diff --git a/.github/actions/alembic-install-dep/action.yml b/.github/actions/alembic-install-dep/action.yml index b88b73f8c4..8dfba53764 100644 --- a/.github/actions/alembic-install-dep/action.yml +++ b/.github/actions/alembic-install-dep/action.yml @@ -10,12 +10,13 @@ runs: using: "composite" steps: + # Alembic is part of VFX reference platform (CY2025: 1.8.x) - name: Cache Alembic id: cache-alembic uses: actions/cache@v4 with: path: dependencies/alembic_install - key: alembic-v1.8.5-${{runner.os}}-${{inputs.cpu}}-4 + key: alembic-v1.8.8-${{runner.os}}-${{inputs.cpu}}-0 - name: Checkout Alembic if: steps.cache-alembic.outputs.cache-hit != 'true' @@ -23,7 +24,7 @@ runs: with: repository: alembic/alembic path: './dependencies/alembic' - ref: 1.8.5 + ref: 1.8.8 - name: Setup Alembic if: steps.cache-alembic.outputs.cache-hit != 'true' @@ -46,7 +47,7 @@ runs: -DCMAKE_PREFIX_PATH:PATH=../install/ -DUSE_BINARIES=OFF -DUSE_TESTS=OFF - ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_MACOSX_RPATH=ON' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 -DCMAKE_MACOSX_RPATH=ON' || null }} ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - name: Build Alembic diff --git a/.github/actions/assimp-install-dep/action.yml b/.github/actions/assimp-install-dep/action.yml index 960d283bde..cf216ed43f 100644 --- a/.github/actions/assimp-install-dep/action.yml +++ b/.github/actions/assimp-install-dep/action.yml @@ -15,7 +15,7 @@ runs: uses: actions/cache@v4 with: path: dependencies/assimp_install - key: assimp-v5.4.2-${{runner.os}}-${{inputs.cpu}}-0 + key: assimp-v5.4.3-${{runner.os}}-${{inputs.cpu}}-0 - name: Checkout ASSIMP if: steps.cache-assimp.outputs.cache-hit != 'true' @@ -23,7 +23,7 @@ runs: with: repository: assimp/assimp path: './dependencies/assimp' - ref: v5.4.2 + ref: v5.4.3 # Revert https://github.com/assimp/assimp/pull/5349 - name: Patch ASSIMP @@ -61,7 +61,7 @@ runs: -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=../assimp_install - ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0' || null }} ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - name: Build ASSIMP diff --git a/.github/actions/blosc-install-dep/action.yml b/.github/actions/blosc-install-dep/action.yml index 7b5845eda5..05bd99b6ba 100644 --- a/.github/actions/blosc-install-dep/action.yml +++ b/.github/actions/blosc-install-dep/action.yml @@ -15,7 +15,7 @@ runs: uses: actions/cache@v4 with: path: dependencies/blosc_install - key: blosc-1.21.5-${{runner.os}}-${{inputs.cpu}}-5 + key: blosc-1.21.6-${{runner.os}}-${{inputs.cpu}}-0 # Dependents: openvdb vtk - name: Checkout blosc @@ -24,7 +24,7 @@ runs: with: repository: Blosc/c-blosc path: './dependencies/blosc' - ref: v1.21.5 + ref: v1.21.6 - name: Setup blosc if: steps.cache-blosc.outputs.cache-hit != 'true' @@ -49,7 +49,7 @@ runs: -DCMAKE_INSTALL_PREFIX=../blosc_install -DCMAKE_PREFIX_PATH:PATH=$(pwd)/../install/ -DPREFER_EXTERNAL_ZLIB=ON - ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0' || null }} ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - name: Build blosc diff --git a/.github/actions/boost-install-dep/action.yml b/.github/actions/boost-install-dep/action.yml deleted file mode 100644 index a4023c4225..0000000000 --- a/.github/actions/boost-install-dep/action.yml +++ /dev/null @@ -1,75 +0,0 @@ -name: 'Install Boost Dependency' -description: 'Install Boost Dependency using cache when possible' -inputs: - cpu: - description: 'CPU architecture to build for' - required: false - default: 'x86_64' - -runs: - using: "composite" - steps: - - - name: Cache Boost - id: cache-boost - uses: actions/cache@v4 - with: - path: dependencies/boost_install - key: boost-1.83.0-${{runner.os}}-${{inputs.cpu}}-4 - - # Dependents: usd openvdb vtk - # Note: usd v23.05 not compatible with boost 1.84.0 - - name: Checkout Boost - if: steps.cache-boost.outputs.cache-hit != 'true' - uses: actions/checkout@v4 - with: - repository: boostorg/boost - submodules: true - fetch-depth: 0 - path: './dependencies/boost' - ref: boost-1.83.0 - - - name: Setup Boost - if: steps.cache-boost.outputs.cache-hit != 'true' - working-directory: ${{github.workspace}}/dependencies - shell: bash - run: | - mkdir boost_build - mkdir boost_install - - - name: Configure Boost - if: steps.cache-boost.outputs.cache-hit != 'true' - working-directory: ${{github.workspace}}/dependencies/boost - shell: bash - run: ./bootstrap.sh - - # Windows require msvc toolset to avoid mingw being picked up instead - # fPIC is needed for clang - # NO_ZSTD is needed on macOS for some reason - - name: Build Boost - if: steps.cache-boost.outputs.cache-hit != 'true' - working-directory: ${{github.workspace}}/dependencies/boost - shell: bash - run: > - ./b2 - --prefix='../boost_install' - --build-dir='../boost_build' - variant='release' - link=static - runtime-link=shared - cxxflags="-fPIC" - ${{ runner.os == 'Windows' && 'toolset=msvc' || null }} - ${{ inputs.cpu == 'arm64' && 'architecture=arm' || null }} - --with-date_time - --with-filesystem - --with-program_options - --with-regex - --with-system - --with-iostreams - -sNO_ZSTD=1 - install - - - name: Copy to install - working-directory: ${{github.workspace}}/dependencies/boost_install - shell: bash - run: cp -r ./* ../install/ diff --git a/.github/actions/draco-install-dep/action.yml b/.github/actions/draco-install-dep/action.yml index d113fe6415..410d42857f 100644 --- a/.github/actions/draco-install-dep/action.yml +++ b/.github/actions/draco-install-dep/action.yml @@ -15,7 +15,7 @@ runs: uses: actions/cache@v4 with: path: dependencies/draco_install - key: draco-1.5.7-${{runner.os}}-${{inputs.cpu}}-2 + key: draco-1.5.7-${{runner.os}}-${{inputs.cpu}}-3 - name: Checkout Draco if: steps.cache-draco.outputs.cache-hit != 'true' @@ -45,7 +45,7 @@ runs: -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DDRACO_BACKWARDS_COMPATIBILITY=OFF -DDRACO_JS_GLUE=OFF - ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0' || null }} ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - name: Build Draco diff --git a/.github/actions/generic-ci/action.yml b/.github/actions/generic-ci/action.yml index 2423088e23..1aa1f34ccf 100644 --- a/.github/actions/generic-ci/action.yml +++ b/.github/actions/generic-ci/action.yml @@ -90,11 +90,12 @@ runs: with: cpu: ${{inputs.cpu}} + # Python is part of VFX reference platform (CY2025: 3.11) - name: Set up Python if: inputs.optional_deps_label == 'optional-deps' uses: actions/setup-python@v5 with: - python-version: '3.x' + python-version: '3.11' - name: Install Python dependencies if: inputs.optional_deps_label == 'optional-deps' @@ -178,7 +179,7 @@ runs: -DF3D_TESTING_FORCE_RENDERING_BACKEND=${{ inputs.rendering_backend }} -DF3D_WINDOWS_GUI=ON ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0' || null }} - name: Build shell: bash diff --git a/.github/actions/imath-install-dep/action.yml b/.github/actions/imath-install-dep/action.yml index e985bc7e66..cdd57d0b73 100644 --- a/.github/actions/imath-install-dep/action.yml +++ b/.github/actions/imath-install-dep/action.yml @@ -15,7 +15,7 @@ runs: uses: actions/cache@v4 with: path: dependencies/imath_install - key: imath-v3.1.11-${{runner.os}}-${{inputs.cpu}}-1 + key: imath-v3.1.12-${{runner.os}}-${{inputs.cpu}}-0 # Dependents: alembic - name: Checkout Imath @@ -24,7 +24,7 @@ runs: with: repository: AcademySoftwareFoundation/Imath path: './dependencies/imath' - ref: v3.1.11 + ref: v3.1.12 - name: Setup Imath if: steps.cache-imath.outputs.cache-hit != 'true' @@ -44,7 +44,7 @@ runs: -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=../imath_install - ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0' || null }} ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - name: Build Imath diff --git a/.github/actions/occt-install-dep/action.yml b/.github/actions/occt-install-dep/action.yml index 0cc9b93754..1b81117415 100644 --- a/.github/actions/occt-install-dep/action.yml +++ b/.github/actions/occt-install-dep/action.yml @@ -15,7 +15,7 @@ runs: uses: actions/cache@v4 with: path: dependencies/occt_install - key: occt-V7_8_1-${{runner.os}}-${{inputs.cpu}}-2 + key: occt-V7_8_1-${{runner.os}}-${{inputs.cpu}}-3 - name: Checkout OCCT if: steps.cache-occt.outputs.cache-hit != 'true' @@ -65,7 +65,7 @@ runs: -DCMAKE_INSTALL_NAME_DIR:PATH=${{github.workspace}}/dependencies/install/lib -DINSTALL_DIR_BIN:PATH=bin -DUSE_FREETYPE=OFF - ${{ runner.os == 'macOS' && '-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0' || null }} ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - name: Build OCCT diff --git a/.github/actions/openexr-install-dep/action.yml b/.github/actions/openexr-install-dep/action.yml index 6191d3e8a4..60163c4bb9 100644 --- a/.github/actions/openexr-install-dep/action.yml +++ b/.github/actions/openexr-install-dep/action.yml @@ -10,12 +10,13 @@ runs: using: "composite" steps: + # OpenEXR is part of VFX reference platform (CY2025: 3.3.x) - name: Cache OpenEXR id: cache-openexr uses: actions/cache@v4 with: path: dependencies/openexr_install - key: openexr-v3.2.4-${{runner.os}}-${{inputs.cpu}}-1 + key: openexr-v3.3.2-${{runner.os}}-${{inputs.cpu}}-0 # Dependents: usd - name: Checkout OpenEXR @@ -24,7 +25,7 @@ runs: with: repository: AcademySoftwareFoundation/openexr path: './dependencies/openexr' - ref: v3.2.4 + ref: v3.3.2 - name: Setup OpenEXR if: steps.cache-openexr.outputs.cache-hit != 'true' @@ -46,7 +47,7 @@ runs: -DCMAKE_PREFIX_PATH:PATH=../install/ -DOPENEXR_INSTALL_TOOLS=OFF -DOPENEXR_INSTALL_EXAMPLES=OFF - ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_MACOSX_RPATH=ON' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 -DCMAKE_MACOSX_RPATH=ON' || null }} ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - name: Build OpenEXR diff --git a/.github/actions/openvdb-install-dep/action.yml b/.github/actions/openvdb-install-dep/action.yml index 7a4b5d5d5c..17499dd7af 100644 --- a/.github/actions/openvdb-install-dep/action.yml +++ b/.github/actions/openvdb-install-dep/action.yml @@ -10,12 +10,13 @@ runs: using: "composite" steps: + # OpenVDB is part of VFX reference platform (CY2025: 12.x) - name: Cache OpenVDB id: cache-openvdb uses: actions/cache@v4 with: path: dependencies/openvdb_install - key: openvdb-11.0.0-${{runner.os}}-${{inputs.cpu}}-8 + key: openvdb-12.0.0-${{runner.os}}-${{inputs.cpu}}-0 # Dependents: vtk - name: Checkout OpenVDB @@ -24,14 +25,7 @@ runs: with: repository: AcademySoftwareFoundation/openvdb path: './dependencies/openvdb' - ref: v11.0.0 - - # https://github.com/AcademySoftwareFoundation/openvdb/pull/1860 - - name: Patch OpenVDB - if: steps.cache-openvdb.outputs.cache-hit != 'true' - working-directory: ${{github.workspace}}/dependencies/openvdb - shell: bash - run: patch -p1 < $GITHUB_ACTION_PATH/openvdb-cmake-CMP0167.patch + ref: v12.0.0 - name: Setup OpenVDB if: steps.cache-openvdb.outputs.cache-hit != 'true' @@ -56,11 +50,12 @@ runs: -DOPENVDB_BUILD_BINARIES=OFF -DOPENVDB_BUILD_VDB_PRINT:BOOL=OFF -DOPENVDB_CORE_STATIC=OFF + -DOPENVDB_USE_DELAYED_LOADING=OFF -DUSE_BLOSC:BOOL=ON -DUSE_CCACHE:BOOL=OFF -DUSE_EXPLICIT_INSTANTIATION:BOOL=OFF -DUSE_ZLIB:BOOL=ON - ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0' || null }} ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - name: Build OpenVDB diff --git a/.github/actions/openvdb-install-dep/openvdb-cmake-CMP0167.patch b/.github/actions/openvdb-install-dep/openvdb-cmake-CMP0167.patch deleted file mode 100644 index 4adff5a4ca..0000000000 --- a/.github/actions/openvdb-install-dep/openvdb-cmake-CMP0167.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/cmake/FindOpenVDB.cmake b/cmake/FindOpenVDB.cmake -index c4213c85..11ebaca9 100644 ---- a/cmake/FindOpenVDB.cmake -+++ b/cmake/FindOpenVDB.cmake -@@ -491,6 +491,10 @@ endif() - # Add standard dependencies - - find_package(TBB REQUIRED COMPONENTS tbb) -+ -+if(POLICY CMP0167) -+ cmake_policy(SET CMP0167 NEW) -+endif() - find_package(Boost REQUIRED COMPONENTS iostreams) - - # Add deps for pyopenvdb diff --git a/.github/actions/ospray-sb-install-dep/action.yml b/.github/actions/ospray-sb-install-dep/action.yml index d034b4673a..cb562be609 100644 --- a/.github/actions/ospray-sb-install-dep/action.yml +++ b/.github/actions/ospray-sb-install-dep/action.yml @@ -15,7 +15,7 @@ runs: uses: actions/cache@v4 with: path: dependencies/ospray_install - key: ospray-sb-v2.7.1-${{runner.os}}-${{inputs.cpu}}-2 + key: ospray-sb-v2.7.1-${{runner.os}}-${{inputs.cpu}}-3 # Dependents: vtk - name: Checkout ospray @@ -63,7 +63,7 @@ runs: -DDOWNLOAD_TBB=OFF -DINSTALL_DEPENDENCIES=ON -DINSTALL_IN_SEPARATE_DIRECTORIES=OFF - ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0' || null }} ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - name: Build ospray diff --git a/.github/actions/pybind11-install-dep/action.yml b/.github/actions/pybind11-install-dep/action.yml index 7cbc5f42ab..c6f221daa4 100644 --- a/.github/actions/pybind11-install-dep/action.yml +++ b/.github/actions/pybind11-install-dep/action.yml @@ -9,7 +9,7 @@ runs: uses: actions/cache@v4 with: path: dependencies/pybind11_install - key: pybind11-v2.12.0-${{runner.os}}-0 + key: pybind11-v2.13.6-${{runner.os}}-0 # v2.13 doesn't support python36 which is needed in common-superbuild for now - name: Checkout pybind11 @@ -19,7 +19,7 @@ runs: repository: pybind/pybind11 submodules: true path: './dependencies/pybind11' - ref: v2.12.0 + ref: v2.13.6 - name: Setup pybind11 if: steps.cache-pybind11.outputs.cache-hit != 'true' @@ -37,7 +37,7 @@ runs: cmake ../pybind11 -DCMAKE_INSTALL_PREFIX:PATH=../pybind11_install -DPYBIND11_TEST=OFF - ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0' || null }} ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - name: Install pybind11 diff --git a/.github/actions/python-ci/action.yml b/.github/actions/python-ci/action.yml index 35d8d2ef55..22da57353a 100644 --- a/.github/actions/python-ci/action.yml +++ b/.github/actions/python-ci/action.yml @@ -4,6 +4,9 @@ inputs: lfs_sha: description: 'Cache LFS sha' required: true + python_version: + description: 'Python version' + required: true runs: using: "composite" @@ -43,7 +46,7 @@ runs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.13' + python-version: ${{ inputs.python_version }} - name: Install Python dependencies shell: bash @@ -99,7 +102,7 @@ runs: uses: actions/upload-artifact@v4 with: path: ./source/*.whl - name: ${{runner.os}}-wheel + name: ${{runner.os}}-${{inputs.python_version}}-wheel - name: Install wheel shell: bash diff --git a/.github/actions/tbb-install-dep/action.yml b/.github/actions/tbb-install-dep/action.yml index 980a9a5b5f..87d457f279 100644 --- a/.github/actions/tbb-install-dep/action.yml +++ b/.github/actions/tbb-install-dep/action.yml @@ -15,7 +15,7 @@ runs: uses: actions/cache@v4 with: path: dependencies/tbb_install - key: tbb-v2021.12.0-${{runner.os}}-${{inputs.cpu}}-1 + key: tbb-v2021.12.0-${{runner.os}}-${{inputs.cpu}}-2 # Dependents: usd openvdb vtk # v2021.13.0 somehow cause memory issue in draco and alembic @@ -47,7 +47,7 @@ runs: -DTBB_STRICT=OFF -DTBB_TEST=OFF -DTBB4PY_BUILD=OFF - ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_MACOSX_RPATH=ON' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 -DCMAKE_MACOSX_RPATH=ON' || null }} ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - name: Build TBB diff --git a/.github/actions/vtk-dependencies/action.yml b/.github/actions/vtk-dependencies/action.yml index bdd2e77419..451c75cc53 100644 --- a/.github/actions/vtk-dependencies/action.yml +++ b/.github/actions/vtk-dependencies/action.yml @@ -26,11 +26,6 @@ runs: with: cpu: ${{inputs.cpu}} - - name: Install Boost dependency - uses: ./.actions/boost-install-dep - with: - cpu: ${{inputs.cpu}} - - name: Install zlib uses: ./.actions/zlib-install-dep with: diff --git a/.github/actions/vtk-install-dep/action.yml b/.github/actions/vtk-install-dep/action.yml index 4faf1b950d..7776c899c5 100644 --- a/.github/actions/vtk-install-dep/action.yml +++ b/.github/actions/vtk-install-dep/action.yml @@ -43,7 +43,7 @@ runs: uses: actions/cache@v4 with: path: dependencies/vtk_install - key: vtk-${{env.VTK_SHA_OR_TAG}}-${{runner.os}}-${{inputs.raytracing_label}}-${{inputs.cpu}}-5 + key: vtk-${{env.VTK_SHA_OR_TAG}}-${{runner.os}}-${{inputs.raytracing_label}}-${{inputs.cpu}}-6 - name: Setup VTK if: steps.cache-vtk.outputs.cache-hit != 'true' @@ -123,7 +123,7 @@ runs: -DVTK_OPENGL_HAS_EGL=${{ inputs.vtk_version != 'v9.2.6' && inputs.vtk_version != 'v9.3.1' && 'ON' || 'OFF' }} -DVTK_SMP_IMPLEMENTATION_TYPE=TBB -DVTK_VERSIONED_INSTALL=OFF - ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0' || null }} ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - name: Build VTK diff --git a/.github/actions/zlib-install-dep/action.yml b/.github/actions/zlib-install-dep/action.yml index 4696182657..ba84c49c88 100644 --- a/.github/actions/zlib-install-dep/action.yml +++ b/.github/actions/zlib-install-dep/action.yml @@ -15,7 +15,7 @@ runs: uses: actions/cache@v4 with: path: dependencies/zlib_install - key: zlib-1.3.1-${{runner.os}}-${{inputs.cpu}}-3 + key: zlib-1.3.1-${{runner.os}}-${{inputs.cpu}}-4 # Dependents: blosc openvdb vtk - name: Checkout zlib @@ -43,7 +43,7 @@ runs: -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../zlib_install - ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15' || null }} + ${{ runner.os == 'macOS' && '-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0' || null }} ${{ runner.os == 'Windows' && '-Ax64 -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL' || null }} - name: Build zlib diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index db506dde42..5786f2fe81 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,7 @@ jobs: strategy: fail-fast: false matrix: - vtk_version: [commit, v9.4.0, v9.3.1, v9.2.6] + vtk_version: [commit, v9.4.1, v9.3.1, v9.2.6] static_label: [no-static] include: - vtk_version: commit @@ -80,7 +80,7 @@ jobs: strategy: fail-fast: false matrix: - vtk_version: [commit, v9.4.0, v9.3.1, v9.2.6] + vtk_version: [commit, v9.4.1, v9.3.1, v9.2.6] build_type: [standard] include: - raytracing_label: raytracing @@ -159,7 +159,7 @@ jobs: strategy: fail-fast: false matrix: - vtk_version: [commit, v9.4.0, v9.3.1, v9.2.6] + vtk_version: [commit, v9.4.1, v9.3.1, v9.2.6] runs-on: macos-13 @@ -189,7 +189,7 @@ jobs: strategy: fail-fast: false matrix: - vtk_version: [commit, v9.4.0, v9.3.1] # VTK 9.2.6 not compatible with recent clang version on macOS + vtk_version: [commit, v9.4.1, v9.3.1] # VTK 9.2.6 not compatible with recent clang version on macOS bundle_label: [no-bundle] static_label: [no-static] include: @@ -231,6 +231,18 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-13] + python_version: ['3.11'] + include: + - os: ubuntu-latest + python_version: '3.9' + - os: ubuntu-latest + python_version: '3.10' + - os: ubuntu-latest + python_version: '3.11' + - os: ubuntu-latest + python_version: '3.12' + - os: ubuntu-latest + python_version: '3.13' runs-on: ${{matrix.os}} container: ${{ matrix.os == 'ubuntu-latest' && 'ghcr.io/f3d-app/f3d-ci' || null }} @@ -251,6 +263,7 @@ jobs: uses: ./source/.github/actions/python-ci with: lfs_sha: ${{ needs.cache_lfs.outputs.lfs_sha}} + python_version: ${{matrix.python_version}} #---------------------------------------------------------------------------- # Coverage: Build and test on linux with last VTK with coverage option diff --git a/application/F3DOptionsTools.cxx b/application/F3DOptionsTools.cxx index 1091f8b127..e57c749bf4 100644 --- a/application/F3DOptionsTools.cxx +++ b/application/F3DOptionsTools.cxx @@ -64,12 +64,13 @@ static inline const std::array CLIOptions = {{ { { "output", "", "Render to file", "", "" }, { "no-background", "", "No background when render to file", "", "1" }, { "help", "h", "Print help", "", "" }, { "version", "", "Print version details", "", "" }, - { "readers-list", "", "Print the list of readers", "", "" }, - { "bindings-list", "", "Print the list of interaction bindings and exits, ignored with `--no-render`, only considers the first file group.", "", "" }, + { "list-readers", "", "Print the list of readers", "", "" }, + { "list-bindings", "", "Print the list of interaction bindings and exits, ignored with `--no-render`, only considers the first file group.", "", "" }, { "config", "", "Specify the configuration file to use. absolute/relative path or filename/filestem to search in configuration file locations", "", "" }, { "no-config", "", "Do not read the configuration file", "", "1" }, { "no-render", "", "Do not render anything and quit right after loading the first file, use with --verbose to recover information about a file.", "", "1" }, { "rendering-backend", "", "Backend to use when rendering (auto|glx|wgl|egl|osmesa)", "", "" }, + { "list-rendering-backends", "", "Print the list of rendering backends available on this system", "", "" }, { "max-size", "", "Maximum size in Mib of a file to load, leave empty for unlimited", "", "" }, #if F3D_MODULE_DMON { "watch", "", "Watch current file and automatically reload it whenever it is modified on disk", "", "1" }, @@ -176,7 +177,7 @@ static inline const std::array CLIOptions = {{ * True boolean options need to be filtered out in ParseCLIOptions * This is the easiest, compile time way to do it */ -constexpr std::array CLIBooleans = {"version", "help", "readers-list", "scan-plugins"}; +constexpr std::array CLIBooleans = {"version", "help", "list-readers", "scan-plugins", "list-rendering-backends"}; //---------------------------------------------------------------------------- /** @@ -235,7 +236,7 @@ void PrintPluginsScan() appPath /= "share/f3d/plugins"; - auto plugins = f3d::engine::getPluginsList(appPath.string()); + auto plugins = f3d::engine::getPluginsList(appPath); f3d::log::info("Found ", plugins.size(), " plugins:"); @@ -270,6 +271,19 @@ void PrintVersion() f3d::log::setUseColoring(true); } +//---------------------------------------------------------------------------- +void PrintRenderingBackendList() +{ + auto backends = f3d::engine::getRenderingBackendList(); + + f3d::log::setUseColoring(false); + f3d::log::info("Rendering backends:"); + for (const auto& [name, available] : backends) + { + f3d::log::info(name + ": " + (available ? "available" : "unavailable")); + } +} + //---------------------------------------------------------------------------- void PrintReadersList() { @@ -485,14 +499,19 @@ F3DOptionsTools::OptionsDict F3DOptionsTools::ParseCLIOptions( ::PrintVersion(); throw F3DExNoProcess("version requested"); } + if (result.count("list-rendering-backends") > 0) + { + ::PrintRenderingBackendList(); + throw F3DExNoProcess("rendering backend list requested"); + } if (result.count("scan-plugins") > 0) { ::PrintPluginsScan(); throw F3DExNoProcess("scan plugins requested"); } - if (result.count("readers-list") > 0) + if (result.count("list-readers") > 0) { - // `--readers-list` needs plugin to be loaded to be useful + // `--list-readers` needs plugin to be loaded to be useful // Load them manually std::vector plugins; if (result.count("load-plugins") > 0) diff --git a/application/F3DOptionsTools.h b/application/F3DOptionsTools.h index aeda133ce3..dce906ad0a 100644 --- a/application/F3DOptionsTools.h +++ b/application/F3DOptionsTools.h @@ -27,7 +27,7 @@ using OptionsEntries = std::vector; static inline const OptionsDict DefaultAppOptions = { { "input", "" }, { "output", "" }, - { "bindings-list", "false" }, + { "list-bindings", "false" }, { "no-background", "false" }, { "config", "" }, { "no-config", "false" }, diff --git a/application/F3DPluginsTools.cxx b/application/F3DPluginsTools.cxx index 9b15f4285a..f50307377f 100644 --- a/application/F3DPluginsTools.cxx +++ b/application/F3DPluginsTools.cxx @@ -6,13 +6,19 @@ #include #include +namespace fs = std::filesystem; + namespace { //---------------------------------------------------------------------------- -std::vector GetPluginSearchPaths() +std::vector GetPluginSearchPaths() { + std::vector searchPaths; + // Recover F3D_PLUGINS_PATH first - auto searchPaths = F3DSystemTools::GetVectorEnvironnementVariable("F3D_PLUGINS_PATH"); + std::vector stringPaths = + F3DSystemTools::GetVectorEnvironnementVariable("F3D_PLUGINS_PATH"); + std::copy(stringPaths.begin(), stringPaths.end(), std::back_inserter(searchPaths)); #if F3D_MACOS_BUNDLE return searchPaths; #else @@ -20,7 +26,7 @@ std::vector GetPluginSearchPaths() auto tmpPath = F3DSystemTools::GetApplicationPath(); tmpPath = tmpPath.parent_path().parent_path(); tmpPath /= F3D::PluginsInstallDir; - searchPaths.push_back(tmpPath.string()); + searchPaths.emplace_back(tmpPath); return searchPaths; #endif } diff --git a/application/F3DStarter.cxx b/application/F3DStarter.cxx index 150808b25d..a8739c5409 100644 --- a/application/F3DStarter.cxx +++ b/application/F3DStarter.cxx @@ -543,7 +543,7 @@ class F3DStarter::F3DInternals { // Update typed app options from app options this->AppOptions.Output = f3d::options::parse(appOptions.at("output")); - this->AppOptions.BindingsList = f3d::options::parse(appOptions.at("bindings-list")); + this->AppOptions.BindingsList = f3d::options::parse(appOptions.at("list-bindings")); this->AppOptions.NoBackground = f3d::options::parse(appOptions.at("no-background")); this->AppOptions.NoRender = f3d::options::parse(appOptions.at("no-render")); this->AppOptions.RenderingBackend = diff --git a/application/testing/CMakeLists.txt b/application/testing/CMakeLists.txt index 10121bff51..ff6c382c97 100644 --- a/application/testing/CMakeLists.txt +++ b/application/testing/CMakeLists.txt @@ -129,6 +129,7 @@ function(f3d_test) set(f3d_test_env_vars ${F3D_TEST_ENV}) list(APPEND f3d_test_env_vars "CTEST_F3D_PROGRESS_BAR=1") + list(APPEND f3d_test_env_vars "CTEST_F3D_CONSOLE_BADGE=1") if (F3D_TEST_NO_DATA_FORCE_RENDER) list(APPEND f3d_test_env_vars "CTEST_F3D_NO_DATA_FORCE_RENDER=1") endif () @@ -327,7 +328,19 @@ endif() # Test plugin fail code path f3d_test(NAME TestPluginVerbose ARGS --verbose REGEXP "Loading plugin \"native\"" NO_BASELINE) f3d_test(NAME TestPluginNonExistent ARGS --load-plugins=dummy REGEXP "Plugin failed to load" NO_BASELINE) -f3d_test(NAME TestPluginInvalid ARGS --load-plugins=${F3D_SOURCE_DIR}/testing/data/invalid.so REGEXP "Cannot open the library" NO_BASELINE) +if(WIN32) + set(_TEST_PLUGIN_INVALID_REGEXP "is not a valid Win32 application") +elseif(APPLE) + set(_TEST_PLUGIN_INVALID_REGEXP "not a mach-o file") +else() + set(_TEST_PLUGIN_INVALID_REGEXP "file too short") +endif() +f3d_test(NAME TestPluginInvalid ARGS --load-plugins=${F3D_SOURCE_DIR}/testing/data/invalid.so REGEXP ${_TEST_PLUGIN_INVALID_REGEXP} NO_BASELINE) + +if(UNIX AND NOT APPLE) + f3d_test(NAME TestPluginInvalidSystem ARGS --verbose --load-plugins=invalid REGEXP "file too short" ENV "LD_LIBRARY_PATH=${F3D_SOURCE_DIR}/testing/data" NO_BASELINE) +endif() + if(WIN32) set(_dirname "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") else() @@ -793,7 +806,6 @@ f3d_test(NAME TestInteractionConfigFileNoColorBar DATA multi CONFIG ${F3D_SOURCE f3d_test(NAME TestInteractionConfigFileBindings DATA dragon.vtu CONFIG ${F3D_SOURCE_DIR}/testing/configs/bindings.json INTERACTION UI) #Ctrl+Shift+O;Ctrl+O;Shift+O;O;3 f3d_test(NAME TestInteractionConfigFileMulti DATA multi CONFIG ${F3D_SOURCE_DIR}/testing/configs/complex.json INTERACTION UI) #SY;Right;XG;Right;N;Right;Right f3d_test(NAME TestInteractionConfigFileAndCommand DATA multi ARGS -o CONFIG ${F3D_SOURCE_DIR}/testing/configs/complex.json INTERACTION UI) #OX;Right;N;Right;Right;Right -f3d_test(NAME TestInteractionDumpSceneState DATA dragon.vtu NO_BASELINE INTERACTION REGEXP "Camera position: 2.23745,3.83305,507.598")#? f3d_test(NAME TestInteractionCycleVerbose DATA dragon.vtu ARGS --verbose -s NO_BASELINE INTERACTION REGEXP "Not coloring")#SSSSYC f3d_test(NAME TestInteractionEmptyDrop INTERACTION REGEXP "Drop event without any provided files.")#DropEvent Empty; f3d_test(NAME TestInteractionCameraUpdate DATA dragon.vtu INTERACTION) #MouseWheel;MouseWheel;MouseWheel;S @@ -821,6 +833,7 @@ f3d_test(NAME TestInteractionConsoleOpenWarningClick DATA f3d.glb ARGS --positio f3d_test(NAME TestInteractionConsoleToggleGrid DATA f3d.glb INTERACTION UI) #Escape;toggle render.grid.enable;Return;Escape f3d_test(NAME TestInteractionConsoleInvalidCommand DATA f3d.glb INTERACTION UI) #Escape;foo;Return f3d_test(NAME TestInteractionConsoleInvalidOption DATA f3d.glb INTERACTION UI) #Escape;toggle foo;Return +f3d_test(NAME TestInteractionConsoleClear DATA dragon.vtu INTERACTION UI) #Escape;e;Escape;printt;BackSpace;_scee;Left;n;Right;_info;Return;clear;Return f3d_test(NAME TestInteractionConsoleTypingSceneInfo DATA f3d.glb INTERACTION UI) #Escape;e;Escape;printt;BackSpace;_scee;Left;Right;_info;Return if (F3D_MODULE_TINYFILEDIALOGS) @@ -887,6 +900,10 @@ f3d_test(NAME TestInteractionPlay DATA cow.vtp ARGS --interaction-test-play=${CM f3d_test(NAME TestCommandScriptBasic DATA dragon.vtu SCRIPT TestCommandScriptBasic.txt --reference=${F3D_SOURCE_DIR}/testing/baselines/TestCommandScriptBasic.png) f3d_test(NAME TestCommandScriptInvalidCommand DATA dragon.vtu SCRIPT TestCommandScriptInvalid.txt REGEXP "Command: \"INVALID_COMMAND_1\" is not recognized, ignoring" NO_BASELINE) f3d_test(NAME TestCommandScriptMissingFile DATA dragon.vtu SCRIPT TestCommandScriptMissingFile.txt REGEXP "Unable to open command script file" NO_BASELINE) +f3d_test(NAME TestCommandScriptPrintScene DATA dragon.vtu SCRIPT TestCommandScriptPrintScene.txt REGEXP "Camera position: 2.23745,3.83305,507.598" NO_BASELINE) # print_scene_info +f3d_test(NAME TestCommandScriptPrintColoring DATA dragon.vtu SCRIPT TestCommandScriptPrintColoring.txt REGEXP "Not coloring" NO_BASELINE) # print_coloring_info +f3d_test(NAME TestCommandScriptPrintMesh DATA dragon.vtu SCRIPT TestCommandScriptPrintMesh.txt REGEXP "Number of points: 13268" NO_BASELINE) # print_mesh_info +f3d_test(NAME TestCommandScriptPrintOptions DATA dragon.vtu SCRIPT TestCommandScriptPrintOptions.txt REGEXP "interactor.invert_zoom: false" NO_BASELINE) # print_options_info f3d_test(NAME TestParseOptionalBoolExtraArg DATA dragon.vtu SCRIPT TestParseOptionalBoolExtraArg.txt REGEXP "Command: load_previous_file_group takes at most 1 argument, got 2 arguments instead." NO_BASELINE) # Window position test @@ -1039,9 +1056,9 @@ f3d_test(NAME TestConfigFileNoOptions DATA cow.vtp CONFIG ${F3D_SOURCE_DIR}/test # Test update interaction verbose f3d_test(NAME TestConfigFileBindingsVerbose DATA dragon.vtu ARGS --verbose CONFIG ${F3D_SOURCE_DIR}/testing/configs/bindings.json REGEXP "'Shift.O' : '`toggle model.point_sprites.enable` '" NO_BASELINE) -# Test bindings-list display with config file -f3d_test(NAME TestConfigFileBindingsList ARGS --bindings-list CONFIG ${F3D_SOURCE_DIR}/testing/configs/bindings.json REGEXP "Ctrl.Shift.O `toggle ui.filename`" NO_BASELINE) -f3d_test(NAME TestConfigFileBindingsListData DATA dragon.vtu ARGS --bindings-list CONFIG ${F3D_SOURCE_DIR}/testing/configs/bindings.json REGEXP "Any.3 `roll_camera 90`" NO_BASELINE) +# Test list-bindings display with config file +f3d_test(NAME TestConfigFileBindingsList ARGS --list-bindings CONFIG ${F3D_SOURCE_DIR}/testing/configs/bindings.json REGEXP "Ctrl.Shift.O `toggle ui.filename`" NO_BASELINE) +f3d_test(NAME TestConfigFileBindingsListData DATA dragon.vtu ARGS --list-bindings CONFIG ${F3D_SOURCE_DIR}/testing/configs/bindings.json REGEXP "Any.3 `roll_camera 90`" NO_BASELINE) # Test invalid value in config file f3d_test(NAME TestConfigFileInvalidValue DATA cow.vtp CONFIG ${F3D_SOURCE_DIR}/testing/configs/invalid_value.json REGEXP "must be a string, a boolean or a number" NO_BASELINE) @@ -1068,19 +1085,19 @@ f3d_test(NAME TestHelpPositional ARGS --help REGEXP "file1 file2 \.\.\.") # Test version display f3d_test(NAME TestVersion ARGS --version REGEXP "Version:") -# Test readers-list display -f3d_test(NAME TestReadersList ARGS --readers-list REGEXP_FAIL "No registered reader found") +# Test list-readers display +f3d_test(NAME TestReadersList ARGS --list-readers REGEXP_FAIL "No registered reader found") # Test invalid component string coverage f3d_test(NAME TestInteractionInvalidComponent INTERACTION UI DATA cow.vtp ARGS --coloring-component=1 NO_BASELINE) #H -# Test multi plugin readers-lists +# Test multi plugin list-readers if(F3D_PLUGIN_BUILD_ALEMBIC AND F3D_PLUGIN_BUILD_ASSIMP) - f3d_test(NAME TestReadersListMultiplePlugins ARGS --readers-list --load-plugins=assimp,alembic NO_BASELINE REGEXP_FAIL "Plugin failed to load") + f3d_test(NAME TestReadersListMultiplePlugins ARGS --list-readers --load-plugins=assimp,alembic NO_BASELINE REGEXP_FAIL "Plugin failed to load") endif() # Test bindings-list display -f3d_test(NAME TestBindingsList ARGS --bindings-list REGEXP "Any.Question Print scene descr to terminal") +f3d_test(NAME TestBindingsList ARGS --list-bindings REGEXP "Any.5 Toggle Orthographic Projection") # Test rendering backends # For some reason the sanitizer detects leaks because of EGL and OSMesa @@ -1156,6 +1173,25 @@ f3d_test(NAME TestHelpPrecedenceWithUnknownOption ARGS --help --unknown REGEXP " # Test that --version is displayed even when there is an unknown option f3d_test(NAME TestVersionPrecedenceWithUnknownOption ARGS --version --unknown REGEXP "Version:" NO_BASELINE) +# Test rendering backend list +if(WIN32) + f3d_test(NAME TestRenderingBackenListWGL ARGS --list-rendering-backends NO_RENDER NO_BASELINE REGEXP "wgl: available") +elseif(APPLE) + f3d_test(NAME TestRenderingBackenListCOCOA ARGS --list-rendering-backends NO_RENDER NO_BASELINE REGEXP "cocoa: available") +endif() + +if(F3D_TESTING_ENABLE_GLX_TESTS AND VTK_VERSION VERSION_GREATER_EQUAL 9.3.20240914) + f3d_test(NAME TestRenderingBackenListGLX ARGS --list-rendering-backends NO_RENDER NO_BASELINE REGEXP "glx: available") +endif() + +if(F3D_TESTING_ENABLE_EGL_TESTS AND VTK_VERSION VERSION_GREATER_EQUAL 9.3.20240914) + f3d_test(NAME TestRenderingBackenListEGL ARGS --list-rendering-backends NO_RENDER NO_BASELINE REGEXP "egl: available") +endif() + +if(F3D_TESTING_ENABLE_OSMESA_TESTS) + f3d_test(NAME TestRenderingBackenListOSMesa ARGS --list-rendering-backends NO_RENDER NO_BASELINE REGEXP "osmesa: available") +endif() + # Test scan plugins if(NOT F3D_MACOS_BUNDLE) f3d_test(NAME TestScanPluginsCheckNative ARGS --scan-plugins NO_RENDER NO_BASELINE REGEXP " - native") diff --git a/doc/dev/BUILD.md b/doc/dev/BUILD.md index 38c8adfe0e..cd008ab3f2 100644 --- a/doc/dev/BUILD.md +++ b/doc/dev/BUILD.md @@ -7,7 +7,7 @@ please take a look at our [getting started guide](GETTING_STARTED.md). ## Dependencies * [CMake](https://cmake.org) >= 3.1. -* [VTK](https://vtk.org) >= 9.2.6 (9.4.0 recommended). +* [VTK](https://vtk.org) >= 9.2.6 (9.4.1 recommended). * A C++17 compiler. * A CMake-compatible build system (Visual Studio, XCode, Ninja, Make, etc.). * Optionally, [Assimp](https://www.assimp.org/) >= 5.0. @@ -22,7 +22,7 @@ please take a look at our [getting started guide](GETTING_STARTED.md). ## VTK compatibility -As stated in the dependencies, F3D is compatible with VTK >= 9.2.6, however, some features may not be available. We suggest using VTK 9.4.0 with RenderingRayTracing, IOExodus and IOOpenVDB modules enabled in order to get as many features as possible in F3D. +As stated in the dependencies, F3D is compatible with VTK >= 9.2.6, however, some features may not be available. We suggest using VTK 9.4.1 with RenderingRayTracing, IOExodus and IOOpenVDB modules enabled in order to get as many features as possible in F3D. ## Configuration and building diff --git a/doc/dev/GETTING_STARTED.md b/doc/dev/GETTING_STARTED.md index 251d4493ac..983d2d9c1c 100644 --- a/doc/dev/GETTING_STARTED.md +++ b/doc/dev/GETTING_STARTED.md @@ -40,7 +40,7 @@ sudo yum install make automake gcc gcc-c++ kernel-devel git git-lfs cmake vtk ``` sudo pacman -Syu -sudo pacman -S base-devel git git-lfs cmake vtk nlohmann-json hdf5 netcdf fmt verdict openmpi glew ospray boost libxcursor +sudo pacman -S base-devel git git-lfs cmake vtk nlohmann-json hdf5 netcdf fmt verdict openmpi glew ospray libxcursor ``` ### Compile F3D diff --git a/doc/user/COMMANDS.md b/doc/user/COMMANDS.md index d3942a6324..afe56e077b 100644 --- a/doc/user/COMMANDS.md +++ b/doc/user/COMMANDS.md @@ -19,6 +19,8 @@ The libf3d provides a few commands, many related to manipulating libf3d (options `reset option.name`: A command to reset a libf3d option to its default values, eg: `reset render.background.blur.coc`. +`clear`: A command to clear ImGui console. No argument. + `print option.name`: A command to print the value of an libf3d option, eg: `print scene.up.direction`. `cycle_animation`: A specific command to cycle `scene.animation.index` option using model information, No argument. @@ -36,6 +38,12 @@ eg: `roll_camera 120`. `print_scene_info`: A specific command to print information about the scene, No argument. +`print_coloring_info`: A specific command to print information about coloring settings, No argument. + +`print_mesh_info`: A specific command to print information from the mesh importer, No argument. + +`print_options_info`: A specific command to print configuration options that have a value, No argument. + `set_camera front/top/right/isometric`: A specific command to position the camera in the specified location relative to the model. Supports `front`, `top`, `right`, `isometric` arguments. eg: `set_camera top`. diff --git a/doc/user/CONFIGURATION_FILE.md b/doc/user/CONFIGURATION_FILE.md index 9554ff51e6..676c571683 100644 --- a/doc/user/CONFIGURATION_FILE.md +++ b/doc/user/CONFIGURATION_FILE.md @@ -65,7 +65,7 @@ The third block specifies raytracing usage for .gltf and .glb files. The last block specifies that volume rendering should be used with .mhd files. The following options cannot be set via config file: -`help`, `version`, `readers-list`, `config`, `no-config` and `input`. +`help`, `version`, `list-readers`, `list-rendering-backends`, `scan-plugins`, `config`, `no-config` and `input`. The following options are only taken on the first load: `no-render`, `output`, `position`, `resolution`, `frame-rate` and all testing options. @@ -115,7 +115,7 @@ interaction on the `Any+3` bind and even define a bindings that have multiple co on the `Ctrl+O` bind. Please note this configuration feature is only available through config file and not through the command line. -However, it is possible to check your current binding configuration by using the `--bindings-list` CLI options. +However, it is possible to check your current binding configuration by using the `--list-bindings` CLI options. ### Bind diff --git a/doc/user/INTERACTIONS.md b/doc/user/INTERACTIONS.md index 9bdf756748..17477b6a39 100644 --- a/doc/user/INTERACTIONS.md +++ b/doc/user/INTERACTIONS.md @@ -66,7 +66,6 @@ Camera Hotkeys: Other hotkeys and interactions are available: * H: key to toggle the display of a cheat sheet showing all these hotkeys and their statuses. -* ?: key to print scene description to the terminal. * CTRL + Q: close the window and quit F3D. * Esc: display/hide the console. * Space: play the animation if any. diff --git a/doc/user/OPTIONS.md b/doc/user/OPTIONS.md index 576fdbd723..26b36aadcb 100644 --- a/doc/user/OPTIONS.md +++ b/doc/user/OPTIONS.md @@ -13,7 +13,9 @@ Options|Type
Default|Description \-\-no-background|bool
false|Use with \-\-output to output a png file with a transparent background. -h, \-\-help||Print *help* and exit. Ignore `--verbose`. \-\-version||Show *version* information and exit. Ignore `--verbose`. -\-\-readers-list||List available *readers* and exit. Ignore `--verbose`. +\-\-list-readers||List available *readers* and exit. Ignore `--verbose`. +\-\-list-bindings||List available *bindings* and exit. Ignore `--verbose`. +\-\-list-rendering-backends||List available *rendering backends* and exit. Ignore `--verbose`. \-\-config=\|string
config|Specify the [configuration file](CONFIGURATION_FILE.md) to use. Supports absolute/relative path but also filename/filestem to search for in standard configuration file locations. \-\-no-config|bool
false|Do not read any configuration file and consider only the command line options. \-\-no-render|bool
false|Do not render anything and quit just after loading the first file, use with \-\-verbose to recover information about a file. diff --git a/java/F3DJavaBindings.cxx b/java/F3DJavaBindings.cxx index 9f9391949b..adc1b907f2 100644 --- a/java/F3DJavaBindings.cxx +++ b/java/F3DJavaBindings.cxx @@ -12,6 +12,8 @@ #define JAVA_BIND(Cls, Func) JNICALL Java_app_f3d_F3D_##Cls##_##Func +namespace fs = std::filesystem; + inline f3d::engine* GetEngine(JNIEnv* env, jobject self) { jclass cls = env->GetObjectClass(self); @@ -39,7 +41,7 @@ extern "C" JNIEXPORT void JAVA_BIND(Engine, setCachePath)(JNIEnv* env, jobject self, jstring path) { const char* str = env->GetStringUTFChars(path, nullptr); - GetEngine(env, self)->setCachePath(str); + GetEngine(env, self)->setCachePath(fs::path(str)); env->ReleaseStringUTFChars(path, str); } diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index cebe1f7a01..7d95444d8e 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -184,7 +184,8 @@ endif () if(F3D_STRICT_BUILD AND MSVC) # There are warnings in VTK related to deprecated features in C++17 - target_compile_definitions(libf3d PRIVATE _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) + # Using std::getenv is also considered unsecured on Windows + target_compile_definitions(libf3d PRIVATE _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS _CRT_SECURE_NO_WARNINGS) endif() if(APPLE) diff --git a/library/private/scene_impl.h b/library/private/scene_impl.h index 50180c21ea..3f0d4f5b3c 100644 --- a/library/private/scene_impl.h +++ b/library/private/scene_impl.h @@ -9,6 +9,7 @@ #ifndef f3d_scene_impl_h #define f3d_scene_impl_h +#include "log.h" #include "scene.h" #include @@ -46,6 +47,11 @@ class scene_impl : public scene */ void SetInteractor(interactor_impl* interactor); + /** + * Display available cameras in the log + */ + void PrintImporterDescription(log::VerboseLevel level); + private: class internals; std::unique_ptr Internals; diff --git a/library/private/window_impl.h b/library/private/window_impl.h index 872d2ffac6..addea7e956 100644 --- a/library/private/window_impl.h +++ b/library/private/window_impl.h @@ -15,6 +15,7 @@ #include "log.h" #include "window.h" +#include #include #include @@ -108,7 +109,7 @@ class window_impl : public window * Implementation only API. * Set the cache path. */ - void SetCachePath(const std::string& cachePath); + void SetCachePath(const std::filesystem::path& cachePath); /** * Implementation only API. diff --git a/library/public/engine.h b/library/public/engine.h index 7d0aac1bce..32760408f9 100644 --- a/library/public/engine.h +++ b/library/public/engine.h @@ -44,11 +44,17 @@ class F3D_EXPORT engine * Linux: Try GLX, then EGL, then OSMesa * Windows: Try Win32, then EGL, then OSMesa * macOS: Always use Cocoa + * Throws a context::loading_exception if a needed graphic library cannot be loaded + * Throws a context::symbol_exception if a needed symbol cannot be found in graphic library + * Throws a engine::no_window_exception if the window cannot be created for another reason + * Throws a engine::cache_exception if the default cache directory cannot be used */ [[nodiscard]] static engine create(bool offscreen = false); /** * Create an engine with no window. + * Throws a engine::no_window_exception if the window cannot be created for another reason + * Throws a engine::cache_exception if the default cache directory cannot be used */ [[nodiscard]] static engine createNone(); @@ -57,7 +63,10 @@ class F3D_EXPORT engine * Works on Linux only. * VTK >= 9.4 required. * Optionally, the window can be hidden by setting offscreen to true. - * Throws engine::loading_exception in case of window creation failure. + * Throws a context::loading_exception if a needed graphic library cannot be loaded + * Throws a context::symbol_exception if a needed symbol cannot be found in graphic library + * Throws a engine::no_window_exception if the window cannot be created for another reason + * Throws a engine::cache_exception if the default cache directory cannot be used */ [[nodiscard]] static engine createGLX(bool offscreen = false); @@ -66,7 +75,10 @@ class F3D_EXPORT engine * Works on Windows only. * VTK >= 9.4 required. * Optionally, the window can be hidden by setting offscreen to true. - * Throws engine::loading_exception in case of window creation failure. + * Throws a context::loading_exception if a needed graphic library cannot be loaded + * Throws a context::symbol_exception if a needed symbol cannot be found in graphic library + * Throws a engine::no_window_exception if the window cannot be created for another reason + * Throws a engine::cache_exception if the default cache directory cannot be used */ [[nodiscard]] static engine createWGL(bool offscreen = false); @@ -75,14 +87,20 @@ class F3D_EXPORT engine * VTK >= 9.4 required. * If several GPU are available, the environment variable * `VTK_DEFAULT_EGL_DEVICE_INDEX` allows its selection. - * Throws engine::loading_exception in case of failure. + * Throws a context::loading_exception if a needed graphic library cannot be loaded + * Throws a context::symbol_exception if a needed symbol cannot be found in graphic library + * Throws a engine::no_window_exception if the window cannot be created for another reason + * Throws a engine::cache_exception if the default cache directory cannot be used */ [[nodiscard]] static engine createEGL(); /** * Create an engine with an offscreen OSMesa window. * VTK >= 9.4 required. - * Throws engine::loading_exception in case of window creation failure. + * Throws a context::loading_exception if a needed graphic library cannot be loaded + * Throws a context::symbol_exception if a needed symbol cannot be found in graphic library + * Throws a engine::no_window_exception if the window cannot be created for another reason + * Throws a engine::cache_exception if the default cache directory cannot be used */ [[nodiscard]] static engine createOSMesa(); @@ -94,6 +112,8 @@ class F3D_EXPORT engine * \code{.cpp} * f3d::engine eng = f3d::engine::createExternal(glfwGetProcAddress); * \endcode + * Throws a engine::no_window_exception if the window cannot be created for another reason + * Throws a engine::cache_exception if the default cache directory cannot be used */ [[nodiscard]] static engine createExternal(const context::function& getProcAddress); @@ -101,7 +121,10 @@ class F3D_EXPORT engine * Create an engine with an external GLX context. * Equivalent to createExternal(f3d::context::glx()); * VTK >= 9.4 required. - * Throws context::loading_exception if GLX library is not found or if not running on Linux. + * Throws a context::loading_exception if a needed graphic library cannot be loaded + * Throws a context::symbol_exception if a needed symbol cannot be found in graphic library + * Throws a engine::no_window_exception if the window cannot be created for another reason + * Throws a engine::cache_exception if the default cache directory cannot be used */ [[nodiscard]] static engine createExternalGLX(); @@ -109,7 +132,10 @@ class F3D_EXPORT engine * Create an engine with an external WGL context. * Equivalent to createExternal(f3d::context::wgl()); * VTK >= 9.4 required. - * Throws context::loading_exception if WGL library is not found or if not running on Windows. + * Throws a context::loading_exception if a needed graphic library cannot be loaded + * Throws a context::symbol_exception if a needed symbol cannot be found in graphic library + * Throws a engine::no_window_exception if the window cannot be created for another reason + * Throws a engine::cache_exception if the default cache directory cannot be used */ [[nodiscard]] static engine createExternalWGL(); @@ -117,7 +143,10 @@ class F3D_EXPORT engine * Create an engine with an external COCOA context. * Equivalent to createExternal(f3d::context::cocoa()); * VTK >= 9.4 required. - * Throws context::loading_exception if WGL library is not found or if not running on Windows. + * Throws a context::loading_exception if a needed graphic library cannot be loaded + * Throws a context::symbol_exception if a needed symbol cannot be found in graphic library + * Throws a engine::no_window_exception if the window cannot be created for another reason + * Throws a engine::cache_exception if the default cache directory cannot be used */ [[nodiscard]] static engine createExternalCOCOA(); @@ -125,7 +154,10 @@ class F3D_EXPORT engine * Create an engine with an external EGL context. * Equivalent to createExternal(f3d::context::egl()); * VTK >= 9.4 required. - * Throws context::loading_exception if EGL library is not found. + * Throws a context::loading_exception if a needed graphic library cannot be loaded + * Throws a context::symbol_exception if a needed symbol cannot be found in graphic library + * Throws a engine::no_window_exception if the window cannot be created for another reason + * Throws a engine::cache_exception if the default cache directory cannot be used */ [[nodiscard]] static engine createExternalEGL(); @@ -133,7 +165,10 @@ class F3D_EXPORT engine * Create an engine with an external OSMesa context. * Equivalent to createExternal(f3d::context::osmesa()); * VTK >= 9.4 required. - * Throws context::loading_exception if OSMesa library is not found. + * Throws a context::loading_exception if a needed graphic library cannot be loaded + * Throws a context::symbol_exception if a needed symbol cannot be found in graphic library + * Throws a engine::no_window_exception if the window cannot be created for another reason + * Throws a engine::cache_exception if the default cache directory cannot be used */ [[nodiscard]] static engine createExternalOSMesa(); @@ -153,14 +188,15 @@ class F3D_EXPORT engine //@} /** - * Set the cache path. Must be an absolute path. + * Set the cache path. The provided path is used as is. * Currently, it's only used to store HDRI baked textures. * By default, the cache path is: * - Windows: %LOCALAPPDATA%\f3d * - Linux: ~/.cache/f3d * - macOS: ~/Library/Caches/f3d + * Throw a cache_exception if the provided cachePath cannot be used. */ - engine& setCachePath(const std::string& cachePath); + engine& setCachePath(const std::filesystem::path& cachePath); /** * Engine provide a default options that you can use using engine::getOptions(). @@ -198,21 +234,27 @@ class F3D_EXPORT engine */ [[nodiscard]] interactor& getInteractor(); + /** + * List rendering backends supported by libf3d. + * All backends have an associated boolean flag indicating if it can be used. + */ + static std::map getRenderingBackendList(); + /** * Load a plugin. - * Supports full path, relative path, and plugin name. + * The provided pathOrName can be a full path, relative path, or plugin name. * First try to load the plugin by name from the static plugins. * Then try to load the path provided as if it is a full path to a plugin. - * Then try to load a plugin by its name looking into the provided plugin search paths. - * Then try to load a plugin by its name relying on internal system (eg: LD_LIBRARY_PATH). + * Then try to load a plugin by its name looking into the provided plugin search paths (used as + * is). Then try to load a plugin by its name relying on internal system (eg: LD_LIBRARY_PATH). * The plugin "native" is always available and includes native VTK readers. * If built and available in your build, F3D is providing 5 additional plugins: * "alembic", "assimp", "draco", "exodus", "occt", "usd". * Custom plugins can also be available that F3D is not supporting officially. * Throw a plugin_exception if the plugin can't be loaded for some reason. */ - static void loadPlugin( - const std::string& nameOrPath, const std::vector& pluginSearchPaths = {}); + static void loadPlugin(const std::string& pathOrName, + const std::vector& pluginSearchPaths = {}); /** * Automatically load all the static plugins. @@ -221,11 +263,14 @@ class F3D_EXPORT engine static void autoloadPlugins(); /** - * List plugins based on associated json files located in the given directory. + * List plugins based on associated json files located in the given directory, used as is. * Listed plugins can be loaded using engine::loadPlugin function. * Note that the listed plugins may fail to load if the library is not found or incompatible. + * Return available plugins if any, or an empty vector if there are none or the provided path does + * not exist. */ - [[nodiscard]] static std::vector getPluginsList(const std::string& pluginPath); + [[nodiscard]] static std::vector getPluginsList( + const std::filesystem::path& pluginPath); /** * A structure providing information about the libf3d. @@ -296,6 +341,15 @@ class F3D_EXPORT engine explicit plugin_exception(const std::string& what = ""); }; + /** + * An exception that can be thrown by the engine + * when the cache cannot be used + */ + struct cache_exception : public exception + { + explicit cache_exception(const std::string& what = ""); + }; + private: class internals; internals* Internals; diff --git a/library/src/engine.cxx b/library/src/engine.cxx index ec01290948..5d083d529f 100644 --- a/library/src/engine.cxx +++ b/library/src/engine.cxx @@ -13,18 +13,31 @@ #include -#include #include -#include #include #include +namespace fs = std::filesystem; + namespace f3d { class engine::internals { public: + template + static bool BackendAvailable(F&& func) + { + try + { + return func() != nullptr; + } + catch (const context::loading_exception&) + { + return false; + } + } + std::unique_ptr Options; std::unique_ptr Window; std::unique_ptr Scene; @@ -39,18 +52,29 @@ engine::engine( // Ensure all lib initialization is done (once) detail::init::initialize(); - // build default cache path #if defined(_WIN32) - std::string cachePath = vtksys::SystemTools::GetEnv("LOCALAPPDATA"); - cachePath = cachePath + "/f3d"; + static constexpr const char* CACHE_ENV_VAR = "LOCALAPPDATA"; +#else + static constexpr const char* CACHE_ENV_VAR = "HOME"; +#endif + + char* env = std::getenv(CACHE_ENV_VAR); + if (!env) + { + throw engine::cache_exception( + std::string("Could not setup cache, please set ") + CACHE_ENV_VAR + " environment variable"); + } + + fs::path cachePath(env); + +#if defined(_WIN32) + cachePath /= "f3d"; #elif defined(__APPLE__) - std::string cachePath = vtksys::SystemTools::GetEnv("HOME"); - cachePath += "/Library/Caches/f3d"; + cachePath = cachePath / "Library" / "Caches" / "f3d"; #elif defined(__ANDROID__) - std::string cachePath = ""; // no default + // XXX: Android does not have a default cache location for now #elif defined(__unix__) - std::string cachePath = vtksys::SystemTools::GetEnv("HOME"); - cachePath += "/.cache/f3d"; + cachePath = cachePath / ".cache" / "f3d"; #else #error "Unsupported platform" #endif @@ -213,7 +237,21 @@ interactor& engine::getInteractor() } //---------------------------------------------------------------------------- -void engine::loadPlugin(const std::string& pathOrName, const std::vector& searchPaths) +std::map engine::getRenderingBackendList() +{ + std::map backends; + + backends["glx"] = engine::internals::BackendAvailable(context::glx); + backends["wgl"] = engine::internals::BackendAvailable(context::wgl); + backends["cocoa"] = engine::internals::BackendAvailable(context::cocoa); + backends["egl"] = engine::internals::BackendAvailable(context::egl); + backends["osmesa"] = engine::internals::BackendAvailable(context::osmesa); + + return backends; +} + +//---------------------------------------------------------------------------- +void engine::loadPlugin(const std::string& pathOrName, const std::vector& searchPaths) { if (pathOrName.empty()) { @@ -239,73 +277,78 @@ void engine::loadPlugin(const std::string& pathOrName, const std::vector( vtksys::DynamicLoader::GetSymbolAddress(handle, "init_plugin")); @@ -329,23 +372,17 @@ void engine::autoloadPlugins() } //---------------------------------------------------------------------------- -std::vector engine::getPluginsList(const std::string& pluginPath) +std::vector engine::getPluginsList(const fs::path& pluginPath) { - vtksys::Directory dir; constexpr std::string_view ext = ".json"; std::vector pluginNames; - - if (dir.Load(pluginPath)) + try { - for (unsigned long i = 0; i < dir.GetNumberOfFiles(); i++) + for (auto& entry : fs::directory_iterator(pluginPath)) { - std::string currentFile = dir.GetFile(i); - if (std::equal(ext.rbegin(), ext.rend(), currentFile.rbegin())) + const fs::path& fullPath = entry.path(); + if (fullPath.extension() == ext) { - std::string fullPath = dir.GetPath(); - fullPath += "/"; - fullPath += currentFile; - try { auto root = nlohmann::json::parse(std::ifstream(fullPath)); @@ -364,6 +401,9 @@ std::vector engine::getPluginsList(const std::string& pluginPath) } } } + catch (const fs::filesystem_error&) + { + } return pluginNames; } @@ -442,7 +482,7 @@ std::vector engine::getReadersInfo() } //---------------------------------------------------------------------------- -engine& engine::setCachePath(const std::string& cachePath) +engine& engine::setCachePath(const fs::path& cachePath) { this->Internals->Window->SetCachePath(cachePath); return *this; @@ -466,4 +506,10 @@ engine::plugin_exception::plugin_exception(const std::string& what) { } +//---------------------------------------------------------------------------- +engine::cache_exception::cache_exception(const std::string& what) + : exception(what) +{ +} + } diff --git a/library/src/interactor_impl.cxx b/library/src/interactor_impl.cxx index ad41261f5d..8ea7e86c84 100644 --- a/library/src/interactor_impl.cxx +++ b/library/src/interactor_impl.cxx @@ -7,6 +7,11 @@ #include "window_impl.h" #include "vtkF3DConsoleOutputWindow.h" + +#if F3D_MODULE_UI +#include "vtkF3DImguiConsole.h" +#endif + #include "vtkF3DInteractorEventRecorder.h" #include "vtkF3DInteractorStyle.h" #include "vtkF3DRenderer.h" @@ -608,6 +613,17 @@ interactor& interactor_impl::initCommands() check_args(args, 1, "reset"); this->Internals->Options.reset(args[0]); }); + this->addCommand("clear", + [&](const std::vector& args) + { + check_args(args, 0, "clear"); +#if F3D_MODULE_UI + vtkF3DImguiConsole* console = + vtkF3DImguiConsole::SafeDownCast(vtkOutputWindow::GetInstance()); + assert(console != nullptr); + console->Clear(); +#endif + }); this->addCommand("print", [&](const std::vector& args) { @@ -667,10 +683,27 @@ interactor& interactor_impl::initCommands() [&](const std::vector&) { this->Internals->IncreaseLightIntensity(true); }); this->addCommand("print_scene_info", + [&](const std::vector&) + { this->Internals->Window.PrintSceneDescription(log::VerboseLevel::INFO); }); + + this->addCommand("print_coloring_info", + [&](const std::vector&) + { this->Internals->Window.PrintColoringDescription(log::VerboseLevel::INFO); }); + + this->addCommand("print_mesh_info", + [&](const std::vector&) + { this->Internals->Scene.PrintImporterDescription(log::VerboseLevel::INFO); }); + + this->addCommand("print_options_info", [&](const std::vector&) { - this->Internals->Window.PrintColoringDescription(log::VerboseLevel::INFO); - this->Internals->Window.PrintSceneDescription(log::VerboseLevel::INFO); + for (const std::string& option : this->Internals->Options.getNames()) + { + const std::string val{ this->Internals->Options.getAsString(option) }; + std::string descr{}; + descr.append(option).append(": ").append(val); + log::print(log::VerboseLevel::INFO, descr); + } }); this->addCommand("set_camera", @@ -934,7 +967,6 @@ interactor& interactor_impl::initBindings() this->addBinding({mod_t::NONE, "H"}, "toggle ui.cheatsheet", "Others", std::bind(docStr, "Toggle cheatsheet display")); this->addBinding({mod_t::NONE, "Escape"}, "toggle ui.console", "Others", std::bind(docStr, "Toggle console display")); #endif - this->addBinding({mod_t::ANY, "Question"}, "print_scene_info", "Others", std::bind(docStr, "Print scene descr to terminal")); this->addBinding({mod_t::CTRL, "Q"}, "stop_interactor", "Others", std::bind(docStr, "Stop the interactor")); this->addBinding({mod_t::NONE, "Return"}, "reset_camera", "Others", std::bind(docStr, "Reset camera to initial parameters")); this->addBinding({mod_t::NONE, "Space"}, "toggle_animation", "Others", std::bind(docStr, "Play/Pause animation if any")); @@ -1046,14 +1078,13 @@ std::vector interactor_impl::getBinds() const std::pair interactor_impl::getBindingDocumentation( const interaction_bind_t& bind) const { - std::vector> doc; - auto it = this->Internals->Bindings.find(bind); + const auto& it = this->Internals->Bindings.find(bind); if (it == this->Internals->Bindings.end()) { throw interactor_impl::does_not_exists_exception( std::string("Bind: ") + bind.format() + " does not exists"); } - auto docFunc = it->second.DocumentationCallback; + const auto& docFunc = it->second.DocumentationCallback; return docFunc ? docFunc() : std::make_pair(std::string(), std::string()); } diff --git a/library/src/scene_impl.cxx b/library/src/scene_impl.cxx index 5cef75f0f5..5303b23f1e 100644 --- a/library/src/scene_impl.cxx +++ b/library/src/scene_impl.cxx @@ -141,29 +141,29 @@ class scene_impl::internals scene_impl::internals::DisplayAllInfo(this->MetaImporter, this->Window); } - static void DisplayImporterDescription(vtkImporter* importer) + static void DisplayImporterDescription(log::VerboseLevel level, vtkImporter* importer) { vtkIdType availCameras = importer->GetNumberOfCameras(); if (availCameras <= 0) { - log::debug("No camera available"); + log::print(level, "No camera available"); } else { - log::debug("Camera(s) available are:"); + log::print(level, "Camera(s) available are:"); } for (int i = 0; i < availCameras; i++) { - log::debug(i, ": ", importer->GetCameraName(i)); + log::print(level, i, ": ", importer->GetCameraName(i)); } - log::debug(""); - log::debug(importer->GetOutputsDescription(), "\n"); + log::print(level, ""); + log::print(level, importer->GetOutputsDescription(), "\n"); } static void DisplayAllInfo(vtkImporter* importer, window_impl& window) { // Display output description - scene_impl::internals::DisplayImporterDescription(importer); + scene_impl::internals::DisplayImporterDescription(log::VerboseLevel::DEBUG, importer); // Display coloring information window.PrintColoringDescription(log::VerboseLevel::DEBUG); @@ -338,4 +338,9 @@ void scene_impl::SetInteractor(interactor_impl* interactor) this->Internals->AnimationManager.SetInteractor(interactor); this->Internals->Interactor->SetAnimationManager(&this->Internals->AnimationManager); } + +void scene_impl::PrintImporterDescription(log::VerboseLevel level) +{ + scene_impl::internals::DisplayImporterDescription(level, this->Internals->MetaImporter); +} } diff --git a/library/src/window_impl.cxx b/library/src/window_impl.cxx index ec7cab309f..53107918a0 100644 --- a/library/src/window_impl.cxx +++ b/library/src/window_impl.cxx @@ -22,7 +22,6 @@ #include #include #include -#include #ifdef VTK_USE_X #include @@ -42,6 +41,8 @@ #include +namespace fs = std::filesystem; + namespace f3d::detail { class window_impl::internals @@ -52,14 +53,6 @@ class window_impl::internals { } - std::string GetCachePath() - { - // create directories if they do not exist - vtksys::SystemTools::MakeDirectory(this->CachePath); - - return this->CachePath; - } - static context::fptr SymbolLoader(void* userptr, const char* name) { assert(userptr != nullptr); @@ -106,7 +99,7 @@ class window_impl::internals vtkNew Renderer; const options& Options; interactor_impl* Interactor = nullptr; - std::string CachePath; + fs::path CachePath; context::function GetProcAddress; }; @@ -129,7 +122,7 @@ window_impl::window_impl(const options& options, const std::optional& type #if defined(VTK_OPENGL_HAS_EGL) this->Internals->RenWin = vtkSmartPointer::New(); #else - throw engine::no_window_exception("Window type is EGL but VTK EGL support is not enabled"); + assert(false); // Unreachable #endif } else if (type == Type::OSMESA) @@ -138,7 +131,7 @@ window_impl::window_impl(const options& options, const std::optional& type this->Internals->RenWin = vtkSmartPointer::New(); #else throw engine::no_window_exception( - "Window type is OSMesa but VTK OSMesa support is not enabled"); + "Window type is OSMesa but the underlying VTK version is not recent enough to support it"); #endif } else if (type == Type::GLX) @@ -146,13 +139,15 @@ window_impl::window_impl(const options& options, const std::optional& type #if defined(VTK_USE_X) this->Internals->RenWin = vtkSmartPointer::New(); #else - throw engine::no_window_exception("Window type is GLX but VTK GLX support is not enabled"); + assert(false); // Unreachable #endif } else if (type == Type::WGL) { #ifdef _WIN32 this->Internals->RenWin = vtkSmartPointer::New(); +#else + assert(false); // Unreachable #endif } else if (!type.has_value()) @@ -160,6 +155,8 @@ window_impl::window_impl(const options& options, const std::optional& type this->Internals->RenWin = internals::AutoBackendWindow(); } + // COCOA and WASM are not handled explicitly + // as there is no helper method to create them in engine if (this->Internals->RenWin == nullptr) { throw engine::no_window_exception("Cannot create a window"); @@ -186,6 +183,9 @@ window_impl::window_impl(const options& options, const std::optional& type this->Internals->Camera = std::make_unique(); this->Internals->Camera->SetVTKRenderer(this->Internals->Renderer); + this->Internals->Renderer->SetConsoleBadgeEnabled( + !offscreen || std::getenv("CTEST_F3D_CONSOLE_BADGE")); + this->Initialize(); log::debug("VTK window class type is ", this->Internals->RenWin->GetClassName()); @@ -371,7 +371,7 @@ void window_impl::UpdateDynamicOptions() } // Set the cache path if not already - renderer->SetCachePath(this->Internals->GetCachePath()); + renderer->SetCachePath(this->Internals->CachePath.string()); // Make sure lights are created before we take options into account renderer->UpdateLights(); @@ -549,8 +549,18 @@ void window_impl::SetImporter(vtkF3DMetaImporter* importer) } //---------------------------------------------------------------------------- -void window_impl::SetCachePath(const std::string& cachePath) +void window_impl::SetCachePath(const fs::path& cachePath) { + try + { + // create directories if they do not exist + fs::create_directories(cachePath); + } + catch (const fs::filesystem_error& ex) + { + throw engine::cache_exception(std::string("Could not use cache: ") + ex.what()); + } + this->Internals->CachePath = cachePath; } diff --git a/library/testing/TestSDKEngine.cxx b/library/testing/TestSDKEngine.cxx index 7aed0478b3..bb7a4f4882 100644 --- a/library/testing/TestSDKEngine.cxx +++ b/library/testing/TestSDKEngine.cxx @@ -12,7 +12,8 @@ int TestSDKEngine(int argc, char* argv[]) f3d::log::setVerboseLevel(f3d::log::VerboseLevel::DEBUG); // clang-format off - // Load all plugins, built or not + // Load all plugins, built or not, already loaded or not + try { f3d::engine::loadPlugin("native", {argv[3]}); } catch (...) {} try { f3d::engine::loadPlugin("alembic", {argv[3]}); } catch (...) {} try { f3d::engine::loadPlugin("assimp", {argv[3]}); } catch (...) {} try { f3d::engine::loadPlugin("draco", {argv[3]}); } catch (...) {} @@ -71,5 +72,9 @@ int TestSDKEngine(int argc, char* argv[]) return EXIT_FAILURE; } + // coverage for getPluginList + std::ignore = f3d::engine::getPluginsList(std::string(argv[1]) + "configs"); + std::ignore = f3d::engine::getPluginsList("inexistent"); + return EXIT_SUCCESS; } diff --git a/library/testing/TestSDKEngineExceptions.cxx b/library/testing/TestSDKEngineExceptions.cxx index f5f4dc60fb..d971404bc9 100644 --- a/library/testing/TestSDKEngineExceptions.cxx +++ b/library/testing/TestSDKEngineExceptions.cxx @@ -1,99 +1,68 @@ +#include "PseudoUnitTest.h" + #include #include #include -#include +#include + +#include + +namespace fs = std::filesystem; int TestSDKEngineExceptions(int argc, char* argv[]) { - f3d::engine eng = f3d::engine::createNone(); + PseudoUnitTest test; - try - { - const f3d::window& win = eng.getWindow(); - std::cerr << "An exception has not been thrown when getting a non-existent window" << std::endl; - return EXIT_FAILURE; - } - catch (const f3d::engine::no_window_exception& ex) { - std::cout << ex.what() << std::endl; - } + f3d::engine eng = f3d::engine::createNone(); + test.expect( + "get non-existent window", [&]() { std::ignore = eng.getWindow(); }); + test.expect( + "get non-existent interactor", [&]() { std::ignore = eng.getInteractor(); }); - try - { - const f3d::interactor& inter = eng.getInteractor(); - std::cerr << "An exception has not been thrown when getting a non-existent interactor" - << std::endl; - return EXIT_FAILURE; - } - catch (const f3d::engine::no_interactor_exception& ex) - { - std::cout << ex.what() << std::endl; - } + // Test setCachePath error handling + test.expect("set cache path with invalid long name", + [&]() { eng.setCachePath("/" + std::string(257, 'x')); }); -// These tests are defined for coverage -#ifdef __linux__ - try - { - eng = f3d::engine::createWGL(); - std::cerr << "An exception has not been thrown when creating a WGL engine on Linux" - << std::endl; - return EXIT_FAILURE; - } - catch (const f3d::context::loading_exception& ex) - { - std::cout << ex.what() << std::endl; + // cover operator=(engine&&) + eng = f3d::engine::create(false); + test("engine assignment operator", eng.getWindow().isOffscreen() == false); } - try - { - eng = f3d::engine::createExternalWGL(); - std::cerr << "An exception has not been thrown when creating an external WGL engine on Linux" - << std::endl; - return EXIT_FAILURE; - } - catch (const f3d::context::loading_exception& ex) - { - std::cout << ex.what() << std::endl; - } +#ifdef __linux__ + // Test incorrect engine configuration + test.expect( + "create WGL engine on linux", [&]() { std::ignore = f3d::engine::createWGL(); }); + test.expect("create external WGL engine on linux", + [&]() { std::ignore = f3d::engine::createExternalWGL(); }); + test.expect("create external COCOA engine on linux", + [&]() { std::ignore = f3d::engine::createExternalCOCOA(); }); + test.expect( + "create external engine with invalid library", [&]() { + std::ignore = f3d::engine::createExternal(f3d::context::getSymbol("invalid", "invalid")); + }); + test.expect("create external engine with invalid symbol", [&]() { + std::ignore = f3d::engine::createExternal(f3d::context::getSymbol("GLX", "invalid")); + }); +#endif - try - { - eng = f3d::engine::createExternalCOCOA(); - std::cerr << "An exception has not been thrown when creating an external COCOA engine on Linux" - << std::endl; - return EXIT_FAILURE; - } - catch (const f3d::context::loading_exception& ex) - { - std::cout << ex.what() << std::endl; - } + // Test loadPlugin error handling + test.expect("load plugin with invalid library", + [&]() { f3d::engine::loadPlugin(std::string(argv[1]) + "data/invalid.so"); }); - try - { - eng = f3d::engine::createExternal(f3d::context::getSymbol("invalid", "invalid")); - std::cerr << "An exception has not been thrown when loading an invalid library" << std::endl; - return EXIT_FAILURE; - } - catch (const f3d::context::loading_exception& ex) - { - std::cout << ex.what() << std::endl; - } + test.expect("load plugin with invalid library from search paths", + [&]() { f3d::engine::loadPlugin("invalid", { fs::path(std::string(argv[1]) + "data") }); }); - try - { - eng = f3d::engine::createExternal(f3d::context::getSymbol("GLX", "invalid")); - std::cerr << "An exception has not been thrown when loading an invalid symbol" << std::endl; - return EXIT_FAILURE; - } - catch (const f3d::context::symbol_exception& ex) - { - std::cout << ex.what() << std::endl; - } + test.expect("load plugin with invalid long name", + [&]() { f3d::engine::loadPlugin("/" + std::string(257, 'x') + "/file.ext"); }); - // cover operator=(engine&&) - eng = f3d::engine::create(false); +#ifdef __linux__ + // Test error handling without "HOME" set + unsetenv("HOME"); + test.expect( + "Create engine without HOME set", [&]() { std::ignore = f3d::engine::createNone(); }); #endif - return EXIT_SUCCESS; + return test.result(); } diff --git a/library/testing/TestSDKInteractorCommand.cxx b/library/testing/TestSDKInteractorCommand.cxx index 50182c700b..ae9e0329ec 100644 --- a/library/testing/TestSDKInteractorCommand.cxx +++ b/library/testing/TestSDKInteractorCommand.cxx @@ -24,6 +24,12 @@ int TestSDKInteractorCommand(int argc, char* argv[]) inter.triggerCommand("reset render.hdri.file"); test("triggerCommand reset optional", options.render.hdri.file.has_value() == false); + // Test clear +#if F3D_MODULE_UI + inter.triggerCommand("print_scene_info"); + test("triggerCommand clear", (inter.triggerCommand("clear") == true)); +#endif + // Test toggle inter.triggerCommand("toggle model.scivis.cells"); test("triggerCommand toggle", options.model.scivis.cells == true); diff --git a/library/testing/TestSDKInteractorDocumentation.cxx b/library/testing/TestSDKInteractorDocumentation.cxx index 6d91be923e..64d464ff3b 100644 --- a/library/testing/TestSDKInteractorDocumentation.cxx +++ b/library/testing/TestSDKInteractorDocumentation.cxx @@ -31,10 +31,10 @@ int TestSDKInteractorDocumentation(int argc, char* argv[]) { // check exceptions for invalid args test.expect( - "Initial invalid group", [&]() { inter.getBindsForGroup("Invalid"); }); + "Initial invalid group", [&]() { std::ignore = inter.getBindsForGroup("Invalid"); }); test.expect("Initial invalid bind", [&]() { - inter.getBindingDocumentation({ mod_t::ANY, "Invalid" }); + std::ignore = inter.getBindingDocumentation({ mod_t::ANY, "Invalid" }); }); } @@ -53,10 +53,10 @@ int TestSDKInteractorDocumentation(int argc, char* argv[]) test("Empty binds size", inter.getBinds().size() == 0); // check exceptions for invalid args test.expect( - "Empty group", [&]() { inter.getBindsForGroup("Camera"); }); + "Empty group", [&]() { std::ignore = inter.getBindsForGroup("Camera"); }); test.expect("Empty bind", [&]() { - inter.getBindingDocumentation({ mod_t::ANY, "5" }); + std::ignore = inter.getBindingDocumentation({ mod_t::ANY, "5" }); }); } diff --git a/python/F3DPythonBindings.cxx b/python/F3DPythonBindings.cxx index 480335315d..96c54a7f98 100644 --- a/python/F3DPythonBindings.cxx +++ b/python/F3DPythonBindings.cxx @@ -404,7 +404,8 @@ PYBIND11_MODULE(pyf3d, module) "autoload_plugins", &f3d::engine::autoloadPlugins, "Automatically load internal plugins") .def_static("get_plugins_list", &f3d::engine::getPluginsList) .def_static("get_lib_info", &f3d::engine::getLibInfo, py::return_value_policy::reference) - .def_static("get_readers_info", &f3d::engine::getReadersInfo); + .def_static("get_readers_info", &f3d::engine::getReadersInfo) + .def_static("get_rendering_backend_list", &f3d::engine::getRenderingBackendList); // libInformation py::class_(module, "LibInformation") diff --git a/python/testing/test_engine.py b/python/testing/test_engine.py index a8f091a782..95009f464c 100644 --- a/python/testing/test_engine.py +++ b/python/testing/test_engine.py @@ -62,3 +62,9 @@ def test_get_readers_info(): assert isinstance(reader.plugin_name, str) and reader.plugin_name assert isinstance(reader.has_scene_reader, bool) assert isinstance(reader.has_geometry_reader, bool) + + +def test_get_rendering_backend_list(): + backends = f3d.Engine.get_rendering_backend_list() + + assert isinstance(backends, dict) and len(backends) == 5 diff --git a/testing/baselines/TestInteractionCheatsheetConfigFile.png b/testing/baselines/TestInteractionCheatsheetConfigFile.png index a72c6ab111..452e42344f 100644 --- a/testing/baselines/TestInteractionCheatsheetConfigFile.png +++ b/testing/baselines/TestInteractionCheatsheetConfigFile.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e44fe81bac3376181b6d9a4a687956c1d0fd07e20bd14ddc520b0720c1ef0813 -size 254888 +oid sha256:3e98d82eaba786e8f2319773e1a61e397f9c098d9b83db9166015b745c06c901 +size 250941 diff --git a/testing/baselines/TestInteractionCheatsheetConfigFileRaytracing.png b/testing/baselines/TestInteractionCheatsheetConfigFileRaytracing.png index 2afd9d2e06..0dcb52ec21 100644 --- a/testing/baselines/TestInteractionCheatsheetConfigFileRaytracing.png +++ b/testing/baselines/TestInteractionCheatsheetConfigFileRaytracing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc0bf0ba171e7ee965065510cd504c2b5502b0273ad8ce2d83f9a5b0c36fd9d9 -size 260087 +oid sha256:23c99f0437fec79df9b974333d5406210dcb7dfa86dcdac1c1ece8320d7dc141 +size 258096 diff --git a/testing/baselines/TestInteractionConsoleClear.png b/testing/baselines/TestInteractionConsoleClear.png new file mode 100644 index 0000000000..1f265e22ce --- /dev/null +++ b/testing/baselines/TestInteractionConsoleClear.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:adc89bb41a18c71ffe2941a80b2d0a45f2976c406ef3cc9eb8078f8f02ff4e8e +size 17706 diff --git a/testing/baselines/TestInteractionConsoleTypingSceneInfo.png b/testing/baselines/TestInteractionConsoleTypingSceneInfo.png index 8e05e64365..bd5ba097d7 100644 --- a/testing/baselines/TestInteractionConsoleTypingSceneInfo.png +++ b/testing/baselines/TestInteractionConsoleTypingSceneInfo.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab2ccb17632c90d069ff787745b21ca13f12cc5f6d5e1f0fc288d1a1e1cf9298 -size 19869 +oid sha256:a37855f19a18d791efad08e012c3d74c2b90a881d920fa14e5ac75d7be026167 +size 18041 diff --git a/testing/baselines/TestSDKInteractorCallBackDefault.png b/testing/baselines/TestSDKInteractorCallBackDefault.png index 8a9166935d..1b2c28c17c 100644 --- a/testing/baselines/TestSDKInteractorCallBackDefault.png +++ b/testing/baselines/TestSDKInteractorCallBackDefault.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:98faa9ce96b4bc96e8f92c114039d3d9f9c2b076b59c9b1beccd29b34b928c36 -size 29622 +oid sha256:a40cafb0a5ff4adede4123de4ccaf1575e91e99ceda87972f11683f782ac327e +size 29286 diff --git a/testing/baselines/TestSDKInteractorCallBackDefaultAgain.png b/testing/baselines/TestSDKInteractorCallBackDefaultAgain.png index e5dfb1c206..bd6017ddfe 100644 --- a/testing/baselines/TestSDKInteractorCallBackDefaultAgain.png +++ b/testing/baselines/TestSDKInteractorCallBackDefaultAgain.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:44518fc48c217066211eaa25df80afea4ef49591a6a8d823f3462617ef893e84 -size 81849 +oid sha256:0d01d95e5cc331366528c0b249b4863cd398fa216f3ef6f351effeb0112da663 +size 80703 diff --git a/testing/baselines/TestSDKInteractorCallBackModified.png b/testing/baselines/TestSDKInteractorCallBackModified.png index be5bd56e0b..5e2b2b3605 100644 --- a/testing/baselines/TestSDKInteractorCallBackModified.png +++ b/testing/baselines/TestSDKInteractorCallBackModified.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f6edb962ab029c374879b9309a109bdcd817209cb87fd9c256d392d2745c425 -size 60698 +oid sha256:9ca8ce62e5927f324b6a09fa22433c5d8b9fd13d4fee168f07857a4d6ec79944 +size 60327 diff --git a/testing/baselines/TestSDKInteractorCallBackModifiedAgain.png b/testing/baselines/TestSDKInteractorCallBackModifiedAgain.png index be5bd56e0b..5e2b2b3605 100644 --- a/testing/baselines/TestSDKInteractorCallBackModifiedAgain.png +++ b/testing/baselines/TestSDKInteractorCallBackModifiedAgain.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f6edb962ab029c374879b9309a109bdcd817209cb87fd9c256d392d2745c425 -size 60698 +oid sha256:9ca8ce62e5927f324b6a09fa22433c5d8b9fd13d4fee168f07857a4d6ec79944 +size 60327 diff --git a/testing/data/libf3d-plugin-invalid.so b/testing/data/libf3d-plugin-invalid.so new file mode 100644 index 0000000000..8575163cc5 --- /dev/null +++ b/testing/data/libf3d-plugin-invalid.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e2df53aec82f9d93ad26e57748dd2e61299bb3a1cf14f55005f180e75e960789 +size 28 diff --git a/testing/recordings/TestInteractionConsoleClear.log b/testing/recordings/TestInteractionConsoleClear.log new file mode 100644 index 0000000000..dcacde83c2 --- /dev/null +++ b/testing/recordings/TestInteractionConsoleClear.log @@ -0,0 +1,125 @@ +# StreamVersion 1.2 +RenderEvent 0 0 0 0 0 0 0 + +KeyPressEvent 0 0 0 27 1 Escape 0 +CharEvent 0 0 0 27 1 Escape 0 +KeyReleaseEvent 0 0 0 27 1 Escape 0 + +KeyPressEvent 0 0 0 101 1 e 0 +CharEvent 0 0 0 101 1 e 0 +KeyReleaseEvent 0 0 0 101 1 e 0 + +KeyPressEvent 0 0 0 27 1 Escape 0 +CharEvent 0 0 0 27 1 Escape 0 +KeyReleaseEvent 0 0 0 27 1 Escape 0 + +KeyPressEvent 0 0 0 112 1 p 0 +CharEvent 0 0 0 112 1 p 0 +KeyReleaseEvent 0 0 0 112 1 p 0 + +KeyPressEvent 0 0 0 114 1 r 0 +CharEvent 0 0 0 114 1 r 0 +KeyReleaseEvent 0 0 0 114 1 r 0 + +KeyPressEvent 0 0 0 105 1 i 0 +CharEvent 0 0 0 105 1 i 0 +KeyReleaseEvent 0 0 0 105 1 i 0 + +KeyPressEvent 0 0 0 110 1 n 0 +CharEvent 0 0 0 110 1 n 0 +KeyReleaseEvent 0 0 0 110 1 n 0 + +KeyPressEvent 0 0 0 116 1 t 0 +CharEvent 0 0 0 116 1 t 0 +KeyReleaseEvent 0 0 0 116 1 t 0 + +KeyPressEvent 0 0 0 116 1 t 0 +CharEvent 0 0 0 116 1 t 0 +KeyReleaseEvent 0 0 0 116 1 t 0 + +KeyPressEvent 0 0 0 8 1 BackSpace 0 +CharEvent 0 0 0 8 1 BackSpace 0 +KeyReleaseEvent 0 0 0 8 1 BackSpace 0 + +KeyPressEvent 0 0 1 0 1 Shift_L 0 +KeyPressEvent 0 0 1 95 1 underscore 0 +CharEvent 0 0 1 95 1 underscore 0 +KeyReleaseEvent 0 0 1 95 1 underscore 0 +KeyReleaseEvent 0 0 0 0 1 Shift_L 0 + +KeyPressEvent 0 0 0 115 1 s 0 +CharEvent 0 0 0 115 1 s 0 +KeyReleaseEvent 0 0 0 115 1 s 0 + +KeyPressEvent 0 0 0 99 1 c 0 +CharEvent 0 0 0 99 1 c 0 +KeyReleaseEvent 0 0 0 99 1 c 0 + +KeyPressEvent 0 0 0 101 1 e 0 +CharEvent 0 0 0 101 1 e 0 +KeyReleaseEvent 0 0 0 101 1 e 0 + +KeyPressEvent 0 0 0 101 1 e 0 +CharEvent 0 0 0 101 1 e 0 +KeyReleaseEvent 0 0 0 101 1 e 0 + +KeyPressEvent 0 0 0 0 1 Left 0 +KeyReleaseEvent 0 0 0 0 1 Left 0 + +KeyPressEvent 0 0 0 110 1 n 0 +CharEvent 0 0 0 110 1 n 0 +KeyReleaseEvent 0 0 0 110 1 n 0 + +KeyPressEvent 0 0 0 0 1 Right 0 +KeyReleaseEvent 0 0 0 0 1 Right 0 + +KeyPressEvent 0 0 1 0 1 Shift_L 0 +KeyPressEvent 0 0 1 95 1 underscore 0 +CharEvent 0 0 1 95 1 underscore 0 +KeyReleaseEvent 0 0 1 95 1 underscore 0 +KeyReleaseEvent 0 0 0 0 1 Shift_L 0 + +KeyPressEvent 0 0 0 105 1 i 0 +CharEvent 0 0 0 105 1 i 0 +KeyReleaseEvent 0 0 0 105 1 i 0 + +KeyPressEvent 0 0 0 110 1 n 0 +CharEvent 0 0 0 110 1 n 0 +KeyReleaseEvent 0 0 0 110 1 n 0 + +KeyPressEvent 0 0 0 102 1 f 0 +CharEvent 0 0 0 102 1 f 0 +KeyReleaseEvent 0 0 0 102 1 f 0 + +KeyPressEvent 0 0 0 111 1 o 0 +CharEvent 0 0 0 111 1 o 0 +KeyReleaseEvent 0 0 0 111 1 o 0 + +KeyPressEvent 0 0 0 13 1 Return 0 +CharEvent 0 0 0 13 1 Return 0 +KeyReleaseEvent 0 0 0 13 1 Return 0 + +KeyPressEvent 0 0 0 99 1 c 0 +CharEvent 0 0 0 99 1 c 0 +KeyReleaseEvent 0 0 0 99 1 c 0 + +KeyPressEvent 0 0 0 108 1 l 0 +CharEvent 0 0 0 108 1 l 0 +KeyReleaseEvent 0 0 0 108 1 l 0 + +KeyPressEvent 0 0 0 101 1 e 0 +CharEvent 0 0 0 101 1 e 0 +KeyReleaseEvent 0 0 0 101 1 e 0 + +KeyPressEvent 0 0 0 97 1 a 0 +CharEvent 0 0 0 97 1 a 0 +KeyReleaseEvent 0 0 0 97 1 a 0 + +KeyPressEvent 0 0 0 114 1 r 0 +CharEvent 0 0 0 114 1 r 0 +KeyReleaseEvent 0 0 0 114 1 r 0 + +KeyPressEvent 0 0 0 13 1 Return 0 +CharEvent 0 0 0 13 1 Return 0 +KeyReleaseEvent 0 0 0 13 1 Return 0 + diff --git a/testing/scripts/TestCommandScriptPrintColoring.txt b/testing/scripts/TestCommandScriptPrintColoring.txt new file mode 100644 index 0000000000..1eb8fa7bca --- /dev/null +++ b/testing/scripts/TestCommandScriptPrintColoring.txt @@ -0,0 +1 @@ +print_coloring_info diff --git a/testing/scripts/TestCommandScriptPrintMesh.txt b/testing/scripts/TestCommandScriptPrintMesh.txt new file mode 100644 index 0000000000..ba22450d28 --- /dev/null +++ b/testing/scripts/TestCommandScriptPrintMesh.txt @@ -0,0 +1 @@ +print_mesh_info diff --git a/testing/scripts/TestCommandScriptPrintOptions.txt b/testing/scripts/TestCommandScriptPrintOptions.txt new file mode 100644 index 0000000000..41d879d670 --- /dev/null +++ b/testing/scripts/TestCommandScriptPrintOptions.txt @@ -0,0 +1 @@ +print_options_info diff --git a/testing/scripts/TestCommandScriptPrintScene.txt b/testing/scripts/TestCommandScriptPrintScene.txt new file mode 100644 index 0000000000..939dd57f2f --- /dev/null +++ b/testing/scripts/TestCommandScriptPrintScene.txt @@ -0,0 +1 @@ +print_scene_info diff --git a/vtkext/private/module/vtkF3DImguiConsole.cxx b/vtkext/private/module/vtkF3DImguiConsole.cxx index 9b405e5f71..87e60db1f9 100644 --- a/vtkext/private/module/vtkF3DImguiConsole.cxx +++ b/vtkext/private/module/vtkF3DImguiConsole.cxx @@ -197,3 +197,11 @@ void vtkF3DImguiConsole::ShowBadge() ImGui::End(); } } + +//---------------------------------------------------------------------------- +void vtkF3DImguiConsole::Clear() +{ + this->Pimpl->Logs.clear(); + this->Pimpl->NewError = false; + this->Pimpl->NewWarning = false; +} diff --git a/vtkext/private/module/vtkF3DImguiConsole.h b/vtkext/private/module/vtkF3DImguiConsole.h index 859218fcbd..e62fb427ad 100644 --- a/vtkext/private/module/vtkF3DImguiConsole.h +++ b/vtkext/private/module/vtkF3DImguiConsole.h @@ -43,6 +43,11 @@ class vtkF3DImguiConsole : public vtkF3DConsoleOutputWindow */ void ShowBadge(); + /** + * Clear console + */ + void Clear(); + protected: vtkF3DImguiConsole(); ~vtkF3DImguiConsole() override; diff --git a/vtkext/private/module/vtkF3DRenderer.cxx b/vtkext/private/module/vtkF3DRenderer.cxx index 31e50b1e02..8d590f05d8 100644 --- a/vtkext/private/module/vtkF3DRenderer.cxx +++ b/vtkext/private/module/vtkF3DRenderer.cxx @@ -637,8 +637,8 @@ void vtkF3DRenderer::ConfigureGridUsingCurrentActors() void vtkF3DRenderer::SetHDRIFile(const std::optional& hdriFile) { // Check HDRI is different than current one - std::optional collapsedHdriFile; - if (hdriFile.has_value()) + std::string collapsedHdriFile; + if (hdriFile.has_value() && !hdriFile.value().empty()) { collapsedHdriFile = vtksys::SystemTools::CollapseFullPath(hdriFile.value()); } @@ -770,25 +770,25 @@ void vtkF3DRenderer::ConfigureHDRIReader() { this->UseDefaultHDRI = false; this->HDRIReader = nullptr; - if (this->HDRIFile.has_value()) + if (!this->HDRIFile.empty()) { - if (!vtksys::SystemTools::FileExists(this->HDRIFile.value(), true)) + if (!vtksys::SystemTools::FileExists(this->HDRIFile, true)) { F3DLog::Print( - F3DLog::Severity::Warning, std::string("HDRI file does not exist ") + this->HDRIFile.value()); + F3DLog::Severity::Warning, std::string("HDRI file does not exist ") + this->HDRIFile); } else { this->HDRIReader = vtkSmartPointer::Take( - vtkImageReader2Factory::CreateImageReader2(this->HDRIFile.value().c_str())); + vtkImageReader2Factory::CreateImageReader2(this->HDRIFile.c_str())); if (this->HDRIReader) { - this->HDRIReader->SetFileName(this->HDRIFile.value().c_str()); + this->HDRIReader->SetFileName(this->HDRIFile.c_str()); } else { F3DLog::Print(F3DLog::Severity::Warning, - std::string("Cannot open HDRI file ") + this->HDRIFile.value() + + std::string("Cannot open HDRI file ") + this->HDRIFile + std::string(". Using default HDRI")); } } @@ -821,8 +821,8 @@ void vtkF3DRenderer::ConfigureHDRIHash() } else { - // Compute HDRI MD5, here we know the HDRIFile has a value - this->HDRIHash = ::ComputeFileHash(this->HDRIFile.value()); + // Compute HDRI MD5, here we know the HDRIFile is not empty + this->HDRIHash = ::ComputeFileHash(this->HDRIFile); } this->HasValidHDRIHash = true; this->CreateCacheDirectory(); @@ -1080,7 +1080,7 @@ void vtkF3DRenderer::ConfigureTextActors() // Font this->DropZoneActor->GetTextProperty()->SetFontFamilyToCourier(); - if (this->FontFile.has_value()) + if (this->FontFile.has_value() && !this->FontFile.value().empty()) { std::string tmpFontFile = vtksys::SystemTools::CollapseFullPath(this->FontFile.value()); if (vtksys::SystemTools::FileExists(tmpFontFile, true)) @@ -2639,3 +2639,9 @@ void vtkF3DRenderer::SetUIDeltaTime(double time) { this->UIActor->SetDeltaTime(time); } + +//---------------------------------------------------------------------------- +void vtkF3DRenderer::SetConsoleBadgeEnabled(bool enabled) +{ + this->UIActor->SetConsoleBadgeEnabled(enabled); +} diff --git a/vtkext/private/module/vtkF3DRenderer.h b/vtkext/private/module/vtkF3DRenderer.h index 40c030da9d..c2b33d6714 100644 --- a/vtkext/private/module/vtkF3DRenderer.h +++ b/vtkext/private/module/vtkF3DRenderer.h @@ -377,6 +377,11 @@ class vtkF3DRenderer : public vtkOpenGLRenderer */ void SetUIDeltaTime(double time); + /** + * Set console badge enabled status + */ + void SetConsoleBadgeEnabled(bool enabled); + private: vtkF3DRenderer(); ~vtkF3DRenderer() override; @@ -527,7 +532,7 @@ class vtkF3DRenderer : public vtkOpenGLRenderer int GridSubdivisions = 10; double GridColor[3] = { 0.0, 0.0, 0.0 }; - std::optional HDRIFile; + std::string HDRIFile; vtkSmartPointer HDRIReader; bool HasValidHDRIReader = false; bool UseDefaultHDRI = false; diff --git a/vtkext/private/module/vtkF3DUIActor.cxx b/vtkext/private/module/vtkF3DUIActor.cxx index f73c8beeb8..5f5f745328 100644 --- a/vtkext/private/module/vtkF3DUIActor.cxx +++ b/vtkext/private/module/vtkF3DUIActor.cxx @@ -48,6 +48,12 @@ void vtkF3DUIActor::SetConsoleVisibility(bool show) this->ConsoleVisible = show; } +//---------------------------------------------------------------------------- +void vtkF3DUIActor::SetConsoleBadgeEnabled(bool enabled) +{ + this->ConsoleBadgeEnabled = enabled; +} + //---------------------------------------------------------------------------- void vtkF3DUIActor::SetCheatSheet(const std::vector& cheatsheet) { @@ -113,7 +119,7 @@ int vtkF3DUIActor::RenderOverlay(vtkViewport* vp) { this->RenderConsole(); } - else + else if (this->ConsoleBadgeEnabled) { this->RenderConsoleBadge(); } diff --git a/vtkext/private/module/vtkF3DUIActor.h b/vtkext/private/module/vtkF3DUIActor.h index a8ef79a1c5..419d5d67ab 100644 --- a/vtkext/private/module/vtkF3DUIActor.h +++ b/vtkext/private/module/vtkF3DUIActor.h @@ -62,6 +62,12 @@ class vtkF3DUIActor : public vtkProp */ void SetConsoleVisibility(bool show); + /** + * Set the console badge enabled status + * False by default + */ + void SetConsoleBadgeEnabled(bool enabled); + /** * Set the cheatsheet string * Empty by default @@ -150,6 +156,7 @@ class vtkF3DUIActor : public vtkProp std::vector CheatSheet; bool ConsoleVisible = false; + bool ConsoleBadgeEnabled = false; bool FpsCounterVisible = false; int FpsValue = 0;