diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..1481282 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,233 @@ +name: build + +on: + push: + branches: [ master ] + tags: + - v* + pull_request: + branches: [ master ] + +env: + BUILD_TYPE: Release + +jobs: + # + # Windows + # + # __ + # |\__/ \ + # | | + # | __ | + # \__/ \| + # + # + maya-win: + runs-on: windows-2019 + + strategy: + # Without this, all containers stop if any fail + # That's bad, we want to know whether it's only one + # or if it happens to multiples or all. + fail-fast: false + + matrix: + include: + - maya: "2018" + devkit: "https://autodesk-adn-transfer.s3-us-west-2.amazonaws.com/ADN+Extranet/M%26E/Maya/devkit+2018/Autodesk_Maya_2018_7_Update_DEVKIT_Windows.zip" + - maya: "2019" + devkit: "https://autodesk-adn-transfer.s3-us-west-2.amazonaws.com/ADN+Extranet/M%26E/Maya/devkit+2019/Autodesk_Maya_2019_3_Update_DEVKIT_Windows.zip" + - maya: "2020" + devkit: "https://autodesk-adn-transfer.s3-us-west-2.amazonaws.com/ADN+Extranet/M%26E/Maya/devkit+2020/Autodesk_Maya_2020_4_Update_DEVKIT_Windows.zip" + - maya: "2022" + devkit: "https://autodesk-adn-transfer.s3-us-west-2.amazonaws.com/ADN+Extranet/M%26E/Maya/devkit+2022/Autodesk_Maya_2022_3_Update_DEVKIT_Windows.zip" + - maya: "2023" + devkit: "https://autodesk-adn-transfer.s3-us-west-2.amazonaws.com/ADN+Extranet/M%26E/Maya/devkit+2023/Autodesk_Maya_2023_DEVKIT_Windows.zip" + + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + submodules: true + + - name: Install devkit + run: | + Write-Host "Downloading Devkit: ${{matrix.devkit}}..." + Invoke-WebRequest -Uri ${{matrix.devkit}} -OutFile "$pwd/devkit.zip" + Write-Host "Extracting devkit.zip.." + Expand-Archive -LiteralPath devkit.zip -DestinationPath $pwd + + - name: Configure CMake + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DMAYA_VERSION="${{matrix.maya}}" -DMAYA_DEVKIT_BASE="$pwd/devkitBase" + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + + - name: Repath Artifacts + run: | + mkdir artifacts/plug-ins + Copy-Item "./build/${{env.BUILD_TYPE}}/BlurRelax.mll" -Destination "artifacts/plug-ins" + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: windows-${{matrix.maya}} + path: | + artifacts/plug-ins/BlurRelax.mll + + maya-macos: + runs-on: macos-10.15 + + strategy: + fail-fast: false + + matrix: + include: + - maya: "2018" + devkit: "https://autodesk-adn-transfer.s3-us-west-2.amazonaws.com/ADN+Extranet/M%26E/Maya/devkit+2018/Autodesk_Maya_2018_7_Update_DEVKIT_Mac.dmg" + - maya: "2019" + devkit: "https://autodesk-adn-transfer.s3-us-west-2.amazonaws.com/ADN+Extranet/M%26E/Maya/devkit+2019/Autodesk_Maya_2019_3_Update_DEVKIT_Mac.dmg" + - maya: "2020" + devkit: "https://autodesk-adn-transfer.s3-us-west-2.amazonaws.com/ADN+Extranet/M%26E/Maya/devkit+2020/Autodesk_Maya_2020_4_Update_DEVKIT_Mac.dmg" + - maya: "2022" + devkit: "https://autodesk-adn-transfer.s3-us-west-2.amazonaws.com/ADN+Extranet/M%26E/Maya/devkit+2022/Autodesk_Maya_2022_3_Update_DEVKIT_Mac.dmg" + - maya: "2023" + devkit: "https://autodesk-adn-transfer.s3-us-west-2.amazonaws.com/ADN+Extranet/M%26E/Maya/devkit+2023/Autodesk_Maya_2023_DEVKIT_Mac.dmg" + + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + submodules: true + + - name: Install devkit + run: | + curl -o devkit.dmg ${{matrix.devkit}} + 7z x devkit.dmg + + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: '10.3' + + - name: Configure CMake + run: | + cmake -G Xcode -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DMAYA_VERSION=${{matrix.maya}} -DMAYA_DEVKIT_BASE="$PWD/devkitBase" + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + + - name: Repath Artifacts + run: | + mkdir -p artifacts/plug-ins + cp ./build/${{env.BUILD_TYPE}}/BlurRelax.bundle artifacts/plug-ins + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: mac-${{matrix.maya}} + path: | + artifacts/plug-ins/BlurRelax.bundle + + maya-linux: + runs-on: ubuntu-latest + container: scottenglert/maya-build:${{matrix.maya}} + + strategy: + fail-fast: false + + matrix: + include: + - maya: "2018.7" + year: "2018" + - maya: "2019.3" + year: "2019" + - maya: "2020.4" + year: "2020" + - maya: "2022.3" + year: "2022" + - maya: "2023" + year: "2023" + + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + submodules: true + + - name: Configure CMake + run: | + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DMAYA_VERSION=${{matrix.maya}} -DMAYA_DEVKIT_BASE="/usr/autodesk/devkitBase" .. + + - name: Build + run: cmake --build ./build --config ${{env.BUILD_TYPE}} + + - name: Repath Artifacts + run: | + mkdir -p artifacts/plug-ins + cp ./build/BlurRelax.so artifacts/plug-ins + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: linux-${{matrix.year}} + path: | + artifacts/plug-ins/BlurRelax.so + +# +# Shipping +# +# _________ +# |\ _ _ _ _\ +# | \________\ +# | | | +# | | | +# \|________| +# +# + upload_release: + name: Upload release + needs: [maya-win, maya-linux, maya-macos] + runs-on: ubuntu-latest + + # Only run on e.g. v0.1.0 + if: startsWith(github.ref, 'refs/tags/v') + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Download artifacts + uses: actions/download-artifact@v3 + + # Omitting name: means "download all artifacts" + # Destination directory structure: + # ~/modules + # /BlurRelax + # /- + # /plug-ins + # BlurRelax.mll + # /BlurRelax.mod + + with: + path: modules/BlurRelax + + - name: Set env + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + + - name: Create distribution + run: | + cp ./BlurRelax.mod modules/ + mkdir -p modules/BlurRelax/scripts + cp -r ./scripts modules/BlurRelax + zip -r BlurRelax-${{env.RELEASE_VERSION}}.zip modules/ + + - name: Upload distribution + uses: "marvinpinto/action-automatic-releases@latest" + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: "latest" + prerelease: false + files: | + BlurRelax-*.zip diff --git a/BlurRelax.mod b/BlurRelax.mod new file mode 100644 index 0000000..58a858c --- /dev/null +++ b/BlurRelax.mod @@ -0,0 +1,44 @@ ++ PLATFORM:win64 MAYAVERSION:2018 BlurRelax 1.0.0 BlurRelax +plug-ins: windows-2018/plug-ins + ++ PLATFORM:linux MAYAVERSION:2018 BlurRelax 1.0.0 BlurRelax +plug-ins: linux-2018/plug-ins + ++ PLATFORM:mac MAYAVERSION:2018 BlurRelax 1.0.0 BlurRelax +plug-ins: mac-2018/plug-ins + ++ PLATFORM:win64 MAYAVERSION:2019 BlurRelax 1.0.0 BlurRelax +plug-ins: windows-2019/plug-ins + ++ PLATFORM:linux MAYAVERSION:2019 BlurRelax 1.0.0 BlurRelax +plug-ins: linux-2019/plug-ins + ++ PLATFORM:mac MAYAVERSION:2019 BlurRelax 1.0.0 BlurRelax +plug-ins: mac-2019/plug-ins + ++ PLATFORM:win64 MAYAVERSION:2020 BlurRelax 1.0.0 BlurRelax +plug-ins: windows-2020/plug-ins + ++ PLATFORM:linux MAYAVERSION:2020 BlurRelax 1.0.0 BlurRelax +plug-ins: linux-2020/plug-ins + ++ PLATFORM:mac MAYAVERSION:2020 BlurRelax 1.0.0 BlurRelax +plug-ins: mac-2020/plug-ins + ++ PLATFORM:win64 MAYAVERSION:2022 BlurRelax 1.0.0 BlurRelax +plug-ins: windows-2022/plug-ins + ++ PLATFORM:linux MAYAVERSION:2022 BlurRelax 1.0.0 BlurRelax +plug-ins: linux-2022/plug-ins + ++ PLATFORM:mac MAYAVERSION:2022 BlurRelax 1.0.0 BlurRelax +plug-ins: mac-2022/plug-ins + ++ PLATFORM:win64 MAYAVERSION:2023 BlurRelax 1.0.0 BlurRelax +plug-ins: windows-2023/plug-ins + ++ PLATFORM:linux MAYAVERSION:2023 BlurRelax 1.0.0 BlurRelax +plug-ins: linux-2023/plug-ins + ++ PLATFORM:mac MAYAVERSION:2023 BlurRelax 1.0.0 BlurRelax +plug-ins: mac-2023/plug-ins diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ec60d2..9d5311c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,28 +1,36 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.9) -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/modules) +project( + "BlurRelax" + VERSION 1.0 + DESCRIPTION "A quick smooth with border conditions" + LANGUAGES CXX +) -project(BlurRelax) -set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME}) -find_package(Maya REQUIRED) -find_package(OpenGL REQUIRED) -set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/../output/Maya${MAYA_VERSION}) +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +set(CMAKE_CXX_STANDARD 14) -set(SOURCE_FILES - "src/blurRelaxNode.cpp" +# (defined in FindMaya.cmake, copied here for reference) +# set(MAYA_INSTALL_BASE_PATH "" CACHE STRING +# "Root path containing your maya installations, e.g. /usr/autodesk or /Applications/Autodesk/" +# ) +set(MAYA_VERSION 2020 CACHE STRING "Maya version") + +set(MAYA_FILES "src/blurRelaxNode.h" - "src/fastRelax.cpp" + "src/fastMayaRelax.h" "src/fastRelax.h" + "src/blurRelaxNode.cpp" "src/fastMayaRelax.cpp" - "src/fastMayaRelax.h" + "src/fastRelax.cpp" "src/pluginRegister.cpp" ) -include_directories(${MAYA_INCLUDE_DIR}) -link_directories(${MAYA_LIBRARY_DIR}) -add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} ${MAYA_LIBRARIES} ${OPENGL_LIBRARY}) - +find_package(Maya REQUIRED) +add_library(${PROJECT_NAME} SHARED ${MAYA_FILES}) +target_link_libraries(${PROJECT_NAME} PRIVATE Maya::Maya) +target_include_directories(${PROJECT_NAME} + PRIVATE Maya::Maya + PUBLIC "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" +) MAYA_PLUGIN(${PROJECT_NAME}) -install(TARGETS ${PROJECT_NAME} ${MAYA_TARGET_TYPE} DESTINATION plug-ins) - diff --git a/cmake/FindMaya.cmake b/cmake/FindMaya.cmake new file mode 100644 index 0000000..1871ea6 --- /dev/null +++ b/cmake/FindMaya.cmake @@ -0,0 +1,163 @@ +# Copyright 2017 Chad Vernon +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +# associated documentation files (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, publish, distribute, +# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all copies or +# substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#.rst: +# FindMaya +# -------- +# +# Find Maya headers and libraries. +# +# Imported targets +# ^^^^^^^^^^^^^^^^ +# +# This module defines the following :prop_tgt:`IMPORTED` target: +# +# ``Maya::Maya`` +# The Maya libraries, if found. +# +# Result variables +# ^^^^^^^^^^^^^^^^ +# +# This module will set the following variables in your project: +# +# ``Maya_FOUND`` +# Defined if a Maya installation has been detected +# ``MAYA_INCLUDE_DIR`` +# Where to find the headers (maya/MFn.h) +# ``MAYA_LIBRARIES`` +# All the Maya libraries. +# + +# Set a default Maya version if not specified +if(NOT DEFINED MAYA_VERSION) + set(MAYA_VERSION 2017 CACHE STRING "Maya version") +endif() + +# OS Specific environment setup +set(MAYA_COMPILE_DEFINITIONS "REQUIRE_IOSTREAM;_BOOL") +set(MAYA_INSTALL_BASE_SUFFIX "") +set(MAYA_TARGET_TYPE LIBRARY) +if(WIN32) + # Windows + set(MAYA_INSTALL_BASE_DEFAULT "C:/Program Files/Autodesk") + set(MAYA_COMPILE_DEFINITIONS "${MAYA_COMPILE_DEFINITIONS};NT_PLUGIN") + set(MAYA_PLUGIN_EXTENSION ".mll") + set(MAYA_TARGET_TYPE RUNTIME) +elseif(APPLE) + # Apple + set(MAYA_INSTALL_BASE_DEFAULT /Applications/Autodesk) + set(MAYA_COMPILE_DEFINITIONS "${MAYA_COMPILE_DEFINITIONS};OSMac_") + set(MAYA_PLUGIN_EXTENSION ".bundle") +else() + # Linux + set(MAYA_COMPILE_DEFINITIONS "${MAYA_COMPILE_DEFINITIONS};LINUX") + set(MAYA_INSTALL_BASE_DEFAULT /usr/autodesk) + + if(MAYA_VERSION LESS 2016) + # Pre Maya 2016 on Linux + set(MAYA_INSTALL_BASE_SUFFIX -x64) + endif() + set(MAYA_PLUGIN_EXTENSION ".so") +endif() + +set(MAYA_INSTALL_BASE_PATH ${MAYA_INSTALL_BASE_DEFAULT} CACHE STRING + "Root path containing your maya installations, e.g. /usr/autodesk or /Applications/Autodesk/") + +if(NOT DEFINED MAYA_DEVKIT_BASE) + set(MAYA_LOCATION ${MAYA_INSTALL_BASE_PATH}/maya${MAYA_VERSION}${MAYA_INSTALL_BASE_SUFFIX}) +else() + set(MAYA_LOCATION ${MAYA_DEVKIT_BASE}) +endif() + +#set(CMAKE_FIND_DEBUG_MODE TRUE) +# Maya include directory +find_path(MAYA_INCLUDE_DIR maya/MFn.h + PATHS + ${MAYA_LOCATION} + $ENV{MAYA_LOCATION} + PATH_SUFFIXES + "include/" + "devkit/include/" +) + +find_library(MAYA_LIBRARY + NAMES + OpenMaya + PATHS + ${MAYA_LOCATION} + $ENV{MAYA_LOCATION} + PATH_SUFFIXES + "lib/" + "Maya.app/Contents/MacOS/" + NO_DEFAULT_PATH +) +#set(CMAKE_FIND_DEBUG_MODE FALSE) + +set(MAYA_LIBRARIES "${MAYA_LIBRARY}") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Maya + REQUIRED_VARS MAYA_INCLUDE_DIR MAYA_LIBRARY) +mark_as_advanced(MAYA_INCLUDE_DIR MAYA_LIBRARY) + +if (NOT TARGET Maya::Maya) + add_library(Maya::Maya UNKNOWN IMPORTED) + set_target_properties(Maya::Maya PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "${MAYA_COMPILE_DEFINITIONS}" + INTERFACE_INCLUDE_DIRECTORIES "${MAYA_INCLUDE_DIR}" + IMPORTED_LOCATION "${MAYA_LIBRARY}") + + if (APPLE AND ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND MAYA_VERSION LESS 2017) + # Clang and Maya 2016 and older needs to use libstdc++ + set_target_properties(Maya::Maya PROPERTIES + INTERFACE_COMPILE_OPTIONS "-std=c++0x;-stdlib=libstdc++") + endif () +endif() + +# Add the other Maya libraries into the main Maya::Maya library +set(_MAYA_LIBRARIES OpenMayaAnim OpenMayaFX OpenMayaRender OpenMayaUI Foundation clew) +foreach(MAYA_LIB ${_MAYA_LIBRARIES}) + find_library(MAYA_${MAYA_LIB}_LIBRARY + NAMES + ${MAYA_LIB} + PATHS + ${MAYA_LOCATION} + $ENV{MAYA_LOCATION} + PATH_SUFFIXES + "lib/" + "Maya.app/Contents/MacOS/" + NO_DEFAULT_PATH) + mark_as_advanced(MAYA_${MAYA_LIB}_LIBRARY) + if (MAYA_${MAYA_LIB}_LIBRARY) + add_library(Maya::${MAYA_LIB} UNKNOWN IMPORTED) + set_target_properties(Maya::${MAYA_LIB} PROPERTIES + IMPORTED_LOCATION "${MAYA_${MAYA_LIB}_LIBRARY}") + set_property(TARGET Maya::Maya APPEND PROPERTY + INTERFACE_LINK_LIBRARIES Maya::${MAYA_LIB}) + set(MAYA_LIBRARIES ${MAYA_LIBRARIES} "${MAYA_${MAYA_LIB}_LIBRARY}") + endif() +endforeach() + +function(MAYA_PLUGIN _target) + if (WIN32) + set_target_properties(${_target} PROPERTIES + LINK_FLAGS "/export:initializePlugin /export:uninitializePlugin") + endif() + set_target_properties(${_target} PROPERTIES + PREFIX "" + SUFFIX ${MAYA_PLUGIN_EXTENSION}) +endfunction() diff --git a/mayaConfigure.bat b/mayaConfigure.bat index 11fac34..4edc786 100644 --- a/mayaConfigure.bat +++ b/mayaConfigure.bat @@ -1,8 +1,8 @@ setlocal SET BUILD=mayabuild -SET MAYA_VERSION=2018 -SET COMPILER=Visual Studio 15 2017 Win64 +SET MAYA_VERSION=2020 +SET COMPILER=Visual Studio 16 2019 SET PFX=%~dp0 cd %PFX% @@ -14,6 +14,6 @@ cmake ^ -DMAYA_VERSION=%MAYA_VERSION% ^ -G "%COMPILER%" ..\ -REM cmake --build . --config Release --target INSTALL +cmake --build . --config Release pause diff --git a/modules/FindMaya.cmake b/modules/FindMaya.cmake deleted file mode 100644 index d6fff9c..0000000 --- a/modules/FindMaya.cmake +++ /dev/null @@ -1,127 +0,0 @@ -# The MIT License (MIT) -# -# Copyright (c) 2015 Chad Vernon -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -# - Maya finder module -# -# Variables that will be defined: -# MAYA_FOUND Defined if a Maya installation has been detected -# MAYA_EXECUTABLE Path to Maya's executable -# MAYA__FOUND Defined if has been found -# MAYA__LIBRARY Path to library -# MAYA_INCLUDE_DIR Path to the devkit's include directories -# MAYA_LIBRARIES All the Maya libraries -# - -# Set a default Maya version if not specified -if(NOT DEFINED MAYA_VERSION) - set(MAYA_VERSION 2016 CACHE STRING "Maya version") -endif() - -# OS Specific environment setup -set(MAYA_COMPILE_DEFINITIONS "REQUIRE_IOSTREAM;_BOOL") -set(MAYA_INSTALL_BASE_SUFFIX "") -set(MAYA_INC_SUFFIX "include") -set(MAYA_LIB_SUFFIX "lib") -set(MAYA_BIN_SUFFIX "bin") -set(MAYA_TARGET_TYPE LIBRARY) -if(WIN32) - # Windows - set(MAYA_INSTALL_BASE_DEFAULT "C:/Program Files/Autodesk") - set(MAYA_COMPILE_DEFINITIONS "${MAYA_COMPILE_DEFINITIONS};NT_PLUGIN") - set(OPENMAYA OpenMaya.lib) - set(MAYA_PLUGIN_EXTENSION ".mll") - set(MAYA_TARGET_TYPE RUNTIME) -elseif(APPLE) - # Apple - set(MAYA_INSTALL_BASE_DEFAULT /Applications/Autodesk) - set(MAYA_INC_SUFFIX "devkit/include") - set(MAYA_LIB_SUFFIX "Maya.app/Contents/MacOS") - set(MAYA_BIN_SUFFIX "Maya.app/Contents/bin/") - set(MAYA_COMPILE_DEFINITIONS "${MAYA_COMPILE_DEFINITIONS};OSMac_") - set(OPENMAYA libOpenMaya.dylib) - set(MAYA_PLUGIN_EXTENSION ".bundle") -else() - # Linux - set(MAYA_COMPILE_DEFINITIONS "${MAYA_COMPILE_DEFINITIONS};LINUX") - set(MAYA_INSTALL_BASE_DEFAULT /usr/autodesk) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") - if(MAYA_VERSION LESS 2016) - SET(MAYA_INSTALL_BASE_SUFFIX -x64) - endif() - set(OPENMAYA libOpenMaya.so) - set(MAYA_PLUGIN_EXTENSION ".so") -endif() - -set(MAYA_INSTALL_BASE_PATH ${MAYA_INSTALL_BASE_DEFAULT} CACHE STRING - "Root path containing your maya installations, e.g. /usr/autodesk or /Applications/Autodesk/") - -set(MAYA_LOCATION ${MAYA_INSTALL_BASE_PATH}/Maya${MAYA_VERSION}${MAYA_INSTALL_BASE_SUFFIX}) - -# Maya library directory -find_path(MAYA_LIBRARY_DIR ${OPENMAYA} - PATHS - ${MAYA_LOCATION} - $ENV{MAYA_LOCATION} - PATH_SUFFIXES - "${MAYA_LIB_SUFFIX}/" - DOC "Maya library path" -) - -# Maya include directory -find_path(MAYA_INCLUDE_DIR maya/MFn.h - PATHS - ${MAYA_LOCATION} - $ENV{MAYA_LOCATION} - PATH_SUFFIXES - "${MAYA_INC_SUFFIX}/" - DOC "Maya include path" -) - -# Maya libraries -set(_MAYA_LIBRARIES OpenMaya OpenMayaAnim OpenMayaFX OpenMayaRender OpenMayaUI Foundation clew) -foreach(MAYA_LIB ${_MAYA_LIBRARIES}) - find_library(MAYA_${MAYA_LIB}_LIBRARY NAMES ${MAYA_LIB} PATHS ${MAYA_LIBRARY_DIR} - NO_DEFAULT_PATH) - if (MAYA_${MAYA_LIB}_LIBRARY) - set(MAYA_LIBRARIES ${MAYA_LIBRARIES} ${MAYA_${MAYA_LIB}_LIBRARY}) - endif() -endforeach() - -if (APPLE AND ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") - # Clang and Maya needs to use libstdc++ - set(MAYA_CXX_FLAGS "-std=c++0x -stdlib=libstdc++") -endif() - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Maya DEFAULT_MSG MAYA_INCLUDE_DIR MAYA_LIBRARIES) - -function(MAYA_PLUGIN _target) - if (WIN32) - set_target_properties(${_target} PROPERTIES - LINK_FLAGS "/export:initializePlugin /export:uninitializePlugin" - ) - endif() - set_target_properties(${_target} PROPERTIES - COMPILE_DEFINITIONS "${MAYA_COMPILE_DEFINITIONS}" - PREFIX "" - SUFFIX ${MAYA_PLUGIN_EXTENSION}) -endfunction() diff --git a/scripts/BlurRelax/__init__.py b/scripts/BlurRelax/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scripts/BlurRelax/menu.py b/scripts/BlurRelax/menu.py new file mode 100644 index 0000000..72ad09d --- /dev/null +++ b/scripts/BlurRelax/menu.py @@ -0,0 +1,377 @@ +import maya.cmds as cmds +import maya.mel as mel +import os + +from PySide2 import QtGui + +NAME_WIDGET = 'BlurRelax_name' +RADIUS_WIDGET = 'BlurRelax_radius' +NEW_BIND_MESH_WIDGET = 'BlurRelax_newbindmesh' +BIND_FILE_WIDGET = 'BlurRelax_bindfile' + + +BORDER_DDL = "BlurRelax_border_ddl" +HARD_DDL = "BlurRelax_hard_ddl" +GROUP_DDL = "BlurRelax_group_ddl" +REPROJ_CHK = "BlurRelax_reproj_chk" +REPROJ_SLD = "BlurRelax_reproj_sld" +PRESERVE_VOL_SLD = "BlurRelax_preserve_vol_sld" +ITERATIONS_SLD = "BlurRelax_iterations_sld" +DELTA_CHK = "BlurRelax_delta_chk" +DELTA_SLD = "BlurRelax_delta_sld" + +WIDGET_NAMES = ( + BORDER_DDL, + HARD_DDL, + GROUP_DDL, + REPROJ_CHK, + REPROJ_SLD, + PRESERVE_VOL_SLD, + ITERATIONS_SLD, + DELTA_CHK, + DELTA_SLD, +) +MENU_ITEMS = [] + + +def create_menuitems(): + global MENU_ITEMS + if MENU_ITEMS: + # Already created + return + if cmds.about(api=True) < 201600: + cmds.warning('BlurRelax menus only available in Maya 2016 and higher.') + return + for menu in ['mainDeformMenu', 'mainRigDeformationsMenu']: + # Make sure the menu widgets exist first. + mel.eval('ChaDeformationsMenu MayaWindow|{0};'.format(menu)) + items = cmds.menu(menu, query=True, itemArray=True) + for item in items: + if cmds.menuItem(item, query=True, divider=True): + section = cmds.menuItem(item, query=True, label=True) + menu_label = cmds.menuItem(item, query=True, label=True) + if menu_label == 'Delta Mush': + if section == 'Create': + BlurRelax_item = cmds.menuItem( + label="BlurRelax", + command=create_blur_relax, + sourceType='python', + insertAfter=item, + parent=menu, + ) + BlurRelax_options = cmds.menuItem( + command=display_blur_relax_options, + insertAfter=BlurRelax_item, + parent=menu, + optionBox=True, + ) + MENU_ITEMS.append(BlurRelax_item) + MENU_ITEMS.append(BlurRelax_options) + elif menu_label == 'Delta Mush' and section == 'Paint Weights': + item = cmds.menuItem( + label="BlurRelax", + command=paint_blur_relax_weights, + sourceType='python', + insertAfter=item, + parent=menu, + ) + MENU_ITEMS.append(item) + + +def create_blur_relax(*args, **kwargs): + cmds.loadPlugin('BlurRelax', quiet=True) + nodes = cmds.deformer(type="BlurRelax") + kwargs = get_create_command_kwargs() + for node in nodes: + for attr, value in kwargs.items(): + cmds.setAttr("{0}.{1}".format(node, attr), value) + + +def get_create_command_kwargs(): + """Gets the BlurRelax command arguments either from the option box widgets or the saved + option vars. If the widgets exist, their values will be saved to the option vars. + @return A dictionary of the kwargs to the BlurRelax command.""" + kwargs = {} + + if cmds.optionMenu(BORDER_DDL, exists=True): + # The index is 1-based + val = cmds.optionMenu(BORDER_DDL, query=True, select=True) - 1 + kwargs['borderBehavior'] = val + cmds.optionVar(intValue=(BORDER_DDL, val)) + else: + kwargs['borderBehavior'] = cmds.optionVar(query=BORDER_DDL) + + if cmds.optionMenu(HARD_DDL, exists=True): + # The index is 1-based + val = cmds.optionMenu(HARD_DDL, query=True, select=True) - 1 + kwargs['hardEdgeBehavior'] = val + cmds.optionVar(intValue=(HARD_DDL, val)) + else: + kwargs['hardEdgeBehavior'] = cmds.optionVar(query=HARD_DDL) + + if cmds.optionMenu(GROUP_DDL, exists=True): + # The index is 1-based + val = cmds.optionMenu(GROUP_DDL, query=True, select=True) - 1 + kwargs['groupEdgeBehavior'] = val + cmds.optionVar(intValue=(GROUP_DDL, val)) + else: + kwargs['groupEdgeBehavior'] = cmds.optionVar(query=GROUP_DDL) + + if cmds.checkBoxGrp(REPROJ_CHK, exists=True): + val = cmds.checkBoxGrp(REPROJ_CHK, query=True, value1=True) + kwargs['reproject'] = bool(val) + cmds.optionVar(intValue=(REPROJ_CHK, int(val))) + else: + kwargs['reproject'] = bool(cmds.optionVar(query=REPROJ_CHK)) + + if cmds.checkBoxGrp(DELTA_CHK, exists=True): + val = cmds.checkBoxGrp(DELTA_CHK, query=True, value1=True) + kwargs['delta'] = bool(val) + cmds.optionVar(intValue=(DELTA_CHK, int(val))) + else: + kwargs['delta'] = bool(cmds.optionVar(query=DELTA_CHK)) + + if cmds.floatSliderGrp(REPROJ_SLD, exists=True): + val = cmds.floatSliderGrp(REPROJ_SLD, query=True, value=True) + kwargs['reprojectDivs'] = val + cmds.optionVar(floatValue=(REPROJ_SLD, val)) + else: + kwargs['reprojectDivs'] = cmds.optionVar(query=REPROJ_SLD) + + if cmds.floatSliderGrp(PRESERVE_VOL_SLD, exists=True): + val = cmds.floatSliderGrp(PRESERVE_VOL_SLD, query=True, value=True) + kwargs['preserveVolume'] = val + cmds.optionVar(floatValue=(PRESERVE_VOL_SLD, val)) + else: + kwargs['preserveVolume'] = cmds.optionVar(query=PRESERVE_VOL_SLD) + + if cmds.floatSliderGrp(ITERATIONS_SLD, exists=True): + val = cmds.floatSliderGrp(ITERATIONS_SLD, query=True, value=True) + kwargs['iterations'] = val + cmds.optionVar(floatValue=(ITERATIONS_SLD, val)) + else: + kwargs['iterations'] = cmds.optionVar(query=ITERATIONS_SLD) + + if cmds.floatSliderGrp(DELTA_SLD, exists=True): + val = cmds.floatSliderGrp(DELTA_SLD, query=True, value=True) + kwargs['deltaMultiplier'] = val + cmds.optionVar(floatValue=(DELTA_SLD, val)) + else: + kwargs['deltaMultiplier'] = cmds.optionVar(query=DELTA_SLD) + + return kwargs + + + +def display_blur_relax_options(*args, **kwargs): + cmds.loadPlugin('BlurRelax', qt=True) + layout = mel.eval('getOptionBox') + cmds.setParent(layout) + cmds.columnLayout(adj=True) + + for widget in WIDGET_NAMES: + # Delete the widgets so we don't create multiple controls with the same name + try: + cmds.deleteUI(widget, control=True) + except RuntimeError: + pass + + if not cmds.optionVar(exists=BORDER_DDL): + init_option_vars() + + pinBehaviors = ["None", "Pin", "Slide"] + + cmds.optionMenu(BORDER_DDL, label="Border Behavior") + for b in pinBehaviors: + cmds.menuItem(label=b, parent=BORDER_DDL) + cmds.optionMenu( + BORDER_DDL, edit=True, value=pinBehaviors[cmds.optionVar(query=BORDER_DDL)] + ) + + cmds.optionMenu(HARD_DDL, label="Hard Edge Behavior") + for b in pinBehaviors: + cmds.menuItem(label=b, parent=HARD_DDL) + cmds.optionMenu( + HARD_DDL, edit=True, value=pinBehaviors[cmds.optionVar(query=HARD_DDL)] + ) + + cmds.optionMenu(GROUP_DDL, label="Group Edge Behavior") + for b in pinBehaviors: + cmds.menuItem(label=b, parent=GROUP_DDL) + cmds.optionMenu( + GROUP_DDL, edit=True, value=pinBehaviors[cmds.optionVar(query=GROUP_DDL)] + ) + + cmds.checkBoxGrp( + REPROJ_CHK, + numberOfCheckBoxes=1, + label='reproject', + value1=cmds.optionVar(query=REPROJ_CHK), + ) + + cmds.floatSliderGrp( + REPROJ_SLD, + label='Reproject Divs', + field=True, + minValue=0, + maxValue=3, + fieldMinValue=0, + fieldMaxValue=3, + step=1, + precision=0, + value=cmds.optionVar(query=REPROJ_SLD), + ) + + cmds.floatSliderGrp( + PRESERVE_VOL_SLD, + label='Preserve Volume', + field=True, + minValue=0.0, + maxValue=2.0, + fieldMinValue=0.0, + fieldMaxValue=2.0, + step=0.01, + precision=2, + value=cmds.optionVar(query=PRESERVE_VOL_SLD), + ) + + cmds.floatSliderGrp( + ITERATIONS_SLD, + label='Iterations', + field=True, + minValue=0.0, + maxValue=50.0, + fieldMinValue=0.0, + fieldMaxValue=1000.0, + step=0.1, + precision=1, + value=cmds.optionVar(query=ITERATIONS_SLD), + ) + + cmds.checkBoxGrp( + DELTA_CHK, + numberOfCheckBoxes=1, + label='Delta', + value1=cmds.optionVar(query=DELTA_CHK), + ) + cmds.floatSliderGrp( + DELTA_SLD, + label='Delta Multiplier', + field=True, + minValue=0.0, + maxValue=1.0, + fieldMinValue=0.0, + fieldMaxValue=10.0, + step=0.1, + precision=1, + value=cmds.optionVar(query=DELTA_SLD), + ) + + mel.eval('setOptionBoxTitle("BlurRelax Options");') + mel.eval('setOptionBoxCommandName("BlurRelax");') + apply_close_button = mel.eval('getOptionBoxApplyAndCloseBtn;') + cmds.button(apply_close_button, edit=True, command=apply_and_close) + apply_button = mel.eval('getOptionBoxApplyBtn;') + cmds.button(apply_button, edit=True, command=create_blur_relax) + reset_button = mel.eval('getOptionBoxResetBtn;') + # For some reason, the buttons in the menu only accept MEL. + cmds.button( + reset_button, + edit=True, + command='python("import BlurRelax.menu; BlurRelax.menu.reset_to_defaults()");', + ) + close_button = mel.eval('getOptionBoxCloseBtn;') + cmds.button(close_button, edit=True, command=close_option_box) + save_button = mel.eval('getOptionBoxSaveBtn;') + cmds.button( + save_button, + edit=True, + command='python("import BlurRelax.menu; BlurRelax.menu.get_create_command_kwargs()");', + ) + mel.eval('showOptionBox') + + +def apply_and_close(*args, **kwargs): + """Create the BlurRelax deformer and close the option box.""" + create_blur_relax() + mel.eval('saveOptionBoxSize') + close_option_box() + + +def close_option_box(*args, **kwargs): + mel.eval('hideOptionBox') + + +def reset_to_defaults(*args, **kwargs): + """Reset the BlurRelax option box widgets to their defaults.""" + cmds.optionMenu(BORDER_DDL, edit=True, value="Pin") + cmds.optionMenu(HARD_DDL, edit=True, value="None") + cmds.optionMenu(GROUP_DDL, edit=True, value="None") + cmds.checkBoxGrp(REPROJ_CHK, edit=True, value1=False) + cmds.checkBoxGrp(DELTA_CHK, edit=True, value1=False) + cmds.floatSliderGrp(REPROJ_SLD, edit=True, value=1) + cmds.floatSliderGrp(PRESERVE_VOL_SLD, edit=True, value=0.0) + cmds.floatSliderGrp(ITERATIONS_SLD, edit=True, value=10.0) + cmds.floatSliderGrp(DELTA_SLD, edit=True, value=1.0) + + +def init_option_vars(): + """Initialize the option vars the first time the ui is run""" + cmds.optionVar(intValue=(BORDER_DDL, 1)) + cmds.optionVar(intValue=(HARD_DDL, 0)) + cmds.optionVar(intValue=(GROUP_DDL, 0)) + cmds.optionVar(intValue=(REPROJ_CHK, 0)) + cmds.optionVar(intValue=(DELTA_CHK, 0)) + cmds.optionVar(floatValue=(REPROJ_SLD, 1.0)) + cmds.optionVar(floatValue=(PRESERVE_VOL_SLD, 0.0)) + cmds.optionVar(floatValue=(ITERATIONS_SLD, 10.0)) + cmds.optionVar(floatValue=(DELTA_SLD, 1.0)) + + +def get_wrap_node_from_object(obj): + """Get a wrap node from the selected geometry.""" + if cmds.nodeType(obj) == 'BlurRelax': + return obj + history = cmds.listHistory(obj, pdo=0) or [] + wrap_nodes = [node for node in history if cmds.nodeType(node) == 'BlurRelax'] + if not wrap_nodes: + raise RuntimeError('No BlurRelax node found on {0}.'.format(obj)) + if len(wrap_nodes) == 1: + return wrap_nodes[0] + else: + # Multiple wrap nodes are deforming the mesh. Let the user choose which one + # to use. + return QtGui.QInputDialog.getItem( + None, 'Select BlurRelax node', 'blurRelax node:', wrap_nodes + ) + + +def get_wrap_node_from_selected(): + """Get a wrap node from the selected geometry.""" + sel = cmds.ls(sl=True) or [] + if not sel: + raise RuntimeError('No BlurRelax found on selected.') + return get_wrap_node_from_object(sel[0]) + + +def destroy_menuitems(): + """Remove the BlurRelax items from the menus.""" + global MENU_ITEMS + for item in MENU_ITEMS: + cmds.deleteUI(item, menuItem=True) + MENU_ITEMS = [] + + +def paint_blur_relax_weights(*args, **kwargs): + """Activates the paint BlurRelax weights context.""" + sel = cmds.ls(sl=True) + if not sel: + return + wrap_node = get_wrap_node_from_selected() + if not wrap_node: + return + mel.eval( + 'artSetToolAndSelectAttr("artAttrCtx", "BlurRelax.{0}.weights");'.format( + wrap_node + ) + ) diff --git a/src/fastMayaRelax.cpp b/src/fastMayaRelax.cpp index 04d07d8..e5a3963 100644 --- a/src/fastMayaRelax.cpp +++ b/src/fastMayaRelax.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -232,7 +233,7 @@ pointArray_t MayaRelaxer::quickRelax( FLOAT(*baseVerts)[NUM_COMPS]; if (slide) { baseVerts = new FLOAT[numVertices][NUM_COMPS]; - memcpy(&(baseVerts[0][0]), &(verts[0][0]), NUM_COMPS * numVertices * sizeof(FLOAT)); + std::memcpy(&(baseVerts[0][0]), &(verts[0][0]), NUM_COMPS * numVertices * sizeof(FLOAT)); } // Reserve some memory for the next-to-last iteration so we can blend @@ -264,7 +265,7 @@ pointArray_t MayaRelaxer::quickRelax( for (size_t r = 0; r < iterI; ++r) { // Store the next-to-last iteration to interpolate with if ((r == iterI - 1) && (iterT > 0.0)) - memcpy(&(prevVerts[0][0]), &(verts[0][0]), NUM_COMPS * numVertices * sizeof(FLOAT)); + std::memcpy(&(prevVerts[0][0]), &(verts[0][0]), NUM_COMPS * numVertices * sizeof(FLOAT)); quickLaplacianSmooth(verts); if (taubinBias < 1.0) diff --git a/src/fastMayaRelax.h b/src/fastMayaRelax.h index ea5116d..fc5dbe2 100644 --- a/src/fastMayaRelax.h +++ b/src/fastMayaRelax.h @@ -33,7 +33,7 @@ class MayaRelaxer: public Relaxer { ) : Relaxer(borderBehavior, hardEdgeBehavior, groupEdgeBehavior, rawNeighbors, rawHardEdges, rawVertData) { } - pointArray_t MayaRelaxer::quickRelax( + pointArray_t quickRelax( MObject &mesh, const bool slide, const bool doReproject, @@ -53,7 +53,7 @@ class MayaRelaxer: public Relaxer { MMatrix getMatrixAtPoint(MObject &mesh, MFnMesh &meshFn, MItMeshVertex &vertIt) const; - std::vector MayaRelaxer::getVertMatrices(MObject &mesh, MFnMesh &meshFn) const; + std::vector getVertMatrices(MObject &mesh, MFnMesh &meshFn) const; }; diff --git a/src/fastRelax.cpp b/src/fastRelax.cpp index 11e5fec..286a0ec 100644 --- a/src/fastRelax.cpp +++ b/src/fastRelax.cpp @@ -22,6 +22,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include +#include #include #include #include @@ -74,7 +76,7 @@ void Relaxer::edgeProject( // normalized(prevPoints[n] - basePos) for (size_t x = 0; x < 3; ++x) edge[x] = basePoints[n][x] - basePos[x]; - FLOAT elen = sqrt(edge[0] * edge[0] + edge[1] * edge[1] + edge[2] * edge[2]); + FLOAT elen = std::sqrt(edge[0] * edge[0] + edge[1] * edge[1] + edge[2] * edge[2]); for (size_t x = 0; x < 3; ++x) edge[x] /= elen; @@ -156,7 +158,7 @@ void Relaxer::quickLaplacianSmooth( outComp[i] = shiftVal[i] * taubinBias * ((outComp[i] / valence[i]) - verts[i]) + verts[i]; } - memcpy(verts, outComp, nzc*sizeof(FLOAT)); + std::memcpy(verts, outComp, nzc*sizeof(FLOAT)); delete outComp; } diff --git a/src/pluginRegister.cpp b/src/pluginRegister.cpp index c433955..106b2e7 100644 --- a/src/pluginRegister.cpp +++ b/src/pluginRegister.cpp @@ -30,8 +30,11 @@ MStatus initializePlugin(MObject obj) { MStatus result; MFnPlugin plugin(obj, "Blur Studio", "1.0", "Any"); result = plugin.registerNode(DEFORMER_NAME, BlurRelax::id, BlurRelax::creator, BlurRelax::initialize, MPxNode::kDeformerNode); - MGlobal::executeCommand("makePaintable -attrType \"multiFloat\" -sm \"deformer\" \"" DEFORMER_NAME "\" \"weights\";"); - + if (MGlobal::mayaState() == MGlobal::kInteractive) { + MGlobal::executeCommand("makePaintable -attrType \"multiFloat\" -sm \"deformer\" \"" DEFORMER_NAME "\" \"weights\";"); + MGlobal::executePythonCommandOnIdle("import BlurRelax.menu"); + MGlobal::executePythonCommandOnIdle("BlurRelax.menu.create_menuitems()"); + } return result; } @@ -41,4 +44,3 @@ MStatus uninitializePlugin(MObject obj) { result = plugin.deregisterNode(BlurRelax::id); return result; } -