diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 423781fa7..9a9b44e7b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -77,8 +77,8 @@ jobs: fi build_linux_gcc: - name: Linux GCC 11.4.0 - runs-on: ubuntu-22.04 + name: Linux GCC 13.3.0 + runs-on: ubuntu-24.04 if: > github.event_name == 'pull_request' || ( contains(github.ref, 'main') && !contains(github.event.head_commit.message, '[no-ci]') ) || @@ -99,7 +99,7 @@ jobs: run: | sudo apt-get update -q sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev libx11-dev - sudo apt-get install libxi-dev libgconf-2-4 libboost-all-dev lcov xvfb + sudo apt-get install libxi-dev lcov xvfb libfreetype-dev - name: Build Externals run: > ./make_externals.sh -G "Unix Makefiles" @@ -130,15 +130,15 @@ jobs: path-to-lcov: ./build/linux-Release/coverage.info build_linux_clang: - name: Linux Clang 14.0 - runs-on: ubuntu-22.04 + name: Linux Clang 18.0 + runs-on: ubuntu-24.04 if: > github.event_name == 'pull_request' || ( contains(github.ref, 'main') && !contains(github.event.head_commit.message, '[no-ci]') ) || contains(github.event.head_commit.message, '[run-ci]') env: - CC: clang-14 - CXX: clang++-14 + CC: clang-18 + CXX: clang++-18 COSMOSCOUT_USE_PCH: false COSMOSCOUT_USE_UNITY_BUILD: false steps: @@ -154,7 +154,7 @@ jobs: run: | sudo apt-get update -q sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev libx11-dev - sudo apt-get install libxi-dev libgconf-2-4 libboost-all-dev + sudo apt-get install libxi-dev libfreetype-dev - name: Build Externals run: > ./make_externals.sh -G "Unix Makefiles" @@ -184,7 +184,6 @@ jobs: ( contains(github.ref, 'main') && !contains(github.event.head_commit.message, '[no-ci]') ) || contains(github.event.head_commit.message, '[run-ci]') env: - BOOST_ROOT_1_72_0: C:\hostedtoolcache\windows\Boost\1.72.0\x86_64 COSMOSCOUT_USE_PCH: true COSMOSCOUT_USE_UNITY_BUILD: true steps: @@ -200,13 +199,6 @@ jobs: uses: ilammy/msvc-dev-cmd@v1 - name: Download Dependencies run: | - # From https://github.com/actions/virtual-environments/issues/2667 - $url = "https://github.com/actions/boost-versions/releases/download/1.72.0-20200608.4/boost-1.72.0-win32-msvc14.2-x86_64.tar.gz" - (New-Object System.Net.WebClient).DownloadFile($url, "$env:TEMP\boost.tar.gz") - 7z.exe x "$env:TEMP\boost.tar.gz" -o"$env:TEMP\boostArchive" -y | Out-Null - 7z.exe x "$env:TEMP\boostArchive" -o"$env:TEMP\boost" -y | Out-Null - Push-Location -Path "$env:TEMP\boost" - Invoke-Expression .\setup.ps1 choco install ninja - name: Build Externals shell: cmd @@ -216,10 +208,9 @@ jobs: - name: Build CosmoScout VR shell: cmd run: | - cmake --preset windows-ninja-release-config -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache -DBOOST_ROOT=%BOOST_ROOT_1_72_0% + cmake --preset windows-ninja-release-config -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache cmake --build --preset windows-ninja-release-build - name: Run Tests shell: cmd run: | - SET PATH=%BOOST_ROOT_1_72_0%\\lib;%PATH% install\\windows-Release\\bin\\run_tests.bat diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 8035bec15..295047217 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -15,7 +15,7 @@ on: jobs: source_code: name: Source Code - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -35,7 +35,7 @@ jobs: release_linux: name: Linux - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -46,7 +46,6 @@ jobs: sudo apt-get update -q sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev libx11-dev sudo apt-get install libxi-dev libgconf-2-4 - sudo apt-get install libboost-all-dev - name: Build Externals run: ./make_externals.sh -G "Unix Makefiles" - name: Build CosmoScout VR @@ -70,29 +69,18 @@ jobs: release_windows: name: Windows runs-on: windows-2025 - env: - BOOST_ROOT_1_72_0: C:\hostedtoolcache\windows\Boost\1.72.0\x86_64 steps: - name: Checkout Repository uses: actions/checkout@v4 - name: Checkout Submodules run: git submodule update --init --recursive - - name: Download Boost - run: | - # From https://github.com/actions/virtual-environments/issues/2667 - $url = "https://github.com/actions/boost-versions/releases/download/1.72.0-20200608.4/boost-1.72.0-win32-msvc14.2-x86_64.tar.gz" - (New-Object System.Net.WebClient).DownloadFile($url, "$env:TEMP\boost.tar.gz") - 7z.exe x "$env:TEMP\boost.tar.gz" -o"$env:TEMP\boostArchive" -y | Out-Null - 7z.exe x "$env:TEMP\boostArchive" -o"$env:TEMP\boost" -y | Out-Null - Push-Location -Path "$env:TEMP\boost" - Invoke-Expression .\setup.ps1 - name: Build Externals shell: cmd run: make_externals.bat -G "Visual Studio 16 2019" -A x64 - name: Build CosmoScout VR shell: cmd run: | - cmake --preset windows-vs-release-config -DBOOST_ROOT=%BOOST_ROOT_1_72_0% + cmake --preset windows-vs-release-config cmake --build --preset windows-vs-release-build - name: Create Release run: | diff --git a/.gitmodules b/.gitmodules index b56bd176b..3b65a715b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -11,9 +11,6 @@ [submodule "externals/opensg-1.8"] path = externals/opensg-1.8 url = https://github.com/cosmoscout/opensg-1.8.git -[submodule "externals/c-ares"] - path = externals/c-ares - url = https://github.com/cosmoscout/c-ares.git [submodule "externals/curl"] path = externals/curl url = https://github.com/cosmoscout/curl.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ffed2800..47a8118a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,6 @@ project(cosmoscout-vr VERSION 1.10.0) # Use cmake 3.12's _ROOT variabled for searching. cmake_policy(SET CMP0074 NEW) -# cmake_policy(SET CMP0167 OLD) # Ensure local modules (for dependencies etc.) are found. list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) @@ -32,12 +31,6 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON) include(GenerateExportHeader) -# Boost and OpenGL must be present on your system. All other dependencies are included as submodules -# in "externals/". Those must be built beforehand, preferably using the scripts "make_externals.*". -set(Boost_REALPATH ON) -set(Boost_USE_MULTITHREADED ON) -set(Boost_USE_STATIC_LIBS OFF) -find_package(Boost REQUIRED COMPONENTS system chrono date_time filesystem) find_package(OpenGL REQUIRED) # You have to provide the directory where the externals got installed to. The scripts make_*.sh and @@ -48,12 +41,6 @@ set(COSMOSCOUT_EXTERNALS_DIR COSMOSCOUT_EXTERNALS_DIR-NotFound # Make sure to use forward slashes only. file(TO_CMAKE_PATH ${COSMOSCOUT_EXTERNALS_DIR} COSMOSCOUT_EXTERNALS_DIR) -if (DEFINED ENV{CARES_ROOT_DIR}) - SET(CARES_ROOT_DIR "$ENV{CARES_ROOT_DIR}") -else() - SET(CARES_ROOT_DIR ${COSMOSCOUT_EXTERNALS_DIR}) -endif() - if (DEFINED ENV{CURL_ROOT_DIR}) SET(CURL_ROOT_DIR "$ENV{CURL_ROOT_DIR}") else() @@ -155,7 +142,6 @@ find_package(GLI REQUIRED) find_package(DOCTEST REQUIRED) find_package(TINYGLTF REQUIRED) find_package(CSPICE REQUIRED) -find_package(CARES REQUIRED) find_package(CURL REQUIRED) find_package(CURLPP REQUIRED) find_package(SPDLOG REQUIRED) @@ -184,30 +170,6 @@ install( FILES_MATCHING PATTERN "*.so*" PATTERN "*.dll*" ) -# Copy boost libraries to install directory. -foreach(BOOST_LIB - ${Boost_CHRONO_LIBRARY_DEBUG} - ${Boost_CHRONO_LIBRARY_RELEASE} - ${Boost_DATE_TIME_LIBRARY_DEBUG} - ${Boost_DATE_TIME_LIBRARY_RELEASE} - ${Boost_FILESYSTEM_LIBRARY_RELEASE} - ${Boost_FILESYSTEM_LIBRARY_DEBUG} - ${Boost_SYSTEM_LIBRARY_RELEASE} - ${Boost_SYSTEM_LIBRARY_DEBUG} -) - if(EXISTS "${BOOST_LIB}") - get_filename_component(LIB_BASE_NAME ${BOOST_LIB} NAME_WE) - get_filename_component(LIB_PATH ${BOOST_LIB} PATH) - if (WIN32) - install(FILES ${LIB_PATH}/${LIB_BASE_NAME}.dll DESTINATION "lib") - endif() - if (UNIX) - file(GLOB LIB_FILES ${LIB_PATH}/${LIB_BASE_NAME}.so*) - install(FILES ${LIB_FILES} DESTINATION "lib") - endif() - endif() -endforeach() - # Install documentation directory install(DIRECTORY ${CMAKE_SOURCE_DIR}/docs @@ -261,11 +223,11 @@ configure_file( # compiler settings -------------------------------------------------------------------------------- add_definitions( - -DBOOST_ALL_DYN_LINK -DGLM_ENABLE_EXPERIMENTAL -DGLM_FORCE_SWIZZLE -DNOMINMAX -DSPDLOG_COMPILED_LIB + -DSPDLOG_USE_STD_FORMAT ) if (MSVC) @@ -294,7 +256,7 @@ else() ) endif() -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Enable unit tests diff --git a/LICENSE-3RD-PARTY.txt b/LICENSE-3RD-PARTY.txt index 4ab08b86c..a45059168 100644 --- a/LICENSE-3RD-PARTY.txt +++ b/LICENSE-3RD-PARTY.txt @@ -34,36 +34,6 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# ------------------------------------------------------------------------------------------------ # -# Boost (system, chrono, filesystem, date_time) # -# http://www.boost.org/LICENSE_1_0.txt # -# ------------------------------------------------------------------------------------------------ # - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - # ------------------------------------------------------------------------------------------------ # # c-ares # # https://c-ares.haxx.se/license.html # diff --git a/cmake/FindCEF.cmake b/cmake/FindCEF.cmake index 04ae5bdc9..298cde5b9 100644 --- a/cmake/FindCEF.cmake +++ b/cmake/FindCEF.cmake @@ -10,10 +10,10 @@ find_path(CEF_INCLUDE_DIR include/cef_version.h HINTS ${CEF_ROOT_DIR}/include/cef) # Locate library. -find_path(CEF_RESOURCE_DIR cef.pak +find_path(CEF_RESOURCE_DIR resources.pak HINTS ${CEF_ROOT_DIR}/share/cef) -find_path(CEF_LIBRARY_DIR snapshot_blob.bin +find_path(CEF_LIBRARY_DIR v8_context_snapshot.bin HINTS ${CEF_ROOT_DIR}/lib) find_library(CEF_LIBRARY NAMES cef libcef diff --git a/docs/dependencies.md b/docs/dependencies.md index 5f01cda54..983c701b6 100644 --- a/docs/dependencies.md +++ b/docs/dependencies.md @@ -9,15 +9,13 @@ SPDX-License-Identifier: CC-BY-4.0 # Complete List of Dependencies -The list below contains all dependencies of CosmoScout VR. Besides Boost, all of them are included either as [git submodules](../externals) or directly in the source tree. +The list below contains all dependencies of CosmoScout VR. All of them are included either as [git submodules](../externals) or directly in the source tree. Some of the dependencies are only required by some plugins. A text document containing [all individual license texts](../LICENSE-3RD-PARTY.txt) is provided in the root directory of the source tree. | Engine Dependencies | Description | License | |:---|:---|:---| -| [Boost (system, chrono, filesystem, date_time)](http://www.boost.org) | Used for time conversions and file system operations. | [Boost Software License](http://www.boost.org/LICENSE_1_0.txt) | -| [c-ares](https://c-ares.haxx.se) | A dependency of curl, used for asynchronous DNS requests. | [MIT](https://c-ares.haxx.se/license.html) | | [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef) | For the Webkit based user interface. | [BSD](https://bitbucket.org/chromiumembedded/cef/raw/a5a5e7ff08129f4122437dfdbba93d2a746c5c59/LICENSE.txt) | | [Curl](https://curl.haxx.se) | Library for downloading stuff from the Internet. | [MIT style](https://curl.haxx.se/legal/licmix.html) | | [CurlPP](https://github.com/jpbarrette/curlpp) | C++ wrapper for curl. | [MIT style](https://github.com/jpbarrette/curlpp/blob/master/doc/LICENSE) | diff --git a/docs/ide-setup.md b/docs/ide-setup.md index 64db7cd3c..bbc4da463 100644 --- a/docs/ide-setup.md +++ b/docs/ide-setup.md @@ -21,7 +21,6 @@ Below you find some instructions on how to setup your preferred IDE for CosmoSco ### Prerequisites - Be sure to build the externals, as specified in the [installation](install.md) guide. -- On Windows ensure that `BOOST_ROOT` is registered as an environment variable. ### Configure CMake Profiles @@ -179,12 +178,7 @@ We will discuss these files in the following. "$gcc" ], "windows": { - "command": "cmake --preset windows-vs-release-config; cmake --build --preset windows-vs-release-build", - "options": { - "env": { - "BOOST_ROOT": "C:\\local\\boost_1_69_0" - } - } + "command": "cmake --preset windows-vs-release-config; cmake --build --preset windows-vs-release-build" } }, { @@ -201,12 +195,7 @@ We will discuss these files in the following. "$gcc" ], "windows": { - "command": "cmake --preset windows-make-debug-config; cmake --build --preset windows-make-debug-build", - "options": { - "env": { - "BOOST_ROOT": "C:\\local\\boost_1_69_0" - } - } + "command": "cmake --preset windows-make-debug-config; cmake --build --preset windows-make-debug-build" } }, { @@ -292,8 +281,6 @@ We will discuss these files in the following. } ``` -If you are on Windows, you may have to replace the `"BOOST_ROOT"` environment variable in this file. - With this file in place, you can press `Ctrl+Shift+P` and select `Tasks: Run Task`. Now you can first select `Make Externals (Release)`, then `Make (Release)` and later `Run CosmoScout VR`. > [!TIP] diff --git a/docs/install.md b/docs/install.md index 4c662eb27..dc40b1618 100644 --- a/docs/install.md +++ b/docs/install.md @@ -12,17 +12,17 @@ SPDX-License-Identifier: CC-BY-4.0 :information_source: _**Tip:** This page contains generic build instructions for CosmoScout VR. Alternatively, you can follow a [guide specific to your IDE](ide-setup.md)._ **CosmoScout VR supports 64 bits only and can be build in debug and release mode on Linux and Windows. -You will need a copy of [CMake](https://cmake.org/) (version 3.22 or greater), [Boost](https://www.boost.org/) (version 1.69 or greater) and a recent C++ compiler (gcc 7, clang 5 or msvc 19). +You will need a copy of [CMake](https://cmake.org/) (version 3.22 or greater) and a recent C++ compiler (gcc 13, clang 18 or msvc 19). For the compilation of the externals [Python](https://www.python.org/) is also required.** ## Linux Before you start, it may be necessary to install some additional system packages. As there are many distributions with varying default libs and available packages, giving an exhaustive list is difficult. -Here is an exemplary list for Ubuntu 20.04 which you have to adapt to your specific distribution: +Here is an exemplary list for Ubuntu 24.04 which you have to adapt to your specific distribution: ```bash -sudo apt-get install git cmake build-essential xorg-dev libboost-all-dev libglu1-mesa-dev libssl-dev libxkbcommon0 +sudo apt-get install git cmake build-essential xorg-dev libglu1-mesa-dev libssl-dev libxkbcommon0 ``` ### Cloning the repository @@ -135,21 +135,6 @@ cd cosmoscout-vr ### Getting the dependencies -Getting a precompiled version of boost suitable for CosmoScout VR which will be found by CMake can be difficult: Older CMake versions fail to find boost versions which are too new; but on the other hand you need a rather new version if you use a very recent version of MSVC (e.g. 14.2, the one shipped with Visual Studio 2019). The "oldest" precompiled boost which you can get on SourceForge for MSVC 14.2 is version 1.70.0. - -So using version 1.70.0 may work in most cases. You can get it from from https://sourceforge.net/projects/boost/files/boost-binaries/1.70.0 - -| MSVC | Visual Studio | File | Link | -|------|---------------|---------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------| -| 14.2 | 2019 | `boost_1_70_0-unsupported-msvc-14.2-64.exe` | [download](https://sourceforge.net/projects/boost/files/boost-binaries/1.70.0/boost_1_70_0-unsupported-msvc-14.2-64.exe/download) | -| 14.1 | 2017 | `boost_1_70_0-msvc-14.1-64.exe` | [download](https://sourceforge.net/projects/boost/files/boost-binaries/1.70.0/boost_1_70_0-msvc-14.1-64.exe/download) | -| 14.0 | 2015 | `boost_1_70_0-msvc-14.0-64.exe` | [download](https://sourceforge.net/projects/boost/files/boost-binaries/1.70.0/boost_1_70_0-msvc-14.0-64.exe/download) | - -> [!TIP] -> If you want that CosmoScout VR detects your 3DConnexion Space Navigator, you have to [download](https://3dconnexion.com/de/software-developer-program/) and install the 3DConnexion SDK. Then you need to add one line to the `make_externals.bat` but file as [described here](https://github.com/cosmoscout/cosmoscout-vr/blob/main/make_externals.bat#L313). - - -Then you have to compile the dependencies. Per default, all dependencies are built in release mode using precompiled headers and unity builds where possible. This behavior can be adjusted using some environment variables: @@ -161,7 +146,7 @@ This behavior can be adjusted using some environment variables: You should set these as required before executing the scripts below. This step only has to be done once. -If you are using Visual Studio 2017, you have to replace `-G "Visual Studio 16 2019" -A x64` with `-G "Visual Studio 15 Win64"`. +If you are using Visual Studio 2022, you have to replace `-G "Visual Studio 16 2019" -A x64` with `-G "Visual Studio 17 2022" -A x64`. ```batch git submodule update --init --recursive @@ -176,9 +161,6 @@ All parameters given to `make_externals.bat` will be forwarded to CMake. For exa One can either use [CMake Presets](https://cmake.org/cmake/help/v3.22/manual/cmake-presets.7.html) or build the software manually using CMake. **Using CMake Presets** is easy and definitely the recommended way. -On Linux, boost is usually found automatically by CMake, on Windows you have to provide the `BOOST_ROOT` path. -**Replace the path in the commands below to match your setup or set `BOOST_ROOT` as an environment variable!** - You can get a list of available configuration presets using the following command: ```batch @@ -189,7 +171,6 @@ The results will be structured the following way: windows-- ``` @@ -203,7 +184,6 @@ The results will be structured the following way: windows-- ``` diff --git a/externals/c-ares b/externals/c-ares deleted file mode 160000 index d3a507e92..000000000 --- a/externals/c-ares +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d3a507e920e7af18a5efb7f9f1d8044ed4750013 diff --git a/make_externals.bat b/make_externals.bat index b5fb6301a..e946ae7bf 100644 --- a/make_externals.bat +++ b/make_externals.bat @@ -12,16 +12,16 @@ rem Make sure to run "git submodule update --init" before executing this script! rem Default build mode is release, if "set COSMOSCOUT_DEBUG_BUILD=true" is executed before, all # rem dependencies will be built in debug mode. # rem Usage: # -rem make_externals.bat [additional CMake flags, defaults to -G "Visual Studio 15 Win64"] # +rem make_externals.bat [additional CMake flags, defaults to -G "Visual Studio 16 2019" -A x64] # rem Examples: # rem make_externals.bat # -rem make_externals.bat -G "Visual Studio 15 Win64" # rem make_externals.bat -G "Visual Studio 16 2019" -A x64 # +rem make_externals.bat -G "Visual Studio 17 2022" -A x64 # rem make_externals.bat -GNinja -DCMAKE_C_COMPILER=cl.exe -DCMAKE_CXX_COMPILER=cl.exe # rem ---------------------------------------------------------------------------------------------- # rem The CMake generator and other flags can be passed as parameters. -set CMAKE_FLAGS=-G "Visual Studio 15 Win64" +set CMAKE_FLAGS=-G "Visual Studio 16 2019" -A x64 IF NOT "%~1"=="" ( SET CMAKE_FLAGS=%* ) @@ -128,20 +128,6 @@ cmake %CMAKE_FLAGS% -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DCMAKE_INSTALL_PREFIX="%INS "%EXTERNALS_DIR%/SDL_ttf" || goto :error cmake --build . --config %BUILD_TYPE% --target install --parallel %NUMBER_OF_PROCESSORS% || goto :error -rem c-ares ----------------------------------------------------------------------------------------- -:c-ares - -echo. -echo Building and installing c-ares ... -echo. - -cmake -E make_directory "%BUILD_DIR%/c-ares" && cd "%BUILD_DIR%/c-ares" -cmake %CMAKE_FLAGS% -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DCARES_BUILD_TOOLS=OFF^ - -DCMAKE_INSTALL_PREFIX="%INSTALL_DIR%"^ - "%EXTERNALS_DIR%/c-ares" || goto :error - -cmake --build . --config %BUILD_TYPE% --target install --parallel %NUMBER_OF_PROCESSORS% || goto :error - rem curl ------------------------------------------------------------------------------------------- :curl @@ -152,7 +138,7 @@ echo. cmake -E make_directory "%BUILD_DIR%/curl" && cd "%BUILD_DIR%/curl" cmake %CMAKE_FLAGS% -DCMAKE_INSTALL_PREFIX="%INSTALL_DIR%"^ -DCMAKE_BUILD_TYPE=%BUILD_TYPE%^ - -DBUILD_TESTING=OFF -DBUILD_CURL_EXE=OFF -DENABLE_ARES=ON^ + -DBUILD_TESTING=OFF -DBUILD_CURL_EXE=OFF -DENABLE_ARES=OFF^ -DCARES_INCLUDE_DIR="%INSTALL_DIR%/include"^ -DCARES_LIBRARY="%INSTALL_DIR%/lib/cares.lib"^ -DCURL_USE_SCHANNEL=On -DCMAKE_INSTALL_LIBDIR=lib^ @@ -207,7 +193,8 @@ echo. cmake -E make_directory "%BUILD_DIR%/spdlog" && cd "%BUILD_DIR%/spdlog" cmake %CMAKE_FLAGS% -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DCMAKE_INSTALL_PREFIX="%INSTALL_DIR%"^ - -DSPDLOG_BUILD_TESTS=Off -DSPDLOG_ENABLE_PCH=On "%EXTERNALS_DIR%/spdlog" || goto :error + -DSPDLOG_BUILD_TESTS=Off -D SPDLOG_BUILD_EXAMPLE=Off -DSPDLOG_ENABLE_PCH=On^ + -DSPDLOG_USE_STD_FORMAT=On "%EXTERNALS_DIR%/spdlog" || goto :error cmake --build . --config %BUILD_TYPE% --target install --parallel %NUMBER_OF_PROCESSORS% || goto :error @@ -378,27 +365,28 @@ echo. echo Downloading, building and installing cef (this may take some time) ... echo. -set CEF_DIR=cef_binary_88.1.6+g4fe33a1+chromium-88.0.4324.96_windows64_minimal +set CEF_DIR=cef_binary_135.0.20+ge7de5c3+chromium-135.0.7049.85_windows64_minimal cmake -E make_directory "%BUILD_DIR%/cef/extracted" && cd "%BUILD_DIR%/cef" IF NOT EXIST cef.tar.bz2 ( - curl.exe https://cef-builds.spotifycdn.com/cef_binary_88.1.6%%2Bg4fe33a1%%2Bchromium-88.0.4324.96_windows64_minimal.tar.bz2 --output cef.tar.bz2 + curl.exe https://cef-builds.spotifycdn.com/cef_binary_135.0.20+ge7de5c3+chromium-135.0.7049.85_windows64_minimal.tar.bz2 --output cef.tar.bz2 + + cd "%BUILD_DIR%/cef/extracted" + + cmake -E tar xfj ../cef.tar.bz2 + + rem We don't want the example applications. + cmake -E remove_directory %CEF_DIR%/tests ) else ( echo File 'cef.tar.bz2' already exists, no download required. ) -cd "%BUILD_DIR%/cef/extracted" -cmake -E tar xfj ../cef.tar.bz2 - -rem We don't want the example applications. -cmake -E remove_directory %CEF_DIR%/tests - -cd .. +cd "%BUILD_DIR%/cef/ cmake %CMAKE_FLAGS% -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DCMAKE_INSTALL_PREFIX="%INSTALL_DIR%"^ -DCMAKE_UNITY_BUILD=%UNITY_BUILD% -DCEF_RUNTIME_LIBRARY_FLAG=/MD -DCEF_DEBUG_INFO_FLAG=""^ - "%BUILD_DIR%/cef/extracted/%CEF_DIR%" || goto :error + -DCEF_COMPILER_DEFINES_DEBUG="_HAS_ITERATOR_DEBUGGING=1" "%BUILD_DIR%/cef/extracted/%CEF_DIR%" || goto :error cmake --build . --config %BUILD_TYPE% --parallel %NUMBER_OF_PROCESSORS% || goto :error diff --git a/make_externals.sh b/make_externals.sh index 290e9d273..8af7e2a55 100755 --- a/make_externals.sh +++ b/make_externals.sh @@ -113,17 +113,6 @@ cmake "${CMAKE_FLAGS[@]}" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_INSTALL_PREFIX= "$EXTERNALS_DIR/SDL_ttf" cmake --build . --target install --parallel "$(nproc)" -# c-ares ------------------------------------------------------------------------------------------- - -echo "" -echo "Building and installing c-ares ..." -echo "" - -cmake -E make_directory "$BUILD_DIR/c-ares" && cd "$BUILD_DIR/c-ares" -cmake "${CMAKE_FLAGS[@]}" -DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" \ - -DCMAKE_BUILD_TYPE=$BUILD_TYPE "$EXTERNALS_DIR/c-ares" -cmake --build . --target install --parallel "$(nproc)" - # curl --------------------------------------------------------------------------------------------- echo "" @@ -132,9 +121,7 @@ echo "" cmake -E make_directory "$BUILD_DIR/curl" && cd "$BUILD_DIR/curl" cmake "${CMAKE_FLAGS[@]}" -DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" \ - -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_TESTING=OFF -DBUILD_CURL_EXE=OFF -DENABLE_ARES=ON \ - -DCARES_INCLUDE_DIR="$INSTALL_DIR/include" \ - -DCARES_LIBRARY="$INSTALL_DIR/lib/libcares.so" \ + -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_TESTING=OFF -DBUILD_CURL_EXE=OFF -DENABLE_ARES=OFF \ -DCMAKE_INSTALL_LIBDIR=lib \ "$EXTERNALS_DIR/curl" cmake --build . --target install --parallel "$(nproc)" @@ -178,7 +165,8 @@ echo "" cmake -E make_directory "$BUILD_DIR/spdlog" && cd "$BUILD_DIR/spdlog" cmake "${CMAKE_FLAGS[@]}" -DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" -DSPDLOG_BUILD_TESTS=Off \ - -DCMAKE_POSITION_INDEPENDENT_CODE=On -DCMAKE_BUILD_TYPE=$BUILD_TYPE "$EXTERNALS_DIR/spdlog" + -DSPDLOG_USE_STD_FORMAT=On -DCMAKE_POSITION_INDEPENDENT_CODE=On \ + -DCMAKE_BUILD_TYPE=$BUILD_TYPE "$EXTERNALS_DIR/spdlog" cmake --build . --target install --parallel "$(nproc)" # civetweb ----------------------------------------------------------------------------------------- @@ -306,10 +294,10 @@ echo "" echo "Downloading, building and installing cef ..." echo "" -CEF_DIR=cef_binary_88.1.6+g4fe33a1+chromium-88.0.4324.96_linux64_minimal +CEF_DIR=cef_binary_135.0.20+ge7de5c3+chromium-135.0.7049.85_linux64_minimal cmake -E make_directory "$BUILD_DIR/cef/extracted" && cd "$BUILD_DIR/cef" -wget -nc https://cef-builds.spotifycdn.com/cef_binary_88.1.6%2Bg4fe33a1%2Bchromium-88.0.4324.96_linux64_minimal.tar.bz2 +wget -nc https://cef-builds.spotifycdn.com/cef_binary_135.0.20+ge7de5c3+chromium-135.0.7049.85_linux64_minimal.tar.bz2 cd "$BUILD_DIR/cef/extracted" cmake -E tar xfj ../$CEF_DIR.tar.bz2 diff --git a/plugins/csl-node-editor/src/NodeFactory.cpp b/plugins/csl-node-editor/src/NodeFactory.cpp index e3058a7c3..bf899cbc2 100644 --- a/plugins/csl-node-editor/src/NodeFactory.cpp +++ b/plugins/csl-node-editor/src/NodeFactory.cpp @@ -31,8 +31,8 @@ std::string NodeFactory::getSocketSource() const { // This JavaScript code registers new rete socket types and adds custom CSS style snippets to the // web page to color the sockets. for (auto const& s : mSockets) { - source += fmt::format("CosmoScout.socketTypes['{0}'] = new Rete.Socket('{0}');\n", s.first); - source += fmt::format("addSocketStyle('{}', '{}');\n", s.first, s.second); + source += std::format("CosmoScout.socketTypes['{0}'] = new Rete.Socket('{0}');\n", s.first); + source += std::format("addSocketStyle('{}', '{}');\n", s.first, s.second); } return source; @@ -73,7 +73,7 @@ std::string NodeFactory::getRegisterSource() const { // This sets up the required code for registering the rete components. for (auto const& f : mNodeCreateFuncs) { source += "{\n"; - source += fmt::format("const component = new {}Component();\n", f.first); + source += std::format("const component = new {}Component();\n", f.first); source += "CosmoScout.nodeEditor.register(component);\n"; source += "}\n"; } diff --git a/plugins/csp-atmospheres/scattering-table-generator/angstromMode.cpp b/plugins/csp-atmospheres/scattering-table-generator/angstromMode.cpp index ede58a0b1..f3ae17311 100644 --- a/plugins/csp-atmospheres/scattering-table-generator/angstromMode.cpp +++ b/plugins/csp-atmospheres/scattering-table-generator/angstromMode.cpp @@ -35,12 +35,12 @@ int angstromMode(std::vector const& arguments) { "The scattering data will be written to _scattering.csv and " "_absorption.csv, respectively (default: \"" + cOutput + "\")."); - args.addArgument({"--alpha"}, &cAlpha, fmt::format("The alpha parameter (default: {}).", cAlpha)); - args.addArgument({"--beta"}, &cBeta, fmt::format("The beta parameter (default: {}).", cBeta)); + args.addArgument({"--alpha"}, &cAlpha, std::format("The alpha parameter (default: {}).", cAlpha)); + args.addArgument({"--beta"}, &cBeta, std::format("The beta parameter (default: {}).", cBeta)); args.addArgument({"--single-scattering-albedo"}, &cSingleScatteringAlbedo, - fmt::format("The single-scattering albedo (default: {}).", cSingleScatteringAlbedo)); + std::format("The single-scattering albedo (default: {}).", cSingleScatteringAlbedo)); args.addArgument({"--scale-height"}, &cScaleHeight, - fmt::format("The scale height of the particles (default: {}).", cScaleHeight)); + std::format("The scale height of the particles (default: {}).", cScaleHeight)); common::addLambdaFlags(args, &cLambdas, &cMinLambda, &cMaxLambda, &cLambdaSamples); args.addArgument({"-h", "--help"}, &cPrintHelp, "Show this help message."); @@ -82,8 +82,8 @@ int angstromMode(std::vector const& arguments) { double beta_sca = cSingleScatteringAlbedo * beta_ext; double beta_abs = beta_ext - beta_sca; - scatteringOutput << fmt::format("{},{}", lambda, beta_sca) << std::endl; - absorptionOutput << fmt::format("{},{}", lambda, beta_abs) << std::endl; + scatteringOutput << std::format("{},{}", lambda, beta_sca) << std::endl; + absorptionOutput << std::format("{},{}", lambda, beta_abs) << std::endl; } return 0; diff --git a/plugins/csp-atmospheres/scattering-table-generator/common.cpp b/plugins/csp-atmospheres/scattering-table-generator/common.cpp index ed571425d..e852b04c0 100644 --- a/plugins/csp-atmospheres/scattering-table-generator/common.cpp +++ b/plugins/csp-atmospheres/scattering-table-generator/common.cpp @@ -19,11 +19,11 @@ void addLambdaFlags(cs::utils::CommandLine& commandLine, std::string* lambdas, d double* maxLambda, int32_t* lambdaSamples) { commandLine.addArgument({"--min-lambda"}, minLambda, - fmt::format("The minimum wavelength in m (default: {})", *minLambda)); + std::format("The minimum wavelength in m (default: {})", *minLambda)); commandLine.addArgument({"--max-lambda"}, maxLambda, - fmt::format("The maximum wavelength in m (default: {})", *maxLambda)); + std::format("The maximum wavelength in m (default: {})", *maxLambda)); commandLine.addArgument({"--lambda-samples"}, lambdaSamples, - fmt::format("The number of wavelengths to compute (default: {})", *lambdaSamples)); + std::format("The number of wavelengths to compute (default: {})", *lambdaSamples)); commandLine.addArgument({"--lambdas"}, lambdas, "A comma-separated list of wavelengths in m. If provided, --min-lambda, --max-lambda, and " "--lambda-samples are ignored."); diff --git a/plugins/csp-atmospheres/scattering-table-generator/densityMode.cpp b/plugins/csp-atmospheres/scattering-table-generator/densityMode.cpp index 20d1541b0..8b2d92b83 100644 --- a/plugins/csp-atmospheres/scattering-table-generator/densityMode.cpp +++ b/plugins/csp-atmospheres/scattering-table-generator/densityMode.cpp @@ -201,7 +201,7 @@ int densityMode(std::vector const& arguments) { // Now write a density value for each altitude. auto densities = sampleDensities(densitySettings, cAltitudeSamples, cMinAltitude, cMaxAltitude); for (auto density : densities) { - output << fmt::format("{}", density) << std::endl; + output << std::format("{}", density) << std::endl; } return 0; diff --git a/plugins/csp-atmospheres/scattering-table-generator/hulstMode.cpp b/plugins/csp-atmospheres/scattering-table-generator/hulstMode.cpp index f42dd15d4..9274c59d3 100644 --- a/plugins/csp-atmospheres/scattering-table-generator/hulstMode.cpp +++ b/plugins/csp-atmospheres/scattering-table-generator/hulstMode.cpp @@ -70,29 +70,29 @@ int hulstMode(std::vector const& arguments) { "_absorption.csv, respectively (default: \"" + cOutput + "\")."); args.addArgument({"--junge"}, &cJunge, - fmt::format("The Junge exponent for the scattering approximation (default: {}).", cJunge)); + std::format("The Junge exponent for the scattering approximation (default: {}).", cJunge)); args.addArgument({"--turbidity"}, &cTurbidity, - fmt::format( + std::format( "The Junge exponent for the scattering approximation (default: {}).", cTurbidity)); args.addArgument({"--kappa"}, &cKappa, - fmt::format("The Kappa factor for the scattering approximation. This can be a single value " + std::format("The Kappa factor for the scattering approximation. This can be a single value " "or a comma-separated list of values per wavelength (default: {}).", cKappa)); args.addArgument({"-r", "--radius"}, &cRadius, - fmt::format("The particle radius for the anomalous diffraction approximation (default: {}).", + std::format("The particle radius for the anomalous diffraction approximation (default: {}).", cRadius)); args.addArgument({"-n", "--ior-real"}, &cIoRreal, - fmt::format("The real part of the particle's IoR for the anomalous diffraction " + std::format("The real part of the particle's IoR for the anomalous diffraction " "approximation. This can be a single value or a comma-separated list of values " "per wavelength (default: {}).", cIoRreal)); args.addArgument({"-k", "--ior-imag"}, &cIoRImag, - fmt::format("The imaginary part of the particle's IoR for the anomalous diffraction " + std::format("The imaginary part of the particle's IoR for the anomalous diffraction " "approximation. This can be a single value or a comma-separated list of values " "per wavelength (default: {}).", cIoRImag)); args.addArgument({"--number-density"}, &cNumberDensity, - fmt::format("The number of particle per unit volume to compute the scattering coefficients " + std::format("The number of particle per unit volume to compute the scattering coefficients " "(default: {}).", cNumberDensity)); common::addLambdaFlags(args, &cLambdas, &cMinLambda, &cMaxLambda, &cLambdaSamples); @@ -164,8 +164,8 @@ int hulstMode(std::vector const& arguments) { double beta_sca = hulstScattering(lambda, cTurbidity, kappa, cJunge); double beta_abs = beta_ext - beta_sca; - scatteringOutput << fmt::format("{},{}", lambda, beta_sca) << std::endl; - absorptionOutput << fmt::format("{},{}", lambda, beta_abs) << std::endl; + scatteringOutput << std::format("{},{}", lambda, beta_sca) << std::endl; + absorptionOutput << std::format("{},{}", lambda, beta_abs) << std::endl; } return 0; diff --git a/plugins/csp-atmospheres/scattering-table-generator/iorMode.cpp b/plugins/csp-atmospheres/scattering-table-generator/iorMode.cpp index b656b2cf7..b43cb235a 100644 --- a/plugins/csp-atmospheres/scattering-table-generator/iorMode.cpp +++ b/plugins/csp-atmospheres/scattering-table-generator/iorMode.cpp @@ -186,7 +186,7 @@ int iorMode(std::vector const& arguments) { totalVolume; } - output << fmt::format("{},{}", lambda, ior - 1.0) << std::endl; + output << std::format("{},{}", lambda, ior - 1.0) << std::endl; } return 0; diff --git a/plugins/csp-atmospheres/scattering-table-generator/manualMode.cpp b/plugins/csp-atmospheres/scattering-table-generator/manualMode.cpp index e9b1d2fe0..3a9abb26b 100644 --- a/plugins/csp-atmospheres/scattering-table-generator/manualMode.cpp +++ b/plugins/csp-atmospheres/scattering-table-generator/manualMode.cpp @@ -91,7 +91,7 @@ int manualMode(std::vector const& arguments) { double lambda = lambdas[i]; double value = values.size() == 1 ? values[0] : values[i]; - output << fmt::format("{},{}", lambda, value) << std::endl; + output << std::format("{},{}", lambda, value) << std::endl; } return 0; diff --git a/plugins/csp-atmospheres/scattering-table-generator/mieMode.cpp b/plugins/csp-atmospheres/scattering-table-generator/mieMode.cpp index 0e6a081e3..b19f6ea30 100644 --- a/plugins/csp-atmospheres/scattering-table-generator/mieMode.cpp +++ b/plugins/csp-atmospheres/scattering-table-generator/mieMode.cpp @@ -431,7 +431,7 @@ int mieMode(std::vector const& arguments) { absorptionOutput << "lambda,beta_abs" << std::endl; phaseOutput << "lambda"; for (int32_t t(0); t < totalAngles; ++t) { - phaseOutput << fmt::format(",{}", 180.0 * t / (totalAngles - 1.0)); + phaseOutput << std::format(",{}", 180.0 * t / (totalAngles - 1.0)); } phaseOutput << std::endl; @@ -475,15 +475,15 @@ int mieMode(std::vector const& arguments) { } // Print wavelength, scattering coefficient, and absorption coefficient. - scatteringOutput << fmt::format("{},{}", lambda, cNumberDensity * cSca / totalCoeffWeight) + scatteringOutput << std::format("{},{}", lambda, cNumberDensity * cSca / totalCoeffWeight) << std::endl; - absorptionOutput << fmt::format("{},{}", lambda, cNumberDensity * cAbs / totalCoeffWeight) + absorptionOutput << std::format("{},{}", lambda, cNumberDensity * cAbs / totalCoeffWeight) << std::endl; - phaseOutput << fmt::format("{}", lambda); + phaseOutput << std::format("{}", lambda); for (double p : phase) { const double isotropic = 0.25 / glm::pi(); p = (1.0 - cPhaseFlattening) * p / totalPhaseWeight + cPhaseFlattening * isotropic; - phaseOutput << fmt::format(",{}", p); + phaseOutput << std::format(",{}", p); } phaseOutput << std::endl; } diff --git a/plugins/csp-atmospheres/scattering-table-generator/ozoneMode.cpp b/plugins/csp-atmospheres/scattering-table-generator/ozoneMode.cpp index 6c9236b13..81e3c8b28 100644 --- a/plugins/csp-atmospheres/scattering-table-generator/ozoneMode.cpp +++ b/plugins/csp-atmospheres/scattering-table-generator/ozoneMode.cpp @@ -35,7 +35,7 @@ int ozoneMode(std::vector const& arguments) { "The absorption data will be written to _absorption.csv (default: \"" + cOutput + "\")."); args.addArgument({"--number-density"}, &cNumberDensity, - fmt::format("The peak number of particles per m³ (default: {}).", cNumberDensity)); + std::format("The peak number of particles per m³ (default: {}).", cNumberDensity)); common::addLambdaFlags(args, &cLambdas, &cMinLambda, &cMaxLambda, &cLambdaSamples); args.addArgument({"-h", "--help"}, &cPrintHelp, "Show this help message."); @@ -87,7 +87,7 @@ int ozoneMode(std::vector const& arguments) { // wavelength using linear interpolation. for (double lambda : lambdas) { double absorption = common::interpolate(absorptions, minLambda, maxLambda, lambda); - output << fmt::format("{},{}", lambda, absorption * cNumberDensity) << std::endl; + output << std::format("{},{}", lambda, absorption * cNumberDensity) << std::endl; } return 0; diff --git a/plugins/csp-atmospheres/scattering-table-generator/parametricModes.cpp b/plugins/csp-atmospheres/scattering-table-generator/parametricModes.cpp index 18ac01c3c..93b076483 100644 --- a/plugins/csp-atmospheres/scattering-table-generator/parametricModes.cpp +++ b/plugins/csp-atmospheres/scattering-table-generator/parametricModes.cpp @@ -134,7 +134,7 @@ int impl(std::vector const& arguments, Type type) { output << "lambda"; for (int32_t t(0); t < totalAngles; ++t) { - output << fmt::format(",{}", 180.0 * t / (totalAngles - 1.0)); + output << std::format(",{}", 180.0 * t / (totalAngles - 1.0)); } output << std::endl; @@ -145,7 +145,7 @@ int impl(std::vector const& arguments, Type type) { double g2 = g2s.size() == 1 ? g2s[0] : g2s[i]; double alpha = alphas.size() == 1 ? alphas[0] : alphas[i]; - output << fmt::format("{}", lambda); + output << std::format("{}", lambda); for (int32_t i(0); i < totalAngles; ++i) { double theta = i * glm::pi() / (totalAngles - 1); double phase = 0.0; @@ -172,7 +172,7 @@ int impl(std::vector const& arguments, Type type) { phase = alpha * a + (1.0 - alpha) * b; } - output << fmt::format(",{}", phase); + output << std::format(",{}", phase); } output << std::endl; } diff --git a/plugins/csp-atmospheres/scattering-table-generator/rayleighMode.cpp b/plugins/csp-atmospheres/scattering-table-generator/rayleighMode.cpp index 3b7f067e3..7cf184c01 100644 --- a/plugins/csp-atmospheres/scattering-table-generator/rayleighMode.cpp +++ b/plugins/csp-atmospheres/scattering-table-generator/rayleighMode.cpp @@ -72,16 +72,16 @@ int rayleighMode(std::vector const& arguments) { args.addArgument({"--penndorf-extinction"}, &cPenndorfExtinction, "Use the Penndorf extinction tables (default: false)"); args.addArgument({"--ior"}, &cIoR, - fmt::format("The index of refraction of the gas. Can be one number or a comma-separated list " + std::format("The index of refraction of the gas. Can be one number or a comma-separated list " "of values for each wavelength (default: {}).", cIoR)); args.addArgument({"-n", "--number-density"}, &cNumberDensity, - fmt::format("The number density per m³ (default: {}).", cNumberDensity)); + std::format("The number density per m³ (default: {}).", cNumberDensity)); args.addArgument({"--phase-depolarization"}, &cPhaseDepolarization, - fmt::format( + std::format( "The depolarization factor for the phase function (default: {}).", cPhaseDepolarization)); args.addArgument({"--scattering-depolarization"}, &cScatteringDepolarization, - fmt::format("The depolarization factor for the king-correction used for the scattering " + std::format("The depolarization factor for the king-correction used for the scattering " "coefficient (default: {}).", cScatteringDepolarization)); common::addLambdaFlags(args, &cLambdas, &cMinLambda, &cMaxLambda, &cLambdaSamples); @@ -132,7 +132,7 @@ int rayleighMode(std::vector const& arguments) { absorptionOutput << "lambda,beta_abs" << std::endl; phaseOutput << "lambda"; for (int32_t t(0); t < totalAngles; ++t) { - phaseOutput << fmt::format(",{}", 180.0 * t / (totalAngles - 1.0)); + phaseOutput << std::format(",{}", 180.0 * t / (totalAngles - 1.0)); } phaseOutput << std::endl; @@ -156,7 +156,7 @@ int rayleighMode(std::vector const& arguments) { double beta_sca = common::interpolate(penndorf, minLambda, maxLambda, lambda); - scatteringOutput << fmt::format("{},{}", lambda, beta_sca) << std::endl; + scatteringOutput << std::format("{},{}", lambda, beta_sca) << std::endl; } else { @@ -171,13 +171,13 @@ int rayleighMode(std::vector const& arguments) { double beta_sca = 8.0 / 3.0 * std::pow(glm::pi(), 3.0) * f / (cNumberDensity * std::pow(lambda, 4)); - scatteringOutput << fmt::format("{},{}", lambda, beta_sca) << std::endl; + scatteringOutput << std::format("{},{}", lambda, beta_sca) << std::endl; } // Absorption is always zero. - absorptionOutput << fmt::format("{},{}", lambda, 0.0) << std::endl; + absorptionOutput << std::format("{},{}", lambda, 0.0) << std::endl; - phaseOutput << fmt::format("{}", lambda); + phaseOutput << std::format("{}", lambda); for (int32_t i(0); i < totalAngles; ++i) { double theta = i * glm::pi() / (totalAngles - 1); double gamma = cPhaseDepolarization / (2.0 - cPhaseDepolarization); @@ -187,7 +187,7 @@ int rayleighMode(std::vector const& arguments) { : 3.0 / (16.0 * glm::pi()) * (1.0 + 3.0 * gamma + (1.0 - gamma) * std::pow(std::cos(theta), 2.0)) / (1.0 + 2.0 * gamma); - phaseOutput << fmt::format(",{}", phase); + phaseOutput << std::format(",{}", phase); } phaseOutput << std::endl; } diff --git a/plugins/csp-atmospheres/src/Atmosphere.cpp b/plugins/csp-atmospheres/src/Atmosphere.cpp index d7e325853..4389382f6 100644 --- a/plugins/csp-atmospheres/src/Atmosphere.cpp +++ b/plugins/csp-atmospheres/src/Atmosphere.cpp @@ -512,7 +512,7 @@ void Atmosphere::renderSkyDome(std::string const& name) const { glReadPixels(0, 0, SIZE, SIZE, GL_RGBA, GL_FLOAT, &pixels[0]); - stbi_write_hdr(fmt::format("{}_{}.hdr", name, e).c_str(), SIZE, SIZE, 4, pixels.data()); + stbi_write_hdr(std::format("{}_{}.hdr", name, e).c_str(), SIZE, SIZE, 4, pixels.data()); } glDepthMask(GL_TRUE); diff --git a/plugins/csp-atmospheres/src/models/cosmoscout/Model.cpp b/plugins/csp-atmospheres/src/models/cosmoscout/Model.cpp index 9ed71fc77..7d43fb78b 100644 --- a/plugins/csp-atmospheres/src/models/cosmoscout/Model.cpp +++ b/plugins/csp-atmospheres/src/models/cosmoscout/Model.cpp @@ -63,10 +63,10 @@ bool Model::init( cs::utils::replaceString(sFrag, "HEIGHT_R", cs::utils::toString(settings.mRayleighHeight)); cs::utils::replaceString(sFrag, "HEIGHT_M", cs::utils::toString(settings.mMieHeight)); cs::utils::replaceString(sFrag, "BETA_R", - fmt::format("vec3({}, {}, {})", settings.mRayleighScattering[0], + std::format("vec3({}, {}, {})", settings.mRayleighScattering[0], settings.mRayleighScattering[1], settings.mRayleighScattering[2])); cs::utils::replaceString(sFrag, "BETA_M", - fmt::format("vec3({}, {}, {})", settings.mMieScattering[0], settings.mMieScattering[1], + std::format("vec3({}, {}, {})", settings.mMieScattering[0], settings.mMieScattering[1], settings.mMieScattering[2])); cs::utils::replaceString( sFrag, "PRIMARY_RAY_STEPS", cs::utils::toString(settings.mPrimaryRaySteps)); diff --git a/plugins/csp-demo-node-editor/src/nodes/TimeNode.cpp b/plugins/csp-demo-node-editor/src/nodes/TimeNode.cpp index ef033d017..47023f999 100644 --- a/plugins/csp-demo-node-editor/src/nodes/TimeNode.cpp +++ b/plugins/csp-demo-node-editor/src/nodes/TimeNode.cpp @@ -56,15 +56,13 @@ std::string const& TimeNode::getName() const { //////////////////////////////////////////////////////////////////////////////////////////////////// void TimeNode::init() { - sendMessageToJS(boost::posix_time::to_simple_string( - cs::utils::convert::time::toPosix(mTimeControl->pSimulationTime.get()))); + sendMessageToJS(cs::utils::convert::time::toString(mTimeControl->pSimulationTime.get())); } //////////////////////////////////////////////////////////////////////////////////////////////////// void TimeNode::process() { - sendMessageToJS(boost::posix_time::to_simple_string( - cs::utils::convert::time::toPosix(mTimeControl->pSimulationTime.get()))); + sendMessageToJS(cs::utils::convert::time::toString(mTimeControl->pSimulationTime.get())); // The name of the port must match the name given in the JavaScript code above. writeOutput("time", mTimeControl->pSimulationTime.get()); diff --git a/plugins/csp-demo-node-editor/src/nodes/TimeNode.js b/plugins/csp-demo-node-editor/src/nodes/TimeNode.js index bb33402e9..722f4b25c 100644 --- a/plugins/csp-demo-node-editor/src/nodes/TimeNode.js +++ b/plugins/csp-demo-node-editor/src/nodes/TimeNode.js @@ -29,7 +29,7 @@ class TimeComponent extends Rete.Component { node.addOutput(output) // Add the time display. The name parameter must be unique amongst all controls of this - // node. The TextDisplayControl class is defined in the controls folder. + // node. The TextDisplayControl class is defined in the controls' folder. let control = new TextDisplayControl('display'); node.addControl(control); diff --git a/plugins/csp-lod-bodies/src/HEALPix.cpp b/plugins/csp-lod-bodies/src/HEALPix.cpp index e131c39eb..007fbf2a7 100644 --- a/plugins/csp-lod-bodies/src/HEALPix.cpp +++ b/plugins/csp-lod-bodies/src/HEALPix.cpp @@ -539,10 +539,10 @@ glm::int64 HEALPixLevel::replaceBits(glm::int64 evenBits, glm::int64 oddBits) { //////////////////////////////////////////////////////////////////////////////////////////////////// /* static */ glm::dvec2 HEALPix::convertBaseXY2LngLat(int basePatchIdx, double x, double y) { - glm::dvec2 lngLat; - auto const pi = glm::pi(); - double jr = HEALPixLevel::sF1LUT.at(basePatchIdx) - x - y; - double nr{}; + glm::dvec2 lngLat; + constexpr auto pi = std::numbers::pi; + double jr = HEALPixLevel::sF1LUT.at(basePatchIdx) - x - y; + double nr{}; if (jr < 1.0) { nr = jr; @@ -571,8 +571,8 @@ glm::int64 HEALPixLevel::replaceBits(glm::int64 evenBits, glm::int64 oddBits) { double _f1 = HEALPixLevel::sF1LUT.at(basePatchIdx); double _f2 = HEALPixLevel::sF2LUT.at(basePatchIdx); - double x = std::fmod(lngLat.x / glm::pi() + 1.0, 2.0); //!< Ranges from 0 to 2 - double y = std::sin(lngLat.y); //!< Ranges from -1 to 1 + double x = std::fmod(lngLat.x / std::numbers::pi + 1.0, 2.0); //!< Ranges from 0 to 2 + double y = std::sin(lngLat.y); //!< Ranges from -1 to 1 double ySep = 2.0 / 3.0; @@ -628,8 +628,8 @@ glm::int64 HEALPixLevel::replaceBits(glm::int64 evenBits, glm::int64 oddBits) { //////////////////////////////////////////////////////////////////////////////////////////////////// int HEALPix::convertLngLat2Base(glm::dvec2 const& lngLat) { - double x = std::fmod(lngLat.x / glm::pi() + 1, 2.0); //!< Ranges from 0 to 2 - double y = std::sin(lngLat.y); //!< Ranges from -1 to 1 + double x = std::fmod(lngLat.x / std::numbers::pi + 1, 2.0); //!< Ranges from 0 to 2 + double y = std::sin(lngLat.y); //!< Ranges from -1 to 1 const double ySep = 2.0 / 3.0; //!< separation height (tip of diamonds) const double slope = ySep / 0.25; //!< slope of diamond edges diff --git a/plugins/csp-lod-bodies/src/PlanetShader.cpp b/plugins/csp-lod-bodies/src/PlanetShader.cpp index a6b0ba789..5c047a892 100644 --- a/plugins/csp-lod-bodies/src/PlanetShader.cpp +++ b/plugins/csp-lod-bodies/src/PlanetShader.cpp @@ -84,8 +84,7 @@ PlanetShader::PlanetShader(std::shared_ptr settings, name.erase(0, lastSlashIdx + 1); } - mColorMaps.insert( - std::make_pair(name, cs::graphics::ColorMap(boost::filesystem::path(file)))); + mColorMaps.insert(std::make_pair(name, cs::graphics::ColorMap(std::filesystem::path(file)))); mGuiManager->getGui()->callJavascript( "CosmoScout.gui.addDropdownValue", "lodBodies.setColormap", name, name, first); if (first) { diff --git a/plugins/csp-lod-bodies/src/TileId.hpp b/plugins/csp-lod-bodies/src/TileId.hpp index e93ec40a9..2e5888292 100644 --- a/plugins/csp-lod-bodies/src/TileId.hpp +++ b/plugins/csp-lod-bodies/src/TileId.hpp @@ -8,9 +8,9 @@ #ifndef CSP_LOD_BODIES_TILEID_HPP #define CSP_LOD_BODIES_TILEID_HPP -#include #include #include +#include namespace csp::lodbodies { @@ -43,14 +43,19 @@ bool operator==(TileId const& lhs, TileId const& rhs); std::ostream& operator<<(std::ostream& os, TileId const& tileId); } // namespace csp::lodbodies +template +void hash_combine(std::size_t& seed, const T& value) { + seed ^= std::hash{}(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2); +} + namespace std { template <> struct hash { std::size_t operator()(csp::lodbodies::TileId const& tileId) const { std::size_t result = 0; - boost::hash_combine(result, tileId.level()); - boost::hash_combine(result, tileId.patchIdx()); + hash_combine(result, tileId.level()); + hash_combine(result, tileId.patchIdx()); return result; } diff --git a/plugins/csp-lod-bodies/src/TileSourceWebMapService.cpp b/plugins/csp-lod-bodies/src/TileSourceWebMapService.cpp index 30bdebcad..0cbf1bd90 100644 --- a/plugins/csp-lod-bodies/src/TileSourceWebMapService.cpp +++ b/plugins/csp-lod-bodies/src/TileSourceWebMapService.cpp @@ -14,7 +14,6 @@ #include "../../../src/cs-utils/filesystem.hpp" #include "../../../src/cs-utils/utils.hpp" -#include #include #include #include @@ -72,7 +71,7 @@ bool loadImpl(TileSourceWebMapService* source, BaseTileData* tile, TileId const& // This is also not critical. Something went wrong - we will just remove the cache file and // will try to download it later again if it's requested once more. logger().debug("Tile loading failed: Removing invalid cache file '{}'.", *cacheFile); - boost::filesystem::remove(*cacheFile); + std::filesystem::remove(*cacheFile); return false; } @@ -84,7 +83,7 @@ bool loadImpl(TileSourceWebMapService* source, BaseTileData* tile, TileId const& int imagelength{}; if (TIFFGetField(data, TIFFTAG_IMAGELENGTH, &imagelength) == 0) { logger().debug("TIFFGetField failed: Removing invalid cache file '{}'.", *cacheFile); - boost::filesystem::remove(*cacheFile); + std::filesystem::remove(*cacheFile); return false; } int tiffReturn{}; @@ -111,7 +110,7 @@ bool loadImpl(TileSourceWebMapService* source, BaseTileData* tile, TileId const& } if (tiffReturn == -1) { logger().debug("TIFFReadScanline failed: Removing invalid cache file '{}'.", *cacheFile); - boost::filesystem::remove(*cacheFile); + std::filesystem::remove(*cacheFile); return false; } @@ -132,7 +131,7 @@ bool loadImpl(TileSourceWebMapService* source, BaseTileData* tile, TileId const& // This is also not critical. Something went wrong - we will just remove the cache file and // will try to download it later again if it's requested once more. logger().debug("Tile loading failed: Removing invalid cache file '{}'.", *cacheFile); - boost::filesystem::remove(*cacheFile); + std::filesystem::remove(*cacheFile); return false; } @@ -150,7 +149,7 @@ bool loadImpl(TileSourceWebMapService* source, BaseTileData* tile, TileId const& "Failed to parse tile data: File '{}' is completely white and most likely corrupt.", *cacheFile); source->markTileDataAsInvalid(*cacheFile); - if (boost::filesystem::remove(*cacheFile) == 0) { + if (std::filesystem::remove(*cacheFile) == 0) { logger().debug("Failed to remove tile data: File '{}'", *cacheFile); } return false; @@ -266,7 +265,7 @@ TileSourceWebMapService::TileSourceWebMapService(uint32_t resolution) return loadImpl(this, tileId); } - throw std::domain_error(fmt::format("Unsupported format: {}!", static_cast(mFormat))); + throw std::domain_error(std::format("Unsupported format: {}!", static_cast(mFormat))); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -367,11 +366,10 @@ std::optional TileSourceWebMapService::loadData(TileId const& tileI << "&width=" << mResolution << "&height=" << mResolution << "&srs=EPSG:900914&format=" << format; - auto cacheFilePath(boost::filesystem::path(cacheFile.str())); + auto cacheFilePath(std::filesystem::path(cacheFile.str())); // The file is already there, we can return it. - if (boost::filesystem::exists(cacheFilePath) && - boost::filesystem::file_size(cacheFile.str()) > 0) { + if (std::filesystem::exists(cacheFilePath) && std::filesystem::file_size(cacheFile.str()) > 0) { return cacheFile.str(); } @@ -385,20 +383,20 @@ std::optional TileSourceWebMapService::loadData(TileId const& tileI std::unique_lock lock(mFileSystemMutex); // Try to create the cache directory if necessary. - auto cacheDirPath(boost::filesystem::absolute(boost::filesystem::path(cacheDir.str()))); - if (!(boost::filesystem::exists(cacheDirPath))) { + auto cacheDirPath(std::filesystem::absolute(std::filesystem::path(cacheDir.str()))); + if (!(std::filesystem::exists(cacheDirPath))) { try { cs::utils::filesystem::createDirectoryRecursively( - cacheDirPath, boost::filesystem::perms::all_all); + cacheDirPath, std::filesystem::perms::all); } catch (std::exception& e) { - throw std::runtime_error(fmt::format("Failed to create cache directory '{}'!", e.what())); + throw std::runtime_error(std::format("Failed to create cache directory '{}'!", e.what())); } } // The file is there but obviously corrupt. Remove it. - if (boost::filesystem::exists(cacheFilePath) && - boost::filesystem::file_size(cacheFile.str()) == 0) { - boost::filesystem::remove(cacheFilePath); + if (std::filesystem::exists(cacheFilePath) && + std::filesystem::file_size(cacheFile.str()) == 0) { + std::filesystem::remove(cacheFilePath); } } @@ -408,7 +406,7 @@ std::optional TileSourceWebMapService::loadData(TileId const& tileI out.open(cacheFile.str(), std::ofstream::out | std::ofstream::binary); if (!out) { - throw std::runtime_error(fmt::format( + throw std::runtime_error(std::format( "Failed to download tile data: Cannot open '{}' for writing!", cacheFile.str())); } @@ -448,11 +446,11 @@ std::optional TileSourceWebMapService::loadData(TileId const& tileI throw std::runtime_error(sstr.str()); } - boost::filesystem::perms filePerms = - boost::filesystem::perms::owner_read | boost::filesystem::perms::owner_write | - boost::filesystem::perms::group_read | boost::filesystem::perms::group_write | - boost::filesystem::perms::others_read | boost::filesystem::perms::others_write; - boost::filesystem::permissions(cacheFilePath, filePerms); + std::filesystem::perms filePerms = + std::filesystem::perms::owner_read | std::filesystem::perms::owner_write | + std::filesystem::perms::group_read | std::filesystem::perms::group_write | + std::filesystem::perms::others_read | std::filesystem::perms::others_write; + std::filesystem::permissions(cacheFilePath, filePerms); return cacheFile.str(); } @@ -460,7 +458,7 @@ std::optional TileSourceWebMapService::loadData(TileId const& tileI //////////////////////////////////////////////////////////////////////////////////////////////////// /* virtual */ void TileSourceWebMapService::loadTileAsync(TileId const& tileId, OnLoadCallback cb) { - mThreadPool.enqueue([=]() { + mThreadPool.enqueue([this, tileId, cb]() { auto tile = loadTile(tileId); cb(tileId, std::move(tile)); }); @@ -529,7 +527,7 @@ bool TileSourceWebMapService::isSame(TileSource const* other) const { //////////////////////////////////////////////////////////////////////////////////////////////////// -void TileSourceWebMapService::markTileDataAsInvalid(boost::filesystem::path const& TileDataPath) { +void TileSourceWebMapService::markTileDataAsInvalid(std::filesystem::path const& TileDataPath) { mLastTimeTileFailed[TileDataPath] = std::chrono::system_clock::now(); } diff --git a/plugins/csp-lod-bodies/src/TileSourceWebMapService.hpp b/plugins/csp-lod-bodies/src/TileSourceWebMapService.hpp index a3278195a..ac80b6a36 100644 --- a/plugins/csp-lod-bodies/src/TileSourceWebMapService.hpp +++ b/plugins/csp-lod-bodies/src/TileSourceWebMapService.hpp @@ -75,7 +75,7 @@ class TileSourceWebMapService : public TileSource { // timestamp. This information is used to avoid quering the same tile immediately after we've // received invalid data from server Tracking the time of the last error allows us to apply a kind // of cooldown mechanism - void markTileDataAsInvalid(boost::filesystem::path const& TileDataPath); + void markTileDataAsInvalid(std::filesystem::path const& TileDataPath); private: static std::mutex mFileSystemMutex; @@ -89,7 +89,7 @@ class TileSourceWebMapService : public TileSource { // We keep track of the time a tile has had invalid data from the server. // This timestamp is used for a cooldown mechanism - std::map mLastTimeTileFailed; + std::map mLastTimeTileFailed; }; } // namespace csp::lodbodies diff --git a/plugins/csp-lod-bodies/src/TreeManager.cpp b/plugins/csp-lod-bodies/src/TreeManager.cpp index bce28bc93..c860f8265 100644 --- a/plugins/csp-lod-bodies/src/TreeManager.cpp +++ b/plugins/csp-lod-bodies/src/TreeManager.cpp @@ -258,8 +258,7 @@ void TreeManager::onNodeInserted(TileNode* node) { void TreeManager::releaseResources(TileNode* node) { for (auto const& res : mGLResources->mChannels) { - auto data = node->getTileData(res->getDataType()); - if (data) { + if (auto const& data = node->getTileData(res->getDataType())) { res->releaseGPU(data); } } @@ -269,14 +268,13 @@ void TreeManager::releaseResources(TileNode* node) { void TreeManager::prune() { // sort by age, oldest nodes at the back - std::sort(mNodes.begin(), mNodes.end(), AgeLess(mFrameCount)); - int count = 0; + std::ranges::sort(mNodes, AgeLess(mFrameCount)); while (!mNodes.empty()) { - TileNode* node = mNodes.back(); // remove unnused nodes, but never root nodes - if (node->getAge(mFrameCount) > maxNodeAge && node->getLevel() > 0) { + if (TileNode* node = mNodes.back(); + node->getAge(mFrameCount) > maxNodeAge && node->getLevel() > 0) { releaseResources(node); if (!removeNode(&mTree, node)) { @@ -285,7 +283,6 @@ void TreeManager::prune() { // remove entries for node from internal data structures mNodes.pop_back(); - ++count; } else { // The node at the back of mAgeStore can not be removed - stop // The sorting of mAgeStore ensures that there is no node that @@ -312,8 +309,6 @@ void TreeManager::merge() { int unmerged = 0; for (auto& node : mergeNodes) { - assert(node != nullptr); - if (insertNode(&mTree, node)) { onNodeInserted(node); ++merged; diff --git a/plugins/csp-measurement-tools/src/FlagTool.cpp b/plugins/csp-measurement-tools/src/FlagTool.cpp index 99d19e852..1a0bc1009 100644 --- a/plugins/csp-measurement-tools/src/FlagTool.cpp +++ b/plugins/csp-measurement-tools/src/FlagTool.cpp @@ -32,8 +32,8 @@ FlagTool::FlagTool(std::shared_ptr pInputManager, : Mark(std::move(pInputManager), std::move(pSolarSystem), std::move(settings), std::move(objectName)) , mGuiArea(std::make_unique(600, 400)) - , mGuiItem(std::make_unique( - "file://{toolZoom}../share/resources/gui/flag.html", true)) { + , mGuiItem( + std::make_unique("file://{toolZoom}../share/resources/gui/flag.html")) { auto* pSG = GetVistaSystem()->GetGraphicsManager()->GetSceneGraph(); mGuiTransform.reset(pSG->NewTransformNode(mTransform.get())); @@ -52,7 +52,7 @@ FlagTool::FlagTool(std::shared_ptr pInputManager, mGuiItem->setCanScroll(false); mGuiItem->waitForFinishedLoading(); - // We use a zoom factor of 2.0 in order to increae the DPI of our world space UIs. + // We use a zoom factor of 2.0 in order to increase the DPI of our world space UIs. mGuiItem->setZoomFactor(2.0); mGuiItem->registerCallback("deleteMe", "Call this to delete the tool.", diff --git a/plugins/csp-minimap/src/Plugin.cpp b/plugins/csp-minimap/src/Plugin.cpp index 3836cfdfa..a455c373f 100644 --- a/plugins/csp-minimap/src/Plugin.cpp +++ b/plugins/csp-minimap/src/Plugin.cpp @@ -199,7 +199,7 @@ void Plugin::onAddBookmark(std::shared_ptr con p = cs::utils::convert::toDegrees(p); auto c = bookmark.mColor.value_or(glm::vec3(0.8F, 0.8F, 1.0F)) * 255.F; mGuiManager->getGui()->callJavascript("CosmoScout.minimap.addBookmark", bookmarkID, - fmt::format("rgb({}, {}, {})", c.r, c.g, c.b), p.x, p.y); + std::format("rgb({}, {}, {})", c.r, c.g, c.b), p.x, p.y); } } } diff --git a/plugins/csp-recorder/src/Plugin.cpp b/plugins/csp-recorder/src/Plugin.cpp index 14adb6d6f..1e9e4ed70 100644 --- a/plugins/csp-recorder/src/Plugin.cpp +++ b/plugins/csp-recorder/src/Plugin.cpp @@ -122,8 +122,8 @@ void Plugin::update() { mFrameCounter = 0; // We use the current date as a filename. - auto timeString = - cs::utils::convert::time::toString(boost::posix_time::microsec_clock::local_time()); + auto timeString = cs::utils::convert::time::toString( + std::chrono::duration(std::chrono::file_clock::now().time_since_epoch()).count()); cs::utils::replaceString(timeString, ":", "-"); cs::utils::replaceString(timeString, ".", "-"); cs::utils::replaceString(timeString, "T", "-"); @@ -162,7 +162,7 @@ def capture(file): // Now that the output file is initialized, we can write the information for each frame. Here we // write a call navigation.setBodyFull() setting the current full observer transformation. if (mPluginSettings.mRecordTime.get()) { - mOutFile << fmt::format("runJS(\"CosmoScout.callbacks.navigation.setBodyFull('{}', '{}', " + mOutFile << std::format("runJS(\"CosmoScout.callbacks.navigation.setBodyFull('{}', '{}', " "{}, {}, {}, {}, {}, {}, {}, 0);\")", mAllSettings->mObserver.pCenter.get(), mAllSettings->mObserver.pFrame.get(), mAllSettings->mObserver.pPosition.get().x, diff --git a/plugins/csp-sharad/src/Plugin.cpp b/plugins/csp-sharad/src/Plugin.cpp index 8b1abb961..5b222b63f 100644 --- a/plugins/csp-sharad/src/Plugin.cpp +++ b/plugins/csp-sharad/src/Plugin.cpp @@ -16,7 +16,6 @@ #include #include -#include //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -79,15 +78,15 @@ void Plugin::init() { mGuiManager->getGui()->callJavascript("CosmoScout.gui.clearHtml", "list-sharad"); // Then add new ones. - boost::filesystem::path dir(filePath); - boost::filesystem::directory_iterator end_iter; - - if (boost::filesystem::exists(dir) && boost::filesystem::is_directory(dir)) { - for (boost::filesystem::directory_iterator dir_iter(dir); dir_iter != end_iter; ++dir_iter) { - if (boost::filesystem::is_regular_file(dir_iter->status())) { - boost::filesystem::path path(boost::filesystem::path(*dir_iter).lexically_normal()); - std::string file(path.stem().string()); - std::string ext(path.extension().string()); + std::filesystem::path dir(filePath); + std::filesystem::directory_iterator end_iter; + + if (std::filesystem::exists(dir) && std::filesystem::is_directory(dir)) { + for (std::filesystem::directory_iterator dir_iter(dir); dir_iter != end_iter; ++dir_iter) { + if (std::filesystem::is_regular_file(dir_iter->status())) { + std::filesystem::path path(std::filesystem::path(*dir_iter).lexically_normal()); + std::string file(path.stem().string()); + std::string ext(path.extension().string()); if (ext == ".tab") { std::string sName = file.substr(0, file.length() - 5); diff --git a/plugins/csp-sharad/src/Sharad.cpp b/plugins/csp-sharad/src/Sharad.cpp index 65ae31089..5b723e115 100644 --- a/plugins/csp-sharad/src/Sharad.cpp +++ b/plugins/csp-sharad/src/Sharad.cpp @@ -197,18 +197,18 @@ Sharad::Sharad(std::shared_ptr settings, std::vector vertices(mSamples * 2); for (int i = 0; i < mSamples; ++i) { - double tTime = cs::utils::convert::time::toSpice( - boost::posix_time::ptime(boost::gregorian::date(meta[i].Year, meta[i].Month, meta[i].Day), - boost::posix_time::hours(meta[i].Hour) + boost::posix_time::minutes(meta[i].Minute) + - boost::posix_time::seconds(meta[i].Second) + - boost::posix_time::milliseconds(meta[i].Millisecond))); + auto entry = meta[i]; + auto ymd{std::chrono::year(entry.Year) / entry.Month / entry.Day}; + auto tod = std::chrono::hours(entry.Hour) + std::chrono::minutes(entry.Minute) + + std::chrono::seconds(entry.Second) + std::chrono::milliseconds(entry.Millisecond); + + double tTime = cs::utils::convert::time::toSpice(cs::utils::convert::time::toUTC(ymd, tod)); if (i == 0) { mStartTime = tTime; } - glm::vec2 lngLat( - cs::utils::convert::toRadians(glm::dvec2(meta[i].Longitude, meta[i].Latitude))); + glm::vec2 lngLat(cs::utils::convert::toRadians(glm::dvec2(entry.Longitude, entry.Latitude))); float x = 1.F * static_cast(i) / (static_cast(mSamples) - 1.F); auto time = static_cast(tTime - mStartTime); diff --git a/plugins/csp-simple-bodies/src/SimpleBody.cpp b/plugins/csp-simple-bodies/src/SimpleBody.cpp index ec248a9b5..e36beb8db 100644 --- a/plugins/csp-simple-bodies/src/SimpleBody.cpp +++ b/plugins/csp-simple-bodies/src/SimpleBody.cpp @@ -295,7 +295,8 @@ void SimpleBody::configure(Plugin::Settings::SimpleBody const& settings) { mTexture = cs::graphics::TextureLoader::loadFromFile(settings.mTexture); } - if (settings.mRing && mSimpleBodySettings.mRing->mTexture != settings.mRing->mTexture) { + if (settings.mRing && (!mSimpleBodySettings.mRing || + mSimpleBodySettings.mRing->mTexture != settings.mRing->mTexture)) { mRingTexture = cs::graphics::TextureLoader::loadFromFile(settings.mRing->mTexture); } diff --git a/plugins/csp-stars/src/Stars.cpp b/plugins/csp-stars/src/Stars.cpp index 7a909cff9..080f9a4f2 100644 --- a/plugins/csp-stars/src/Stars.cpp +++ b/plugins/csp-stars/src/Stars.cpp @@ -630,13 +630,11 @@ bool Stars::readStarsFromCatalog(CatalogType type, std::string const& filename) } if (file.is_open()) { - int lineCount = 0; bool loadHipparcos(mCatalogs.find(CatalogType::eHipparcos) != mCatalogs.end()); // read line by line while (!file.eof()) { // get line - ++lineCount; std::string line; getline(file, line); diff --git a/plugins/csp-timings/src/Plugin.cpp b/plugins/csp-timings/src/Plugin.cpp index b907dc97c..d60f2ff26 100644 --- a/plugins/csp-timings/src/Plugin.cpp +++ b/plugins/csp-timings/src/Plugin.cpp @@ -55,8 +55,8 @@ void Plugin::init() { // documentation of cs::gui::WebView::setZoomLevel in great detail. This also means that all other // WebViews with an URL starting with "file://{mainUIZoom}../" will be automatically affected by // the pMainUIScale factor. - mGuiItem = std::make_unique( - "file://{mainUIZoom}../share/resources/gui/timings.html", false); + mGuiItem = + std::make_unique("file://{mainUIZoom}../share/resources/gui/timings.html"); // Configure the positioning and attributes of the statistics GUI item. mGuiItem->setSizeX(500); @@ -241,16 +241,14 @@ void Plugin::update() { if (!mEnableRecording && !mRecordedGPURanges.empty()) { // We use the current date as a directory name. - auto timeString = - cs::utils::convert::time::toString(boost::posix_time::microsec_clock::local_time()); + auto timeString = cs::utils::convert::time::toString(std::chrono::utc_clock::now()); cs::utils::replaceString(timeString, ":", "-"); cs::utils::replaceString(timeString, ".", "-"); cs::utils::replaceString(timeString, "T", "-"); cs::utils::replaceString(timeString, "Z", ""); std::string directory = "csp-timings/" + timeString; - cs::utils::filesystem::createDirectoryRecursively( - boost::filesystem::system_complete(directory)); + cs::utils::filesystem::createDirectoryRecursively(std::filesystem::absolute(directory)); // This stores a CSV file for each nesting level in the directory created above. The prefix will // be prepended to the CSV file name. diff --git a/plugins/csp-vr-accessibility/src/FovVignette.cpp b/plugins/csp-vr-accessibility/src/FovVignette.cpp index a8f820145..7b280c192 100644 --- a/plugins/csp-vr-accessibility/src/FovVignette.cpp +++ b/plugins/csp-vr-accessibility/src/FovVignette.cpp @@ -266,9 +266,9 @@ void FovVignette::updateFadeAnimatedVignette() { //////////////////////////////////////////////////////////////////////////////////////////////////// double FovVignette::getNow() { - boost::posix_time::ptime const EPOCH(boost::gregorian::date(1970, 1, 1)); - auto delta = boost::posix_time::microsec_clock::universal_time() - EPOCH; - return delta.total_microseconds() / 1000000.0; + return std::chrono::duration(std::chrono::high_resolution_clock::now().time_since_epoch()) + .count(); + ; } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/csp-wms-overlays/src/Plugin.cpp b/plugins/csp-wms-overlays/src/Plugin.cpp index f6d2defcf..7f323197f 100644 --- a/plugins/csp-wms-overlays/src/Plugin.cpp +++ b/plugins/csp-wms-overlays/src/Plugin.cpp @@ -10,6 +10,8 @@ #include "WebMapService.hpp" #include "logger.hpp" +#include + #include "../../../src/cs-core/GuiManager.hpp" #include "../../../src/cs-core/InputManager.hpp" #include "../../../src/cs-core/Settings.hpp" @@ -247,15 +249,15 @@ void Plugin::init() { mAllSettings->pTimeSpeed = 0.f; - boost::posix_time::ptime time = - cs::utils::convert::time::toPosix(mTimeControl->pSimulationTime.get()); + std::chrono::utc_clock::time_point time = + cs::utils::convert::time::toUTC(mTimeControl->pSimulationTime.get()); std::vector intervals = mActiveLayers[mActiveOverlay->getObjectName()]->getSettings().mTimeIntervals; // Check if current time is in any interval - TimeInterval result; - boost::posix_time::ptime sampleStartTime = time; + TimeInterval result; + std::chrono::utc_clock::time_point sampleStartTime = time; if (utils::timeInIntervals(sampleStartTime, intervals, result)) { if (sampleStartTime != time) { // timeInIntervals rounds down the time to the nearest timestep, so the @@ -279,14 +281,14 @@ void Plugin::init() { } // If the time was not the start time of any interval we can substract the duration to // get the previous timestep. - sampleStartTime = utils::addDurationToTime(sampleStartTime, result.mSampleDuration, -1); + sampleStartTime = sampleStartTime - result.mSampleDuration; mTimeControl->setTime(cs::utils::convert::time::toSpice(sampleStartTime)); return; } // Time was not part of any interval, so the last interval, that lies before the current // time has to be found. - boost::posix_time::ptime temp = time; + std::chrono::utc_clock::time_point temp = time; for (auto const& interval : intervals) { if (time > interval.mEndTime) { temp = interval.mEndTime; @@ -306,15 +308,15 @@ void Plugin::init() { mAllSettings->pTimeSpeed = 0.f; - boost::posix_time::ptime time = - cs::utils::convert::time::toPosix(mTimeControl->pSimulationTime.get()); + std::chrono::utc_clock::time_point time = + cs::utils::convert::time::toUTC(mTimeControl->pSimulationTime.get()); std::vector intervals = mActiveLayers[mActiveOverlay->getObjectName()]->getSettings().mTimeIntervals; // Check if current time is in any interval - TimeInterval result; - boost::posix_time::ptime sampleStartTime = time; + TimeInterval result; + std::chrono::utc_clock::time_point sampleStartTime = time; if (utils::timeInIntervals(sampleStartTime, intervals, result)) { if (sampleStartTime == result.mEndTime) { auto it = std::find(intervals.begin(), intervals.end(), result); @@ -331,7 +333,7 @@ void Plugin::init() { } // If the time was not the end time of any interval we can add the duration to // get the next timestep. - sampleStartTime = utils::addDurationToTime(sampleStartTime, result.mSampleDuration); + sampleStartTime = sampleStartTime + result.mSampleDuration; mTimeControl->setTime(cs::utils::convert::time::toSpice(sampleStartTime)); return; } @@ -687,8 +689,8 @@ void Plugin::setWMSLayer( "CosmoScout.gui.addDropdownValue", "wmsOverlays.setStyle", "", "Default", false); mGuiManager->getGui()->callJavascript("CosmoScout.wmsOverlays.setInfo", layer->getTitle(), - boost::replace_all_copy( - layer->getAbstract().value_or("No description given"), "\r", "
"), + std::regex_replace(layer->getAbstract().value_or("No description given"), + std::regex("\r"), "
"), layer->getSettings().mAttribution.value_or("None")); mGuiManager->getGui()->callJavascript("CosmoScout.wmsOverlays.enableInfoButton", true); diff --git a/plugins/csp-wms-overlays/src/TextureOverlayRenderer.cpp b/plugins/csp-wms-overlays/src/TextureOverlayRenderer.cpp index 89780aecf..8e0f3c93c 100644 --- a/plugins/csp-wms-overlays/src/TextureOverlayRenderer.cpp +++ b/plugins/csp-wms-overlays/src/TextureOverlayRenderer.cpp @@ -34,7 +34,6 @@ #include // Standard includes -#include #include #include @@ -399,8 +398,8 @@ bool TextureOverlayRenderer::Do() { if (mActiveWMSLayer && !mActiveWMSLayer->getSettings().mTimeIntervals.empty()) { // Get the current time. Pre-fetch times are related to this. - boost::posix_time::ptime time = - cs::utils::convert::time::toPosix(mTimeControl->pSimulationTime.get()); + std::chrono::utc_clock::time_point time = + cs::utils::convert::time::toUTC(mTimeControl->pSimulationTime.get()); // Select WMS textures to be downloaded. If no pre-fetch is set, only sellect the texture for // the current timestep. @@ -408,9 +407,10 @@ bool TextureOverlayRenderer::Do() { preFetch <= mPluginSettings->mPrefetchCount.get(); preFetch++) { // Get the start time of the WMS sample. - boost::posix_time::ptime sampleStartTime = - utils::addDurationToTime(time, mCurrentInterval.mSampleDuration, preFetch); - sampleStartTime -= boost::posix_time::microseconds(time.time_of_day().fractional_seconds()); + std::chrono::utc_clock::time_point sampleStartTime = + time + (mCurrentInterval.mSampleDuration * preFetch); + + sampleStartTime = std::chrono::floor(sampleStartTime); bool inInterval = utils::timeInIntervals( sampleStartTime, mActiveWMSLayer->getSettings().mTimeIntervals, mCurrentInterval); @@ -419,7 +419,7 @@ bool TextureOverlayRenderer::Do() { auto requestedTexture = mTexturesBuffer.find(timeString); auto loadedTexture = mTextures.find(timeString); - auto wrongTexture = std::find(mWrongTextures.begin(), mWrongTextures.end(), timeString); + auto wrongTexture = std::ranges::find(mWrongTextures, timeString); // Only load textures that aren't stored yet. if (requestedTexture == mTexturesBuffer.end() && loadedTexture == mTextures.end() && @@ -431,10 +431,10 @@ bool TextureOverlayRenderer::Do() { request.mTime = timeString; request.mBounds = getBounds(); - mTexturesBuffer.insert(std::pair>>( + mTexturesBuffer.emplace( timeString, mTextureLoader.loadTextureAsync(*mActiveWMS, *mActiveWMSLayer, request, mPluginSettings->mMapCache.get(), - request.mBounds == mActiveWMSLayer->getSettings().mBounds))); + request.mBounds == mActiveWMSLayer->getSettings().mBounds)); } } @@ -445,8 +445,7 @@ bool TextureOverlayRenderer::Do() { std::optional texture = texIt->second.get(); if (texture.has_value()) { - mTextures.insert( - std::pair(texIt->first, std::move(texture.value()))); + mTextures.emplace(texIt->first, std::move(texture.value())); } else { mWrongTextures.emplace_back(texIt->first); } @@ -458,9 +457,11 @@ bool TextureOverlayRenderer::Do() { } // Get the current time. - time = cs::utils::convert::time::toPosix(mTimeControl->pSimulationTime.get()); - boost::posix_time::ptime sampleStartTime = - time - boost::posix_time::microseconds(time.time_of_day().fractional_seconds()); + time = cs::utils::convert::time::toUTC(mTimeControl->pSimulationTime.get()); + + std::chrono::utc_clock::time_point sampleStartTime{ + std::chrono::floor(time)}; + bool inInterval = utils::timeInIntervals( sampleStartTime, mActiveWMSLayer->getSettings().mTimeIntervals, mCurrentInterval); @@ -486,13 +487,13 @@ bool TextureOverlayRenderer::Do() { } if (!mWMSTextureUsed || !mPluginSettings->mEnableInterpolation.get() || - !mCurrentInterval.mSampleDuration.isDuration()) { + mCurrentInterval.mSampleDuration.count() == 0) { mSecondWMSTextureUsed = false; mCurrentSecondTexture = ""; } // Create fading between Wms textures when interpolation is enabled. else { - boost::posix_time::ptime sampleAfter = - utils::addDurationToTime(sampleStartTime, mCurrentInterval.mSampleDuration); + std::chrono::utc_clock::time_point sampleAfter = + sampleStartTime + mCurrentInterval.mSampleDuration; bool isAfterInInterval = utils::timeInIntervals( sampleAfter, mActiveWMSLayer->getSettings().mTimeIntervals, mCurrentInterval); @@ -509,8 +510,8 @@ bool TextureOverlayRenderer::Do() { } // Interpolate fade value between the 2 WMS textures. mFade = static_cast( - static_cast((sampleAfter - time).total_seconds()) / - static_cast((sampleAfter - sampleStartTime).total_seconds())); + std::chrono::duration(sampleAfter - time).count() / + std::chrono::duration(sampleAfter - sampleStartTime).count()); } } } diff --git a/plugins/csp-wms-overlays/src/WebMapService.cpp b/plugins/csp-wms-overlays/src/WebMapService.cpp index 3c4b774d3..cfa4e0a3b 100644 --- a/plugins/csp-wms-overlays/src/WebMapService.cpp +++ b/plugins/csp-wms-overlays/src/WebMapService.cpp @@ -14,8 +14,6 @@ #include -#include - #include #include @@ -142,12 +140,12 @@ VistaXML::TiXmlElement* WebMapService::getCapabilities() { if (saveToCache && docString.has_value()) { // Save capabilities to cache - boost::filesystem::path cacheFile(mCacheFileName); - boost::filesystem::path cacheDir(mCacheDir); - boost::filesystem::path cacheFilePath(cacheDir / cacheFile); + std::filesystem::path cacheFile(mCacheFileName); + std::filesystem::path cacheDir(mCacheDir); + std::filesystem::path cacheFilePath(cacheDir / cacheFile); - auto cacheDirAbs(boost::filesystem::absolute(cacheDir)); - if (!(boost::filesystem::exists(cacheDirAbs))) { + auto cacheDirAbs(std::filesystem::absolute(cacheDir)); + if (!(std::filesystem::exists(cacheDirAbs))) { try { cs::utils::filesystem::createDirectoryRecursively(cacheDirAbs); } catch (std::exception& e) { @@ -164,12 +162,12 @@ VistaXML::TiXmlElement* WebMapService::getCapabilities() { //////////////////////////////////////////////////////////////////////////////////////////////////// std::optional WebMapService::getCapabilitiesFromCache() { - boost::filesystem::path cacheFile(mCacheFileName); - boost::filesystem::path cacheDir(mCacheDir); - boost::filesystem::path cacheFilePath(cacheDir / cacheFile); + std::filesystem::path cacheFile(mCacheFileName); + std::filesystem::path cacheDir(mCacheDir); + std::filesystem::path cacheFilePath(cacheDir / cacheFile); // Check if file with the correct name is in the cache - if (boost::filesystem::exists(cacheFilePath) && boost::filesystem::file_size(cacheFilePath) > 0) { + if (std::filesystem::exists(cacheFilePath) && std::filesystem::file_size(cacheFilePath) > 0) { std::string capabilitiesString = cs::utils::filesystem::loadToString(cacheFilePath.string()); VistaXML::TiXmlDocument cacheDoc; diff --git a/plugins/csp-wms-overlays/src/WebMapTextureLoader.cpp b/plugins/csp-wms-overlays/src/WebMapTextureLoader.cpp index 45273f969..3477812c2 100644 --- a/plugins/csp-wms-overlays/src/WebMapTextureLoader.cpp +++ b/plugins/csp-wms-overlays/src/WebMapTextureLoader.cpp @@ -15,9 +15,6 @@ #include "../../../src/cs-utils/filesystem.hpp" #include "../../../src/cs-utils/utils.hpp" -#include -#include -#include #include #include @@ -27,6 +24,7 @@ #include #include +#include namespace csp::wmsoverlays { @@ -41,8 +39,9 @@ WebMapTextureLoader::WebMapTextureLoader() std::future> WebMapTextureLoader::loadTextureAsync( WebMapService const& wms, WebMapLayer const& layer, Request const& request, std::string const& mapCache, bool saveToCache) { - return mThreadPool.enqueue( - [=]() { return loadTexture(wms, layer, request, mapCache, saveToCache); }); + return mThreadPool.enqueue([this, wms, layer, request, mapCache, saveToCache]() { + return loadTexture(wms, layer, request, mapCache, saveToCache); + }); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -50,10 +49,10 @@ std::future> WebMapTextureLoader::loadTextureAsync( std::optional WebMapTextureLoader::loadTexture(WebMapService const& wms, WebMapLayer const& layer, Request const& request, std::string const& mapCache, bool saveToCache) { - boost::filesystem::path cachePath = getCachePath(wms, layer, request, mapCache); + std::filesystem::path cachePath = getCachePath(wms, layer, request, mapCache); if (saveToCache) { // The file is already there, we can return it - if (boost::filesystem::exists(cachePath) && boost::filesystem::file_size(cachePath) > 0) { + if (std::filesystem::exists(cachePath) && std::filesystem::file_size(cachePath) > 0) { std::optional texture = loadTextureFromFile(cachePath.string()); return texture; } @@ -147,19 +146,19 @@ std::optional WebMapTextureLoader::requestTexture( //////////////////////////////////////////////////////////////////////////////////////////////////// void WebMapTextureLoader::saveTextureToFile( - boost::filesystem::path const& file, std::stringstream const& data) { + std::filesystem::path const& file, std::stringstream const& data) { { std::unique_lock lock(mTextureMutex); - if (boost::filesystem::exists(file) && boost::filesystem::file_size(file) == 0) { - boost::filesystem::remove(file); + if (std::filesystem::exists(file) && std::filesystem::file_size(file) == 0) { + std::filesystem::remove(file); } - auto cacheDirPath(boost::filesystem::absolute(file.parent_path())); - if (!(boost::filesystem::exists(file))) { + auto cacheDirPath(std::filesystem::absolute(file.parent_path())); + if (!(std::filesystem::exists(file))) { try { cs::utils::filesystem::createDirectoryRecursively( - cacheDirPath, boost::filesystem::perms::all_all); + cacheDirPath, std::filesystem::perms::all); } catch (std::exception& e) { logger().warn("Failed to create cache directory: '{}'!", e.what()); return; @@ -179,11 +178,11 @@ void WebMapTextureLoader::saveTextureToFile( out << data.rdbuf(); } - boost::filesystem::perms filePerms = - boost::filesystem::perms::owner_read | boost::filesystem::perms::owner_write | - boost::filesystem::perms::group_read | boost::filesystem::perms::group_write | - boost::filesystem::perms::others_read | boost::filesystem::perms::others_write; - boost::filesystem::permissions(file, filePerms); + std::filesystem::perms filePerms = + std::filesystem::perms::owner_read | std::filesystem::perms::owner_write | + std::filesystem::perms::group_read | std::filesystem::perms::group_write | + std::filesystem::perms::others_read | std::filesystem::perms::others_write; + std::filesystem::permissions(file, filePerms); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -226,13 +225,18 @@ std::optional WebMapTextureLoader::loadTextureFromStream( //////////////////////////////////////////////////////////////////////////////////////////////////// -boost::filesystem::path WebMapTextureLoader::getCachePath(WebMapService const& wms, +std::filesystem::path WebMapTextureLoader::getCachePath(WebMapService const& wms, WebMapLayer const& layer, Request const& request, std::string const& mapCache) { // Replace forbidden characters in layer string before creating cache dir. std::string layerFixed; - boost::replace_copy_if( - layer.getName(), std::back_inserter(layerFixed), boost::is_any_of("*.,:[|]\""), '_'); + std::ranges::copy(layer.getName() | std::views::transform([](char c) { + return (c == '*' || c == '.' || c == ',' || c == ':' || c == '[' || c == '|' || c == ']' || + c == '"') + ? '_' + : c; + }), + std::back_inserter(layerFixed)); // Set file format to three caracters. std::string fileFormat = mMimeToExtension.at(getMimeType(wms, layer)); @@ -268,7 +272,7 @@ boost::filesystem::path WebMapTextureLoader::getCachePath(WebMapService const& w cacheFile << cacheDir.str() << layerFixed << "." << fileFormat; } - return boost::filesystem::path(cacheFile.str()); + return std::filesystem::path(cacheFile.str()); } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/csp-wms-overlays/src/WebMapTextureLoader.hpp b/plugins/csp-wms-overlays/src/WebMapTextureLoader.hpp index cdf40dac0..b16171954 100644 --- a/plugins/csp-wms-overlays/src/WebMapTextureLoader.hpp +++ b/plugins/csp-wms-overlays/src/WebMapTextureLoader.hpp @@ -13,9 +13,8 @@ #include "../../../src/cs-utils/ThreadPool.hpp" -#include - #include +#include #include namespace csp::wmsoverlays { @@ -60,7 +59,7 @@ class WebMapTextureLoader { WebMapService const& wms, WebMapLayer const& layer, Request const& request); /// Saves a binary stream of a texture file to the given path. - void saveTextureToFile(boost::filesystem::path const& file, std::stringstream const& data); + void saveTextureToFile(std::filesystem::path const& file, std::stringstream const& data); /// Loads WMS texture from a file using stbi. static std::optional loadTextureFromFile(std::string const& fileName); @@ -69,7 +68,7 @@ class WebMapTextureLoader { static std::optional loadTextureFromStream(std::stringstream const& stream); /// Constructs a path for loading/saving the texture requested with the given parameters. - boost::filesystem::path getCachePath(WebMapService const& wms, WebMapLayer const& layer, + std::filesystem::path getCachePath(WebMapService const& wms, WebMapLayer const& layer, Request const& request, std::string const& mapCache); /// Constructs a request URL for the given parameters. diff --git a/plugins/csp-wms-overlays/src/utils.cpp b/plugins/csp-wms-overlays/src/utils.cpp index e14885d7c..17fbca73a 100644 --- a/plugins/csp-wms-overlays/src/utils.cpp +++ b/plugins/csp-wms-overlays/src/utils.cpp @@ -12,13 +12,10 @@ #include "../../../src/cs-utils/logger.hpp" #include "../../../src/cs-utils/utils.hpp" -namespace csp::wmsoverlays { - -//////////////////////////////////////////////////////////////////////////////////////////////////// +#include +#include -bool Duration::isDuration() const { - return mYears + mMonths + mTimeDuration.total_seconds() != 0; -} +namespace csp::wmsoverlays { //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -26,25 +23,20 @@ namespace utils { //////////////////////////////////////////////////////////////////////////////////////////////////// -std::string timeToString(std::string const& format, boost::posix_time::ptime time) { - std::stringstream sstr; - // Delete is called by the std::locale constructor. - auto* facet = new boost::posix_time::time_facet(); - facet->format(format.c_str()); - sstr.imbue(std::locale(std::locale::classic(), facet)); - sstr << time; - - return sstr.str(); +std::string timeToString(std::string const& format, std::chrono::utc_clock::time_point time) { + auto value = std::chrono::time_point_cast(time); + return std::vformat("{:" + format + "}", std::make_format_args(value)); } //////////////////////////////////////////////////////////////////////////////////////////////////// -void matchDuration(std::string const& input, std::regex const& re, Duration& duration) { +void matchDuration( + std::string const& input, std::regex const& re, std::chrono::utc_clock::duration& duration) { std::smatch match; std::regex_search(input, match, re); if (match.empty()) { - spdlog::debug("Pattern does not match!"); + logger().debug("Pattern does not match!"); return; } @@ -58,22 +50,18 @@ void matchDuration(std::string const& input, std::regex const& re, Duration& dur } } - duration.mYears = vec[0]; // years - duration.mMonths = vec[1]; // months - duration.mTimeDuration = boost::posix_time::hours(24 * vec[2]) + // days - boost::posix_time::hours(vec[3]) + // hours - boost::posix_time::minutes(vec[4]) + // minutes - boost::posix_time::seconds(vec[5]); // seconds + duration = std::chrono::years(vec[0]) + std::chrono::months(vec[1]) + std::chrono::days(vec[2]) + + std::chrono::hours(vec[3]) + std::chrono::minutes(vec[4]) + + std::chrono::seconds(vec[5]); - if (!duration.isDuration()) { - spdlog::debug("Input is not valid!"); - return; + if (duration.count() == 0) { + logger().debug("Input is not valid!"); } } //////////////////////////////////////////////////////////////////////////////////////////////////// -void timeDuration(std::string const& isoString, Duration& duration) { +void timeDuration(std::string const& isoString, std::chrono::utc_clock::duration& duration) { std::regex rshort("^((?!T).)*$"); // Check if isoString matches rshort. @@ -90,42 +78,8 @@ void timeDuration(std::string const& isoString, Duration& duration) { //////////////////////////////////////////////////////////////////////////////////////////////////// -void convertIsoDate(std::string& date, boost::posix_time::ptime& time) { - if (date.find('T') != std::string::npos) { - if (std::regex_match(date, std::regex("[+\\-][0-9]{2}:?([0-9]{2})?$"))) { - logger().warn( - "Time '{}' is not given in UTC but uses an offset. The offset will be ignored!"); - } - - // Remove timezone from date string. - // For now UTC offsets are not supported and will be ignored. - date = std::regex_replace(date, std::regex("(Z$|[+\\-][0-9]{2}:?([0-9]{2})?$)"), ""); - } - - date.erase( - std::remove_if(date.begin(), date.end(), [](unsigned char x) { return std::ispunct(x); }), - date.end()); - - std::size_t pos = date.find('T'); - std::string dateSubStr = date.substr(0, pos); - std::string timeSubStr = "T"; - - if (pos != std::string::npos) { - timeSubStr = date.substr(pos); - } - - if (dateSubStr.size() == 4) { - // Only year given, append month - dateSubStr.append("01"); - } - if (dateSubStr.size() == 6) { - // Only year and month given, append day - dateSubStr.append("01"); - } - - dateSubStr.resize(8, '0'); - timeSubStr.resize(7, '0'); - time = boost::posix_time::from_iso_string(dateSubStr + timeSubStr); +void convertIsoDate(std::string& date, std::chrono::utc_clock::time_point& time) { + time = cs::utils::convert::time::toUTC(date); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -145,14 +99,14 @@ void parseIsoString(std::string const& isoString, std::vector& tim std::getline(timeRange_stringstream, endDate, '/'); std::getline(timeRange_stringstream, duration, '/'); - TimeInterval tmp; - boost::posix_time::ptime start; - boost::posix_time::ptime end; + TimeInterval tmp; + std::chrono::utc_clock::time_point start; + std::chrono::utc_clock::time_point end; convertIsoDate(startDate, start); // Check format of startData - std::array formatParts = {"%Y", "-%m", "-%d", "T%H", ":%M", ":%S", ".%f"}; - std::array partLengths = {"4", "2", "2", "2", "2", "2", "1,3"}; + std::array formatParts = {"%Y", "-%m", "-%d", "T%H", ":%M", ":%S"}; + std::array partLengths = {"4", "2", "2", "2", "2", "2"}; std::smatch result; // Initialize result to complete startDate string std::regex_search(startDate, result, std::regex("^")); @@ -165,7 +119,7 @@ void parseIsoString(std::string const& isoString, std::vector& tim } else { if (i == 0) { // No year found, using default format - tmp.mFormat = "%Y-%m-%dT%H:%M:%S.%fZ"; + tmp.mFormat = "%Y-%m-%dT%H:%M:%SZ"; } break; } @@ -181,17 +135,15 @@ void parseIsoString(std::string const& isoString, std::vector& tim } else { timeDuration(duration, tmp.mSampleDuration); - // If end date is set to currect, select it according to the time format. + // If end date is set to current, select it according to the time format. if (endDate == "current") { + auto now = std::chrono::utc_clock::now(); if (tmp.mFormat == "%Y") { - end = boost::posix_time::ptime(boost::gregorian::date( - boost::posix_time::microsec_clock::universal_time().date().year(), 1, 1)); + end = std::chrono::floor(now); } else if (tmp.mFormat == "%Y-%m") { - end = boost::posix_time::ptime(boost::gregorian::date( - boost::posix_time::microsec_clock::universal_time().date().year(), - boost::posix_time::microsec_clock::universal_time().date().month(), 1)); + end = std::chrono::floor(now); } else { - end = boost::posix_time::microsec_clock::universal_time(); + end = now; } } else { convertIsoDate(endDate, end); @@ -206,83 +158,29 @@ void parseIsoString(std::string const& isoString, std::vector& tim //////////////////////////////////////////////////////////////////////////////////////////////////// -bool timeInIntervals(boost::posix_time::ptime& time, std::vector const& timeIntervals, - TimeInterval& foundInterval) { - // Check each interval whether the given time is inside or not.. - for (auto interval = timeIntervals.rbegin(); interval != timeIntervals.rend(); interval++) { - // In order to check if there is data for the current time, the length of the WMS interval - // (duration of one sample) is added to the current interval. - boost::posix_time::ptime intervalEndTime = - addDurationToTime(interval->mEndTime, interval->mSampleDuration); - - // Sample time of the current time is inside the time interval. - if (interval->mStartTime <= time && intervalEndTime > time) { - - // Find the last sample time before the current time. - if (interval->mSampleDuration.mYears != 0) { - // Sample rate is in years. - - // Substract years when sample rate is more than one year. - int year = time.date().year() - ((time.date().year() - interval->mStartTime.date().year()) % - interval->mSampleDuration.mYears); - - // Construct a new time for sample start time. - time = boost::posix_time::ptime(boost::gregorian::date(year, 1, 1)); - } else if (interval->mSampleDuration.mMonths != 0) { - // Sample rate is in months. - - // Substract months when sample rate is more than one month. - int month = - time.date().month() - ((time.date().month() - interval->mStartTime.date().month()) % - interval->mSampleDuration.mMonths); - int year = time.date().year(); - - // When month is in the previous year. - if (month > time.date().month()) { - year -= 1; - } - - // Construct a new time for sample start time. - time = boost::posix_time::ptime(boost::gregorian::date(year, month, 1)); - } else { - // Sample rate is in days or time. +bool timeInIntervals(std::chrono::utc_clock::time_point& time, + std::vector const& timeIntervals, TimeInterval& foundInterval) { + for (const auto& interval : timeIntervals) { + // Check if time is within the interval + if (time >= interval.mStartTime && time < interval.mEndTime) { + // Calculate the number of samples since the start of the interval + auto elapsed = time - interval.mStartTime; + auto samplesPassed = elapsed / interval.mSampleDuration; - // Necessary when sample rate is more than 1 day. - if (interval->mSampleDuration.mTimeDuration.total_seconds() > 0) { - time -= - boost::posix_time::seconds((time - interval->mStartTime).total_seconds() % - interval->mSampleDuration.mTimeDuration.total_seconds()); - } - } + // Snap the time to the start of the current sample + time = interval.mStartTime + samplesPassed * interval.mSampleDuration; - foundInterval = *interval; + // Set the found interval + foundInterval = interval; return true; } } - - // Time is not in any of the intervals. return false; } //////////////////////////////////////////////////////////////////////////////////////////////////// -boost::posix_time::ptime addDurationToTime( - boost::posix_time::ptime time, Duration const& duration, int multiplier) { - - // Check which unit the interval contatins. - if (duration.mYears != 0) { - return time + boost::gregorian::years(multiplier * duration.mYears); - } - if (duration.mMonths != 0) { - return time + boost::gregorian::months(multiplier * duration.mMonths); - } else { - return time + duration.mTimeDuration * multiplier; - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - std::optional> getSizeAttribute( VistaXML::TiXmlElement* element, std::string const& attributeName) { std::optional value = getAttribute(element, attributeName); diff --git a/plugins/csp-wms-overlays/src/utils.hpp b/plugins/csp-wms-overlays/src/utils.hpp index 139664a9b..04f0dbcb0 100644 --- a/plugins/csp-wms-overlays/src/utils.hpp +++ b/plugins/csp-wms-overlays/src/utils.hpp @@ -45,27 +45,12 @@ struct Bounds { } }; -/// Struct for the duration of the WMS time step. -/// Ideally only one of the members should be non-zero. -struct Duration { - int mYears = 0; - int mMonths = 0; - boost::posix_time::time_duration mTimeDuration = boost::posix_time::seconds(0); - - /// Checks whether the object represents a non-zero duration. - bool isDuration() const; - - inline bool operator==(const Duration& rhs) const { - return mYears == rhs.mYears && mMonths == rhs.mMonths && mTimeDuration == rhs.mTimeDuration; - } -}; - /// Struct of timeintervals of the data set. struct TimeInterval { - boost::posix_time::ptime mStartTime; ///< The beginning of the interval. - boost::posix_time::ptime mEndTime; ///< The end of the interval. - std::string mFormat; ///< The string format of time values. - Duration mSampleDuration; ///< The duration of one sample in WMS interval. + std::chrono::utc_clock::time_point mStartTime; ///< The beginning of the interval. + std::chrono::utc_clock::time_point mEndTime; ///< The end of the interval. + std::chrono::utc_clock::duration mSampleDuration; ///< The duration of one sample in WMS interval. + std::string mFormat; ///< The string format of time values. inline bool operator==(const TimeInterval& rhs) const { return mStartTime == rhs.mStartTime && mEndTime == rhs.mEndTime && mFormat == rhs.mFormat && @@ -90,16 +75,17 @@ struct TimeInterval { namespace utils { /// Create formatted date, time string from time value. -std::string timeToString(std::string const& format, boost::posix_time::ptime time); +std::string timeToString(std::string const& format, std::chrono::utc_clock::time_point time); /// Match years, months, days, etc. in regex input string and calculate duration. -void matchDuration(std::string const& input, std::regex const& re, Duration& duration); +void matchDuration( + std::string const& input, std::regex const& re, std::chrono::utc_clock::duration& duration); /// Determine interval duration from string regex. -void timeDuration(std::string const& isoString, Duration& duration); +void timeDuration(std::string const& isoString, std::chrono::utc_clock::duration& duration); /// Convert date from string to time. -void convertIsoDate(std::string& date, boost::posix_time::ptime& time); +void convertIsoDate(std::string& date, std::chrono::utc_clock::time_point& time); /// Parse time intervals from string. void parseIsoString(std::string const& isoString, std::vector& timeIntervals); @@ -107,14 +93,8 @@ void parseIsoString(std::string const& isoString, std::vector& tim /// Check whether the given time is inside one of the time intervals. /// Then calculate the start time of the current sample if it is in the interval. /// If the time is in an interval, the 'foundInterval' parameter will be set to it. -bool timeInIntervals(boost::posix_time::ptime& time, std::vector const& timeIntervals, - TimeInterval& foundInterval); - -/// Adds the interval duration to the given time. -/// The duration can be either in years, months or in time_duration. -/// Adds the interval multiple times, if it is specified (e.g. for pre-fetch). -boost::posix_time::ptime addDurationToTime( - boost::posix_time::ptime time, Duration const& duration, int multiplier = 1); +bool timeInIntervals(std::chrono::utc_clock::time_point& time, + std::vector const& timeIntervals, TimeInterval& foundInterval); /// Tries to get the value contained in a XML element. /// Starts at baseElement and then descends into the children given as childPath. diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index 07273cb4e..17db54bb9 100644 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -18,21 +18,21 @@ install(DIRECTORY "shaders" DESTINATION "share/resources") if(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC) set(CEF_RESOURCES - "${CEF_LIBRARY_DIR}/snapshot_blob.bin" "${CEF_LIBRARY_DIR}/v8_context_snapshot.bin" "${CEF_LIBRARY_DIR}/libcef.dll" "${CEF_LIBRARY_DIR}/chrome_elf.dll" + "${CEF_LIBRARY_DIR}/libEGL.dll" + "${CEF_LIBRARY_DIR}/libGLESv2.dll" ) install(FILES ${CEF_RESOURCES} DESTINATION "bin") - install(DIRECTORY "${CEF_LIBRARY_DIR}/swiftshader" DESTINATION "bin") install(DIRECTORY "${CEF_RESOURCE_DIR}/" DESTINATION "bin") else() set(CEF_RESOURCES - "${CEF_LIBRARY_DIR}/snapshot_blob.bin" "${CEF_LIBRARY_DIR}/v8_context_snapshot.bin" + "${CEF_LIBRARY_DIR}/libEGL.so" + "${CEF_LIBRARY_DIR}/libGLESv2.so" ) install(FILES ${CEF_RESOURCES} DESTINATION "lib") - install(DIRECTORY "${CEF_LIBRARY_DIR}/swiftshader/" DESTINATION "lib") install(DIRECTORY "${CEF_RESOURCE_DIR}/" DESTINATION "lib" PATTERN "locales" EXCLUDE) install(DIRECTORY "${CEF_RESOURCE_DIR}/locales" DESTINATION "bin") endif() diff --git a/resources/gui/js/apis/timeline.js b/resources/gui/js/apis/timeline.js index 710fd4a8d..96ba3d9d6 100644 --- a/resources/gui/js/apis/timeline.js +++ b/resources/gui/js/apis/timeline.js @@ -233,7 +233,7 @@ class TimelineApi extends IApi { */ setDate(date) { if (isNaN(date.getTime())) { - console.warn("Invalid date given to timeline!"); + console.warn(`Invalid date given to timeline: ${date}!`); } else { this._centerTime = date; this._timeline.moveTo(this._centerTime, { diff --git a/src/cosmoscout/Application.cpp b/src/cosmoscout/Application.cpp index ae55a08c2..1a6578bcc 100644 --- a/src/cosmoscout/Application.cpp +++ b/src/cosmoscout/Application.cpp @@ -595,7 +595,7 @@ void Application::FrameUpdate() { if (!std::isnan(polar.x) && !std::isnan(polar.y) && !std::isnan(heightDiff)) { mGuiManager->getGui()->executeJavascript( - fmt::format("CosmoScout.state.observerLngLatHeight = [{}, {}, {}]", + std::format("CosmoScout.state.observerLngLatHeight = [{}, {}, {}]", cs::utils::convert::toDegrees(polar.x), cs::utils::convert::toDegrees(polar.y), heightDiff)); } @@ -828,7 +828,7 @@ void Application::connectSlots() { if (!std::isnan(lngLat.x) && !std::isnan(lngLat.y) && !std::isnan(polar.z)) { mGuiManager->getGui()->executeJavascript( - fmt::format("CosmoScout.state.pointerPosition = [{}, {}, {}];", lngLat.x, lngLat.y, + std::format("CosmoScout.state.pointerPosition = [{}, {}, {}];", lngLat.x, lngLat.y, polar.z / mSettings->mGraphics.pHeightScale.get())); return; } @@ -839,13 +839,13 @@ void Application::connectSlots() { // Update the time shown in the user interface when the simulation time changes. mTimeControl->pSimulationTime.connectAndTouch([this](double val) { mGuiManager->getGui()->executeJavascript( - fmt::format("CosmoScout.state.simulationTime = new Date('{}');", + std::format("CosmoScout.state.simulationTime = new Date('{}');", cs::utils::convert::time::toString(val))); }); // Update the simulation time speed shown in the user interface. mSettings->pTimeSpeed.connectAndTouch([this](float val) { - mGuiManager->getGui()->executeJavascript(fmt::format("CosmoScout.state.timeSpeed = {};", val)); + mGuiManager->getGui()->executeJavascript(std::format("CosmoScout.state.timeSpeed = {};", val)); }); // Show notification when the center name of the celestial observer changes. @@ -860,34 +860,34 @@ void Application::connectSlots() { } mGuiManager->getGui()->executeJavascript( - fmt::format("CosmoScout.state.activePlanetCenter = '{}';", center)); + std::format("CosmoScout.state.activePlanetCenter = '{}';", center)); - mGuiManager->getGui()->executeJavascript(fmt::format( + mGuiManager->getGui()->executeJavascript(std::format( "CosmoScout.state.activePlanetRadius = [{}, {}, {}];", radii[0], radii[1], radii[2])); }); // Show notification when the frame name of the celestial observer changes. mSettings->mObserver.pFrame.connectAndTouch([this](std::string const& frame) { mGuiManager->getGui()->executeJavascript( - fmt::format("CosmoScout.state.activePlanetFrame = '{}';", frame)); + std::format("CosmoScout.state.activePlanetFrame = '{}';", frame)); }); // Set the observer position state. mSettings->mObserver.pPosition.connectAndTouch([this](glm::dvec3 const& p) { mGuiManager->getGui()->executeJavascript( - fmt::format("CosmoScout.state.observerPosition = [{}, {}, {}];", p.x, p.y, p.z)); + std::format("CosmoScout.state.observerPosition = [{}, {}, {}];", p.x, p.y, p.z)); }); // Set the observer rotation state. mSettings->mObserver.pRotation.connectAndTouch([this](glm::dquat const& r) { mGuiManager->getGui()->executeJavascript( - fmt::format("CosmoScout.state.observerRotation = [{}, {}, {}, {}];", r.x, r.y, r.z, r.w)); + std::format("CosmoScout.state.observerRotation = [{}, {}, {}, {}];", r.x, r.y, r.z, r.w)); }); // Show the current speed of the celestial observer in the user interface. mSolarSystem->pCurrentObserverSpeed.connect([this](float speed) { mGuiManager->getGui()->executeJavascript( - fmt::format("CosmoScout.state.observerSpeed = {};", speed)); + std::format("CosmoScout.state.observerSpeed = {};", speed)); }); // Show log messages in the user interface. diff --git a/src/cs-core/GuiManager.cpp b/src/cs-core/GuiManager.cpp index 8ffb25d46..c461e5f5a 100644 --- a/src/cs-core/GuiManager.cpp +++ b/src/cs-core/GuiManager.cpp @@ -111,8 +111,8 @@ GuiManager::GuiManager( // documentation of cs::gui::WebView::setZoomLevel in great detail. This also means that all other // WebViews with an URL starting with "file://{mainUIZoom}../" will be automatically affected by // the pMainUIScale factor. - mCosmoScoutGui = std::make_unique( - "file://{mainUIZoom}../share/resources/gui/cosmoscout.html", true); + mCosmoScoutGui = + std::make_unique("file://{mainUIZoom}../share/resources/gui/cosmoscout.html"); // Usually, all GuiItems are attached to the global world-space GuiArea if it is // available. If not, they are added to the local screen-space GuiArea. @@ -303,7 +303,7 @@ uint32_t GuiManager::addBookmark(Settings::Bookmark bookmark) { auto c = bookmark.mColor.value_or(glm::vec3(0.8F, 0.8F, 1.0F)) * 255.F; mCosmoScoutGui->callJavascript("CosmoScout.timeline.addBookmark", newID, start, end, - fmt::format("rgb({}, {}, {})", c.r, c.g, c.b)); + std::format("rgb({}, {}, {})", c.r, c.g, c.b)); } mBookmarks.emplace(newID, std::move(bookmark)); diff --git a/src/cs-core/InputManager.cpp b/src/cs-core/InputManager.cpp index f6dbd935f..de2f92595 100644 --- a/src/cs-core/InputManager.cpp +++ b/src/cs-core/InputManager.cpp @@ -10,6 +10,7 @@ #include "../cs-gui/GuiItem.hpp" #include "../cs-gui/ScreenSpaceGuiArea.hpp" #include "../cs-gui/WorldSpaceGuiArea.hpp" +#include "../cs-scene/IntersectableObject.hpp" #include "../cs-utils/utils.hpp" #include "GuiManager.hpp" #include "logger.hpp" @@ -17,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -33,7 +33,6 @@ #include #include #include -#include namespace cs::core { @@ -45,7 +44,7 @@ InputManager::InputManager(std::shared_ptr settings) // Tell the user what's going on. logger().debug("Creating InputManager."); - mClickTime = boost::posix_time::microsec_clock::universal_time(); + mClickTime = std::chrono::steady_clock::now(); auto* pSG = GetVistaSystem()->GetGraphicsManager()->GetSceneGraph(); @@ -548,12 +547,11 @@ void InputManager::HandleEvent(VistaEvent* pEvent) { } if (!port->GetValue()) { - auto t = boost::posix_time::microsec_clock::universal_time(); + auto t = std::chrono::steady_clock::now(); auto diff = (t - mClickTime); - int32_t const doubleClickTimeMillis = 200; - if (diff < boost::posix_time::time_duration( - boost::posix_time::millisec(doubleClickTimeMillis))) { + std::chrono::milliseconds doubleClickTime{200}; + if (diff < doubleClickTime) { sOnDoubleClick.emit(); } mClickTime = t; diff --git a/src/cs-core/InputManager.hpp b/src/cs-core/InputManager.hpp index 332517a7e..4b4b1f95d 100644 --- a/src/cs-core/InputManager.hpp +++ b/src/cs-core/InputManager.hpp @@ -10,7 +10,6 @@ #include "cs_core_export.hpp" -#include "../cs-scene/IntersectableObject.hpp" #include "../cs-utils/Property.hpp" #include "Settings.hpp" @@ -19,12 +18,9 @@ #include #include -#include #include #include -#include - class IVistaNode; class VistaNodeAdapter; class VistaOpenGLNode; @@ -170,7 +166,7 @@ class CS_CORE_EXPORT InputManager : public VistaKeyboardSystemControl::IVistaDir VistaIntentionSelect mSelection; std::unordered_set mAdapters; std::unordered_set mScreenSpaceGuis; - boost::posix_time::ptime mClickTime; + std::chrono::steady_clock::time_point mClickTime; VistaOpenGLNode* mActiveWorldSpaceGuiNode{}; diff --git a/src/cs-core/Settings.cpp b/src/cs-core/Settings.cpp index bedca43fe..bfeda14af 100644 --- a/src/cs-core/Settings.cpp +++ b/src/cs-core/Settings.cpp @@ -13,7 +13,6 @@ #include "logger.hpp" #include -#include namespace nlohmann { @@ -46,15 +45,15 @@ void from_json(nlohmann::json const& cs::scene::CelestialObject object; // First, we parse the required parameters. - std::string center, frame; - std::array existence; + std::string center, frame; + std::pair existence; cs::core::Settings::deserialize(data, "center", center); cs::core::Settings::deserialize(data, "frame", frame); cs::core::Settings::deserialize(data, "existence", existence); object.setCenterName(center); object.setFrameName(frame); - object.setExistenceAsStrings(existence); + object.setExistenceAsStrings({existence.first, existence.second}); // All others are optional. std::optional position, radii; diff --git a/src/cs-core/Settings.hpp b/src/cs-core/Settings.hpp index c859ba3bf..bfb0f0916 100644 --- a/src/cs-core/Settings.hpp +++ b/src/cs-core/Settings.hpp @@ -18,7 +18,6 @@ #include "../cs-utils/utils.hpp" #include "EclipseShadowReceiver.hpp" -#include #include #include #include diff --git a/src/cs-core/SolarSystem.cpp b/src/cs-core/SolarSystem.cpp index 73411f005..7da419046 100644 --- a/src/cs-core/SolarSystem.cpp +++ b/src/cs-core/SolarSystem.cpp @@ -240,8 +240,7 @@ void SolarSystem::fixObserverFrame(double lastWorkingSimulationTime) { void SolarSystem::update() { double simulationTime(mTimeControl->pSimulationTime.get()); - double realTime( - utils::convert::time::toSpice(boost::posix_time::microsec_clock::universal_time())); + double realTime(utils::convert::time::toSpice(std::chrono::utc_clock::now())); mObserver.updateMovementAnimation(realTime); // First, update all celestial object positions. @@ -465,8 +464,7 @@ void SolarSystem::flyObserverTo(std::string const& sCenter, std::string const& s glm::dvec3 const& position, glm::dquat const& rotation, double duration) { double simulationTime(mTimeControl->pSimulationTime.get()); - double startTime( - utils::convert::time::toSpice(boost::posix_time::microsec_clock::universal_time())); + double startTime(utils::convert::time::toSpice(std::chrono::utc_clock::now())); double endTime(startTime + duration); if (GetVistaSystem()->GetClusterMode()->GetIsLeader()) { diff --git a/src/cs-core/TimeControl.cpp b/src/cs-core/TimeControl.cpp index c2f8c0831..c30850393 100644 --- a/src/cs-core/TimeControl.cpp +++ b/src/cs-core/TimeControl.cpp @@ -24,7 +24,7 @@ TimeControl::TimeControl(std::shared_ptr settings) // Update the mStartDate in the settings. If the current simulation time differs less than one // minute from the current system time, we write "today", else the actual simulation date. mSettings->onSave().connect([this]() { - auto now = utils::convert::time::toSpice(boost::posix_time::microsec_clock::universal_time()); + auto now = utils::convert::time::toSpice(std::chrono::utc_clock::now()); if (std::abs(pSimulationTime.get() - now) < 60) { mSettings->mStartDate = "today"; } else { @@ -34,8 +34,7 @@ TimeControl::TimeControl(std::shared_ptr settings) mSettings->onLoad().connect([this]() { if (mSettings->mStartDate == "today") { - setTime( - utils::convert::time::toSpice(boost::posix_time::microsec_clock::universal_time()), 5.0); + setTime(utils::convert::time::toSpice(std::chrono::utc_clock::now()), 5.0); } else { try { setTime(utils::convert::time::toSpice(mSettings->mStartDate), 5.0); @@ -61,7 +60,7 @@ TimeControl::~TimeControl() { void TimeControl::update() { - double now = utils::convert::time::toSpice(boost::posix_time::microsec_clock::universal_time()); + double now = utils::convert::time::toSpice(std::chrono::utc_clock::now()); // Initialize our members. This has to be done here as SPICE is not yet loaded at construction // time. @@ -73,7 +72,7 @@ void TimeControl::update() { [this](std::string const& val) { pMinDate = utils::convert::time::toSpice(val); }); if (mSettings->mStartDate == "today") { - setTime(utils::convert::time::toSpice(boost::posix_time::microsec_clock::universal_time())); + setTime(utils::convert::time::toSpice(std::chrono::utc_clock::now())); } else { try { setTime(utils::convert::time::toSpice(mSettings->mStartDate)); @@ -110,7 +109,7 @@ void TimeControl::update() { //////////////////////////////////////////////////////////////////////////////////////////////////// void TimeControl::setTime(double tTime, double duration, double threshold) { - double now = utils::convert::time::toSpice(boost::posix_time::microsec_clock::universal_time()); + double now = utils::convert::time::toSpice(std::chrono::utc_clock::now()); double difference = std::abs(pSimulationTime.get() - tTime); if (tTime >= pMaxDate || tTime <= pMinDate) { @@ -138,8 +137,7 @@ void TimeControl::setTime(double tTime, double duration, double threshold) { void TimeControl::resetTime(double duration, double threshold) { if (mSettings->mResetDate == "today") { - setTime(utils::convert::time::toSpice(boost::posix_time::microsec_clock::universal_time()), - duration, threshold); + setTime(utils::convert::time::toSpice(std::chrono::utc_clock::now()), duration, threshold); } else { try { setTime(utils::convert::time::toSpice(mSettings->mResetDate), duration, threshold); diff --git a/src/cs-graphics/ColorMap.cpp b/src/cs-graphics/ColorMap.cpp index 2fa83f912..002a4a750 100644 --- a/src/cs-graphics/ColorMap.cpp +++ b/src/cs-graphics/ColorMap.cpp @@ -113,7 +113,7 @@ ColorMap::ColorMap(std::string const& sJsonString) { //////////////////////////////////////////////////////////////////////////////////////////////////// -ColorMap::ColorMap(boost::filesystem::path const& sJsonPath) { +ColorMap::ColorMap(std::filesystem::path const& sJsonPath) { std::ifstream file(sJsonPath.string()); nlohmann::json json; file >> json; diff --git a/src/cs-graphics/ColorMap.hpp b/src/cs-graphics/ColorMap.hpp index a76632fa3..c688910dc 100644 --- a/src/cs-graphics/ColorMap.hpp +++ b/src/cs-graphics/ColorMap.hpp @@ -11,9 +11,9 @@ #include "cs_graphics_export.hpp" #include -#include #include +#include #include #include #include @@ -26,7 +26,7 @@ class CS_GRAPHICS_EXPORT ColorMap { /// Creates a ColorMap from a json string. explicit ColorMap(std::string const& sJsonString); /// Creates a ColorMap from the json file at sJsonPath. - explicit ColorMap(boost::filesystem::path const& sJsonPath); + explicit ColorMap(std::filesystem::path const& sJsonPath); /// Binds the color map for use in rendering. void bind(unsigned unit); diff --git a/src/cs-gui/GuiItem.cpp b/src/cs-gui/GuiItem.cpp index 252946be1..59204457e 100644 --- a/src/cs-gui/GuiItem.cpp +++ b/src/cs-gui/GuiItem.cpp @@ -15,8 +15,8 @@ namespace cs::gui { //////////////////////////////////////////////////////////////////////////////////////////////////// -GuiItem::GuiItem(std::string const& url, bool allowLocalFileAccess) - : WebView(url, 100, 100, allowLocalFileAccess) +GuiItem::GuiItem(std::string const& url) + : WebView(url, 100, 100) , mAreaWidth(1) , mAreaHeight(1) , mSizeX(0) diff --git a/src/cs-gui/GuiItem.hpp b/src/cs-gui/GuiItem.hpp index 4c1d60d39..7e8e1cff1 100644 --- a/src/cs-gui/GuiItem.hpp +++ b/src/cs-gui/GuiItem.hpp @@ -22,7 +22,7 @@ class CS_GUI_EXPORT GuiItem : public WebView { public: /// Creates a new GuiItem for the given page at the location of the URL. - explicit GuiItem(std::string const& url, bool allowLocalFileAccess = false); + explicit GuiItem(std::string const& url); GuiItem(GuiItem const& other) = delete; GuiItem(GuiItem&& other) = delete; diff --git a/src/cs-gui/WebView.cpp b/src/cs-gui/WebView.cpp index 29d35baa4..734f5c467 100644 --- a/src/cs-gui/WebView.cpp +++ b/src/cs-gui/WebView.cpp @@ -23,13 +23,13 @@ class DevToolsClient : public CefClient { //////////////////////////////////////////////////////////////////////////////////////////////////// -WebView::WebView(const std::string& url, int width, int height, bool allowLocalFileAccess) +WebView::WebView(const std::string& url, int width, int height) : mClient(new detail::WebViewClient()) { WebView::resize(width, height); CefWindowInfo info; - info.width = width; - info.height = height; + info.bounds.width = width; + info.bounds.height = height; #ifdef _MSC_VER info.SetAsWindowless(nullptr); @@ -41,7 +41,6 @@ WebView::WebView(const std::string& url, int width, int height, bool allowLocalF int const targetFrameRate = 60; browserSettings.windowless_frame_rate = targetFrameRate; - browserSettings.web_security = allowLocalFileAccess ? STATE_DISABLED : STATE_ENABLED; mBrowser = CefBrowserHost::CreateBrowserSync(info, mClient, url, browserSettings, nullptr, nullptr); @@ -247,7 +246,7 @@ void WebView::selectAll() const { void WebView::injectFocusEvent(bool focus) { if (mInteractive) { - mBrowser->GetHost()->SendFocusEvent(focus); + mBrowser->GetHost()->SetFocus(focus); } } @@ -259,7 +258,7 @@ void WebView::injectMouseEvent(MouseEvent const& event) { } CefMouseEvent cef_event; - cef_event.modifiers = static_cast(mMouseModifiers); + cef_event.modifiers = static_cast(mMouseModifiers); cef_event.x = mMouseX; cef_event.y = mMouseY; @@ -298,7 +297,7 @@ void WebView::injectMouseEvent(MouseEvent const& event) { mMouseModifiers |= int(Modifier::eMiddleButton); } - cef_event.modifiers = static_cast(mMouseModifiers); + cef_event.modifiers = static_cast(mMouseModifiers); mBrowser->GetHost()->SendMouseClickEvent( cef_event, static_cast(event.mButton), false, mClickCount); break; @@ -312,7 +311,7 @@ void WebView::injectMouseEvent(MouseEvent const& event) { mMouseModifiers &= ~int(Modifier::eMiddleButton); } - cef_event.modifiers = static_cast(mMouseModifiers); + cef_event.modifiers = static_cast(mMouseModifiers); mBrowser->GetHost()->SendMouseClickEvent( cef_event, static_cast(event.mButton), true, mClickCount); break; diff --git a/src/cs-gui/WebView.hpp b/src/cs-gui/WebView.hpp index 8d2d7ed5b..919c374f1 100644 --- a/src/cs-gui/WebView.hpp +++ b/src/cs-gui/WebView.hpp @@ -31,7 +31,7 @@ namespace cs::gui { class CS_GUI_EXPORT WebView { public: /// Creates a new WebView for the given page at the location of the URL. - WebView(const std::string& url, int width, int height, bool allowLocalFileAccess = false); + WebView(const std::string& url, int width, int height); WebView(WebView const& other) = delete; WebView(WebView&& other) = delete; diff --git a/src/cs-gui/gui.cpp b/src/cs-gui/gui.cpp index 2697be828..c655be898 100644 --- a/src/cs-gui/gui.cpp +++ b/src/cs-gui/gui.cpp @@ -10,6 +10,7 @@ #include "internal/WebApp.hpp" #include "logger.hpp" +#include #include namespace cs::gui { @@ -33,6 +34,21 @@ void executeWebProcess(int argc, char* argv[]) { //////////////////////////////////////////////////////////////////////////////////////////////////// +std::filesystem::path getExecutablePath() { +#ifdef __linux__ + std::filesystem::path path = "/proc/self/exe"; + return std::filesystem::read_symlink(path); +#elif _WIN32 + wchar_t buffer[MAX_PATH]; + GetModuleFileNameW(nullptr, buffer, MAX_PATH); + return {buffer}; +#else + return {}; +#endif +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + void init() { if (!app) { @@ -50,6 +66,15 @@ void init() { settings.remote_debugging_port = 8999; settings.windowless_rendering_enabled = true; + std::filesystem::path exePath = getExecutablePath(); + std::filesystem::path exeDir = exePath.parent_path(); + + std::filesystem::path localesPath = exeDir / "locales"; + CefString(&settings.locales_dir_path).FromString(localesPath.string()); + + std::filesystem::path cachePath = exeDir / "cef_cache"; + CefString(&settings.root_cache_path).FromString(cachePath.string()); + if (!CefInitialize(app->GetArgs(), settings, app, nullptr)) { logger().error("Failed to initialize CEF. Gui will not work at all."); } diff --git a/src/cs-gui/internal/LifeSpanHandler.cpp b/src/cs-gui/internal/LifeSpanHandler.cpp index 4c9c88b2a..944646da4 100644 --- a/src/cs-gui/internal/LifeSpanHandler.cpp +++ b/src/cs-gui/internal/LifeSpanHandler.cpp @@ -15,7 +15,7 @@ namespace cs::gui::detail { //////////////////////////////////////////////////////////////////////////////////////////////////// bool LifeSpanHandler::OnBeforePopup(CefRefPtr /*browser*/, - CefRefPtr /*frame*/, const CefString& target_url, + CefRefPtr /*frame*/, int /*popup_id*/, const CefString& target_url, const CefString& /*target_frame_name*/, WindowOpenDisposition /*target_disposition*/, bool /*user_gesture*/, const CefPopupFeatures& /*popupFeatures*/, CefWindowInfo& /*windowInfo*/, CefRefPtr& /*client*/, CefBrowserSettings& /*settings*/, diff --git a/src/cs-gui/internal/LifeSpanHandler.hpp b/src/cs-gui/internal/LifeSpanHandler.hpp index aaec3c42b..97f78241f 100644 --- a/src/cs-gui/internal/LifeSpanHandler.hpp +++ b/src/cs-gui/internal/LifeSpanHandler.hpp @@ -22,7 +22,7 @@ class LifeSpanHandler : public CefLifeSpanHandler { /// Gets called when a popup or new window is to be created. We always open them in the system's /// default browser. - bool OnBeforePopup(CefRefPtr browser, CefRefPtr frame, + bool OnBeforePopup(CefRefPtr browser, CefRefPtr frame, int popup_id, const CefString& target_url, const CefString& target_frame_name, WindowOpenDisposition target_disposition, bool user_gesture, const CefPopupFeatures& popupFeatures, CefWindowInfo& windowInfo, diff --git a/src/cs-gui/internal/RequestHandler.cpp b/src/cs-gui/internal/RequestHandler.cpp index 5b462e20a..c957798cd 100644 --- a/src/cs-gui/internal/RequestHandler.cpp +++ b/src/cs-gui/internal/RequestHandler.cpp @@ -15,11 +15,11 @@ namespace cs::gui::detail { bool RequestHandler::OnCertificateError(CefRefPtr /*browser*/, cef_errorcode_t /*cert_error*/, CefString const& /*request_url*/, - CefRefPtr /*ssl_info*/, CefRefPtr callback) { + CefRefPtr /*ssl_info*/, CefRefPtr callback) { logger().warn("Detected a certificate error in Chromium Embedded Framework. Continuing..."); - callback->Continue(true); + callback->Continue(); return true; } diff --git a/src/cs-gui/internal/RequestHandler.hpp b/src/cs-gui/internal/RequestHandler.hpp index 479a1cd05..4b2f16935 100644 --- a/src/cs-gui/internal/RequestHandler.hpp +++ b/src/cs-gui/internal/RequestHandler.hpp @@ -21,7 +21,7 @@ class RequestHandler : public CefRequestHandler { /// Implements to ignore certificate errors. bool OnCertificateError(CefRefPtr browser, cef_errorcode_t cert_error, CefString const& request_url, CefRefPtr ssl_info, - CefRefPtr callback) override; + CefRefPtr callback) override; CefRefPtr GetResourceRequestHandler(CefRefPtr /*browser*/, CefRefPtr /*frame*/, CefRefPtr /*request*/, bool /*is_navigation*/, diff --git a/src/cs-gui/internal/ResourceRequestHandler.cpp b/src/cs-gui/internal/ResourceRequestHandler.cpp index a275dcb84..2d09ed6b4 100644 --- a/src/cs-gui/internal/ResourceRequestHandler.cpp +++ b/src/cs-gui/internal/ResourceRequestHandler.cpp @@ -30,10 +30,9 @@ CefRefPtr ResourceRequestHandler::GetResourceHandler( } // Here we skip anything marked with { ... } at the beginning of a file URL. This is explained in - // the documentation of WebView::setZoomLevel in great detail. The curly braces are %7B and %7D in - // encoded URLs. - if (url.find("file://%7B") == 0) { - pathStartIndex = url.find("%7D") + 3; + // the documentation of WebView::setZoomLevel in great detail. + if (url.find("file://{") == 0) { + pathStartIndex = url.find('}') + 1; } if (pathStartIndex > 0) { diff --git a/src/cs-gui/internal/WebApp.cpp b/src/cs-gui/internal/WebApp.cpp index e32300470..4a3d50af5 100644 --- a/src/cs-gui/internal/WebApp.cpp +++ b/src/cs-gui/internal/WebApp.cpp @@ -35,6 +35,7 @@ void WebApp::OnBeforeCommandLineProcessing( if (process_type.empty()) { command_line->AppendSwitch("enable-overlay-scrollbar"); command_line->AppendSwitch("enable-begin-frame-scheduling"); + command_line->AppendSwitch("disable-web-security"); if (!mHardwareAccelerated) { command_line->AppendSwitch("disable-gpu"); diff --git a/src/cs-utils/CMakeLists.txt b/src/cs-utils/CMakeLists.txt index 62c3adfaf..846499a58 100644 --- a/src/cs-utils/CMakeLists.txt +++ b/src/cs-utils/CMakeLists.txt @@ -22,9 +22,6 @@ target_link_libraries(cs-utils glm::glm doctest::doctest tinygltf::tinygltf - Boost::filesystem - Boost::chrono - Boost::date_time GLEW::GLEW SDL2::base SDL2::main @@ -40,7 +37,6 @@ target_link_libraries(cs-utils cspice::cspice curl::curl curlpp::curlpp - c-ares::c-ares spdlog::spdlog ) diff --git a/src/cs-utils/Downloader.cpp b/src/cs-utils/Downloader.cpp index f303eb285..588929fe7 100644 --- a/src/cs-utils/Downloader.cpp +++ b/src/cs-utils/Downloader.cpp @@ -21,7 +21,7 @@ Downloader::Downloader(size_t threadCount) //////////////////////////////////////////////////////////////////////////////////////////////////// void Downloader::download(std::string const& url, std::string const& file) { - if (boost::filesystem::exists(file)) { + if (std::filesystem::exists(file)) { return; } diff --git a/src/cs-utils/convert.cpp b/src/cs-utils/convert.cpp index 944e3fd81..017ac7444 100644 --- a/src/cs-utils/convert.cpp +++ b/src/cs-utils/convert.cpp @@ -112,16 +112,14 @@ namespace time { //////////////////////////////////////////////////////////////////////////////////////////////////// -double toSpice(boost::posix_time::ptime const& tIn) { +double toSpice(std::chrono::utc_clock::time_point const& tIn) { + using namespace std::chrono_literals; - auto const startYear = 2000; - auto const noon = 12; - auto const secondsToMillis = 1000.0; + auto j2000 = toUTC(2000y / 1 / 1, 12h); - auto j2000 = boost::posix_time::ptime( - boost::gregorian::date(startYear, 1, 1), boost::posix_time::hours(noon)); - - double dTime = (tIn - j2000).total_milliseconds() / secondsToMillis; + // Calculate time difference in seconds + auto diff = tIn - j2000; + auto dTime = std::chrono::duration_cast>(diff).count(); // Incorporate delta between ET and UTC. double ETUTCDelta = 0.0; @@ -134,7 +132,7 @@ double toSpice(boost::posix_time::ptime const& tIn) { double toSpice(std::string const& tIn) { try { - return toSpice(toPosix(tIn)); + return toSpice(toUTC(tIn)); } catch (std::exception& e) { logger().error("Failed to convert time: {}", e.what()); } return 0.0; @@ -142,60 +140,121 @@ double toSpice(std::string const& tIn) { //////////////////////////////////////////////////////////////////////////////////////////////////// -boost::posix_time::ptime toPosix(std::string const& tIn) { - - // We need at least a length of 19 chracters +std::chrono::utc_clock::time_point toUTC(const std::string& tIn) { + // We need at least a length of 19 characters if (tIn.length() < 19) { - logger().error("Failed to convert '{}' to boost::posix_time::ptime!", tIn); - return boost::posix_time::ptime(); - } - - // Remove potential Z in YYYY-MM-DDTHH:MM:SS.fffZ - auto copy = tIn; - if (copy.back() == 'Z') { - copy.back() = '0'; + logger().error("Failed to convert '{}' to time_point!", tIn); + return std::chrono::utc_clock::time_point{}; } - // Remove potential T in YYYY-MM-DDTHH:MM:SS.fff - copy[10] = ' '; - try { - // Let boost do the parsing - return boost::posix_time::time_from_string(copy); - - } catch (std::exception& e) { - logger().error("Failed to convert '{}' to boost::posix_time::ptime: {}!", tIn, e.what()); + // Create a copy for potential modifications + std::string copy = tIn; + + // Remove potential Z in YYYY-MM-DDTHH:MM:SS.fffZ + if (copy.back() == 'Z') { + copy.pop_back(); + } + + // Replace T with space if present at position 10 + if (copy.length() > 10 && copy[10] == 'T') { + copy[10] = ' '; + } + + // Parse date and time using C++20 chrono + std::istringstream ss(copy); + std::chrono::year_month_day date; + + int year, month, day; + char delimiter; + ss >> year >> delimiter >> month >> delimiter >> day; + + if (ss.fail()) { + throw std::runtime_error("Failed to parse date part"); + } + + date = std::chrono::year{year} / static_cast(month) / + static_cast(day); + + if (!date.ok()) { + throw std::runtime_error("Invalid date"); + } + + int hour, minute, second; + ss >> hour >> delimiter >> minute >> delimiter >> second; + + if (ss.fail()) { + throw std::runtime_error("Failed to parse time part"); + } + + // Handle potential milliseconds + int milliseconds = 0; + if (ss.peek() == '.') { + ss.ignore(); // Skip the dot + ss >> milliseconds; + } + + auto time = std::chrono::hours{hour} + std::chrono::minutes{minute} + + std::chrono::seconds{second} + std::chrono::milliseconds{milliseconds}; + + // Combine date and time + return toUTC(date, time); + } catch (const std::exception& e) { + logger().error("Failed to convert '{}' to time_point: {}!", tIn, e.what()); } - return boost::posix_time::ptime(); + return std::chrono::utc_clock::time_point{}; } //////////////////////////////////////////////////////////////////////////////////////////////////// -boost::posix_time::ptime toPosix(double tIn) { - auto const startYear = 2000; - auto const noon = 12; - auto const secondsToMillis = 1000; +std::chrono::utc_clock::time_point toUTC(double tIn) { + using namespace std::chrono_literals; // Incorporate delta between ET and UTC. double ETUTCDelta = 0.0; deltet_c(tIn, "ET", &ETUTCDelta); - return boost::posix_time::ptime(boost::gregorian::date(startYear, 1, 1), - boost::posix_time::hours(noon) + boost::posix_time::milliseconds(static_cast( - (tIn - ETUTCDelta) * secondsToMillis))); + // Create J2000 reference time (January 1, 2000 at 12:00:00 UTC) + auto j2000 = toUTC(2000y / 1 / 1, 12h); + + // Add the milliseconds offset + auto seconds = std::chrono::duration(tIn - ETUTCDelta); + + // Return the computed time point + return j2000 + std::chrono::duration_cast(seconds); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +std::chrono::utc_clock::time_point toUTC( + std::chrono::year_month_day const& ymd, std::chrono::utc_clock::duration const& hms) { + return std::chrono::utc_clock::from_sys(std::chrono::sys_days{ymd} + hms); } //////////////////////////////////////////////////////////////////////////////////////////////////// std::string toString(double tIn) { - return toString(toPosix(tIn)); + return toString(toUTC(tIn)); } //////////////////////////////////////////////////////////////////////////////////////////////////// -std::string toString(boost::posix_time::ptime const& tIn) { - return boost::posix_time::to_iso_extended_string(tIn).substr(0, 23) + "Z"; +std::string toString(std::chrono::utc_clock::time_point const& tIn) { + using namespace std::chrono_literals; + + // This method is mainly used by creating a JavaScript date object, which doesn't support leap + // seconds. The formatter below does support them and would generate a 60 in the seconds field, + // which would not work with JavaScript's date parsing. We handle this here by subtracting a + // second during a leap second and displaying 59 seconds, instead of 60 seconds. + bool isLeapSecond = std::chrono::get_leap_second_info(tIn).is_leap_second; + + auto time = + std::chrono::time_point_cast(tIn - (isLeapSecond ? 1s : 0s)); + + // Format the time point as ISO 8601 string with milliseconds precision + // and append 'Z' to indicate UTC time zone + return std::format("{:%Y-%m-%dT%H:%M:%S}Z", time); } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cs-utils/convert.hpp b/src/cs-utils/convert.hpp index 17337b919..31c7e3cae 100644 --- a/src/cs-utils/convert.hpp +++ b/src/cs-utils/convert.hpp @@ -10,11 +10,10 @@ #include "cs_utils_export.hpp" -#include -#include +#include +#include #include -#include /// This namespace contains utility functions for converting numbers between different units of /// measuring. Most of the coordinate system conversion methods are based on the code from the @@ -48,12 +47,12 @@ T metersToAstronomicalUnits(T meters) { template T toRadians(T degrees) { - return static_cast(degrees * glm::pi() / 180.0); + return static_cast(degrees * std::numbers::pi / 180.0); } template T toDegrees(T radians) { - return static_cast(radians * 180.0 / glm::pi()); + return static_cast(radians * 180.0 / std::numbers::pi); } /// Projects an arbitrary cartesian point to the surface of an origin-centered ellipsoid with the @@ -105,16 +104,16 @@ CS_UTILS_EXPORT glm::dvec3 cartesianToNormal(glm::dvec3 const& cartesian, glm::d /// format is also directly convertible to JavaScript Dates, here however the 'Z' is required! /// Else the Date object will be in your local time zone. So it's a good practice to always append /// the 'Z'. -/// * boost::posix_time::ptime is used for conversions and is also always in UTC. +/// * std::chrono::utc_clock::time_point is used for conversions and is also always in UTC. /// * SPICE time is stored in doubles representing Barycentric Dynamical Time (TDB, seconds since /// 2000-01-01 12:00:00). Note that this is not the same as UTC seconds since 2000-01-01 12:00:00 /// because TDB considers leap seconds. The conversion methods below take this into account. namespace time { -/// Converts boost::posix_time::ptime to spice time, which is defined by the Barycentric Dynamical -/// Time. Be aware, that SPICE kernels with leap seconds have to be loaded for this method to work. -/// This means, SolarSystem::init() must have been called before. -CS_UTILS_EXPORT double toSpice(boost::posix_time::ptime const& tIn); +/// Converts std::chrono::utc_clock::time_point to spice time, which is defined by the Barycentric +/// Dynamical Time. Be aware, that SPICE kernels with leap seconds have to be loaded for this method +/// to work. This means, SolarSystem::init() must have been called before. +CS_UTILS_EXPORT double toSpice(std::chrono::utc_clock::time_point const& tIn); /// Converts a time string to spice time, which is defined by the Barycentric Dynamical Time. The /// string can be in the format YYYY-MM-DD HH:MM:SS.fff, YYYY-MM-DDTHH:MM:SS.fff, or @@ -123,24 +122,29 @@ CS_UTILS_EXPORT double toSpice(boost::posix_time::ptime const& tIn); /// have been called before. CS_UTILS_EXPORT double toSpice(std::string const& tIn); -/// Converts a time string to boost::posix_time time. The string can be in the format -/// YYYY-MM-DD HH:MM:SS.fff, YYYY-MM-DDTHH:MM:SS.fff, or YYYY-MM-DDTHH:MM:SS.fffZ and is always -/// interpreted as UTC. -CS_UTILS_EXPORT boost::posix_time::ptime toPosix(std::string const& tIn); +/// Converts a time string to std::chrono::utc_clock::time_point time. The string can be in the +/// format YYYY-MM-DD HH:MM:SS.fff, YYYY-MM-DDTHH:MM:SS.fff, or YYYY-MM-DDTHH:MM:SS.fffZ and is +/// always interpreted as UTC. +CS_UTILS_EXPORT std::chrono::utc_clock::time_point toUTC(std::string const& tIn); -/// Converts a Barycentric Dynamical Time to boost::posix_time::ptime. Be aware, that SPICE kernels -/// with leap seconds have to be loaded for this method to work. This means, SolarSystem::init() -/// must have been called before. -CS_UTILS_EXPORT boost::posix_time::ptime toPosix(double tIn); +/// Converts a Barycentric Dynamical Time to std::chrono::utc_clock::time_point. Be aware, that +/// SPICE kernels with leap seconds have to be loaded for this method to work. This means, +/// SolarSystem::init() must have been called before. +CS_UTILS_EXPORT std::chrono::utc_clock::time_point toUTC(double tIn); -/// Converts a Barycentric Dynamical Time time to a time string in the format +/// This is a helper function to more easily create a UTC time point from year/month/day and +/// optionally the time of day. +CS_UTILS_EXPORT std::chrono::utc_clock::time_point toUTC(std::chrono::year_month_day const& ymd, + std::chrono::utc_clock::duration const& hms = std::chrono::utc_clock::duration::zero()); + +/// Converts Barycentric Dynamical Time to a time string in the format /// YYYY-MM-DDTHH:MM:SS.fffZ. Be aware, that SPICE kernels with leap seconds have to be loaded for /// this method to work. This means, SolarSystem::init() must have been called before. CS_UTILS_EXPORT std::string toString(double tIn); -/// Converts a boost::posix_time::ptime time to a time string in the format +/// Converts a std::chrono::utc_clock::time_point time to a time string in the format /// YYYY-MM-DDTHH:MM:SS.fffZ. -CS_UTILS_EXPORT std::string toString(boost::posix_time::ptime const& tIn); +CS_UTILS_EXPORT std::string toString(std::chrono::utc_clock::time_point const& tIn); } // namespace time diff --git a/src/cs-utils/filesystem.cpp b/src/cs-utils/filesystem.cpp index b095410d8..f847ca6ef 100644 --- a/src/cs-utils/filesystem.cpp +++ b/src/cs-utils/filesystem.cpp @@ -10,27 +10,23 @@ #include "utils.hpp" #include -#include -#include #include -#include #include -#include namespace cs::utils::filesystem { //////////////////////////////////////////////////////////////////////////////////////////////////// void createDirectoryRecursively( - boost::filesystem::path const& path, boost::filesystem::perms permissions) { + std::filesystem::path const& path, std::filesystem::perms permissions) { - if (!boost::filesystem::exists(path.parent_path())) { + if (!std::filesystem::exists(path.parent_path())) { createDirectoryRecursively(path.parent_path(), permissions); } - boost::filesystem::create_directory(path); - boost::filesystem::permissions(path, permissions); + std::filesystem::create_directory(path); + std::filesystem::permissions(path, permissions); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -38,11 +34,11 @@ void createDirectoryRecursively( std::set listFiles(std::string const& directory, std::regex const& regex) { std::set result; - for (auto& p : boost::filesystem::directory_iterator(directory)) { - auto path = p.path().generic_path(); + for (auto& p : std::filesystem::directory_iterator(directory)) { - if (std::regex_match(path.string(), regex) && boost::filesystem::is_regular_file(path)) { - result.insert(path.string()); + if (auto const& path = p.path(); + std::regex_match(path.string(), regex) && std::filesystem::is_regular_file(path)) { + result.insert(path.generic_string()); } } @@ -54,10 +50,10 @@ std::set listFiles(std::string const& directory, std::regex const& std::set listDirs(std::string const& directory, std::regex const& regex) { std::set result; - for (auto& p : boost::filesystem::directory_iterator(directory)) { - auto path = p.path().generic_path(); - if (std::regex_match(path.string(), regex) && boost::filesystem::is_directory(path)) { - result.insert(path.string()); + for (auto& p : std::filesystem::directory_iterator(directory)) { + if (auto const& path = p.path(); + std::regex_match(path.string(), regex) && std::filesystem::is_directory(path)) { + result.insert(path.generic_string()); } } @@ -91,7 +87,7 @@ void writeStringToFile(std::string const& filePath, std::string const& content) void downloadFile(std::string const& url, std::string const& destination, std::function const& progressCallback) { - createDirectoryRecursively(boost::filesystem::path(destination).parent_path()); + createDirectoryRecursively(std::filesystem::path(destination).parent_path()); std::ofstream stream(destination, std::ofstream::out | std::ofstream::binary); if (!stream) { diff --git a/src/cs-utils/filesystem.hpp b/src/cs-utils/filesystem.hpp index ce7d2a29b..64f21aaf8 100644 --- a/src/cs-utils/filesystem.hpp +++ b/src/cs-utils/filesystem.hpp @@ -10,7 +10,7 @@ #include "cs_utils_export.hpp" -#include +#include #include #include #include @@ -19,10 +19,10 @@ namespace cs::utils::filesystem { /// Creates all required directories for @param path if they do not exist -CS_UTILS_EXPORT void createDirectoryRecursively(boost::filesystem::path const& path, - boost::filesystem::perms permissions = boost::filesystem::perms::owner_all | - boost::filesystem::perms::group_read | - boost::filesystem::perms::others_read); +CS_UTILS_EXPORT void createDirectoryRecursively(std::filesystem::path const& path, + std::filesystem::perms permissions = std::filesystem::perms::owner_all | + std::filesystem::perms::group_read | + std::filesystem::perms::others_read); /// Lists all files in the given directory. The returned paths are relative to the given directory, /// forward slashes are used as separators independent from the operating system.