From 19eb0237a07ac30afcdbbfd5fca54ad3c8213f7a Mon Sep 17 00:00:00 2001
From: Ashwin Bhat <1727158+ashwinbhat@users.noreply.github.com>
Date: Thu, 17 Aug 2023 15:07:04 -0700
Subject: [PATCH 01/69] Version information for MaterialX dlls (#1447)
---
cmake/modules/MaterialXVersion.rc.in | 34 +++++++++++++++++++++++
source/MaterialXCore/CMakeLists.txt | 24 ++++++++++------
source/MaterialXFormat/CMakeLists.txt | 24 ++++++++++------
source/MaterialXGenGlsl/CMakeLists.txt | 24 ++++++++++------
source/MaterialXGenMdl/CMakeLists.txt | 24 ++++++++++------
source/MaterialXGenMsl/CMakeLists.txt | 24 ++++++++++------
source/MaterialXGenOsl/CMakeLists.txt | 24 ++++++++++------
source/MaterialXGenShader/CMakeLists.txt | 24 ++++++++++------
source/MaterialXRender/CMakeLists.txt | 24 ++++++++++------
source/MaterialXRenderGlsl/CMakeLists.txt | 32 +++++++++++++--------
source/MaterialXRenderHw/CMakeLists.txt | 28 ++++++++++++-------
source/MaterialXRenderMsl/CMakeLists.txt | 22 ++++++++-------
source/MaterialXRenderOsl/CMakeLists.txt | 24 ++++++++++------
13 files changed, 228 insertions(+), 104 deletions(-)
create mode 100644 cmake/modules/MaterialXVersion.rc.in
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/source/MaterialXCore/CMakeLists.txt b/source/MaterialXCore/CMakeLists.txt
index 37edf7929a..675c42c5de 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,14 @@ target_include_directories(MaterialXCore
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS MaterialXCore
+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/)
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/)
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXCore.pdb"
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
diff --git a/source/MaterialXFormat/CMakeLists.txt b/source/MaterialXFormat/CMakeLists.txt
index 940ef9662c..6b6d3ae9c3 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,26 @@ 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
+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
+ 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"
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
diff --git a/source/MaterialXGenGlsl/CMakeLists.txt b/source/MaterialXGenGlsl/CMakeLists.txt
index 2ddcb5475c..58ff8a45ba 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,27 @@ 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
+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
+ 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"
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
diff --git a/source/MaterialXGenMdl/CMakeLists.txt b/source/MaterialXGenMdl/CMakeLists.txt
index b73e674b7f..04dc2e76b4 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,30 @@ 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
+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
+ 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(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXGenMdl.pdb"
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
diff --git a/source/MaterialXGenMsl/CMakeLists.txt b/source/MaterialXGenMsl/CMakeLists.txt
index 31d2599531..d8ba092ee8 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,27 @@ 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
+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
+ 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"
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
diff --git a/source/MaterialXGenOsl/CMakeLists.txt b/source/MaterialXGenOsl/CMakeLists.txt
index 03e30de0c1..24bd0043d9 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,28 @@ 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
+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}/MaterialXGenOsl/ MESSAGE_NEVER
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
FILES_MATCHING PATTERN "*.h*")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXGenOsl.pdb"
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
diff --git a/source/MaterialXGenShader/CMakeLists.txt b/source/MaterialXGenShader/CMakeLists.txt
index 231dda6e5c..0a16049f25 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,29 +26,29 @@ 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
+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
+ 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"
+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"
diff --git a/source/MaterialXRender/CMakeLists.txt b/source/MaterialXRender/CMakeLists.txt
index d0a50232cd..eb054303c5 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,25 @@ 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
+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
+ 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"
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
diff --git a/source/MaterialXRenderGlsl/CMakeLists.txt b/source/MaterialXRenderGlsl/CMakeLists.txt
index ddab96c318..971c356bd0 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,30 @@ 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
+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
+ 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"
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
diff --git a/source/MaterialXRenderHw/CMakeLists.txt b/source/MaterialXRenderHw/CMakeLists.txt
index 85ef13c55c..07210b12fa 100644
--- a/source/MaterialXRenderHw/CMakeLists.txt
+++ b/source/MaterialXRenderHw/CMakeLists.txt
@@ -1,3 +1,5 @@
+set(MATERIALX_MODULE_NAME MaterialXRenderHw)
+
file(GLOB materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
file(GLOB materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h*")
@@ -20,18 +22,24 @@ 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)
+# 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"
@@ -39,7 +47,7 @@ elseif(APPLE)
"-framework Metal")
elseif(UNIX)
target_link_libraries(
- MaterialXRenderHw
+ ${MATERIALX_MODULE_NAME}
MaterialXRender
${CMAKE_DL_LIBS}
${X11_LIBRARIES}
@@ -47,30 +55,30 @@ 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
+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
+ 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"
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
diff --git a/source/MaterialXRenderMsl/CMakeLists.txt b/source/MaterialXRenderMsl/CMakeLists.txt
index 5ad50ea2cc..173a9e9bae 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*")
@@ -34,7 +36,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)
@@ -45,12 +47,12 @@ set(COMMON_LIBRARIES
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"
@@ -58,7 +60,7 @@ elseif(APPLE)
"-framework Metal")
elseif(UNIX)
target_link_libraries(
- MaterialXRenderMsl
+ ${MATERIALX_MODULE_NAME}
${COMMON_LIBRARIES}
${OPENGL_LIBRARIES}
${X11_LIBRARIES}
@@ -66,29 +68,29 @@ 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
+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
+ 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"
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
diff --git a/source/MaterialXRenderOsl/CMakeLists.txt b/source/MaterialXRenderOsl/CMakeLists.txt
index a4ffa81235..d4e5dbf151 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,26 @@ 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
+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
+ 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"
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
From b23de80a5e8e3cdf4b2ed5a5e12ced765c8b0125 Mon Sep 17 00:00:00 2001
From: Bernard Kwok
Date: Thu, 17 Aug 2023 22:29:08 -0400
Subject: [PATCH 02/69] Add support for top level inputs (#1453)
Fix so that top level inputs are parsed properly and values and path reflection data is correct (for uniform updates).
---
.../stdlib/nodegraph_inputs/top_level_input.mtlx | 10 ++++++++++
source/MaterialXCore/Interface.cpp | 2 +-
source/MaterialXGenShader/ShaderNode.cpp | 12 +++++++++++-
3 files changed, 22 insertions(+), 2 deletions(-)
create mode 100644 resources/Materials/TestSuite/stdlib/nodegraph_inputs/top_level_input.mtlx
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/source/MaterialXCore/Interface.cpp b/source/MaterialXCore/Interface.cpp
index 3a93a384c2..b733d3a4c7 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());
diff --git a/source/MaterialXGenShader/ShaderNode.cpp b/source/MaterialXGenShader/ShaderNode.cpp
index c923e4be57..3eb750f1ff 100644
--- a/source/MaterialXGenShader/ShaderNode.cpp
+++ b/source/MaterialXGenShader/ShaderNode.cpp
@@ -381,7 +381,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);
}
}
From 79433cca61a2b3c23fc20c41a3c5ed7c19286da7 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Fri, 18 Aug 2023 15:55:59 -0700
Subject: [PATCH 03/69] Simplify default color handling in GLSL (#1452)
This changelist simplifies default color handling in GLSL, making the renderer responsible for generating fallback textures when images are not found on disk, and removing associated dynamic branches in GLSL shader code.
Two advantages of this simplification are:
- Hydra Storm and other MaterialXGenGlsl integrations can now render materials that reference 1x1 images without needing special-case logic.
- The render performance of MaterialXGenGlsl shaders that reference images is slightly improved, as dynamic branches exact a performance cost in some situations.
This new logic doesn't yet handle color space differences between missing images and default colors, and we should address this across languages in a future improvement.
---
libraries/stdlib/genglsl/mx_image_color3.glsl | 11 +----
libraries/stdlib/genglsl/mx_image_color4.glsl | 11 +----
libraries/stdlib/genglsl/mx_image_float.glsl | 11 +----
.../stdlib/genglsl/mx_image_vector2.glsl | 11 +----
.../stdlib/genglsl/mx_image_vector3.glsl | 11 +----
.../stdlib/genglsl/mx_image_vector4.glsl | 11 +----
.../stdlib/texture/image_default.mtlx | 36 +++++++++++++++++
source/MaterialXGraphEditor/RenderView.cpp | 2 +-
source/MaterialXRender/ImageHandler.cpp | 40 ++++++++-----------
source/MaterialXRender/ImageHandler.h | 10 +----
source/MaterialXRenderGlsl/GlslMaterial.cpp | 2 +-
source/MaterialXRenderGlsl/GlslProgram.cpp | 2 +-
source/MaterialXRenderMsl/MslMaterial.mm | 2 +-
.../MslPipelineStateObject.mm | 2 +-
source/MaterialXView/Viewer.cpp | 4 +-
.../PyMaterialXRender/PyImageHandler.cpp | 4 +-
16 files changed, 74 insertions(+), 96 deletions(-)
create mode 100644 resources/Materials/TestSuite/stdlib/texture/image_default.mtlx
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/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/MaterialXGraphEditor/RenderView.cpp b/source/MaterialXGraphEditor/RenderView.cpp
index faf48f543a..f36a492502 100644
--- a/source/MaterialXGraphEditor/RenderView.cpp
+++ b/source/MaterialXGraphEditor/RenderView.cpp
@@ -720,7 +720,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/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/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/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/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/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);
}
From 7fd2b4f5069e54f86688e19159393741e43511b2 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Sat, 19 Aug 2023 10:12:47 -0700
Subject: [PATCH 04/69] Remove exceptions from topologicalSort
This changelist removes cycle exceptions from the topologicalSort methods in MaterialX, as these functions are already protected from recursion, and clients have more robust ways of checking for cycles in graphs (e.g. hasUpstreamCycle).
This addresses edge cases in MaterialXGraphEditor where certain graph configurations could trigger a crash.
---
source/MaterialXCore/Node.cpp | 10 ----------
source/MaterialXCore/Node.h | 1 -
source/MaterialXGenShader/ShaderGraph.cpp | 6 ------
source/MaterialXGenShader/ShaderGraph.h | 1 -
4 files changed, 18 deletions(-)
diff --git a/source/MaterialXCore/Node.cpp b/source/MaterialXCore/Node.cpp
index 45524b116d..28be7e432c 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;
diff --git a/source/MaterialXCore/Node.h b/source/MaterialXCore/Node.h
index a316b0eb6c..1b1115fde7 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
diff --git a/source/MaterialXGenShader/ShaderGraph.cpp b/source/MaterialXGenShader/ShaderGraph.cpp
index e6ad6eca29..8a424f8bf5 100644
--- a/source/MaterialXGenShader/ShaderGraph.cpp
+++ b/source/MaterialXGenShader/ShaderGraph.cpp
@@ -1225,12 +1225,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
From 42bb654d5d0b1cd9206045fcebaa36bdc7c0ac9f Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Sat, 19 Aug 2023 12:45:40 -0700
Subject: [PATCH 05/69] Add empty vector check to node paste
This changelist adds an empty vector check to node paste operations in the graph editor, addressing a case where copying nodes from a deleted material would trigger a crash.
---
source/MaterialXGraphEditor/Graph.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index 9e3fbccc40..c773ef4457 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -3796,11 +3796,11 @@ void Graph::drawGraph(ImVec2 mousePos)
linkGraph();
ImVec2 canvasPos = ed::ScreenToCanvas(mousePos);
// place the copied nodes or the individual new nodes
- if ((int) _copiedNodes.size() > 0)
+ if (!_copiedNodes.empty())
{
positionPasteBin(canvasPos);
}
- else
+ else if (!_graphNodes.empty())
{
ed::SetNodePosition(_graphNodes.back()->getId(), canvasPos);
}
From 2d12c1687887f793609133cadf192bf4b29e9502 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Sat, 19 Aug 2023 19:02:52 -0700
Subject: [PATCH 06/69] Improve validation in graph editor
This changelist improves the document validation step in the graph editor, importing the standard libraries to allow validation of node interfaces as well as document syntax.
---
source/MaterialXGraphEditor/Graph.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index c773ef4457..9bf3afcd1b 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -84,7 +84,6 @@ Graph::Graph(const std::string& materialFilename,
_geomFilter.push_back(".gltf");
_graphDoc = loadDocument(materialFilename);
- _graphDoc->importLibrary(_stdLib);
_initial = true;
createNodeUIList(_stdLib);
@@ -177,6 +176,7 @@ 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))
{
@@ -4057,7 +4057,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);
From 6918d5d9848701134bc517debdac33a58554ba79 Mon Sep 17 00:00:00 2001
From: Morteza Mostajab <92918486+Morteeza@users.noreply.github.com>
Date: Mon, 21 Aug 2023 17:34:50 +0100
Subject: [PATCH 07/69] Fix search paths in MSL render tests (#1481)
Previously it was failing to find options.mtlx, and not rendering results.
---
.../MaterialXRenderMsl/RenderMsl.mm | 19 ++++++-------------
1 file changed, 6 insertions(+), 13 deletions(-)
diff --git a/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm b/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm
index f33e793690..c3accade49 100644
--- a/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm
+++ b/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm
@@ -179,6 +179,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 +278,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 +287,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))
@@ -456,18 +457,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);
}
From c5b376cbf33583dcc4cb5a02772758c8b17499e6 Mon Sep 17 00:00:00 2001
From: Morteza Mostajab <92918486+Morteeza@users.noreply.github.com>
Date: Tue, 22 Aug 2023 18:57:57 +0100
Subject: [PATCH 08/69] Add support for MaterialX builds on iOS (#1435)
Thanks to @ikuznetcova for the contribution
---
.github/workflows/main.yml | 9 +++++
CMakeLists.txt | 22 ++++++++++
source/MaterialXRenderHw/CMakeLists.txt | 9 ++++-
source/MaterialXRenderHw/SimpleWindowIOS.cpp | 40 +++++++++++++++++++
source/MaterialXRenderHw/SimpleWindowMac.cpp | 4 ++
.../MaterialXRenderHw/WindowCocoaWrappers.m | 4 ++
source/MaterialXRenderHw/WindowWrapper.cpp | 4 ++
source/MaterialXRenderMsl/CMakeLists.txt | 9 ++++-
8 files changed, 99 insertions(+), 2 deletions(-)
create mode 100644 source/MaterialXRenderHw/SimpleWindowIOS.cpp
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 8787240cd9..53111d286d 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -83,6 +83,15 @@ jobs:
python: 3.11
test_shaders: ON
+ - name: iOS_Xcode_14_Python311
+ os: macos-13
+ compiler: xcode
+ compiler_version: "14.3"
+ python: None
+ cmake_config: -DMATERIALX_BUILD_IOS=ON -DMATERIALX_BUILD_PYTHON=OFF -DMATERIALX_BUILD_VIEWER=OFF -DMATERIALX_BUILD_GRAPH_EDITOR=OFF
+ -DCMAKE_OSX_SYSROOT=`xcrun --sdk iphoneos --show-sdk-path`
+ -DCMAKE_OSX_ARCHITECTURES=arm64
+
- name: Windows_VS2019_Win32_Python37
os: windows-2019
architecture: x86
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 69e5c8c0f3..11829bd59d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -55,6 +55,27 @@ option(MATERIALX_WARNINGS_AS_ERRORS "Interpret all compiler warnings as errors."
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_GLSL OFF)
+ set(MATERIALX_BUILD_GEN_MDL OFF)
+ set(MATERIALX_BUILD_OIIO OFF)
+ set(MATERIALX_PYTHON_LTO OFF)
+ set(MATERIALX_INSTALL_PYTHON OFF)
+ set(MATERIALX_DYNAMIC_ANALYSIS OFF)
+ set(MATERIALX_DYNAMIC_ANALYSIS OFF)
+ set(MATERIALX_OSL_LEGACY_CLOSURES OFF)
+ set(MATERIALX_BUILD_TESTS OFF)
+ set(MATERIALX_TEST_RENDER 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
@@ -134,6 +155,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)
diff --git a/source/MaterialXRenderHw/CMakeLists.txt b/source/MaterialXRenderHw/CMakeLists.txt
index 07210b12fa..b0383acfd7 100644
--- a/source/MaterialXRenderHw/CMakeLists.txt
+++ b/source/MaterialXRenderHw/CMakeLists.txt
@@ -4,7 +4,9 @@ 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
@@ -26,6 +28,12 @@ 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)
@@ -43,7 +51,6 @@ elseif(APPLE)
MaterialXRender
${CMAKE_DL_LIBS}
"-framework Foundation"
- "-framework Cocoa"
"-framework Metal")
elseif(UNIX)
target_link_libraries(
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 173a9e9bae..6e7a4f5172 100644
--- a/source/MaterialXRenderMsl/CMakeLists.txt
+++ b/source/MaterialXRenderMsl/CMakeLists.txt
@@ -11,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
@@ -44,6 +46,12 @@ 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(
@@ -56,7 +64,6 @@ elseif(APPLE)
${COMMON_LIBRARIES}
${OPENGL_LIBRARIES}
"-framework Foundation"
- "-framework Cocoa"
"-framework Metal")
elseif(UNIX)
target_link_libraries(
From c545829a9018a63fff7fca61c356fc8391e65344 Mon Sep 17 00:00:00 2001
From: Jean-Christophe Morin
<38703886+JeanChristopheMorinPerso@users.noreply.github.com>
Date: Tue, 22 Aug 2023 14:37:59 -0400
Subject: [PATCH 09/69] Generate Python wheels in CI (#1317)
This PR adds a new GitHub Actions workflow that generates Python wheels and an sdist that all can be uploaded to PyPI.
It generates wheels for Python 3.7, 3.8, 3.9 3.10, and 3.11 for Windows, macOS and Linux.
I used https://github.com/scikit-build/scikit-build-core as the build backend. It's a new tool that is quite simple and allows to build Python extensions (C, C++, etc) without setuptools. Since it's a build backend, everything can be built with pip install. or https://github.com/pypa/build (python -m build).
---
.github/workflows/python.yml | 128 ++++++++++++++++++
.gitignore | 1 +
CMakeLists.txt | 64 +++++----
libraries/CMakeLists.txt | 24 ++--
pyproject.toml | 78 +++++++++++
python/CMakeLists.txt | 25 ++--
python/MaterialX/_scripts/README.md | 2 +
python/MaterialX/_scripts/__init__.py | 1 +
python/mtx_skbuild_plugin.py | 90 ++++++++++++
resources/CMakeLists.txt | 6 +-
source/MaterialXCore/CMakeLists.txt | 24 ++--
source/MaterialXFormat/CMakeLists.txt | 26 ++--
source/MaterialXGenGlsl/CMakeLists.txt | 26 ++--
source/MaterialXGenMdl/CMakeLists.txt | 32 +++--
source/MaterialXGenMsl/CMakeLists.txt | 26 ++--
source/MaterialXGenOsl/CMakeLists.txt | 27 ++--
source/MaterialXGenShader/CMakeLists.txt | 32 +++--
source/MaterialXRender/CMakeLists.txt | 26 ++--
source/MaterialXRenderGlsl/CMakeLists.txt | 26 ++--
source/MaterialXRenderHw/CMakeLists.txt | 22 +--
source/MaterialXRenderMsl/CMakeLists.txt | 22 +--
source/MaterialXRenderOsl/CMakeLists.txt | 26 ++--
.../PyMaterialXCore/CMakeLists.txt | 4 +-
.../PyMaterialXFormat/CMakeLists.txt | 4 +-
.../PyMaterialXGenGlsl/CMakeLists.txt | 4 +-
.../PyMaterialXGenMdl/CMakeLists.txt | 4 +-
.../PyMaterialXGenMsl/CMakeLists.txt | 4 +-
.../PyMaterialXGenOsl/CMakeLists.txt | 4 +-
.../PyMaterialXGenShader/CMakeLists.txt | 4 +-
.../PyMaterialXRender/CMakeLists.txt | 4 +-
.../PyMaterialXRenderGlsl/CMakeLists.txt | 4 +-
.../PyMaterialXRenderMsl/CMakeLists.txt | 4 +-
.../PyMaterialXRenderOsl/CMakeLists.txt | 4 +-
33 files changed, 554 insertions(+), 224 deletions(-)
create mode 100644 .github/workflows/python.yml
create mode 100644 pyproject.toml
create mode 100644 python/MaterialX/_scripts/README.md
create mode 100644 python/MaterialX/_scripts/__init__.py
create mode 100644 python/mtx_skbuild_plugin.py
diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml
new file mode 100644
index 0000000000..6f54ed45e4
--- /dev/null
+++ b/.github/workflows/python.yml
@@ -0,0 +1,128 @@
+name: python
+
+on:
+ push:
+ paths-ignore:
+ - '**.md'
+ pull_request:
+ paths-ignore:
+ - '**.md'
+ workflow_dispatch:
+
+jobs:
+ # Generate the sdist first. We'll use it to create the wheels.
+ # https://packaging.python.org/en/latest/flow#the-source-distribution-sdist
+ sdist:
+ name: Generate Source Distribution
+ runs-on: ubuntu-latest
+ outputs:
+ sdist_filename: ${{ steps.generate.outputs.filename }}
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: actions/setup-python@v4
+ with:
+ python-version: 3.11
+
+ - name: Install Build Command
+ run: python -m pip install build
+
+ - name: Generate Sdist
+ id: generate
+ run: |
+ python -m build -s . --outdir dist
+ echo "filename=$(ls dist)" >> "$GITHUB_OUTPUT"
+
+ - name: Upload Sdist
+ uses: actions/upload-artifact@v3
+ with:
+ name: sdist
+ path: ./dist/*.tar.gz
+
+ # Create the wheels. It'll use the sdist to confirm that we can compile MaterialX from the sdist.
+ # https://packaging.python.org/en/latest/flow#the-built-distributions-wheels
+ wheels:
+ name: Generate Wheel
+ runs-on: ${{ matrix.os }}
+ needs: ['sdist']
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: ['37', '38', '39', '310', '311']
+ os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
+
+ steps:
+ - name: Download Sdist
+ uses: actions/download-artifact@v3
+ with:
+ name: sdist
+ path: sdist
+
+ - name: Build Wheel
+ # https://cibuildwheel.readthedocs.io/en/stable/
+ uses: pypa/cibuildwheel@v2.12.1
+ with:
+ # Build from the sdist. We want to make sure it's valid and works as expected.
+ package-dir: ${{ github.workspace }}/sdist/${{ needs.sdist.outputs.sdist_filename }}
+ output-dir: wheels
+ env:
+ CIBW_BUILD: 'cp${{ matrix.python-version }}-*'
+ 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: Upload Wheel
+ uses: actions/upload-artifact@v3
+ with:
+ name: wheels
+ path: ./wheels/*.whl
+
+ test:
+ name: Test Wheel
+ needs: ['wheels']
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
+ os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: actions/setup-python@v4
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ - name: Download Wheels
+ uses: actions/download-artifact@v3
+ with:
+ name: wheels
+ path: wheels
+
+ - name: Install Wheel
+ run: python -m pip install MaterialX --find-links wheels --no-index
+
+ - name: Python Tests
+ shell: bash
+ run: |
+ set -e
+ python python/MaterialXTest/main.py
+ python python/MaterialXTest/genshader.py
+ python python/Scripts/mxformat.py ./resources/Materials/TestSuite/stdlib/upgrade --yes --upgrade
+ python python/Scripts/mxvalidate.py ./resources/Materials/Examples/StandardSurface/standard_surface_marble_solid.mtlx --stdlib --verbose
+ python python/Scripts/mxdoc.py --docType md ./libraries/pbrlib/pbrlib_defs.mtlx
+ python python/Scripts/mxdoc.py --docType html ./libraries/bxdf/standard_surface.mtlx
+ python python/Scripts/generateshader.py ./resources/Materials/Examples/StandardSurface --target glsl
+ python python/Scripts/generateshader.py ./resources/Materials/Examples/StandardSurface --target osl
+ python python/Scripts/generateshader.py ./resources/Materials/Examples/StandardSurface --target mdl
+ python python/Scripts/generateshader.py ./resources/Materials/Examples/StandardSurface --target msl
diff --git a/.gitignore b/.gitignore
index 378eac25d3..9d0b71a3c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
build
+dist
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 11829bd59d..58dfe85aed 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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)
@@ -101,6 +101,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.")
@@ -207,6 +213,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)
@@ -300,7 +312,7 @@ if(MATERIALX_BUILD_RENDER)
if(MATERIALX_BUILD_GRAPH_EDITOR)
add_subdirectory(source/MaterialXGraphEditor)
endif()
- if(MATERIALX_INSTALL_RESOURCES)
+ if(MATERIALX_INSTALL_RESOURCES AND NOT SKBUILD)
add_subdirectory(resources)
endif()
endif()
@@ -335,26 +347,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/libraries/CMakeLists.txt b/libraries/CMakeLists.txt
index 0d47cad5ed..eddbeb16e9 100644
--- a/libraries/CMakeLists.txt
+++ b/libraries/CMakeLists.txt
@@ -1,20 +1,26 @@
-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()
+
+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()
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
- DESTINATION "python/MaterialX/${MATERIALX_INSTALL_STDLIB_PATH}"
+ 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 "python/MaterialX/${MATERIALX_INSTALL_STDLIB_PATH}/pbrlib/genosl/" RENAME pbrlib_genosl_impl.mtlx)
+ DESTINATION "${MATERIALX_PYTHON_LIBRARIES_PATH}/pbrlib/genosl/" RENAME pbrlib_genosl_impl.mtlx)
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/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/source/MaterialXCore/CMakeLists.txt b/source/MaterialXCore/CMakeLists.txt
index 675c42c5de..33e4fafdf4 100644
--- a/source/MaterialXCore/CMakeLists.txt
+++ b/source/MaterialXCore/CMakeLists.txt
@@ -35,14 +35,16 @@ target_include_directories(${MATERIALX_MODULE_NAME}
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-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}/${MATERIALX_MODULE_NAME}/)
-
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+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}/${MATERIALX_MODULE_NAME}/)
+
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
+ DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+endif()
diff --git a/source/MaterialXFormat/CMakeLists.txt b/source/MaterialXFormat/CMakeLists.txt
index 6b6d3ae9c3..420149bae4 100644
--- a/source/MaterialXFormat/CMakeLists.txt
+++ b/source/MaterialXFormat/CMakeLists.txt
@@ -37,15 +37,17 @@ target_include_directories(${MATERIALX_MODULE_NAME}
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-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}/${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)
+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}/${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/MaterialXGenGlsl/CMakeLists.txt b/source/MaterialXGenGlsl/CMakeLists.txt
index 58ff8a45ba..da497f9f88 100644
--- a/source/MaterialXGenGlsl/CMakeLists.txt
+++ b/source/MaterialXGenGlsl/CMakeLists.txt
@@ -38,15 +38,17 @@ target_include_directories(${MATERIALX_MODULE_NAME}
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-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}/${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)
+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}/${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/MaterialXGenMdl/CMakeLists.txt b/source/MaterialXGenMdl/CMakeLists.txt
index 04dc2e76b4..d9991843ce 100644
--- a/source/MaterialXGenMdl/CMakeLists.txt
+++ b/source/MaterialXGenMdl/CMakeLists.txt
@@ -38,18 +38,20 @@ target_include_directories(${MATERIALX_MODULE_NAME}
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-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}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
- FILES_MATCHING PATTERN "*.h*")
-
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mdl
- DESTINATION "${MATERIALX_INSTALL_MDL_MODULE_PATH}")
-
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+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}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
+ FILES_MATCHING PATTERN "*.h*")
+
+ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mdl
+ DESTINATION "${MATERIALX_INSTALL_MDL_MODULE_PATH}")
+
+ 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 d8ba092ee8..8d6d009f50 100644
--- a/source/MaterialXGenMsl/CMakeLists.txt
+++ b/source/MaterialXGenMsl/CMakeLists.txt
@@ -38,15 +38,17 @@ target_include_directories(${MATERIALX_MODULE_NAME}
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-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}/${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)
+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}/${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/MaterialXGenOsl/CMakeLists.txt b/source/MaterialXGenOsl/CMakeLists.txt
index 24bd0043d9..3cf7b93438 100644
--- a/source/MaterialXGenOsl/CMakeLists.txt
+++ b/source/MaterialXGenOsl/CMakeLists.txt
@@ -38,16 +38,17 @@ target_include_directories(${MATERIALX_MODULE_NAME}
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-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}/${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)
-
+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}/${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 0a16049f25..1b9533e0a5 100644
--- a/source/MaterialXGenShader/CMakeLists.txt
+++ b/source/MaterialXGenShader/CMakeLists.txt
@@ -38,18 +38,20 @@ target_include_directories(${MATERIALX_MODULE_NAME}
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-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}/${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)
-
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../resources"
- DESTINATION . MESSAGE_NEVER)
+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}/${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)
+
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../resources"
+ DESTINATION . MESSAGE_NEVER)
+endif()
diff --git a/source/MaterialXRender/CMakeLists.txt b/source/MaterialXRender/CMakeLists.txt
index eb054303c5..52d07e688e 100644
--- a/source/MaterialXRender/CMakeLists.txt
+++ b/source/MaterialXRender/CMakeLists.txt
@@ -60,17 +60,19 @@ set_target_properties(
VERSION "${MATERIALX_LIBRARY_VERSION}"
SOVERSION "${MATERIALX_MAJOR_VERSION}")
-install(TARGETS ${MATERIALX_MODULE_NAME}
- 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}/${MATERIALX_MODULE_NAME}/ 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}/${MATERIALX_MODULE_NAME}.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/CMakeLists.txt b/source/MaterialXRenderGlsl/CMakeLists.txt
index 971c356bd0..cb2f3c27c2 100644
--- a/source/MaterialXRenderGlsl/CMakeLists.txt
+++ b/source/MaterialXRenderGlsl/CMakeLists.txt
@@ -101,15 +101,17 @@ target_include_directories(${MATERIALX_MODULE_NAME}
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-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}/${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)
+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}/${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/MaterialXRenderHw/CMakeLists.txt b/source/MaterialXRenderHw/CMakeLists.txt
index b0383acfd7..dfd262a3ae 100644
--- a/source/MaterialXRenderHw/CMakeLists.txt
+++ b/source/MaterialXRenderHw/CMakeLists.txt
@@ -77,15 +77,17 @@ target_include_directories(${MATERIALX_MODULE_NAME}
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS ${MATERIALX_MODULE_NAME}
- 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}/${MATERIALX_MODULE_NAME}/ 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}/${MATERIALX_MODULE_NAME}.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/CMakeLists.txt b/source/MaterialXRenderMsl/CMakeLists.txt
index 6e7a4f5172..4d5e286463 100644
--- a/source/MaterialXRenderMsl/CMakeLists.txt
+++ b/source/MaterialXRenderMsl/CMakeLists.txt
@@ -89,15 +89,17 @@ target_include_directories(${MATERIALX_MODULE_NAME}
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS ${MATERIALX_MODULE_NAME}
- 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}/${MATERIALX_MODULE_NAME}/ 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}/${MATERIALX_MODULE_NAME}.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/MaterialXRenderOsl/CMakeLists.txt b/source/MaterialXRenderOsl/CMakeLists.txt
index d4e5dbf151..ac1de93d2e 100644
--- a/source/MaterialXRenderOsl/CMakeLists.txt
+++ b/source/MaterialXRenderOsl/CMakeLists.txt
@@ -37,15 +37,17 @@ target_include_directories(${MATERIALX_MODULE_NAME}
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-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}/${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)
+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}/${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/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/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/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}")
From 9bbc4cecc795d1ef283695e6bea72b186fa635f8 Mon Sep 17 00:00:00 2001
From: Bernard Kwok
Date: Tue, 22 Aug 2023 19:10:09 -0400
Subject: [PATCH 10/69] Follow-up fix for graph editor inputs (#1478)
Remove code to find interface inputs as it finds the incorrect input if it's already an interface.
Was sending the wrong path so would not update the uniform.
---
source/MaterialXGraphEditor/Graph.cpp | 6 ------
1 file changed, 6 deletions(-)
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index 9bf3afcd1b..7e27ccfcd9 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -821,12 +821,6 @@ 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.
From dd12a100bdff8806599d6ab501df0a4fa9c52e72 Mon Sep 17 00:00:00 2001
From: Marcel Wiessler
Date: Wed, 23 Aug 2023 01:29:28 +0200
Subject: [PATCH 11/69] Reduce graph view auto layout spacing (#1476)
Currently spacing between graph nodes is quite large.
This reduces the horizontal space between nodes when using AutoLayout slightly.
---
source/MaterialXGraphEditor/Graph.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index 7e27ccfcd9..3628d02835 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -570,7 +570,7 @@ ImVec2 Graph::layoutPosition(UiNodePtr layoutNode, ImVec2 startingPos, bool init
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
@@ -581,7 +581,7 @@ 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
ed::SetNodePosition(layoutNode->getId(), ImVec2(startingPos));
From b1f727542d4541a78d24ba4dc780e32052f9cfb8 Mon Sep 17 00:00:00 2001
From: Ashwin Bhat <1727158+ashwinbhat@users.noreply.github.com>
Date: Tue, 22 Aug 2023 18:29:31 -0700
Subject: [PATCH 12/69] Various Pattern nodes for AEC and MFG (#1411)
A collection of pattern nodes for lines, circles, cloverleafs, and hexagons
---
libraries/stdlib/stdlib_defs.mtlx | 119 +++
libraries/stdlib/stdlib_ng.mtlx | 755 ++++++++++++++++++
.../stdlib/procedural/linepattern.mtlx | 39 +
.../stdlib/procedural/tiledshape.mtlx | 38 +
4 files changed, 951 insertions(+)
create mode 100644 resources/Materials/TestSuite/stdlib/procedural/linepattern.mtlx
create mode 100644 resources/Materials/TestSuite/stdlib/procedural/tiledshape.mtlx
diff --git a/libraries/stdlib/stdlib_defs.mtlx b/libraries/stdlib/stdlib_defs.mtlx
index bc1240e574..b6e2e0c5d9 100644
--- a/libraries/stdlib/stdlib_defs.mtlx
+++ b/libraries/stdlib/stdlib_defs.mtlx
@@ -1089,6 +1089,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libraries/stdlib/stdlib_ng.mtlx b/libraries/stdlib/stdlib_ng.mtlx
index ab1332e79d..5a9e8da6ae 100644
--- a/libraries/stdlib/stdlib_ng.mtlx
+++ b/libraries/stdlib/stdlib_ng.mtlx
@@ -1419,6 +1419,761 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
From c6f48c7b483dbeec36f2349cb8e77b583c4cb597 Mon Sep 17 00:00:00 2001
From: Marcel Wiessler
Date: Wed, 23 Aug 2023 17:17:01 +0200
Subject: [PATCH 13/69] Fix user texture assignments in graph editor (#1475)
Fix for selecting file being assigned to wrong input.
This saves the input ptr the file dialogue was opened for and assigns the selected file when ready to the same input.
---
source/MaterialXGraphEditor/Graph.cpp | 4 +++-
source/MaterialXGraphEditor/Graph.h | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index 3628d02835..e4714dd9b0 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -1012,6 +1012,7 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
ImGui::PushItemWidth(-100);
if (ImGui::Button("Browse"))
{
+ _fileDialogImageInputName = input->getName();
_fileDialogImage.setTitle("Node Input Dialog");
_fileDialogImage.open();
_fileDialogImage.setTypeFilters(_imageFilter);
@@ -1023,7 +1024,7 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
ImGui::PopStyleColor();
// create and load document from selected file
- if (_fileDialogImage.hasSelected())
+ if (_fileDialogImage.hasSelected() && _fileDialogImageInputName == input->getName())
{
// set the new filename to the complete file path
mx::FilePath fileName = _fileDialogImage.getSelected();
@@ -1032,6 +1033,7 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
input->setAttribute(input->FILE_PREFIX_ATTRIBUTE, "");
_fileDialogImage.clearSelected();
_fileDialogImage.setTypeFilters(std::vector());
+ _fileDialogImageInputName = "";
}
// set input value and update materials if different from previous value
diff --git a/source/MaterialXGraphEditor/Graph.h b/source/MaterialXGraphEditor/Graph.h
index 68140cdaae..f01e45fe35 100644
--- a/source/MaterialXGraphEditor/Graph.h
+++ b/source/MaterialXGraphEditor/Graph.h
@@ -214,7 +214,7 @@ class Graph
FileDialog _fileDialogSave;
FileDialog _fileDialogImage;
FileDialog _fileDialogGeom;
-
+ std::string _fileDialogImageInputName;
bool _isNodeGraph;
From dc9bfaaad6a2be7b6b85158f818cf097e563362d Mon Sep 17 00:00:00 2001
From: Morteza Mostajab <92918486+Morteeza@users.noreply.github.com>
Date: Wed, 23 Aug 2023 16:41:10 +0100
Subject: [PATCH 14/69] Improve robustness of Metal render tests (#1485)
Without this change, MaterialXTest needs to be run from a specific path; otherwise, some texture loads will fail.
---
source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm b/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm
index c3accade49..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);
@@ -374,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();
}
From bcbf8a0118e4be668344e807a70b5d5b82b3af7b Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Wed, 23 Aug 2023 08:43:55 -0700
Subject: [PATCH 15/69] Improvements to CI workflows
This changelist makes a few minor improvements to CI workflows, clarifying the names of steps and artifacts, and simplifying setup for the new iOS build.
---
.github/workflows/main.yml | 6 ++----
.github/workflows/python.yml | 14 ++++++++------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 53111d286d..e5e8b5b31f 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -83,14 +83,12 @@ jobs:
python: 3.11
test_shaders: ON
- - name: iOS_Xcode_14_Python311
+ - name: iOS_Xcode_14
os: macos-13
compiler: xcode
compiler_version: "14.3"
python: None
- cmake_config: -DMATERIALX_BUILD_IOS=ON -DMATERIALX_BUILD_PYTHON=OFF -DMATERIALX_BUILD_VIEWER=OFF -DMATERIALX_BUILD_GRAPH_EDITOR=OFF
- -DCMAKE_OSX_SYSROOT=`xcrun --sdk iphoneos --show-sdk-path`
- -DCMAKE_OSX_ARCHITECTURES=arm64
+ 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
diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml
index 6f54ed45e4..dddfefb9a4 100644
--- a/.github/workflows/python.yml
+++ b/.github/workflows/python.yml
@@ -19,9 +19,11 @@ jobs:
sdist_filename: ${{ steps.generate.outputs.filename }}
steps:
- - uses: actions/checkout@v3
+ - name: Sync Repository
+ uses: actions/checkout@v3
- - uses: actions/setup-python@v4
+ - name: Install Python ${{ matrix.python }}
+ uses: actions/setup-python@v4
with:
python-version: 3.11
@@ -37,7 +39,7 @@ jobs:
- name: Upload Sdist
uses: actions/upload-artifact@v3
with:
- name: sdist
+ name: MaterialX_Python_Source_Distribution
path: ./dist/*.tar.gz
# Create the wheels. It'll use the sdist to confirm that we can compile MaterialX from the sdist.
@@ -56,7 +58,7 @@ jobs:
- name: Download Sdist
uses: actions/download-artifact@v3
with:
- name: sdist
+ name: MaterialX_Python_Source_Distribution
path: sdist
- name: Build Wheel
@@ -83,7 +85,7 @@ jobs:
- name: Upload Wheel
uses: actions/upload-artifact@v3
with:
- name: wheels
+ name: MaterialX_Python_Wheels
path: ./wheels/*.whl
test:
@@ -106,7 +108,7 @@ jobs:
- name: Download Wheels
uses: actions/download-artifact@v3
with:
- name: wheels
+ name: MaterialX_Python_Wheels
path: wheels
- name: Install Wheel
From 84adc65600101118fee687dbd5f5c8e9db9ab95b Mon Sep 17 00:00:00 2001
From: nicolassavva-autodesk
<61437351+nicolassavva-autodesk@users.noreply.github.com>
Date: Thu, 24 Aug 2023 13:07:31 -0700
Subject: [PATCH 16/69] Remove MslRenderer camera initialization (#1465)
Allow ShaderRenderer camera to be modified by the client in subclass renderers when using Metal.
The PR removes the Metal Renderer specific camera initialization in MslRenderer (and now handled by ShaderRenderer).
---
source/MaterialXRender/ShaderRenderer.cpp | 15 ++++++++--
source/MaterialXRender/ShaderRenderer.h | 11 ++++++-
source/MaterialXRenderGlsl/GlslRenderer.cpp | 2 +-
source/MaterialXRenderMsl/MslRenderer.h | 8 ------
source/MaterialXRenderMsl/MslRenderer.mm | 32 +--------------------
5 files changed, 24 insertions(+), 44 deletions(-)
diff --git a/source/MaterialXRender/ShaderRenderer.cpp b/source/MaterialXRender/ShaderRenderer.cpp
index a5e81d1f68..b621e5cd88 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)
diff --git a/source/MaterialXRender/ShaderRenderer.h b/source/MaterialXRender/ShaderRenderer.h
index 2c6f5fbf87..b049f81126 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;
@@ -123,13 +129,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/GlslRenderer.cpp b/source/MaterialXRenderGlsl/GlslRenderer.cpp
index e81ded996e..bf2c8cd849 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)
{
diff --git a/source/MaterialXRenderMsl/MslRenderer.h b/source/MaterialXRenderMsl/MslRenderer.h
index bf968078fe..1c54bdbc6a 100644
--- a/source/MaterialXRenderMsl/MslRenderer.h
+++ b/source/MaterialXRenderMsl/MslRenderer.h
@@ -126,9 +126,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 +143,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..072f6f1a3a 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)
@@ -160,20 +147,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 +190,6 @@
[renderCmdEncoder setCullMode:MTLCullModeBack];
-
- updateViewInformation();
- updateWorldInformation();
try
{
From d329ed7631e805dcf431d0222ef830b08a02f4e2 Mon Sep 17 00:00:00 2001
From: Bernard Kwok
Date: Thu, 24 Aug 2023 16:58:21 -0400
Subject: [PATCH 17/69] Fix downstream traversal in graph editor (#1349)
- Includes nodegraph references in port connection cache
- Adds NodeGraph::getDownstreamPorts() so downstream traversal is possible from graphs
- Update GraphEditor logic to use downstream traversal which will now properly traverse through nodegraphs.
---
source/MaterialXCore/Document.cpp | 12 ++
source/MaterialXCore/Node.cpp | 19 ++
source/MaterialXCore/Node.h | 8 +
source/MaterialXGraphEditor/Graph.cpp | 175 +++++++++++-------
source/MaterialXGraphEditor/RenderView.cpp | 2 +-
source/PyMaterialX/PyMaterialXCore/PyNode.cpp | 1 +
6 files changed, 150 insertions(+), 67 deletions(-)
diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp
index f1a0c4bd1a..4ba48cc84b 100644
--- a/source/MaterialXCore/Document.cpp
+++ b/source/MaterialXCore/Document.cpp
@@ -86,6 +86,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);
@@ -97,6 +98,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/Node.cpp b/source/MaterialXCore/Node.cpp
index 28be7e432c..9596d905bc 100644
--- a/source/MaterialXCore/Node.cpp
+++ b/source/MaterialXCore/Node.cpp
@@ -728,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 1b1115fde7..55846cf2e3 100644
--- a/source/MaterialXCore/Node.h
+++ b/source/MaterialXCore/Node.h
@@ -357,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/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index e4714dd9b0..801a7e09aa 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -644,8 +644,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)));
@@ -701,8 +701,13 @@ void Graph::selectMaterial(UiNodePtr uiNode)
// 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 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
if (_currRenderNode != node)
@@ -712,55 +717,123 @@ 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)
+ {
+ mx::ElementPtr parent = mtlxOutput->getParent();
+ if (parent->isA())
+ mtlxNodeGraph = parent->asA();
+ else if (parent->isA())
+ mtlxNode = parent->asA();
+ }
+ mx::StringSet testPaths;
+ if (mtlxNode)
{
- if (outNodes[0]->getNode())
+ 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())
+ {
+ 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)
+ {
+ downstreamPorts = testGraph->getDownstreamPorts();
+ }
+ }
+ // Test all downstream ports. If the port's node is renderable
+ // then stop searching.
+ for (mx::PortElementPtr downstreamPort : downstreamPorts)
{
- std::vector shaderOut = outNodes[0]->getOutputConnections();
- if (shaderOut.size() > 0)
+ mx::ElementPtr parent = downstreamPort->getParent();
+ if (parent)
{
- if (shaderOut[0])
+ 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;
}
}
}
- }
- else
- {
- _currRenderNode = nullptr;
+ if (!foundNode)
+ {
+ nextPaths.insert(parent->getNamePath());
+ }
}
}
- 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 +841,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();
}
}
@@ -824,7 +874,7 @@ void Graph::updateMaterials(mx::InputPtr input, mx::ValuePtr value)
// 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);
}
}
}
@@ -2737,7 +2787,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);
}
@@ -3710,17 +3760,10 @@ void Graph::drawGraph(ImVec2 mousePos)
_currUiNode = _graphNodes[graphPos];
// 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);
}
diff --git a/source/MaterialXGraphEditor/RenderView.cpp b/source/MaterialXGraphEditor/RenderView.cpp
index f36a492502..a88ca5cdaa 100644
--- a/source/MaterialXGraphEditor/RenderView.cpp
+++ b/source/MaterialXGraphEditor/RenderView.cpp
@@ -452,7 +452,7 @@ void RenderView::updateMaterials(mx::TypedElementPtr typedElem)
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())
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")
From 00417d71ea8664222153b166b0539da8191d62e0 Mon Sep 17 00:00:00 2001
From: hybridherbst
Date: Fri, 25 Aug 2023 16:43:52 +0200
Subject: [PATCH 18/69] Add drag & drop loading to Web Viewer (#1482)
This PR implements drag-drop file loading for
- .mtlx files
- .mtlx files + textures or folders with textures
- folders that contain at least one single .mtlx and textures
- .zip files containing the above
Currently, only the first found .mtlx file from any of the above will be loaded; future improvements could include
- showing a list of dropped .mtlx files to choose from
- hot reload when a .mtlx file on disk or a referenced texture changes again
- this would turn the web viewer into a pretty nice MaterialX hand editor without having any kind of MaterialX software installed.
---
.../MaterialXView/source/dropHandling.js | 281 ++++++++++++++++++
javascript/MaterialXView/source/index.js | 15 +
javascript/MaterialXView/source/viewer.js | 1 +
3 files changed, 297 insertions(+)
create mode 100644 javascript/MaterialXView/source/dropHandling.js
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/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('/');
From 77dd15bb93d3c4c198954fca6d339c6065b89c6f Mon Sep 17 00:00:00 2001
From: Mikael Sundell
Date: Fri, 25 Aug 2023 16:46:33 +0200
Subject: [PATCH 19/69] Add OPENIMAGEIO_UTIL_LIBRARY to OpenImageIO (#1488)
---
.../External/OpenImageIO/FindOpenImageIO.cmake | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
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)
From bc6a97ca3ea721c9666535f065ada51111e4537f Mon Sep 17 00:00:00 2001
From: Paul Molodowitch
Date: Fri, 25 Aug 2023 08:02:39 -0700
Subject: [PATCH 20/69] Omit Python data installation in non-Python builds
(#1437)
Since the addition of #1237, we now create a python folder, with a copy of the stdlibs, even if we're not building python.
This is at best redundant, and in my particular case, caused a problem in a downstream build script.
---
libraries/CMakeLists.txt | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt
index eddbeb16e9..d60a54cf3b 100644
--- a/libraries/CMakeLists.txt
+++ b/libraries/CMakeLists.txt
@@ -18,9 +18,11 @@ if(SKBUILD)
set(MATERIALX_PYTHON_LIBRARIES_PATH "${SKBUILD_PLATLIB_DIR}/MaterialX/libraries")
endif()
-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)
+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()
From 57566ce4cab49736b093115c5bc2b553166400ad Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Fri, 25 Aug 2023 08:23:48 -0700
Subject: [PATCH 21/69] Update changelog for recent work
---
CHANGELOG.md | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a27b8d124c..efd3fce2f1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,35 @@
## [1.38.8] - Development
+### Added
+- Added new [Random Color, Random Float](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1330), [Checkerboard](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1328), [Triangle Wave](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1334), and [Distance](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1333) nodes for common artistic patterns.
+- Added new [Line, Circle, Hexagon, Cloverleaf, Grid, and Crosshatch](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1411) nodes for common architecture, engineering, and construction patterns.
+- Added support for [MaterialX builds on iOS](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1435).
+- 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 [drag-and-drop import](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1482) of MaterialX files in the [Web Viewer](https://academysoftwarefoundation.github.io/MaterialX/).
+- 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 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 accuracy of [GGX importance sampling](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1390) in GLSL shader generation.
+- 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 definitions of the [default color transforms](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1352), implementing them as language-independent MaterialX graphs.
+- 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.
+
## [1.38.7] - 2023-04-21
### Added
From 59b6b9e828475eb76ae001f741dad30921876422 Mon Sep 17 00:00:00 2001
From: Bernard Kwok
Date: Fri, 25 Aug 2023 18:17:35 -0400
Subject: [PATCH 22/69] Replace uvindex on gltf image nodes with texcoord
(#1491)
Changes the exposed input interface from `uvindex` which is an integer to `texcoord` which is a `vector2`. This allows for either
1. A `texcoord` to be attached for integer based uv set workflows (e.g. glTF).
2. A `geompropvalue ` to be attached for name based workflows (e.g. USD).
---
libraries/bxdf/gltf_pbr.mtlx | 46 +++++++++++-------------------------
1 file changed, 14 insertions(+), 32 deletions(-)
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 @@
-
+
From 7c3695bde91b4a4e281a77c9978616c670271ad4 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Sat, 26 Aug 2023 09:22:52 -0700
Subject: [PATCH 23/69] Refinements to checkerboard node (#1496)
- Rename tiling inputs to 'uvtiling' and 'uvoffset', aligning them with the latest conventions for tiling pattern nodes.
- Minor optimizations to the checkerboard graph, taking advantage of vector operations where possible.
---
.../Specification/MaterialX.Specification.md | 4 +-
libraries/stdlib/stdlib_defs.mtlx | 4 +-
libraries/stdlib/stdlib_ng.mtlx | 52 +++++++------------
3 files changed, 22 insertions(+), 38 deletions(-)
diff --git a/documents/Specification/MaterialX.Specification.md b/documents/Specification/MaterialX.Specification.md
index c6b4a66101..7e876bdb57 100644
--- a/documents/Specification/MaterialX.Specification.md
+++ b/documents/Specification/MaterialX.Specification.md
@@ -787,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.
diff --git a/libraries/stdlib/stdlib_defs.mtlx b/libraries/stdlib/stdlib_defs.mtlx
index b6e2e0c5d9..8c4b5b4150 100644
--- a/libraries/stdlib/stdlib_defs.mtlx
+++ b/libraries/stdlib/stdlib_defs.mtlx
@@ -1083,8 +1083,8 @@
-
-
+
+
diff --git a/libraries/stdlib/stdlib_ng.mtlx b/libraries/stdlib/stdlib_ng.mtlx
index 5a9e8da6ae..2c87e17196 100644
--- a/libraries/stdlib/stdlib_ng.mtlx
+++ b/libraries/stdlib/stdlib_ng.mtlx
@@ -1376,47 +1376,31 @@
A 2D checkerboard pattern.
-->
-
-
-
-
-
-
-
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
@@ -1112,10 +1112,10 @@
-
+
@@ -1123,10 +1123,10 @@
-
+
@@ -1134,11 +1134,11 @@
-
+
diff --git a/libraries/stdlib/stdlib_ng.mtlx b/libraries/stdlib/stdlib_ng.mtlx
index 0b601d6857..e031e72412 100644
--- a/libraries/stdlib/stdlib_ng.mtlx
+++ b/libraries/stdlib/stdlib_ng.mtlx
@@ -1609,13 +1609,13 @@
-
+
@@ -1660,11 +1660,11 @@
-
+
@@ -1686,12 +1686,12 @@
-
-
+
+
@@ -1718,22 +1718,22 @@
-
+
-
+
-
+
-
+
@@ -1754,12 +1754,12 @@
-
+
@@ -2010,13 +2010,13 @@
-
+
-
+
@@ -2109,15 +2109,15 @@
-
+
-
+
-
+
@@ -2129,7 +2129,7 @@
-
+
@@ -2218,15 +2218,15 @@
-
+
-
+
-
+
@@ -2238,7 +2238,7 @@
-
+
@@ -2327,15 +2327,15 @@
-
+
-
+
-
+
@@ -2347,7 +2347,7 @@
-
+
From a32f35d8bd60b154abe7b1f90762d4cd9295245a Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Wed, 30 Aug 2023 10:20:15 -0700
Subject: [PATCH 28/69] Add braces to matrix initializers
This changelist adds braces to matrix initializers in Types.h, improving conformance with upcoming versions of Clang.
---
source/MaterialXCore/Types.h | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
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
From 3fc7b1dc53fadeb5af5253e73276b6802a1072b1 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Wed, 30 Aug 2023 14:00:45 -0700
Subject: [PATCH 29/69] Fix edge case in Python installation
This changelist explicitly sets zip_safe to False in setup.py, as Python's automated detection logic can make this determination incorrectly in some environments.
---
python/setup.py.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
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)
From 8667bd61061f10268e0d721ab00c6e602d34e603 Mon Sep 17 00:00:00 2001
From: Bernard Kwok
Date: Wed, 30 Aug 2023 21:11:39 -0400
Subject: [PATCH 30/69] Guard against invalid nodegraphs and connections in
editor (#1503)
- Add firewall check for output->input connections which are invalid.
- Prevent nodegraph creation inside of nodegraphs which is unimplemented, and actually creates at the root unexpectedly.
## Fixes
- Add a check for output to input connect when trying to create a link. Show the appropriate message. Also some minor variable cleanup.
- Filter out nodes to display in UI when trying to add a node. If inside a nodegraph, then filter out the "nodegraph" entry.
---
source/MaterialXGraphEditor/Graph.cpp | 236 +++++++++++++++-----------
1 file changed, 133 insertions(+), 103 deletions(-)
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index 801a7e09aa..4ddf257706 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -2486,154 +2486,176 @@ void Graph::AddLink(ed::PinId inputPinId, ed::PinId outputPinId)
int start_attr = int(inputPinId.Get());
UiPinPtr inputPin = getPin(outputPinId);
UiPinPtr outputPin = getPin(inputPinId);
- if (inputPinId && outputPinId && (outputPin->_type == inputPin->_type))
+
+ if (!inputPin || !outputPin)
+ {
+ ed::RejectNewItem();
+ return;
+ }
+
+ // Perform type check
+ bool typesMatch = (outputPin->_type == inputPin->_type);
+ if (!typesMatch)
{
- if (inputPin->_connected == false)
+ 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());
+ pin->_input->setConnectedNode(uiUpNode->getNode());
}
- else
+ else if (uiUpNode->getNodeGraph())
{
- if (_graphNodes[upNode]->getNode())
- {
- pin->_input->setConnectedNode(_graphNodes[upNode]->getNode());
- }
- else if (_graphNodes[upNode]->getNodeGraph())
+ 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);
}
}
}
}
-
- 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));
}
}
@@ -3479,6 +3501,7 @@ void Graph::addNodePopup(bool cursor)
std::string subs(input);
// 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
@@ -3489,6 +3512,13 @@ void Graph::addNodePopup(bool cursor)
{
std::string str(it->second[i][0]);
std::string nodeName = it->second[i][0];
+
+ // 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(), ' ', '_');
From 2e60a9fb63e0a83c0ac97cdaa2dbf04e34488919 Mon Sep 17 00:00:00 2001
From: Bernard Kwok
Date: Thu, 31 Aug 2023 16:55:26 -0400
Subject: [PATCH 31/69] Improvements to file I/O options in graph editor
(#1499)
---
source/MaterialXGraphEditor/Graph.cpp | 47 ++++++++++++++++++++-------
source/MaterialXGraphEditor/Graph.h | 4 +--
2 files changed, 38 insertions(+), 13 deletions(-)
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index 4ddf257706..6c437a87bc 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -183,6 +183,9 @@ mx::DocumentPtr Graph::loadDocument(mx::FilePath filename)
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)
@@ -2961,7 +2964,7 @@ void Graph::clearGraph()
_renderer->updateMaterials(nullptr);
}
-void Graph::loadGraphFromFile()
+void Graph::loadGraphFromFile(bool prompt)
{
// deselect node before loading new file
if (_currUiNode != nullptr)
@@ -2970,9 +2973,25 @@ void Graph::loadGraphFromFile()
_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()
@@ -3006,7 +3025,11 @@ void Graph::graphButtons()
}
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"))
{
@@ -3052,12 +3075,16 @@ 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();
@@ -4094,19 +4121,17 @@ void Graph::drawGraph(ImVec2 mousePos)
// saving 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
@@ -4257,7 +4282,7 @@ void Graph::savePosition()
}
}
}
-void Graph::writeText(std::string fileName, mx::FilePath filePath)
+void Graph::saveDocument(mx::FilePath filePath)
{
if (filePath.getExtension() != mx::MTLX_EXTENSION)
{
diff --git a/source/MaterialXGraphEditor/Graph.h b/source/MaterialXGraphEditor/Graph.h
index f01e45fe35..e214af0f41 100644
--- a/source/MaterialXGraphEditor/Graph.h
+++ b/source/MaterialXGraphEditor/Graph.h
@@ -106,7 +106,7 @@ class Graph
void createEdge(UiNodePtr upNode, UiNodePtr downNode, mx::InputPtr connectingInput);
void removeEdge(int downNode, int upNode, UiPinPtr pin);
- void writeText(std::string filename, mx::FilePath filePath);
+ void saveDocument(mx::FilePath filePath);
void savePosition();
bool checkPosition(UiNodePtr node);
@@ -148,7 +148,7 @@ class Graph
// File I/O
void clearGraph();
- void loadGraphFromFile();
+ void loadGraphFromFile(bool prompt);
void saveGraphToFile();
void loadGeometry();
From 4c0f613dc383e047ad468d04a7b6a47079e521f1 Mon Sep 17 00:00:00 2001
From: Bernard Kwok
Date: Thu, 31 Aug 2023 17:39:39 -0400
Subject: [PATCH 32/69] Add support for multioutput connection edits (#1506)
Incorrect connections were being stored on the MaterialX document when making / breaking connections with upstream nodes which have more than one output (mulitoutput nodes).
## Fixes
- Make sure to remove any reference on an input to an upstream output attribute when breaking links.
- Make sure to add the connection to an upstream output if the upstream node is multioutput. Otherwise use the current logic to connect to the node.
- If we always add an output reference on the downstream input, then there is a validation warning if the upstream node is not multioutput but you specify an output on the downstream input. This might be worthwhile to remove as it's not really an error.
---
source/MaterialXGraphEditor/Graph.cpp | 31 ++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index 6c437a87bc..4bea402d6e 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -2606,7 +2606,33 @@ void Graph::AddLink(ed::PinId inputPinId, ed::PinId outputPinId)
{
if (uiUpNode->getNode())
{
- pin->_input->setConnectedNode(uiUpNode->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(uiUpNode->getNode());
+ }
+ else
+ {
+ for (UiPinPtr outPin : _graphNodes[upNode]->outputPins)
+ {
+ // set pin connection to correct output
+ if (outPin->_pinId == inputPinId)
+ {
+ 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())
{
@@ -2716,6 +2742,9 @@ void Graph::deleteLinkInfo(int startAttr, int endAttr)
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 (val)
From 854d056a7817c38df9c1ce0eac421550fe7e5b60 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Thu, 31 Aug 2023 17:10:25 -0700
Subject: [PATCH 33/69] Add Save Node Positions option to editor
This changelist adds a Save Node Positions option to the Graph Editor, allowing the user to save a document without writing out node positions.
---
source/MaterialXGraphEditor/Graph.cpp | 24 ++++++++++++++++++++++--
source/MaterialXGraphEditor/Graph.h | 5 ++++-
2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index 4bea402d6e..991a2b4a9d 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -72,7 +72,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();
@@ -3085,6 +3086,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");
@@ -4318,7 +4325,20 @@ void Graph::saveDocument(mx::FilePath filePath)
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 e214af0f41..9f3f6b0e5e 100644
--- a/source/MaterialXGraphEditor/Graph.h
+++ b/source/MaterialXGraphEditor/Graph.h
@@ -236,7 +236,10 @@ class Graph
std::string _pinFilterType;
// DPI scaling for fonts
- float _fontScale = 1.0f;
+ float _fontScale;
+
+ // Options
+ bool _saveNodePositions;
};
#endif
From 31f8304314fa5b993f2beb838a26d91f6b916af7 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Fri, 1 Sep 2023 14:09:14 -0700
Subject: [PATCH 34/69] Editor code style updates (#1509)
This changelist updates the code style in Graph.cpp and Graph.h, aligning it more closely with the style of the MaterialX codebase.
---
source/MaterialXGraphEditor/Graph.cpp | 542 +++++++++++++-------------
source/MaterialXGraphEditor/Graph.h | 93 ++++-
2 files changed, 350 insertions(+), 285 deletions(-)
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index 991a2b4a9d..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;
@@ -199,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)
@@ -207,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());
@@ -219,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;
@@ -228,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)
@@ -290,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;
@@ -302,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());
@@ -356,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++)
{
@@ -382,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)
@@ -394,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;
@@ -404,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
@@ -417,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[
@@ -436,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)
{
@@ -445,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);
@@ -462,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();
@@ -482,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"))
@@ -510,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])
@@ -537,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)
{
@@ -554,22 +578,22 @@ 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)
@@ -577,7 +601,8 @@ ImVec2 Graph::layoutPosition(UiNodePtr layoutNode, ImVec2 startingPos, bool init
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);
}
}
@@ -587,7 +612,8 @@ ImVec2 Graph::layoutPosition(UiNodePtr layoutNode, ImVec2 startingPos, bool init
{
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));
}
}
@@ -595,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;
@@ -617,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)
@@ -629,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)));
@@ -666,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)
@@ -702,18 +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)
{
- // For now surface shaders and materials are considered renderable.
+ // 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
+ // 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;
@@ -779,6 +782,7 @@ void Graph::setRenderMaterial(UiNodePtr node)
downstreamPorts = testGraph->getDownstreamPorts();
}
}
+
// Test all downstream ports. If the port's node is renderable
// then stop searching.
for (mx::PortElementPtr downstreamPort : downstreamPorts)
@@ -875,6 +879,7 @@ void Graph::updateMaterials(mx::InputPtr input, mx::ValuePtr value)
else
{
std::string name = input->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.
@@ -882,29 +887,29 @@ void Graph::updateMaterials(mx::InputPtr input, mx::ValuePtr 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);
@@ -923,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);
@@ -947,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);
@@ -969,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);
@@ -990,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);
@@ -1009,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);
@@ -1028,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);
@@ -1044,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);
@@ -1062,7 +1074,8 @@ 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"))
{
@@ -1077,20 +1090,21 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
ImGui::PopStyleColor();
ImGui::PopStyleColor();
- // create and load document from selected file
+ // 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);
@@ -1107,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);
@@ -1119,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();
@@ -1205,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())
{
@@ -1228,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();
@@ -1244,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))
@@ -1254,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))
@@ -1280,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())
@@ -1306,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());
@@ -1341,7 +1359,6 @@ void Graph::buildUiBaseGraph(mx::DocumentPtr doc)
}
if (upNum != -1)
{
-
UiEdge newEdge = UiEdge(_graphNodes[upNum], _graphNodes[downNum], input);
if (!edgeExists(newEdge))
{
@@ -1354,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();
@@ -1369,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();
@@ -1387,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();
@@ -1460,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))
{
@@ -1498,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();
@@ -1524,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();
@@ -1593,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;
@@ -1623,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());
@@ -1639,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;
@@ -1655,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))
{
@@ -1724,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());
@@ -1734,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)
@@ -1745,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())
@@ -1771,7 +1784,6 @@ void Graph::copyInputs()
}
else
{
- // node graph
if (upNode->getNodeGraph())
{
ed::PinId outputId = getOutputPin(copyNode, upNode, copyNode->inputPins[count]);
@@ -1811,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);
}
@@ -1831,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 = "";
@@ -1853,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));
@@ -1865,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");
@@ -1889,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));
}
@@ -1904,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);
@@ -1942,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)
@@ -1955,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)
@@ -1969,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);
@@ -1984,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;
@@ -2041,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)
{
@@ -2058,7 +2072,6 @@ mx::InputPtr Graph::findInput(mx::InputPtr nodeInput, std::string name)
{
if (input->getInterfaceInput())
{
-
if (input->getInterfaceInput() == nodeInput)
{
return input;
@@ -2090,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)
{
@@ -2125,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();
@@ -2146,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();
@@ -2176,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)
{
@@ -2230,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)
@@ -2291,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();
@@ -2361,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");
@@ -2427,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())
@@ -2483,8 +2483,7 @@ 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());
@@ -2689,7 +2688,6 @@ void Graph::AddLink(ed::PinId inputPinId, ed::PinId outputPinId)
}
}
-// 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);
@@ -2705,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());
}
@@ -2715,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());
@@ -2737,7 +2733,7 @@ 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());
@@ -2747,7 +2743,8 @@ void Graph::deleteLinkInfo(int startAttr, int endAttr)
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());
@@ -2757,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)
{
@@ -2788,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.
@@ -2797,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);
@@ -2809,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);
@@ -2817,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)
@@ -2834,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;
@@ -2883,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)
@@ -2996,8 +2995,8 @@ void Graph::clearGraph()
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;
@@ -3047,8 +3046,7 @@ 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();
@@ -3127,11 +3125,12 @@ void Graph::graphButtons()
}
}
- // 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("<"))
{
@@ -3155,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;
@@ -3178,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();
@@ -3226,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)
{
@@ -3288,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())
@@ -3333,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());
@@ -3349,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())
{
@@ -3396,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);
@@ -3455,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());
@@ -3499,7 +3500,6 @@ void Graph::propertyEditor()
}
}
-// Helper to display basic user controls.
void Graph::showHelp() const
{
ImGui::Text("MATERIALX GRAPH EDITOR HELP");
@@ -3562,12 +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));
@@ -3582,14 +3583,14 @@ void Graph::addNodePopup(bool cursor)
continue;
}
- // allow spaces to be used to search for node names
+ // 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));
}
@@ -3605,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;
}
}
@@ -3615,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));
@@ -3628,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());
@@ -3647,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());
@@ -3663,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);
@@ -3686,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)
@@ -3720,7 +3722,6 @@ void Graph::readOnlyPopup()
}
}
-// compiling shaders message
void Graph::shaderPopup()
{
if (_renderer->getMaterialCompilation())
@@ -3740,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();
@@ -3784,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)
@@ -3802,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));
@@ -3815,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);
@@ -3825,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());
@@ -3841,17 +3844,18 @@ 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())
{
setRenderMaterial(_currUiNode);
@@ -3865,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())
@@ -3885,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());
@@ -3918,16 +3923,17 @@ 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
+
+ // Place the copied nodes or the individual new nodes
if (!_copiedNodes.empty())
{
positionPasteBin(canvasPos);
@@ -3939,19 +3945,22 @@ void Graph::drawGraph(ImVec2 mousePos)
_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)
{
@@ -3966,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)
@@ -3976,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();
@@ -4012,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;
@@ -4037,7 +4050,7 @@ void Graph::drawGraph(ImVec2 mousePos)
{
if (!readOnly())
{
- AddLink(inputPinId, outputPinId);
+ addLink(inputPinId, outputPinId);
}
else
{
@@ -4057,7 +4070,8 @@ void Graph::drawGraph(ImVec2 mousePos)
_pinFilterType = mx::EMPTY_STRING;
}
ed::EndCreate();
- // deleting link
+
+ // Delete link
if (ed::BeginDelete())
{
ed::LinkId deletedLinkId;
@@ -4076,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)
{
@@ -4084,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();
@@ -4154,7 +4168,8 @@ void Graph::drawGraph(ImVec2 mousePos)
ed::Suspend();
_fileDialogSave.display();
- // saving file
+
+ // Save file
if (_fileDialogSave.hasSelected())
{
std::string message;
@@ -4179,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();
@@ -4210,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;
@@ -4225,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;
@@ -4238,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)
@@ -4274,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)
@@ -4283,7 +4296,6 @@ bool Graph::linkExists(Link newLink)
{
if (link._endAttr == newLink._endAttr)
{
- // link exists
return true;
}
}
@@ -4291,7 +4303,6 @@ bool Graph::linkExists(Link newLink)
{
if (link._endAttr == newLink._startAttr)
{
- // link exists
return true;
}
}
@@ -4299,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;
diff --git a/source/MaterialXGraphEditor/Graph.h b/source/MaterialXGraphEditor/Graph.h
index 9f3f6b0e5e..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 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(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
From 5a781fa3f0e5f996b6eea9892006113db32b41e8 Mon Sep 17 00:00:00 2001
From: Bernard Kwok
Date: Fri, 1 Sep 2023 18:00:50 -0400
Subject: [PATCH 35/69] Handle precedence of generic and target-specific
implementations (#1430)
When dealing with an explicit target on definition search. First test for implementations which have a non-empty target string.
If not found then fallback to non-target implementations. This should fix returning non-target implementations before trying to find implementations with targets.
---
source/MaterialXCore/Definition.cpp | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
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();
}
From f3787626df7e8dc462f1cd1682ec19373efd479a Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Sun, 3 Sep 2023 00:09:08 -0700
Subject: [PATCH 36/69] Consolidate CI workflows (#1511)
- Merge Python Wheel jobs into the Main workflow, reducing overlap and simplifying maintenance.
- Merge Build and Test jobs for Python Wheels, allowing an increase in build parallelism.
- Omit Python Wheel jobs in forks of MaterialX.
---
.github/workflows/main.yml | 93 +++++++++++++++++++++++--
.github/workflows/python.yml | 130 -----------------------------------
2 files changed, 88 insertions(+), 135 deletions(-)
delete mode 100644 .github/workflows/python.yml
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index e5e8b5b31f..c26e00953b 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -160,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: |
@@ -326,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/.github/workflows/python.yml b/.github/workflows/python.yml
deleted file mode 100644
index dddfefb9a4..0000000000
--- a/.github/workflows/python.yml
+++ /dev/null
@@ -1,130 +0,0 @@
-name: python
-
-on:
- push:
- paths-ignore:
- - '**.md'
- pull_request:
- paths-ignore:
- - '**.md'
- workflow_dispatch:
-
-jobs:
- # Generate the sdist first. We'll use it to create the wheels.
- # https://packaging.python.org/en/latest/flow#the-source-distribution-sdist
- sdist:
- name: Generate Source Distribution
- runs-on: ubuntu-latest
- outputs:
- sdist_filename: ${{ steps.generate.outputs.filename }}
-
- steps:
- - name: Sync Repository
- uses: actions/checkout@v3
-
- - name: Install Python ${{ matrix.python }}
- uses: actions/setup-python@v4
- with:
- python-version: 3.11
-
- - name: Install Build Command
- run: python -m pip install build
-
- - name: Generate Sdist
- id: generate
- run: |
- python -m build -s . --outdir dist
- echo "filename=$(ls dist)" >> "$GITHUB_OUTPUT"
-
- - name: Upload Sdist
- uses: actions/upload-artifact@v3
- with:
- name: MaterialX_Python_Source_Distribution
- path: ./dist/*.tar.gz
-
- # Create the wheels. It'll use the sdist to confirm that we can compile MaterialX from the sdist.
- # https://packaging.python.org/en/latest/flow#the-built-distributions-wheels
- wheels:
- name: Generate Wheel
- runs-on: ${{ matrix.os }}
- needs: ['sdist']
- strategy:
- fail-fast: false
- matrix:
- python-version: ['37', '38', '39', '310', '311']
- os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
-
- steps:
- - name: Download Sdist
- uses: actions/download-artifact@v3
- with:
- name: MaterialX_Python_Source_Distribution
- path: sdist
-
- - name: Build Wheel
- # https://cibuildwheel.readthedocs.io/en/stable/
- uses: pypa/cibuildwheel@v2.12.1
- with:
- # Build from the sdist. We want to make sure it's valid and works as expected.
- package-dir: ${{ github.workspace }}/sdist/${{ needs.sdist.outputs.sdist_filename }}
- output-dir: wheels
- env:
- CIBW_BUILD: 'cp${{ matrix.python-version }}-*'
- 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: Upload Wheel
- uses: actions/upload-artifact@v3
- with:
- name: MaterialX_Python_Wheels
- path: ./wheels/*.whl
-
- test:
- name: Test Wheel
- needs: ['wheels']
- runs-on: ${{ matrix.os }}
- strategy:
- fail-fast: false
- matrix:
- python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
- os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
-
- steps:
- - uses: actions/checkout@v3
-
- - uses: actions/setup-python@v4
- with:
- python-version: ${{ matrix.python-version }}
-
- - name: Download Wheels
- uses: actions/download-artifact@v3
- with:
- name: MaterialX_Python_Wheels
- path: wheels
-
- - name: Install Wheel
- run: python -m pip install MaterialX --find-links wheels --no-index
-
- - name: Python Tests
- shell: bash
- run: |
- set -e
- python python/MaterialXTest/main.py
- python python/MaterialXTest/genshader.py
- python python/Scripts/mxformat.py ./resources/Materials/TestSuite/stdlib/upgrade --yes --upgrade
- python python/Scripts/mxvalidate.py ./resources/Materials/Examples/StandardSurface/standard_surface_marble_solid.mtlx --stdlib --verbose
- python python/Scripts/mxdoc.py --docType md ./libraries/pbrlib/pbrlib_defs.mtlx
- python python/Scripts/mxdoc.py --docType html ./libraries/bxdf/standard_surface.mtlx
- python python/Scripts/generateshader.py ./resources/Materials/Examples/StandardSurface --target glsl
- python python/Scripts/generateshader.py ./resources/Materials/Examples/StandardSurface --target osl
- python python/Scripts/generateshader.py ./resources/Materials/Examples/StandardSurface --target mdl
- python python/Scripts/generateshader.py ./resources/Materials/Examples/StandardSurface --target msl
From 488d59bf0796b7f17b011e93b2e1933a352fbd76 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Sun, 3 Sep 2023 13:51:50 -0700
Subject: [PATCH 37/69] Raise minimum version of CMake to 3.5 (#1512)
This changelist raises the minimum version of CMake to 3.5, as earlier versions have been deprecated by the CMake developers.
---
CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 58dfe85aed..cb68ddfae2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@ set(MATERIALX_BUILD_VERSION 8)
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)
From 5de8dc020e8244eefbfa3dcaae6557afae442370 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Mon, 4 Sep 2023 10:47:36 -0700
Subject: [PATCH 38/69] Updates for iOS build (#1515)
- Build iOS with Xcode 15 in GitHub Actions.
- Reduce restrictions for iOS builds in CMake configuration.
---
.github/workflows/main.yml | 4 ++--
CMakeLists.txt | 8 --------
2 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index c26e00953b..d5ac9d3f79 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -83,10 +83,10 @@ jobs:
python: 3.11
test_shaders: ON
- - name: iOS_Xcode_14
+ - name: iOS_Xcode_15
os: macos-13
compiler: xcode
- compiler_version: "14.3"
+ 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
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cb68ddfae2..1e8763d6c7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -64,16 +64,8 @@ if (MATERIALX_BUILD_IOS)
set(MATERIALX_BUILD_GRAPH_EDITOR OFF)
set(MATERIALX_BUILD_GEN_GLSL OFF)
set(MATERIALX_BUILD_GEN_OSL OFF)
- set(MATERIALX_BUILD_GEN_GLSL OFF)
set(MATERIALX_BUILD_GEN_MDL OFF)
- set(MATERIALX_BUILD_OIIO OFF)
- set(MATERIALX_PYTHON_LTO OFF)
- set(MATERIALX_INSTALL_PYTHON OFF)
- set(MATERIALX_DYNAMIC_ANALYSIS OFF)
- set(MATERIALX_DYNAMIC_ANALYSIS OFF)
- set(MATERIALX_OSL_LEGACY_CLOSURES OFF)
set(MATERIALX_BUILD_TESTS OFF)
- set(MATERIALX_TEST_RENDER OFF)
endif()
set(MATERIALX_PYTHON_VERSION "" CACHE STRING
From 6d6c5aa72670c38de95726190a51ccf9bd935485 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Tue, 5 Sep 2023 10:36:46 -0700
Subject: [PATCH 39/69] Update changelog for recent work
---
CHANGELOG.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b65fdb32d4..bf3fdcd50a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@
- 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 an up-axis control to the [triplanar projection node](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1489).
- 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.
@@ -30,6 +31,7 @@
- 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.
## [1.38.7] - 2023-04-21
From f822dc9826162b783c30e4e0ba95341d1a2f1326 Mon Sep 17 00:00:00 2001
From: Ashwin Bhat <1727158+ashwinbhat@users.noreply.github.com>
Date: Tue, 5 Sep 2023 14:12:28 -0700
Subject: [PATCH 40/69] Add method to update uniforms in ShaderRenderer (#1510)
ShaderRenderer::updateUniform allows user to update a uniform value.
---
source/MaterialXRender/ShaderRenderer.cpp | 5 +++++
source/MaterialXRender/ShaderRenderer.h | 3 +++
source/MaterialXRenderGlsl/GlslRenderer.cpp | 10 ++++++++++
source/MaterialXRenderGlsl/GlslRenderer.h | 3 +++
source/MaterialXRenderMsl/MslRenderer.h | 3 +++
source/MaterialXRenderMsl/MslRenderer.mm | 5 +++++
.../PyMaterialX/PyMaterialXRender/PyShaderRenderer.cpp | 1 +
7 files changed, 30 insertions(+)
diff --git a/source/MaterialXRender/ShaderRenderer.cpp b/source/MaterialXRender/ShaderRenderer.cpp
index b621e5cd88..3bba62795e 100644
--- a/source/MaterialXRender/ShaderRenderer.cpp
+++ b/source/MaterialXRender/ShaderRenderer.cpp
@@ -59,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 b049f81126..c1cfbecfa0 100644
--- a/source/MaterialXRender/ShaderRenderer.h
+++ b/source/MaterialXRender/ShaderRenderer.h
@@ -110,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);
diff --git a/source/MaterialXRenderGlsl/GlslRenderer.cpp b/source/MaterialXRenderGlsl/GlslRenderer.cpp
index bf2c8cd849..374305f32f 100644
--- a/source/MaterialXRenderGlsl/GlslRenderer.cpp
+++ b/source/MaterialXRenderGlsl/GlslRenderer.cpp
@@ -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/MaterialXRenderMsl/MslRenderer.h b/source/MaterialXRenderMsl/MslRenderer.h
index 1c54bdbc6a..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;
diff --git a/source/MaterialXRenderMsl/MslRenderer.mm b/source/MaterialXRenderMsl/MslRenderer.mm
index 072f6f1a3a..f5e794c2b3 100644
--- a/source/MaterialXRenderMsl/MslRenderer.mm
+++ b/source/MaterialXRenderMsl/MslRenderer.mm
@@ -124,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,
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);
From 49b0835f07e135eb93491997b33bc9fa74a0e5a6 Mon Sep 17 00:00:00 2001
From: Rasmus Bonnedal
Date: Fri, 8 Sep 2023 01:33:31 +0200
Subject: [PATCH 41/69] Fix input/output count in Element::clearContent (#1520)
When clearContent() is called on an InterfaceElement its _inputCount and _outputCount were not updated even though all inputs and outputs were removed. This led to problems including potential crash in Document::validate().
---
source/MaterialXCore/Element.h | 2 +-
source/MaterialXCore/Interface.cpp | 7 +++++++
source/MaterialXCore/Interface.h | 3 +++
source/MaterialXTest/MaterialXCore/Node.cpp | 18 ++++++++++++++++++
.../PyMaterialXCore/PyInterface.cpp | 1 +
5 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/source/MaterialXCore/Element.h b/source/MaterialXCore/Element.h
index 51e5f7dc24..0e00bf596a 100644
--- a/source/MaterialXCore/Element.h
+++ b/source/MaterialXCore/Element.h
@@ -739,7 +739,7 @@ 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.
diff --git a/source/MaterialXCore/Interface.cpp b/source/MaterialXCore/Interface.cpp
index b733d3a4c7..65570ab6b6 100644
--- a/source/MaterialXCore/Interface.cpp
+++ b/source/MaterialXCore/Interface.cpp
@@ -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/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/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)
From be5b3389f12f89f3d78025dec285a2959c9e9c86 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Fri, 8 Sep 2023 09:29:48 -0700
Subject: [PATCH 42/69] Finalize changelog for 1.38.8 (#1521)
---
CHANGELOG.md | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bf3fdcd50a..b60aaaaf0e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
# 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).
@@ -10,7 +10,7 @@
- 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 an up-axis control to the [triplanar projection node](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1489).
+- 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.
@@ -23,6 +23,7 @@
- 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.
- 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
From f69e4c22f915dd9e1186655a936313faef2f458a Mon Sep 17 00:00:00 2001
From: JGamache-autodesk <56274617+JGamache-autodesk@users.noreply.github.com>
Date: Fri, 8 Sep 2023 15:16:13 -0400
Subject: [PATCH 43/69] Refine dot node elision and remove unused code (#1522)
Dot nodes were elided in #1152 to prevent creating extra samplers in rasterized shadergen.
This preserves the change written by @kwokcb while keeping the distinction between a topological constant node and a non-topological dot node.
In scenarios where you want to feed a single color to multiple shader nodes in a complex material, using a constant node will force recompilation every time the color is tweaked, we want users to be able to use a dot node to feed the graph, which should allow tweaking the color without having to recompile the shader. Also allows re-using the shader code for material instances differing on this input color.
---
.../stdlib/organization/organization.mtlx | 10 +++++
source/MaterialXGenShader/ShaderGraph.cpp | 40 ++-----------------
source/MaterialXGenShader/ShaderNode.cpp | 10 -----
source/MaterialXGenShader/ShaderNode.h | 13 ++----
4 files changed, 18 insertions(+), 55 deletions(-)
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/source/MaterialXGenShader/ShaderGraph.cpp b/source/MaterialXGenShader/ShaderGraph.cpp
index 8a424f8bf5..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)
diff --git a/source/MaterialXGenShader/ShaderNode.cpp b/source/MaterialXGenShader/ShaderNode.cpp
index 3eb750f1ff..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)
{
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;
From 92734332d595278298ad08e6543409bbabf344f0 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Fri, 8 Sep 2023 12:26:50 -0700
Subject: [PATCH 44/69] Additional changelog updates for 1.38.8
---
CHANGELOG.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b60aaaaf0e..5704c54b84 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@
- 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
@@ -33,6 +34,7 @@
- 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
From 46a5b507b82bb38a70c66877e5d87e588ca9785e Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Sun, 10 Sep 2023 10:50:11 -0700
Subject: [PATCH 45/69] Update development build to 1.38.9
---
CHANGELOG.md | 2 ++
CMakeLists.txt | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5704c54b84..47b1bfe8b8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,7 @@
# Change Log
+## [1.38.9] - Development
+
## [1.38.8] - 2023-09-08
### Added
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1e8763d6c7..c255924fa4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
# MaterialX Version
set(MATERIALX_MAJOR_VERSION 1)
set(MATERIALX_MINOR_VERSION 38)
-set(MATERIALX_BUILD_VERSION 8)
+set(MATERIALX_BUILD_VERSION 9)
set(MATERIALX_LIBRARY_VERSION ${MATERIALX_MAJOR_VERSION}.${MATERIALX_MINOR_VERSION}.${MATERIALX_BUILD_VERSION})
# Cmake setup
From 1a39d99a41ccfd5c0a12759b185af3946e2ff45f Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Tue, 12 Sep 2023 17:03:47 -0700
Subject: [PATCH 46/69] Update documentation
- Update links to pre-built binaries in README.md.
- Update link to ASWF Open Source Days in README.md.
- Update MaterialX Overview in MainPage.md.
- Update code and data syntax in ShaderGeneration.md.
- Update documentation for the ImageHandler::acquireImage method.
---
README.md | 8 +-
documents/DeveloperGuide/MainPage.md | 2 +-
documents/DeveloperGuide/ShaderGeneration.md | 135 +++++++++----------
source/MaterialXRender/ImageHandler.h | 3 +
4 files changed, 71 insertions(+), 77 deletions(-)
diff --git a/README.md b/README.md
index e6c6e2d0e4..ddccb4a9db 100644
--- a/README.md
+++ b/README.md
@@ -60,13 +60,13 @@ The Open Chess Set is an open reference asset, consisting of a [MaterialX file](
The following packages contain pre-built binaries for the latest release, including the MaterialX viewer, Python libraries, and example assets:
-- [Microsoft Windows (Visual Studio 2022, Python 3.9)](https://github.com/AcademySoftwareFoundation/MaterialX/releases/latest/download/MaterialX_Windows_VS2022_x64_Python39.zip)
-- [MacOS (Xcode 13, Python 3.9)](https://github.com/AcademySoftwareFoundation/MaterialX/releases/latest/download/MaterialX_MacOS_Xcode_13_Python39.zip)
-- [Linux (GCC 11, Python 3.9)](https://github.com/AcademySoftwareFoundation/MaterialX/releases/latest/download/MaterialX_Linux_GCC_11_Python39.zip)
+- [Microsoft Windows (Visual Studio 2022, Python 3.11)](https://github.com/AcademySoftwareFoundation/MaterialX/releases/latest/download/MaterialX_Windows_VS2022_x64_Python311.zip)
+- [MacOS (Xcode 14, Python 3.11)](https://github.com/AcademySoftwareFoundation/MaterialX/releases/latest/download/MaterialX_MacOS_Xcode_14_Python311.zip)
+- [Linux (GCC 12, Python 3.11)](https://github.com/AcademySoftwareFoundation/MaterialX/releases/latest/download/MaterialX_Linux_GCC_12_Python311.zip)
### Additional Resources
- The [Developer Guide](http://www.materialx.org/docs/api/index.html) contains a developer-oriented overview of MaterialX with API documentation.
- The [Python Scripts](python/Scripts) folder contains standalone examples of MaterialX Python code.
- The [JavaScript](javascript) folder contains details on building JavaScript bindings for MaterialX.
-- Presentations at [ASWF Open Source Days](http://www.materialx.org/assets/ASWF_OSD2022_MaterialX_OSL_Final.pdf) and the [SIGGRAPH Physically Based Shading Course](https://blog.selfshadow.com/publications/s2020-shading-course/#materialx) provide details on the roadmap for MaterialX development.
+- Presentations at [ASWF Open Source Days](https://materialx.org/assets/ASWF_OSD2023_MaterialX_Final.pdf) and the [SIGGRAPH Physically Based Shading Course](https://blog.selfshadow.com/publications/s2020-shading-course/#materialx) provide details on the roadmap for MaterialX development.
diff --git a/documents/DeveloperGuide/MainPage.md b/documents/DeveloperGuide/MainPage.md
index 79441a3e4d..d6c098a23d 100644
--- a/documents/DeveloperGuide/MainPage.md
+++ b/documents/DeveloperGuide/MainPage.md
@@ -1,6 +1,6 @@
# MaterialX Overview
-MaterialX is an open standard for transfer of rich material and look-development content between applications and renderers. Originated at Lucasfilm in 2012, MaterialX has been used by Industrial Light & Magic (ILM) in feature films such as _Star Wars: The Force Awakens_ and real-time experiences such as _Trials on Tatooine_, and it remains the central material format for new ILM productions.
+MaterialX is an open standard for representing rich material and look-development content in computer graphics, enabling its platform-independent description and exchange across applications and renderers. Launched at [Industrial Light & Magic](https://www.ilm.com/) in 2012, MaterialX has been a key technology in their feature films and real-time experiences since _Star Wars: The Force Awakens_ and _Millennium Falcon: Smugglers Run_. The project was released as open source in 2017, with companies including Sony Pictures Imageworks, Pixar, Autodesk, Adobe, and SideFX contributing to its ongoing development. In 2021, MaterialX became the seventh hosted project of the [Academy Software Foundation](https://www.aswf.io/).
### Quick Start for Developers
diff --git a/documents/DeveloperGuide/ShaderGeneration.md b/documents/DeveloperGuide/ShaderGeneration.md
index 059b34d580..01bd823ec4 100644
--- a/documents/DeveloperGuide/ShaderGeneration.md
+++ b/documents/DeveloperGuide/ShaderGeneration.md
@@ -33,37 +33,41 @@ Figure 2. The first option is to keep inline code in a file. The file extension
```xml
// Nodedef elements for node
-
-
-
+
+
+
+
-
-
-
+
+
+
+
<... more types ...>
// Implementation elements for node
-
-
+
+
<... more types ...>
// Nodedef elements for node
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
<... more types ...>
// Implementation elements for node
-
-
+
+
<... more types ...>
```
```c++
@@ -79,30 +83,29 @@ For nodes that can’t be implemented by inline expressions a function definitio
```xml
// Nodedef element
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
// Implementation element
-
+
```
```c++
// File 'mx_image_color3.osl' contains:
void mx_image_color3(string file, string layer, color defaultvalue,
- vector2 texcoord, string filtertype,
- string uaddressmode, string vaddressmode,
- string framerange, int frameoffset,
- string frameendaction, output color out)
+ vector2 texcoord, string uaddressmode, string vaddressmode, string filtertype,
+ string framerange, int frameoffset, string frameendaction,
+ output color out)
{
// Sample the texture
out = texture(file, texcoord.x, texcoord.y,
@@ -120,40 +123,28 @@ As an alternative to defining source code, there is also an option to reference
This is useful for creating a compound for a set of nodes performing some common operation. It can then be referenced as a node inside other nodegraphs. It is also useful for creating compatibility graphs for unknown nodes. If a node is created by some third party, and its implementation is unknown or proprietary, a compatibility graph can be created using known nodes and be referenced as a stand-in implementation. Linking a nodegraph to a nodedef is done by simply setting a nodedef attribute on the nodegraph definition. See Figure 4 for an example.
```xml
-
-
+
+
+
+
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
```
**Figure 4**: Checker node implementation using a nodegraph.
@@ -161,10 +152,9 @@ This is useful for creating a compound for a set of nodes performing some common
### 1.3.4 Dynamic Code Generation
In some situations static source code is not enough to implement a node. The code might need to be customized depending on parameters set on the node. Or for a hardware render target vertex streams or uniform inputs might need to be created in order to supply the data needed for the node implementation.
-In this case, a C++ class can be added to handle the implementation of the node. The class should be derived from the base class `ShaderNodeImpl`. It should specify what language and target it is for by overriding `getLanguage()` and `getTarget()`. It can also be specified to support all languages or all targets by setting the identifier to an empty string, as done for the target identifier in the example below. It then needs to be registered for a `ShaderGenerator` by calling `ShaderGenerator::registerImplementation()`. See Figure 5 for an example.
+In this case, a C++ class can be added to handle the implementation of the node. The class should be derived from the base class `ShaderNodeImpl`. It should specify what target it is for by overriding `getTarget()`. It then needs to be registered for a `ShaderGenerator` by calling `ShaderGenerator::registerImplementation()`. See Figure 5 for an example.
-When a `ShaderNodeImpl` class is used for a nodedef the corresponding ``
-element doesn’t need a file attribute, since no static source code is used. The `` element will then act only as a declaration that there exists an implementation for the nodedef for a particular language and target.
+When a `ShaderNodeImpl` class is used for a nodedef the corresponding `` element doesn’t need a file attribute, since no static source code is used. The `` element will then act only as a declaration that there exists an implementation for the nodedef for a particular target.
Note that by using a `ShaderNodeImpl` class for your node's implementation it is no longer data driven, as in the other three methods above. So it's recommended to use this only when inline expressions or static source code functions are not enough to handle the implementation of a node.
@@ -175,8 +165,7 @@ class FooOsl : public ShaderNodeImpl
public:
static ShaderNodeImplPtr create() { return std::make_shared(); }
- const string& getLanguage() const override { return LANGUAGE_OSL; }
- const string& getTarget() const override { return EMPTY_STRING; }
+ const string& getTarget() const override { return OslShaderGenerator::TARGET; }
void emitFunctionDefinition(const ShaderNode& node, GenContext& context,
ShaderStage& stage) const override
@@ -291,7 +280,8 @@ class TexCoordGlsl : public ShaderNodeImpl
const string index = indexInput ? indexInput->getValue()->getValueString() : "0";
const string variable = "texcoord_" + index;
- BEGIN_SHADER_STAGE(stage, Stage::VERTEX)
+ DEFINE_SHADER_STAGE(stage, Stage::VERTEX)
+ {
VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA);
const string prefix = vertexData.getInstance() + ".";
ShaderPort* texcoord = vertexData[variable];
@@ -300,9 +290,10 @@ class TexCoordGlsl : public ShaderNodeImpl
shadergen.emitLine(prefix + texcoord->getVariable() + " = i_" + variable, stage);
texcoord->setEmitted();
}
- END_SHADER_STAGE(shader, Stage::VERTEX)
+ }
- BEGIN_SHADER_STAGE(stage, Stage::PIXEL)
+ DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
+ {
VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA);
const string prefix = vertexData.getInstance() + ".";
ShaderPort* texcoord = vertexData[variable];
@@ -310,7 +301,7 @@ class TexCoordGlsl : public ShaderNodeImpl
shadergen.emitOutput(node.getOutput(), true, false, context, stage);
shadergen.emitString(" = " + prefix + texcoord->getVariable(), stage);
shadergen.emitLineEnd(stage);
- END_SHADER_STAGE(shader, Stage::PIXEL)
+ }
}
};
```
diff --git a/source/MaterialXRender/ImageHandler.h b/source/MaterialXRender/ImageHandler.h
index c744eb2f6a..fafc021857 100644
--- a/source/MaterialXRender/ImageHandler.h
+++ b/source/MaterialXRender/ImageHandler.h
@@ -186,7 +186,10 @@ class MX_RENDER_API ImageHandler
/// Acquire an image from the cache or file system. If the image is not
/// found in the cache, then each image loader will be applied in turn.
+ /// If the image cannot be found by any loader, then a uniform image of the
+ /// given default color will be returned.
/// @param filePath File path of the image.
+ /// @param defaultColor Default color to use as a fallback for missing images.
/// @return On success, a shared pointer to the acquired image.
ImagePtr acquireImage(const FilePath& filePath, const Color4& defaultColor = Color4(0.0f));
From a5a74feab2eec007ca8e87eeb9c57c667e32ff2c Mon Sep 17 00:00:00 2001
From: Niklas Harrysson
Date: Sun, 17 Sep 2023 00:11:53 +0200
Subject: [PATCH 47/69] Fix attenuation of coated emission in Standard Surface
(#1534)
This change list fixes a math mistake in the handling of how emission is attenuated by the top coat in Standard Surface. Thanks to @portsmouth and @Reedbeta for reporting my mistake and suggesting a workaround.
---
libraries/bxdf/standard_surface.mtlx | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/libraries/bxdf/standard_surface.mtlx b/libraries/bxdf/standard_surface.mtlx
index 843885aa50..c7de68929a 100644
--- a/libraries/bxdf/standard_surface.mtlx
+++ b/libraries/bxdf/standard_surface.mtlx
@@ -386,6 +386,10 @@
+
+
+
+
@@ -398,8 +402,8 @@
-
-
+
+
From 6c486837e682abd61fdd566fc28ef9980cdcda93 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Fri, 22 Sep 2023 10:26:46 -0700
Subject: [PATCH 48/69] Align default precision across shading languages
(#1538)
This changelist removes explicit overrides of floating-point precision in shader generation, making the default precision 6 decimal places across shading languages, and allowing the client to adjust the precision of generated shaders via Value::setFloatPrecision.
This addresses a slight visual regression in generated OSL (with a maximum visual error on the order of 1e-3), caused by a hard-coding of floating-point precision to 3 decimal places in OslSyntax.
---
source/MaterialXCore/Value.cpp | 5 ++++-
source/MaterialXCore/Value.h | 2 +-
source/MaterialXGenGlsl/GlslShaderGenerator.cpp | 4 +---
source/MaterialXGenMdl/MdlShaderGenerator.cpp | 3 +++
source/MaterialXGenMsl/MslShaderGenerator.cpp | 4 +---
source/MaterialXGenOsl/OslShaderGenerator.cpp | 3 +++
source/MaterialXGenOsl/OslSyntax.cpp | 1 -
7 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/source/MaterialXCore/Value.cpp b/source/MaterialXCore/Value.cpp
index 238473d5ad..3e8c1f4462 100644
--- a/source/MaterialXCore/Value.cpp
+++ b/source/MaterialXCore/Value.cpp
@@ -242,7 +242,10 @@ ScopedFloatFormatting::ScopedFloatFormatting(Value::FloatFormat format, int prec
_precision(Value::getFloatPrecision())
{
Value::setFloatFormat(format);
- Value::setFloatPrecision(precision);
+ if (precision >= 0)
+ {
+ Value::setFloatPrecision(precision);
+ }
}
ScopedFloatFormatting::~ScopedFloatFormatting()
diff --git a/source/MaterialXCore/Value.h b/source/MaterialXCore/Value.h
index 8e55a97acf..1bd29b1d2b 100644
--- a/source/MaterialXCore/Value.h
+++ b/source/MaterialXCore/Value.h
@@ -198,7 +198,7 @@ template class MX_CORE_API TypedValue : public Value
class MX_CORE_API ScopedFloatFormatting
{
public:
- explicit ScopedFloatFormatting(Value::FloatFormat format, int precision = 6);
+ explicit ScopedFloatFormatting(Value::FloatFormat format, int precision = -1);
~ScopedFloatFormatting();
private:
diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp
index 766b61ec05..839f591aa5 100644
--- a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp
+++ b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp
@@ -279,9 +279,7 @@ ShaderPtr GlslShaderGenerator::generate(const string& name, ElementPtr element,
{
ShaderPtr shader = createShader(name, element, context);
- // Turn on fixed float formatting to make sure float values are
- // emitted with a decimal point and not as integers, and to avoid
- // any scientific notation which isn't supported by all OpenGL targets.
+ // Request fixed floating-point notation for consistency across targets.
ScopedFloatFormatting fmt(Value::FloatFormatFixed);
// Make sure we initialize/reset the binding context before generation.
diff --git a/source/MaterialXGenMdl/MdlShaderGenerator.cpp b/source/MaterialXGenMdl/MdlShaderGenerator.cpp
index dddf1f2f13..f64b555c20 100644
--- a/source/MaterialXGenMdl/MdlShaderGenerator.cpp
+++ b/source/MaterialXGenMdl/MdlShaderGenerator.cpp
@@ -198,6 +198,9 @@ ShaderPtr MdlShaderGenerator::generate(const string& name, ElementPtr element, G
ShaderPtr shader = createShader(name, element, context);
+ // Request fixed floating-point notation for consistency across targets.
+ ScopedFloatFormatting fmt(Value::FloatFormatFixed);
+
ShaderGraph& graph = shader->getGraph();
ShaderStage& stage = shader->getStage(Stage::PIXEL);
diff --git a/source/MaterialXGenMsl/MslShaderGenerator.cpp b/source/MaterialXGenMsl/MslShaderGenerator.cpp
index dcb0a3ed69..0d97e8408f 100644
--- a/source/MaterialXGenMsl/MslShaderGenerator.cpp
+++ b/source/MaterialXGenMsl/MslShaderGenerator.cpp
@@ -283,9 +283,7 @@ ShaderPtr MslShaderGenerator::generate(const string& name, ElementPtr element, G
{
ShaderPtr shader = createShader(name, element, context);
- // Turn on fixed float formatting to make sure float values are
- // emitted with a decimal point and not as integers, and to avoid
- // any scientific notation which isn't supported by all OpenGL targets.
+ // Request fixed floating-point notation for consistency across targets.
ScopedFloatFormatting fmt(Value::FloatFormatFixed);
// Make sure we initialize/reset the binding context before generation.
diff --git a/source/MaterialXGenOsl/OslShaderGenerator.cpp b/source/MaterialXGenOsl/OslShaderGenerator.cpp
index b4edbee44b..b37a84c579 100644
--- a/source/MaterialXGenOsl/OslShaderGenerator.cpp
+++ b/source/MaterialXGenOsl/OslShaderGenerator.cpp
@@ -170,6 +170,9 @@ ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, G
{
ShaderPtr shader = createShader(name, element, context);
+ // Request fixed floating-point notation for consistency across targets.
+ ScopedFloatFormatting fmt(Value::FloatFormatFixed);
+
ShaderGraph& graph = shader->getGraph();
ShaderStage& stage = shader->getStage(Stage::PIXEL);
diff --git a/source/MaterialXGenOsl/OslSyntax.cpp b/source/MaterialXGenOsl/OslSyntax.cpp
index d421c5e3d9..5a6b45dd61 100644
--- a/source/MaterialXGenOsl/OslSyntax.cpp
+++ b/source/MaterialXGenOsl/OslSyntax.cpp
@@ -220,7 +220,6 @@ class OSLMatrix3TypeSyntax : public AggregateTypeSyntax
string getValue(const Value& value, bool uniform) const override
{
- ScopedFloatFormatting fmt(Value::FloatFormatFixed, 3);
StringVec values = splitString(value.getValueString(), ",");
return getValue(values, uniform);
}
From 7009c6daf7459716350593e318e4243d6e808f19 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Thu, 28 Sep 2023 17:57:00 -0700
Subject: [PATCH 49/69] Initial coverage test in GitHub CI
This changelist adds an initial coverage test to GitHub Actions builds, uploading the generated HTML document as a new build artifact.
---
.github/workflows/main.yml | 61 +++++++++++++++++++++++++++-----------
CMakeLists.txt | 6 ++++
2 files changed, 50 insertions(+), 17 deletions(-)
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index d5ac9d3f79..4fdcefb7fb 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -39,6 +39,14 @@ jobs:
python: 3.11
upload_shaders: ON
+ - name: Linux_GCC_CoverageAnalysis
+ os: ubuntu-22.04
+ compiler: gcc
+ compiler_version: "None"
+ python: None
+ coverage_analysis: ON
+ cmake_config: -DMATERIALX_COVERAGE_ANALYSIS=ON -DMATERIALX_BUILD_RENDER=OFF -DMATERIALX_BUILD_PYTHON=OFF
+
- name: Linux_Clang_10_Python37
os: ubuntu-20.04
compiler: clang
@@ -120,28 +128,32 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install xorg-dev mesa-utils
- if [ "${{ matrix.compiler }}" = "gcc" ]; then
- sudo apt-get install -y g++-${{ matrix.compiler_version }} g++-${{ matrix.compiler_version }}-multilib
- echo "CC=gcc-${{ matrix.compiler_version }}" >> $GITHUB_ENV
- echo "CXX=g++-${{ matrix.compiler_version }}" >> $GITHUB_ENV
- else
- sudo apt-get install -y clang-${{ matrix.compiler_version }} libc++-${{ matrix.compiler_version }}-dev libc++abi-${{ matrix.compiler_version }}-dev
- echo "CC=clang-${{ matrix.compiler_version }}" >> $GITHUB_ENV
- echo "CXX=clang++-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ if [ "${{ matrix.compiler_version }}" != 'None' ]; then
+ if [ "${{ matrix.compiler }}" = "gcc" ]; then
+ sudo apt-get install -y g++-${{ matrix.compiler_version }} g++-${{ matrix.compiler_version }}-multilib
+ echo "CC=gcc-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ echo "CXX=g++-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ else
+ sudo apt-get install -y clang-${{ matrix.compiler_version }} libc++-${{ matrix.compiler_version }}-dev libc++abi-${{ matrix.compiler_version }}-dev
+ echo "CC=clang-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ echo "CXX=clang++-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ fi
fi
- name: Install Dependencies (MacOS)
if: runner.os == 'macOS'
run: |
- if [ "${{ matrix.compiler }}" = "gcc" ]; then
- brew install gcc@${{ matrix.compiler_version }}
- echo "CC=gcc-${{ matrix.compiler_version }}" >> $GITHUB_ENV
- echo "CXX=g++-${{ matrix.compiler_version }}" >> $GITHUB_ENV
- else
- ls -ls /Applications/
- sudo xcode-select -switch /Applications/Xcode_${{ matrix.compiler_version }}.app
- echo "CC=clang" >> $GITHUB_ENV
- echo "CXX=clang++" >> $GITHUB_ENV
+ if [ "${{ matrix.compiler_version }}" != 'None' ]; then
+ if [ "${{ matrix.compiler }}" = "gcc" ]; then
+ brew install gcc@${{ matrix.compiler_version }}
+ echo "CC=gcc-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ echo "CXX=g++-${{ matrix.compiler_version }}" >> $GITHUB_ENV
+ else
+ ls -ls /Applications/
+ sudo xcode-select -switch /Applications/Xcode_${{ matrix.compiler_version }}.app
+ echo "CC=clang" >> $GITHUB_ENV
+ echo "CXX=clang++" >> $GITHUB_ENV
+ fi
fi
- name: Install Dependencies (Windows)
@@ -222,6 +234,14 @@ jobs:
run: |
python python/Scripts/generateshader.py resources/Materials/Examples/StandardSurface --target msl --validator "xcrun metal --language=metal" --validatorArgs="-w"
+ - name: Coverage Analysis Tests
+ if: matrix.coverage_analysis == 'ON'
+ run: |
+ sudo apt-get install gcovr
+ mkdir coverage
+ gcovr --html --html-details --output coverage/index.html --exclude .*\/External\/.* --root .. .
+ working-directory: build
+
- name: Static Analysis Tests
if: matrix.static_analysis == 'ON' && runner.os == 'Linux'
run: |
@@ -279,6 +299,13 @@ jobs:
name: Renders_${{ matrix.name }}
path: build/render/*.png
+ - name: Upload Coverage Report
+ uses: actions/upload-artifact@v3
+ if: matrix.coverage_analysis == 'ON'
+ with:
+ name: MaterialX_Coverage
+ path: build/coverage
+
- name: JavaScript CMake Generate
if: matrix.build_javascript == 'ON'
run: |
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c255924fa4..de6aa7442f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -52,6 +52,7 @@ option(MATERIALX_INSTALL_PYTHON "Install the MaterialX Python package as a third
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_COVERAGE_ANALYSIS "Build MaterialX libraries with coverage analysis on supporting platforms." 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)
@@ -138,6 +139,7 @@ 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_COVERAGE_ANALYSIS)
mark_as_advanced(MATERIALX_DYNAMIC_ANALYSIS)
mark_as_advanced(MATERIALX_PYTHON_VERSION)
mark_as_advanced(MATERIALX_PYTHON_EXECUTABLE)
@@ -228,6 +230,10 @@ else()
if(MATERIALX_WARNINGS_AS_ERRORS)
add_compile_options(-Werror)
endif()
+ if(MATERIALX_COVERAGE_ANALYSIS)
+ add_compile_options(--coverage -O0)
+ add_link_options(--coverage)
+ endif()
if(MATERIALX_DYNAMIC_ANALYSIS)
set(DYNAMIC_ANALYSIS_OPTIONS -fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-sanitize-recover=all)
add_compile_options(${DYNAMIC_ANALYSIS_OPTIONS})
From 0bd09787e869619ea4ca0f78fe89711539d9f2cf Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Tue, 3 Oct 2023 09:08:10 -0700
Subject: [PATCH 50/69] Improvements to shader generation tests
- Include all example documents by default in shader generation tests, rather than excluding a subset of the examples in all generators.
- Remove an unused input from the render test suite options, eliminating a source of syntax errors in shader generation tests.
---
resources/Materials/TestSuite/_options.mtlx | 3 ---
.../MaterialXGenShader/GenShaderUtil.cpp | 21 -------------------
.../MaterialXGenShader/GenShaderUtil.h | 8 +++----
3 files changed, 3 insertions(+), 29 deletions(-)
diff --git a/resources/Materials/TestSuite/_options.mtlx b/resources/Materials/TestSuite/_options.mtlx
index 8716cba5f0..bb29fbd7c1 100644
--- a/resources/Materials/TestSuite/_options.mtlx
+++ b/resources/Materials/TestSuite/_options.mtlx
@@ -87,9 +87,6 @@
-
-
-
diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp
index 863cd1af05..261aacdefe 100644
--- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp
+++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp
@@ -480,27 +480,6 @@ void ShaderGeneratorTester::setupDependentLibraries()
loadLibraries({ "libraries" }, _searchPath, _dependLib, _skipLibraryFiles);
}
-void ShaderGeneratorTester::addSkipFiles()
-{
- _skipFiles.insert("_options.mtlx");
- _skipFiles.insert("light_rig_test_1.mtlx");
- _skipFiles.insert("light_rig_test_2.mtlx");
- _skipFiles.insert("light_compound_test.mtlx");
- _skipFiles.insert("xinclude_search_path.mtlx");
- _skipFiles.insert("1_38_parameter_to_input.mtlx");
- _skipFiles.insert("1_36_to_1_37.mtlx");
- _skipFiles.insert("1_37_to_1_38.mtlx");
- _skipFiles.insert("material_element_to_surface_material.mtlx");
-}
-
-void ShaderGeneratorTester::addSkipNodeDefs()
-{
-}
-
-void ShaderGeneratorTester::addSkipLibraryFiles()
-{
-}
-
LightIdMap ShaderGeneratorTester::computeLightIdMap(const std::vector& nodes)
{
std::unordered_map idMap;
diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h
index 7be195e9de..ea34170d71 100644
--- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h
+++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h
@@ -180,13 +180,13 @@ class ShaderGeneratorTester
virtual void setTestStages() = 0;
// Add files in to not examine
- virtual void addSkipFiles();
+ virtual void addSkipFiles() { };
// Add nodedefs to not examine
- virtual void addSkipNodeDefs();
+ virtual void addSkipNodeDefs() { };
// Add files to be skipped while loading libraries
- virtual void addSkipLibraryFiles();
+ virtual void addSkipLibraryFiles() { };
// Add color management
virtual void addColorManagement();
@@ -268,8 +268,6 @@ class ShaderGeneratorTester
mx::StringSet _usedImplementations;
};
-
-
} // namespace GenShaderUtil
#endif
From a79ddfb25589955bdb6060f4ce379dce56029275 Mon Sep 17 00:00:00 2001
From: Niklas Harrysson
Date: Wed, 4 Oct 2023 17:16:32 +0200
Subject: [PATCH 51/69] Use explicit colorspace parameters in OSL texture calls
(#1546)
This change list adds the parameter "colorspace" to the texture call in OSL, for sampling color3/color4 textures. Previously this was supported under the covers, by token replacement that a custom OSL generator had to setup, and only done for the Arnold OSL generator.
---
libraries/stdlib/genosl/mx_image_color3.osl | 3 +--
libraries/stdlib/genosl/mx_image_color4.osl | 2 +-
source/MaterialXGenOsl/OslShaderGenerator.cpp | 4 ----
source/MaterialXGenOsl/OslShaderGenerator.h | 3 ---
4 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/libraries/stdlib/genosl/mx_image_color3.osl b/libraries/stdlib/genosl/mx_image_color3.osl
index 15b594e885..89ba94f376 100644
--- a/libraries/stdlib/genosl/mx_image_color3.osl
+++ b/libraries/stdlib/genosl/mx_image_color3.osl
@@ -12,6 +12,5 @@ void mx_image_color3(textureresource file, string layer, color default_value, ve
color missingColor = default_value;
vector2 st = mx_transform_uv(texcoord);
- out = texture(file.filename, st.x, st.y, "subimage", layer, "missingcolor", missingColor, "swrap", uaddressmode, "twrap", vaddressmode $extraTextureLookupArguments);
+ out = texture(file.filename, st.x, st.y, "subimage", layer, "missingcolor", missingColor, "swrap", uaddressmode, "twrap", vaddressmode, "colorspace", file.colorspace);
}
-
diff --git a/libraries/stdlib/genosl/mx_image_color4.osl b/libraries/stdlib/genosl/mx_image_color4.osl
index 3bde1a5047..261108b5b4 100644
--- a/libraries/stdlib/genosl/mx_image_color4.osl
+++ b/libraries/stdlib/genosl/mx_image_color4.osl
@@ -15,7 +15,7 @@ void mx_image_color4(textureresource file, string layer, color4 default_value, v
vector2 st = mx_transform_uv(texcoord);
float alpha;
color rgb = texture(file.filename, st.x, st.y, "alpha", alpha, "subimage", layer,
- "missingcolor", missingColor, "missingalpha", missingAlpha, "swrap", uaddressmode, "twrap", vaddressmode $extraTextureLookupArguments );
+ "missingcolor", missingColor, "missingalpha", missingAlpha, "swrap", uaddressmode, "twrap", vaddressmode, "colorspace", file.colorspace);
out = color4(rgb, alpha);
}
diff --git a/source/MaterialXGenOsl/OslShaderGenerator.cpp b/source/MaterialXGenOsl/OslShaderGenerator.cpp
index b37a84c579..28ada48626 100644
--- a/source/MaterialXGenOsl/OslShaderGenerator.cpp
+++ b/source/MaterialXGenOsl/OslShaderGenerator.cpp
@@ -26,7 +26,6 @@
MATERIALX_NAMESPACE_BEGIN
const string OslShaderGenerator::TARGET = "genosl";
-const string OslShaderGenerator::T_FILE_EXTRA_ARGUMENTS = "$extraTextureLookupArguments";
//
// OslShaderGenerator methods
@@ -161,9 +160,6 @@ OslShaderGenerator::OslShaderGenerator() :
//
registerImplementation("IM_surfacematerial_" + OslShaderGenerator::TARGET, MaterialNodeOsl::create);
-
- // Extra arguments for texture lookups.
- _tokenSubstitutions[T_FILE_EXTRA_ARGUMENTS] = EMPTY_STRING;
}
ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, GenContext& context) const
diff --git a/source/MaterialXGenOsl/OslShaderGenerator.h b/source/MaterialXGenOsl/OslShaderGenerator.h
index 91690adc1d..0c7ca426d7 100644
--- a/source/MaterialXGenOsl/OslShaderGenerator.h
+++ b/source/MaterialXGenOsl/OslShaderGenerator.h
@@ -48,9 +48,6 @@ class MX_GENOSL_API OslShaderGenerator : public ShaderGenerator
void registerShaderMetadata(const DocumentPtr& doc, GenContext& context) const override;
protected:
- // Extra file arguments for texture lookup call
- static const string T_FILE_EXTRA_ARGUMENTS;
-
/// Create and initialize a new OSL shader for shader generation.
virtual ShaderPtr createShader(const string& name, ElementPtr element, GenContext& context) const;
From ab4c211ac3bc033afa8c9a0dbcfafa48eff2147e Mon Sep 17 00:00:00 2001
From: Bernard Kwok
Date: Wed, 4 Oct 2023 11:26:15 -0400
Subject: [PATCH 52/69] Add XML tags to MaterialX blocks in specification
(#1544)
- Add xml formatting tag for spec markdown docs.
- Existing docs like shader gen already use the appropriate formatting tags.
- Tested this with converters such as pandoc, and VScode markdown converter and should make no difference as they
will just end up as preformatted text ``.
---
documents/Specification/MaterialX.GeomExts.md | 42 +++---
.../Specification/MaterialX.Specification.md | 130 +++++++++---------
.../Specification/MaterialX.Supplement.md | 2 +-
3 files changed, 87 insertions(+), 87 deletions(-)
diff --git a/documents/Specification/MaterialX.GeomExts.md b/documents/Specification/MaterialX.GeomExts.md
index fb0d581ed8..5ff300de01 100644
--- a/documents/Specification/MaterialX.GeomExts.md
+++ b/documents/Specification/MaterialX.GeomExts.md
@@ -113,7 +113,7 @@ Collections are recipes for building a list of geometries (which can be any path
A **<collection>** element contains lists of geometry expressions and/or collections to be included, and an optional list of geometry expressions to be excluded:
-```
+```xml
@@ -132,7 +132,7 @@ As a shorthand convenience, MaterialX allows the specification of a `geomprefix`
So the following MTLX file snippets are equivalent:
-```
+```xml
@@ -176,7 +176,7 @@ The most common use for geominfo elements is to define the filenames (or portion
A **<geominfo>** element contains one or more geometry property and/or token definitions, and associates them and their values with all geometries listed in the `geom` or `collection` attribute of the <geominfo>:
-```
+```xml
...geometry property and token value definitions...
@@ -200,7 +200,7 @@ The core MaterialX Specification defines a Geometric Property, or "geomprop", as
MaterialX Geometry Extensions expands upons this by allowing the use of <geomprop> elements to define specific uniform values of a geometric property with specific geometries, as opposed to relying on those values being defined externally. This could include application-specific metadata, attributes passed from a lighting package to a renderer, or other geometry-specific data. A geomprop may also specify a `unittype` and `unit` if appropriate to indicate that the geometric property's value is in that unit; see the [**Units** section of the main MaterialX Specification](./MaterialX.Specification.md#units), although typically the <geompropdef> would define the `unittype` and `unit`, and a geomprop would only provide an overriding `unit` if the unit for its value differed from the geompropdef's defined default unit.
-```
+```xml
```
@@ -216,7 +216,7 @@ Only float and vectorN geometric properties may specify a `unittype` an
For example, one could specify a unique surface ID value associated with a geometry:
-```
+```xml
@@ -225,13 +225,13 @@ For example, one could specify a unique surface ID value associated with a geome
GeomProp values can be accessed from a nodegraph using a `` node:
-```
+```xml
```
A <geomprop> can also be used to define a default value for an intrinsic varying geometric property such as "geomcolor" for the geometry specified by the enclosing <geominfo>, which would be returned by the corresponding Geometric node (e.g. <geomcolor>) if the current geometry did not itself define values for that property.
-```
+```xml
@@ -243,7 +243,7 @@ A <geomprop> can also be used to define a default value for an intrinsic vary
Token elements may be used within <geominfo> elements to define constant (typically string or integer) named values associated with specific geometries. These geometry token values can be substituted into filenames within image nodes; see the [**Additional Filename Substitutions**](#additional-filename-substitutions) section above for details:
-```
+```xml
```
@@ -257,7 +257,7 @@ Token elements have the following attributes:
For example, one could specify a texture identifier value associated with a geometry:
-```
+```xml
@@ -265,7 +265,7 @@ For example, one could specify a texture identifier value associated with a geom
and then reference that token's value in a filename:
-```
+```xml
@@ -279,7 +279,7 @@ The <txtid> in the file name would be replaced by whatever value the txtid to
TokenDefault elements define the default value for a specified geometry token name; this default value will be used in a filename string substitution if an explicit token value is not defined for the current geometry. Since TokenDefault does not apply to any geometry in particular, it must be used outside of a <geominfo> element.
-```
+```xml
```
@@ -288,7 +288,7 @@ TokenDefault elements define the default value for a specified geometry token na
Workflows involving textures with implicitly-computed filenames based on u,v coordinates (such as <UDIM> and <UVTILE>) can be made more efficient by explicitly listing the set of values that they resolve to for any given geometry. The MaterialX specification reserves two geomprop names for this purpose, `udimset` and `uvtileset`, each of which is a stringarray containing a comma-separated list of UDIM or UVTILE values:
-```
+```xml
@@ -313,7 +313,7 @@ A MaterialX document can contain multiple property and/or look elements.
A **<property>** element defines the name, type and value of a look-specific non-material property of geometry; <**propertyset**> elements are used to group a number of <property>s into a single named object. The connection between properties or propertysets and specific geometries or collections is done in a <look> element, so that these properties can be reused across different geometries, and enabled in some looks but not others. <Property> elements may only be used within <propertyset>s; they may not be used independently, although a dedicated <propertyassign> element may be used within a <look> to declare a property name, type, value and assignment all at once.
-```
+```xml
@@ -338,7 +338,7 @@ In the example above, the "trace_maxdiffusedepth" property is target-specific, h
A **<look>** element contains one or more material, variant, visibility and/or propertyset assignment declarations:
-```
+```xml
...materialassign, variantassign, visibilityassign, property/propertysetassign declarations...
@@ -348,7 +348,7 @@ Looks can inherit the assignments from another look by including an `inherit` at
A number of looks can be grouped together into a **LookGroup**, e.g. to indicate which looks are defined for a particular asset:
-```
+```xml
```
@@ -368,7 +368,7 @@ For elements which make assignments to geometries, the pathed names within `geom
MaterialAssign elements are used within a <look> to connect a specified material to one or more geometries or collections (either a `geom` or a `collection` may be specified, but not both).
-```
+```xml
@@ -383,7 +383,7 @@ Material assignments are generally assumed to be mutually-exclusive, that is, an
VariantAssign elements are used within a <materialassign> or a <look> to apply the values defined in one variant of a variantset to one assigned material, or to all applicable materials in a look.
-```
+```xml
@@ -407,7 +407,7 @@ In the above example, the input/token values defined within variant "var1" will
Visibility elements are used within a <look> to define various types of generalized visibility between a "viewer" object and other geometries. A "viewer object" is simply a geometry that has the ability to "see" other geometries in some rendering context and thus may need to have the list of geometries that it "sees" in different contexts be specified; the most common examples are light sources and a primary rendering camera.
-```
+```xml
@@ -442,7 +442,7 @@ If the <visibility> `geom` or `collection` refers to light geometry, then ass
For the "secondary" vistype, `viewergeom` should be renderable geometry rather than a light, to declare that certain other geometry is or is not visible to indirect bounce illumination or raytraced reflections in that `viewergeom`. In this example, "/b" would not be seen in reflections nor contribute indirect bounce illumination to "/a", while geometry "/c" would not be visible to _any_ secondary rays:
-```
+```xml
```
@@ -452,7 +452,7 @@ For the "secondary" vistype, `viewergeom` should be renderable geometry rather t
PropertyAssign and PropertySetAssign elements are used within a <look> to connect a specified property value or propertyset to one or more geometries or collections.
-```
+```xml
@@ -467,7 +467,7 @@ Either a `geom` or a `collection` may be specified, but not both. Multiple prop
This example defines four collections, a light shader and material, and a propertyset, which are then used by two looks:
-```
+```xml
diff --git a/documents/Specification/MaterialX.Specification.md b/documents/Specification/MaterialX.Specification.md
index 7e876bdb57..4b99956fb4 100644
--- a/documents/Specification/MaterialX.Specification.md
+++ b/documents/Specification/MaterialX.Specification.md
@@ -267,7 +267,7 @@ Types not defined with a specific semantic are assumed to have semantic="default
Custom types are defined using the <typedef> element:
-```
+```xml
```
@@ -292,7 +292,7 @@ The standard MaterialX distribution includes definitions for four "shader"-seman
An MTLX file (with file extension ".mtlx") has the following general form:
-```
+```xml
@@ -303,7 +303,7 @@ That is, a standard XML declaration line followed by a root <materialx> eleme
Standard XML XIncludes are supported ([http://en/wikipedia.org/wiki/XInclude](http://en/wikipedia.org/wiki/Xinclude)), as well as standard XML comments and the XML character entities `"`, `&`, `'`, `<` and `>`:
-```
+```xml
@@ -345,7 +345,7 @@ The working color space of a MaterialX document is defined by the `colorspace` a
The color space of individual color image files and values may be defined via a `colorspace` attribute in an input which defines a filename or value. Color images and values in spaces other than the working color space are expected to be transformed by the application into the working space before computations are performed. In the example below, an image file has been defined in the “srgb_texture” color space, while its default value has been defined in “lin_rec709”; both should be transformed to the application’s working color space before being applied to any computations.
-```
+```xml
@@ -364,7 +364,7 @@ MaterialX allows floating-point and vector values to be defined in terms of a sp
Unit types are defined using a <unittypedef> element, and a set of units of that type is defined using a <unitdef> element with one or more child <unit> elements:
-```
+```xml
@@ -397,7 +397,7 @@ References to elements in a different namespace are qualified using the syntax "
Mtllib.mtlx contains the following (assuming that "..." contains any necessary material input connections and other element definitions):
-```
+```xml
...
@@ -412,7 +412,7 @@ Mtllib.mtlx contains the following (assuming that "..." contains any necessary m
Then another MaterialX file could reference these materials like this:
-```
+```xml
...
@@ -423,7 +423,7 @@ Then another MaterialX file could reference these materials like this:
Similarly, if a .mtlx file defining the "site_ops" namespace defined a custom color3-typed node "mynoise" with a single float input "f", it could be used in a node graph like this:
-```
+```xml
@@ -431,7 +431,7 @@ Similarly, if a .mtlx file defining the "site_ops" namespace defined a custom co
A `namespace` attribute may also be added to individual <nodedef>s or <nodegraph>s, in which case the `name` and `node` of a <nodedef>, or just the `name` of a <nodegraph> will be assigned to the specified `namespace`. In a <nodegraph>, the `nodedef` must include a namespace reference if the <nodedef> to which it refers is defined in a specific namespace, even if it's the same namespace as the <nodegraph>: this is because the `namespace` only applies to the content that is created by or contained within an element, not to anything external referenced by that element.
-```
+```xml
@@ -453,14 +453,14 @@ Geometric Properties, or "geomprops", are intrinsic or user-defined surface coor
One may also define custom geometric properties using a <geompropdef> element:
-```
+```xml
```
e.g.
-```
+```xml
```
@@ -469,13 +469,13 @@ The `type` of the geomprop may be any non-array MaterialX type, although `string
Once defined, a custom geomprop name may be used any place that a standard geomprop can:
-```
+```xml
```
A geompropdef may also specify a `unittype` and a `unit` to indicate that the geometric property is defined in terms of a specific unit. If a geomprop with a defined unit is accessed in a nodegraph using <geompropvalue>, the geometric property value will be converted from the unit specified by the geompropdef to the application-specified scene unit.
-```
+```xml
```
@@ -487,7 +487,7 @@ As a shorthand convenience, MaterialX allows the specification of a `fileprefix`
So the following snippets are equivalent:
-```
+```xml
@@ -538,7 +538,7 @@ Nodes are individual data generation or processing "blocks". Node functionality
Individual node elements have the form:
-```
+```xml
@@ -560,7 +560,7 @@ Node elements contain zero or more <input> elements defining the name, type,
A float/vectorN input of a node, or a "filename"-type input referring to an image file containing float or vectorN values, may specify a unit for its value by providing a `unit` attribute, and that unit must be one associated with the `unittype` for that input in the nodedef, if specified; please see the [Units](#units) section above for details on declaring units and unittypes. If the nodedef for a node (see the [Custom Nodes](#custom-nodes) section below) does not declare a `unittype` for an input, the node may do so; it is not permissible to provide a `unit` for a node input without a compatible `unittype` being defined on either the node or applicable nodedef.
-```
+```xml
@@ -570,7 +570,7 @@ Unless specified otherwise, all inputs default to a value of 0 in all channels f
A node input must generally be connected to outputs of the same type, but float inputs may also be connected to any single channel within a multi-channel data types by adding an integer "channel" attribute, indicating the channel number (0-3) to extract from the input:
-```
+```xml
@@ -593,7 +593,7 @@ Standard MaterialX nodes have exactly one output, while custom nodes may have an
A graph containing any number of nodes and output declarations forms a Node Graph, which may be enclosed within a <nodegraph> element to group them together into a single functional unit. Please see the [Custom Node Definition Using Node Graphs](#custom-node-definition-using-node-graphs) section below for details on how nodegraphs can be used to describe the functionality of new nodes.
-```
+```xml
...node element(s)...
...output element(s)...
@@ -606,7 +606,7 @@ A graph containing any number of nodes and output declarations forms a Node Grap
Output data streams are defined using **<output>** elements, and may be used to declare which output streams are connectable to other MaterialX elements. Within a node graph, an <output> element declares an output stream that may be connected to a shader input or to the input of a referencing node in another graph when the nodegraph is the implementation of a custom node. See the [Custom Node Definition Using Node Graphs](#custom-node-definition-using-node-graphs) section for details on the use of node graphs as node implementations.
-```
+```xml
@@ -640,7 +640,7 @@ This section defines the Source Nodes that all MaterialX implementations are exp
Texture nodes are used to read filtered image data from image or texture map files for processing within a node graph.
-```
+```xml
@@ -721,7 +721,7 @@ Arbitrary frame number expressions and speed changes are not supported.
Procedural nodes are used to generate value data programmatically.
-```
+```xml
@@ -900,7 +900,7 @@ To scale or offset the noise pattern generated by `noise3d`, `fractal3d` or `cel
Geometric nodes are used to reference local geometric properties from within a node graph:
-```
+```xml
@@ -982,7 +982,7 @@ Applications may also reference other renderer-specific named spaces, at the exp
Global nodes generate color data using non-local geometric context, requiring access to geometric features beyond the surface point being processed. This non-local context can be provided by tracing rays into the scene, rasterizing scene geometry, or any other appropriate method.
-```
+```xml
@@ -1002,7 +1002,7 @@ Standard Global nodes:
Application nodes are used to reference application-defined properties within a node graph, and have no inputs:
-```
+```xml
```
@@ -1028,7 +1028,7 @@ Standard Application nodes:
Operator nodes process one or more required input streams to form an output. Like other nodes, each operator must define its output type, which in most cases also determines the type(s) of the required input streams.
-```
+```xml
@@ -1786,7 +1786,7 @@ A simple merge of two single-layer images with a separate mask image, followed b
![Nodegraph Example 1](media/nodegraph1.png "Nodegraph Example 1")
-```
+```xml
@@ -1818,7 +1818,7 @@ A more complex nodegraph using geometry properties to define two diffuse albedo
![Nodegraph Example 2](media/nodegraph2.png "Nodegraph Example 2")
-```
+```xml
@@ -1885,7 +1885,7 @@ MaterialX supports the definition of nodes, attributes and inputs that are speci
Targets are declared using a <targetdef> element:
-```
+```xml
@@ -1893,7 +1893,7 @@ Targets are declared using a <targetdef> element:
A target may inherit from another target, so that any reference to a parent target will automatically include any definitions specific to the inherited child target that do not have a definition for the parent target itself:
-```
+```xml
@@ -1913,14 +1913,14 @@ While the MaterialX specification describes the attributes and elements that are
If an application requires additional information related to any MaterialX element, it may define and utilize additional attributes with non-standard names. Custom attributes are defined using <attributedef> elements:
-```
+```xml
```
where _name_ is a unique name for the attributedef, _attrname_ is the name of the custom attribute to define, _type_ is the type of the attribute (typically string, stringarray, integer or boolean, although any MaterialX type is allowed), _defaultvalue_ is the default value for the attribute, _target_ is an optional list of targets to which this attribute applies, and _elements_ is an optional list of element names or elementname/inputname in which the attribute may be used. It is also permissible to provide enum and enumvalues attributes for an attributedef, to define specific labels and values that the custom attribute is allowed to take, using the same syntax and limitations as enum/enumvalues on nodedef inputs and tokens (see below). By default, a custom attribute is not emitted as metadata in generated shaders, but can be exported if the `exportable` attribute is set to "true". Examples:
-```
+```xml
@@ -1948,7 +1948,7 @@ Once defined, custom attributes may be used in exactly the same manner as standa
If an application requires additional custom inputs within a standard MaterialX node, it may define a target application-specific <nodedef> for that node inheriting the base input definitions from the standard node's <nodedef>, then add inputs specific to that target application.
-```
+```xml
@@ -1958,7 +1958,7 @@ In the above example, a Maya-specific version of the color4-type <image> node
When using a node, the definition appropriate for the current target will automatically be used, and other targets will ignore any inputs that are not part of the nodedef for that target. However, one may specify a documentational `target` attribute on an input to hint what target it is intended for if desired. In this example, the "preFilter" input has indicated that it is specific to the "maya" target.
-```
+```xml
@@ -1998,7 +1998,7 @@ NodeDefs must define one or more child <output> elements within the <noded
The parameter interface of a custom node is specified via a set of child <input> and <token> elements of the <nodedef>, while documentation of the folder structure of a node may be defined using a number of <uifolder> elements, each of which may provide a doc attribute to provide documentation for that folder layer. A <uifolder> element may not contain any other elements; in particular, the <input>s and <token>s of the nodedef interface must be direct children of the <nodedef>. Nested folders may be indicated using a full path for the folder, with a "/" separator between folder levels.
-```
+```xml
@@ -2012,7 +2012,7 @@ The parameter interface of a custom node is specified via a set of child <inp
**Input** elements are used within a <nodedef> to declare the spatially-varying and uniform inputs for a node:
-```
+```xml
```
@@ -2047,7 +2047,7 @@ It is permissible to define a `value` or a `defaultgeomprop` for an input but no
**Token** elements are used within a <nodedef> to declare uniform "interface token" string-substitution values to be referenced and substituted within filenames used in a node's nodegraph implementation:
-```
+```xml
```
@@ -2068,7 +2068,7 @@ Please see the [Example Pre-Shader Compositing Material](#example-pre-shader-com
**Output** elements are used within a <nodedef> to declare an output for node definitions, including the output's name, type, and default value or "defaultinput" connection:
-```
+```xml
```
@@ -2103,7 +2103,7 @@ An <implementation> may define a `file` or `sourcecode` attribute, or neither
Because the names used for node inputs (such as "normal" or "default") may conflict with the reserved words in various shading languages, or may simply be different for specific targets, <implementation> elements may contain a number of <input> elements to remap the `name`s of <input>s as specified in the <nodedef> to different `implname`s to indicate what the input name is actually called in the implementation's code. Only the inputs that need to be remapped to new `implname`s need to be listed; for each, it is recommended that the `type` of that input be listed for clarity, but if specified, it must match the type specified in the <nodedef>: <implementation>s are not allowed to change the type or any other attribute defined in the <nodedef>. In this example, the <implementation> declares that the "default" input defined in the "ND_image_color3" nodedef is actually called "default_value" in the "mx_image_color" function:
-```
+```xml
@@ -2112,7 +2112,7 @@ Because the names used for node inputs (such as "normal" or "default") may confl
For uniform inputs and tokens whose nodedef description includes an enum list of allowable values, individual implementations may associate different target-specific resolved values for them potentially of a different type; these may be described by providing an `enumvalues` attribute on the uniform input or token within an <implementation> and if appropriate, an `impltype` to declare the target-specific type of these enumvalues. Note that if the type of an enum input in the nodedef is an array type, then the `impltype` (if specified) must also be an array type, while `enumvalues` is a list of values of the base (non-array) type. The following <implementation> states that for the "mystudio" target, the uaddressmode and vaddressmode inputs of the "image" node are actually called "extrapolate_u" and "extrapolate_v", are integers rather than strings, and take different values (e.g. "clamp" is 2):
-```
+```xml
element with a file attribute defining an external compiled implementation of a surface shader may contain one or more <aov> elements to declare the names and types of arbitrary output variables ("AOVs") which the shader can output to the renderer. AOVs must be of type float, color3, vector3, BSDF or EDF. Note that in MaterialX, AOVs for pre-shading "pattern" colors are normally of type color3, while post-shaded color-like values are normally of type BSDF and emissive color-like values are normally of type EDF. An <implementation> with a `nodegraph` attribute may not contain <aov> elements; instead, <aovoutput> elements within the nodegraph should be used.
-```
+```xml
@@ -2139,7 +2139,7 @@ An <implementation> element with a file attribute defining an external compil
#### Example Custom Nodes Defined by External File Implementations
-```
+```xml
@@ -2179,7 +2179,7 @@ This example defines two templates for a custom operator node called "mariBlend"
Here is an example of a two-output node definition and external implementation declaration.
-```
+```xml
@@ -2203,7 +2203,7 @@ A **<nodegraph>** element consists of at least one node element and at least
A **functional nodegraph** is a nodegraph-based implementation for a specified <nodedef>, with the <nodedef> declaring the set of inputs that the nodegraph accepts: a functional nodegraph may not itself specify any direct child input elements.
-```
+```xml
...node element(s)...
...output element(s)...
@@ -2212,7 +2212,7 @@ A **functional nodegraph** is a nodegraph-based implementation for a specified &
or
-```
+```xml
...node element(s)...
...output element(s)...
@@ -2223,7 +2223,7 @@ or
The type(s) of the <output>(s) of the <nodedef> and the type(s) of the nodegraph <output>(s) must agree, and if there are multiple outputs, then the `name`s of the <output>s in the <nodegraph> and <nodedef> must also agree. The inputs and tokens of the <nodedef> can be referenced within <input> and <token> elements of nodes within the nodegraph implementation using `interfacename` attributes in place of `value` or `nodename` attributes, e.g. a nodedef input "i2" and interface token "diffmap" could be referenced as follows:
-```
+```xml
```
@@ -2235,7 +2235,7 @@ Note that a uniform <input> of a node within the nodegraph may use `interface
A **compound <nodegraph>** element may specify one or more child <input> and/or <token> elements. In this case, the <nodegraph> functions as a collapsible "wrapper" for the contained nodes.
-```
+```xml
[...input and/or token element(s)...]
...node and/or (compound) nodegraph element(s)...
@@ -2250,7 +2250,7 @@ It is permissible to define multiple nodegraph- and/or file-based implementation
#### Example Custom Node Defined by a Nodegraph
-```
+```xml
@@ -2277,7 +2277,7 @@ The inputs of the nodegraph are declared by the <nodedef>, and the nodes with
Once defined with a <nodedef>, using a custom node within a node graph follows the same syntax as any other standard node: the name of the element is the name of the custom node, and the MaterialX type of the node's output is required; the custom node's child elements define connections of inputs to other node outputs as well as any input values for the custom node.
-```
+```xml
@@ -2292,7 +2292,7 @@ Once defined with a <nodedef>, using a custom node within a node graph follow
When invoking nodes with multiple outputs, the `type` of the node should be declared as "multioutput", and other node inputs connecting to an output of the node must include an `output` attribute to specify which output of the node to connect to:
-```
+```xml
@@ -2313,7 +2313,7 @@ When invoking nodes with multiple outputs, the `type` of the node should be decl
Custom nodes that output data types with a "shader" semantic are referred to in MaterialX as "Shader Nodes". Shaders, along with their inputs, are declared using the same <nodedef>, <implementation> and <nodegraph> elements described above:
-```
+```xml
...input declarations...
@@ -2331,7 +2331,7 @@ NodeDef elements defining shader nodes do not typically include `default` or `de
As mentioned in the [Custom Data Types](#custom-data-types) section earlier, the standard MaterialX distribution includes the following standard data types for shaders:
-```
+```xml
@@ -2342,7 +2342,7 @@ These types all declare that they have "shader" semantic, but define different c
Instantiation of shader nodes to give them specific values is done the same way as instantiating any other node type:
-```
+```xml
@@ -2352,7 +2352,7 @@ Instantiation of shader nodes to give them specific values is done the same way
Instantiated shader nodes can also inherit from other shader nodes of the same class:
-```
+```xml
@@ -2398,7 +2398,7 @@ The Standard MaterialX Library defines the following nodes and node variants ope
A functional nodegraph with either a "shader" or "material"-semantic output type may contain a number of <aovoutput> elements to declare arbitrary output variables ("AOVs") which the renderer can see and output as additional streams of information. AOVoutputs must be of type float, color3 or vector3 for pre-shading "pattern" values, or BSDF or EDF for shader-node output values; the renderer is expected to extract the appropriate color-like information from BSDF and EDF types. AOVs defined within a shader-semantic node instantiated within this functional nodegraph may be "passed along" and potentially renamed (but may not be modified or operated on in any way) by providing a sourceaov attribute in the <aovoutput>.
-```
+```xml
```
@@ -2413,7 +2413,7 @@ The attributes for <aovoutput> elements are:
Examples:
-```
+```xml
@@ -2424,7 +2424,7 @@ Examples:
Example of using <aovoutput> with sourceaov to forward AOVs from within an instantiation of a shader-semantic node; this assumes that <standard_surface> has itself defined <aovoutput>s for "diffuse" and "specular" AOVs:
-```
+```xml
s for geometric
Custom nodes that output data types with a "material" semantic are referred to in MaterialX as "Material Nodes". Material nodes typically have one or more "shader" semantic inputs which establish what shaders the material references; previous versions of MaterialX used <shaderref> elements to establish these shader-to-material connections. Material Nodes are declared using the same <nodedef> elements as described above:
-```
+```xml
...additional shader or input declarations...
@@ -2476,7 +2476,7 @@ The attributes for <nodedef> elements as they pertain to the declaration of m
The standard MaterialX distribution includes a single material type definition used as the output type for all material nodes:
-```
+```xml
```
@@ -2501,7 +2501,7 @@ as well as definitions for three standard material nodes, all outputting type "m
Material nodes supporting multiple shaders of the same type for different rendering targets can be defined:
-```
+```xml
@@ -2514,7 +2514,7 @@ Material nodes supporting multiple shaders of the same type for different render
Creating materials with specific values bound to shader inputs involves instantiating a Shader Node for each desired shader type and setting values on those shader nodes, and connecting the shader node(s) to the inputs of a Material Node:
-```
+```xml
@@ -2535,7 +2535,7 @@ Alternatively, and perhaps more usefully, a complete network of multiple shader
Materials can inherit from other materials, to add or change shaders connected to different inputs; in this example, a displacement shader is added to the above "Mgold" material to create a new "Mgolddsp" material:
-```
+```xml
@@ -2555,7 +2555,7 @@ Inheritance of material-type custom nodes is also allowed, so that new or change
A material to blend between three different surface layers using mask textures. This example also demonstrates the use of the "target" attribute of a shader implementation element to define multiple renderer-specific shaders of the same type referenced within a single material, and the use of interface tokens to define texture filenames.
-```
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_25.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_25.mtlx
new file mode 100644
index 0000000000..df723e7054
--- /dev/null
+++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_25.mtlx
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/Materials/TestSuite/stdlib/upgrade/1_36_to_1_37.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_36.mtlx
similarity index 99%
rename from resources/Materials/TestSuite/stdlib/upgrade/1_36_to_1_37.mtlx
rename to resources/Materials/TestSuite/stdlib/upgrade/syntax_1_36.mtlx
index 84db1c6101..08a049435f 100644
--- a/resources/Materials/TestSuite/stdlib/upgrade/1_36_to_1_37.mtlx
+++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_36.mtlx
@@ -1,9 +1,7 @@
diff --git a/resources/Materials/TestSuite/stdlib/upgrade/1_37_to_1_38.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx
similarity index 62%
rename from resources/Materials/TestSuite/stdlib/upgrade/1_37_to_1_38.mtlx
rename to resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx
index 28b9ae8ad2..3cb8eb6237 100644
--- a/resources/Materials/TestSuite/stdlib/upgrade/1_37_to_1_38.mtlx
+++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx
@@ -1,5 +1,9 @@
-
+
+
+
@@ -37,4 +41,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp
index 4ba48cc84b..0449189873 100644
--- a/source/MaterialXCore/Document.cpp
+++ b/source/MaterialXCore/Document.cpp
@@ -492,12 +492,10 @@ void Document::upgradeVersion()
if (nodeDef->hasAttribute("shadertype"))
{
nodeDef->setType(SURFACE_SHADER_TYPE_STRING);
- nodeDef->removeAttribute("shadertype");
}
if (nodeDef->hasAttribute("shaderprogram"))
{
nodeDef->setNodeString(nodeDef->getAttribute("shaderprogram"));
- nodeDef->removeAttribute("shaderprogram");
}
}
else if (child->getCategory() == "shaderref")
@@ -751,8 +749,18 @@ void Document::upgradeVersion()
// Remove legacy shader nodedefs.
for (NodeDefPtr nodeDef : getNodeDefs())
{
- if (nodeDef->getType() == "surface")
+ if (nodeDef->hasAttribute("shadertype"))
{
+ for (ElementPtr mat : getChildrenOfType("material"))
+ {
+ for (ElementPtr shaderRef : mat->getChildrenOfType("shaderref"))
+ {
+ if (shaderRef->getAttribute(InterfaceElement::NODE_DEF_ATTRIBUTE) == nodeDef->getName())
+ {
+ shaderRef->removeAttribute(InterfaceElement::NODE_DEF_ATTRIBUTE);
+ }
+ }
+ }
removeNodeDef(nodeDef->getName());
}
}
diff --git a/source/MaterialXGraphEditor/RenderView.cpp b/source/MaterialXGraphEditor/RenderView.cpp
index 176014ba65..d2967e6b85 100644
--- a/source/MaterialXGraphEditor/RenderView.cpp
+++ b/source/MaterialXGraphEditor/RenderView.cpp
@@ -82,26 +82,6 @@ void applyModifiers(mx::DocumentPtr doc, const DocumentModifiers& modifiers)
}
}
- // Remap references to unimplemented shader nodedefs.
- for (mx::NodePtr materialNode : doc->getMaterialNodes())
- {
- for (mx::NodePtr shader : getShaderNodes(materialNode))
- {
- mx::NodeDefPtr nodeDef = shader->getNodeDef();
- if (nodeDef && !nodeDef->getImplementation())
- {
- std::vector altNodeDefs = doc->getMatchingNodeDefs(nodeDef->getNodeString());
- for (mx::NodeDefPtr altNodeDef : altNodeDefs)
- {
- if (altNodeDef->getImplementation())
- {
- shader->setNodeDefString(altNodeDef->getName());
- }
- }
- }
- }
- }
-
// Remap unsupported texture coordinate indices.
for (mx::ElementPtr elem : doc->traverseTree())
{
diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp
index 29092071cf..af39035dbe 100644
--- a/source/MaterialXTest/MaterialXCore/Document.cpp
+++ b/source/MaterialXTest/MaterialXCore/Document.cpp
@@ -108,108 +108,3 @@ TEST_CASE("Document", "[document]")
// Validate the combined document.
REQUIRE(doc->validate());
}
-
-TEST_CASE("Version", "[document]")
-{
- mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath();
- mx::DocumentPtr stdlib = mx::createDocument();
- mx::loadLibraries({ "libraries" }, searchPath, stdlib);
- searchPath.append(searchPath.find("resources/Materials/TestSuite/stdlib/upgrade"));
-
- // 1.36 to 1.37
- {
- mx::DocumentPtr doc = mx::createDocument();
- mx::readFromXmlFile(doc, "1_36_to_1_37.mtlx", searchPath);
- doc->importLibrary(stdlib);
- REQUIRE(doc->validate());
-
- mx::XmlWriteOptions writeOptions;
- writeOptions.writeXIncludeEnable = true;
- std::string xmlString = mx::writeToXmlString(doc, &writeOptions);
-
- mx::DocumentPtr doc2 = mx::createDocument();
- mx::readFromXmlString(doc2, xmlString);
- REQUIRE(doc2->validate());
-
- // Check conversion to desired types occurred
- std::unordered_map convertSet =
- {
- { "invertmatrix", 2},
- { "rotate2d", 1},
- { "rotate3d", 1},
- { "transformmatrix", 7},
- { "ifgreatereq", 7},
- { "separate2", 1},
- { "separate3", 1},
- { "separate4", 1},
- { "combine2", 1},
- { "combine3", 1},
- { "combine4", 1}
- };
- for (mx::NodePtr node : doc2->getNodes())
- {
- auto convertItem = convertSet.find(node->getCategory());
- if (convertItem != convertSet.end())
- {
- convertItem->second--;
- }
- }
- for (auto convertItem : convertSet)
- {
- REQUIRE((convertItem.second == 0));
- }
- }
-
- // 1.37 to 1.38
- {
- mx::DocumentPtr doc = mx::createDocument();
- mx::readFromXmlFile(doc, "1_37_to_1_38.mtlx", searchPath);
- doc->importLibrary(stdlib);
- REQUIRE(doc->validate());
-
- mx::XmlWriteOptions writeOptions;
- writeOptions.writeXIncludeEnable = false;
- std::string xmlString = mx::writeToXmlString(doc, &writeOptions);
-
- mx::DocumentPtr doc2 = mx::createDocument();
- mx::readFromXmlString(doc2, xmlString);
- REQUIRE(doc2->validate());
-
- // atan2 test
- const std::string ATAN2 = "atan2";
- mx::StringMap ATAN2_MAP;
- ATAN2_MAP["in1"] = "in2";
- ATAN2_MAP["in2"] = "in1";
-
- for (mx::ElementPtr elem : doc->traverseTree())
- {
- mx::NodePtr node = elem->asA();
- if (!node)
- {
- continue;
- }
- const std::string& nodeCategory = node->getCategory();
- if (nodeCategory == ATAN2)
- {
- const std::string &nodePath = node->getNamePath();
- for (auto in : ATAN2_MAP)
- {
- mx::ElementPtr input = node->getChild(in.first);
- if (input)
- {
- mx::ElementPtr newNode = doc2->getDescendant(nodePath);
- REQUIRE((newNode && newNode->getChild(in.second)));
- }
- }
- }
- }
-
- mx::NodeGraphPtr testNodeGraph = doc2->getNodeGraph("NG_Test");
- REQUIRE(!testNodeGraph->getNode("add"));
- REQUIRE(testNodeGraph->getNode("add1"));
- REQUIRE(testNodeGraph->getNode("add2"));
- REQUIRE(testNodeGraph->getNode("add2")->getInput("in1")->getInterfaceName() == "add");
- REQUIRE(testNodeGraph->getNode("add1")->getInput("in1")->getNodeName() == "add2");
- }
-}
-
diff --git a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp
index af392a9a05..0460f9282a 100644
--- a/source/MaterialXTest/MaterialXRender/RenderUtil.cpp
+++ b/source/MaterialXTest/MaterialXRender/RenderUtil.cpp
@@ -76,19 +76,6 @@ void ShaderRenderTester::loadDependentLibraries(GenShaderUtil::TestSuiteOptions
loadAdditionalLibraries(dependLib, options);
}
-void ShaderRenderTester::addSkipFiles()
-{
- _skipFiles.insert("_options.mtlx");
- _skipFiles.insert("light_rig_test_1.mtlx");
- _skipFiles.insert("light_rig_test_2.mtlx");
- _skipFiles.insert("light_compound_test.mtlx");
- _skipFiles.insert("xinclude_search_path.mtlx");
- _skipFiles.insert("1_38_parameter_to_input.mtlx");
- _skipFiles.insert("1_36_to_1_37.mtlx");
- _skipFiles.insert("1_37_to_1_38.mtlx");
- _skipFiles.insert("material_element_to_surface_material.mtlx");
-}
-
bool ShaderRenderTester::validate(const mx::FilePath optionsFilePath)
{
#ifdef LOG_TO_FILE
@@ -144,9 +131,6 @@ bool ShaderRenderTester::validate(const mx::FilePath optionsFilePath)
}
ioTimer.endTimer();
- // Add files to skip
- addSkipFiles();
-
// Load in the library dependencies once
// This will be imported in each test document below
ioTimer.startTimer();
@@ -215,11 +199,6 @@ bool ShaderRenderTester::validate(const mx::FilePath optionsFilePath)
for (const mx::FilePath& file : files)
{
- if (_skipFiles.count(file))
- {
- continue;
- }
-
ioTimer.startTimer();
// Check if a file override set is used and ignore all files
// not part of the override set
diff --git a/source/MaterialXTest/MaterialXRender/RenderUtil.h b/source/MaterialXTest/MaterialXRender/RenderUtil.h
index 9f892569de..b29145dcb1 100644
--- a/source/MaterialXTest/MaterialXRender/RenderUtil.h
+++ b/source/MaterialXTest/MaterialXRender/RenderUtil.h
@@ -114,9 +114,6 @@ class ShaderRenderTester
}
#endif
- // Add files to skip
- void addSkipFiles();
-
// Load dependencies
void loadDependentLibraries(GenShaderUtil::TestSuiteOptions options, mx::FileSearchPath searchPath,
mx::DocumentPtr& dependLib);
@@ -181,9 +178,6 @@ class ShaderRenderTester
bool _resolveImageFilenames;
mx::StringResolverPtr _customFilenameResolver;
- // Files to skip
- mx::StringSet _skipFiles;
-
// Color management information
mx::ColorManagementSystemPtr _colorManagementSystem;
mx::FilePath _colorManagementConfigFile;
diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp
index 6346658d07..560a19e778 100644
--- a/source/MaterialXView/Viewer.cpp
+++ b/source/MaterialXView/Viewer.cpp
@@ -121,26 +121,6 @@ void applyModifiers(mx::DocumentPtr doc, const DocumentModifiers& modifiers)
}
}
- // Remap references to unimplemented shader nodedefs.
- for (mx::NodePtr materialNode : doc->getMaterialNodes())
- {
- for (mx::NodePtr shader : getShaderNodes(materialNode))
- {
- mx::NodeDefPtr nodeDef = shader->getNodeDef();
- if (nodeDef && !nodeDef->getImplementation())
- {
- std::vector altNodeDefs = doc->getMatchingNodeDefs(nodeDef->getNodeString());
- for (mx::NodeDefPtr altNodeDef : altNodeDefs)
- {
- if (altNodeDef->getImplementation())
- {
- shader->setNodeDefString(altNodeDef->getName());
- }
- }
- }
- }
- }
-
// Remap unsupported texture coordinate indices.
for (mx::ElementPtr elem : doc->traverseTree())
{
From 85dc5e1ea3239de507af07143224fd1c7852ee75 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Sat, 7 Oct 2023 09:59:34 -0700
Subject: [PATCH 55/69] Improvements to 1.37 upgrade (#1555)
- Add an example shading model graph using MaterialX 1.37 syntax, allowing improved coverage of version upgrade logic in unit tests.
- Simplify the logic for 1.37 upgrades in Document::upgradeVersion, removing legacy code that was dedicated to upgrading the MaterialX standard libraries.
---
.../TestSuite/stdlib/upgrade/syntax_1_37.mtlx | 151 ++++++++++------
source/MaterialXCore/Document.cpp | 166 +++++-------------
2 files changed, 144 insertions(+), 173 deletions(-)
diff --git a/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx
index 3cb8eb6237..66dc69f668 100644
--- a/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx
+++ b/resources/Materials/TestSuite/stdlib/upgrade/syntax_1_37.mtlx
@@ -4,61 +4,110 @@
Examples of MaterialX 1.37 syntax
-->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp
index 0449189873..80143bb9c8 100644
--- a/source/MaterialXCore/Document.cpp
+++ b/source/MaterialXCore/Document.cpp
@@ -1040,39 +1040,7 @@ void Document::upgradeVersion()
}
}
- // Update atan2 interface and rotate3d interface
- const string ATAN2 = "atan2";
- const string IN1 = "in1";
- const string IN2 = "in2";
- const string ROTATE3D = "rotate3d";
- const string AXIS = "axis";
- const string INPUT_ONE = "1.0";
-
- // Update nodedefs
- bool upgradeAtan2Instances = false;
- for (auto nodedef : getMatchingNodeDefs(ATAN2))
- {
- InputPtr input = nodedef->getInput(IN1);
- InputPtr input2 = nodedef->getInput(IN2);
- string inputValue = input->getValueString();
- // Only flip value if nodedef value is the previous versions.
- if (inputValue == INPUT_ONE)
- {
- input->setValueString(input2->getValueString());
- input2->setValueString(inputValue);
- upgradeAtan2Instances = true;
- }
- }
- for (auto nodedef : getMatchingNodeDefs(ROTATE3D))
- {
- ElementPtr axis = nodedef->getChild(AXIS);
- if (axis)
- {
- nodedef->changeChildCategory(axis, "input");
- }
- }
-
- // Update BSDF interfaces
+ // Define BSDF node pairs.
using StringPair = std::pair;
const StringPair DIELECTRIC_BRDF = { "dielectric_brdf", "dielectric_bsdf" };
const StringPair DIELECTRIC_BTDF = { "dielectric_btdf", "dielectric_bsdf" };
@@ -1085,57 +1053,11 @@ void Document::upgradeVersion()
const StringPair SUBSURFACE_BRDF = { "subsurface_brdf", "subsurface_bsdf" };
const StringPair THIN_FILM_BRDF = { "thin_film_brdf", "thin_film_bsdf" };
- const string SCATTER_MODE = "scatter_mode";
- const string BSDF = "BSDF";
- const string LAYER = "layer";
- const string TOP = "top";
- const string BASE = "base";
- const string INTERIOR = "interior";
- const string ARTISTIC_IOR = "artistic_ior";
- const string COMPLEX_IOR = "complex_ior";
- const string REFLECTIVITY = "reflectivity";
- const string EDGE_COLOR = "edge_color";
- const string IOR = "ior";
- const string EXTINCTION = "extinction";
- const string COLOR3 = "color3";
- const string VECTOR3 = "vector3";
- const string CONVERT = "convert";
- const string IN = "in";
-
- // Function for upgrading BSDF nodedef.
- auto upgradeBsdfNodeDef = [SCATTER_MODE](NodeDefPtr nodedef, const string& newCategory, bool addScatterMode = false)
- {
- if (nodedef)
- {
- nodedef->setName(newCategory);
- if (addScatterMode)
- {
- InputPtr mode = nodedef->addInput(SCATTER_MODE, STRING_TYPE_STRING);
- mode->setIsUniform(true);
- mode->setValueString("R");
- mode->setAttribute("enum", "R,T,RT");
- }
- }
- };
-
- // Update nodedefs.
- upgradeBsdfNodeDef(getNodeDef(DIELECTRIC_BRDF.first), DIELECTRIC_BRDF.second, true);
- upgradeBsdfNodeDef(getNodeDef(GENERALIZED_SCHLICK_BRDF.first), GENERALIZED_SCHLICK_BRDF.second, true);
- upgradeBsdfNodeDef(getNodeDef(CONDUCTOR_BRDF.first), CONDUCTOR_BRDF.second);
- upgradeBsdfNodeDef(getNodeDef(SHEEN_BRDF.first), SHEEN_BRDF.second);
- upgradeBsdfNodeDef(getNodeDef(DIFFUSE_BRDF.first), DIFFUSE_BRDF.second);
- upgradeBsdfNodeDef(getNodeDef(BURLEY_DIFFUSE_BRDF.first), BURLEY_DIFFUSE_BRDF.second);
- upgradeBsdfNodeDef(getNodeDef(DIFFUSE_BTDF.first), DIFFUSE_BTDF.second);
- upgradeBsdfNodeDef(getNodeDef(SUBSURFACE_BRDF.first), SUBSURFACE_BRDF.second);
- upgradeBsdfNodeDef(getNodeDef(THIN_FILM_BRDF.first), THIN_FILM_BRDF.second);
- removeNodeDef(DIELECTRIC_BTDF.first);
- removeNodeDef(COMPLEX_IOR);
-
// Function for upgrading old nested layering setup
// to new setup with layer operators.
- auto upgradeBsdfLayering = [TOP, BASE, LAYER, BSDF](NodePtr node)
+ auto upgradeBsdfLayering = [](NodePtr node)
{
- InputPtr base = node->getInput(BASE);
+ InputPtr base = node->getInput("base");
if (base)
{
NodePtr baseNode = base->getConnectedNode();
@@ -1146,13 +1068,13 @@ void Document::upgradeVersion()
// so we don't need to update any connection references.
const string oldName = node->getName();
node->setName(oldName + "__layer_top");
- NodePtr layer = parent->addNode(LAYER, oldName, BSDF);
- InputPtr layerTop = layer->addInput(TOP, BSDF);
- InputPtr layerBase = layer->addInput(BASE, BSDF);
+ NodePtr layer = parent->addNode("layer", oldName, "BSDF");
+ InputPtr layerTop = layer->addInput("top", "BSDF");
+ InputPtr layerBase = layer->addInput("base", "BSDF");
layerTop->setConnectedNode(node);
layerBase->setConnectedNode(baseNode);
}
- node->removeInput(BASE);
+ node->removeInput("base");
}
};
@@ -1177,31 +1099,31 @@ void Document::upgradeVersion()
continue;
}
const string& nodeCategory = node->getCategory();
- if (upgradeAtan2Instances && nodeCategory == ATAN2)
+ if (nodeCategory == "atan2")
{
- InputPtr input = node->getInput(IN1);
- InputPtr input2 = node->getInput(IN2);
+ InputPtr input = node->getInput("in1");
+ InputPtr input2 = node->getInput("in2");
if (input && input2)
{
input->setName(EMPTY_STRING);
- input2->setName(IN1);
- input->setName(IN2);
+ input2->setName("in1");
+ input->setName("in2");
}
else
{
if (input)
{
- input->setName(IN2);
+ input->setName("in2");
}
if (input2)
{
- input2->setName(IN1);
+ input2->setName("in1");
}
}
}
- else if (nodeCategory == ROTATE3D)
+ else if (nodeCategory == "rotate3d")
{
- ElementPtr axis = node->getChild(AXIS);
+ ElementPtr axis = node->getChild("axis");
if (axis)
{
node->changeChildCategory(axis, "input");
@@ -1215,8 +1137,8 @@ void Document::upgradeVersion()
else if (nodeCategory == DIELECTRIC_BTDF.first)
{
node->setCategory(DIELECTRIC_BTDF.second);
- node->removeInput(INTERIOR);
- InputPtr mode = node->addInput(SCATTER_MODE, STRING_TYPE_STRING);
+ node->removeInput("interior");
+ InputPtr mode = node->addInput("scatter_mode", STRING_TYPE_STRING);
mode->setValueString("T");
}
else if (nodeCategory == GENERALIZED_SCHLICK_BRDF.first)
@@ -1240,32 +1162,32 @@ void Document::upgradeVersion()
// Create an artistic_ior node to convert from artistic to physical parameterization.
GraphElementPtr parent = node->getParent()->asA();
- NodePtr artisticIor = parent->addNode(ARTISTIC_IOR, node->getName() + "__artistic_ior", "multioutput");
- OutputPtr artisticIor_ior = artisticIor->addOutput(IOR, COLOR3);
- OutputPtr artisticIor_extinction = artisticIor->addOutput(EXTINCTION, COLOR3);
+ NodePtr artisticIor = parent->addNode("artistic_ior", node->getName() + "__artistic_ior", "multioutput");
+ OutputPtr artisticIor_ior = artisticIor->addOutput("ior", "color3");
+ OutputPtr artisticIor_extinction = artisticIor->addOutput("extinction", "color3");
// Copy values and connections from conductor node to artistic_ior node.
- InputPtr reflectivity = node->getInput(REFLECTIVITY);
+ InputPtr reflectivity = node->getInput("reflectivity");
if (reflectivity)
{
- InputPtr artisticIor_reflectivity = artisticIor->addInput(REFLECTIVITY, COLOR3);
+ InputPtr artisticIor_reflectivity = artisticIor->addInput("reflectivity", "color3");
copyAttributes(reflectivity, artisticIor_reflectivity);
}
- InputPtr edge_color = node->getInput(EDGE_COLOR);
+ InputPtr edge_color = node->getInput("edge_color");
if (edge_color)
{
- InputPtr artisticIor_edge_color = artisticIor->addInput(EDGE_COLOR, COLOR3);
+ InputPtr artisticIor_edge_color = artisticIor->addInput("edge_color", "color3");
copyAttributes(edge_color, artisticIor_edge_color);
}
// Update the parameterization on the conductor node
// and connect it to the artistic_ior node.
- node->removeInput(REFLECTIVITY);
- node->removeInput(EDGE_COLOR);
- InputPtr ior = node->addInput(IOR, COLOR3);
+ node->removeInput("reflectivity");
+ node->removeInput("edge_color");
+ InputPtr ior = node->addInput("ior", "color3");
ior->setNodeName(artisticIor->getName());
ior->setOutputString(artisticIor_ior->getName());
- InputPtr extinction = node->addInput(EXTINCTION, COLOR3);
+ InputPtr extinction = node->addInput("extinction", "color3");
extinction->setNodeName(artisticIor->getName());
extinction->setOutputString(artisticIor_extinction->getName());
}
@@ -1285,17 +1207,17 @@ void Document::upgradeVersion()
{
node->setCategory(SUBSURFACE_BRDF.second);
}
- else if (nodeCategory == ARTISTIC_IOR)
+ else if (nodeCategory == "artistic_ior")
{
- OutputPtr ior = node->getOutput(IOR);
+ OutputPtr ior = node->getOutput("ior");
if (ior)
{
- ior->setType(COLOR3);
+ ior->setType("color3");
}
- OutputPtr extinction = node->getOutput(EXTINCTION);
+ OutputPtr extinction = node->getOutput("extinction");
if (extinction)
{
- extinction->setType(COLOR3);
+ extinction->setType("color3");
}
}
@@ -1306,18 +1228,18 @@ void Document::upgradeVersion()
// since we can't modify the graph while traversing it.
for (InputPtr input : node->getInputs())
{
- if (input->getOutputString() == IOR && input->getType() == VECTOR3)
+ if (input->getOutputString() == "ior" && input->getType() == "vector3")
{
NodePtr connectedNode = input->getConnectedNode();
- if (connectedNode && connectedNode->getCategory() == ARTISTIC_IOR)
+ if (connectedNode && connectedNode->getCategory() == "artistic_ior")
{
artisticIorConnections.push_back(input);
}
}
- else if (input->getOutputString() == EXTINCTION && input->getType() == VECTOR3)
+ else if (input->getOutputString() == "extinction" && input->getType() == "vector3")
{
NodePtr connectedNode = input->getConnectedNode();
- if (connectedNode && connectedNode->getCategory() == ARTISTIC_IOR)
+ if (connectedNode && connectedNode->getCategory() == "artistic_ior")
{
artisticExtConnections.push_back(input);
}
@@ -1331,10 +1253,10 @@ void Document::upgradeVersion()
NodePtr artisticIorNode = input->getConnectedNode();
ElementPtr node = input->getParent();
GraphElementPtr parent = node->getParent()->asA();
- NodePtr convert = parent->addNode(CONVERT, node->getName() + "__convert_ior", VECTOR3);
- InputPtr convertInput = convert->addInput(IN, COLOR3);
+ NodePtr convert = parent->addNode("convert", node->getName() + "__convert_ior", "vector3");
+ InputPtr convertInput = convert->addInput("in", "color3");
convertInput->setNodeName(artisticIorNode->getName());
- convertInput->setOutputString(IOR);
+ convertInput->setOutputString("ior");
input->setNodeName(convert->getName());
input->removeAttribute(PortElement::OUTPUT_ATTRIBUTE);
}
@@ -1343,10 +1265,10 @@ void Document::upgradeVersion()
NodePtr artisticIorNode = input->getConnectedNode();
ElementPtr node = input->getParent();
GraphElementPtr parent = node->getParent()->asA();
- NodePtr convert = parent->addNode(CONVERT, node->getName() + "__convert_extinction", VECTOR3);
- InputPtr convertInput = convert->addInput(IN, COLOR3);
+ NodePtr convert = parent->addNode("convert", node->getName() + "__convert_extinction", "vector3");
+ InputPtr convertInput = convert->addInput("in", "color3");
convertInput->setNodeName(artisticIorNode->getName());
- convertInput->setOutputString(EXTINCTION);
+ convertInput->setOutputString("extinction");
input->setNodeName(convert->getName());
input->removeAttribute(PortElement::OUTPUT_ATTRIBUTE);
}
From f583ea1aaa4d1e97488fd7528695d7590a566db5 Mon Sep 17 00:00:00 2001
From: Igor Elovikov
Date: Sat, 7 Oct 2023 20:13:03 +0300
Subject: [PATCH 56/69] Fix Ninja builds of both Viewer and Editor (#1533)
Related to: #1208
---
source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt b/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt
index eaae85a825..2ec553856f 100644
--- a/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt
+++ b/source/MaterialXGraphEditor/External/Glfw/CMakeLists.txt
@@ -41,7 +41,7 @@ if (BUILD_SHARED_LIBS AND UNIX)
# On Unix-like systems, shared libraries can use the soname system.
set(GLFW_LIB_NAME glfw)
else()
- set(GLFW_LIB_NAME glfw3)
+ set(GLFW_LIB_NAME glfw3_minimal)
endif()
if (GLFW_VULKAN_STATIC)
From 695901492ef791d09a0ecf23c0ef7680aa27a563 Mon Sep 17 00:00:00 2001
From: Jonathan Stone
Date: Sat, 7 Oct 2023 15:39:32 -0700
Subject: [PATCH 57/69] Improvements to look inheritance
- Add support for look inheritance in the MaterialX viewer.
- Improve coverage of look inheritance in MaterialX unit tests.
- Raises statement coverage for MaterialX unit tests to 88.6%.
---
source/MaterialXTest/MaterialXCore/Look.cpp | 2 ++
source/MaterialXView/Viewer.cpp | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/source/MaterialXTest/MaterialXCore/Look.cpp b/source/MaterialXTest/MaterialXCore/Look.cpp
index 4106bf2eb3..006538891c 100644
--- a/source/MaterialXTest/MaterialXCore/Look.cpp
+++ b/source/MaterialXTest/MaterialXCore/Look.cpp
@@ -75,6 +75,7 @@ TEST_CASE("Look", "[look]")
// Create an inherited look.
mx::LookPtr look2 = doc->addLook();
look2->setInheritsFrom(look);
+ REQUIRE(look2->getActiveMaterialAssigns().size() == 2);
REQUIRE(look2->getActivePropertySetAssigns().size() == 1);
REQUIRE(look2->getActiveVisibilities().size() == 1);
@@ -86,6 +87,7 @@ TEST_CASE("Look", "[look]")
// Disconnect the inherited look.
look2->setInheritsFrom(nullptr);
+ REQUIRE(look2->getActiveMaterialAssigns().empty());
REQUIRE(look2->getActivePropertySetAssigns().empty());
REQUIRE(look2->getActiveVisibilities().empty());
}
diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp
index 560a19e778..c06846f2ce 100644
--- a/source/MaterialXView/Viewer.cpp
+++ b/source/MaterialXView/Viewer.cpp
@@ -1375,7 +1375,7 @@ void Viewer::loadDocument(const mx::FilePath& filename, mx::DocumentPtr librarie
// with later assignments superseding earlier ones.
for (mx::LookPtr look : doc->getLooks())
{
- for (mx::MaterialAssignPtr matAssign : look->getMaterialAssigns())
+ for (mx::MaterialAssignPtr matAssign : look->getActiveMaterialAssigns())
{
const std::string& activeGeom = matAssign->getActiveGeom();
for (mx::MeshPartitionPtr part : _geometryList)
From c7f01d89e402ff58364cbdcf52cbd2d6f2213e0e Mon Sep 17 00:00:00 2001
From: Niklas Harrysson
Date: Mon, 9 Oct 2023 19:54:24 +0200
Subject: [PATCH 58/69] Improve OSL generation of filename inputs (#1547)
This change list modifies the generation of public filename parameters from being a textureresource struct, to being two separate string parameters for filename and colorspace.
---
source/MaterialXGenOsl/OslShaderGenerator.cpp | 212 +++++++++++-------
source/MaterialXGenOsl/OslShaderGenerator.h | 3 +
2 files changed, 130 insertions(+), 85 deletions(-)
diff --git a/source/MaterialXGenOsl/OslShaderGenerator.cpp b/source/MaterialXGenOsl/OslShaderGenerator.cpp
index 28ada48626..fbb2bb29be 100644
--- a/source/MaterialXGenOsl/OslShaderGenerator.cpp
+++ b/source/MaterialXGenOsl/OslShaderGenerator.cpp
@@ -294,6 +294,25 @@ ShaderPtr OslShaderGenerator::generate(const string& name, ElementPtr element, G
emitLineBreak(stage);
}
+ // Inputs of type 'filename' has been generated into two shader inputs.
+ // So here we construct a single 'textureresource' from these inputs,
+ // to be used further downstream. See emitShaderInputs() for details.
+ VariableBlock& inputs = stage.getUniformBlock(OSL::UNIFORMS);
+ for (size_t i = 0; i < inputs.size(); ++i)
+ {
+ ShaderPort* input = inputs[i];
+ if (input->getType() == Type::FILENAME)
+ {
+ // Construct the textureresource variable.
+ const string newVariableName = input->getVariable() + "_";
+ const string& type = _syntax->getTypeName(input->getType());
+ emitLine(type + newVariableName + " = {" + input->getVariable() + ", " + input->getVariable() + "_colorspace}", stage);
+
+ // Update the variable name to be used downstream.
+ input->setVariable(newVariableName);
+ }
+ }
+
// Emit all texturing nodes. These are inputs to any
// closure/shader nodes and need to be emitted first.
emitFunctionCalls(graph, context, stage, ShaderNode::Classification::TEXTURE);
@@ -489,111 +508,75 @@ void OslShaderGenerator::emitLibraryIncludes(ShaderStage& stage, GenContext& con
emitLineBreak(stage);
}
-namespace
-{
-
-std::unordered_map GEOMPROP_DEFINITIONS =
-{
- { "Pobject", "transform(\"object\", P)" },
- { "Pworld", "P" },
- { "Nobject", "transform(\"object\", N)" },
- { "Nworld", "N" },
- { "Tobject", "transform(\"object\", dPdu)" },
- { "Tworld", "dPdu" },
- { "Bobject", "transform(\"object\", dPdv)" },
- { "Bworld", "dPdv" },
- { "UV0", "{u,v}" },
- { "Vworld", "I" }
-};
-
-} // anonymous namespace
-
void OslShaderGenerator::emitShaderInputs(const VariableBlock& inputs, ShaderStage& stage) const
{
- const std::unordered_map UI_WIDGET_METADATA =
- {
- { Type::FLOAT, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) },
- { Type::INTEGER, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) },
- { Type::FILENAME, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("filename", Type::STRING->getName())) },
- { Type::BOOLEAN, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("checkBox", Type::STRING->getName())) }
- };
-
- const std::set METADATA_TYPE_BLACKLIST =
+ static const std::unordered_map GEOMPROP_DEFINITIONS =
{
- Type::VECTOR2, // Custom struct types doesn't support metadata declarations.
- Type::VECTOR4, //
- Type::COLOR4, //
- Type::FILENAME, //
- Type::BSDF //
+ { "Pobject", "transform(\"object\", P)" },
+ { "Pworld", "P" },
+ { "Nobject", "transform(\"object\", N)" },
+ { "Nworld", "N" },
+ { "Tobject", "transform(\"object\", dPdu)" },
+ { "Tworld", "dPdu" },
+ { "Bobject", "transform(\"object\", dPdv)" },
+ { "Bworld", "dPdv" },
+ { "UV0", "{u,v}" },
+ { "Vworld", "I" }
};
for (size_t i = 0; i < inputs.size(); ++i)
{
const ShaderPort* input = inputs[i];
-
const string& type = _syntax->getTypeName(input->getType());
- string value = _syntax->getValue(input, true);
-
- emitLineBegin(stage);
- emitString(type + " " + input->getVariable(), stage);
- const string& geomprop = input->getGeomProp();
- if (!geomprop.empty())
+ if (input->getType() == Type::FILENAME)
{
- auto it = GEOMPROP_DEFINITIONS.find(geomprop);
- if (it != GEOMPROP_DEFINITIONS.end())
- {
- value = it->second;
- }
+ // Shader inputs of type 'filename' (textures) need special handling.
+ // In OSL codegen a 'filename' is translated to the custom type 'textureresource',
+ // which is a struct containing a file string and a colorspace string.
+ // For the published shader interface we here split this into two separate inputs,
+ // which gives a nicer shader interface with widget metadata on each input.
+
+ ValuePtr value = input->getValue();
+ const string valueStr = value ? value->getValueString() : EMPTY_STRING;
+
+ // Add the file string input
+ emitLineBegin(stage);
+ emitString("string " + input->getVariable() + " = \"" + valueStr + "\"", stage);
+ emitMetadata(input, stage);
+ emitString(",", stage);
+ emitLineEnd(stage, false);
+
+ // Add the colorspace string input
+ emitLineBegin(stage);
+ emitString("string " + input->getVariable() + "_colorspace = \"" + input->getColorSpace() + "\"", stage);
+ emitLineEnd(stage, false);
+ emitScopeBegin(stage, Syntax::DOUBLE_SQUARE_BRACKETS);
+ emitLine("string widget = \"colorspace\"", stage, false);
+ emitScopeEnd(stage, false, false);
}
-
- if (value.empty())
+ else
{
- value = _syntax->getDefaultValue(input->getType());
- }
- emitString(" = " + value, stage);
-
- //
- // Add shader input metadata.
- //
-
- auto widgetMetadataIt = UI_WIDGET_METADATA.find(input->getType());
- const ShaderMetadata* widgetMetadata = widgetMetadataIt != UI_WIDGET_METADATA.end() ? &widgetMetadataIt->second : nullptr;
- const ShaderMetadataVecPtr& metadata = input->getMetadata();
+ emitLineBegin(stage);
+ emitString(type + " " + input->getVariable(), stage);
- if (widgetMetadata || (metadata && metadata->size()))
- {
- StringVec metadataLines;
- if (metadata)
+ string value = _syntax->getValue(input, true);
+ const string& geomprop = input->getGeomProp();
+ if (!geomprop.empty())
{
- for (size_t j = 0; j < metadata->size(); ++j)
+ auto it = GEOMPROP_DEFINITIONS.find(geomprop);
+ if (it != GEOMPROP_DEFINITIONS.end())
{
- const ShaderMetadata& data = metadata->at(j);
- if (METADATA_TYPE_BLACKLIST.count(data.type) == 0)
- {
- const string& delim = (widgetMetadata || j < metadata->size() - 1) ? Syntax::COMMA : EMPTY_STRING;
- const string& dataType = _syntax->getTypeName(data.type);
- const string dataValue = _syntax->getValue(data.type, *data.value, true);
- metadataLines.push_back(dataType + " " + data.name + " = " + dataValue + delim);
- }
+ value = it->second;
}
}
- if (widgetMetadata)
+ if (value.empty())
{
- const string& dataType = _syntax->getTypeName(widgetMetadata->type);
- const string dataValue = _syntax->getValue(widgetMetadata->type, *widgetMetadata->value, true);
- metadataLines.push_back(dataType + " " + widgetMetadata->name + " = " + dataValue);
- }
- if (metadataLines.size())
- {
- emitLineEnd(stage, false);
- emitScopeBegin(stage, Syntax::DOUBLE_SQUARE_BRACKETS);
- for (auto line : metadataLines)
- {
- emitLine(line, stage, false);
- }
- emitScopeEnd(stage, false, false);
+ value = _syntax->getDefaultValue(input->getType());
}
+
+ emitString(" = " + value, stage);
+ emitMetadata(input, stage);
}
if (i < inputs.size())
@@ -618,6 +601,65 @@ void OslShaderGenerator::emitShaderOutputs(const VariableBlock& outputs, ShaderS
}
}
+void OslShaderGenerator::emitMetadata(const ShaderPort* port, ShaderStage& stage) const
+{
+ static const std::unordered_map UI_WIDGET_METADATA =
+ {
+ { Type::FLOAT, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) },
+ { Type::INTEGER, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("number", Type::STRING->getName())) },
+ { Type::FILENAME, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("filename", Type::STRING->getName())) },
+ { Type::BOOLEAN, ShaderMetadata("widget", Type::STRING, Value::createValueFromStrings("checkBox", Type::STRING->getName())) }
+ };
+
+ static const std::set METADATA_TYPE_BLACKLIST =
+ {
+ Type::VECTOR2, // Custom struct types doesn't support metadata declarations.
+ Type::VECTOR4, //
+ Type::COLOR4, //
+ Type::FILENAME, //
+ Type::BSDF //
+ };
+
+ auto widgetMetadataIt = UI_WIDGET_METADATA.find(port->getType());
+ const ShaderMetadata* widgetMetadata = widgetMetadataIt != UI_WIDGET_METADATA.end() ? &widgetMetadataIt->second : nullptr;
+ const ShaderMetadataVecPtr& metadata = port->getMetadata();
+
+ if (widgetMetadata || (metadata && metadata->size()))
+ {
+ StringVec metadataLines;
+ if (metadata)
+ {
+ for (size_t j = 0; j < metadata->size(); ++j)
+ {
+ const ShaderMetadata& data = metadata->at(j);
+ if (METADATA_TYPE_BLACKLIST.count(data.type) == 0)
+ {
+ const string& delim = (widgetMetadata || j < metadata->size() - 1) ? Syntax::COMMA : EMPTY_STRING;
+ const string& dataType = _syntax->getTypeName(data.type);
+ const string dataValue = _syntax->getValue(data.type, *data.value, true);
+ metadataLines.push_back(dataType + " " + data.name + " = " + dataValue + delim);
+ }
+ }
+ }
+ if (widgetMetadata)
+ {
+ const string& dataType = _syntax->getTypeName(widgetMetadata->type);
+ const string dataValue = _syntax->getValue(widgetMetadata->type, *widgetMetadata->value, true);
+ metadataLines.push_back(dataType + " " + widgetMetadata->name + " = " + dataValue);
+ }
+ if (metadataLines.size())
+ {
+ emitLineEnd(stage, false);
+ emitScopeBegin(stage, Syntax::DOUBLE_SQUARE_BRACKETS);
+ for (auto line : metadataLines)
+ {
+ emitLine(line, stage, false);
+ }
+ emitScopeEnd(stage, false, false);
+ }
+ }
+}
+
namespace OSL
{
diff --git a/source/MaterialXGenOsl/OslShaderGenerator.h b/source/MaterialXGenOsl/OslShaderGenerator.h
index 0c7ca426d7..e5cf13977e 100644
--- a/source/MaterialXGenOsl/OslShaderGenerator.h
+++ b/source/MaterialXGenOsl/OslShaderGenerator.h
@@ -59,6 +59,9 @@ class MX_GENOSL_API OslShaderGenerator : public ShaderGenerator
/// Emit a block of shader outputs.
virtual void emitShaderOutputs(const VariableBlock& inputs, ShaderStage& stage) const;
+
+ /// Emit metadata for a shader parameter.
+ virtual void emitMetadata(const ShaderPort* port, ShaderStage& stage) const;
};
namespace OSL
From 54adaeefcb2864632e2e7a38e842e8cd6658ea54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ars=C3=A8ne=20P=C3=A9rard-Gayot?=
Date: Fri, 13 Oct 2023 21:47:47 +0200
Subject: [PATCH 59/69] Fix edge case in HW shader generation for texcoords
(#1559)
This merges both TexCoordNodeMsl and TexCoordNodeGlsl into a single HwTexCoordNode. The parts of the node that are configurable (e.g. the input index) can be changed via re-implementation of the virtual member function getIndexInput().
The new mechanism works regardless of syntax, and uses the smallest texcoord width, depending on what is used in the shader graph.
---
.../TestSuite/stdlib/texture/texcoord.mtlx | 25 ++++++
.../MaterialXGenGlsl/GlslShaderGenerator.cpp | 6 +-
source/MaterialXGenGlsl/GlslShaderGenerator.h | 2 +-
.../Nodes/TexCoordNodeGlsl.cpp | 62 --------------
source/MaterialXGenMsl/MslShaderGenerator.cpp | 6 +-
source/MaterialXGenMsl/MslShaderGenerator.h | 2 +-
.../MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp | 62 --------------
.../MaterialXGenMsl/Nodes/TexCoordNodeMsl.h | 26 ------
source/MaterialXGenShader/HwShaderGenerator.h | 3 +
.../Nodes/HwTexCoordNode.cpp | 83 +++++++++++++++++++
.../Nodes/HwTexCoordNode.h} | 15 ++--
source/MaterialXGenShader/ShaderStage.cpp | 17 +++-
source/MaterialXGenShader/ShaderStage.h | 26 ++++--
13 files changed, 163 insertions(+), 172 deletions(-)
create mode 100644 resources/Materials/TestSuite/stdlib/texture/texcoord.mtlx
delete mode 100644 source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.cpp
delete mode 100644 source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp
delete mode 100644 source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.h
create mode 100644 source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp
rename source/{MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.h => MaterialXGenShader/Nodes/HwTexCoordNode.h} (55%)
diff --git a/resources/Materials/TestSuite/stdlib/texture/texcoord.mtlx b/resources/Materials/TestSuite/stdlib/texture/texcoord.mtlx
new file mode 100644
index 0000000000..4fbf6d12d9
--- /dev/null
+++ b/resources/Materials/TestSuite/stdlib/texture/texcoord.mtlx
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp
index 839f591aa5..87582c8f50 100644
--- a/source/MaterialXGenGlsl/GlslShaderGenerator.cpp
+++ b/source/MaterialXGenGlsl/GlslShaderGenerator.cpp
@@ -10,7 +10,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -34,6 +33,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -174,8 +174,8 @@ GlslShaderGenerator::GlslShaderGenerator() :
//
registerImplementation("IM_bitangent_vector3_" + GlslShaderGenerator::TARGET, BitangentNodeGlsl::create);
//
- registerImplementation("IM_texcoord_vector2_" + GlslShaderGenerator::TARGET, TexCoordNodeGlsl::create);
- registerImplementation("IM_texcoord_vector3_" + GlslShaderGenerator::TARGET, TexCoordNodeGlsl::create);
+ registerImplementation("IM_texcoord_vector2_" + GlslShaderGenerator::TARGET, HwTexCoordNode::create);
+ registerImplementation("IM_texcoord_vector3_" + GlslShaderGenerator::TARGET, HwTexCoordNode::create);
//
registerImplementation("IM_geomcolor_float_" + GlslShaderGenerator::TARGET, GeomColorNodeGlsl::create);
registerImplementation("IM_geomcolor_color3_" + GlslShaderGenerator::TARGET, GeomColorNodeGlsl::create);
diff --git a/source/MaterialXGenGlsl/GlslShaderGenerator.h b/source/MaterialXGenGlsl/GlslShaderGenerator.h
index 1df2ace543..4464f5d47c 100644
--- a/source/MaterialXGenGlsl/GlslShaderGenerator.h
+++ b/source/MaterialXGenGlsl/GlslShaderGenerator.h
@@ -45,7 +45,7 @@ class MX_GENGLSL_API GlslShaderGenerator : public HwShaderGenerator
ShaderNodeImplPtr getImplementation(const NodeDef& nodedef, GenContext& context) const override;
/// Determine the prefix of vertex data variables.
- virtual string getVertexDataPrefix(const VariableBlock& vertexData) const;
+ string getVertexDataPrefix(const VariableBlock& vertexData) const override;
public:
/// Unique identifier for this generator target
diff --git a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.cpp b/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.cpp
deleted file mode 100644
index 846c77f5b7..0000000000
--- a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#include
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-ShaderNodeImplPtr TexCoordNodeGlsl::create()
-{
- return std::make_shared();
-}
-
-void TexCoordNodeGlsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const
-{
- const ShaderOutput* output = node.getOutput();
- const ShaderInput* indexInput = node.getInput(INDEX);
- const string index = indexInput ? indexInput->getValue()->getValueString() : "0";
-
- ShaderStage& vs = shader.getStage(Stage::VERTEX);
- ShaderStage& ps = shader.getStage(Stage::PIXEL);
-
- addStageInput(HW::VERTEX_INPUTS, output->getType(), HW::T_IN_TEXCOORD + "_" + index, vs);
- addStageConnector(HW::VERTEX_DATA, output->getType(), HW::T_TEXCOORD + "_" + index, vs, ps);
-}
-
-void TexCoordNodeGlsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
-{
- const GlslShaderGenerator& shadergen = static_cast(context.getShaderGenerator());
-
- const ShaderInput* indexInput = node.getInput(INDEX);
- const string index = indexInput ? indexInput->getValue()->getValueString() : "0";
- const string variable = HW::T_TEXCOORD + "_" + index;
-
- DEFINE_SHADER_STAGE(stage, Stage::VERTEX)
- {
- VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA);
- const string prefix = shadergen.getVertexDataPrefix(vertexData);
- ShaderPort* texcoord = vertexData[variable];
- if (!texcoord->isEmitted())
- {
- shadergen.emitLine(prefix + texcoord->getVariable() + " = " + HW::T_IN_TEXCOORD + "_" + index, stage);
- texcoord->setEmitted();
- }
- }
-
- DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
- {
- VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA);
- const string prefix = shadergen.getVertexDataPrefix(vertexData);
- ShaderPort* texcoord = vertexData[variable];
- shadergen.emitLineBegin(stage);
- shadergen.emitOutput(node.getOutput(), true, false, context, stage);
- shadergen.emitString(" = " + prefix + texcoord->getVariable(), stage);
- shadergen.emitLineEnd(stage);
- }
-}
-
-MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenMsl/MslShaderGenerator.cpp b/source/MaterialXGenMsl/MslShaderGenerator.cpp
index 0d97e8408f..1d93104ce8 100644
--- a/source/MaterialXGenMsl/MslShaderGenerator.cpp
+++ b/source/MaterialXGenMsl/MslShaderGenerator.cpp
@@ -10,7 +10,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -34,6 +33,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -178,8 +178,8 @@ MslShaderGenerator::MslShaderGenerator() :
//
registerImplementation("IM_bitangent_vector3_" + MslShaderGenerator::TARGET, BitangentNodeMsl::create);
//
- registerImplementation("IM_texcoord_vector2_" + MslShaderGenerator::TARGET, TexCoordNodeMsl::create);
- registerImplementation("IM_texcoord_vector3_" + MslShaderGenerator::TARGET, TexCoordNodeMsl::create);
+ registerImplementation("IM_texcoord_vector2_" + MslShaderGenerator::TARGET, HwTexCoordNode::create);
+ registerImplementation("IM_texcoord_vector3_" + MslShaderGenerator::TARGET, HwTexCoordNode::create);
//
registerImplementation("IM_geomcolor_float_" + MslShaderGenerator::TARGET, GeomColorNodeMsl::create);
registerImplementation("IM_geomcolor_color3_" + MslShaderGenerator::TARGET, GeomColorNodeMsl::create);
diff --git a/source/MaterialXGenMsl/MslShaderGenerator.h b/source/MaterialXGenMsl/MslShaderGenerator.h
index ecbf37d7a6..631c38f33d 100644
--- a/source/MaterialXGenMsl/MslShaderGenerator.h
+++ b/source/MaterialXGenMsl/MslShaderGenerator.h
@@ -48,7 +48,7 @@ class MX_GENMSL_API MslShaderGenerator : public HwShaderGenerator
ShaderNodeImplPtr getImplementation(const NodeDef& nodedef, GenContext& context) const override;
/// Determine the prefix of vertex data variables.
- virtual string getVertexDataPrefix(const VariableBlock& vertexData) const;
+ string getVertexDataPrefix(const VariableBlock& vertexData) const override;
public:
/// Unique identifier for this generator target
diff --git a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp b/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp
deleted file mode 100644
index a88152eb82..0000000000
--- a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#include
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-ShaderNodeImplPtr TexCoordNodeMsl::create()
-{
- return std::make_shared();
-}
-
-void TexCoordNodeMsl::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const
-{
- const ShaderOutput* output = node.getOutput();
- const ShaderInput* indexInput = node.getInput(INDEX);
- const string index = indexInput ? indexInput->getValue()->getValueString() : "0";
-
- ShaderStage& vs = shader.getStage(Stage::VERTEX);
- ShaderStage& ps = shader.getStage(Stage::PIXEL);
-
- addStageInput(HW::VERTEX_INPUTS, output->getType(), HW::T_IN_TEXCOORD + "_" + index, vs);
- addStageConnector(HW::VERTEX_DATA, output->getType(), HW::T_TEXCOORD + "_" + index, vs, ps);
-}
-
-void TexCoordNodeMsl::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
-{
- const MslShaderGenerator& shadergen = static_cast(context.getShaderGenerator());
-
- const ShaderInput* indexInput = node.getInput(INDEX);
- const string index = indexInput ? indexInput->getValue()->getValueString() : "0";
- const string variable = HW::T_TEXCOORD + "_" + index;
-
- DEFINE_SHADER_STAGE(stage, Stage::VERTEX)
- {
- VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA);
- const string prefix = shadergen.getVertexDataPrefix(vertexData);
- ShaderPort* texcoord = vertexData[variable];
- if (!texcoord->isEmitted())
- {
- shadergen.emitLine(prefix + texcoord->getVariable() + " = " + HW::T_IN_TEXCOORD + "_" + index, stage);
- texcoord->setEmitted();
- }
- }
-
- DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
- {
- VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA);
- const string prefix = shadergen.getVertexDataPrefix(vertexData);
- ShaderPort* texcoord = vertexData[variable];
- shadergen.emitLineBegin(stage);
- shadergen.emitOutput(node.getOutput(), true, false, context, stage);
- shadergen.emitString(" = " + prefix + texcoord->getVariable(), stage);
- shadergen.emitLineEnd(stage);
- }
-}
-
-MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.h b/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.h
deleted file mode 100644
index 6c227cc63b..0000000000
--- a/source/MaterialXGenMsl/Nodes/TexCoordNodeMsl.h
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// Copyright Contributors to the MaterialX Project
-// SPDX-License-Identifier: Apache-2.0
-//
-
-#ifndef MATERIALX_TEXCOORDNODEMSL_H
-#define MATERIALX_TEXCOORDNODEMSL_H
-
-#include
-
-MATERIALX_NAMESPACE_BEGIN
-
-/// TexCoord node implementation for MSL
-class MX_GENMSL_API TexCoordNodeMsl : public MslImplementation
-{
- public:
- static ShaderNodeImplPtr create();
-
- void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override;
-
- void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
-};
-
-MATERIALX_NAMESPACE_END
-
-#endif
diff --git a/source/MaterialXGenShader/HwShaderGenerator.h b/source/MaterialXGenShader/HwShaderGenerator.h
index 66d60dc68a..bba572c631 100644
--- a/source/MaterialXGenShader/HwShaderGenerator.h
+++ b/source/MaterialXGenShader/HwShaderGenerator.h
@@ -306,6 +306,9 @@ class MX_GENSHADER_API HwShaderGenerator : public ShaderGenerator
/// Unbind all light shaders previously bound.
static void unbindLightShaders(GenContext& context);
+ /// Determine the prefix of vertex data variables.
+ virtual string getVertexDataPrefix(const VariableBlock& vertexData) const = 0;
+
/// Types of closure contexts for HW.
enum ClosureContextType
{
diff --git a/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp b/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp
new file mode 100644
index 0000000000..3aa84400df
--- /dev/null
+++ b/source/MaterialXGenShader/Nodes/HwTexCoordNode.cpp
@@ -0,0 +1,83 @@
+//
+// Copyright Contributors to the MaterialX Project
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include
+#include
+#include
+
+MATERIALX_NAMESPACE_BEGIN
+
+string HwTexCoordNode::INDEX = "index";
+
+ShaderNodeImplPtr HwTexCoordNode::create()
+{
+ return std::make_shared();
+}
+
+void HwTexCoordNode::createVariables(const ShaderNode& node, GenContext&, Shader& shader) const
+{
+ const ShaderOutput* output = node.getOutput();
+ const string index = getIndex(node);
+
+ ShaderStage& vs = shader.getStage(Stage::VERTEX);
+ ShaderStage& ps = shader.getStage(Stage::PIXEL);
+
+ addStageInput(HW::VERTEX_INPUTS, output->getType(), HW::T_IN_TEXCOORD + "_" + index, vs, true);
+ addStageConnector(HW::VERTEX_DATA, output->getType(), HW::T_TEXCOORD + "_" + index, vs, ps, true);
+}
+
+void HwTexCoordNode::emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const
+{
+ const HwShaderGenerator& shadergen = static_cast(context.getShaderGenerator());
+
+ const string index = getIndex(node);
+ const string variable = HW::T_TEXCOORD + "_" + index;
+ const ShaderOutput* output = node.getOutput();
+
+ DEFINE_SHADER_STAGE(stage, Stage::VERTEX)
+ {
+ VariableBlock& vertexData = stage.getOutputBlock(HW::VERTEX_DATA);
+ const string prefix = shadergen.getVertexDataPrefix(vertexData);
+ ShaderPort* texcoord = vertexData[variable];
+ if (!texcoord->isEmitted())
+ {
+ shadergen.emitLine(prefix + texcoord->getVariable() + " = " + HW::T_IN_TEXCOORD + "_" + index, stage);
+ texcoord->setEmitted();
+ }
+ }
+
+ DEFINE_SHADER_STAGE(stage, Stage::PIXEL)
+ {
+ VariableBlock& vertexData = stage.getInputBlock(HW::VERTEX_DATA);
+ const string prefix = shadergen.getVertexDataPrefix(vertexData);
+ ShaderPort* texcoord = vertexData[variable];
+ shadergen.emitLineBegin(stage);
+ shadergen.emitOutput(output, true, false, context, stage);
+
+ // Extract the requested number of components from the texture coordinates (which may be a
+ // larger datatype than the requested number of texture coordinates, if several texture
+ // coordinate nodes with different width coexist).
+ string suffix = EMPTY_STRING;
+ if (output->getType() == Type::VECTOR2)
+ {
+ suffix = ".xy";
+ }
+ else if (output->getType() == Type::VECTOR3)
+ {
+ suffix = ".xyz";
+ }
+
+ shadergen.emitString(" = " + prefix + texcoord->getVariable() + suffix, stage);
+ shadergen.emitLineEnd(stage);
+ }
+}
+
+string HwTexCoordNode::getIndex(const ShaderNode& node) const
+{
+ const ShaderInput* input = node.getInput(INDEX);
+ return input ? input->getValue()->getValueString() : "0";
+}
+
+MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.h b/source/MaterialXGenShader/Nodes/HwTexCoordNode.h
similarity index 55%
rename from source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.h
rename to source/MaterialXGenShader/Nodes/HwTexCoordNode.h
index c15a86fd9c..9aae3d18ce 100644
--- a/source/MaterialXGenGlsl/Nodes/TexCoordNodeGlsl.h
+++ b/source/MaterialXGenShader/Nodes/HwTexCoordNode.h
@@ -3,15 +3,15 @@
// SPDX-License-Identifier: Apache-2.0
//
-#ifndef MATERIALX_TEXCOORDNODEGLSL_H
-#define MATERIALX_TEXCOORDNODEGLSL_H
+#ifndef MATERIALX_HWTEXCOORDNODE_H
+#define MATERIALX_HWTEXCOORDNODE_H
-#include
+#include
MATERIALX_NAMESPACE_BEGIN
-/// TexCoord node implementation for GLSL
-class MX_GENGLSL_API TexCoordNodeGlsl : public GlslImplementation
+/// Generic texture coordinate node for hardware languages
+class MX_GENSHADER_API HwTexCoordNode : public ShaderNodeImpl
{
public:
static ShaderNodeImplPtr create();
@@ -19,6 +19,11 @@ class MX_GENGLSL_API TexCoordNodeGlsl : public GlslImplementation
void createVariables(const ShaderNode& node, GenContext& context, Shader& shader) const override;
void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override;
+
+ protected:
+ virtual string getIndex(const ShaderNode& node) const;
+
+ static string INDEX;
};
MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXGenShader/ShaderStage.cpp b/source/MaterialXGenShader/ShaderStage.cpp
index 822f3c9664..b5387bcb94 100644
--- a/source/MaterialXGenShader/ShaderStage.cpp
+++ b/source/MaterialXGenShader/ShaderStage.cpp
@@ -65,11 +65,26 @@ ShaderPort* VariableBlock::find(const ShaderPortPredicate& predicate)
return nullptr;
}
-ShaderPort* VariableBlock::add(const TypeDesc* type, const string& name, ValuePtr value)
+ShaderPort* VariableBlock::add(const TypeDesc* type, const string& name, ValuePtr value, bool shouldWiden)
{
auto it = _variableMap.find(name);
if (it != _variableMap.end())
{
+ if (shouldWiden)
+ {
+ // Automatically try to widen the type of the shader port if the requested type differs from
+ // the existing port's type.
+ if (it->second->getType()->getSize() < type->getSize())
+ {
+ it->second->setType(type);
+ }
+ }
+ else if (type != it->second->getType())
+ {
+ throw ExceptionShaderGenError("Trying to add shader port '" + name + "' with type '" +
+ type->getName() + "', but existing shader port with type '" +
+ it->second->getType()->getName() + "' was found");
+ }
return it->second.get();
}
diff --git a/source/MaterialXGenShader/ShaderStage.h b/source/MaterialXGenShader/ShaderStage.h
index 71004f8e52..a6a5cec0b8 100644
--- a/source/MaterialXGenShader/ShaderStage.h
+++ b/source/MaterialXGenShader/ShaderStage.h
@@ -113,7 +113,14 @@ class MX_GENSHADER_API VariableBlock
ShaderPort* find(const ShaderPortPredicate& predicate);
/// Add a new shader port to this block.
- ShaderPort* add(const TypeDesc* type, const string& name, ValuePtr value = nullptr);
+ /// @param type The desired shader port type
+ /// @param name The shader port name
+ /// @param value The value to attach to the shader port
+ /// @param shouldWiden When false, an exception is thrown if the type of the existing port with
+ /// the same name does not match the requested type. When true, the types can mismatch, and the
+ /// type of any existing port is widened to match the requested type when necessary.
+ /// @return A new shader port, or a pre-existing shader port with the same name.
+ ShaderPort* add(const TypeDesc* type, const string& name, ValuePtr value = nullptr, bool shouldWiden = false);
/// Add an existing shader port to this block.
void add(ShaderPortPtr port);
@@ -339,20 +346,22 @@ inline ShaderPort* addStageUniform(const string& block,
inline ShaderPort* addStageInput(const string& block,
const TypeDesc* type,
const string& name,
- ShaderStage& stage)
+ ShaderStage& stage,
+ bool shouldWiden = false)
{
VariableBlock& inputs = stage.getInputBlock(block);
- return inputs.add(type, name);
+ return inputs.add(type, name, {}, shouldWiden);
}
/// Utility function for adding a new shader port to an output block.
inline ShaderPort* addStageOutput(const string& block,
const TypeDesc* type,
const string& name,
- ShaderStage& stage)
+ ShaderStage& stage,
+ bool shouldWiden = false)
{
VariableBlock& outputs = stage.getOutputBlock(block);
- return outputs.add(type, name);
+ return outputs.add(type, name, {}, shouldWiden);
}
/// Utility function for adding a connector block between stages.
@@ -370,10 +379,11 @@ inline void addStageConnector(const string& block,
const TypeDesc* type,
const string& name,
ShaderStage& from,
- ShaderStage& to)
+ ShaderStage& to,
+ bool shouldWiden = false)
{
- addStageOutput(block, type, name, from);
- addStageInput(block, type, name, to);
+ addStageOutput(block, type, name, from, shouldWiden);
+ addStageInput(block, type, name, to, shouldWiden);
}
MATERIALX_NAMESPACE_END
From eb52ec28e09fc86e00b6e7120f5676d37db6e8b8 Mon Sep 17 00:00:00 2001
From: Erika Harrison
Date: Fri, 13 Oct 2023 17:26:19 -0600
Subject: [PATCH 60/69] Update link connections by dragging between ports
(#1569)
Currently, one must explicitly delete an existing link before adding a new link for a given node. This change enables dragging to update a link connection, and automatically deletes the existing link on the input pin if one exists.
Note: An output pin on a node may have many outgoing links, but an input pin may only have one incoming link. This behaviour is unchanged.
Also:
- Renames a few variables for consistency on start/end and input/output pins
- Ensures you can't add a link from an input to an input, or from an output to an output
- Can also drag from an output to an input and have it correctly delete existing link
---
source/MaterialXGraphEditor/Graph.cpp | 307 ++++++++++++++------------
source/MaterialXGraphEditor/Graph.h | 4 +-
2 files changed, 171 insertions(+), 140 deletions(-)
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index 2b28317ee2..522280cb08 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -846,7 +846,7 @@ void Graph::setRenderMaterial(UiNodePtr node)
}
}
-void Graph::updateMaterials(mx::InputPtr input, mx::ValuePtr value)
+void Graph::updateMaterials(mx::InputPtr input /* = nullptr */, mx::ValuePtr value /* = nullptr */)
{
std::string renderablePath;
if (_currRenderNode)
@@ -2483,12 +2483,22 @@ void Graph::setDefaults(mx::InputPtr input)
}
}
-void Graph::addLink(ed::PinId inputPinId, ed::PinId outputPinId)
+void Graph::addLink(ed::PinId startPinId, ed::PinId endPinId)
{
- int end_attr = int(outputPinId.Get());
- int start_attr = int(inputPinId.Get());
- UiPinPtr inputPin = getPin(outputPinId);
- UiPinPtr outputPin = getPin(inputPinId);
+ // prefer to assume left to right - start is an output, end is an input; swap if inaccurate
+ if (UiPinPtr inputPin = getPin(endPinId); inputPin && inputPin->_kind != ed::PinKind::Input)
+ {
+ auto tmp = startPinId;
+ startPinId = endPinId;
+ endPinId = tmp;
+ }
+
+ int end_attr = int(endPinId.Get());
+ int start_attr = int(startPinId.Get());
+ ed::PinId outputPinId = startPinId;
+ ed::PinId inputPinId = endPinId;
+ UiPinPtr outputPin = getPin(outputPinId);
+ UiPinPtr inputPin = getPin(inputPinId);
if (!inputPin || !outputPin)
{
@@ -2505,187 +2515,206 @@ void Graph::addLink(ed::PinId inputPinId, ed::PinId outputPinId)
return;
}
- if (inputPin->_connected == false)
+ // Perform kind check
+ bool kindsMatch = (outputPin->_kind == inputPin->_kind);
+ if (kindsMatch)
{
- int upNode = getNodeId(inputPinId);
- int downNode = getNodeId(outputPinId);
- UiNodePtr uiDownNode = _graphNodes[downNode];
- UiNodePtr uiUpNode = _graphNodes[upNode];
- if (!uiDownNode || !uiUpNode)
- {
- ed::RejectNewItem();
- return;
- }
+ ed::RejectNewItem();
+ showLabel("Invalid connection due to same input/output kind", ImColor(50, 50, 50, 255));
+ return;
+ }
- // make sure there is an implementation for node
- const mx::ShaderGenerator& shadergen = _renderer->getGenContext().getShaderGenerator();
+ int upNode = getNodeId(outputPinId);
+ int downNode = getNodeId(inputPinId);
+ UiNodePtr uiDownNode = _graphNodes[downNode];
+ UiNodePtr uiUpNode = _graphNodes[upNode];
+ if (!uiDownNode || !uiUpNode)
+ {
+ ed::RejectNewItem();
+ return;
+ }
- // 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;
- }
+ // make sure there is an implementation for node
+ const mx::ShaderGenerator& shadergen = _renderer->getGenContext().getShaderGenerator();
- // Find the implementation for this nodedef if not an input or output uinode
- if (uiDownNode->getInput() && _isNodeGraph)
+ // 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 (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 (uiUpNode->getNode())
+ }
+
+ if (ed::AcceptNewItem())
+ {
+ // If the accepting node already has a link, remove it
+ if (inputPin->_connected)
{
- mx::ShaderNodeImplPtr impl = shadergen.getImplementation(*_graphNodes[upNode]->getNode()->getNodeDef(), _renderer->getGenContext());
- if (!impl)
+ for (auto linksItr = _currLinks.begin(); linksItr != _currLinks.end(); linksItr++)
{
- ed::RejectNewItem();
- showLabel("Invalid Connection: Node does not have an implementation", ImColor(50, 50, 50, 255));
- return;
+ if (linksItr->_endAttr == end_attr)
+ {
+ // found existing link - remove it; adapted from deleteLink
+ // note: ed::BreakLinks doesn't work as the order ends up inaccurate
+ deleteLinkInfo(linksItr->_startAttr, linksItr->_endAttr);
+ _currLinks.erase(linksItr);
+ break;
+ }
}
+
}
- 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);
+ // 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 (uiDownNode->getNode() || uiDownNode->getNodeGraph())
+ if (uiDownNode->getNode() || uiDownNode->getNodeGraph())
+ {
+ mx::InputPtr connectingInput = nullptr;
+ for (UiPinPtr pin : uiDownNode->inputPins)
{
- mx::InputPtr connectingInput = nullptr;
- for (UiPinPtr pin : uiDownNode->inputPins)
+ if (pin->_pinId == inputPinId)
{
- 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(uiDownNode, pin->_input);
- // update value to be empty
- if (uiDownNode->getNode() && uiDownNode->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING)
+ if (uiUpNode->getOutput() != nullptr)
{
- if (uiUpNode->getOutput() != nullptr)
- {
- pin->_input->setConnectedOutput(uiUpNode->getOutput());
- }
- else if (uiUpNode->getInput() != nullptr)
- {
- pin->_input->setInterfaceName(uiUpNode->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 (uiUpNode->getNodeGraph() != nullptr)
+ for (UiPinPtr outPin : uiUpNode->outputPins)
{
- for (UiPinPtr outPin : uiUpNode->outputPins)
+ // set pin connection to correct output
+ if (outPin->_pinId == outputPinId)
{
- // set pin connection to correct output
- if (outPin->_pinId == inputPinId)
- {
- mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name);
- pin->_input->setConnectedOutput(outputs);
- }
+ mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name);
+ pin->_input->setConnectedOutput(outputs);
}
}
- else
- {
- pin->_input->setConnectedNode(uiUpNode->getNode());
- }
}
+ else
+ {
+ pin->_input->setConnectedNode(uiUpNode->getNode());
+ }
+ }
+ }
+ else
+ {
+ if (uiUpNode->getInput())
+ {
+ pin->_input->setInterfaceName(uiUpNode->getName());
}
else
{
- if (uiUpNode->getInput())
- {
- pin->_input->setInterfaceName(uiUpNode->getName());
- }
- else
+ if (uiUpNode->getNode())
{
- if (uiUpNode->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)
{
- 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(uiUpNode->getNode());
- }
- else
+ pin->_input->setConnectedNode(uiUpNode->getNode());
+ }
+ else
+ {
+ for (UiPinPtr outPin : _graphNodes[upNode]->outputPins)
{
- for (UiPinPtr outPin : _graphNodes[upNode]->outputPins)
+ // set pin connection to correct output
+ if (outPin->_pinId == outputPinId)
{
- // set pin connection to correct output
- if (outPin->_pinId == inputPinId)
+ mx::OutputPtr outputs = uiUpNode->getNode()->getOutput(outPin->_name);
+ if (!outputs)
{
- mx::OutputPtr outputs = uiUpNode->getNode()->getOutput(outPin->_name);
- if (!outputs)
- {
- outputs = uiUpNode->getNode()->addOutput(outPin->_name, pin->_input->getType());
- }
- pin->_input->setConnectedOutput(outputs);
+ outputs = uiUpNode->getNode()->addOutput(outPin->_name, pin->_input->getType());
}
+ pin->_input->setConnectedOutput(outputs);
}
}
}
- else if (uiUpNode->getNodeGraph())
+ }
+ else if (uiUpNode->getNodeGraph())
+ {
+ for (UiPinPtr outPin : uiUpNode->outputPins)
{
- for (UiPinPtr outPin : uiUpNode->outputPins)
+ // set pin connection to correct output
+ if (outPin->_pinId == outputPinId)
{
- // set pin connection to correct output
- if (outPin->_pinId == inputPinId)
- {
- mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name);
- pin->_input->setConnectedOutput(outputs);
- }
+ 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();
- }
}
void Graph::removeEdge(int downNode, int upNode, UiPinPtr pin)
@@ -4045,12 +4074,12 @@ void Graph::drawGraph(ImVec2 mousePos)
// Add new link
if (ed::BeginCreate())
{
- ed::PinId inputPinId, outputPinId, filterPinId;
- if (ed::QueryNewLink(&inputPinId, &outputPinId))
+ ed::PinId startPinId, endPinId, filterPinId;
+ if (ed::QueryNewLink(&startPinId, &endPinId))
{
if (!readOnly())
{
- addLink(inputPinId, outputPinId);
+ addLink(startPinId, endPinId);
}
else
{
diff --git a/source/MaterialXGraphEditor/Graph.h b/source/MaterialXGraphEditor/Graph.h
index 8c76f0f68d..9b9857c69a 100644
--- a/source/MaterialXGraphEditor/Graph.h
+++ b/source/MaterialXGraphEditor/Graph.h
@@ -90,7 +90,9 @@ class Graph
// Add link to nodegraph and set up connections between UiNodes and
// MaterialX Nodes to update shader
- void addLink(ed::PinId inputPinId, ed::PinId outputPinId);
+ // startPinId - where the link was initiated
+ // endPinId - where the link was ended
+ void addLink(ed::PinId startPinId, ed::PinId endPinId);
// Delete link from current link vector and remove any connections in
// UiNode or MaterialX Nodes to update shader
From 044645345bd491250ff6041489b83b28640e54bb Mon Sep 17 00:00:00 2001
From: Andy <94316446+beersandrew@users.noreply.github.com>
Date: Sat, 14 Oct 2023 22:56:53 +0300
Subject: [PATCH 61/69] Restructure Add Node List (#1562)
Added a list of nodes to the best of my ability to be the order they should be displayed
---
source/MaterialXGraphEditor/Graph.cpp | 166 ++++++++++++++------------
source/MaterialXGraphEditor/Graph.h | 27 ++++-
2 files changed, 112 insertions(+), 81 deletions(-)
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index 522280cb08..849b8607b4 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -236,9 +236,6 @@ void Graph::addExtraNodes()
return;
}
- // Clear any old nodes, if we previously used tab with another graph doc
- _extraNodes.clear();
-
// Get all types from the doc
std::vector types;
std::vector typeDefs = _graphDoc->getTypeDefs();
@@ -252,18 +249,16 @@ void Graph::addExtraNodes()
for (const std::string& type : types)
{
std::string nodeName = "ND_input_" + type;
- _extraNodes["Input Nodes"].push_back({ nodeName, type, "input" });
+ _nodesToAdd.emplace_back(nodeName, type, "input", "Input Nodes");
nodeName = "ND_output_" + type;
- _extraNodes["Output Nodes"].push_back({ nodeName, type, "output" });
+ _nodesToAdd.emplace_back(nodeName, type, "output", "Output Nodes");
}
// Add group node
- std::vector groupNode{ "ND_group", "", "group" };
- _extraNodes["Group Nodes"].push_back(groupNode);
+ _nodesToAdd.emplace_back("ND_group", "", "group", "Group Nodes");
// Add nodegraph node
- std::vector nodeGraph{ "ND_nodegraph", "", "nodegraph" };
- _extraNodes["Node Graph"].push_back(nodeGraph);
+ _nodesToAdd.emplace_back("ND_nodegraph", "", "nodegraph", "Node Graph");
}
ed::PinId Graph::getOutputPin(UiNodePtr node, UiNodePtr upNode, UiPinPtr input)
@@ -1224,20 +1219,63 @@ void Graph::setUiNodeInfo(UiNodePtr node, const std::string& type, const std::st
void Graph::createNodeUIList(mx::DocumentPtr doc)
{
_nodesToAdd.clear();
- const std::string EXTRA_GROUP_NAME = "extra";
- for (mx::NodeDefPtr nodeDef : doc->getNodeDefs())
+
+ std::vector ordered_groups = {
+ "texture2d",
+ "texture3d",
+ "procedural",
+ "procedural2d",
+ "procedural3d",
+ "geometric",
+ "translation",
+ "convolution2d",
+ "math",
+ "adjustment",
+ "compositing",
+ "conditional",
+ "channel",
+ "organization",
+ "global",
+ "application",
+ "material",
+ "shader",
+ "pbr",
+ "light",
+ "colortransform",
+ "no_group"
+ };
+
+ auto nodeDefs = doc->getNodeDefs();
+ std::unordered_map> groupToNodeDef;
+
+ for (const auto& nodeDef : nodeDefs)
{
- // NodeDef is the key for the map
std::string group = nodeDef->getNodeGroup();
+
if (group.empty())
{
- group = EXTRA_GROUP_NAME;
+ group = "no_group";
}
- if (_nodesToAdd.find(group) == _nodesToAdd.end())
+
+ if (groupToNodeDef.find(group) == groupToNodeDef.end())
{
- _nodesToAdd[group] = std::vector();
+ groupToNodeDef[group] = std::vector();
+ }
+ groupToNodeDef[group].push_back(nodeDef);
+ }
+
+ for (const auto& group : ordered_groups)
+ {
+ auto it = groupToNodeDef.find(group);
+ if (it != groupToNodeDef.end())
+ {
+ const auto& groupNodeDefs = it->second;
+
+ for (const auto& nodeDef : groupNodeDefs)
+ {
+ _nodesToAdd.emplace_back(nodeDef->getName(), nodeDef->getType(), nodeDef->getNodeString(), group);
+ }
}
- _nodesToAdd[group].push_back(nodeDef);
}
addExtraNodes();
@@ -3595,96 +3633,66 @@ void Graph::addNodePopup(bool cursor)
// 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 nodedefs and add to menu if matches filter
+ for (auto node : _nodesToAdd)
{
// Filter out list of nodes
if (subs.size() > 0)
{
ImGui::SetNextWindowSizeConstraints(ImVec2(250.0f, 300.0f), ImVec2(-1.0f, 500.0f));
- for (size_t i = 0; i < it->second.size(); i++)
- {
- std::string str(it->second[i][0]);
- std::string nodeName = it->second[i][0];
+ std::string str(node.getName());
+ std::string nodeName = node.getName();
- // Disallow creating nested nodegraphs
- if (_isNodeGraph && it->first == NODEGRAPH_ENTRY)
- {
- continue;
- }
+ // Disallow creating nested nodegraphs
+ if (_isNodeGraph && node.getGroup() == NODEGRAPH_ENTRY)
+ {
+ continue;
+ }
- // Allow spaces to be used to search for node names
- std::replace(subs.begin(), subs.end(), ' ', '_');
+ // Allow spaces to be used to search for node names
+ std::replace(subs.begin(), subs.end(), ' ', '_');
- if (str.find(subs) != std::string::npos)
+ if (str.find(subs) != std::string::npos)
+ {
+ if (ImGui::MenuItem(getUserNodeDefName(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], getUserNodeDefName(nodeName), it->second[i][1]);
- _addNewNode = true;
- memset(input, '\0', sizeof(input));
- }
+ addNode(node.getCategory(), getUserNodeDefName(nodeName), node.getType());
+ _addNewNode = true;
+ memset(input, '\0', sizeof(input));
}
}
}
else
{
ImGui::SetNextWindowSizeConstraints(ImVec2(100, 10), ImVec2(-1, 300));
- if (ImGui::BeginMenu(it->first.c_str()))
+ if (ImGui::BeginMenu(node.getGroup().c_str()))
{
ImGui::SetWindowFontScale(_fontScale);
- for (size_t j = 0; j < it->second.size(); j++)
+ std::string name = node.getName();
+ std::string prefix = "ND_";
+ if (name.compare(0, prefix.size(), prefix) == 0 && name.compare(prefix.size(), std::string::npos, node.getCategory()) == 0)
{
- std::string name = it->second[j][0];
if (ImGui::MenuItem(getUserNodeDefName(name).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
{
- addNode(it->second[j][2], getUserNodeDefName(name), it->second[j][1]);
- _addNewNode = true;
- }
- }
- ImGui::EndMenu();
- }
- }
- }
-
- // 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
- if (subs.size() > 0)
- {
- ImGui::SetNextWindowSizeConstraints(ImVec2(250.0f, 300.0f), ImVec2(-1.0f, 500.0f));
- for (size_t i = 0; i < it->second.size(); i++)
- {
- std::string str(it->second[i]->getName());
- std::string nodeName = it->second[i]->getName();
- if (str.find(subs) != std::string::npos)
- {
- 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());
+ addNode(node.getCategory(), getUserNodeDefName(name), node.getType());
_addNewNode = true;
- memset(input, '\0', sizeof(input));
}
}
- }
- }
- else
- {
- ImGui::SetNextWindowSizeConstraints(ImVec2(100, 10), ImVec2(-1, 300));
- if (ImGui::BeginMenu(it->first.c_str()))
- {
- ImGui::SetWindowFontScale(_fontScale);
- for (size_t i = 0; i < it->second.size(); i++)
+ else
{
- std::string name = it->second[i]->getName();
- std::string val = getUserNodeDefName(name);
- if (ImGui::MenuItem(val.c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
+ if (ImGui::BeginMenu(node.getCategory().c_str()))
{
- addNode(it->second[i]->getNodeString(), val, it->second[i]->getType());
- _addNewNode = true;
+ if (ImGui::MenuItem(getUserNodeDefName(name).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
+ {
+ addNode(node.getCategory(), getUserNodeDefName(name), node.getType());
+ _addNewNode = true;
+ }
+ ImGui::EndMenu();
}
}
+
+
ImGui::EndMenu();
}
}
diff --git a/source/MaterialXGraphEditor/Graph.h b/source/MaterialXGraphEditor/Graph.h
index 9b9857c69a..87d4119c2a 100644
--- a/source/MaterialXGraphEditor/Graph.h
+++ b/source/MaterialXGraphEditor/Graph.h
@@ -14,6 +14,30 @@
#include
+class MenuItem
+{
+ public:
+ MenuItem(const std::string& name, const std::string& type, const std::string& category, const std::string& group) :
+ name(name), type(type), category(category), group(group) { }
+
+ // getters
+ std::string getName() const { return name; }
+ std::string getType() const { return type; }
+ std::string getCategory() const { return category; }
+ std::string getGroup() const { return group; }
+
+ // setters
+ void setName(const std::string& newName) { this->name = newName; }
+ void setType(const std::string& newType) { this->type = newType; }
+ void setCategory(const std::string& newCategory) { this->category = newCategory; }
+ void setGroup(const std::string& newGroup) { this->group = newGroup; }
+
+ private:
+ std::string name;
+ std::string type;
+ std::string category;
+ std::string group;
+};
namespace ed = ax::NodeEditor;
namespace mx = MaterialX;
@@ -248,8 +272,7 @@ class Graph
std::vector _currGraphName;
// for adding new nodes
- std::unordered_map> _nodesToAdd;
- std::unordered_map>> _extraNodes;
+ std::vector
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl
index bce4a44ea5..8089feb7f0 100644
--- a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl
+++ b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl
@@ -2777,66 +2777,6 @@ export color4 mx_screen_color4(
return color4(rgb,a);
}
-float mx_overlay(float mxp_fg, float mxp_bg)
-{
- return (mxp_fg < 0.5) ? (2 * mxp_fg * mxp_bg) : (1 - (1 - mxp_fg) * (1 - mxp_bg));
-}
-float2 mx_overlay(float2 mxp_fg, float2 mxp_bg) [[ anno::unused() ]]
-{
- return float2(
- mx_overlay(mxp_fg.x, mxp_bg.x),
- mx_overlay(mxp_fg.y, mxp_bg.y)
- );
-}
-color mx_overlay(color mxp_fg, color mxp_bg)
-{
- float3 fg(mxp_fg);
- float3 bg(mxp_bg);
- return color(
- mx_overlay(fg.x, bg.x),
- mx_overlay(fg.y, bg.y),
- mx_overlay(fg.z, bg.z)
- );
-}
-
-export float mx_overlay_float(
- float mxp_fg = 0.0,
- float mxp_bg = 0.0,
- float mxp_mix = 1.0
-)
- [[
- anno::description("Node Group: compositing")
- ]]
-{
- return mxp_mix * mx_overlay(mxp_fg, mxp_bg) + (1-mxp_mix) * mxp_bg;
-}
-
-export color mx_overlay_color3(
- color mxp_fg = color(0.0),
- color mxp_bg = color(0.0),
- float mxp_mix = 1.0
-)
- [[
- anno::description("Node Group: compositing")
- ]]
-{
- return mxp_mix * mx_overlay(mxp_fg, mxp_bg) + (1-mxp_mix) * mxp_bg;
-}
-
-export color4 mx_overlay_color4(
- color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0),
- color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0),
- float mxp_mix = float(1.0)
-)
- [[
- anno::description("Node Group: compositing")
- ]]
-{
- color rgb = mxp_mix * mx_overlay(mxp_fg.rgb, mxp_bg.rgb) + (1-mxp_mix) * mxp_bg.rgb;
- float a = mxp_mix * mx_overlay(mxp_fg.a , mxp_bg.a ) + (1-mxp_mix) * mxp_bg.a;
- return color4(rgb,a);
-}
-
export color4 mx_disjointover_color4(
color4 mxp_fg = mk_color4(0.0, 0.0, 0.0, 0.0),
color4 mxp_bg = mk_color4(0.0, 0.0, 0.0, 0.0),
From a5b832dc8addc24cb2d661d6c1a04faacd684fe9 Mon Sep 17 00:00:00 2001
From: Stefan Habel <19556655+StefanHabel@users.noreply.github.com>
Date: Tue, 24 Oct 2023 08:15:32 -0700
Subject: [PATCH 68/69] Fixed off-by-one index check in setChildIndex (#1582)
Fixed an off-by-one index check in Element::setChildIndex().
---
source/MaterialXCore/Element.cpp | 2 +-
source/MaterialXTest/MaterialXCore/Element.cpp | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/source/MaterialXCore/Element.cpp b/source/MaterialXCore/Element.cpp
index 18d028efd3..5131dc8070 100644
--- a/source/MaterialXCore/Element.cpp
+++ b/source/MaterialXCore/Element.cpp
@@ -168,7 +168,7 @@ void Element::setChildIndex(const string& name, int index)
return;
}
- if (index < 0 || index > (int) _childOrder.size())
+ if (index < 0 || index >= (int) _childOrder.size())
{
throw Exception("Invalid child index");
}
diff --git a/source/MaterialXTest/MaterialXCore/Element.cpp b/source/MaterialXTest/MaterialXCore/Element.cpp
index fc4939a74f..3865934ccb 100644
--- a/source/MaterialXTest/MaterialXCore/Element.cpp
+++ b/source/MaterialXTest/MaterialXCore/Element.cpp
@@ -54,6 +54,9 @@ TEST_CASE("Element", "[element]")
REQUIRE(*doc2 != *doc);
doc2->setChildIndex("elem1", doc2->getChildIndex("elem2"));
REQUIRE(*doc2 == *doc);
+ REQUIRE_THROWS_AS(doc2->setChildIndex("elem1", -100), mx::Exception);
+ REQUIRE_THROWS_AS(doc2->setChildIndex("elem1", -1), mx::Exception);
+ REQUIRE_THROWS_AS(doc2->setChildIndex("elem1", 2), mx::Exception);
REQUIRE_THROWS_AS(doc2->setChildIndex("elem1", 100), mx::Exception);
REQUIRE(*doc2 == *doc);
From 926ac2756c36f5541d44f6c3f8814bfebf228f3b Mon Sep 17 00:00:00 2001
From: Ashwin Bhat <1727158+ashwinbhat@users.noreply.github.com>
Date: Tue, 24 Oct 2023 14:45:51 -0700
Subject: [PATCH 69/69] Update Catch2 to version 2.13.10 (#1566)
- Update Catch2 version to v2.13.10
- Catch2 v2.13.0 supports BENCHMARK tests.
- A new BENCHMARK test "GenShader: ShaderGen Performance" to benchmark document load, validation and shadergen times
---
CMakeLists.txt | 5 ++
source/MaterialXTest/CMakeLists.txt | 4 +
source/MaterialXTest/External/Catch/catch.hpp | 28 ++++---
.../MaterialXGenGlsl/GenGlsl.cpp | 11 +++
.../MaterialXGenShader/GenShaderUtil.cpp | 79 +++++++++++++++++++
.../MaterialXGenShader/GenShaderUtil.h | 3 +
6 files changed, 119 insertions(+), 11 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index de6aa7442f..0d6a64d6b1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -45,6 +45,7 @@ option(MATERIALX_BUILD_GEN_MSL "Build the MSL shader generator back-end." ON)
option(MATERIALX_BUILD_RENDER "Build the MaterialX Render modules." ON)
option(MATERIALX_BUILD_OIIO "Build OpenImageIO support for MaterialXRender." OFF)
option(MATERIALX_BUILD_TESTS "Build unit tests." ON)
+option(MATERIALX_BUILD_BENCHMARK_TESTS "Build benchmark tests." OFF)
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)
@@ -131,6 +132,7 @@ mark_as_advanced(MATERIALX_BUILD_GEN_MSL)
mark_as_advanced(MATERIALX_BUILD_RENDER)
mark_as_advanced(MATERIALX_BUILD_OIIO)
mark_as_advanced(MATERIALX_BUILD_TESTS)
+mark_as_advanced(MATERIALX_BUILD_BENCHMARK_TESTS)
mark_as_advanced(MATERIALX_BUILD_SHARED_LIBS)
mark_as_advanced(MATERIALX_NAMESPACE_SUFFIX)
mark_as_advanced(MATERIALX_LIBNAME_SUFFIX)
@@ -177,6 +179,9 @@ endif()
if(MATERIALX_TEST_RENDER)
add_definitions(-DMATERIALX_TEST_RENDER)
endif()
+if (MATERIALX_BUILD_BENCHMARK_TESTS)
+ add_definitions(-DMATERIALX_BUILD_BENCHMARK_TESTS)
+endif()
if (MATERIALX_BUILD_GEN_MDL)
add_definitions(-DMATERIALX_MDLC_EXECUTABLE=\"${MATERIALX_MDLC_EXECUTABLE}\")
diff --git a/source/MaterialXTest/CMakeLists.txt b/source/MaterialXTest/CMakeLists.txt
index e66db4bd2e..862a176b50 100644
--- a/source/MaterialXTest/CMakeLists.txt
+++ b/source/MaterialXTest/CMakeLists.txt
@@ -121,6 +121,10 @@ set_target_properties(
VERSION "${MATERIALX_LIBRARY_VERSION}"
SOVERSION "${MATERIALX_MAJOR_VERSION}")
+if(MATERIALX_BUILD_BENCHMARK_TESTS)
+ target_compile_definitions(MaterialXTest PRIVATE -DCATCH_CONFIG_ENABLE_BENCHMARKING)
+endif()
+
target_link_libraries(
MaterialXTest
${CMAKE_DL_LIBS})
diff --git a/source/MaterialXTest/External/Catch/catch.hpp b/source/MaterialXTest/External/Catch/catch.hpp
index d2a12427b2..9b309bddc6 100644
--- a/source/MaterialXTest/External/Catch/catch.hpp
+++ b/source/MaterialXTest/External/Catch/catch.hpp
@@ -1,6 +1,6 @@
/*
- * Catch v2.13.9
- * Generated: 2022-04-12 22:37:23.260201
+ * Catch v2.13.10
+ * Generated: 2022-10-16 11:01:23.452308
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved.
@@ -15,7 +15,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 13
-#define CATCH_VERSION_PATCH 9
+#define CATCH_VERSION_PATCH 10
#ifdef __clang__
# pragma clang system_header
@@ -7395,8 +7395,6 @@ namespace Catch {
template
struct ObjectStorage
{
- using TStorage = typename std::aligned_storage::value>::type;
-
ObjectStorage() : data() {}
ObjectStorage(const ObjectStorage& other)
@@ -7439,7 +7437,7 @@ namespace Catch {
return *static_cast(static_cast(&data));
}
- TStorage data;
+ struct { alignas(T) unsigned char data[sizeof(T)]; } data;
};
}
@@ -7949,7 +7947,7 @@ namespace Catch {
#if defined(__i386__) || defined(__x86_64__)
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
#elif defined(__aarch64__)
- #define CATCH_TRAP() __asm__(".inst 0xd4200000")
+ #define CATCH_TRAP() __asm__(".inst 0xd43e0000")
#endif
#elif defined(CATCH_PLATFORM_IPHONE)
@@ -13558,7 +13556,7 @@ namespace Catch {
// Handle list request
if( Option listed = list( m_config ) )
- return static_cast( *listed );
+ return (std::min) (MaxExitCode, static_cast(*listed));
TestGroup tests { m_config };
auto const totals = tests.execute();
@@ -15391,7 +15389,7 @@ namespace Catch {
}
Version const& libraryVersion() {
- static Version version( 2, 13, 9, "", 0 );
+ static Version version( 2, 13, 10, "", 0 );
return version;
}
@@ -17526,12 +17524,20 @@ namespace Catch {
#ifndef __OBJC__
+#ifndef CATCH_INTERNAL_CDECL
+#ifdef _MSC_VER
+#define CATCH_INTERNAL_CDECL __cdecl
+#else
+#define CATCH_INTERNAL_CDECL
+#endif
+#endif
+
#if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
// Standard C/C++ Win32 Unicode wmain entry point
-extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
+extern "C" int CATCH_INTERNAL_CDECL wmain (int argc, wchar_t * argv[], wchar_t * []) {
#else
// Standard C/C++ main entry point
-int main (int argc, char * argv[]) {
+int CATCH_INTERNAL_CDECL main (int argc, char * argv[]) {
#endif
return Catch::Session().run( argc, argv );
diff --git a/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp b/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp
index 339d3853cb..2cc4d7ccf4 100644
--- a/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp
+++ b/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp
@@ -119,6 +119,17 @@ TEST_CASE("GenShader: Bind Light Shaders", "[genglsl]")
REQUIRE_NOTHROW(mx::HwShaderGenerator::bindLightShader(*spotLightShader, 66, context));
}
+#ifdef MATERIALX_BUILD_BENCHMARK_TESTS
+TEST_CASE("GenShader: Performance Test", "[genglsl]")
+{
+ mx::GenContext context(mx::GlslShaderGenerator::create());
+ BENCHMARK("Load documents, validate and generate shader")
+ {
+ return GenShaderUtil::shaderGenPerformanceTest(context);
+ };
+}
+#endif
+
enum class GlslType
{
Glsl400,
diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp
index 261aacdefe..2ca8afa86c 100644
--- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp
+++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp
@@ -314,6 +314,85 @@ void testUniqueNames(mx::GenContext& context, const std::string& stage)
REQUIRE(sgNode1->getOutput()->getVariable() == "unique_names_out");
}
+// Test ShaderGen performance
+void shaderGenPerformanceTest(mx::GenContext& context)
+{
+ mx::DocumentPtr nodeLibrary = mx::createDocument();
+ mx::FilePath currentPath = mx::FilePath::getCurrentPath();
+ const mx::FileSearchPath libSearchPath(currentPath);
+
+ // Load the standard libraries.
+ loadLibraries({ "libraries" }, libSearchPath, nodeLibrary);
+ context.registerSourceCodeSearchPath(libSearchPath);
+
+ // Enable Color Management
+ mx::ColorManagementSystemPtr colorManagementSystem =
+ mx::DefaultColorManagementSystem::create(context.getShaderGenerator().getTarget());
+
+ REQUIRE(colorManagementSystem);
+ if (colorManagementSystem)
+ {
+ context.getShaderGenerator().setColorManagementSystem(colorManagementSystem);
+ colorManagementSystem->loadLibrary(nodeLibrary);
+ }
+
+ // Enable Unit System
+ mx::UnitSystemPtr unitSystem = mx::UnitSystem::create(context.getShaderGenerator().getTarget());
+ REQUIRE(unitSystem);
+ if (unitSystem)
+ {
+ context.getShaderGenerator().setUnitSystem(unitSystem);
+ unitSystem->loadLibrary(nodeLibrary);
+ // Setup Unit converters
+ unitSystem->setUnitConverterRegistry(mx::UnitConverterRegistry::create());
+ mx::UnitTypeDefPtr distanceTypeDef = nodeLibrary->getUnitTypeDef("distance");
+ unitSystem->getUnitConverterRegistry()->addUnitConverter(distanceTypeDef, mx::LinearUnitConverter::create(distanceTypeDef));
+ mx::UnitTypeDefPtr angleTypeDef = nodeLibrary->getUnitTypeDef("angle");
+ unitSystem->getUnitConverterRegistry()->addUnitConverter(angleTypeDef, mx::LinearUnitConverter::create(angleTypeDef));
+ context.getOptions().targetDistanceUnit = "meter";
+ }
+
+ // Read mtlx documents
+ mx::FilePathVec testRootPaths;
+ testRootPaths.push_back("resources/Materials/Examples/StandardSurface");
+
+ std::vector loadedDocuments;
+ mx::StringVec documentsPaths;
+ mx::StringVec errorLog;
+
+ for (const auto& testRoot : testRootPaths)
+ {
+ mx::loadDocuments(testRoot, libSearchPath, {}, {}, loadedDocuments, documentsPaths,
+ nullptr, &errorLog);
+ }
+
+ REQUIRE(loadedDocuments.size() > 0);
+ REQUIRE(loadedDocuments.size() == documentsPaths.size());
+
+ // Shuffle the order of documents and perform document library import validatation and shadergen
+ std::random_device random_dev;
+ std::mt19937 generator(random_dev());
+ std::shuffle(loadedDocuments.begin(), loadedDocuments.end(), generator);
+ for (const auto& doc : loadedDocuments)
+ {
+ doc->importLibrary(nodeLibrary);
+ std::vector elements = mx::findRenderableElements(doc);
+
+ REQUIRE(elements.size() > 0);
+
+ std::string message;
+ bool docValid = doc->validate(&message);
+
+ REQUIRE(docValid == true);
+
+ mx::StringVec sourceCode;
+ mx::ShaderPtr shader = nullptr;
+ shader = context.getShaderGenerator().generate(elements[0]->getName(), elements[0], context);
+
+ REQUIRE(shader != nullptr);
+ REQUIRE(shader->getSourceCode(mx::Stage::PIXEL).length() > 0);
+ }
+}
void ShaderGeneratorTester::checkImplementationUsage(const mx::StringSet& usedImpls,
const mx::GenContext& context,
diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h
index ea34170d71..9c471466aa 100644
--- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h
+++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h
@@ -52,6 +52,9 @@ void checkImplementations(mx::GenContext& context,
// Utility test to check unique name generation on a shader generator
void testUniqueNames(mx::GenContext& context, const std::string& stage);
+// Utility to perfrom simple performance test to load, validate and generate shaders
+void shaderGenPerformanceTest(mx::GenContext& context);
+
//
// Render validation options. Reflects the _options.mtlx
// file in the test suite area.