diff --git a/.clang-tidy b/.clang-tidy index f8113f83..2a758f91 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -60,7 +60,7 @@ modernize-loop-convert, modernize-make-shared, modernize-make-unique, - modernize-redundant-void-arg, + modernize-redundant-void-arg, #SDL3 headers modernize-replace-random-shuffle, modernize-shrink-to-fit, modernize-use-bool-literals, @@ -69,7 +69,7 @@ modernize-use-equals-default, modernize-use-equals-delete, modernize-use-noexcept, - modernize-use-nullptr, + modernize-use-nullptr, #SDL3 headers modernize-use-override, modernize-use-transparent-functors, readability-redundant-member-init' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 85fc551f..741ea88a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -40,6 +40,7 @@ jobs: cmake -Bbuild -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=x64-windows-static-md + -DYML=YML build: cmake --build build --parallel "$env:NUMBER_OF_PROCESSORS" steps: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..a7aba777 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,208 @@ +name: Desktop builds + +on: + push: + branches: [main, 'port/**'] + tags: ['v*'] + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + formatting: + name: Check formatting + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 2 + - run: | + files=$(git diff --name-only --diff-filter=ACMRT HEAD^ -- \ + 'src/*.cpp' 'src/*.h' 'src/*.mm') + if [ -n "$files" ]; then + clang-format --dry-run --Werror -style=file $files + fi + + windows: + name: Windows x64 + runs-on: windows-2022 + steps: + - uses: actions/checkout@v4 + - uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + - name: Configure + shell: pwsh + run: | + cmake -B out/build/windows-release -G Ninja ` + -DCMAKE_BUILD_TYPE=Release ` + -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" ` + -DVCPKG_TARGET_TRIPLET=x64-windows-static-md + - name: Build + run: cmake --build out/build/windows-release --parallel + - name: Smoke test + run: out/build/windows-release/src/System/ArrowVortex.exe --smoke-test + - name: Install + run: cmake --install out/build/windows-release --prefix out/install/windows + - uses: actions/upload-artifact@v4 + with: + name: ArrowVortex-windows-x64 + path: out/install/windows + + linux: + name: Linux x86_64 + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - name: Install system build dependencies + run: | + sudo apt-get update + sudo apt-get install -y ninja-build pkg-config xvfb libgl1-mesa-dev \ + libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev \ + libxfixes-dev libxss-dev libwayland-dev libxkbcommon-dev \ + libasound2-dev libpulse-dev libdbus-1-dev libibus-1.0-dev \ + libdecor-0-dev libpipewire-0.3-dev nasm autoconf automake libtool + - name: Configure + run: | + cmake -B out/build/linux-release -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_TOOLCHAIN_FILE="$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" \ + -DVCPKG_TARGET_TRIPLET=x64-linux + - name: Build and test + run: | + cmake --build out/build/linux-release --parallel + SDL_AUDIODRIVER=dummy xvfb-run -a \ + out/build/linux-release/src/System/ArrowVortex --smoke-test + ctest --test-dir out/build/linux-release --output-on-failure + - name: Install and package + run: | + cmake --install out/build/linux-release --prefix out/install/linux + tools/package_linux.sh out/install/linux out/packages + - uses: actions/upload-artifact@v4 + with: + name: ArrowVortex-linux-x86_64 + path: | + out/packages/ArrowVortex-linux-x86_64.tar.gz + out/packages/ArrowVortex-linux-x86_64.tar.gz.sha256 + + macos: + name: macOS ${{ matrix.arch }} + strategy: + fail-fast: false + matrix: + include: + - arch: arm64 + runner: macos-15 + preset: macos-arm64-release + - arch: x86_64 + runner: macos-15-intel + preset: macos-x64-release + runs-on: ${{ matrix.runner }} + env: + VCPKG_ROOT: ${{ github.workspace }}/vcpkg + steps: + - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + with: + repository: microsoft/vcpkg + path: vcpkg + ref: a62ce77d56ee07513b4b67de1ec2daeaebfae51a + - name: Install macOS build tools + run: brew install nasm + - name: Bootstrap vcpkg + run: ./vcpkg/bootstrap-vcpkg.sh -disableMetrics + - name: Configure and build + run: | + cmake --preset ${{ matrix.preset }} + cmake --build --preset ${{ matrix.preset }} --parallel + - name: Smoke test + run: | + app=out/build/${{ matrix.preset }}/src/System/ArrowVortex.app + smoke_result="$RUNNER_TEMP/arrowvortex-smoke-${{ matrix.arch }}" + rm -f "$smoke_result" + open -W -n "$app" --args --smoke-test --smoke-result "$smoke_result" + grep -qx success "$smoke_result" + ctest --test-dir out/build/${{ matrix.preset }} --output-on-failure + - name: Validate architecture and bundle + run: | + app=out/build/${{ matrix.preset }}/src/System/ArrowVortex.app + lipo -archs "$app/Contents/MacOS/ArrowVortex" | grep -qw ${{ matrix.arch }} + plutil -lint "$app/Contents/Info.plist" + test -d "$app/Contents/Resources/assets" + test -d "$app/Contents/Resources/noteskins" + test -d "$app/Contents/Resources/settings" + ditto -c -k --keepParent "$app" "ArrowVortex-macOS-${{ matrix.arch }}.zip" + - uses: actions/upload-artifact@v4 + with: + name: ArrowVortex-macOS-${{ matrix.arch }} + path: ArrowVortex-macOS-${{ matrix.arch }}.zip + + universal-macos: + name: Universal 2 package + needs: [macos] + runs-on: macos-15 + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + pattern: ArrowVortex-macOS-* + path: out/architectures + - name: Assemble Universal 2 bundle + run: | + ditto -x -k out/architectures/ArrowVortex-macOS-arm64/ArrowVortex-macOS-arm64.zip out/arm64 + ditto -x -k out/architectures/ArrowVortex-macOS-x86_64/ArrowVortex-macOS-x86_64.zip out/x86_64 + tools/merge_macos_universal.sh out/arm64/ArrowVortex.app \ + out/x86_64/ArrowVortex.app out/ArrowVortex.app + ditto -c -k --keepParent out/ArrowVortex.app out/ArrowVortex-Universal2.zip + - name: Create ad-hoc-signed DMG + run: tools/package_macos.sh out/ArrowVortex.app out/packages + - uses: actions/upload-artifact@v4 + with: + name: ArrowVortex-macOS-Universal2 + path: | + out/packages/ArrowVortex-macOS-Universal2.dmg + out/packages/ArrowVortex-macOS-Universal2.dmg.sha256 + out/ArrowVortex-Universal2.zip + + signed-release: + name: Sign and notarize release + if: startsWith(github.ref, 'refs/tags/') + needs: [windows, linux, universal-macos] + runs-on: macos-15 + environment: release + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: ArrowVortex-macOS-Universal2 + path: out/download + - name: Import Developer ID certificate + env: + MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }} + MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} + run: | + test -n "$MACOS_CERTIFICATE" + keychain=build.keychain-db + security create-keychain -p temporary "$keychain" + security default-keychain -s "$keychain" + security unlock-keychain -p temporary "$keychain" + echo "$MACOS_CERTIFICATE" | base64 --decode > certificate.p12 + security import certificate.p12 -k "$keychain" -P "$MACOS_CERTIFICATE_PASSWORD" -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple: -s -k temporary "$keychain" + - name: Sign, notarize, and verify + env: + MACOS_SIGN_IDENTITY: ${{ secrets.MACOS_SIGN_IDENTITY }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} + run: | + ditto -x -k out/download/ArrowVortex-Universal2.zip out/app + tools/package_macos.sh out/app/ArrowVortex.app out/release + - name: Publish release assets + env: + GH_TOKEN: ${{ github.token }} + run: gh release upload "${GITHUB_REF_NAME}" out/release/* --clobber diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml deleted file mode 100644 index 2e34177b..00000000 --- a/.github/workflows/windows.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Build & Latest Beta - -on: - push: - pull_request: - paths-ignore: - - '**.md' - -env: - USERNAME: uvcat7 - FEED_URL: https://nuget.pkg.github.com/uvcat7/index.json - VCPKG_BINARY_SOURCES: "clear;nuget,https://nuget.pkg.github.com/uvcat7/index.json,readwrite" - -jobs: - formatting: - name: "Check formatting" - runs-on: windows-2022 - permissions: - contents: read - steps: - - name: Get AV - uses: actions/checkout@v7 - - name: Check formatting with clang-format - run: > - clang-format --dry-run --Werror -style=file $(find src/ -type f \( -name '*.cpp' -o -name '*.h' -o -name '*.c' -o -name '*.hpp' \)) - shell: bash - windows: - name: "Build Windows x64" - runs-on: windows-2022 - permissions: - contents: read - steps: - - name: Get AV - uses: actions/checkout@v7 - - name: Add NuGet sources - shell: pwsh - run: | - .$(vcpkg fetch nuget) ` - sources add ` - -Source "${{ env.FEED_URL }}" ` - -StorePasswordInClearText ` - -Name GitHubPackages ` - -UserName "${{ env.USERNAME }}" ` - -Password "${{ secrets.GH_PACKAGES_TOKEN }}" - .$(vcpkg fetch nuget) ` - setapikey "${{ secrets.GH_PACKAGES_TOKEN }}" ` - -Source "${{ env.FEED_URL }}" - - name: Configure CMake - run: > - cmake -Bbuild -DCMAKE_BUILD_TYPE=Release - -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT\scripts\buildsystems\vcpkg.cmake" - -DVCPKG_TARGET_TRIPLET=x64-windows-static-md - - name: Build AV - run: cmake --build build --config Release --parallel "$env:NUMBER_OF_PROCESSORS" - - name: Collect into a directory - if: github.ref_name == 'beta' - run: cmake --install build --config Release --prefix ./ - - name: Upload artifact - if: github.ref_name == 'beta' - uses: actions/upload-artifact@v7 - with: - name: ArrowVortex-${{ github.sha }} - path: | - bin/assets - bin/noteskins - bin/settings - bin/ArrowVortex.exe - bin/oggenc2.exe - if-no-files-found: error diff --git a/BUILDING.md b/BUILDING.md index 45bd82c0..e020a208 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -1,31 +1,72 @@ -# Building +# Building ArrowVortex -## Windows +ArrowVortex uses CMake 3.28+, Ninja, and the pinned vcpkg manifest in +`vcpkg.json`. Set `VCPKG_ROOT` to a vcpkg checkout before using a release +preset. -Prerequsites: -* Installation of Visual Studio Build Tools -* CMake (available with VS Build Tools) -* vcpkg (available with VS Build Tools) -* `VCPKG_ROOT` environment variable pointing at vcpkg installation folder +## macOS -### With CMake CLI -With Developer PowerShell open at root folder of this project run: -```pwsh -cmake -Bbuild -S. -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=x64-windows-static-md -cmake --build build +The supported deployment target is macOS 12.0. Release builds use static +vcpkg triplets so the app bundle does not depend on Homebrew or build-tree +paths. + +```sh +cmake --preset macos-arm64-release +cmake --build --preset macos-arm64-release --parallel +``` + +Use `macos-x64-release` on an Intel Mac. For local Apple Silicon development +with Homebrew dependencies, use `macos-local-debug`. The app is emitted under +`out/build//src/System/ArrowVortex.app`. + +The CI workflow builds both native architectures on matching GitHub-hosted +runners, merges Mach-O files with `lipo`, validates both slices, signs the app, +and creates a DMG. Tagged builds use Developer ID and notarization only when +the protected release environment provides the documented secrets. + +## Linux + +Install the SDL build prerequisites listed in `.github/workflows/release.yml`, +then run: + +```sh +cmake --preset linux-release +cmake --build --preset linux-release --parallel +ctest --test-dir out/build/linux-release --output-on-failure +cmake --install out/build/linux-release --prefix out/install/linux +tools/package_linux.sh out/install/linux out/packages ``` -Resulting binary will be located at `build/src/System/Debug/ArrowVortex.exe` -To install ArrowVortex to a folder run: +Ubuntu 22.04 is the release baseline. The supported Linux release artifact is +the x86_64 tarball produced by the packaging script. + +## Windows + +From Developer PowerShell with Ninja and vcpkg available: + ```pwsh -cmake --install build --prefix "" +cmake --preset windows-release +cmake --build --preset windows-release --parallel +ctest --test-dir out/build/windows-release --output-on-failure ``` -### With Visual Studio -1. Run `vcpkg integrate install` in Developer PowerShell. This will integrate vcpkg with your installation of Visual Studio and needs to be run once. -2. Open root folder of this project in Visual Studio +## Tests + +`--smoke-test [fixture]` initializes SDL video, OpenGL 2.1, audio, the editor, +and optional simfile input, renders 120 frames, and exits. CTest also performs +load-save-reload checks for SM, SSC, osu!, and DWI fixtures, including BPM +changes, repeated stops at BPM boundaries, warps, holds, and Unicode metadata. + +## Release secrets + +Store these only in GitHub's protected `release` environment: +- `MACOS_CERTIFICATE` (base64-encoded Developer ID Application PKCS#12) +- `MACOS_CERTIFICATE_PASSWORD` +- `MACOS_SIGN_IDENTITY` +- `APPLE_ID` +- `APPLE_TEAM_ID` +- `APPLE_APP_PASSWORD` (app-specific password) -## Troubleshooting -### CMake can't find freetype -CMake failed to integrate with vcpkg. Remove your build directory (either `build/` or `out/`) and follow instructions for your system. +Without them, CI still produces ad-hoc-signed Universal 2 artifacts. A tagged +notarized release is intentionally blocked until all signing values exist. diff --git a/CMakeLists.txt b/CMakeLists.txt index db3f3996..936975a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,34 +1,67 @@ -cmake_minimum_required(VERSION 3.30) +cmake_minimum_required(VERSION 3.28) -set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +project(ArrowVortex VERSION 1.1.0 LANGUAGES C CXX) + +include(CTest) +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED True) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) -project(ArrowVortex) +if(APPLE) + enable_language(OBJCXX) + set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0" CACHE STRING "Minimum macOS version") +endif() -set(CMAKE_CONFIGURATION_TYPES Debug;Release;MinSizeRel) -if("${CMAKE_BUILD_TYPE}" STREQUAL "MinSizeRel") - set(tidy_flags "--fix-errors;--fix-notes") - set(format_flags "-i") -else() - set(tidy_flags "--warnings-as-errors=*") - set(format_flags "--dry-run") +option(ARROWVORTEX_ENABLE_TIDY "Run clang-tidy while compiling" OFF) +if(ARROWVORTEX_ENABLE_TIDY) + find_program(CLANG_TIDY_EXECUTABLE clang-tidy REQUIRED) + set(CMAKE_CXX_CLANG_TIDY + "${CLANG_TIDY_EXECUTABLE};--warnings-as-errors=*;--exclude-header-filter=SDL3*" + ) endif() -set(CMAKE_CXX_CLANG_TIDY "clang-tidy;${tidy_flags};-extra-arg=/EHsc;-p=build") include_directories("${PROJECT_SOURCE_DIR}/src") -find_package(aubio CONFIG REQUIRED) -find_package(FFMPEG REQUIRED) +find_package(PkgConfig QUIET) + +find_package(Aubio CONFIG QUIET NAMES aubio Aubio) +if(NOT TARGET Aubio::aubio) + if(NOT PkgConfig_FOUND) + message(FATAL_ERROR "aubio was not found and pkg-config is unavailable") + endif() + pkg_check_modules(AUBIO REQUIRED IMPORTED_TARGET aubio) + add_library(Aubio::aubio ALIAS PkgConfig::AUBIO) +endif() + +find_package(FFMPEG QUIET) +if(NOT FFMPEG_FOUND) + if(NOT PkgConfig_FOUND) + message(FATAL_ERROR "FFmpeg was not found and pkg-config is unavailable") + endif() + pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET + libavcodec libavformat libavutil libswresample libswscale) + set(FFMPEG_LIBRARIES PkgConfig::FFMPEG) +endif() + find_package(Freetype REQUIRED) find_package(iir CONFIG REQUIRED) find_package(MAD REQUIRED) find_package(Ogg CONFIG REQUIRED) find_package(OpenGL REQUIRED) find_package(SDL3 CONFIG REQUIRED) -find_package(Stb REQUIRED) -find_package(Vorbis REQUIRED) + +# System.h exposes SDL types and is included throughout the internal libraries. +# Propagate SDL's include path and link requirement consistently to every target. +link_libraries(SDL3::SDL3) + +find_package(Stb CONFIG QUIET) +if(NOT Stb_FOUND AND NOT Stb_INCLUDE_DIR) + find_path(Stb_INCLUDE_DIR NAMES stb_image.h REQUIRED) +endif() + +find_package(Vorbis REQUIRED COMPONENTS vorbis vorbisfile) add_subdirectory(src/Core) add_subdirectory(src/Dialogs) @@ -37,17 +70,54 @@ add_subdirectory(src/Managers) add_subdirectory(src/Simfile) add_subdirectory(src/System) -install(TARGETS ArrowVortex RUNTIME) -install(DIRECTORY bin/assets DESTINATION bin) -install(DIRECTORY bin/noteskins DESTINATION bin) -install(DIRECTORY bin/settings DESTINATION bin) - -file(GLOB_RECURSE path_sources "src/*.cpp" "src/*.hpp" "src/*.c" "src/*.h") -add_custom_target(format ALL) -add_custom_command( - TARGET format - POST_BUILD - COMMAND clang-format ${format_flags} -Werror -style=file ${path_sources} - USES_TERMINAL -) -add_dependencies(format ArrowVortex) +if(BUILD_TESTING) + add_executable(ArrowVortexSimfileRoundTrip tests/SimfileRoundTrip.cpp) + if(UNIX AND NOT APPLE) + # The application libraries intentionally retain upstream's circular + # references. GNU ld needs an explicit rescan group when the headless + # test executable links those static archives directly. + target_link_libraries(ArrowVortexSimfileRoundTrip PRIVATE + "$" + ) + else() + target_link_libraries(ArrowVortexSimfileRoundTrip PRIVATE Simfile System) + endif() + if(APPLE) + target_link_libraries(ArrowVortexSimfileRoundTrip PRIVATE + "-framework Cocoa") + endif() + + foreach(format sm ssc osu dwi) + add_test( + NAME simfile-roundtrip-${format} + COMMAND $ + "${PROJECT_SOURCE_DIR}/tests/fixtures/roundtrip.${format}" + ) + set_tests_properties(simfile-roundtrip-${format} PROPERTIES + TIMEOUT 30 + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/bin" + ) + endforeach() +endif() + +if(APPLE) + install(TARGETS ArrowVortex BUNDLE DESTINATION .) +else() + install(TARGETS ArrowVortex RUNTIME DESTINATION bin) + install(DIRECTORY bin/assets DESTINATION bin) + install(DIRECTORY bin/noteskins DESTINATION bin) + install(DIRECTORY bin/settings DESTINATION bin) + install(FILES LICENSE CREDITS DESTINATION .) +endif() + +file(GLOB_RECURSE path_sources CONFIGURE_DEPENDS + "src/*.cpp" "src/*.mm" "src/*.hpp" "src/*.c" "src/*.h") +if(WIN32) + add_custom_target(format ALL) + add_custom_command( + TARGET format POST_BUILD + COMMAND clang-format --dry-run -Werror -style=file ${path_sources} + USES_TERMINAL + ) + add_dependencies(format ArrowVortex) +endif() diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 00000000..b5cdd2ba --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,121 @@ +{ + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 28 + }, + "configurePresets": [ + { + "name": "windows-debug", + "displayName": "Windows x64 Debug", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", + "VCPKG_TARGET_TRIPLET": "x64-windows-static-md" + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "windows-release", + "displayName": "Windows x64 Release", + "inherits": "windows-debug", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "linux-debug", + "displayName": "Linux x64 Debug", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", + "VCPKG_TARGET_TRIPLET": "x64-linux" + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Linux" + } + }, + { + "name": "linux-release", + "displayName": "Linux x64 Release", + "inherits": "linux-debug", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "macos-local-debug", + "displayName": "macOS Local Debug (system packages)", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_OSX_ARCHITECTURES": "arm64", + "CMAKE_OSX_DEPLOYMENT_TARGET": "12.0", + "CMAKE_PREFIX_PATH": "/opt/homebrew" + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + } + }, + { + "name": "macos-arm64-release", + "displayName": "macOS Apple Silicon Release", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_OSX_ARCHITECTURES": "arm64", + "CMAKE_OSX_DEPLOYMENT_TARGET": "12.0", + "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", + "VCPKG_TARGET_TRIPLET": "arm64-osx-static", + "VCPKG_OVERLAY_TRIPLETS": "${sourceDir}/cmake/triplets" + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + } + }, + { + "name": "macos-x64-release", + "displayName": "macOS Intel Release", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_OSX_ARCHITECTURES": "x86_64", + "CMAKE_OSX_DEPLOYMENT_TARGET": "12.0", + "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", + "VCPKG_TARGET_TRIPLET": "x64-osx-static", + "VCPKG_OVERLAY_TRIPLETS": "${sourceDir}/cmake/triplets" + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + } + } + ], + "buildPresets": [ + {"name": "windows-debug", "configurePreset": "windows-debug"}, + {"name": "windows-release", "configurePreset": "windows-release"}, + {"name": "linux-debug", "configurePreset": "linux-debug"}, + {"name": "linux-release", "configurePreset": "linux-release"}, + {"name": "macos-local-debug", "configurePreset": "macos-local-debug"}, + {"name": "macos-arm64-release", "configurePreset": "macos-arm64-release"}, + {"name": "macos-x64-release", "configurePreset": "macos-x64-release"} + ] +} diff --git a/CMakeSettings.json b/CMakeSettings.json deleted file mode 100644 index 4578bda1..00000000 --- a/CMakeSettings.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "configurations": [ - { - "name": "Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\out\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "-DVCPKG_TARGET_TRIPLET=x64-windows-static-md", - "buildCommandArgs": "", - "ctestCommandArgs": "" - }, - { - "name": "Release", - "generator": "Ninja", - "configurationType": "RelWithDebInfo", - "buildRoot": "${projectDir}\\out\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "-DVCPKG_TARGET_TRIPLET=x64-windows-static-md", - "buildCommandArgs": "", - "ctestCommandArgs": "", - "inheritEnvironments": [ "msvc_x64_x64" ] - }, - { - "name": "Reformat", - "generator": "Ninja", - "configurationType": "MinSizeRel", - "buildRoot": "${projectDir}\\out\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "-DVCPKG_TARGET_TRIPLET=x64-windows-static-md", - "buildCommandArgs": "", - "ctestCommandArgs": "", - "inheritEnvironments": [ "msvc_x64_x64" ], - "intelliSenseMode": "windows-clang-x64" - } - ] -} \ No newline at end of file diff --git a/README.md b/README.md index 1f2c6d14..2a198a7c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # ArrowVortex -ArrowVortex is a simfile editor for Windows. It can be used to create or edit stepfiles for various rhythm games, such as StepMania, ITG, osu!, and other games which support DDR-style and/or PIU-style panel layouts. +ArrowVortex is a cross-platform simfile editor for macOS, Linux, and Windows. It +can create or edit stepfiles for StepMania, ITG, osu!, and other games which +support DDR-style and/or PIU-style panel layouts. This is a continuation of the original project by Bram 'Fietsemaker' van de Wetering. He has graciously allowed for the open sourcing of this code so that development can continue. @@ -61,25 +63,17 @@ Game styles: - Pump Double - Pump Couple -# About this project - -## Support and Contributing to the project - -When you have questions about ArrowVortex and its functionality, make a discussion topic! - -If you would like to report bugs or suggest simple features to add, please use the issue templates to do so. Make sure an issue for your problem doesn't exist before you create a new one. -When the changes you would like to add are of a larger scope (e.g. adding a new subsystem to the editor or redesigning a popup window), make a discussion instead. - -Pull requests to add features and fix bugs are always welcomed. Please reach out to @uvcat7 with any questions. After a contribution, @uvcat7 will add you to the repository as a collaborator. +# Platforms -## Support and Contributing to the project +- macOS 12.0 or later on Apple Silicon and Intel (Universal 2 DMG) +- Linux x86_64 (portable tarball built on Ubuntu 22.04) +- Windows x64 -When you have questions about ArrowVortex and its functionality, make a discussion topic! +The desktop ports use SDL3 for lifecycle, windowing, input, dialogs, clipboard, +URLs, drag-and-drop, and audio while retaining ArrowVortex's OpenGL renderer and +simfile data model. -If you would like to report bugs or suggest simple features to add, please use the issue templates to do so. Make sure an issue for your problem doesn't exist before you create a new one. -When the changes you would like to add are of a larger scope (e.g. adding a new subsystem to the editor or redesigning a popup window), make a discussion instead. - -Pull requests to add features and fix bugs are always welcomed. Please reach out to @uvcat7 with any questions. After a contribution, @uvcat7 will add you to the repository as a collaborator. +# About this project ## Support and Contributing to the project @@ -92,9 +86,9 @@ Pull requests to add features and fix bugs are always welcomed. Please reach out ## Building ArrowVortex -The project uses CMake for building and vcpkg for package management. Currently Visual Studio is recommended for building the solution, since the project is Windows-only. The Visual Studio Build Tools are required. - -See the [build details](BUILDING.md) for more information. +The project uses CMake presets and a pinned vcpkg manifest. See the +[build details](BUILDING.md) for native instructions, tests, package validation, +and release-signing configuration. ## License diff --git a/arrowvortex.desktop b/arrowvortex.desktop new file mode 100755 index 00000000..d43fcde7 --- /dev/null +++ b/arrowvortex.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=ArrowVortex +Comment=Stepmania .sm/.ssc simfile editor +Exec=arrowvortex +Icon=arrowvortex +Terminal=false +Type=Application +Categories=Game; diff --git a/bin/settings/shortcuts.txt b/bin/settings/shortcuts.txt index 9c756ae9..bbd6d545 100644 --- a/bin/settings/shortcuts.txt +++ b/bin/settings/shortcuts.txt @@ -1,6 +1,6 @@ FILE_OPEN = ctrl + o FILE_SAVE = ctrl + s -FILE_SAVE_AS = +FILE_SAVE_AS = FILE_CLOSE = OPEN_DIALOG_SONG_PROPERTIES = shift + p @@ -201,4 +201,4 @@ PREVIEW_VIEW_VARIABLE = SHOW_SHORTCUTS = F1 SHOW_MESSAGE_LOG = F2 SHOW_DEBUG_LOG = -SHOW_ABOUT = \ No newline at end of file +SHOW_ABOUT = diff --git a/cmake/Info.plist.in b/cmake/Info.plist.in new file mode 100644 index 00000000..39609b34 --- /dev/null +++ b/cmake/Info.plist.in @@ -0,0 +1,50 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ArrowVortex + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleIconFile + ArrowVortex + CFBundleIdentifier + org.arrowvortex.ArrowVortex + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ArrowVortex + CFBundlePackageType + APPL + CFBundleShortVersionString + @PROJECT_VERSION@ + CFBundleVersion + @PROJECT_VERSION@ + NSHumanReadableCopyright + Copyright ArrowVortex contributors. GPL-3.0-or-later. + LSMinimumSystemVersion + 12.0 + NSHighResolutionCapable + + CFBundleDocumentTypes + + + CFBundleTypeName + Rhythm Game Simfile + CFBundleTypeRole + Editor + LSHandlerRank + Owner + CFBundleTypeExtensions + + sm + ssc + osu + dwi + + + + + diff --git a/cmake/triplets/arm64-osx-static.cmake b/cmake/triplets/arm64-osx-static.cmake new file mode 100644 index 00000000..ffe44b7c --- /dev/null +++ b/cmake/triplets/arm64-osx-static.cmake @@ -0,0 +1,5 @@ +set(VCPKG_TARGET_ARCHITECTURE arm64) +set(VCPKG_CRT_LINKAGE dynamic) +set(VCPKG_LIBRARY_LINKAGE static) +set(VCPKG_CMAKE_SYSTEM_NAME Darwin) +set(VCPKG_OSX_DEPLOYMENT_TARGET 12.0) diff --git a/cmake/triplets/x64-osx-static.cmake b/cmake/triplets/x64-osx-static.cmake new file mode 100644 index 00000000..09c8f044 --- /dev/null +++ b/cmake/triplets/x64-osx-static.cmake @@ -0,0 +1,5 @@ +set(VCPKG_TARGET_ARCHITECTURE x64) +set(VCPKG_CRT_LINKAGE dynamic) +set(VCPKG_LIBRARY_LINKAGE static) +set(VCPKG_CMAKE_SYSTEM_NAME Darwin) +set(VCPKG_OSX_DEPLOYMENT_TARGET 12.0) diff --git a/docs/linux-launch.txt b/docs/linux-launch.txt new file mode 100644 index 00000000..f8b87609 --- /dev/null +++ b/docs/linux-launch.txt @@ -0,0 +1,9 @@ +ArrowVortex for Linux x86_64 + +Run ./ArrowVortex from this directory. The assets, noteskins, and default +settings directories must remain alongside the executable. To install the +desktop launcher, adjust Exec and Icon in ArrowVortex.desktop to absolute paths +and copy it to ~/.local/share/applications/. + +ArrowVortex is GPL-3.0-or-later software. Source and dependency notices are +available from https://github.com/douglasjv/ArrowVortex. diff --git a/src/Core/AlignedMemory.h b/src/Core/AlignedMemory.h index 884e37c3..9de19d52 100644 --- a/src/Core/AlignedMemory.h +++ b/src/Core/AlignedMemory.h @@ -1,13 +1,14 @@ #pragma once +#include template inline T* AlignedMalloc(size_t count) { - return static_cast(_aligned_malloc(count * sizeof(T), 16)); + return static_cast(SDL_aligned_alloc(16, count * sizeof(T))); } inline void AlignedFree(void* ptr) { if (ptr) { - _aligned_free(ptr); + SDL_aligned_free(ptr); ptr = nullptr; } } diff --git a/src/Core/ByteStream.cpp b/src/Core/ByteStream.cpp index 81b476b6..4cbb5901 100644 --- a/src/Core/ByteStream.cpp +++ b/src/Core/ByteStream.cpp @@ -36,7 +36,7 @@ void WriteStream::write(const void* in, int bytes) { memcpy(buffer_ + current_size_, in, bytes); current_size_ = newSize; } else if (!is_external_buffer_) { - capacity_ = max(capacity_ << 1, newSize); + capacity_ = std::max(capacity_ << 1, newSize); buffer_ = static_cast(realloc(buffer_, capacity_)); memcpy(buffer_ + current_size_, in, bytes); current_size_ = newSize; diff --git a/src/Core/ByteStream.h b/src/Core/ByteStream.h index dbf931da..5f998006 100644 --- a/src/Core/ByteStream.h +++ b/src/Core/ByteStream.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include namespace Vortex { @@ -11,46 +11,25 @@ struct WriteStream { WriteStream(void* out, int bytes); ~WriteStream(); - void write(const void* in, int bytes); - - void write8(const void* val); - void write16(const void* val); - void write32(const void* val); - void write64(const void* val); - void writeNum(uint32_t num); void writeStr(const std::string& str); - template - inline void writeSz(const void* val) { - write(val, S); - } - - template <> - inline void writeSz<1>(const void* val) { - write8(val); - } - - template <> - inline void writeSz<2>(const void* val) { - write16(val); - } - - template <> - inline void writeSz<4>(const void* val) { - write32(val); - } - - template <> - inline void writeSz<8>(const void* val) { - write64(val); - } - template inline void write(const T& val) { writeSz(&val); } + template + inline void writeSz(const void* val) { + write(val, S); + } + + void write(const void* in, int bytes); + void write8(const void* val); + void write16(const void* val); + void write32(const void* val); + void write64(const void* val); + // Returns true if all write operations have succeeded. bool success() const { return is_write_successful_; } @@ -91,26 +70,6 @@ struct ReadStream { read(out, S); } - template <> - inline void readSz<1>(void* out) { - read8(out); - } - - template <> - inline void readSz<2>(void* out) { - read16(out); - } - - template <> - inline void readSz<4>(void* out) { - read32(out); - } - - template <> - inline void readSz<8>(void* out) { - read64(out); - } - template inline void read(T& out) { readSz(&out); diff --git a/src/Core/CMakeLists.txt b/src/Core/CMakeLists.txt index 8bb8914a..f23b363d 100644 --- a/src/Core/CMakeLists.txt +++ b/src/Core/CMakeLists.txt @@ -27,7 +27,6 @@ list(APPEND INC "Texture.h" "TextureImpl.h" "Utils.h" - "Vector.h" "VectorUtils.h" "WideString.h" "Widgets.h" diff --git a/src/Core/Canvas.cpp b/src/Core/Canvas.cpp index 42720612..96448065 100644 --- a/src/Core/Canvas.cpp +++ b/src/Core/Canvas.cpp @@ -3,6 +3,7 @@ #include #include +#include namespace Vortex { @@ -82,7 +83,7 @@ struct GetCircleDist : public DistanceFunc { float Get(float px, float py) const override { float dx = px - x, dy = py - y; - return sqrt(dx * dx + dy * dy) - r; + return std::sqrt(dx * dx + dy * dy) - r; } }; @@ -94,15 +95,15 @@ struct GetRoundRectDist : public DistanceFunc { : x1(x1), y1(y1), x2(x2), y2(y2), r(r) {} float Get(float px, float py) const override { - float x = min(max(px, x1 + r), x2 - r); - float y = min(max(py, y1 + r), y2 - r); + float x = std::clamp(px, x1 + r, x2 - r); + float y = std::clamp(py, y1 + r, y2 - r); if (x == px && y == py) { - float dx = min(x - x1, x2 - x); - float dy = min(y - y1, y2 - y); - return -min(dx, dy); + float dx = std::min(x - x1, x2 - x); + float dy = std::min(y - y1, y2 - y); + return -std::min(dx, dy); } else { float dx = px - x, dy = py - y; - return sqrt(dx * dx + dy * dy) - r; + return std::sqrt(dx * dx + dy * dy) - r; } } }; @@ -128,7 +129,7 @@ struct GetPolyDist : public DistanceFunc { float d = 1e10; for (int i = 0, j = count - 1; i < count; j = i, ++i) { GetLineDist ld(x[i], y[i], x[j], y[j], 0); - d = min(d, ld.Get(px, py)); + d = std::min(d, ld.Get(px, py)); } return InsidePoly(px, py) ? -d : d; } @@ -163,13 +164,13 @@ void Canvas::Data::draw(float* buf, int w, int h, const areaf& area, if (blendMode == Canvas::BM_ALPHA) blendfunc = BlendAlpha; if (blendMode == Canvas::BM_ADD) blendfunc = BlendAdd; - int x1 = max(mask.l, static_cast(area.l - outerGlow - 1 + 0.5f)); - int y1 = max(mask.t, static_cast(area.t - outerGlow - 1 + 0.5f)); - int x2 = min(mask.r, static_cast(area.r + outerGlow + 1 + 0.5f)); - int y2 = min(mask.b, static_cast(area.b + outerGlow + 1 + 0.5f)); + int x1 = std::max(mask.l, static_cast(area.l - outerGlow - 1 + 0.5f)); + int y1 = std::max(mask.t, static_cast(area.t - outerGlow - 1 + 0.5f)); + int x2 = std::min(mask.r, static_cast(area.r + outerGlow + 1 + 0.5f)); + int y2 = std::min(mask.b, static_cast(area.b + outerGlow + 1 + 0.5f)); - float rh = 1.f / max(1, y2 - y1); - float rw = 1.f / max(1, x2 - x1); + float rh = 1.f / std::max(1, y2 - y1); + float rw = 1.f / std::max(1, x2 - x1); float ig = 1.f / (innerGlow + 1); float og = 1.f / (outerGlow + 1); @@ -189,10 +190,10 @@ void Canvas::Data::draw(float* buf, int w, int h, const areaf& area, BlendLinear(src, r, xf * rw); if (outline && dist < -0.5f) { float a = 1 - ig * ((-dist - lineWidth) + 0.5f); - if (a > 0) blendfunc(*dst, src, min(a, 1.f)); + if (a > 0) blendfunc(*dst, src, std::min(a, 1.f)); } else { float a = 1 - og * (dist + 0.5f); - if (a > 0) blendfunc(*dst, src, min(a, 1.f)); + if (a > 0) blendfunc(*dst, src, std::min(a, 1.f)); } } } @@ -233,8 +234,8 @@ Canvas::Canvas(const Canvas& other) } void Canvas::setMask(int l, int t, int r, int b) { - data_->mask = {max(0, l), max(0, t), min(r, canvas_width_), - min(r, canvas_height_)}; + data_->mask = {std::max(0, l), std::max(0, t), std::min(r, canvas_width_), + std::min(r, canvas_height_)}; } void Canvas::setOutline(float size) { data_->lineWidth = size; } @@ -280,8 +281,8 @@ void Canvas::clear(float l) { void Canvas::line(float x1, float y1, float x2, float y2, float width) { float r = width * 0.5f; - float xmin = min(x1, x2), xmax = max(x1, x2); - float ymin = min(y1, y2), ymax = max(y1, y2); + float xmin = std::min(x1, x2), xmax = std::max(x1, x2); + float ymin = std::min(y1, y2), ymax = std::max(y1, y2); GetLineDist func(x1, y1, x2, y2, r); data_->draw(canvas_data_, canvas_width_, canvas_height_, {xmin - r, ymin - r, xmax + r, ymax + r}, &func); @@ -294,9 +295,10 @@ void Canvas::circle(float x, float y, float r) { } void Canvas::box(float x1, float y1, float x2, float y2, float radius) { - float xl = min(x1, x2), xr = max(x1, x2); - float yt = min(y1, y2), yb = max(y1, y2); - float r = min(min(xr - xl, yb - yt) * 0.5f, max(0.f, radius)); + float xl = std::min(x1, x2), xr = std::max(x1, x2); + float yt = std::min(y1, y2), yb = std::max(y1, y2); + float r = + std::min(std::min(xr - xl, yb - yt) * 0.5f, std::max(0.f, radius)); GetRoundRectDist func(xl, yt, xr, yb, r); data_->draw(canvas_data_, canvas_width_, canvas_height_, {xl, yt, xr, yb}, &func); @@ -321,7 +323,7 @@ Texture Canvas::createTexture(bool mipmap) const { malloc(canvas_width_ * canvas_height_ * 4 * sizeof(uint8_t))); for (int i = 0; i < canvas_width_ * canvas_height_ * 4; ++i) { int v = static_cast(canvas_data_[i] * 255.f + 0.5f); - dst[i] = min(max(v, 0), 255); + dst[i] = std::clamp(v, 0, 255); } Texture result(canvas_width_, canvas_height_, dst, mipmap); free(dst); @@ -336,8 +338,8 @@ Canvas& Canvas::operator=(const Canvas& other) { if (other.canvas_data_) canvas_data_ = static_cast( malloc(canvas_width_ * canvas_height_ * 4 * sizeof(float))); - memcpy(canvas_data_, other.canvas_data_, - canvas_width_ * canvas_height_ * 4 * sizeof(float)); + std::memcpy(canvas_data_, other.canvas_data_, + canvas_width_ * canvas_height_ * 4 * sizeof(float)); return *this; } diff --git a/src/Core/Draw.cpp b/src/Core/Draw.cpp index 808aa12b..5f88147a 100644 --- a/src/Core/Draw.cpp +++ b/src/Core/Draw.cpp @@ -100,8 +100,8 @@ static void TB_setUvs(float* vt, float a, float b, float c, float d, float u, static void TB_setVerts(const TileBar& bar, int* vp, float* vt, recti r, areaf uvs, int flags) { if (flags & TileBar::VERTICAL) { - swapValues(r.x, r.y); - swapValues(r.w, r.h); + std::swap(r.x, r.y); + std::swap(r.w, r.h); } // Vertex positions: left-to-right [a,b,c,d] top-to-bottom [e,f]. @@ -118,24 +118,24 @@ static void TB_setVerts(const TileBar& bar, int* vp, float* vt, recti r, } // Texture coordinates: left-to-right [s,t,u,v] top-to-bottom [w,x]. - float rw = 1.0f / max(bar.texture.width(), 1); + float rw = 1.0f / std::max(bar.texture.width(), 1); float s = uvs.l, t = uvs.l + (b - a) * rw, u = uvs.r - (d - c) * rw, v = uvs.r; float w = uvs.t, x = uvs.b; if (flags & TileBar::FLIP_H) { - swapValues(s, v); - swapValues(t, u); + std::swap(s, v); + std::swap(t, u); } if (flags & TileBar::FLIP_V) { - swapValues(w, x); + std::swap(w, x); } // Fill in the texture coordinates. TB_setUvs(vt, s, t, u, v, w, x); } -TileBar::TileBar() : uvs({0, 0, 1, 1}), border(0) {} +TileBar::TileBar() : uvs({0, 0, 1, 1}) {} void TileBar::draw(recti rect, uint32_t color, int flags) const { int vp[24]; @@ -205,8 +205,8 @@ static void TR_setUvs(float* vt, float a, float b, float c, float d, float u, static void TR_setVerts(const TileRect& rect, int* vp, float* vt, recti r, areaf uvs, int flags) { if (flags & TileRect::VERTICAL) { - swapValues(r.x, r.y); - swapValues(r.w, r.h); + std::swap(r.x, r.y); + std::swap(r.w, r.h); } // Vertex positions: left-to-right [a,b,c,d] top-to-bottom [e,f,g,h]. @@ -225,27 +225,27 @@ static void TR_setVerts(const TileRect& rect, int* vp, float* vt, recti r, // Texture coordinates: left-to-right [s,t,u,v] top-to-bottom [w,x,y,z]. vec2i size = rect.texture.size(); - float rw = 1.f / max(size.x, 1); - float rh = 1.f / max(size.y, 1); + float rw = 1.f / std::max(size.x, 1); + float rh = 1.f / std::max(size.y, 1); float s = uvs.l, t = uvs.l + (b - a) * rw, u = uvs.r - (d - c) * rw, v = uvs.r; float w = uvs.t, x = uvs.t + (f - e) * rh, y = uvs.b - (h - g) * rh, z = uvs.b; if (flags & Draw::FLIP_H) { - swapValues(s, v); - swapValues(t, u); + std::swap(s, v); + std::swap(t, u); } if (flags & Draw::FLIP_V) { - swapValues(w, z); - swapValues(x, y); + std::swap(w, z); + std::swap(x, y); } // Fill in the texture coordinates. TR_setUvs(vt, s, t, u, v, w, x, y, z); } -TileRect::TileRect() : uvs({0, 0, 1, 1}), border(0) {} +TileRect::TileRect() : uvs({0, 0, 1, 1}) {} void TileRect::draw(recti rect, uint32_t color, int flags) const { int vp[72]; @@ -276,8 +276,8 @@ void TileRect::draw(QuadBatchTC* out, recti rect, uint32_t color, static void TR2_setVerts(const TileRect2& rect, int* vp, float* vt, recti r, int rounding, int flags) { if (flags & TileRect2::VERTICAL) { - swapValues(r.x, r.y); - swapValues(r.w, r.h); + std::swap(r.x, r.y); + std::swap(r.w, r.h); } // Vertex positions: left-to-right [a,b,c,d] top-to-bottom [e,f,g,h]. @@ -296,18 +296,18 @@ static void TR2_setVerts(const TileRect2& rect, int* vp, float* vt, recti r, // Texture coordinates: left-to-right [s,t,u,v] top-to-bottom [w,x,y,z]. vec2i size = rect.texture.size(); - float rw = 1.f / max(size.x, 1); - float rh = 1.f / max(size.y, 1); + float rw = 1.f / std::max(size.x, 1); + float rh = 1.f / std::max(size.y, 1); float s = 0, t = (b - a) * rw, u = 0.5f - (d - c) * rw, v = 0.5f; float w = 0, x = (f - e) * rh, y = 1.0f - (h - g) * rh, z = 1.0f; if (flags & TileRect2::FLIP_H) { - swapValues(s, v); - swapValues(t, u); + std::swap(s, v); + std::swap(t, u); } if (flags & TileRect2::FLIP_V) { - swapValues(w, z); - swapValues(x, y); + std::swap(w, z); + std::swap(x, y); } // Texture coordinate offsets. @@ -479,8 +479,8 @@ void Draw::sprite(const Texture& tex, recti r, uint32_t col, int flags) { vt[2] = vt[5] = vt[6] = vt[7] = 1; } else { float u = 0, v = 0, s = 1, w = 1; - if (flags & Draw::FLIP_H) swapValues(u, s); - if (flags & Draw::FLIP_V) swapValues(v, w); + if (flags & Draw::FLIP_H) std::swap(u, s); + if (flags & Draw::FLIP_V) std::swap(v, w); if (flags & Draw::ROT_90) { vt[2] = vt[0] = u; vt[3] = vt[7] = v; diff --git a/src/Core/Draw.h b/src/Core/Draw.h index 057cda39..6fac86eb 100644 --- a/src/Core/Draw.h +++ b/src/Core/Draw.h @@ -66,7 +66,7 @@ struct TileBar { Texture texture; areaf uvs; - int border; + int border = 0; }; // A 9-part texture with a middle section that stretches horizontally and @@ -83,7 +83,7 @@ struct TileRect { Texture texture; areaf uvs; - int border; + int border = 0; }; // A horizontal texture of two tile rects, 1st with round corners, 2nd with diff --git a/src/Core/FontData.cpp b/src/Core/FontData.cpp index 98511646..0694650e 100644 --- a/src/Core/FontData.cpp +++ b/src/Core/FontData.cpp @@ -199,7 +199,7 @@ static Glyph* PutGlyphInCache(GlyphCache* cache, FT_GlyphSlot slot) { uint8_t* pixels = CopyGlyphBitmap(bitmapW, bitmapH, bitmap); cache->tex->modify(glyph->box.x, glyph->box.y, bitmapW, bitmapH, pixels); - cache->shelfH = max(cache->shelfH, bitmapH); + cache->shelfH = std::max(cache->shelfH, bitmapH); free(pixels); // Set the glyph uvs. diff --git a/src/Core/FontManager.cpp b/src/Core/FontManager.cpp index c7e26139..b0c61173 100644 --- a/src/Core/FontManager.cpp +++ b/src/Core/FontManager.cpp @@ -225,7 +225,7 @@ void FontManager::startFrame(float dt) { } const Glyph& FontManager::getPlaceholderGlyph(int size) { - int i = max(0, min(size / 8, 7)); + int i = std::max(0, std::min(size / 8, 7)); return FM->placeholderGlyphs[i]; } diff --git a/src/Core/Gui.cpp b/src/Core/Gui.cpp index 6e986b96..ee8b91ea 100644 --- a/src/Core/Gui.cpp +++ b/src/Core/Gui.cpp @@ -15,6 +15,9 @@ #include #include +#include + +#include namespace Vortex { namespace { @@ -85,8 +88,8 @@ static void handleTooltip() { if (GUI->tooltipText.length() && GUI->tooltipTimer > 1.0f) { TextStyle style; - int alpha = clamp(static_cast(GUI->tooltipTimer * 1000 - 1000), - 0, 255); + int alpha = std::clamp( + static_cast(GUI->tooltipTimer * 1000 - 1000), 0, 255); style.textColor = Color32(0, alpha); style.shadowColor = Colors::blank; @@ -105,8 +108,8 @@ static void handleTooltip() { } } - pos.x = clamp(pos.x, 4, GUI->viewSize.x - textSize.x - 4); - pos.y = clamp(pos.y, 4, GUI->viewSize.y - textSize.y - 4); + pos.x = std::clamp(pos.x, 4, GUI->viewSize.x - textSize.x - 4); + pos.y = std::clamp(pos.y, 4, GUI->viewSize.y - textSize.y - 4); recti textBox = {pos.x, pos.y, textSize.x, textSize.y}; recti box = Expand(textBox, 3); diff --git a/src/Core/Gui.h b/src/Core/Gui.h index 1cfb202e..4b2c1608 100644 --- a/src/Core/Gui.h +++ b/src/Core/Gui.h @@ -2,6 +2,7 @@ #include #include +#include namespace Vortex { @@ -84,7 +85,7 @@ class GuiWidget : public InputHandler { virtual ~GuiWidget(); - GuiWidget(GuiContext* gui); + explicit GuiWidget(GuiContext* gui); // Captures mouse over for the current frame. void captureMouseOver(); @@ -147,7 +148,7 @@ class GuiWidget : public InputHandler { recti rect_; int width_; int height_; - uint32_t flags_; + uint32_t flags_ = WidgetFlags::WF_ENABLED; }; // Base class for dialog objects. @@ -155,7 +156,7 @@ class GuiDialog { public: virtual ~GuiDialog(); - GuiDialog(GuiContext* gui); + explicit GuiDialog(GuiContext* gui); virtual void onUpdateSize(); virtual void onArrange(recti r); diff --git a/src/Core/GuiContext.cpp b/src/Core/GuiContext.cpp index bab3b369..b6e962f1 100644 --- a/src/Core/GuiContext.cpp +++ b/src/Core/GuiContext.cpp @@ -4,6 +4,10 @@ #include #include +#include + +#include + namespace Vortex { GuiContext::~GuiContext() = default; @@ -28,8 +32,8 @@ InputEvents& GuiContextImpl::getEvents() { return *input_events_; } void GuiContextImpl::tick(recti view, float deltaTime, InputEvents& events) { view_rect_ = view; - view_rect_.w = max(view_rect_.w, 0); - view_rect_.h = max(view_rect_.h, 0); + view_rect_.w = std::max(view_rect_.w, 0); + view_rect_.h = std::max(view_rect_.h, 0); delta_time_ = deltaTime; input_events_ = &events; @@ -43,11 +47,11 @@ void GuiContextImpl::tick(recti view, float deltaTime, InputEvents& events) { FOR_VECTOR_REVERSE(dialogs_, i) { auto dialog = dialogs_[i]; if (dialog->request_close_) { - dialogs_.erase_values(dialog); + dialogs_.erase(dialogs_.begin() + i); delete dialog; } else if (dialog->request_move_to_top_) { - dialogs_.erase(i); - dialogs_.push_back(dialog); + dialogs_.erase(dialogs_.begin() + i); + dialogs_.emplace_back(dialog); dialog->request_move_to_top_ = false; } } @@ -84,29 +88,29 @@ void GuiContextImpl::closeDialogs() { FOR_VECTOR_REVERSE(dialogs_, i) { auto dialog = dialogs_[i]; if (dialog->request_close_) { - dialogs_.erase_values(dialog); + std::erase(dialogs_, dialog); delete dialog; } } } void GuiContextImpl::removeWidget(GuiWidget* w) { - focus_widgets_.erase_values(w); + std::erase(focus_widgets_, w); } -void GuiContextImpl::addDialog(DialogData* f) { dialogs_.push_back(f); } +void GuiContextImpl::addDialog(DialogData* f) { dialogs_.emplace_back(f); } -void GuiContextImpl::removeDialog(DialogData* f) { dialogs_.erase_values(f); } +void GuiContextImpl::removeDialog(DialogData* f) { std::erase(dialogs_, f); } void GuiContextImpl::grabFocus(GuiWidget* w) { for (GuiWidget* focus_widget : focus_widgets_) { if (focus_widget == w) return; } - focus_widgets_.push_back(w); + focus_widgets_.emplace_back(w); } void GuiContextImpl::releaseFocus(GuiWidget* w) { - focus_widgets_.erase_values(w); + std::erase(focus_widgets_, w); } // ================================================================================================ diff --git a/src/Core/GuiContext.h b/src/Core/GuiContext.h index f2142925..439ba3bf 100644 --- a/src/Core/GuiContext.h +++ b/src/Core/GuiContext.h @@ -6,6 +6,7 @@ #include #include +#include namespace Vortex { @@ -14,11 +15,11 @@ namespace Vortex { class GuiContextImpl : public GuiContext { public: - ~GuiContextImpl(); GuiContextImpl(); + ~GuiContextImpl() override; - void tick(recti view, float deltaTime, InputEvents& events); - void draw(); + void tick(recti view, float deltaTime, InputEvents& events) override; + void draw() override; void closeDialogs(); @@ -73,8 +74,8 @@ class GuiContextImpl : public GuiContext { float delta_time_; InputEvents* input_events_; - Vector dialogs_; - Vector focus_widgets_; + std::vector dialogs_; + std::vector focus_widgets_; }; }; // namespace Vortex diff --git a/src/Core/GuiDialog.cpp b/src/Core/GuiDialog.cpp index 846da54c..9744fe82 100644 --- a/src/Core/GuiDialog.cpp +++ b/src/Core/GuiDialog.cpp @@ -8,8 +8,6 @@ namespace Vortex { -#define MY_GUI ((GuiContextImpl*)gui_) - static const int FRAME_TITLEBAR_H = 24; #define FRAME_TITLEBAR_H static_cast(24 * gSystem->getScaleFactor()) static const int FRAME_PADDING = 4; @@ -25,27 +23,9 @@ DialogData::~DialogData() { } DialogData::DialogData(GuiContext* gui, GuiDialog* dialog) - : GuiWidget(gui), - dialog_ptr_(dialog), - gui_(gui), - is_closeable_(true), - is_minimizable_(true), - is_pinnable_(true), - is_draggable_(true), - is_horizontally_resizable_(false), - is_vertically_resizable_(false), - request_close_(false), - request_pin_(false), - request_minimize_(false), - request_move_to_top_(false), - pinned_state_(false), - minimized_state_(false), - min_size_({0, 0}), - max_size_({INT_MAX, INT_MAX}), - pinned_position_({0, 0}), - current_action_(nullptr) { + : GuiWidget(gui), dialog_ptr_(dialog), gui_(gui) { rect_ = {16, 16, 256, 256}; - MY_GUI->addDialog(this); + reinterpret_cast(gui_)->addDialog(this); } // ================================================================================================ @@ -182,16 +162,16 @@ void DialogData::ClampRect() { if (current_action_ && current_action_->type >= ACT_RESIZE) { auto a = static_cast(current_action_); - if (a->dirH < 0) rect_.w = min(rect_.w, a->anchor.x - bounds.x); + if (a->dirH < 0) rect_.w = std::min(rect_.w, a->anchor.x - bounds.x); if (a->dirH > 0) - rect_.w = min(rect_.w, bounds.x + bounds.w - a->anchor.x); - if (a->dirV < 0) rect_.h = min(rect_.h, a->anchor.y - bounds.y); + rect_.w = std::min(rect_.w, bounds.x + bounds.w - a->anchor.x); + if (a->dirV < 0) rect_.h = std::min(rect_.h, a->anchor.y - bounds.y); if (a->dirV > 0) - rect_.h = min(rect_.h, bounds.y + bounds.h - a->anchor.y); + rect_.h = std::min(rect_.h, bounds.y + bounds.h - a->anchor.y); } - rect_.w = max(min_size_.x, min(max_size_.x, min(bounds.w, rect_.w))); - rect_.h = max(min_size_.y, min(max_size_.y, min(bounds.h, rect_.h))); + rect_.w = std::clamp(std::min(bounds.w, rect_.w), min_size_.x, max_size_.x); + rect_.h = std::clamp(std::min(bounds.h, rect_.h), min_size_.y, max_size_.y); if (current_action_ && current_action_->type >= ACT_RESIZE) { auto a = static_cast(current_action_); @@ -200,8 +180,8 @@ void DialogData::ClampRect() { } int marginH = minimized_state_ ? (FRAME_PADDING * -2) : rect_.h; - rect_.x = max(min(rect_.x, bounds.x + bounds.w - rect_.w), bounds.x); - rect_.y = max(min(rect_.y, bounds.y + bounds.h - marginH), bounds.y); + rect_.x = std::clamp(rect_.x, bounds.x, bounds.x + bounds.w - rect_.w); + rect_.y = std::clamp(rect_.y, bounds.y, bounds.y + bounds.h - marginH); } void DialogData::arrange() { @@ -443,13 +423,13 @@ void GuiDialog::setWidth(int w) { DATA->rect_.w = w; } void GuiDialog::setHeight(int h) { DATA->rect_.h = h; } -void GuiDialog::setMinimumWidth(int w) { DATA->min_size_.x = max(0, w); } +void GuiDialog::setMinimumWidth(int w) { DATA->min_size_.x = std::max(0, w); } -void GuiDialog::setMinimumHeight(int h) { DATA->min_size_.y = max(0, h); } +void GuiDialog::setMinimumHeight(int h) { DATA->min_size_.y = std::max(0, h); } -void GuiDialog::setMaximumWidth(int w) { DATA->max_size_.x = max(0, w); } +void GuiDialog::setMaximumWidth(int w) { DATA->max_size_.x = std::max(0, w); } -void GuiDialog::setMaximumHeight(int h) { DATA->max_size_.y = max(0, h); } +void GuiDialog::setMaximumHeight(int h) { DATA->max_size_.y = std::max(0, h); } void GuiDialog::setCloseable(bool enable) { DATA->is_closeable_ = enable; } diff --git a/src/Core/GuiDialog.h b/src/Core/GuiDialog.h index 1e3de23a..dfa71f1e 100644 --- a/src/Core/GuiDialog.h +++ b/src/Core/GuiDialog.h @@ -1,6 +1,9 @@ #pragma once #include +#include + +#include namespace Vortex { @@ -46,20 +49,20 @@ class DialogData : public GuiWidget { GuiDialog* dialog_ptr_; GuiContext* gui_; - bool is_closeable_ : 1; - bool is_minimizable_ : 1; - bool is_pinnable_ : 1; - bool is_draggable_ : 1; - bool is_horizontally_resizable_ : 1; - bool is_vertically_resizable_ : 1; + bool is_pinnable_ : 1 = true; + bool is_closeable_ : 1 = true; + bool is_minimizable_ : 1 = true; + bool is_draggable_ : 1 = true; + bool is_horizontally_resizable_ : 1 = false; + bool is_vertically_resizable_ : 1 = false; - bool request_close_ : 1; - bool request_pin_ : 1; - bool request_minimize_ : 1; - bool request_move_to_top_ : 1; + bool request_close_ : 1 = false; + bool request_pin_ : 1 = false; + bool request_minimize_ : 1 = false; + bool request_move_to_top_ : 1 = false; - bool pinned_state_ : 1; - bool minimized_state_ : 1; + bool pinned_state_ : 1 = false; + bool minimized_state_ : 1 = false; private: friend class GuiDialog; @@ -72,13 +75,13 @@ class DialogData : public GuiWidget { ActionType GetAction(int x, int y) const; void FinishActions(); - vec2i min_size_; - vec2i max_size_; - vec2i pinned_position_; + vec2i min_size_ = {0, 0}; + vec2i max_size_ = {INT_MAX, INT_MAX}; + vec2i pinned_position_ = {0, 0}; std::string dialog_title_; - BaseAction* current_action_; + BaseAction* current_action_ = nullptr; }; }; // namespace Vortex diff --git a/src/Core/GuiDraw.cpp b/src/Core/GuiDraw.cpp index ccf13c86..4f4f6414 100644 --- a/src/Core/GuiDraw.cpp +++ b/src/Core/GuiDraw.cpp @@ -188,6 +188,12 @@ static void CreateIcons() { c.polygon(arrow, arrow + 3, 3); GD->icons.arrow = c.createTexture(); + // Chevron : right pointing > symbol + c.clear(1.0f); + c.line(24, 12, 40, 32, 8); + c.line(40, 32, 24, 52, 8); + GD->icons.chevron = c.createTexture(); + // Check : checkmark. c = Canvas(80, 80, 1.f); float check[12] = {56, 80, 40, 0, 16, 32, 0, 8, 80, 40, 24, 48}; diff --git a/src/Core/GuiDraw.h b/src/Core/GuiDraw.h index 824a6d96..a3768339 100644 --- a/src/Core/GuiDraw.h +++ b/src/Core/GuiDraw.h @@ -15,6 +15,7 @@ struct GuiDraw { Texture grab, arrow; Texture plus, minus, cross; Texture check; + Texture chevron; }; struct Button { diff --git a/src/Core/GuiManager.cpp b/src/Core/GuiManager.cpp index 75cdc988..2705563a 100644 --- a/src/Core/GuiManager.cpp +++ b/src/Core/GuiManager.cpp @@ -2,6 +2,8 @@ #include +#include + namespace Vortex { struct GuiManagerData { @@ -9,7 +11,7 @@ struct GuiManagerData { GuiWidget* mouseCapture; GuiWidget* textCapture; - Vector mouseBlockers; + std::vector mouseBlockers; std::map widgetToIdMap; std::multimap idToWidgetMap; @@ -72,7 +74,7 @@ void GuiManager::removeWidget(GuiWidget* w) { GM->tooltipMap.erase(w); Map::eraseVals(GM->idToWidgetMap, w); GM->widgetToIdMap.erase(w); - GM->mouseBlockers.erase_values(w); + std::erase(GM->mouseBlockers, w); } void GuiManager::setWidgetId(GuiWidget* w, const std::string& id) { @@ -104,11 +106,11 @@ std::string GuiManager::getTooltip(const GuiWidget* w) { } void GuiManager::blockMouseOver(GuiWidget* w) { - GM->mouseBlockers.push_back(w); + GM->mouseBlockers.emplace_back(w); } void GuiManager::unblockMouseOver(GuiWidget* w) { - GM->mouseBlockers.erase_values(w); + std::erase(GM->mouseBlockers, w); } void GuiManager::makeMouseOver(GuiWidget* w) { diff --git a/src/Core/GuiWidget.cpp b/src/Core/GuiWidget.cpp index d521340a..947ed239 100644 --- a/src/Core/GuiWidget.cpp +++ b/src/Core/GuiWidget.cpp @@ -8,8 +8,6 @@ namespace Vortex { -#define MY_GUI ((GuiContextImpl*)gui_) - // ================================================================================================ // GuiWidget :: constructor / destructor. @@ -24,11 +22,10 @@ GuiWidget::GuiWidget(GuiContext* gui) rect_({0, 0, static_cast(128 * gSystem->getScaleFactor()), static_cast(24 * gSystem->getScaleFactor())}), width_(static_cast(128 * gSystem->getScaleFactor())), - height_(static_cast(24 * gSystem->getScaleFactor())), - flags_(WF_ENABLED) {} + height_(static_cast(24 * gSystem->getScaleFactor())) {} GuiWidget::~GuiWidget() { - MY_GUI->removeWidget(this); + reinterpret_cast(gui_)->removeWidget(this); GuiManager::removeWidget(this); } @@ -66,12 +63,12 @@ void GuiWidget::onMouseCaptureLost() {} void GuiWidget::onTextCaptureLost() {} void GuiWidget::startCapturingFocus() { - MY_GUI->grabFocus(this); + reinterpret_cast(gui_)->grabFocus(this); SetFlags(flags_, WF_IN_FOCUS, true); } void GuiWidget::stopCapturingFocus() { - MY_GUI->releaseFocus(this); + reinterpret_cast(gui_)->releaseFocus(this); SetFlags(flags_, WF_IN_FOCUS, false); } diff --git a/src/Core/ImageLoader.cpp b/src/Core/ImageLoader.cpp index f0683e02..24be9719 100644 --- a/src/Core/ImageLoader.cpp +++ b/src/Core/ImageLoader.cpp @@ -26,13 +26,13 @@ ImageLoader::Data ImageLoader::load(fs::path path, ImageLoader::Format fmt) { auto desiredChannels = sFmtChannels[fmt]; ImageLoader::Data out = {nullptr, 0, 0}; auto path_str = pathToUtf8(path); - stbi_uc *pixels = stbi_load(path_str.c_str(), &w, &h, &channels, 0); + stbi_uc* pixels = stbi_load(path_str.c_str(), &w, &h, &channels, 0); if (pixels && w > 0 && h > 0) { // stb is missing the ability to convert to alpha-only format from 2 and // 4 channels, so we do it ourselves here. if (fmt == ImageLoader::ALPHA && (channels == 2 || channels == 4)) { out.pixels = - reinterpret_cast(malloc(w * h * desiredChannels)); + reinterpret_cast(malloc(w * h * desiredChannels)); if (!out.pixels) { Debug::blockBegin(Debug::WARNING, "malloc failed on loading image"); @@ -42,8 +42,8 @@ ImageLoader::Data ImageLoader::load(fs::path path, ImageLoader::Format fmt) { return out; } for (auto j = 0; j < w * h; ++j) { - unsigned char *src = pixels + j * channels; - unsigned char *dest = out.pixels + j * desiredChannels; + unsigned char* src = pixels + j * channels; + unsigned char* dest = out.pixels + j * desiredChannels; if (channels == 4) { dest[0] = src[3]; } else { @@ -66,19 +66,19 @@ ImageLoader::Data ImageLoader::load(fs::path path, ImageLoader::Format fmt) { return out; } -void ImageLoader::release(ImageLoader::Data &data) { +void ImageLoader::release(ImageLoader::Data& data) { stbi_image_free(data.pixels); } -Zlib::Data Zlib::deflate(const stbi_uc *data, int inSize) { +Zlib::Data Zlib::deflate(const stbi_uc* data, int inSize) { int numBytes = 0; Zlib::Data out = {nullptr, 0}; - out.data = reinterpret_cast(stbi_zlib_decode_malloc( - reinterpret_cast(data), inSize, &numBytes)); + out.data = reinterpret_cast(stbi_zlib_decode_malloc( + reinterpret_cast(data), inSize, &numBytes)); if (out.data) out.numBytes = numBytes; return out; } -void Zlib::release(Zlib::Data &data) { free(data.data); } +void Zlib::release(Zlib::Data& data) { free(data.data); } }; // namespace Vortex diff --git a/src/Core/Input.cpp b/src/Core/Input.cpp index b3b17fc6..4c7f9165 100644 --- a/src/Core/Input.cpp +++ b/src/Core/Input.cpp @@ -131,11 +131,9 @@ bool ReadNext(void* data, int type, T*& it) { InputEvents::~InputEvents() { clear(); } -InputEvents::InputEvents() : data_(nullptr) {} +InputEvents::InputEvents() = default; -InputEvents::InputEvents(const InputEvents& other) : data_(nullptr) { - *this = other; -} +InputEvents::InputEvents(const InputEvents& other) { *this = other; } void InputEvents::clear() { EventHeader* header = static_cast(data_); diff --git a/src/Core/Input.h b/src/Core/Input.h index 97f1e984..790955a2 100644 --- a/src/Core/Input.h +++ b/src/Core/Input.h @@ -1,6 +1,9 @@ #pragma once #include +#ifdef DELETE +#undef DELETE +#endif namespace Vortex { @@ -328,7 +331,8 @@ class InputEvents { void operator=(const InputEvents& other); private: - void* data_; // TODO: replace with a more descriptive variable name. + void* data_ = + nullptr; // TODO: replace with a more descriptive variable name. friend class InputHandler; }; diff --git a/src/Core/NonCopyable.h b/src/Core/NonCopyable.h index 24cc8a65..380e966c 100644 --- a/src/Core/NonCopyable.h +++ b/src/Core/NonCopyable.h @@ -6,13 +6,11 @@ namespace Vortex { namespace NonCopyable_ { class NonCopyable { - protected: - NonCopyable() {} - ~NonCopyable() {} - - private: - NonCopyable(const NonCopyable&); - void operator=(const NonCopyable&); // why is this private? + public: + NonCopyable() = default; + ~NonCopyable() = default; + NonCopyable(const NonCopyable&) = delete; + void operator=(const NonCopyable&) = delete; }; } // namespace NonCopyable_ typedef NonCopyable_::NonCopyable NonCopyable; diff --git a/src/Core/Polyfit.h b/src/Core/Polyfit.h index d04f954c..a2a0d8bb 100644 --- a/src/Core/Polyfit.h +++ b/src/Core/Polyfit.h @@ -1,9 +1,9 @@ #pragma once #include -#include #include +#include #include namespace mathalgo { @@ -44,7 +44,7 @@ struct matrix { } return oResult; } - Vortex::Vector data; + std::vector data; uint32_t rows; uint32_t cols; }; @@ -182,8 +182,7 @@ struct Givens { */ template -Vortex::Vector polyfit(const T* oX, const T* oY, size_t nCount, - int nDegree) { +std::vector polyfit(const T* oX, const T* oY, size_t nCount, int nDegree) { // more intuitive this way nDegree++; diff --git a/src/Core/QuadBatch.h b/src/Core/QuadBatch.h index 34a75b10..21c954d2 100644 --- a/src/Core/QuadBatch.h +++ b/src/Core/QuadBatch.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include namespace Vortex { diff --git a/src/Core/Reference.h b/src/Core/Reference.h index d2e452a1..79fba26e 100644 --- a/src/Core/Reference.h +++ b/src/Core/Reference.h @@ -36,14 +36,15 @@ class Reference { /// Returns the number of references to the current value. inline int count() const { - return reference_ptr_ ? *((int*)reference_ptr_ - 1) : 0; + return reference_ptr_ ? *(reinterpret_cast(reference_ptr_) - 1) + : 0; } /// Returns a pointer to the current value. - inline operator T*() { return reference_ptr_; } + inline explicit operator T*() { return reference_ptr_; } /// Returns a const pointer to the current value. - inline operator T*() const { return reference_ptr_; } + inline explicit operator T*() const { return reference_ptr_; } /// Returns a pointer to the current value. inline T* operator->() { return reference_ptr_; } @@ -100,7 +101,7 @@ void Reference::create(const T& v) { template void Reference::destroy() { if (reference_ptr_) { - int* ref = (int*)reference_ptr_ - 1; + int* ref = reinterpret_cast(reference_ptr_) - 1; if (--*ref == 0) { reference_ptr_->~T(); delete ref; @@ -114,16 +115,16 @@ void Reference::copy(const Reference& o) { if (reference_ptr_ != o.reference_ptr_) { destroy(); reference_ptr_ = o.reference_ptr_; - ++*((int*)reference_ptr_ - 1); + ++*(reinterpret_cast(reference_ptr_) - 1); } } template void Reference::InitReference() { destroy(); - int* ref = (int*)malloc(sizeof(int) + sizeof(T)); + int* ref = reinterpret_cast(malloc(sizeof(int) + sizeof(T))); *ref = 1; - reference_ptr_ = (T*)(ref + 1); + reference_ptr_ = reinterpret_cast(ref + 1); } }; // namespace Vortex diff --git a/src/Core/Renderer.cpp b/src/Core/Renderer.cpp index 8b04b145..292311af 100644 --- a/src/Core/Renderer.cpp +++ b/src/Core/Renderer.cpp @@ -1,15 +1,18 @@ #include -#include #include #include #include #include +#include #include #include #include +#include +#include + namespace Vortex { static const int BATCH_QUAD_LIMIT = 256; @@ -29,7 +32,7 @@ namespace { struct RendererInstance { Shader shaders[4]; - Vector scissorStack; + std::vector scissorStack; uint32_t* quadIndices; uint8_t* batchPos; @@ -160,8 +163,10 @@ void Renderer::destroy() { void Renderer::startFrame() { vec2i view = GuiMain::getViewSize(); + int menu_height = gMenubar ? gMenubar->getMenubarHeight() : 0; glLoadIdentity(); glOrtho(0, view.x, view.y, 0, -1, 1); + glTranslated(0, menu_height, 0); } void Renderer::endFrame() { @@ -201,24 +206,27 @@ void Renderer::pushScissorRect(const recti& r) { void Renderer::pushScissorRect(int x, int y, int w, int h) { auto& stack = RI->scissorStack; - w = max(w, 0), h = max(h, 0); + w = std::max(w, 0), h = std::max(h, 0); + recti newRect = {x, y, w, h}; if (stack.empty()) { // The new scissor region is the first scissor region, use it as-is. glEnable(GL_SCISSOR_TEST); - stack.push_back({x, y, w, h}); + stack.emplace_back(newRect); } else if (stack.size() < 256) { // Calculate the intersection of the current and new scissor region. recti last = stack.back(); - int r = min(last.x + last.w, x + w); - int b = min(last.y + last.h, y + h); - x = max(last.x, x), w = max(0, r - x); - y = max(last.y, y), h = max(0, b - y); - stack.push_back({x, y, w, h}); + int r = std::min(last.x + last.w, x + w); + int b = std::min(last.y + last.h, y + h); + x = std::max(last.x, x), w = std::max(0, r - x); + y = std::max(last.y, y), h = std::max(0, b - y); + stack.emplace_back(newRect); } // Apply the new scissor region. vec2i view = GuiMain::getViewSize(); - glScissor(x, view.y - (y + h), w, h); + // Scissor is in window coordinates + int menu_h = gMenubar ? gMenubar->getMenubarHeight() : 0; + glScissor(x, view.y - (y + h) - menu_h, w, h); } void Renderer::popScissorRect() { @@ -230,7 +238,9 @@ void Renderer::popScissorRect() { stack.pop_back(); recti r = stack.back(); vec2i view = GuiMain::getViewSize(); - glScissor(r.x, view.y - (r.y + r.h), r.w, r.h); + // Scissor is in window coordinates + int menu_h = gMenubar ? gMenubar->getMenubarHeight() : 0; + glScissor(r.x, view.y - (r.y + r.h) - menu_h, r.w, r.h); } } diff --git a/src/Core/Shader.cpp b/src/Core/Shader.cpp index 3e4d4b5e..de1f0482 100644 --- a/src/Core/Shader.cpp +++ b/src/Core/Shader.cpp @@ -6,6 +6,9 @@ #include #include #include +#include + +#include namespace Vortex { @@ -14,30 +17,26 @@ namespace Vortex { static bool sSupported = false; -#define EXT(name, result) static result(APIENTRY* name) - -#define PROC(name) \ - name = (decltype(name))wglGetProcAddress(#name); \ - if (!name) { \ - missing.push_back(#name); \ - ++numMissing; \ - } -#define PROC_OPT(name) \ - name = (decltype(name))wglGetProcAddress(#name); \ - if (!name) { \ - missing.push_back(#name); \ - } - -// #define PROC(name) name = nullptr; if(!name) { missing.push_back(#name); -// ++numMissing; } #define PROC_OPT(name) name = nullptr; if(!name) { -// missing.push_back(#name); } - #define GL_FRAGMENT_SHADER 0x8B30 #define GL_VERTEX_SHADER 0x8B31 #define GL_COMPILE_STATUS 0x8B81 #define GL_LINK_STATUS 0x8B82 #define GL_INFO_LOG_LENGTH 0x8B84 +#define EXT(name, result) static result(APIENTRY* name) + +#define PROC(name) \ + name = (decltype(name))SDL_GL_GetProcAddress(#name); \ + if (!name) { \ + missing.emplace_back(#name); \ + ++numMissing; \ + } +#define PROC_OPT(name) \ + name = (decltype(name))SDL_GL_GetProcAddress(#name); \ + if (!name) { \ + missing.emplace_back(#name); \ + } + EXT(glCreateShader, GLint)(GLenum type); EXT(glDeleteShader, void)(GLuint shader); EXT(glCompileShader, void)(GLuint shader); @@ -54,7 +53,7 @@ EXT(glUniform2f, void)(GLint loc, GLfloat v0, GLfloat v1); EXT(glUniform4f, void)(GLint loc, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -EXT(glCreateProgram, GLuint)(void); +EXT(glCreateProgram, GLuint)(); EXT(glUseProgram, void)(GLuint program); EXT(glDeleteProgram, void)(GLuint program); EXT(glLinkProgram, void)(GLuint program); @@ -64,7 +63,7 @@ EXT(glGetProgramInfoLog, void)(GLuint program, GLsizei bufSize, GLsizei* len, char* str); void Shader::initExtension() { - Vector missing; + std::vector missing; int numMissing = 0; PROC(glCreateShader); @@ -183,8 +182,7 @@ Shader::~Shader() { Destroy(program_id_, vertex_shader_id_, fragment_shader_id_); } -Shader::Shader() - : program_id_(0), vertex_shader_id_(0), fragment_shader_id_(0) {} +Shader::Shader() = default; bool Shader::load(const char* vertexCode, const char* fragmentCode, const char* def, const char* shaderName, diff --git a/src/Core/Shader.h b/src/Core/Shader.h index d4df4b4f..efcd5a4d 100644 --- a/src/Core/Shader.h +++ b/src/Core/Shader.h @@ -30,7 +30,7 @@ class Shader { static void uniform4f(int loc, float x, float y, float z, float w); static void uniform4f(int loc, const colorf& color); - uint32_t program_id_, vertex_shader_id_, fragment_shader_id_; + uint32_t program_id_ = 0, vertex_shader_id_ = 0, fragment_shader_id_ = 0; }; }; // namespace Vortex diff --git a/src/Core/Slot.cpp b/src/Core/Slot.cpp index a111cd87..63e54c35 100644 --- a/src/Core/Slot.cpp +++ b/src/Core/Slot.cpp @@ -161,7 +161,7 @@ static void ReleaseVal(void* data) { // ================================================================================================ // ValueSlot :: implementation. -ValueSlot::ValueSlot() : data_(nullptr) {} +ValueSlot::ValueSlot() = default; ValueSlot::~ValueSlot() { ReleaseVal(data_); } @@ -391,7 +391,7 @@ const char* TextSlot::get() const { // ================================================================================================ // CallSlot :: implementation. -CallSlot::CallSlot() : data_(nullptr) {} +CallSlot::CallSlot() = default; CallSlot::~CallSlot() { delete static_cast(data_); } diff --git a/src/Core/Slot.h b/src/Core/Slot.h index f87286b8..8ac7eba3 100644 --- a/src/Core/Slot.h +++ b/src/Core/Slot.h @@ -10,7 +10,7 @@ using namespace Vortex; struct Functor { /// Generic functor that can be called trough exec. struct Generic { - virtual ~Generic() {} + virtual ~Generic() = default; virtual void exec() = 0; }; @@ -18,8 +18,8 @@ struct Functor { template struct Static : public Generic { typedef Result (*Function)(); - Static(Function f) : f(f) {} - void exec() { (*f)(); } + explicit Static(Function f) : f(f) {} + void exec() override { (*f)(); } Function f; }; @@ -28,7 +28,7 @@ struct Functor { struct StaticWithArg : public Generic { typedef Result (*Function)(Arg); StaticWithArg(Function f, Arg a) : f(f), a(a) {} - void exec() { (*f)(a); } + void exec() override { (*f)(a); } Function f; Arg a; }; @@ -38,7 +38,7 @@ struct Functor { struct Member : public Generic { typedef Result (Object::*Function)(); Member(Object* o, Function f) : o(o), f(f) {} - void exec() { (o->*f)(); } + void exec() override { (o->*f)(); } Object* o; Function f; }; @@ -48,7 +48,7 @@ struct Functor { struct MemberWithArg : public Generic { typedef Result (Object::*Function)(Arg); MemberWithArg(Object* o, Function f, Arg a) : o(o), f(f), a(a) {} - void exec() { (o->*f)(a); } + void exec() override { (o->*f)(a); } Object* o; Function f; Arg a; @@ -83,7 +83,8 @@ class ValueSlot { void bind(bool* v); protected: - void* data_; // TODO: replace with a more descriptive variable name. + void* data_ = + nullptr; // TODO: replace with a more descriptive variable name. }; /// Slot that binds to an integer value. @@ -204,7 +205,8 @@ class CallSlot { } private: - void* data_; // TODO: replace with a more descriptive variable name. + void* data_ = + nullptr; // TODO: replace with a more descriptive variable name. }; }; // namespace Vortex diff --git a/src/Core/StringUtils.cpp b/src/Core/StringUtils.cpp index c248eec8..e171fed9 100644 --- a/src/Core/StringUtils.cpp +++ b/src/Core/StringUtils.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include #include #include @@ -462,9 +464,9 @@ static const int DBL_BUFLEN = 64; static int PrintInt(char* buf, int v, int minDig, bool hex) { int len; if (minDig <= 0) { - len = _snprintf(buf, INT_BUFLEN, hex ? "%X" : "%i", v); + len = std::snprintf(buf, INT_BUFLEN, hex ? "%X" : "%i", v); } else { - len = _snprintf(buf, INT_BUFLEN, hex ? "%0*X" : "%0*i", minDig, v); + len = std::snprintf(buf, INT_BUFLEN, hex ? "%0*X" : "%0*i", minDig, v); } return (len < 0) ? DBL_BUFLEN : len; } @@ -472,19 +474,19 @@ static int PrintInt(char* buf, int v, int minDig, bool hex) { static int PrintUint(char* buf, uint32_t v, int minDig, bool hex) { int len; if (minDig <= 0) { - len = _snprintf(buf, INT_BUFLEN, hex ? "%X" : "%u", v); + len = std::snprintf(buf, INT_BUFLEN, hex ? "%X" : "%u", v); } else { - len = _snprintf(buf, INT_BUFLEN, hex ? "%0*X" : "%0*u", minDig, v); + len = std::snprintf(buf, INT_BUFLEN, hex ? "%0*X" : "%0*u", minDig, v); } return (len < 0) ? INT_BUFLEN : len; } static int PrintDouble(char* buf, double v, int minDec, int maxDec) { - minDec = min(max(minDec, 0), 16); - maxDec = min(max(minDec, maxDec), 16); + minDec = std::clamp(minDec, 0, 16); + maxDec = std::clamp(maxDec, minDec, 16); // Print the value. - int len = _snprintf(buf, DBL_BUFLEN, "%.*f", maxDec, v); + int len = std::snprintf(buf, DBL_BUFLEN, "%.*f", maxDec, v); if (len < 0) len = DBL_BUFLEN; // Cap the number of decimal digits. @@ -731,8 +733,8 @@ bool Str::parse(const char* expr, double& out) { // ================================================================================================ // Str :: string splitting and joining. -Vector Str::split(const std::string& s) { - Vector out; +std::vector Str::split(const std::string& s) { + std::vector out; if (s.empty()) { return out; } @@ -742,15 +744,16 @@ Vector Str::split(const std::string& s) { while (it != s.end()) { auto cur = it; while (cur != s.end() && !IsWhiteSpace(*cur)) ++cur; - out.push_back(std::string(it, cur)); + std::string new_string = std::string(it, cur); + out.emplace_back(new_string); while (it != s.end() && IsWhiteSpace(*it)) ++it; } return out; } -Vector Str::split(const std::string& s, const char* lim, bool trim, - bool skip) { - Vector out; +std::vector Str::split(const std::string& s, const char* lim, + bool trim, bool skip) { + std::vector out; auto limlen = strlen(lim); auto slen = s.length() - limlen; size_t start = 0; @@ -758,18 +761,18 @@ Vector Str::split(const std::string& s, const char* lim, bool trim, if (memcmp(s.data() + i, lim, limlen) == 0) { std::string sub = Str::substr(s, start, i - start); if (trim) Str::trim(sub); - if (sub.length() || !skip) out.push_back(sub); + if (sub.length() || !skip) out.emplace_back(sub); i += limlen, start = i; } else ++i; } std::string sub = Str::substr(s, start, std::string::npos); if (trim) Str::trim(sub); - if (sub.length() || !skip) out.push_back(sub); + if (sub.length() || !skip) out.emplace_back(sub); return out; } -std::string Str::join(const Vector& list, const char* lim) { +std::string Str::join(const std::vector& list, const char* lim) { if (list.empty()) return {}; // Determine the total String length and allocate the output string. @@ -807,9 +810,10 @@ std::string Str::formatTime(double seconds, bool precise) { t -= min * (60 * 1000); int64_t sec = t / 1000; - auto fmt = Str::fmt("%1:%2.") - .arg(static_cast(min), 2) - .arg(static_cast(sec), 2); + std::string fmt = + static_cast(Str::fmt("%1:%2.") + .arg(static_cast(min), 2) + .arg(static_cast(sec), 2)); if (precise) { t -= sec * 1000; diff --git a/src/Core/StringUtils.h b/src/Core/StringUtils.h index e0e30f88..6e2bbd47 100644 --- a/src/Core/StringUtils.h +++ b/src/Core/StringUtils.h @@ -1,6 +1,8 @@ #pragma once -#include +#include +#include +#include namespace Vortex { @@ -210,8 +212,8 @@ struct Str { /// Helper struct used in string formatting. struct fmt { - fmt(const std::string& format); - fmt(const char* format); + explicit fmt(const std::string& format); + explicit fmt(const char* format); fmt& arg(char c); fmt& arg(const std::string& s); @@ -222,8 +224,8 @@ struct Str { fmt& arg(float v, int minDecimals = 0, int maxDecimals = 6); fmt& arg(double v, int minDecimals = 0, int maxDecimals = 6); - inline operator const char*() { return str.data(); } - inline operator std::string&() { return str; } + inline explicit operator const char*() { return str.data(); } + inline explicit operator std::string&() { return str; } std::string str; }; @@ -233,19 +235,20 @@ struct Str { /// Splits a string into a string list based on word boundaries. /// For example, SplitString("Hello World") returns {"Hello", "World"}. - static Vector split(const std::string& s); + static std::vector split(const std::string& s); /// Splits a string into a string list based on a delimiter. /// For example, SplitString("Hello ~ World", "~") returns {"Hello", /// "World"}. If trim is true, whitespace surrounding each element is /// removed. If skipEmpty is true, empty elements are not added to the list. - static Vector split(const std::string& s, - const char* delimiter, bool trim = true, - bool skipEmpty = true); + static std::vector split(const std::string& s, + const char* delimiter, + bool trim = true, + bool skipEmpty = true); /// Returns the concatenation of the list of strings, seperated by the given /// delimiter. - static std::string join(const Vector& list, + static std::string join(const std::vector& list, const char* delimiter); }; diff --git a/src/Core/Text.h b/src/Core/Text.h index cf7b6668..ecb4ad43 100644 --- a/src/Core/Text.h +++ b/src/Core/Text.h @@ -1,6 +1,7 @@ #pragma once #include +#include namespace Vortex { @@ -113,7 +114,7 @@ class Font { Font& operator=(const Font& s); /// Loads a font from a TrueType/OpenType font file. - Font(const char* path, Text::Hinting hint = Text::HINT_NORMAL); + explicit Font(const char* path, Text::Hinting hint = Text::HINT_NORMAL); /// Makes sure the font stays loaded until the shutdown of goo. void cache() const; @@ -142,10 +143,10 @@ struct TextStyle { void makeDefault(); Font font; - int fontSize; - uint32_t textFlags; - uint32_t textColor; - uint32_t shadowColor; + int fontSize = 12; + uint32_t textFlags = 0; + uint32_t textColor = Colors::white; + uint32_t shadowColor = Colors::black; }; }; // namespace Vortex diff --git a/src/Core/TextDraw.cpp b/src/Core/TextDraw.cpp index 1284a6e8..c5245cd3 100644 --- a/src/Core/TextDraw.cpp +++ b/src/Core/TextDraw.cpp @@ -258,16 +258,14 @@ void Text::draw(vec2i textPos) { RD->shadowColor = style.shadowColor; // Render the text. - auto* markup = layout.markup.begin(); int markupIndex = 0, numMarkup = layout.markup.size(); - auto* glyphs = layout.glyphs.begin(); for (auto& line : layout.lines) { int glyphIndex = line.beginGlyph, lineEnd = line.endGlyph; while (glyphIndex != lineEnd) { // Apply markup until the current glyph index is reached. while (markupIndex < numMarkup && - markup[markupIndex].glyphIndex <= glyphIndex) { - ApplyMarkup(markup[markupIndex]); + layout.markup[markupIndex].glyphIndex <= glyphIndex) { + ApplyMarkup(layout.markup[markupIndex]); ++markupIndex; } @@ -275,13 +273,13 @@ void Text::draw(vec2i textPos) { // or the line end. int drawEnd = lineEnd; if (markupIndex < numMarkup && - markup[markupIndex].glyphIndex < lineEnd) { - drawEnd = markup[markupIndex].glyphIndex; + layout.markup[markupIndex].glyphIndex < lineEnd) { + drawEnd = layout.markup[markupIndex].glyphIndex; } // Draw said glyphs. for (; glyphIndex < drawEnd; ++glyphIndex) { - auto& item = glyphs[glyphIndex]; + auto& item = layout.glyphs[glyphIndex]; if (item.glyph->hasPixels) { PushGlyph(textPos.x + line.x + item.x, textPos.y + line.y, *item.glyph); diff --git a/src/Core/TextLayout.cpp b/src/Core/TextLayout.cpp index 4c3fc0c0..d155fb17 100644 --- a/src/Core/TextLayout.cpp +++ b/src/Core/TextLayout.cpp @@ -3,12 +3,13 @@ #include #include #include -#include #include #include #include +#include +#include #include namespace Vortex { @@ -141,18 +142,20 @@ static void ReadMarkupColor(uint32_t& out, const uint8_t* param, int len, static void ReadTextColor(const uint8_t* param, int len) { ReadMarkupColor(LD->textColor, param, len, LD->baseTextColor); - auto& item = LD->markup.append(); - item.type = LMarkup::SET_TEXT_COLOR; - item.glyphIndex = LD->glyphs.size(); - item.setTextColor = LD->textColor; + LMarkup new_markup = {0}; + new_markup.type = LMarkup::SET_TEXT_COLOR; + new_markup.glyphIndex = LD->glyphs.size(); + new_markup.setTextColor = LD->textColor; + LD->markup.emplace_back(new_markup); } static void ReadShadowColor(const uint8_t* param, int len) { ReadMarkupColor(LD->shadowColor, param, len, LD->baseShadowColor); - auto& item = LD->markup.append(); - item.type = LMarkup::SET_SHADOW_COLOR; - item.glyphIndex = LD->glyphs.size(); - item.setShadowColor = LD->shadowColor; + LMarkup new_markup = {0}; + new_markup.type = LMarkup::SET_SHADOW_COLOR; + new_markup.glyphIndex = LD->glyphs.size(); + new_markup.setShadowColor = LD->shadowColor; + LD->markup.emplace_back(new_markup); } static void ReadFontSize(const uint8_t* param, int len) { @@ -168,7 +171,7 @@ static void ReadFontSize(const uint8_t* param, int len) { } else { fontSize = static_cast(ReadNumber(param, len) + 0.5); } - LD->fontSize = min(max(1, fontSize), 256); + LD->fontSize = std::clamp(fontSize, 1, 256); SetLineMetrics(); } @@ -185,11 +188,8 @@ static void ReadFontChange(const uint8_t* param, int len) { static void ReadFgColor(const uint8_t* param, int len) { if (LD->fgQuad.enabled) { - auto& quad = LD->fgQuads.append(); - quad.color = LD->fgQuad.color; - quad.line = LD->lineIndex; - quad.x = LD->fgQuad.x; - quad.w = LD->lineW - LD->fgQuad.x; + LD->fgQuads.push_back({LD->lineIndex, LD->fgQuad.x, + LD->lineW - LD->fgQuad.x, LD->fgQuad.color}); LD->fgQuad.enabled = false; } union { @@ -205,11 +205,8 @@ static void ReadFgColor(const uint8_t* param, int len) { static void ReadBgColor(const uint8_t* param, int len) { if (LD->bgQuad.enabled) { - auto& quad = LD->bgQuads.append(); - quad.color = LD->bgQuad.color; - quad.line = LD->lineIndex; - quad.x = LD->bgQuad.x; - quad.w = LD->lineW - LD->bgQuad.x; + LD->bgQuads.push_back({LD->lineIndex, LD->bgQuad.x, + LD->lineW - LD->bgQuad.x, LD->bgQuad.color}); LD->bgQuad.enabled = false; } union { @@ -320,8 +317,8 @@ static const Glyph* GetGlyph(int charcode) { } static void SetLineMetrics() { - LD->lineTop = min(LD->lineTop, -LD->fontSize); - LD->lineBottom = max(LD->lineBottom, LD->fontSize / 4); + LD->lineTop = std::min(LD->lineTop, -LD->fontSize); + LD->lineBottom = std::max(LD->lineBottom, LD->fontSize / 4); } static const Glyph* ReadGlyph(const uint8_t* str) { @@ -356,32 +353,34 @@ static const Glyph* ReadGlyph(const uint8_t* str) { static void AddEllipsesToLine() { const Glyph* ellipsesGlyph = GetGlyph('.'); int ellipsesW = ellipsesGlyph->advance * 3; - int maxLineW = max(0, LD->maxLineW - ellipsesW); + int maxLineW = std::max(0, LD->maxLineW - ellipsesW); // In order to do ellipses, the line must contain atleast one glyph. if (LD->lineBeginGlyph == LD->glyphs.size()) return; - auto* glyphs = LD->glyphs.begin(); int firstGlyph = LD->lineBeginGlyph; int lastGlyph = LD->glyphs.size() - 1; - int lineEndCharIndex = glyphs[firstGlyph].charIndex; + int lineEndCharIndex = LD->glyphs[firstGlyph].charIndex; // Omit all glyphs that are past the maximum line width. while (lastGlyph >= firstGlyph && - glyphs[lastGlyph].x + glyphs[lastGlyph].glyph->advance > maxLineW) { - lineEndCharIndex = glyphs[lastGlyph].charIndex; + LD->glyphs[lastGlyph].x + LD->glyphs[lastGlyph].glyph->advance > + maxLineW) { + lineEndCharIndex = LD->glyphs[lastGlyph].charIndex; --lastGlyph; } // We don't put ellipses after whitespace, so omit trailing whitespace as // well. - while (lastGlyph >= firstGlyph && glyphs[lastGlyph].glyph->isWhitespace) { - lineEndCharIndex = glyphs[lastGlyph].charIndex; + while (lastGlyph >= firstGlyph && + LD->glyphs[lastGlyph].glyph->isWhitespace) { + lineEndCharIndex = LD->glyphs[lastGlyph].charIndex; --lastGlyph; } // Determine the new line width. if (lastGlyph >= 0) { - LD->lineW = glyphs[lastGlyph].x + glyphs[lastGlyph].glyph->advance; + LD->lineW = + LD->glyphs[lastGlyph].x + LD->glyphs[lastGlyph].glyph->advance; } else { LD->lineW = 0; } @@ -389,12 +388,12 @@ static void AddEllipsesToLine() { // Clamp foreground/background quads to the new line width. for (auto& quad : LD->fgQuads) { if (quad.line == LD->lineIndex) { - quad.w = min(quad.w, max(0, LD->lineW - quad.x)); + quad.w = std::min(quad.w, std::max(0, LD->lineW - quad.x)); } } for (auto& quad : LD->bgQuads) { if (quad.line == LD->lineIndex) { - quad.w = min(quad.w, max(0, LD->lineW - quad.x)); + quad.w = std::min(quad.w, std::max(0, LD->lineW - quad.x)); } } @@ -402,20 +401,16 @@ static void AddEllipsesToLine() { LD->glyphs.resize(lastGlyph + 1, LGlyph()); if (ellipsesW < LD->maxLineW) { for (int i = 0; i < 3; ++i) { - auto& item = LD->glyphs.append(); - item.glyph = ellipsesGlyph; - item.x = LD->lineW; - item.charIndex = lineEndCharIndex; + LD->glyphs.push_back({ellipsesGlyph, LD->lineW, lineEndCharIndex}); LD->lineW += ellipsesGlyph->advance; } } // Make sure all markup from the omitted part is applied after the ellipses. int postEllipsesIndex = LD->glyphs.size(); - auto* markup = LD->markup.begin(); int markupIndex = LD->markup.size() - 1; - while (markupIndex >= 0 && markup[markupIndex].glyphIndex > lastGlyph) { - markup[markupIndex].glyphIndex = postEllipsesIndex; + while (markupIndex >= 0 && LD->markup[markupIndex].glyphIndex > lastGlyph) { + LD->markup[markupIndex].glyphIndex = postEllipsesIndex; --markupIndex; } } @@ -423,21 +418,15 @@ static void AddEllipsesToLine() { static void FinishCurrentLine(bool last) { // Finish the current foreground quad. if (LD->fgQuad.enabled && LD->lineW > LD->fgQuad.x) { - auto& quad = LD->fgQuads.append(); - quad.color = LD->fgQuad.color; - quad.line = LD->lineIndex; - quad.x = LD->fgQuad.x; - quad.w = LD->lineW - LD->fgQuad.x; + LD->fgQuads.push_back({LD->lineIndex, LD->fgQuad.x, + LD->lineW - LD->fgQuad.x, LD->fgQuad.color}); LD->fgQuad.x = 0; } // Finish the current background quad. if (LD->fgQuad.enabled && LD->lineW > LD->fgQuad.x) { - auto& quad = LD->bgQuads.append(); - quad.color = LD->fgQuad.color; - quad.line = LD->lineIndex; - quad.x = LD->fgQuad.x; - quad.w = LD->lineW - LD->fgQuad.x; + LD->bgQuads.push_back({LD->lineIndex, LD->fgQuad.x, + LD->lineW - LD->fgQuad.x, LD->fgQuad.color}); LD->fgQuad.x = 0; } @@ -454,17 +443,12 @@ static void FinishCurrentLine(bool last) { } // Store the current line info. - auto& line = LD->lines.append(); - line.beginGlyph = LD->lineBeginGlyph; - line.endGlyph = LD->glyphs.size(); - line.x = 0; - line.y = lineY; - line.w = LD->lineW; - line.top = LD->lineTop; - line.bottom = LD->lineBottom; + LD->lines.push_back({LD->lineBeginGlyph, + static_cast(LD->glyphs.size()), 0, lineY, + LD->lineW, LD->lineTop, LD->lineBottom}); // Update the size of the text area. - LD->textW = max(LD->textW, LD->lineW); + LD->textW = std::max(LD->textW, LD->lineW); LD->textH = lineY + LD->lineBottom; // advance to the next line. @@ -551,10 +535,7 @@ static void CreateLayout(const char* str) { } // Insert the glyph in the list. - auto& item = LD->glyphs.append(); - item.glyph = glyph; - item.x = LD->lineW; - item.charIndex = LD->charIndex; + LD->glyphs.push_back({glyph, LD->lineW, LD->charIndex}); // Check if we are forced to break the line and continue on a new line. if (glyph->isNewline && isMultiline) { @@ -628,11 +609,7 @@ static vec2i ArrangeText(const TextStyle& style, int maxLineWidth, // ================================================================================================ // TextStyle -TextStyle::TextStyle() - : fontSize(12), - textFlags(0), - textColor(Colors::white), - shadowColor(Colors::black) { +TextStyle::TextStyle() { if (LD) *this = LD->defaultStyle; } @@ -716,7 +693,8 @@ vec2i Text::arrange(Text::Align align, const char* text) { } vec2i Text::arrange(Text::Align align, int maxLineWidth, const char* text) { - return ArrangeText(LD->defaultStyle, max(maxLineWidth, 0), align, text); + return ArrangeText(LD->defaultStyle, std::max(maxLineWidth, 0), align, + text); } vec2i Text::arrange(Text::Align align, const TextStyle& style, @@ -726,7 +704,7 @@ vec2i Text::arrange(Text::Align align, const TextStyle& style, vec2i Text::arrange(Text::Align align, const TextStyle& style, int maxLineWidth, const char* text) { - return ArrangeText(style, max(maxLineWidth, 0), align, text); + return ArrangeText(style, std::max(maxLineWidth, 0), align, text); } vec2i Text::getSize() { return {LD->textW, LD->textH}; } @@ -746,8 +724,8 @@ int Text::getCharIndex(recti textBox, vec2i cursorPos) { } int Text::getCharIndex(vec2i textPos, vec2i cursorPos) { - const LLine* line = LD->lines.begin(); - const LLine* lineEnd = LD->lines.end(); + auto line = LD->lines.begin(); + auto lineEnd = LD->lines.end(); cursorPos.x -= textPos.x; cursorPos.y -= textPos.y; @@ -766,8 +744,8 @@ int Text::getCharIndex(vec2i textPos, vec2i cursorPos) { // Otherwise, we look for the closest character on the current line. int lastPos = line->beginGlyph; - auto* begin = LD->glyphs.begin() + line->beginGlyph; - auto* end = LD->glyphs.begin() + line->endGlyph; + auto begin = LD->glyphs.begin() + line->beginGlyph; + auto end = LD->glyphs.begin() + line->endGlyph; for (auto item = begin; item != end; ++item) { int glyphCenterX = line->x + item->x + item->glyph->advance / 2; if (glyphCenterX > cursorPos.x) return item->charIndex; @@ -792,8 +770,8 @@ Text::CursorPos Text::getCursorPos(vec2i textPos, int charIndex) { // Return the rect of the first glyph on or after index. for (auto& line : LD->lines) { - auto* begin = LD->glyphs.begin() + line.beginGlyph; - auto* end = LD->glyphs.begin() + line.endGlyph; + auto begin = LD->glyphs.begin() + line.beginGlyph; + auto end = LD->glyphs.begin() + line.endGlyph; for (auto item = begin; item != end; ++item) { if (item->charIndex >= charIndex) { int x = textPos.x + line.x + item->x; @@ -829,4 +807,4 @@ int Text::getEscapedCharIndex(const char* str, int index) { return offset; } -}; // namespace Vortex \ No newline at end of file +}; // namespace Vortex diff --git a/src/Core/TextLayout.h b/src/Core/TextLayout.h index a9f7f938..835c3015 100644 --- a/src/Core/TextLayout.h +++ b/src/Core/TextLayout.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -84,11 +84,11 @@ struct LLayout { QuadData fgQuad; QuadData bgQuad; - Vector fgQuads; - Vector bgQuads; - Vector glyphs; - Vector markup; - Vector lines; + std::vector fgQuads; + std::vector bgQuads; + std::vector glyphs; + std::vector markup; + std::vector lines; int stringLength; }; diff --git a/src/Core/Texture.h b/src/Core/Texture.h index de39166c..5121d425 100644 --- a/src/Core/Texture.h +++ b/src/Core/Texture.h @@ -2,6 +2,7 @@ #include #include +#include namespace fs = std::filesystem; namespace Vortex { @@ -30,7 +31,7 @@ class Texture { Texture(int w, int h, Format fmt = RGBA); /// Loads a texture from an image file. - Texture(fs::path path, bool mipmap = false, Format fmt = RGBA); + explicit Texture(fs::path path, bool mipmap = false, Format fmt = RGBA); /// Creates a texture from a buffer of [w * h * channels] pixel values. Texture(int w, int h, const uint8_t* pixeldata, bool mipmap = false, diff --git a/src/Core/TextureImpl.cpp b/src/Core/TextureImpl.cpp index 58467dce..b7c00437 100644 --- a/src/Core/TextureImpl.cpp +++ b/src/Core/TextureImpl.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include #include @@ -12,6 +11,8 @@ #include #include +#include +#include #include @@ -23,7 +24,7 @@ ImageLoader::Format TexLoadFormats[] = {ImageLoader::RGBA, ImageLoader::LUMA, struct TextureManagerInstance { typedef std::map TexMap; - typedef Vector TexList; + typedef std::vector TexList; TexMap files; TexList textures; @@ -74,7 +75,7 @@ Texture::Data* TextureManager::load(fs::path path, Texture::Format fmt, ImageLoader::Data img = ImageLoader::load(path, TexLoadFormats[fmt]); if (img.pixels) { out = new Texture::Data(img.width, img.height, fmt, img.pixels, mipmap); - TM->textures.push_back(out); + TM->textures.emplace_back(out); TM->files[key] = out; ImageLoader::release(img); } @@ -88,7 +89,7 @@ Texture::Data* TextureManager::load(int w, int h, Texture::Format fmt, // Try to create the texture. Texture::Data* out = new Texture::Data(w, h, fmt, pixels, mipmap); - TM->textures.push_back(out); + TM->textures.emplace_back(out); return out; } @@ -99,7 +100,7 @@ void TextureManager::release(Texture::Data* tex) { // Textures can still exist after shutdown, don't assume TM is valid. if (TM) { Map::eraseVals(TM->files, tex); - TM->textures.erase_values(tex); + std::erase(TM->textures, tex); } delete tex; } @@ -119,17 +120,17 @@ static int NextPowerOfTwo(int v) { return v; } -static const uint8_t* ConvertAlphaToLuma(Vector& out, +static const uint8_t* ConvertAlphaToLuma(std::vector& out, const uint8_t* in, int width, int height) { int numPixels = width * height; out.resize(numPixels * 2); - uint8_t* dst = out.begin(); - for (auto end = in + numPixels; in != end; ++in) { + auto dst = out.begin(); + for (auto end = in + numPixels; &(*in) != end; ++in) { *dst++ = 255; *dst++ = *in; } - return out.begin(); + return &(*out.begin()); } // Maps a channel count to an OpenGL texture type. @@ -231,7 +232,7 @@ static bool PowerOfTwoTexImage2D(Texture::Format fmt, int w, int h, int px = static_cast(sx); const uint8_t* p1 = - pixels + clamp(py * w + px, 0, maxIndex) * channels; + pixels + std::clamp(py * w + px, 0, maxIndex) * channels; const uint8_t* p2 = p1 + channels; const uint8_t* p3 = p1 + w * channels; const uint8_t* p4 = p3 + channels; @@ -275,7 +276,7 @@ Texture::Data::Data(int inW, int inH, Texture::Format inFmt, VortexCheckGlError(); Format usedFmt = fmt; - Vector tempPixels; + std::vector tempPixels; if (fmt == Texture::ALPHA && !Shader::isSupported()) { pixels = ConvertAlphaToLuma(tempPixels, pixels, inW, inH); usedFmt = Texture::LUMA; @@ -328,7 +329,7 @@ void Texture::Data::modify(int mx, int my, int mw, int mh, const uint8_t* pixels) { if (handle && mx >= 0 && my >= 0 && mx + mw <= w && my + mh <= h) { Format usedFmt = fmt; - Vector tempPixels; + std::vector tempPixels; if (fmt == Texture::ALPHA && !Shader::isSupported()) { pixels = ConvertAlphaToLuma(tempPixels, pixels, mw, mh); usedFmt = Texture::LUMA; @@ -357,7 +358,8 @@ void Texture::Data::increaseHeight(int newHeight) { int channels = sNumChannels[usedFmt]; uint8_t* pixels = static_cast(malloc(w * newHeight * channels)); - memset(pixels + w * h * channels, 0, w * (newHeight - h) * channels); + std::memset(pixels + w * h * channels, 0, + w * (newHeight - h) * channels); glBindTexture(GL_TEXTURE_2D, handle); glGetTexImage(GL_TEXTURE_2D, 0, sFmtGL[usedFmt], GL_UNSIGNED_BYTE, @@ -369,7 +371,7 @@ void Texture::Data::increaseHeight(int newHeight) { glBindTexture(GL_TEXTURE_2D, 0); h = newHeight; - rh = 1.0f / static_cast max(h, 1); + rh = 1.0f / static_cast(std::max(h, 1)); free(pixels); } } @@ -411,11 +413,11 @@ Texture::~Texture() { Texture::Texture() : data_(nullptr) {} Texture::Texture(int w, int h, Format fmt) : data_(nullptr) { - w = max(w, 1); - h = max(h, 1); - Vector pixels; + w = std::max(w, 1); + h = std::max(h, 1); + std::vector pixels; pixels.resize(w * h * sNumChannels[fmt], 0); - data_ = TexMan::load(w, h, fmt, false, pixels.begin()); + data_ = TexMan::load(w, h, fmt, false, &(*pixels.begin())); } Texture::Texture(fs::path path, bool mipmap, Format fmt) : data_(nullptr) { @@ -499,9 +501,9 @@ int Texture::createTiles(fs::path path, int tileW, int tileH, int numTiles, ImageLoader::Data image = ImageLoader::load(path, TexLoadFormats[fmt]); int ch = sNumChannels[fmt]; - Vector pixelData; + std::vector pixelData; pixelData.resize(tileW * tileH * ch, 0); - uint8_t* dst = pixelData.begin(); + uint8_t* dst = &(*pixelData.begin()); int tileIndex = 0; for (int y = 0; y + tileH <= image.height; y += tileH) { @@ -509,8 +511,8 @@ int Texture::createTiles(fs::path path, int tileW, int tileH, int numTiles, if (tileIndex < numTiles) { uint8_t* src = image.pixels + ((y * image.width) + x) * ch; for (int line = 0; line < tileH; ++line) { - memcpy(dst + line * tileW * ch, - src + line * image.width * ch, tileW * ch); + std::memcpy(dst + line * tileW * ch, + src + line * image.width * ch, tileW * ch); } outTiles[tileIndex++] = Texture(tileW, tileH, dst, mipmap, fmt); } @@ -527,9 +529,9 @@ int Texture::createTiles(fs::path path, int tileW, int tileH, int numTiles, ImageLoader::Data image = ImageLoader::load(path, TexLoadFormats[fmt]); int ch = sNumChannels[fmt]; - Vector pixelData; + std::vector pixelData; pixelData.resize(tileW * tileH * ch, 0); - uint8_t* dst = pixelData.begin(); + uint8_t* dst = &(*pixelData.begin()); int tileIndex = 0; for (int y = 0; y + tileH <= image.height; y += tileH) { @@ -537,8 +539,8 @@ int Texture::createTiles(fs::path path, int tileW, int tileH, int numTiles, if (tileIndex < numTiles) { uint8_t* src = image.pixels + ((y * image.width) + x) * ch; for (int line = 0; line < tileH; ++line) { - memcpy(dst + line * tileW * ch, - src + line * image.width * ch, tileW * ch); + std::memcpy(dst + line * tileW * ch, + src + line * image.width * ch, tileW * ch); } outTiles.emplace_back(tileW, tileH, dst, mipmap, fmt); } diff --git a/src/Core/Utils.h b/src/Core/Utils.h index b9ae00c0..55fffaa7 100644 --- a/src/Core/Utils.h +++ b/src/Core/Utils.h @@ -1,9 +1,8 @@ #pragma once -#include - -#include -#include +#include +#include +#include namespace Vortex { @@ -28,20 +27,6 @@ TT inline bool HasLength(const vec2t& v) { return v.x * v.x + v.y * v.y > 0.001f; } -TT inline const T& min(const T& a, const T& b) { return (a < b) ? a : b; } - -TT inline const T& max(const T& a, const T& b) { return (b < a) ? a : b; } - -TT inline const T& clamp(const T& x, const T& min, const T& max) { - return (x < min) ? min : ((max < x) ? max : x); -} - -TT inline void swapValues(T& a, T& b) { - T c(a); - a = b; - b = c; -} - TT inline T lerp(T begin, T end, T t) { return begin + (end - begin) * t; } // ================================================================================================ @@ -63,6 +48,10 @@ TT inline void operator-=(rectt& r, const vec2t& v) { r.x -= v.x, r.y -= v.y; } +TT inline bool IsInside(const rectt& r, const vec2t& v) { + return IsInside(r, v.x, v.y); +} + TT inline bool IsInside(const rectt& r, T x, T y) { return (x >= r.x && y >= r.y && x < r.x + r.w && y < r.y + r.h); } @@ -168,10 +157,12 @@ TT inline rectt ToRect(areat a) { return {a.l, a.t, a.r - a.l, a.b - a.t}; } -TT inline vec2t ToVec2i(const vec2t& v) { return {(int)v.x, (int)v.y}; } +TT inline vec2t ToVec2i(const vec2t& v) { + return {static_cast(v.x), static_cast(v.y)}; +} TT inline vec2t ToVec2f(const vec2t& v) { - return {(float)v.x, (float)v.y}; + return {static_cast(v.x), static_cast(v.y)}; } #undef TT @@ -217,10 +208,10 @@ inline uint32_t ToColor32(const colorf& c) { uint8_t u8[4]; uint32_t u32; }; - u8[0] = (uint8_t)min(max(0, (int)(c.r * 255.0f)), 255); - u8[1] = (uint8_t)min(max(0, (int)(c.g * 255.0f)), 255); - u8[2] = (uint8_t)min(max(0, (int)(c.b * 255.0f)), 255); - u8[3] = (uint8_t)min(max(0, (int)(c.a * 255.0f)), 255); + u8[0] = static_cast(std::clamp(c.r * 255.0f, 0.f, 255.f)); + u8[1] = static_cast(std::clamp(c.g * 255.0f, 0.f, 255.f)); + u8[2] = static_cast(std::clamp(c.b * 255.0f, 0.f, 255.f)); + u8[3] = static_cast(std::clamp(c.a * 255.0f, 0.f, 255.f)); return u32; } @@ -229,26 +220,12 @@ inline uint32_t ToColor32(float r, float g, float b, float a) { uint8_t u8[4]; uint32_t u32; }; - u8[0] = (uint8_t)min(max(0, (int)(r * 255.0f)), 255); - u8[1] = (uint8_t)min(max(0, (int)(g * 255.0f)), 255); - u8[2] = (uint8_t)min(max(0, (int)(b * 255.0f)), 255); - u8[3] = (uint8_t)min(max(0, (int)(a * 255.0f)), 255); + u8[0] = static_cast(std::clamp(r * 255.0f, 0.f, 255.f)); + u8[1] = static_cast(std::clamp(g * 255.0f, 0.f, 255.f)); + u8[2] = static_cast(std::clamp(b * 255.0f, 0.f, 255.f)); + u8[3] = static_cast(std::clamp(a * 255.0f, 0.f, 255.f)); return u32; } - -static int gcd(int a, int b) { - if (a == 0) { - return b; - } - if (b == 0) { - return a; - } - if (a > b) { - return gcd(a - b, b); - } else { - return gcd(a, b - a); - } -} }; // namespace Vortex #undef TT \ No newline at end of file diff --git a/src/Core/Vector.h b/src/Core/Vector.h deleted file mode 100644 index 4e046e4f..00000000 --- a/src/Core/Vector.h +++ /dev/null @@ -1,437 +0,0 @@ -#pragma once - -#include - -#include -#include -#include - -namespace Vortex { - -template -class Vector { - public: - ~Vector(); - Vector(); - Vector(Vector&& v) noexcept; - Vector(const Vector& v); - Vector& operator=(Vector v); - - /// Constructs an empty vector. Reserves memory for the given number of - /// elements. - Vector(int capacity); - - /// Constructs a vector of the given size, with all elements copy - /// constructed from v. - Vector(int size, const T& value); - - /// Constructs a vector from a range of values. - Vector(const T* begin, const T* end); - - /// Sets the vector contents by copying the elements of another vector. - void assign(const Vector& other); - - /// Swaps the contents with another vector. - void swap(Vector& other); - - /// Removes all the elements from the vector. - void clear(); - - /// Removes all elements from the vector and releases the reserved memory. - void release(); - - /// Reduces the capacity to the minimum size required to store all current - /// elements. - void squeeze(); - - /// Reserves memory for the given number of elements. - void reserve(int capacity); - - /// Makes sure the vector contains at least minCount elements. - void grow(int minCount); - - /// Makes sure the vector contains at least minCount elements. - void grow(int minCount, const T& val); - - /// Makes sure the vector contains at most maxCount elements. - void truncate(int maxCount); - - /// Resizes the vector to count elements. - void resize(int count); - - /// Resizes the vector to count elements. - void resize(int count, const T& val); - - /// Appends a default constructed elements and returns a reference to it. - T& append(); - - /// Appends a value to the end of the vector. - void push_back(const T& val); - - /// Appends a value to the end of the vector. - void push_back(T&& val); - - /// Inserts a value at index pos in the vector. - void insert(int pos, const T& val, int num); - - /// Inserts an array of count values at index pos in the vector. - void insert(int pos, const T* val, int count); - - /// Removes the element at index pos from the vector. - void erase(int pos); - - /// Removes all elements with indices in the range [begin, end). - void erase(int begin, int end); - - /// Removes all elements that are equal to value from the vector. - void erase_values(const T& value); - - /// Removes the last element from the vector. - void pop_back(); - - /// Returns true if the vector contains one or more elements that equal - /// value. - bool contains(const T& value) const; - - /// Returns the index of the first element on or after pos that equals - /// value. If no matching element is found, the vector size is returned. - int find(const T& value, int pos = 0) const; - - /// Returns a pointer to the array of elements. - inline T* data() { return data_; } - - /// Returns a const pointer to the array of elements. - inline const T* data() const { return data_; } - - /// Returns a pointer to the first element. - inline T* begin() { return data_; } - - /// Returns a const pointer to the first element. - inline const T* begin() const { return data_; } - - /// Returns a pointer to the past-the-end element. - inline T* end() { return data_ + size_; } - - /// Returns a const pointer to the past-the-end element. - inline const T* end() const { return data_ + size_; } - - /// Returns the final element of the vector; does not perform an - /// out-of-bounds check. To avoid failure, make sure size is non-zero before - /// using this function. - inline T& back() { return data_[size_ - 1]; } - - /// Returns the final element of the vector; does not perform an - /// out-of-bounds check. To avoid failure, make sure size is non-zero before - /// using this function. - inline const T& back() const { return data_[size_ - 1]; } - - /// Returns a reference to the value at index i; does not perform an - /// out-of-bounds check. - inline T& at(int i) { return data_[i]; } - - /// Returns a reference to the value at index i; does not perform an - /// out-of-bounds check. - inline const T& at(int i) const { return data_[i]; } - - /// Returns the current number of elements in the vector. - inline int size() const { return size_; } - - /// Returns true if the vector has a size of zero. - inline bool empty() const { return !size_; } - - /// Return size of allocated storage capacity, expressed in elements. - inline int capacity() const { return capacity_; } - - /// Returns a reference to the value at index i; does not perform an - /// out-of-bounds check. - inline T& operator[](int i) { return data_[i]; } - - /// Returns a const reference to the value at index i; does not perform an - /// out-of-bounds check. - inline const T& operator[](int i) const { return data_[i]; } - - /// Appends a value to the end of the vector. - inline Vector& operator<<(const T& v) { - push_back(v); - return *this; - } - - private: - void EnsureCapacity(int n); - T* data_; - int size_, capacity_; -}; - -// ================================================================================================ -// Anything below this line is used internally and is not part of the API. - -template -Vector::~Vector() { - release(); -} - -template -Vector::Vector() : data_(nullptr), size_(0), capacity_(0) {} - -template -Vector::Vector(int n) : data_(nullptr), size_(0), capacity_(0) { - reserve(n); -} - -template -Vector::Vector(Vector&& v) noexcept - : data_(v.data_), size_(v.size_), capacity_(v.capacity_) { - v.data_ = nullptr; - v.size_ = v.capacity_ = 0; -} - -template -Vector::Vector(const Vector& v) : data_(nullptr), size_(0), capacity_(0) { - assign(v); -} - -template -Vector& Vector::operator=(Vector v) { - swap(v); - return *this; -} - -template -Vector::Vector(int n, const T& v) : data_(nullptr), size_(n), capacity_(0) { - EnsureCapacity(size_); - for (int i = 0; i < n; ++i) new (data_ + i) T(v); -} - -template -Vector::Vector(const T* begin, const T* end) - : data_(nullptr), size_(end - begin), capacity_(0) { - EnsureCapacity(size_); - for (T* p = data_; begin != end; ++begin, ++p) new (p) T(*begin); -} - -template -void Vector::assign(const Vector& o) { - if (this != &o) { - clear(); - size_ = o.size_; - EnsureCapacity(size_); - for (int i = 0; i < size_; ++i) new (data_ + i) T(o.data_[i]); - } -} - -template -void Vector::swap(Vector& o) { - if (this != &o) { - int n = size_; - size_ = o.size_; - o.size_ = n; - int c = capacity_; - capacity_ = o.capacity_; - o.capacity_ = c; - T* p = data_; - data_ = o.data_; - o.data_ = p; - } -} - -template -void Vector::clear() { - for (int i = 0; i < size_; ++i) data_[i].~T(); - size_ = 0; -} - -template -void Vector::release() { - if (data_) { - clear(); - free(data_); - data_ = nullptr; - capacity_ = 0; - } -} - -template -void Vector::squeeze() { - if (size_) { - if (capacity_ > size_) { - T* src = data_; - capacity_ = size_; - data_ = static_cast(malloc(sizeof(T) * capacity_)); - if (data_) { - memcpy(data_, src, size_ * sizeof(T)); - } - free(src); - } - } else - release(); -} - -template -void Vector::reserve(int n) { - if (n > capacity_) { - data_ = static_cast(realloc(data_, sizeof(T) * n)); - capacity_ = n; - } -} - -template -void Vector::grow(int n) { - if (size_ < n) { - EnsureCapacity(n); - for (int i = size_; i < n; ++i) new (data_ + i) T(); - size_ = n; - } -} - -template -void Vector::grow(int n, const T& val) { - if (size_ < n) { - EnsureCapacity(n); - for (int i = size_; i < n; ++i) new (data_ + i) T(val); - size_ = n; - } -} - -template -void Vector::truncate(int n) { - if (size_ > n) { - if (n < 0) n = 0; - for (int i = n; i < size_; ++i) data_[i].~T(); - size_ = n; - } -} - -template -void Vector::resize(int n) { - if (size_ < n) - grow(n); - else - truncate(n); -} - -template -void Vector::resize(int n, const T& val) { - if (size_ < n) { - EnsureCapacity(n); - for (int i = size_; i < n; ++i) new (data_ + i) T(val); - size_ = n; - } else - truncate(n); -} - -template -T& Vector::append() { - if (size_ != capacity_) - new (data_ + size_) T(), ++size_; - else - insert(size_, T(), 1); - return data_[size_ - 1]; -} - -template -void Vector::push_back(const T& v) { - if (size_ != capacity_) - new (data_ + size_) T(v), ++size_; - else - insert(size_, v, 1); -} - -template -void Vector::push_back(T&& v) { - if (size_ != capacity_) - new (data_ + size_) T(v), ++size_; - else - insert(size_, v, 1); -} - -template -void Vector::insert(int i, const T& v, int n) { - if (n <= 0) return; - EnsureCapacity(size_ + n); - if (i >= size_) { - i = size_; - } else { - if (i < 0) i = 0; - memmove(data_ + i + n, data_ + i, sizeof(T) * (size_ - i)); - } - for (int j = 0; j < n; ++j) { - new (data_ + i + j) T(v); - } - size_ += n; -} - -template -void Vector::insert(int i, const T* v, int n) { - if (n <= 0) return; - EnsureCapacity(size_ + n); - if (i >= size_) { - i = size_; - } else { - if (i < 0) i = 0; - memmove(data_ + i + n, data_ + i, sizeof(T) * (size_ - i)); - } - for (int j = 0; j < n; ++j) { - new (data_ + i + j) T(v[j]); - } - size_ += n; -} - -template -void Vector::erase(int i) { - if (i >= 0 && i < size_) { - int end = i + 1; - data_[i].~T(); - memmove(data_ + i, data_ + end, sizeof(T) * (size_ - end)); - --size_; - } -} - -template -void Vector::erase(int begin, int end) { - if (begin < 0) begin = 0; - if (end > size_) end = size_; - if (begin < end) { - for (int i = begin; i < end; ++i) data_[i].~T(); - memmove(data_ + begin, data_ + end, sizeof(T) * (size_ - end)); - size_ -= end - begin; - } -} - -template -void Vector::erase_values(const T& v) { - for (int i = size_ - 1; i >= 0; --i) { - if (data_[i] == v) erase(i); - } -} - -template -void Vector::pop_back() { - if (size_) data_[--size_].~T(); -} - -template -bool Vector::contains(const T& v) const { - return find(v) != size_; -} - -template -int Vector::find(const T& v, int i) const { - while (i < size_ && data_[i] != v) ++i; - return i; -} - -template -void Vector::EnsureCapacity(int n) { - if (capacity_ < n) { - capacity_ <<= 1; - if (capacity_ < n) capacity_ = n; - auto new_data_ = (T*)realloc(data_, sizeof(T) * capacity_); - if (new_data_) { - data_ = new_data_; - } else { - throw std::bad_alloc(); - } - } -} - -}; // namespace Vortex diff --git a/src/Core/VectorUtils.h b/src/Core/VectorUtils.h index 42b6cd6c..fbb1df1a 100644 --- a/src/Core/VectorUtils.h +++ b/src/Core/VectorUtils.h @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace Vortex { @@ -13,16 +13,17 @@ struct Vec { // Destroys all elements in the vector and emtpies the vector. template - static void release(Vector& v) { + static void release(std::vector& v) { for (T* v : v) { delete v; } - v.release(); + v.clear(); } // Erases elements from a vector. Both must be sorted according to compare. template - static void erase(Vector& v, const K* elems, int num, Compare compare) { + static void erase(std::vector& v, const K* elems, int num, + Compare compare) { if (num <= 0) return; // Work forwards, keeping track of a read and write position. @@ -57,7 +58,8 @@ struct Vec { // Inserts elements into a vector. Both must be sorted according to compare. template - static void insert(Vector& v, const K* elems, int num, Compare compare) { + static void insert(std::vector& v, const K* elems, int num, + Compare compare) { if (num <= 0) return; // Make room for the elements that are going to be inserted. @@ -90,8 +92,8 @@ struct Vec { // Erases matching elements from two vectors for which the predicate is // true. Both vectors must be sorted according to compare. template - static void erasePairs(Vector& a, Vector& b, Compare compare, - Predicate pred) { + static void erasePairs(std::vector& a, std::vector& b, + Compare compare, Predicate pred) { for (int i = a.size() - 1, j = b.size() - 1; i >= 0 && j >= 0;) { if (compare(a[i], b[j])) { --j; diff --git a/src/Core/WideString.cpp b/src/Core/WideString.cpp index 9ce5f4db..b03a850d 100644 --- a/src/Core/WideString.cpp +++ b/src/Core/WideString.cpp @@ -7,7 +7,6 @@ #ifdef _WIN32 #include -#endif namespace Vortex { @@ -42,3 +41,5 @@ std::wstring Widen(const char* s) { return Widen(s, strlen(s)); } std::wstring Widen(const std::string& s) { return Widen(s.data(), s.length()); } }; // namespace Vortex + +#endif diff --git a/src/Core/WideString.h b/src/Core/WideString.h index 4b13c51c..a1602cad 100644 --- a/src/Core/WideString.h +++ b/src/Core/WideString.h @@ -2,6 +2,7 @@ #include +#ifdef _WIN32 namespace Vortex { // Converts a wide String (UTF-16) to a string (UTF-8). @@ -15,3 +16,4 @@ extern std::wstring Widen(const char* str); extern std::wstring Widen(const std::string& str); }; // namespace Vortex +#endif diff --git a/src/Core/Widgets.h b/src/Core/Widgets.h index 27e601c7..f8247530 100644 --- a/src/Core/Widgets.h +++ b/src/Core/Widgets.h @@ -1,18 +1,19 @@ #pragma once #include -#include #include #include #include +#include + namespace Vortex { /// Seperator Line GuiWidget. class WgSeperator : public GuiWidget { public: ~WgSeperator(); - WgSeperator(GuiContext* gui); + explicit WgSeperator(GuiContext* gui); void onDraw() override; }; @@ -21,7 +22,7 @@ class WgSeperator : public GuiWidget { class WgLabel : public GuiWidget { public: ~WgLabel(); - WgLabel(GuiContext* gui); + explicit WgLabel(GuiContext* gui); void onDraw() override; @@ -32,7 +33,7 @@ class WgLabel : public GuiWidget { class WgButton : public GuiWidget { public: ~WgButton(); - WgButton(GuiContext* gui); + explicit WgButton(GuiContext* gui); void onMousePress(MousePress& evt) override; void onMouseRelease(MouseRelease& evt) override; @@ -48,7 +49,7 @@ class WgButton : public GuiWidget { class WgCheckbox : public GuiWidget { public: ~WgCheckbox(); - WgCheckbox(GuiContext* gui); + explicit WgCheckbox(GuiContext* gui); void onMousePress(MousePress& evt) override; void onMouseRelease(MouseRelease& evt) override; @@ -66,7 +67,7 @@ class WgCheckbox : public GuiWidget { class WgSlider : public GuiWidget { public: ~WgSlider(); - WgSlider(GuiContext* gui); + explicit WgSlider(GuiContext* gui); void onMousePress(MousePress& evt) override; void onMouseRelease(MouseRelease& evt) override; @@ -89,7 +90,7 @@ class WgSlider : public GuiWidget { class WgScrollbar : public GuiWidget { public: ~WgScrollbar(); - WgScrollbar(GuiContext* gui); + explicit WgScrollbar(GuiContext* gui); void onMousePress(MousePress& evt) override; void onMouseRelease(MouseRelease& evt) override; @@ -107,8 +108,8 @@ class WgScrollbar : public GuiWidget { protected: void ScrollbarUpdateValue(int v); int scrollbar_end_, scrollbar_page_; - uint32_t scrollbar_action_ : 9; - uint32_t scrollbar_grab_position_ : 16; + uint32_t scrollbar_action_ : 9 = 0; + uint32_t scrollbar_grab_position_ : 16 = 0; private: uint32_t GetScrollbarActionAtPosition(int x, int y); @@ -120,7 +121,7 @@ class WgScrollRegion : public GuiWidget { enum ScrollType { SCROLL_ALWAYS, SCROLL_WHEN_NEEDED, SCROLL_NEVER }; ~WgScrollRegion(); - WgScrollRegion(GuiContext* gui); + explicit WgScrollRegion(GuiContext* gui); void onMouseScroll(MouseScroll& evt) override; void onMousePress(MousePress& evt) override; @@ -144,14 +145,14 @@ class WgScrollRegion : public GuiWidget { void PostTick(); void ClampScrollPositions(); - uint32_t scroll_type_horizontal_ : 2; - uint32_t scroll_type_vertical_ : 2; - uint32_t is_horizontal_scrollbar_active_ : 1; - uint32_t is_vertical_scrollbar_active_ : 1; - uint32_t scroll_region_action_ : 9; - uint32_t scroll_region_grab_position_ : 16; - int scroll_width_, scroll_height_; - int scroll_position_x_, scroll_position_y_; + uint32_t scroll_type_horizontal_ : 2 = 0; + uint32_t scroll_type_vertical_ : 2 = 0; + uint32_t is_horizontal_scrollbar_active_ : 1 = 0; + uint32_t is_vertical_scrollbar_active_ : 1 = 0; + uint32_t scroll_region_action_ : 9 = 0; + uint32_t scroll_region_grab_position_ : 16 = 0; + int scroll_width_ = 0, scroll_height_ = 0; + int scroll_position_x_ = 0, scroll_position_y_ = 0; private: uint32_t getScrollRegionActionAt_(int x, int y); @@ -160,14 +161,14 @@ class WgScrollRegion : public GuiWidget { // Vertical Scrollbar GuiWidget. class WgScrollbarV : public WgScrollbar { public: - WgScrollbarV(GuiContext* gui); + explicit WgScrollbarV(GuiContext* gui); bool isVertical() const; }; // Horizontal Scrollbar GuiWidget. class WgScrollbarH : public WgScrollbar { public: - WgScrollbarH(GuiContext* gui); + explicit WgScrollbarH(GuiContext* gui); bool isVertical() const; }; @@ -175,7 +176,7 @@ class WgScrollbarH : public WgScrollbar { class WgSelectList : public GuiWidget { public: ~WgSelectList(); - WgSelectList(GuiContext* gui); + explicit WgSelectList(GuiContext* gui); void onArrange(recti r) override; void onMousePress(MousePress& evt) override; @@ -199,18 +200,18 @@ class WgSelectList : public GuiWidget { bool HasScrollBar() const; recti ItemRect() const; - WgScrollbarV* scrollbar_; - Vector selectlist_items_; - int scroll_position_; - uint32_t is_interacted_ : 1; - uint32_t show_background_ : 1; + WgScrollbarV* scrollbar_ = nullptr; + std::vector selectlist_items_; + int scroll_position_ = 0; + uint32_t is_interacted_ : 1 = 0; + uint32_t show_background_ : 1 = 1; }; /// Vertical Drop Down List GuiWidget. class WgDroplist : public GuiWidget { public: ~WgDroplist(); - WgDroplist(GuiContext* gui); + explicit WgDroplist(GuiContext* gui); void onArrange(recti r) override; void onMousePress(MousePress& evt) override; @@ -229,7 +230,7 @@ class WgDroplist : public GuiWidget { void CloseDroplist(); WgSelectList* selectlist_widget_; - Vector droplist_items_; + std::vector droplist_items_; int selected_index_; }; @@ -237,7 +238,7 @@ class WgDroplist : public GuiWidget { class WgCycleButton : public GuiWidget { public: ~WgCycleButton(); - WgCycleButton(GuiContext* gui); + explicit WgCycleButton(GuiContext* gui); void onMousePress(MousePress& evt) override; void onMouseRelease(MouseRelease& evt) override; @@ -250,14 +251,14 @@ class WgCycleButton : public GuiWidget { CallSlot onChange; protected: - Vector cycle_items_; + std::vector cycle_items_; }; /// Single Line Text Editor GuiWidget. class WgLineEdit : public GuiWidget { public: ~WgLineEdit(); - WgLineEdit(GuiContext* gui); + explicit WgLineEdit(GuiContext* gui); void onKeyPress(KeyPress& evt) override; void onKeyRelease(KeyRelease& evt) override; @@ -290,7 +291,7 @@ class WgLineEdit : public GuiWidget { uint32_t is_numerical_ : 1; uint32_t is_editable_ : 1; uint32_t force_scroll_update_ : 1; - uint32_t lineedit_show_background_ : 1; + uint32_t lineedit_show_background_ : 1 = 1; TextStyle lineedit_style_; }; @@ -298,7 +299,7 @@ class WgLineEdit : public GuiWidget { class WgSpinner : public GuiWidget { public: ~WgSpinner(); - WgSpinner(GuiContext* gui); + explicit WgSpinner(GuiContext* gui); void onArrange(recti r) override; void onMousePress(MousePress& evt) override; @@ -334,7 +335,7 @@ class WgSpinner : public GuiWidget { class WgColorPicker : public GuiWidget { public: ~WgColorPicker(); - WgColorPicker(GuiContext* gui); + explicit WgColorPicker(GuiContext* gui); void onMousePress(MousePress& evt) override; void onMouseRelease(MouseRelease& evt) override; @@ -346,7 +347,7 @@ class WgColorPicker : public GuiWidget { private: struct Expanded; - Expanded* colorpicker_expanded_; + Expanded* colorpicker_expanded_ = nullptr; }; }; // namespace Vortex diff --git a/src/Core/WidgetsColor.cpp b/src/Core/WidgetsColor.cpp index 810aefe9..5a08f101 100644 --- a/src/Core/WidgetsColor.cpp +++ b/src/Core/WidgetsColor.cpp @@ -23,8 +23,8 @@ struct ColorHSV { ColorHSV RGBtoHSV(colorf rgb, float a) { float r = rgb.r, g = rgb.g, b = rgb.b, h, s, v; - float cmax = max(max(r, g), b); - float cmin = min(min(r, g), b); + float cmax = std::max(std::max(r, g), b); + float cmin = std::min(std::min(r, g), b); float delta = cmax - cmin; if (delta > 0) { if (cmax == r) { @@ -142,27 +142,27 @@ void WgColorPicker::Expanded::tick(recti r, GuiContext* gui) { recti view = gui->getView(); - rect_.x = clamp(rect_.x, view.x, view.x + view.w - rect_.w); - rect_.y = clamp(rect_.y, view.y, view.y + view.h - rect_.h); + rect_.x = std::clamp(rect_.x, view.x, view.x + view.w - rect_.w); + rect_.y = std::clamp(rect_.y, view.y, view.y + view.h - rect_.h); vec2i mpos = gui->getMousePos(); if (myDrag == 1) { recti r = getSr(); - myCol.s = - clamp(static_cast(mpos.x - r.x) / static_cast(r.w), - 0.0f, 1.0f); - myCol.v = clamp( + myCol.s = std::clamp( + static_cast(mpos.x - r.x) / static_cast(r.w), 0.0f, + 1.0f); + myCol.v = std::clamp( 1.0f - static_cast(mpos.y - r.y) / static_cast(r.h), 0.0f, 1.0f); } else if (myDrag == 2) { recti r = getHr(); - myCol.h = - clamp(static_cast(mpos.y - r.y) / static_cast(r.h), - 0.0f, 1.0f); + myCol.h = std::clamp( + static_cast(mpos.y - r.y) / static_cast(r.h), 0.0f, + 1.0f); } else if (myDrag == 3) { recti r = getAr(); - myCol.a = clamp( + myCol.a = std::clamp( 1.0f - static_cast(mpos.y - r.y) / static_cast(r.h), 0.0f, 1.0f); } @@ -221,8 +221,7 @@ WgColorPicker::~WgColorPicker() { if (colorpicker_expanded_) delete colorpicker_expanded_; } -WgColorPicker::WgColorPicker(GuiContext* gui) - : GuiWidget(gui), colorpicker_expanded_(nullptr) {} +WgColorPicker::WgColorPicker(GuiContext* gui) : GuiWidget(gui) {} void WgColorPicker::onMousePress(MousePress& evt) { if (colorpicker_expanded_) { @@ -292,7 +291,8 @@ void WgColorPicker::onDraw() { GuiDraw::checkerboard(r, Colors::white); ColorHSV hsv = RGBtoHSV(rgb, rgb.a); - hsv.v = min(1.0f, hsv.v * 0.75f + isMouseOver() * (hsv.v * 0.25f + 0.25f)); + hsv.v = + std::min(1.0f, hsv.v * 0.75f + isMouseOver() * (hsv.v * 0.25f + 0.25f)); Draw::fill(r, ToColor32(HSVtoRGB(hsv, rgb.a))); r = Shrink(r, 1); diff --git a/src/Core/WidgetsLayout.cpp b/src/Core/WidgetsLayout.cpp index 8b502d78..c6acd79b 100644 --- a/src/Core/WidgetsLayout.cpp +++ b/src/Core/WidgetsLayout.cpp @@ -4,6 +4,7 @@ #include +#include #include namespace Vortex { @@ -22,8 +23,8 @@ struct RowLayout::Row { uint32_t expand : 1 = 0; - Vector cols; - Vector widgets; + std::vector cols; + std::vector widgets; }; RowLayout::~RowLayout() { @@ -36,7 +37,7 @@ RowLayout::RowLayout(GuiContext* gui, int spacing) : GuiWidget(gui), row_spacing_(spacing) { Row row; row.cols.push_back({0, 1, 0}); - row_list_.push_back(row); + row_list_.emplace_back(row); } void RowLayout::onUpdateSize() { @@ -46,10 +47,10 @@ void RowLayout::onUpdateSize() { height_ = 0; for (auto& row : row_list_) { - GuiWidget** widget = row.widgets.begin(); + auto widget = row.widgets.begin(); int numWidgets = row.widgets.size(); int numCols = row.cols.size(); - Col* cols = row.cols.begin(); + auto cols = row.cols.begin(); for (int c = 0; c < numCols; ++c) { if (cols[c].adjust) { @@ -69,15 +70,15 @@ void RowLayout::onUpdateSize() { if (*widget) { (*widget)->updateSize(); vec2i size = (*widget)->getSize(); - h = max(h, size.y); + h = std::max(h, size.y); if (cols[c].adjust) { cols[c].width = - max(cols[c].width, static_cast(size.x)); + std::max(cols[c].width, static_cast(size.x)); } } x += cols[c].width; - width_ = max(width_, x); + width_ = std::max(width_, x); x += row_spacing_; } @@ -90,15 +91,15 @@ void RowLayout::onUpdateSize() { void RowLayout::onArrange(recti r) { int y = r.y; - int extraW = max(0, r.w - width_); + int extraW = std::max(0, r.w - width_); for (auto& row : row_list_) { bool expanded = false; - GuiWidget** widget = row.widgets.begin(); + auto widget = row.widgets.begin(); int numWidgets = row.widgets.size(); int numCols = row.cols.size(); - Col* cols = row.cols.begin(); + auto cols = row.cols.begin(); int h = 0, x = r.x; for (int i = 0, c = 0; i < numWidgets; ++i, ++c, ++widget) { @@ -117,7 +118,7 @@ void RowLayout::onArrange(recti r) { if (*widget) { vec2i size = (*widget)->getSize(); (*widget)->arrange({x, y, colW, size.y}); - h = max(h, size.y); + h = std::max(h, size.y); } x += cols[c].width + row_spacing_; @@ -138,17 +139,18 @@ void RowLayout::onDraw() { } void RowLayout::add(GuiWidget* widget) { - widget_list_.push_back(widget); - row_list_.back().widgets.push_back(widget); + widget_list_.emplace_back(widget); + row_list_.back().widgets.emplace_back(widget); } -void RowLayout::addBlank() { row_list_.back().widgets.push_back(nullptr); } +void RowLayout::addBlank() { row_list_.back().widgets.emplace_back(nullptr); } RowLayout& RowLayout::row(bool expand) { if (row_list_.back().widgets.empty()) row_list_.pop_back(); - Row& row = row_list_.append(); - row.expand = (expand == true); + Row new_row = {}; + new_row.expand = expand; + row_list_.emplace_back(new_row); return *this; } @@ -156,17 +158,21 @@ RowLayout& RowLayout::row(bool expand) { RowLayout& RowLayout::col(bool expand) { return col(INT_MAX, expand); } RowLayout& RowLayout::col(int w, bool expand) { - Col& col = row_list_.back().cols.append(); - col.width = - (w == INT_MAX) ? 0 : static_cast(w * gSystem->getScaleFactor()); - col.adjust = (w == INT_MAX); - col.expand = (expand == true); - + auto& cols = row_list_.back().cols; + cols.push_back({(w == INT_MAX) + ? 0 + : static_cast(w * gSystem->getScaleFactor()), + w == INT_MAX, expand == true}); + Col& col = cols.back(); return *this; } -GuiWidget** RowLayout::begin() { return widget_list_.begin(); } +std::vector::const_iterator RowLayout::begin() { + return widget_list_.begin(); +} -GuiWidget** RowLayout::end() { return widget_list_.end(); } +std::vector::const_iterator RowLayout::end() { + return widget_list_.end(); +} }; // namespace Vortex diff --git a/src/Core/WidgetsLayout.h b/src/Core/WidgetsLayout.h index 040bec85..20d2ace6 100644 --- a/src/Core/WidgetsLayout.h +++ b/src/Core/WidgetsLayout.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include namespace Vortex { @@ -23,8 +23,8 @@ class RowLayout : public GuiWidget { RowLayout& col(bool expand = false); RowLayout& col(int w, bool expand = false); - GuiWidget** begin(); - GuiWidget** end(); + std::vector::const_iterator begin(); + std::vector::const_iterator end(); template T* add() { @@ -51,8 +51,8 @@ class RowLayout : public GuiWidget { struct Row; struct Col; - Vector row_list_; - Vector widget_list_; + std::vector row_list_; + std::vector widget_list_; int row_spacing_; }; diff --git a/src/Core/WidgetsScroll.cpp b/src/Core/WidgetsScroll.cpp index 6505ad04..a7dd0340 100644 --- a/src/Core/WidgetsScroll.cpp +++ b/src/Core/WidgetsScroll.cpp @@ -36,12 +36,12 @@ static ScrollButtonData GetButton(int size, int end, int page, int scroll) { if (end > page) { out.size = static_cast(0.5 + size * static_cast(page) / static_cast(end)); - out.size = max(16, out.size); + out.size = std::max(16, out.size); out.pos = static_cast( 0.5 + scroll * static_cast(size - out.size) / static_cast(end - page)); - out.pos = max(0, min(out.pos, size - out.size)); + out.pos = std::max(0, std::min(out.pos, size - out.size)); } return out; } @@ -53,7 +53,7 @@ static int GetScroll(int size, int end, int page, int pos) { out = static_cast(0.5 + pos * static_cast(end - page) / static_cast(size - button.size)); - out = max(0, min(out, end - page)); + out = std::max(0, std::min(out, end - page)); } return out; } @@ -86,9 +86,9 @@ static void DrawScrollbar(recti bar, ScrollButtonData button, bool vertical, } void ApplyScrollOffset(int& offset, int page, int scroll, bool up) { - int delta = max(1, page / 8); + int delta = std::max(1, page / 8); if (up) delta = -delta; - offset = max(0, min(offset + delta, scroll - page)); + offset = std::max(0, std::min(offset + delta, scroll - page)); } }; // anonymous namespace. @@ -98,8 +98,7 @@ void ApplyScrollOffset(int& offset, int page, int scroll, bool up) { WgScrollbar::~WgScrollbar() = default; -WgScrollbar::WgScrollbar(GuiContext* gui) - : GuiWidget(gui), scrollbar_action_(0), scrollbar_grab_position_(0) { +WgScrollbar::WgScrollbar(GuiContext* gui) : GuiWidget(gui) { scrollbar_end_ = 1; scrollbar_page_ = 1; } @@ -171,7 +170,7 @@ void WgScrollbar::onDraw() { void WgScrollbar::ScrollbarUpdateValue(int v) { double prev = value.get(); - v = max(0, min(scrollbar_end_, v)); + v = std::max(0, std::min(scrollbar_end_, v)); value.set(v); if (value.get() != prev) onChange.call(); } @@ -215,18 +214,7 @@ static const int SCROLLBAR_SIZE = 14; WgScrollRegion::~WgScrollRegion() = default; -WgScrollRegion::WgScrollRegion(GuiContext* gui) - : GuiWidget(gui), - scroll_type_horizontal_(0), - scroll_type_vertical_(0), - is_horizontal_scrollbar_active_(0), - is_vertical_scrollbar_active_(0), - scroll_region_action_(0), - scroll_region_grab_position_(0), - scroll_width_(0), - scroll_height_(0), - scroll_position_x_(0), - scroll_position_y_(0) {} +WgScrollRegion::WgScrollRegion(GuiContext* gui) : GuiWidget(gui) {} void WgScrollRegion::onMouseScroll(MouseScroll& evt) { if (is_vertical_scrollbar_active_) { @@ -304,9 +292,13 @@ void WgScrollRegion::setScrollType(ScrollType h, ScrollType v) { scroll_type_vertical_ = v; } -void WgScrollRegion::setScrollW(int width) { scroll_width_ = max(0, width); } +void WgScrollRegion::setScrollW(int width) { + scroll_width_ = std::max(0, width); +} -void WgScrollRegion::setScrollH(int height) { scroll_height_ = max(0, height); } +void WgScrollRegion::setScrollH(int height) { + scroll_height_ = std::max(0, height); +} int WgScrollRegion::getViewWidth() const { return rect_.w - is_vertical_scrollbar_active_ * SCROLLBAR_SIZE; @@ -387,10 +379,10 @@ uint32_t WgScrollRegion::getScrollRegionActionAt_(int x, int y) { } void WgScrollRegion::ClampScrollPositions() { - scroll_position_x_ = - max(0, min(scroll_position_x_, scroll_width_ - getViewWidth())); - scroll_position_y_ = - max(0, min(scroll_position_y_, scroll_height_ - getViewHeight())); + scroll_position_x_ = std::max( + 0, std::min(scroll_position_x_, scroll_width_ - getViewWidth())); + scroll_position_y_ = std::max( + 0, std::min(scroll_position_y_, scroll_height_ - getViewHeight())); } }; // namespace Vortex diff --git a/src/Core/WidgetsSelect.cpp b/src/Core/WidgetsSelect.cpp index 4764a12c..8df6bb3e 100644 --- a/src/Core/WidgetsSelect.cpp +++ b/src/Core/WidgetsSelect.cpp @@ -21,11 +21,7 @@ WgSelectList::~WgSelectList() { delete scrollbar_; } -WgSelectList::WgSelectList(GuiContext* gui) - : GuiWidget(gui), - scroll_position_(0), - is_interacted_(0), - show_background_(1) { +WgSelectList::WgSelectList(GuiContext* gui) : GuiWidget(gui) { scrollbar_ = new WgScrollbarV(gui_); scrollbar_->value.bind(&scroll_position_); } @@ -33,7 +29,7 @@ WgSelectList::WgSelectList(GuiContext* gui) void WgSelectList::hideBackground() { show_background_ = 0; } void WgSelectList::addItem(const std::string& text) { - selectlist_items_.push_back(text); + selectlist_items_.emplace_back(text); } void WgSelectList::clearItems() { selectlist_items_.clear(); } @@ -74,7 +70,7 @@ void WgSelectList::scroll(bool up) { if (HasScrollBar()) { int end = selectlist_items_.size() * ITEM_H - ItemRect().h; int delta = up ? -ITEM_H : ITEM_H; - scroll_position_ = min(max(scroll_position_ + delta, 0), end); + scroll_position_ = std::clamp(scroll_position_ + delta, 0, end); } } @@ -187,7 +183,7 @@ void WgDroplist::onMousePress(MousePress& evt) { int numItems = droplist_items_.size(); if (isEnabled() && numItems && evt.button == Mouse::LMB && evt.unhandled()) { - int h = min( + int h = std::min( numItems * static_cast(18 * gSystem->getScaleFactor()) + 8, static_cast(128 * gSystem->getScaleFactor())); recti r = {rect_.x, rect_.y + rect_.h, rect_.w, h}; @@ -289,7 +285,7 @@ void WgDroplist::onDraw() { void WgDroplist::clearItems() { droplist_items_.clear(); } void WgDroplist::addItem(const std::string& text) { - droplist_items_.push_back(text); + droplist_items_.emplace_back(text); } void WgDroplist::CloseDroplist() { @@ -308,7 +304,7 @@ WgCycleButton::~WgCycleButton() { clearItems(); } WgCycleButton::WgCycleButton(GuiContext* gui) : GuiWidget(gui) {} void WgCycleButton::addItem(const std::string& text) { - cycle_items_.push_back(text); + cycle_items_.emplace_back(text); } void WgCycleButton::clearItems() { cycle_items_.clear(); } diff --git a/src/Core/WidgetsSimple.cpp b/src/Core/WidgetsSimple.cpp index 9a8154d1..0dc2041f 100644 --- a/src/Core/WidgetsSimple.cpp +++ b/src/Core/WidgetsSimple.cpp @@ -204,8 +204,8 @@ void WgSlider::onDraw() { int boxX = static_cast(static_cast(bar.w) * (value.get() - slider_begin_) / (slider_end_ - slider_begin_)); - recti box = {bar.x + min(max(boxX, 0), bar.w) - 4, bar.y - bar_size / 2, - bar_size / 2, bar_size}; + recti box = {bar.x + std::clamp(boxX, 0, bar.w) - 4, + bar.y - bar_size / 2, bar_size / 2, bar_size}; button.base.draw(box, 0); if (isCapturingMouse()) { @@ -218,15 +218,15 @@ void WgSlider::onDraw() { void WgSlider::SliderUpdateValue(double v) { double prev = value.get(); - v = min(v, max(slider_begin_, slider_end_)); - v = max(v, min(slider_begin_, slider_end_)); + v = std::min(v, std::max(slider_begin_, slider_end_)); + v = std::max(v, std::min(slider_begin_, slider_end_)); value.set(v); if (value.get() != prev) onChange.call(); } void WgSlider::SliderDrag(int x, int y) { recti r = rect_; - r.w = max(r.w, 1); + r.w = std::max(r.w, 1); double val = slider_begin_ + (slider_end_ - slider_begin_) * (static_cast(x - r.x) / static_cast(r.w)); diff --git a/src/Core/WidgetsText.cpp b/src/Core/WidgetsText.cpp index 8202c111..58b178c1 100644 --- a/src/Core/WidgetsText.cpp +++ b/src/Core/WidgetsText.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -30,8 +31,7 @@ enum LineEditDragType { WgLineEdit::~WgLineEdit() = default; -WgLineEdit::WgLineEdit(GuiContext* gui) - : GuiWidget(gui), lineedit_show_background_(1) { +WgLineEdit::WgLineEdit(GuiContext* gui) : GuiWidget(gui) { lineedit_max_length_ = MaximumTextBoxLength; lineedit_blink_time_ = 0.f; lineedit_scroll_offset_ = 0.f; @@ -66,7 +66,7 @@ void WgLineEdit::onKeyPress(KeyPress& evt) { GuiMain::setClipboardText(std::string()); } else { int a = lineedit_cursor_.x, b = lineedit_cursor_.y; - if (a > b) swapValues(a, b); + if (a > b) std::swap(a, b); std::string substring(lineedit_text_.data() + a, b - a); GuiMain::setClipboardText(substring.c_str()); if (key == Key::X) DeleteSection(); @@ -94,8 +94,8 @@ void WgLineEdit::onKeyPress(KeyPress& evt) { if (key == Key::END) cx = cy = static_cast(lineedit_text_.length()); if (cx != cy) { - if (key == Key::LEFT) cx = cy = min(cx, cy); - if (key == Key::RIGHT) cx = cy = max(cx, cy); + if (key == Key::LEFT) cx = cy = std::min(cx, cy); + if (key == Key::RIGHT) cx = cy = std::max(cx, cy); } else { if (key == Key::LEFT) cx = cy = Str::prevChar(lineedit_text_, cy); if (key == Key::RIGHT) cx = cy = Str::nextChar(lineedit_text_, cy); @@ -116,8 +116,8 @@ void WgLineEdit::onKeyPress(KeyPress& evt) { } int len = static_cast(lineedit_text_.length()); - lineedit_cursor_.x = clamp(lineedit_cursor_.x, 0, len); - lineedit_cursor_.y = clamp(lineedit_cursor_.y, 0, len); + lineedit_cursor_.x = std::clamp(lineedit_cursor_.x, 0, len); + lineedit_cursor_.y = std::clamp(lineedit_cursor_.y, 0, len); } void WgLineEdit::onKeyRelease(KeyRelease& evt) { @@ -238,10 +238,10 @@ void WgLineEdit::onTick() { Text::getCharIndex(vec2i{tp.x, tp.y}, {mp.x, tp.y}); lineedit_blink_time_ = 0.f; } - lineedit_cursor_.x = min(max(lineedit_cursor_.x, 0), - static_cast(lineedit_text_.length())); - lineedit_cursor_.y = min(max(lineedit_cursor_.y, 0), - static_cast(lineedit_text_.length())); + lineedit_cursor_.x = std::clamp(lineedit_cursor_.x, 0, + static_cast(lineedit_text_.length())); + lineedit_cursor_.y = std::clamp(lineedit_cursor_.y, 0, + static_cast(lineedit_text_.length())); // Update text offset @@ -250,15 +250,15 @@ void WgLineEdit::onTick() { float textW = static_cast(Text::getSize().x); float cursorX = static_cast( Text::getCursorPos(vec2i{0, 0}, lineedit_cursor_.y).x); - float target = min(max(lineedit_scroll_offset_, cursorX - barW + SPINNER_W), - cursorX - SPINNER_W); - target = max(0.f, min(target, textW - barW)); + float target = std::clamp(lineedit_scroll_offset_, + cursorX - barW + SPINNER_W, cursorX - SPINNER_W); + target = std::clamp(target, 0.f, std::max(0.f, textW - barW)); - float delta = - max(fabs(lineedit_scroll_offset_ - target) * 10.f * dt, dt * 256.f); + float delta = std::max(fabs(lineedit_scroll_offset_ - target) * 10.f * dt, + dt * 256.f); float smooth = (lineedit_scroll_offset_ < target) - ? min(lineedit_scroll_offset_ + delta, target) - : max(lineedit_scroll_offset_ - delta, target); + ? std::min(lineedit_scroll_offset_ + delta, target) + : std::max(lineedit_scroll_offset_ - delta, target); lineedit_scroll_offset_ = force_scroll_update_ ? target : smooth; force_scroll_update_ = false; @@ -292,7 +292,7 @@ void WgLineEdit::onDraw() { int cx = Text::getEscapedCharIndex(str, lineedit_cursor_.x); int cy = Text::getEscapedCharIndex(str, lineedit_cursor_.y); - if (cx > cy) swapValues(cx, cy); + if (cx > cy) std::swap(cx, cy); Str::insert(hlstr, cy, "{tc}{bc}{sc}"); Str::insert(hlstr, cx, "{tc:000F}{bc:FFFF}{sc:0000}"); @@ -323,7 +323,7 @@ void WgLineEdit::onDraw() { void WgLineEdit::hideBackground() { lineedit_show_background_ = 0; } -void WgLineEdit::setMaxLength(int n) { lineedit_max_length_ = max(0, n); } +void WgLineEdit::setMaxLength(int n) { lineedit_max_length_ = std::max(0, n); } void WgLineEdit::setNumerical(bool numerical) { is_numerical_ = numerical; } @@ -344,7 +344,7 @@ void WgLineEdit::setFocus() { void WgLineEdit::DeleteSection() { if (is_editable_ && lineedit_cursor_.x != lineedit_cursor_.y) { if (lineedit_cursor_.x > lineedit_cursor_.y) - swapValues(lineedit_cursor_.x, lineedit_cursor_.y); + std::swap(lineedit_cursor_.x, lineedit_cursor_.y); Str::erase(lineedit_text_, lineedit_cursor_.x, lineedit_cursor_.y - lineedit_cursor_.x); lineedit_cursor_.y = lineedit_cursor_.x; @@ -508,7 +508,7 @@ void WgSpinner::setFocus() { void WgSpinner::SpinnerUpdateValue(double v) { double prev = value.get(); - value.set(max(spinner_min_, min(spinner_max_, v))); + value.set(std::max(spinner_min_, std::min(spinner_max_, v))); SpinnerUpdateText(); if (value.get() != prev) onChange.call(); } diff --git a/src/Core/Xmr.cpp b/src/Core/Xmr.cpp index a8c8d975..e47f75e0 100644 --- a/src/Core/Xmr.cpp +++ b/src/Core/Xmr.cpp @@ -46,13 +46,17 @@ class xstring { void append(const char* str) { append(str, strlen(str)); } void append(long v) { char buf[32]; - int n = sprintf_s(buf, 32, "%i", v); +#ifdef _WIN32 + int n = std::snprintf(buf, 32, "%i", v); +#else + int n = std::snprintf(buf, 32, "%li", v); +#endif if (n < 0) n = 32; append(buf, n); } void append(double v) { char buf[32]; - int n = sprintf_s(buf, 32, "%f", v); + int n = std::snprintf(buf, 32, "%f", v); if (n < 0) n = 32; if (memchr(buf, '.', n)) { while (n > 0 && buf[n - 1] == '0') --n; @@ -67,8 +71,6 @@ class xstring { // ================================================================================================ // Utility functions. -static const char* NO_ERROR = "no error"; - static const char* EMPTY_ERROR_STRING = ""; // Valid chars: space, horizontal tab, carriage return, line feed. @@ -474,13 +476,7 @@ static void WriteComment(xstring& out, const char* str) { // ============================================================================================================= // XmrSaveSettings -XmrSaveSettings::XmrSaveSettings() - : headerComment(nullptr), - useTabsInsteadOfSpaces(false), - quoteNodes(XMR_QUOTE_WHEN_NECESSARY), - quoteNames(XMR_QUOTE_WHEN_NECESSARY), - quoteValues(XMR_QUOTE_WHEN_NECESSARY), - spacesPerIndent(2) {} +XmrSaveSettings::XmrSaveSettings() = default; // ============================================================================================================= // XmrAttrib @@ -783,7 +779,7 @@ XmrDoc::~XmrDoc() { clear(); } -XmrDoc::XmrDoc() : lastError(NO_ERROR) { +XmrDoc::XmrDoc() { name = "root"; attribPtr = nullptr; childPtr = nextPtr = nullptr; diff --git a/src/Core/Xmr.h b/src/Core/Xmr.h index 5b1d43e6..dab4cb0f 100644 --- a/src/Core/Xmr.h +++ b/src/Core/Xmr.h @@ -6,6 +6,8 @@ namespace fs = std::filesystem; namespace Vortex { +static const char* NO_ERROR = "no error"; + /// For-loop macro to iterate over node attributes. /// it: name of iterator, node: pointer to root node. #define ForXmrAttribs(it, node) \ @@ -54,12 +56,15 @@ enum XmrQuoteSetting { // Save settings, used when saving XMR documents. struct XmrSaveSettings { XmrSaveSettings(); - const char* headerComment; ///< Default is nullptr. - bool useTabsInsteadOfSpaces; ///< Default is false. - XmrQuoteSetting quoteNodes; ///< Default is XMR_QUOTE_WHEN_NECESSARY. - XmrQuoteSetting quoteNames; ///< Default is XMR_QUOTE_WHEN_NECESSARY. - XmrQuoteSetting quoteValues; ///< Default is XMR_QUOTE_WHEN_NECESSARY. - int spacesPerIndent; ///< Default is 2. + const char* headerComment = nullptr; ///< Default is nullptr. + bool useTabsInsteadOfSpaces = false; ///< Default is false. + XmrQuoteSetting quoteNodes = + XMR_QUOTE_WHEN_NECESSARY; ///< Default is XMR_QUOTE_WHEN_NECESSARY. + XmrQuoteSetting quoteNames = + XMR_QUOTE_WHEN_NECESSARY; ///< Default is XMR_QUOTE_WHEN_NECESSARY. + XmrQuoteSetting quoteValues = + XMR_QUOTE_WHEN_NECESSARY; ///< Default is XMR_QUOTE_WHEN_NECESSARY. + int spacesPerIndent = 2; ///< Default is 2. }; /// XmrAttrib contains the name and value of an XMR attribute. @@ -195,7 +200,7 @@ struct XmrDoc : public XmrNode { std::string saveString(XmrSaveSettings settings); /// Description of the last occured error. - const char* lastError; + const char* lastError = NO_ERROR; }; }; // namespace Vortex diff --git a/src/Dialogs/AdjustSync.cpp b/src/Dialogs/AdjustSync.cpp index 906b11c8..1b0b3313 100755 --- a/src/Dialogs/AdjustSync.cpp +++ b/src/Dialogs/AdjustSync.cpp @@ -33,12 +33,7 @@ enum Actions { DialogAdjustSync::~DialogAdjustSync() { delete myTempoDetector; } -DialogAdjustSync::DialogAdjustSync() - : mySelectedResult(0), - myOffset(0), - myInitialBPM(0), - myTempoDetector(nullptr), - myDetectionRow(0) { +DialogAdjustSync::DialogAdjustSync() { setTitle("ADJUST SYNC"); myCreateWidgets(); onChanges(VCM_ALL_CHANGES); @@ -162,7 +157,7 @@ void DialogAdjustSync::onTick() { Str::fmt fmt("#%1 :: %2 BPM :: %3%"); fmt.arg(i + 1).arg(t.bpm, 2, 2).arg(t.fitness * 100, 0, 0); - myBPMList->addItem(fmt); + myBPMList->addItem(static_cast(fmt)); } if (myDetectionResults.size() == 0) { myBPMList->addItem("- no results found -"); diff --git a/src/Dialogs/AdjustSync.h b/src/Dialogs/AdjustSync.h index d8860cf8..305d7523 100644 --- a/src/Dialogs/AdjustSync.h +++ b/src/Dialogs/AdjustSync.h @@ -7,6 +7,8 @@ #include +#include + namespace Vortex { class DialogAdjustSync : public EditorDialog { @@ -28,14 +30,14 @@ class DialogAdjustSync : public EditorDialog { void myResetBPMDetection(); - int mySelectedResult; - double myOffset, myInitialBPM; + int mySelectedResult = 0; + double myOffset = 0.0, myInitialBPM = 0.0; WgLabel* myBPMLabel; WgButton *myApplyBPM, *myFindBPM; WgSelectList* myBPMList; - TempoDetector* myTempoDetector; - Vector myDetectionResults; - int myDetectionRow; + TempoDetector* myTempoDetector = nullptr; + std::vector myDetectionResults; + int myDetectionRow = 0; }; }; // namespace Vortex diff --git a/src/Dialogs/AdjustTempoSM5.cpp b/src/Dialogs/AdjustTempoSM5.cpp index b74af456..577b266e 100644 --- a/src/Dialogs/AdjustTempoSM5.cpp +++ b/src/Dialogs/AdjustTempoSM5.cpp @@ -15,6 +15,8 @@ #include #include +#include + namespace Vortex { enum Actions { @@ -225,38 +227,39 @@ void DialogAdjustTempoSM5::onAction(int id) { gTempo->addSegment(Delay(row, myDelay)); } break; case ACT_WARP_SET: { - int rows = max(0, static_cast(ROWS_PER_BEAT * myWarp)); + int rows = std::max(0, static_cast(ROWS_PER_BEAT * myWarp)); gTempo->addSegment(Warp(row, rows)); } break; case ACT_TIME_SIG_SET: { - int rowsPerMeasure = ROWS_PER_BEAT * max(1, myTimeSigBpm); - int beatNote = max(1, myTimeSigNote); + int rowsPerMeasure = ROWS_PER_BEAT * std::max(1, myTimeSigBpm); + int beatNote = std::max(1, myTimeSigNote); gTempo->addSegment(TimeSignature(row, rowsPerMeasure, beatNote)); } break; case ACT_TICK_COUNT_SET: { - int ticks = max(0, myTickCount); + int ticks = std::max(0, myTickCount); gTempo->addSegment(TickCount(row, ticks)); } break; case ACT_COMBO_SET: { - int hit = max(1, myComboHit); - int miss = max(1, myComboMiss); + int hit = std::max(1, myComboHit); + int miss = std::max(1, myComboMiss); gTempo->addSegment(Combo(row, hit, miss)); } break; case ACT_SPEED_SET: { double ratio = mySpeedRatio; - double delay = max(0.0, mySpeedDelay); - int unit = clamp(mySpeedUnit, 0, 1); + double delay = std::max(0.0, mySpeedDelay); + int unit = std::clamp(mySpeedUnit, 0, 1); gTempo->addSegment(Speed(row, ratio, delay, unit)); } break; case ACT_SCROLL_SET: { gTempo->addSegment(Scroll(row, myScrollRatio)); } break; case ACT_FAKE_SET: { - int rows = max(0, static_cast(ROWS_PER_BEAT * myFakeBeats)); + int rows = + std::max(0, static_cast(ROWS_PER_BEAT * myFakeBeats)); gTempo->addSegment(Fake(row, rows)); } break; case ACT_LABEL_SET: { - if (strpbrk(myLabelText.c_str(), ";,=") != nullptr) { + if (std::strpbrk(myLabelText.c_str(), ";,=") != nullptr) { HudWarning( "A Label cannot contain commas, semicolons, or equal " "signs; they will be replaced with underscores."); diff --git a/src/Dialogs/ChartList.cpp b/src/Dialogs/ChartList.cpp index 843f5a01..215e659b 100644 --- a/src/Dialogs/ChartList.cpp +++ b/src/Dialogs/ChartList.cpp @@ -63,7 +63,7 @@ struct DialogChartList::ChartButton : public GuiWidget { const Chart* chart = gSimfile->getChart(myChartIndex); if (chart) { // Draw the left-side colored bar with difficulty and meter. - recti left = {rect_.x, rect_.y, min(r.w, w), TEXT_H}; + recti left = {rect_.x, rect_.y, std::min(r.w, w), TEXT_H}; uint32_t color = ToColor(chart->difficulty); myBar->draw(left, 0, color); @@ -116,11 +116,11 @@ static int GetChartListH() { } h += TEXT_H + 1; } - return max(TEXT_H, h); + return std::max(TEXT_H, h); } struct DialogChartList::ChartList : public WgScrollRegion { - Vector myButtons; + std::vector myButtons; TileRect2 myButtonTex; ~ChartList() override { @@ -209,7 +209,7 @@ struct DialogChartList::ChartList : public WgScrollRegion { void updateButtons() { int numCharts = gSimfile->getNumCharts(); while (myButtons.size() < numCharts) { - myButtons.push_back( + myButtons.emplace_back( new ChartButton(getGui(), &myButtonTex, myButtons.size())); } while (myButtons.size() > numCharts) { @@ -243,8 +243,8 @@ void DialogChartList::onChanges(int changes) { if (changes & VCM_CHART_LIST_CHANGED) { myList->updateButtons(); int h = GetChartListH(); - h = min(h, getGui()->getView().h - 128); - h = max(h, static_cast(gSystem->getScaleFactor() * 32)); + h = std::min(h, getGui()->getView().h - 128); + h = std::max(h, static_cast(gSystem->getScaleFactor() * 32)); setHeight(h); } } @@ -252,8 +252,8 @@ void DialogChartList::onChanges(int changes) { void DialogChartList::onUpdateSize() { myList->updateSize(); int h = myList->getScrollHeight(); - setMinimumHeight(min(64, h)); - setMaximumHeight(min(1024, h)); + setMinimumHeight(std::min(64, h)); + setMaximumHeight(std::min(1024, h)); } void DialogChartList::onTick() { diff --git a/src/Dialogs/ChartProperties.cpp b/src/Dialogs/ChartProperties.cpp index c0ec6e38..780f06dc 100755 --- a/src/Dialogs/ChartProperties.cpp +++ b/src/Dialogs/ChartProperties.cpp @@ -17,6 +17,7 @@ #include #include +#include namespace Vortex { @@ -40,8 +41,7 @@ static const char* noteItemLabels[] = {"steps", "jumps", "mines", DialogChartProperties::~DialogChartProperties() = default; -DialogChartProperties::DialogChartProperties() - : myDifficulty(0), myRating(1), myStyle(0) { +DialogChartProperties::DialogChartProperties() { setTitle("CHART PROPERTIES"); myCreateChartProperties(); @@ -209,8 +209,9 @@ void DialogChartProperties::myUpdateNoteInfo() { double density = 0.0; if (gNotes->begin() < gNotes->end()) { - density = static_cast(gNotes->getNumJudge()) / - max(1.0, (gNotes->end() - 1)->time - gNotes->begin()->time); + density = + static_cast(gNotes->getNumJudge()) / + std::max(1.0, (gNotes->end() - 1)->time - gNotes->begin()->time); } myNoteDensity->text.set( @@ -290,7 +291,7 @@ void DialogChartProperties::GraphWidget::updateGraph() { } endMeasure = (gSimfile->getEndRow() - 1) / (ROWS_PER_BEAT * 4) + 1; endTime = gTempo->rowToTime(gSimfile->getEndRow()); - scale = endMeasure / width_; + scale = endMeasure / static_cast(width_ * gSystem->getScaleFactor()); if (scale < 1) scale = 1; int buckets = endMeasure; peak = 0; @@ -315,8 +316,9 @@ void DialogChartProperties::GraphWidget::updateGraph() { notes += data[i + slices]; slices++; } - peak = max(peak, static_cast(notes / (measure_time(i + slices) - - measure_time(i)))); + peak = std::max( + peak, static_cast( + notes / (measure_time(i + slices) - measure_time(i)))); } } void DialogChartProperties::GraphWidget::onDraw() { @@ -331,9 +333,10 @@ void DialogChartProperties::GraphWidget::onDraw() { Draw::fill(rect_, Color32(20, 20, 20, 255)); return; } + int scale_width = static_cast(width_ * gSystem->getScaleFactor()); endTime = gTempo->rowToTime(gSimfile->getEndRow()); int buckets = data.size(); - double barWidth = (static_cast(width_) / buckets); + double barWidth = (static_cast(scale_width) / buckets); int w = barWidth + 1; auto batch = Renderer::batchC(); Draw::fill(rect_, Color32(20, 20, 20, 255)); @@ -341,9 +344,10 @@ void DialogChartProperties::GraphWidget::onDraw() { for (int i = 0; i < buckets; i += slices) { slices = 1; - int x = rect_.x + static_cast(measure_time(i) / endTime * width_); + int x = + rect_.x + static_cast(measure_time(i) / endTime * scale_width); int notes = data[i]; - while (delta_measure_time(i, slices + 1) <= endTime / width_ && + while (delta_measure_time(i, slices + 1) <= endTime / scale_width && // Averaging looks bad beyond 30 seconds delta_measure_time(i, slices + 1) <= 30.f && i + slices < buckets) { @@ -352,15 +356,16 @@ void DialogChartProperties::GraphWidget::onDraw() { } int h = std::min( height_, - static_cast( - round(notes / delta_measure_time(i, slices) / peak * height_))); + static_cast(std::round(notes / delta_measure_time(i, slices) / + peak * height_))); w = rect_.x + - static_cast(measure_time(i + slices) / endTime * width_) - x; + static_cast(measure_time(i + slices) / endTime * scale_width) - + x; int y = rect_.y + height_ - h; Draw::fill(&batch, {x, y, w, h}, Color32(80, 80, 80, 255)); } - double time = min(endTime, gView->getCursorTime()); - int x = static_cast(time / endTime * width_); + double time = std::min(endTime, gView->getCursorTime()); + int x = static_cast(time / endTime * scale_width); Draw::fill(&batch, {rect_.x + x, rect_.y, 1, height_}, Color32(160, 160, 160, 255)); batch.flush(); @@ -399,7 +404,7 @@ class DialogChartProperties::BreakdownWidget : public GuiWidget { private: DialogChartProperties* myDialog; - Vector myButtons; + std::vector myButtons; }; DialogChartProperties::BreakdownWidget::~BreakdownWidget() { @@ -419,10 +424,10 @@ void DialogChartProperties::BreakdownWidget::updateBreakdown( auto& item = breakdown[i]; Text::arrange(Text::TL, TextStyle(), item.text.c_str()); - int w = max(16, Text::getSize().x + 8); + int w = std::max(16, Text::getSize().x + 8); if (i >= myButtons.size()) { - myButtons.push_back(new WgButton(getGui())); + myButtons.emplace_back(new WgButton(getGui())); } WgButton* button = myButtons[i]; @@ -509,7 +514,7 @@ void DialogChartProperties::myUpdateBreakdown() { } void DialogChartProperties::myCopyBreakdown() { - auto breakdown = gChart->getStreamBreakdown(); + auto breakdown = gChart->getStreamBreakdown(nullptr); if (breakdown.empty()) { HudInfo("%s", "There is no breakdown to copy..."); } else { diff --git a/src/Dialogs/ChartProperties.h b/src/Dialogs/ChartProperties.h index c16e6fa0..1bdc6661 100644 --- a/src/Dialogs/ChartProperties.h +++ b/src/Dialogs/ChartProperties.h @@ -2,7 +2,7 @@ #include -#include +#include namespace Vortex { @@ -44,7 +44,7 @@ class DialogChartProperties : public EditorDialog { WgDroplist* myStyleList; std::string myStepArtist; - int myRating, myDifficulty, myStyle; + int myRating = 1, myDifficulty = 0, myStyle = 0; }; }; // namespace Vortex diff --git a/src/Dialogs/DancingBot.cpp b/src/Dialogs/DancingBot.cpp index b55d51c3..0d96606f 100644 --- a/src/Dialogs/DancingBot.cpp +++ b/src/Dialogs/DancingBot.cpp @@ -308,8 +308,8 @@ void DialogDancingBot::onUpdateSize() { int w = 200, h = 64; auto style = gStyle->get(); if (style && style->padWidth > 0) { - w = max(w, style->padWidth * 64 + 8); - h = max(h, style->padHeight * 64 + 24); + w = std::max(w, style->padWidth * 64 + 8); + h = std::max(h, style->padHeight * 64 + 24); } w = static_cast(w * gSystem->getScaleFactor()); h = static_cast(h * gSystem->getScaleFactor()); @@ -349,8 +349,8 @@ void DialogDancingBot::onDraw() { for (int col = 0; col < prevNotes.size(); ++col) { auto n = prevNotes[col]; double dist = n ? (time - n->endtime) : 1000.0; - int alpha = - min(max(static_cast((1.5 - dist * 6.0) * 255.0), 0), 255); + int alpha = std::min( + std::max(static_cast((1.5 - dist * 6.0) * 255.0), 0), 255); if (alpha > 0) { vec2i pos = myGetDrawPos(style->padColPositions[col]); myPadSpr[2].draw(&batch, pos.x, pos.y, @@ -376,7 +376,7 @@ void DialogDancingBot::onDraw() { float rotation = 0.f; if (abs(l.x - r.x) + abs(l.y - r.y) > 0.1f) { rotation = atan2(r.y - l.y, r.x - l.x); - rotation = min(max(rotation, -0.8f), 0.8f); + rotation = std::clamp(rotation, -0.8f, 0.8f); } // Draw the feet. @@ -396,7 +396,7 @@ void DialogDancingBot::onChanges(int changes) { if (changes & VCM_CHART_CHANGED) { auto style = gStyle->get(); if (style == nullptr || style->padWidth == 0 || style->padHeight == 0) { - myPadLayout.release(); + myPadLayout.clear(); } else { // Copy the layout of the buttons. myPadLayout.resize(style->padWidth * style->padHeight); @@ -437,7 +437,7 @@ vec2i DialogDancingBot::myGetDrawPos(vec2i colRow) { } void DialogDancingBot::myAssignFeetToNotes() { - myFeetBits.release(); + myFeetBits.clear(); int numNotes = gNotes->end() - gNotes->begin(); auto style = gStyle->get(); if (numNotes > 0 && style && style->padWidth > 0) { @@ -507,15 +507,16 @@ void DialogDancingBot::myGetFeetPositions(vec3f* out, int pn) { vec2f curPos = ToVec2f(myGetDrawPos(curButton)); vec2f endPos = ToVec2f(myGetDrawPos(endButton)); if (endtime > curTime) { - double startTime = max(curTime, endtime - 0.5); + double startTime = std::max(curTime, endtime - 0.5); double delta = LerpDelta(startTime, endtime, time); - curPos = SmoothStep(curPos, endPos, - static_cast(min(max(delta, 0.0), 1.0))); + curPos = + SmoothStep(curPos, endPos, + static_cast(std::clamp(delta, 0.0, 1.0))); } // Determine feet scale. - double dt = min(fabs(curTime - time), fabs(endtime - time)); - float scale = static_cast(min(1.0, 0.8 + dt * 6.0)); + double dt = std::min(fabs(curTime - time), fabs(endtime - time)); + float scale = static_cast(std::min(1.0, 0.8 + dt * 6.0)); out[f] = {curPos.x, curPos.y, scale}; } diff --git a/src/Dialogs/DancingBot.h b/src/Dialogs/DancingBot.h index 5db3585d..86725a51 100644 --- a/src/Dialogs/DancingBot.h +++ b/src/Dialogs/DancingBot.h @@ -4,9 +4,10 @@ #include #include -#include #include +#include + namespace Vortex { class DialogDancingBot : public EditorDialog { @@ -31,8 +32,8 @@ class DialogDancingBot : public EditorDialog { void myAssignFeetToNotes(); void myGetFeetPositions(vec3f* out, int player); - Vector myPadLayout; - Vector myFeetBits; + std::vector myPadLayout; + std::vector myFeetBits; BatchSprite myPadSpr[6]; BatchSprite myFeetSpr[2]; Texture myPadTex, myFeetTex; diff --git a/src/Dialogs/Dialog.h b/src/Dialogs/Dialog.h index 61f5cede..bb3fbe7f 100644 --- a/src/Dialogs/Dialog.h +++ b/src/Dialogs/Dialog.h @@ -3,6 +3,8 @@ #include #include +#include + namespace Vortex { struct WidgetMapping { diff --git a/src/Dialogs/EditSegment.cpp b/src/Dialogs/EditSegment.cpp index 2e5a28cc..7abf2d73 100644 --- a/src/Dialogs/EditSegment.cpp +++ b/src/Dialogs/EditSegment.cpp @@ -235,7 +235,7 @@ void WarpEditor::onTick() { } void WarpEditor::onChange(int id) { - int numRows = max(0, static_cast(ROWS_PER_BEAT * myBeats)); + int numRows = std::max(0, static_cast(ROWS_PER_BEAT * myBeats)); switch (id) { HALVE(ACT_HALVE, numRows); DOUBLE(ACT_DOUBLE, numRows); @@ -309,8 +309,8 @@ void TimeSignatureEditor::onTick() { } void TimeSignatureEditor::onChange(int id) { - int rowsPerMeasure = ROWS_PER_BEAT * max(1, myRowsPerMeasure); - int beatNote = max(1, myBeatNote); + int rowsPerMeasure = ROWS_PER_BEAT * std::max(1, myRowsPerMeasure); + int beatNote = std::max(1, myBeatNote); switch (id) { HALVE(ACT_HALVE, rowsPerMeasure); DOUBLE(ACT_DOUBLE, rowsPerMeasure); @@ -363,7 +363,7 @@ void TickCountEditor::onTick() { } void TickCountEditor::onChange(int id) { - int ticks = max(0, myTicks); + int ticks = std::max(0, myTicks); switch (id) { HALVE(ACT_HALVE, ticks); DOUBLE(ACT_DOUBLE, ticks); @@ -436,8 +436,8 @@ void ComboEditor::onTick() { } void ComboEditor::onChange(int id) { - int hit = max(1, myHit); - int miss = max(1, myMiss); + int hit = std::max(1, myHit); + int miss = std::max(1, myMiss); switch (id) { HALVE(ACT_HALVE, hit); DOUBLE(ACT_DOUBLE, hit); @@ -525,8 +525,8 @@ void SpeedEditor::onTick() { void SpeedEditor::onChange(int id) { double ratio = myRatio; - double delay = max(0.0, myDelay); - int unit = clamp(myUnit, 0, 1); + double delay = std::max(0.0, myDelay); + int unit = std::clamp(myUnit, 0, 1); switch (id) { HALVE(ACT_HALVE, ratio); DOUBLE(ACT_DOUBLE, ratio); @@ -630,7 +630,7 @@ void FakeEditor::onTick() { } void FakeEditor::onChange(int id) { - int numRows = max(0, static_cast(ROWS_PER_BEAT * myBeats)); + int numRows = std::max(0, static_cast(ROWS_PER_BEAT * myBeats)); switch (id) { HALVE(ACT_HALVE, numRows); DOUBLE(ACT_DOUBLE, numRows); @@ -725,7 +725,7 @@ static std::string createTitle(Segment::Type type) { DialogEditSegment::~DialogEditSegment() = default; -DialogEditSegment::DialogEditSegment() : myType(Segment::BPM) { +DialogEditSegment::DialogEditSegment() { setMinimumHeight(HEIGHT_1_ROW); setMinimumWidth(FULL); setPinnable(false); diff --git a/src/Dialogs/EditSegment.h b/src/Dialogs/EditSegment.h index 4324b477..9dce3fe0 100644 --- a/src/Dialogs/EditSegment.h +++ b/src/Dialogs/EditSegment.h @@ -180,7 +180,7 @@ class DialogEditSegment : public EditorDialog, public InputHandler { private: void myCreateWidgets(); - Segment::Type myType; + Segment::Type myType = Segment::Type::BPM; std::unique_ptr myEditor; }; diff --git a/src/Dialogs/GenerateNotes.cpp b/src/Dialogs/GenerateNotes.cpp index 2282eff4..6bb97bc1 100755 --- a/src/Dialogs/GenerateNotes.cpp +++ b/src/Dialogs/GenerateNotes.cpp @@ -26,8 +26,7 @@ static const int IFP_SPACING = 4; DialogGenerateNotes::~DialogGenerateNotes() = default; -DialogGenerateNotes::DialogGenerateNotes() - : footSelectionIndex_(0), spacingValue_(0) { +DialogGenerateNotes::DialogGenerateNotes() { setTitle("GENERATE NOTES"); myCreateWidgets(); } @@ -82,7 +81,7 @@ void DialogGenerateNotes::onChanges(int changes) { int w = 180; auto style = gStyle->get(); if (style && style->padWidth > 0) { - w = max(w, gStyle->getNumCols() * (IFP_SIZE + IFP_SPACING)); + w = std::max(w, gStyle->getNumCols() * (IFP_SIZE + IFP_SPACING)); streamGenerator_.feetCols = style->padInitialFeetCols[0]; } } diff --git a/src/Dialogs/GenerateNotes.h b/src/Dialogs/GenerateNotes.h index 4cfa3aaf..f06b0800 100644 --- a/src/Dialogs/GenerateNotes.h +++ b/src/Dialogs/GenerateNotes.h @@ -20,8 +20,8 @@ class DialogGenerateNotes : public EditorDialog, public InputHandler { StreamGenerator streamGenerator_; WgDroplist* spacingDroplist_; - int footSelectionIndex_; - int spacingValue_; + int footSelectionIndex_ = 0; + int spacingValue_ = 0; }; }; // namespace Vortex diff --git a/src/Dialogs/LabelBreakdown.cpp b/src/Dialogs/LabelBreakdown.cpp index 1892595c..529f6fd7 100644 --- a/src/Dialogs/LabelBreakdown.cpp +++ b/src/Dialogs/LabelBreakdown.cpp @@ -13,6 +13,8 @@ #include +#include + #define ITEM_H static_cast(20 * gSystem->getScaleFactor()) #define ITEM_W static_cast(74 * gSystem->getScaleFactor()) @@ -94,7 +96,7 @@ struct DialogLabelBreakdown::LabelButton : public GuiWidget { // LabelList struct DialogLabelBreakdown::LabelList : public WgScrollRegion { - Vector myButtons; + std::vector myButtons; TileRect2 myButtonTex; int myDisplayType; @@ -123,8 +125,9 @@ struct DialogLabelBreakdown::LabelList : public WgScrollRegion { } void onUpdateSize() override { - scroll_height_ = max(static_cast(24 * gSystem->getScaleFactor()), - myButtons.size() * (ITEM_H + 1)); + scroll_height_ = + std::max(static_cast(24 * gSystem->getScaleFactor()), + static_cast(myButtons.size() * (ITEM_H + 1))); ClampScrollPositions(); } @@ -183,7 +186,7 @@ struct DialogLabelBreakdown::LabelList : public WgScrollRegion { while (seg != segEnd) { std::string time = displayTime(seg->row); std::string text = segs->getRow