diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 0cbb993..9e6ed48 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1,24 +1,33 @@ name: Nightly build on: [ push, pull_request ] +# set env (global) variables +env: + ndkname: android-ndk-r22 + jobs: build: + # We will use this OS runs-on: ubuntu-latest - strategy: - matrix: - target: ["Release", "Debug"] - + # building a mod consists of a few steps steps: + + # Downloads and installs Android NDK - uses: actions/checkout@v2 + name: Checkout NDK with: - fetch-depth: 0 - - name: Setup NDK - id: setup-ndk - uses: nttld/setup-ndk@v1.0.3 - with: - ndk-version: r22b + submodules: recursive + lfs: true + - # Copied from sc2ad :) + # create the ndkpath.txt file needed in our own compile scripts + - name: Create ndkpath.txt + run: | + echo "$ANDROID_NDK_LATEST_HOME" > ${GITHUB_WORKSPACE}/ndkpath.txt + cat ${GITHUB_WORKSPACE}/ndkpath.txt + + + # Downloads QPM package for Beat Saber for Quest Development - name: Get QPM uses: dawidd6/action-download-artifact@v2 with: @@ -27,10 +36,16 @@ jobs: name: QPM-ubuntu-x64 path: QPM repo: sc2ad/QuestPackageManager + + + # Collect dependencies and print them to console - name: QPM Collect run: | chmod +x ./QPM/QPM ./QPM/QPM collect + + + # Accelerates QPM restore - name: QPM Dependencies Cache id: cache-qpm-deps uses: actions/cache@v2 @@ -43,27 +58,93 @@ jobs: ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- + + + # Restore and resolve all dependencies from the package - name: QPM Restore run: ./QPM/QPM restore + + + # Step added for workflow debugging - name: List Post Restore run: | ls -la ${GITHUB_WORKSPACE}/extern/ ls -la QPM_Temp - - name: Build for ${{ matrix.target }} - run: ./build.sh - env: - ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} - CI_BUILD_TARGET: ${{ matrix.target }} - - name: Package for ${{ matrix.target }} - run: ./release-qmod.sh - env: - ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} - CI_BUILD_TARGET: ${{ matrix.target }} - - name: Upload Artifacts + + # Step added for workflow debugging + - name: List Pre Build + run: | + ls -la ${GITHUB_WORKSPACE}/ + + + # Creates the release and debug library binary files + - name: Build Binary + shell: pwsh + run: ./build.ps1 + + + # Creates the QMOD package release file + - name: Create QMOD Package + shell: pwsh + run: ./buildQMOD.ps1 + + + # Step added for workflow debugging + - name: List Post Build + run: | + ls -la ${GITHUB_WORKSPACE}/ + ls -la ${GITHUB_WORKSPACE}/libs/arm64-v8a/ + ls -la ${GITHUB_WORKSPACE}/obj/local/arm64-v8a/ + + + # get the library name from mod.json + - name: Get Library Filename + id: libname + shell: pwsh + run: | + $mod = "./mod.json" + $modJson = Get-Content $mod -Raw | ConvertFrom-Json + $libname = "lib" + $modJson.id.ToLower() + ".so" + echo "::set-output name=NAME::$libname" + + + # get the qmod package name mod.json + - name: Get QMOD Package Filename + id: qmodname + shell: pwsh + run: | + $mod = "./mod.json" + $modJson = Get-Content $mod -Raw | ConvertFrom-Json + $qmodname = $modJson.id + "-v" + $modJson.version + ".qmod" + echo "::set-output name=NAME::$qmodname" + + + #uploads the normal .so binary as artifact + - name: Upload Release Lib Artifact + uses: actions/upload-artifact@v2 + with: + name: ${{ steps.libname.outputs.NAME }} + path: ./libs/arm64-v8a/${{ steps.libname.outputs.NAME }} + # if not found error obviously + if-no-files-found: error + + + #uploads the debug .so binary as artifact + - name: Upload Debug Artifact + uses: actions/upload-artifact@v2 + with: + name: debug_${{ steps.libname.outputs.NAME }} + path: ./obj/local/arm64-v8a/${{ steps.libname.outputs.NAME }} + # if not found error obviously + if-no-files-found: error + + + # uploads the qmod package as artifact + - name: Upload qmod artifact uses: actions/upload-artifact@v2 with: - name: ParticleTuner.${{ matrix.target }} - path: | - *.qmod + name: ${{ steps.qmodname.outputs.NAME }} + path: ./${{ steps.qmodname.outputs.NAME }} + # if not found error obviously if-no-files-found: error diff --git a/.gitignore b/.gitignore index 8eedb8f..1f84f58 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,9 @@ libs/ obj/ Android.mk.backup qpm.shared.json -ParticleTuner.zip .idea cmake-build-debug -ParticleTuner.qmod -ParticleTuner.*.qmod +*.qmod +*.backup +*.so +ndkpath.txt diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 69d3417..4b33a70 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -4,7 +4,7 @@ "defines": [ "__GNUC__", "__aarch64__", - "VERSION=\"1.3.0\"", + "VERSION=\"1.17.1\"", "ID=\"particletuner\"" ], "includePath": [ diff --git a/Android.mk b/Android.mk index 418241b..29a03d7 100644 --- a/Android.mk +++ b/Android.mk @@ -3,35 +3,39 @@ TARGET_ARCH_ABI := $(APP_ABI) rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)) -# Creating prebuilt for dependency: beatsaber-hook - version: 2.2.5 +# Creating prebuilt for dependency: beatsaber-hook include $(CLEAR_VARS) -LOCAL_MODULE := beatsaber-hook_2_2_5 +LOCAL_MODULE := beatsaber-hook_$(BSHOOK) LOCAL_EXPORT_C_INCLUDES := extern/beatsaber-hook -LOCAL_SRC_FILES := extern/libbeatsaber-hook_2_2_5.so +LOCAL_SRC_FILES := extern/libbeatsaber-hook_$(BSHOOK).so LOCAL_CPP_FEATURES += exceptions include $(PREBUILT_SHARED_LIBRARY) -# Creating prebuilt for dependency: modloader - version: 1.2.3 + +# Creating prebuilt for dependency: modloader include $(CLEAR_VARS) LOCAL_MODULE := modloader LOCAL_EXPORT_C_INCLUDES := extern/modloader LOCAL_SRC_FILES := extern/libmodloader.so LOCAL_CPP_FEATURES += exceptions include $(PREBUILT_SHARED_LIBRARY) -# Creating prebuilt for dependency: custom-types - version: 0.12.6 + +# Creating prebuilt for dependency: custom-types include $(CLEAR_VARS) LOCAL_MODULE := custom-types LOCAL_EXPORT_C_INCLUDES := extern/custom-types LOCAL_SRC_FILES := extern/libcustom-types.so LOCAL_CPP_FEATURES += exceptions include $(PREBUILT_SHARED_LIBRARY) -# Creating prebuilt for dependency: codegen - version: 0.12.5 + +# Creating prebuilt for dependency: codegen include $(CLEAR_VARS) -LOCAL_MODULE := codegen_0_12_5 +LOCAL_MODULE := codegen LOCAL_EXPORT_C_INCLUDES := extern/codegen -LOCAL_SRC_FILES := extern/libcodegen_0_12_5.so +LOCAL_SRC_FILES := extern/libcodegen.so LOCAL_CPP_FEATURES += exceptions include $(PREBUILT_SHARED_LIBRARY) -# Creating prebuilt for dependency: questui - version: 0.10.2 + +# Creating prebuilt for dependency: questui include $(CLEAR_VARS) LOCAL_MODULE := questui LOCAL_EXPORT_C_INCLUDES := extern/questui @@ -39,19 +43,27 @@ LOCAL_SRC_FILES := extern/libquestui.so LOCAL_CPP_FEATURES += exceptions include $(PREBUILT_SHARED_LIBRARY) +# Creating main build include $(CLEAR_VARS) -LOCAL_MODULE := particletuner +LOCAL_MODULE := "$(LIBNAME)" LOCAL_SRC_FILES += $(call rwildcard,src/,*.cpp) LOCAL_SRC_FILES += $(call rwildcard,extern/beatsaber-hook/src/inline-hook/,*.cpp) LOCAL_SRC_FILES += $(call rwildcard,extern/beatsaber-hook/src/inline-hook/,*.c) -LOCAL_SHARED_LIBRARIES += beatsaber-hook_2_2_5 +LOCAL_CFLAGS += -DVERSION='"$(VERSION)"' +LOCAL_CFLAGS += -DID='"$(MODID)"' +LOCAL_CFLAGS += -isystem 'extern/libil2cpp/il2cpp/libil2cpp' +LOCAL_CPPFLAGS += -std=c++2a -frtti +LOCAL_CPP_FEATURES += exceptions +LOCAL_LDLIBS += -llog +LOCAL_SHARED_LIBRARIES += beatsaber-hook_$(BSHOOK) LOCAL_SHARED_LIBRARIES += modloader LOCAL_SHARED_LIBRARIES += custom-types LOCAL_SHARED_LIBRARIES += questui -LOCAL_SHARED_LIBRARIES += codegen_0_12_5 -LOCAL_LDLIBS += -llog -LOCAL_CFLAGS += -DVERSION='"1.3.0"' -DID='"particletuner"' -isystem 'extern/libil2cpp/il2cpp/libil2cpp' -LOCAL_CPPFLAGS += -std=c++2a -frtti -LOCAL_C_INCLUDES += ./include ./src ./shared ./extern ./extern/beatsaber-hook/shared ./extern/modloader/shared ./extern/questui/shared ./extern/custom-types/shared ./extern/codegen/include -LOCAL_CPP_FEATURES += exceptions +LOCAL_SHARED_LIBRARIES += codegen +LOCAL_C_INCLUDES += ./include ./src ./shared ./extern +LOCAL_C_INCLUDES += ./extern/codegen/shared ./extern/codegen/include +LOCAL_C_INCLUDES += ./extern/beatsaber-hook/shared ./extern/beatsaber-hook/include +LOCAL_C_INCLUDES += ./extern/modloader/shared ./extern/modloader/include +LOCAL_C_INCLUDES += ./extern/questui/shared ./extern/questui/include +LOCAL_C_INCLUDES += ./extern/custom-types/shared ./extern/custom-types/include include $(BUILD_SHARED_LIBRARY) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c8ec17b --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2018, Jack Baron + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md index a4d65b8..96d2ea9 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,19 @@ Quest ParticleTuner ![cover](./cover.gif) -A partial port of the [ParticleOverdrive mod](https://github.com/Shadnix-was-taken/BeatSaber-ParticleOverdrive/commit/68f8eeb9100a88606faabdd875520654993fbcbc) from PC. +A partial port of the [ParticleOverdrive mod](https://github.com/Shadnix-was-taken/BeatSaber-ParticleOverdrive/commit/68f8eeb9100a88606faabdd875520654993fbcbc) from PC. Coded by [Marcus Zhou](https://github.com/SuperMarcus) for Beat Saber v1.16.4 and updated to BSQ 1.17.1 by [Mioki](https://github.com/okibcn) with fixed rainbow particles and speed optimizations. + +## Features + +* De/Activate Core particles +* De/Activate Clash effects +* De/Activate ambiend dust +* De/Activate Rainbow sparkles + +* customizable amount of sparkles +* customizable amount of explosion particles +* customizable lengh of effects explosions and sparkles +* customizable transparency of explosions and sparkles ## Settings diff --git a/bmbfmod.json b/bmbfmod.json index bad616f..dbd0d3e 100644 --- a/bmbfmod.json +++ b/bmbfmod.json @@ -1,14 +1,14 @@ { "id": "particletuner", "name": "Particles", - "version": "1.3.0", + "version": "1.17.1", "author": "marcuszhou", "description": [ "Boost or reduce note-cutting and environmental particle effects. QuestParticles is a port of the ParticleOverdrive mod from PC to the Quest." ], "coverImageFilename": "cover.gif", "category": "Gameplay", - "gameVersion": "1.13.2", + "gameVersion": "1.17.1", "links": { "project-home": "https://github.com/SuperMarcus/QuestParticleTuner" }, @@ -26,7 +26,7 @@ { "type": "HookModLibrary", "installAction": { - "installLibraryFile": "libbeatsaber-hook_1_3_3.so" + "installLibraryFile": "libbeatsaber-hook_2_3_0.so" } } ] diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..be5db62 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,93 @@ +# ██████╗ ██╗ ██╗██╗██╗ ██████╗ +# ██╔══██╗██║ ██║██║██║ ██╔══██╗ +# ██████╔╝██║ ██║██║██║ ██║ ██║ +# ██╔══██╗██║ ██║██║██║ ██║ ██║ +# ██████╔╝╚██████╔╝██║███████╗██████╔╝ + + + +if(!(Test-Path ./ndkpath.txt)){ + Write-Host "Please create the ndkpath.txt file with the path to the Android NDK." + exit +} +$NDKPath = Get-Content ./ndkpath.txt -First 1 + + +# Get Mod data from QPM.JSON +echo "Reading QMOD data from qpm.json" +$qpmJson = Get-Content ./qpm.json -raw | ConvertFrom-Json +$modID = $qpmJson.info.id +$modName = $qpmJson.info.name +$ver = $qpmJson.info.version +$buildlevel = (Get-Date -format "yyMMdd") +$Version = $ver + "-" + (Get-Date -format "yyMMdd") +$numDependencies = $qpmJson.dependencies.Count +for ($i = 0; $i -lt $numDependencies; $i++) { + $dep = $qpmJson.dependencies[$i] + if ($dep.id -eq "beatsaber-hook") { + $BSHook = $qpmJson.dependencies[$i].versionRange + break + } +} +$modfile = "lib" + $modID.ToLower() + ".so" +$BSHookfile = "libbeatsaber-hook_" + $BSHook.Replace(".", "_") + ".so" +$qmodfile = $modID + "-v" + $Version + ".qmod" + +echo "Mod name: $modName" +echo "Mod ID: $modID" +echo "Mod version: $ver" +echo "Mod build: $buildlevel" +echo "BS-Hook version: $BSHook" +echo "Mod lib file: $modfile" +echo "BS-Hook file: $BSHookfile" +echo "Qmod file: $qmodfile" +echo "" + +# Injects changes in MOD.JSON +echo "Updating mod.json..." +$modJson = Get-Content ./mod.json -raw | ConvertFrom-Json +$modJson.id = $modID +$modJson.name = $modName +$modJson.version = $Version +$numDependencies = $modJson.libraryFiles.Count +for ($i = 0; $i -lt $numDependencies; $i++) { + $lib = $modJson.libraryFiles[$i] + $pos = $lib.IndexOf("libbeatsaber-hook") + if ($pos -ge 0) { + $modJson.libraryFiles[$i] = $BSHookfile + break + } +} +$modJson | ConvertTo-Json -depth 32 | Set-Content ./mod.json +echo "mod.json updated." + + +if ((Test-Path "./extern/beatsaber-hook/src/inline-hook/And64InlineHook.cpp", "./extern/beatsaber-hook/src/inline-hook/inlineHook.c", "./extern/beatsaber-hook/src/inline-hook/relocate.c") -contains $false) { + Write-Host "Critical: Missing inline-hook" + if (!(Test-Path "./extern/beatsaber-hook/src/inline-hook/And64InlineHook.cpp")) { + Write-Host "./extern/beatsaber-hook/src/inline-hook/And64InlineHook.cpp" + } + if (!(Test-Path "./extern/beatsaber-hook/src/inline-hook/inlineHook.c")) { + Write-Host "./extern/beatsaber-hook/src/inline-hook/inlineHook.c" + } + if (!(Test-Path "./extern/beatsaber-hook/inline-hook/src/relocate.c")) { + Write-Host "./extern/beatsaber-hook/src/inline-hook/relocate.c" + } + Write-Host "Task Failed" + exit 1; +} + + +$buildScript = "$NDKPath/build/ndk-build" +if (-not ($PSVersionTable.PSEdition -eq "Core")) { + $buildScript += ".cmd" +} + +$modlib = $modID.ToLower() +$BSHook = $BSHook.Replace(".", "_") +# Read-Host "ready to build $modfile. Press ENTER key to continue..." +echo "Building $modfile Version: $Version ..." +& $buildScript NDK_DEBUG=0 NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk NDK_APPLICATION_MK=./Application.mk VERSION=$Version MODID=$modID LIBNAME=$modLib BSHOOK=$BSHook -Oline +Write-Host "Build complete." +Write-Host "Debug lib file: ./obj/local/arm64-v8a/$modfile" +Write-Host "Release lib file: ./libs/arm64-v8a/$modfile" \ No newline at end of file diff --git a/buildQMOD.ps1 b/buildQMOD.ps1 new file mode 100644 index 0000000..33e3ed0 --- /dev/null +++ b/buildQMOD.ps1 @@ -0,0 +1,91 @@ +$mod = "./mod.json" +$modJson = Get-Content $mod -Raw | ConvertFrom-Json + +$env:qmodName = $modJson.name +$env:module_id = $modJson.id +$qmodVersion = $modJson.version + +$qmod = $env:qmodName + "-v" + $qmodVersion + ".qmod" + + +$allLibs = Get-ChildItem ./libs/arm64-v8a/*.so | Select -Expand Name + +$cover = "./" + $modJson.coverImage + +$fileList = @($cover, $mod) + +$bannedLibList = "libmodloader.so libquestui.so libcodegen.so libcustom-types.so" + +# Creates the list of Modfiles and Library files +$modlib = @() +$libs = @() +foreach ($lib in $allLibs) { + if (!($bannedLibList.Contains($lib))) { + $path = "./libs/arm64-v8a/" + $lib; + $fileList += , $path; + if ($lib.Contains($env:module_id.ToLower())){ + $modlib += , $lib; + } + else { + $libs += , $lib + + } + } +} + + +$extraFiles = @() +if (Test-Path "./ExtraFiles") { + $extraEntries = Get-ChildItem ./ExtraFiles/* -Recurse + + foreach ($entry in $extraEntries) { + $mode = $entry | Select -Expand Mode + if ($mode.Contains("d")) { + continue + } + + # if not a dir + if (-not $entry.Directory.Name.Contains("ExtraFiles")) { + $dir = $entry.Directory + $folderPath = $dir.Name + "/" + $entry.Name + while (($dir.Directory) -and (-not $dir.Directory.Name.Contains("ExtraFiles"))) { + $folderPath = $dir.Directory.Name + "/" + $folderPath + } + + if ($folderPath.Contains("Icons")) { + continue; + } + $extraFiles += , $folderPath + } + else { + $extraFiles += , $entry.Name + } + } + + foreach ($file in $extraFiles) { + $path = "./ExtraFiles/" + $file + $fileList += , $path + } +} +else { + echo "No ExtraFiles Directory Found" +} + +# add the thing to the libs list because we don't need it as a mod file +$modJson.modFiles = $modlib +$modJson.libraryFiles = $libs + +$modText = $modJson | ConvertTo-Json -depth 32 +echo $modText +Set-Content $mod $modText + +# if the qmod exists, rename it to zip to update it, we'll rename it back later +if (Test-Path $qmod) { + Remove-Item -Force $qmod +} +$msg = "Creating qmod for module " + $env:module_id + " With name " + $qmod +echo $msg +echo $fileList +Compress-Archive -Path $fileList -DestinationPath ./temp.zip +& move-item -Force ./temp.zip $qmod +echo "Task Completed" diff --git a/copy.ps1 b/copy.ps1 new file mode 100644 index 0000000..885c496 --- /dev/null +++ b/copy.ps1 @@ -0,0 +1,10 @@ +& $PSScriptRoot/build.ps1 +if ($?) { + adb push libs/arm64-v8a/lib#{id}.so /sdcard/Android/data/com.beatgames.beatsaber/files/mods/lib#{id}.so + if ($?) { + & $PSScriptRoot/restart-game.ps1 + if ($args[0] -eq "--log") { + & $PSScriptRoot/start-logging.ps1 + } + } +} diff --git a/include/Config.hpp b/include/Config.hpp index 5b5ef08..a394c98 100644 --- a/include/Config.hpp +++ b/include/Config.hpp @@ -8,13 +8,13 @@ #define PT_DEFAULT_LIFETIME_MULTIPLIER 1.0 #define PT_DEFAULT_PARTICLE_OPACITY 0.5 -#define PT_PRESET_NONE { "None", 0.0, 0.0, 0.0, 0.0, true, true, true, false, false } -#define PT_PRESET_NORMAL { "Normal", 1.0, 1.0, 1.0, 0.5, false, false, false, false, false } -#define PT_PRESET_FANCY { "Fancy", 5.0, 5.0, 2.0, 1.0, false, false, false, true, true } -#define PT_PRESET_TOO_MUCH { "Too Much", 100.0, 100.0, 10.0, 1.0, false, false, false, true, true } +#define PT_PRESET_NONE { "None", 0.0, 0.0, 0.0, 0.0, true, true, true, false } +#define PT_PRESET_NORMAL { "Normal", 1.0, 1.0, 1.0, 0.5, false, false, false, false } +#define PT_PRESET_FANCY { "Fantasy", 12.0, 0.1, 5.0, 1.0, false, false, true, true } +#define PT_PRESET_TOO_MUCH { "Insane", 100.0, 10.0, 10.0, 1.0, false, false, false, true } #define PT_NUMBER_OF_PRESETS 4 -#define PT_DISCOVERY_MAX_ITERATIONS 5 +#define PT_DISCOVERY_MAX_ITERATIONS 5 struct PTPreset { std::string name; @@ -22,10 +22,10 @@ struct PTPreset { float explosionMultiplier; float lifetimeMultiplier; float particleOpacity; + bool reduceCoreParticles; bool reduceClashParticles; bool reduceDustParticles; - bool boostSaturation; bool rainbowParticles; }; @@ -40,7 +40,6 @@ class ConfigClass { bool reduceCoreParticles; bool reduceClashParticles; bool reduceDustParticles; - bool boostSaturation; void load(); void store(); diff --git a/include/color.h b/include/color.h deleted file mode 100644 index 4a9f2c3..0000000 --- a/include/color.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -namespace UnityEngine { - struct Color32; - struct Color; -} - -namespace ParticleTuner { - void hsv2rgb(float h, float s, float v, UnityEngine::Color32& rgb); - void rgb2hsv(const UnityEngine::Color32& rgb, float& h, float& s, float& v); - - UnityEngine::Color toColor(const UnityEngine::Color32 &in); - UnityEngine::Color32 toColor32(UnityEngine::Color in); -} diff --git a/mod.json b/mod.json index 8229259..606902c 100644 --- a/mod.json +++ b/mod.json @@ -1,17 +1,18 @@ { "_QPVersion": "0.1.1", - "name": "Particles", - "author": "Marcus Zhou", + "name": "ParticleTuner", + "author": "Marcus Zhou, Mioki", "packageId": "com.beatgames.beatsaber", - "packageVersion": "1.16.4", - "id": "particletuner", - "version": "1.3.0", + "packageVersion": "1.17.1", + "id": "ParticleTuner", + "version": "1.17.1-211117", "coverImage": "cover.gif", + "description": "A partial port of the Particle Overdrive mod from PC with colorful sparckles and custom parameters including ambiend dust.", "dependencies": [], "modFiles": [ "libparticletuner.so" ], "libraryFiles": [ - "libbeatsaber-hook_2_2_5.so" + "libbeatsaber-hook_2_3_2.so" ] } \ No newline at end of file diff --git a/ndk-stack.ps1 b/ndk-stack.ps1 new file mode 100644 index 0000000..5eb4af8 --- /dev/null +++ b/ndk-stack.ps1 @@ -0,0 +1,12 @@ +$NDKPath = Get-Content ./ndkpath.txt + +$stackScript = "$NDKPath/ndk-stack" +if (-not ($PSVersionTable.PSEdition -eq "Core")) { + $stackScript += ".cmd" +} + +if ($args.Count -eq 0) { + Get-Content ./log.txt | & $stackScript -sym ./obj/local/arm64-v8a/ > log_unstripped.log +} else { + Get-Content $args[0] | & $stackScript -sym ./obj/local/arm64-v8a/ > "$($args[0])_unstripped.txt" +} diff --git a/qpm.json b/qpm.json index 2334050..cbdd544 100644 --- a/qpm.json +++ b/qpm.json @@ -2,45 +2,45 @@ "sharedDir": "shared", "dependenciesDir": "extern", "info": { - "name": "particletuner", - "id": "particletuner", - "version": "1.3.0", + "name": "ParticleTuner", + "id": "ParticleTuner", + "version": "1.17.1", "url": "https://github.com/SuperMarcus/QuestParticleTuner", "additionalData": {} }, "dependencies": [ + { + "id": "beatsaber-hook", + "versionRange": "2.3.2", + "additionalData": { + "extraFiles": [ + "src/inline-hook" + ] + } + }, { "id": "codegen", - "versionRange": "^0.12.5", + "versionRange": "0.14.0", "additionalData": {} }, { "id": "custom-types", - "versionRange": "^0.12.6", + "versionRange": "0.12.7", "additionalData": {} }, { "id": "questui", - "versionRange": "^0.10.2", + "versionRange": "0.11.1", "additionalData": {} }, - { - "id": "beatsaber-hook", - "versionRange": "^2.2.5", - "additionalData": { - "extraFiles": [ - "src/inline-hook" - ] - } - }, { "id": "libil2cpp", - "versionRange": "^0.1.2", + "versionRange": "*", "additionalData": {} }, { "id": "modloader", - "versionRange": "^1.0.4", + "versionRange": "1.2.3", "additionalData": {} } ], diff --git a/release-qmod.sh b/release-qmod.sh index 6d2bf67..5ee313b 100755 --- a/release-qmod.sh +++ b/release-qmod.sh @@ -15,6 +15,8 @@ zip -j "$PKG_NAME" mod.json cover.gif find ./libs/arm64-v8a \ ! -name 'libmodloader.so' \ - ! -name 'libcodegen_*.so' \ + ! -name 'libcodegen*.so' \ + ! -name 'libcustom-types.so' \ + ! -name 'questui.so' \ ! -name 'gdb*' \ -type f -exec zip -j "$PKG_NAME" {} + diff --git a/restart-game.ps1 b/restart-game.ps1 new file mode 100644 index 0000000..fd0196a --- /dev/null +++ b/restart-game.ps1 @@ -0,0 +1,2 @@ +adb shell am force-stop com.beatgames.beatsaber +adb shell am start com.beatgames.beatsaber/com.unity3d.player.UnityPlayerActivity diff --git a/settings_screenshot_wide.png b/settings_screenshot_wide.png index 9e14fd7..a2afc2e 100644 Binary files a/settings_screenshot_wide.png and b/settings_screenshot_wide.png differ diff --git a/src/Config.cpp b/src/Config.cpp index f638f48..8b63802 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -2,26 +2,32 @@ #include "particletune_private.hpp" #define SET_PRIMITIVE(doc, name, type, value, alloc) \ - if (doc .HasMember(name)) { \ - doc [name].Set ## type (value); \ - } else { \ - doc .AddMember(name, value, alloc); \ + if (doc.HasMember(name)) \ + { \ + doc[name].Set##type(value); \ + } \ + else \ + { \ + doc.AddMember(name, value, alloc); \ } #define GET_PRIMITIVE(doc, name, type, default) \ - doc .HasMember(name) && doc[name].Is ## type () \ - ? doc [name].Get ## type () : (default) + doc.HasMember(name) && doc[name].Is##type() \ + ? doc[name].Get##type() \ + : (default) -ConfigClass::ConfigClass(Configuration& storage): _storage(storage) { +ConfigClass::ConfigClass(Configuration &storage) : _storage(storage) +{ load(); } -void ConfigClass::load() { +void ConfigClass::load() +{ getLogger().info("Loading configurations..."); _storage.Load(); - auto& document = _storage.config; - + auto &document = _storage.config; + sparkleMultiplier = GET_PRIMITIVE(document, "sparkles_multiplier", Float, PT_DEFAULT_SPARKLE_MULTIPLIER); explosionMultiplier = GET_PRIMITIVE(document, "explosion_multiplier", Float, PT_DEFAULT_EXPLOSION_MULTIPLIER); lifetimeMultiplier = GET_PRIMITIVE(document, "lifetime_multiplier", Float, PT_DEFAULT_LIFETIME_MULTIPLIER); @@ -33,19 +39,20 @@ void ConfigClass::load() { reduceDustParticles = GET_PRIMITIVE(document, "reduce_dust_particles", Bool, false); } -void ConfigClass::store() { - auto& document = _storage.config; - auto& allocator = document.GetAllocator(); +void ConfigClass::store() +{ + auto &document = _storage.config; + auto &allocator = document.GetAllocator(); SET_PRIMITIVE(document, "sparkles_multiplier", Float, sparkleMultiplier, allocator); SET_PRIMITIVE(document, "explosion_multiplier", Float, explosionMultiplier, allocator); SET_PRIMITIVE(document, "lifetime_multiplier", Float, lifetimeMultiplier, allocator); SET_PRIMITIVE(document, "particle_opacity", Float, particleOpacity, allocator); + SET_PRIMITIVE(document, "rainbow_particles", Bool, rainbowParticles, allocator); SET_PRIMITIVE(document, "reduce_core_particles", Bool, reduceCoreParticles, allocator); SET_PRIMITIVE(document, "reduce_clash_particles", Bool, reduceClashParticles, allocator); SET_PRIMITIVE(document, "reduce_dust_particles", Bool, reduceDustParticles, allocator); - _storage.Write(); getLogger().info("Configuration updated."); } diff --git a/src/PTModSettings.cpp b/src/PTModSettings.cpp index 20c71b6..0784ef7 100644 --- a/src/PTModSettings.cpp +++ b/src/PTModSettings.cpp @@ -20,111 +20,133 @@ using namespace ParticleTuner; DEFINE_TYPE(::ParticleTuner, PTModSettingsViewController); // NOLINT(cert-err58-cpp) -DEFINE_TYPE(::ParticleTuner, PTPresetData); // NOLINT(cert-err58-cpp) +DEFINE_TYPE(::ParticleTuner, PTPresetData); // NOLINT(cert-err58-cpp) static PTPreset presetsRawList[] = { PT_PRESET_NONE, PT_PRESET_NORMAL, PT_PRESET_FANCY, - PT_PRESET_TOO_MUCH -}; + PT_PRESET_TOO_MUCH}; -void PTModSettingsApplyPreset(PTPresetData * presetData) { - auto* vc = presetData->parent; - auto& preset = presetsRawList[presetData->preset]; - auto& currentConfig = getConfig(); +void PTModSettingsApplyPreset(PTPresetData *presetData) +{ + auto *vc = presetData->parent; + auto &preset = presetsRawList[presetData->preset]; + auto ¤tConfig = getConfig(); - if (vc) { + if (vc) + { getLogger().info("Selecting preset %s", preset.name.c_str()); currentConfig.sparkleMultiplier = preset.sparkleMultiplier; currentConfig.explosionMultiplier = preset.explosionMultiplier; currentConfig.lifetimeMultiplier = preset.lifetimeMultiplier; currentConfig.particleOpacity = preset.particleOpacity; + currentConfig.reduceCoreParticles = preset.reduceCoreParticles; currentConfig.reduceClashParticles = preset.reduceClashParticles; currentConfig.reduceDustParticles = preset.reduceDustParticles; - currentConfig.boostSaturation = preset.boostSaturation; currentConfig.rainbowParticles = preset.rainbowParticles; + vc->UpdateUIComponents(); } } -void PTModSettingsOnSparkleMultChange(PTModSettingsViewController* parent, float newValue) { - if (newValue < 0) { +void PTModSettingsOnSparkleMultChange(PTModSettingsViewController *parent, float newValue) +{ + if (newValue < 0) + { parent->sparklesMultInc->CurrentValue = 0.0; parent->sparklesMultInc->UpdateValue(); - } else { + } + else + { getConfig().sparkleMultiplier = newValue; getLogger().info("Set sparkleMultiplier=%f", newValue); } } -void PTModSettingsOnExplosionMultChange(PTModSettingsViewController* parent, float newValue) { - if (newValue < 0) { +void PTModSettingsOnExplosionMultChange(PTModSettingsViewController *parent, float newValue) +{ + if (newValue < 0) + { parent->explosionsMultInc->CurrentValue = 0.0; parent->explosionsMultInc->UpdateValue(); - } else { + } + else + { getConfig().explosionMultiplier = newValue; getLogger().info("Set explosionMultiplier=%f", newValue); } } -void PTModSettingsOnLifetimeMultChange(PTModSettingsViewController* parent, float newValue) { - if (newValue < 0) { +void PTModSettingsOnLifetimeMultChange(PTModSettingsViewController *parent, float newValue) +{ + if (newValue < 0) + { parent->lifetimeMultInc->CurrentValue = 0.0; parent->lifetimeMultInc->UpdateValue(); - } else { + } + else + { getConfig().lifetimeMultiplier = newValue; getLogger().info("Set lifetimeMultiplier=%f", newValue); } } -void PTModSettingsOnParticleOpacityChange(PTModSettingsViewController* parent, float newValue) { - if (newValue < 0.0f) { +void PTModSettingsOnParticleOpacityChange(PTModSettingsViewController *parent, float newValue) +{ + if (newValue < 0.0f) + { parent->particleOpacityInc->CurrentValue = 0.0f; parent->particleOpacityInc->UpdateValue(); - } else if (newValue > 1.0f) { + } + else if (newValue > 1.0f) + { parent->particleOpacityInc->CurrentValue = 1.0f; parent->particleOpacityInc->UpdateValue(); - } else { + } + else + { getConfig().particleOpacity = newValue; getLogger().info("Set particleOpacity=%f", newValue); } } -void PTModSettingsOnReduceCoreParticlesToggle(PTModSettingsViewController* parent, bool newValue) { +void PTModSettingsOnReduceCoreParticlesToggle(PTModSettingsViewController *parent, bool newValue) +{ getConfig().reduceCoreParticles = newValue; getLogger().info("Set reduceCoreParticles=%d", newValue); } -void PTModSettingsOnRainbowToggle(PTModSettingsViewController* parent, bool newValue) { +void PTModSettingsOnRainbowToggle(PTModSettingsViewController *parent, bool newValue) +{ getConfig().rainbowParticles = newValue; getLogger().info("Set rainbowParticles=%d", newValue); } -void PTModSettingsOnReduceClashParticlesToggle(PTModSettingsViewController* parent, bool newValue) { +void PTModSettingsOnReduceClashParticlesToggle(PTModSettingsViewController *parent, bool newValue) +{ getConfig().reduceClashParticles = newValue; getLogger().info("Set reduceClashParticles=%d", newValue); } -void PTModSettingsOnReduceDustParticlesToggle(PTModSettingsViewController* parent, bool newValue) { +void PTModSettingsOnReduceDustParticlesToggle(PTModSettingsViewController *parent, bool newValue) +{ getConfig().reduceDustParticles = newValue; - auto dustPSAgent = reinterpret_cast(parent->dustPSAgent); - if (dustPSAgent) { + auto dustPSAgent = reinterpret_cast(parent->dustPSAgent); + if (dustPSAgent) + { dustPSAgent->UpdateDustPSSettings(); } getLogger().info("Set reduceDustParticles=%d", newValue); } -//void PTModSettingsOnBoostSaturationToggle(PTModSettingsViewController* parent, bool newValue) { -// getConfig().boostSaturation = newValue; -// getLogger().info("Set boostSaturation=%d", newValue); -//} - -void PTModSettingsViewController::DidActivate(bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling) { - if (firstActivation) { +void PTModSettingsViewController::DidActivate(bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling) +{ + if (firstActivation) + { getLogger().info("Adding mod settings UI components..."); auto sectionBackgroundName = il2cpp_utils::createcsstr("round-rect-panel"); @@ -140,11 +162,11 @@ void PTModSettingsViewController::DidActivate(bool firstActivation, bool addedTo auto leftTogglesLayout = QuestUI::BeatSaberUI::CreateVerticalLayoutGroup(sectionContainerLayout->get_rectTransform()); leftTogglesLayout->get_gameObject() - ->AddComponent() + ->AddComponent() ->ApplyBackground(sectionBackgroundName); leftTogglesLayout->set_padding(sectionPadding); - - auto leftTogglesLayoutElement = leftTogglesLayout->GetComponent(); + + auto leftTogglesLayoutElement = leftTogglesLayout->GetComponent(); // leftTogglesLayoutElement->set_flexibleHeight(0); // leftTogglesLayoutElement->set_preferredHeight(45); leftTogglesLayoutElement->set_preferredWidth(60); @@ -164,11 +186,11 @@ void PTModSettingsViewController::DidActivate(bool firstActivation, bool addedTo // Layout - Center Multipliers auto centerSectionLayout = QuestUI::BeatSaberUI::CreateVerticalLayoutGroup(centerContainerLayout->get_rectTransform()); centerSectionLayout->get_gameObject() - ->AddComponent() + ->AddComponent() ->ApplyBackground(sectionBackgroundName); centerSectionLayout->set_padding(sectionPadding); centerSectionLayout->set_spacing(4); - auto centerSectionLayoutElement = centerSectionLayout->GetComponent(); + auto centerSectionLayoutElement = centerSectionLayout->GetComponent(); centerSectionLayoutElement->set_preferredWidth(110); // centerSectionLayoutElement->set_preferredHeight(60); @@ -177,7 +199,7 @@ void PTModSettingsViewController::DidActivate(bool firstActivation, bool addedTo presetContainerLayout->set_spacing(4); presetContainerLayout->set_padding(UnityEngine::RectOffset::New_ctor(2, 2, 0, 0)); auto presetContainerLayoutElement = presetContainerLayout - ->GetComponent(); + ->GetComponent(); presetContainerLayoutElement->set_preferredHeight(8); // presetContainerLayoutElement->set_preferredWidth(100); // presetContainerLayoutElement->set_flexibleWidth(0); @@ -191,7 +213,7 @@ void PTModSettingsViewController::DidActivate(bool firstActivation, bool addedTo // auto rightSectionLayoutElement = rightSectionLayout->GetComponent(); // rightSectionLayoutElement->set_preferredWidth(60); // rightSectionLayoutElement->set_preferredHeight(45); - + // Delegates auto sparkleChangeDelegate = std::bind(PTModSettingsOnSparkleMultChange, this, std::placeholders::_1); auto explosionChangeDelegate = std::bind(PTModSettingsOnExplosionMultChange, this, std::placeholders::_1); @@ -200,10 +222,10 @@ void PTModSettingsViewController::DidActivate(bool firstActivation, bool addedTo auto reduceCoreParticlesToggleDelegate = std::bind(PTModSettingsOnReduceCoreParticlesToggle, this, std::placeholders::_1); auto reduceClashParticlesToggleDelegate = std::bind(PTModSettingsOnReduceClashParticlesToggle, this, std::placeholders::_1); auto reduceDustParticlesToggleDelegate = std::bind(PTModSettingsOnReduceDustParticlesToggle, this, std::placeholders::_1); -// auto boostSaturationToggleDelegate = il2cpp_utils::MakeDelegate*>( -// classof(UnityEngine::Events::UnityAction_1*), -// this, PTModSettingsOnBoostSaturationToggle -// ); + // auto boostSaturationToggleDelegate = il2cpp_utils::MakeDelegate*>( + // classof(UnityEngine::Events::UnityAction_1*), + // this, PTModSettingsOnBoostSaturationToggle + // ); auto rainbowToggleDelegate = std::bind(PTModSettingsOnRainbowToggle, this, std::placeholders::_1); auto ¤tConfig = getConfig(); @@ -213,40 +235,28 @@ void PTModSettingsViewController::DidActivate(bool firstActivation, bool addedTo leftTogglesLayout->get_rectTransform(), "Reduce Core Particles", currentConfig.reduceCoreParticles, - reduceCoreParticlesToggleDelegate - ); + reduceCoreParticlesToggleDelegate); QuestUI::BeatSaberUI::AddHoverHint(reduceCoreParticlesToggle->get_gameObject(), "Remove the core particle effects from slicing a block."); reduceClashParticlesToggle = QuestUI::BeatSaberUI::CreateToggle( leftTogglesLayout->get_rectTransform(), "Reduce Clash Effects", currentConfig.reduceClashParticles, - reduceClashParticlesToggleDelegate - ); + reduceClashParticlesToggleDelegate); QuestUI::BeatSaberUI::AddHoverHint(reduceClashParticlesToggle->get_gameObject(), "Remove saber clash effects."); reduceDustParticlesToggle = QuestUI::BeatSaberUI::CreateToggle( leftTogglesLayout->get_rectTransform(), "Reduce Dust", currentConfig.reduceDustParticles, - reduceDustParticlesToggleDelegate - ); + reduceDustParticlesToggleDelegate); QuestUI::BeatSaberUI::AddHoverHint(reduceDustParticlesToggle->get_gameObject(), "Remove the particles floating in the air."); -// boostSaturationToggle = QuestUI::BeatSaberUI::CreateToggle( -// leftTogglesLayout->get_rectTransform(), -// "Boost Saturation", -// currentConfig.boostSaturation, -// boostSaturationToggleDelegate -// ); -// QuestUI::BeatSaberUI::AddHoverHint(boostSaturationToggle->get_gameObject(), "Make the note slash particle more vibrant."); - rainbowParticlesToggle = QuestUI::BeatSaberUI::CreateToggle( leftTogglesLayout->get_rectTransform(), "Rainbow Particles", currentConfig.rainbowParticles, - rainbowToggleDelegate - ); + rainbowToggleDelegate); QuestUI::BeatSaberUI::AddHoverHint(rainbowParticlesToggle->get_gameObject(), "Make slash particles rainbow!"); // Center Panel Configs @@ -255,8 +265,7 @@ void PTModSettingsViewController::DidActivate(bool firstActivation, bool addedTo "Sparkles Multiplier", 1, 0.2, currentConfig.sparkleMultiplier, - sparkleChangeDelegate - ); + sparkleChangeDelegate); QuestUI::BeatSaberUI::AddHoverHint(sparklesMultInc->get_gameObject(), "Tune the amount of sparkles generated after a slash. Set to 0 to disable sparkles."); explosionsMultInc = QuestUI::BeatSaberUI::CreateIncrementSetting( @@ -264,8 +273,7 @@ void PTModSettingsViewController::DidActivate(bool firstActivation, bool addedTo "Explosions Multiplier", 1, 0.2, currentConfig.explosionMultiplier, - explosionChangeDelegate - ); + explosionChangeDelegate); QuestUI::BeatSaberUI::AddHoverHint(explosionsMultInc->get_gameObject(), "Tune the amount of explosions generated after a slash. Set to 0 to disable explosions."); lifetimeMultInc = QuestUI::BeatSaberUI::CreateIncrementSetting( @@ -273,8 +281,7 @@ void PTModSettingsViewController::DidActivate(bool firstActivation, bool addedTo "Lifetime Multiplier", 1, 0.2, currentConfig.lifetimeMultiplier, - lifetimeChangeDelegate - ); + lifetimeChangeDelegate); QuestUI::BeatSaberUI::AddHoverHint(lifetimeMultInc->get_gameObject(), "Tune the lifetime of particles. Lifetime determines how long the particles stay on the screen."); particleOpacityInc = QuestUI::BeatSaberUI::CreateIncrementSetting( @@ -282,13 +289,13 @@ void PTModSettingsViewController::DidActivate(bool firstActivation, bool addedTo "Particle Opacity", 1, 0.1, currentConfig.particleOpacity, - particleOpacityChangeDelegate - ); + particleOpacityChangeDelegate); QuestUI::BeatSaberUI::AddHoverHint(particleOpacityInc->get_gameObject(), "Adjust the opacity of the slash particle."); - for (int i = 0; i < PT_NUMBER_OF_PRESETS; ++i) { + for (int i = 0; i < PT_NUMBER_OF_PRESETS; ++i) + { auto *preset = &presetsRawList[i]; - auto *presetData = CRASH_UNLESS(il2cpp_utils::New()); + auto *presetData = CRASH_UNLESS(il2cpp_utils::New()); presetData->preset = i; presetData->parent = this; @@ -296,25 +303,27 @@ void PTModSettingsViewController::DidActivate(bool firstActivation, bool addedTo presetContainerLayout->get_rectTransform(), preset->name, "OkButton", - [presetData] { return PTModSettingsApplyPreset(presetData); } - ); + [presetData] + { return PTModSettingsApplyPreset(presetData); }); } // Start private DustPS discovery agent - auto privateAgent = THROW_UNLESS(il2cpp_utils::New()); - dustPSAgent = reinterpret_cast(privateAgent); + auto privateAgent = THROW_UNLESS(il2cpp_utils::New()); + dustPSAgent = reinterpret_cast(privateAgent); GlobalNamespace::SharedCoroutineStarter::get_instance() - ->StartCoroutine(reinterpret_cast(privateAgent)); + ->StartCoroutine(reinterpret_cast(privateAgent)); } } -void PTModSettingsViewController::DidDeactivate(bool removedFromHierarchy, bool systemScreenDisabling) { +void PTModSettingsViewController::DidDeactivate(bool removedFromHierarchy, bool systemScreenDisabling) +{ getLogger().info("Deactivated PTModSettingsViewController."); getConfig().store(); } -void PTModSettingsViewController::UpdateUIComponents() { - auto& currentConfig = getConfig(); +void PTModSettingsViewController::UpdateUIComponents() +{ + auto ¤tConfig = getConfig(); sparklesMultInc->CurrentValue = currentConfig.sparkleMultiplier; explosionsMultInc->CurrentValue = currentConfig.explosionMultiplier; @@ -330,10 +339,11 @@ void PTModSettingsViewController::UpdateUIComponents() { reduceClashParticlesToggle->set_isOn(currentConfig.reduceClashParticles); reduceCoreParticlesToggle->set_isOn(currentConfig.reduceCoreParticles); reduceDustParticlesToggle->set_isOn(currentConfig.reduceDustParticles); -// boostSaturationToggle->set_isOn(currentConfig.boostSaturation); + // boostSaturationToggle->set_isOn(currentConfig.boostSaturation); } -void PTRegisterUI(ModInfo& modInfo) { +void PTRegisterUI(ModInfo &modInfo) +{ getLogger().info("Registering ParticleTuner UI..."); - QuestUI::Register::RegisterModSettingsViewController(modInfo, "Particle Tuner"); + QuestUI::Register::RegisterModSettingsViewController(modInfo, "Particle Tuner"); } diff --git a/src/PTScenePSDiscoveryAgent.cpp b/src/PTScenePSDiscoveryAgent.cpp index 40b7d4c..c8a253b 100644 --- a/src/PTScenePSDiscoveryAgent.cpp +++ b/src/PTScenePSDiscoveryAgent.cpp @@ -20,31 +20,39 @@ using namespace ParticleTuner; DEFINE_TYPE(::ParticleTuner, PTScenePSDiscoveryAgent); // NOLINT(cert-err58-cpp) -bool PTScenePSDiscoveryAgent::MoveNext() { - if (dustPS == nullptr) { +bool PTScenePSDiscoveryAgent::MoveNext() +{ + if (dustPS == nullptr) + { getLogger().info("PTScenePSDiscoveryAgent discovery iteration %d", iterations); - auto particleSystems = UnityEngine::Object::FindObjectsOfType(); + auto particleSystems = UnityEngine::Object::FindObjectsOfType(); auto particleSystemsLen = particleSystems->Length(); - for (auto i = 0; i < particleSystemsLen; ++i) { + for (auto i = 0; i < particleSystemsLen; ++i) + { auto ps = particleSystems->values[i]; auto psName = ps->get_name(); - if (to_utf8(csstrtostr(psName)) == "DustPS") { + if (to_utf8(csstrtostr(psName)) == "DustPS") + { getLogger().info("PTScenePSDiscoveryAgent found new DustPS."); dustPS = ps; UpdateDustPSSettings(); break; } } - - if (dustPS == nullptr) { - if (iterations < PT_DISCOVERY_MAX_ITERATIONS) { + + if (dustPS == nullptr) + { + if (iterations < PT_DISCOVERY_MAX_ITERATIONS) + { currentOp = UnityEngine::WaitForSeconds::New_ctor(0.5f); - iterations += 1; + iterations++; return true; - } else { + } + else + { getLogger().info("PTScenePSDiscoveryAgent discovery exceeded maximum iterations. Aborting..."); } } @@ -55,18 +63,22 @@ bool PTScenePSDiscoveryAgent::MoveNext() { return false; } -void PTScenePSDiscoveryAgent::UpdateDustPSSettings() { - if (dustPS) { - auto& currentConfig = getConfig(); +void PTScenePSDiscoveryAgent::UpdateDustPSSettings() +{ + if (dustPS) + { + auto ¤tConfig = getConfig(); dustPS->get_gameObject()->SetActive(!currentConfig.reduceDustParticles); } } -Il2CppObject* PTScenePSDiscoveryAgent::get_Current() { +Il2CppObject *PTScenePSDiscoveryAgent::get_Current() +{ return currentOp; } -void PTScenePSDiscoveryAgent::Reset() { +void PTScenePSDiscoveryAgent::Reset() +{ getLogger().info("Resetting PTScenePSDiscoveryAgent..."); dustPS = nullptr; currentOp = nullptr; diff --git a/src/color.cpp b/src/color.cpp deleted file mode 100644 index 89ce5fe..0000000 --- a/src/color.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include - -#include "UnityEngine/Color32.hpp" -#include "UnityEngine/Color.hpp" - -#include "particletune_private.hpp" -#include "color.h" - -// Modified from Jan Winkler 's color conversion code: -// https://gist.github.com/fairlight1337/4935ae72bcbcc1ba5c72 - -using namespace std; - -void ParticleTuner::hsv2rgb(float fH, float fS, float fV, UnityEngine::Color32 &rgb) { - float fC = fV * fS; // Chroma - float fHPrime = fmod(fH * 6.0f, 6.0f); - float fX = fC * (1.0f - fabs(fmod(fHPrime, 2.0f) - 1.0f)); - float fM = fV - fC; - float fR, fG, fB; - - if(0 <= fHPrime && fHPrime < 1) { - fR = fC; - fG = fX; - fB = 0.0f; - } else if(1 <= fHPrime && fHPrime < 2) { - fR = fX; - fG = fC; - fB = 0.0f; - } else if(2 <= fHPrime && fHPrime < 3) { - fR = 0.0f; - fG = fC; - fB = fX; - } else if(3 <= fHPrime && fHPrime < 4) { - fR = 0.0f; - fG = fX; - fB = fC; - } else if(4 <= fHPrime && fHPrime < 5) { - fR = fX; - fG = 0.0f; - fB = fC; - } else if(5 <= fHPrime && fHPrime < 6) { - fR = fC; - fG = 0.0f; - fB = fX; - } else { - fR = 0.0f; - fG = 0.0f; - fB = 0.0f; - } - - fR += fM; - fG += fM; - fB += fM; - - rgb.r = static_cast(fR * 255.0f); - rgb.g = static_cast(fG * 255.0f); - rgb.b = static_cast(fB * 255.0f); -} - -void ParticleTuner::rgb2hsv(const UnityEngine::Color32 &rgb, float &fH, float &fS, float &fV) { - auto fR = clamp(static_cast(rgb.r) / 255.0f, 0.0f, 1.0f); - auto fG = clamp(static_cast(rgb.g) / 255.0f, 0.0f, 1.0f); - auto fB = clamp(static_cast(rgb.b) / 255.0f, 0.0f, 1.0f); - auto fCMax = max({ fR, fG, fB }); - auto fCMin = min({ fR, fG, fB }); - auto fDelta = fCMax - fCMin; - - if(fDelta > 0) { - if(fCMax == fR) { - fH = (fmod(((fG - fB) / fDelta), 6.0f)) / 6.0f; - } else if(fCMax == fG) { - fH = (((fB - fR) / fDelta) + 2.0f) / 6.0f; - } else if(fCMax == fB) { - fH = (((fR - fG) / fDelta) + 4.0f) / 6.0f; - } - - if(fCMax > 0) { - fS = fDelta / fCMax; - } else { - fS = 0.0f; - } - - fV = fCMax; - } else { - fH = 0.0f; - fS = 0.0f; - fV = fCMax; - } - - if(fH < 0) { - fH = 1.0f + fH; - } -} - -UnityEngine::Color ParticleTuner::toColor(const UnityEngine::Color32 &in) { - return { - static_cast(in.r) / 255.0f, - static_cast(in.g) / 255.0f, - static_cast(in.b) / 255.0f, - static_cast(in.a) / 255.0f - }; -} - -UnityEngine::Color32 ParticleTuner::toColor32(UnityEngine::Color in) { - return { static_cast(in.r * 0xff), static_cast(in.g * 0xff), static_cast(in.b * 0xff) }; -} diff --git a/src/hooks.cpp b/src/hooks.cpp index 38dfbdd..a976bc8 100644 --- a/src/hooks.cpp +++ b/src/hooks.cpp @@ -25,16 +25,16 @@ #include "PTScenePSController.hpp" #include "Config.hpp" #include "UnityInternalCalls.hpp" -#include "color.h" using namespace ParticleTuner; MAKE_HOOK_MATCH(NoteCutParticlesEffect_SpawnParticles, &GlobalNamespace::NoteCutParticlesEffect::SpawnParticles, void, - GlobalNamespace::NoteCutParticlesEffect* self, UnityEngine::Vector3 cutPoint, - UnityEngine::Vector3 cutNormal, UnityEngine::Vector3 saberDir, float saberSpeed, - UnityEngine::Vector3 noteMovementVec, UnityEngine::Color32 color, int sparkleParticlesCount, - int explosionParticlesCount, float lifetimeMultiplier) { - auto& currentConfig = getConfig(); + GlobalNamespace::NoteCutParticlesEffect *self, UnityEngine::Vector3 cutPoint, + UnityEngine::Vector3 cutNormal, UnityEngine::Vector3 saberDir, float saberSpeed, + UnityEngine::Vector3 noteMovementVec, UnityEngine::Color32 color, int sparkleParticlesCount, + int explosionParticlesCount, float lifetimeMultiplier) +{ + auto ¤tConfig = getConfig(); int newSparkleCount = static_cast(static_cast(sparkleParticlesCount) * currentConfig.sparkleMultiplier); int newExplosionCount = static_cast(static_cast(explosionParticlesCount) * currentConfig.explosionMultiplier); float newLifetimeMultiplier = lifetimeMultiplier * currentConfig.lifetimeMultiplier; @@ -52,98 +52,135 @@ MAKE_HOOK_MATCH(NoteCutParticlesEffect_SpawnParticles, &GlobalNamespace::NoteCut icall_functions::ParticleSystem_MainModule::set_startLifetimeMultiplier_Injected( &explosionMain, - currentConfig.lifetimeMultiplier - ); + currentConfig.lifetimeMultiplier); -// icall_functions::ParticleSystem_ColorOverLifetimeModule::set_enabled_Injected( -// &sparklesMain, -// true -// ); - icall_functions::ParticleSystem_ColorBySpeedModule::set_enabled_Injected(&sparklesMain, false); - icall_functions::ParticleSystem_ColorOverLifetimeModule::set_enabled_Injected(&sparklesMain, false); + icall_functions::ParticleSystem_ColorBySpeedModule::set_enabled_Injected(&sparklesMain, currentConfig.rainbowParticles); - if (currentConfig.reduceCoreParticles) { + icall_functions::ParticleSystem_ColorOverLifetimeModule::set_enabled_Injected(&sparklesMain, currentConfig.rainbowParticles); + + if (currentConfig.reduceCoreParticles) + { icall_functions::ParticleSystem_MainModule::set_startLifetimeMultiplier_Injected( &coreMain, - 0.0f - ); + 0.0f); coreMain.set_maxParticles(0); } - if (currentConfig.rainbowParticles) { - auto seed = std::chrono::system_clock::now().time_since_epoch().count(); - std::default_random_engine generator (seed); - auto randomHue = std::generate_canonical::digits>(generator); - hsv2rgb(randomHue, 1.0f, 0.5f, color); - } + // getLogger().debug("Original color R,G,B,A: %d, %d, %d, %d", color.r, color.g, color.b, color.a); + + if (currentConfig.rainbowParticles) + { + const int color_value = 127; // color value of the HSV color code. 127 equals to 0.5f + int rgb_variable = rand(); + int color_hue = rgb_variable % 256; + rgb_variable >>= 8; + int rgb_zero = rgb_variable & 1; + rgb_variable >>= 1; + rgb_variable %= 3; + rgb_zero = (rgb_variable + 1 + rgb_zero) % 3; + int rgb_fixed = 3 - rgb_variable - rgb_zero; + + switch (rgb_variable) + { + case 0: + color.r = color_hue; + break; + case 1: + color.g = color_hue; + break; + case 2: + color.b = color_hue; + break; + } -// getLogger().debug("before: %d, %d, %d, %d", color.r, color.g, color.b, color.a); + switch (rgb_zero) + { + case 0: + color.r = 0; + break; + case 1: + color.g = 0; + break; + case 2: + color.b = 0; + break; + } - if (currentConfig.boostSaturation) { -// float h, s, v; -// rgb2hsv(color, h, s, v); -// s = 1.0f; // Max saturation, value -// v = 0.3f; -// hsv2rgb(h, s, v, color); + switch (rgb_fixed) + { + case 0: + color.r = color_value; + break; + case 1: + color.g = color_value; + break; + case 2: + color.b = color_value; + break; + } } -// getLogger().debug("after: %d, %d, %d, %d", color.r, color.g, color.b, color.a); - // Set alpha channel color.a = static_cast(std::clamp(currentConfig.particleOpacity * 255.0f, 0.0f, 255.0f)); -// auto updatedColor = toColor(color); -// auto newGradient = new UnityEngine::ParticleSystem::MinMaxGradient(updatedColor); -// icall_functions::ParticleSystem_ColorOverLifetimeModule::set_color_Injected(&sparklesMain, newGradient); -// + getLogger().debug("Processed color R,G,B,A: %d, %d, %d, %d", color.r, color.g, color.b, color.a); + + // auto updatedColor = toColor(color); + // auto newGradient = new UnityEngine::ParticleSystem::MinMaxGradient(updatedColor); + // icall_functions::ParticleSystem_ColorOverLifetimeModule::set_color_Injected(&sparklesMain, newGradient); + // NoteCutParticlesEffect_SpawnParticles( self, cutPoint, cutNormal, saberDir, saberSpeed, noteMovementVec, color, - newSparkleCount, newExplosionCount, newLifetimeMultiplier - ); + newSparkleCount, newExplosionCount, newLifetimeMultiplier); } MAKE_HOOK_MATCH(SaberClashEffect_LateUpdate, &GlobalNamespace::SaberClashEffect::LateUpdate, void, - GlobalNamespace::SaberClashEffect* self) { - auto& currentConfig = getConfig(); + GlobalNamespace::SaberClashEffect *self) +{ + auto ¤tConfig = getConfig(); auto glowPS = self->glowParticleSystem; auto sparklePS = self->sparkleParticleSystem; glowPS->get_main().set_maxParticles(currentConfig.reduceClashParticles ? 0 : INT_MAX); sparklePS->get_main().set_maxParticles(currentConfig.reduceClashParticles ? 0 : INT_MAX); - + SaberClashEffect_LateUpdate(self); } MAKE_HOOK_MATCH(SceneManager_Internal_ActiveSceneChanged, &UnityEngine::SceneManagement::SceneManager::Internal_ActiveSceneChanged, void, - UnityEngine::SceneManagement::Scene oldScene, UnityEngine::SceneManagement::Scene newScene) { + UnityEngine::SceneManagement::Scene oldScene, UnityEngine::SceneManagement::Scene newScene) +{ static std::vector sensitiveScenes = { - "Init", "MenuViewControllers", "GameCore", "Credits" - }; + "Init", "MenuViewControllers", "GameCore", "Credits"}; SceneManager_Internal_ActiveSceneChanged(oldScene, newScene); auto sceneNameCs = newScene.get_name(); - if (sceneNameCs) { + if (sceneNameCs) + { auto sceneName = to_utf8(csstrtostr(newScene.get_name())); // getLogger().info("Transitioning to scene: %s", sceneName.data()); - - if (std::find(sensitiveScenes.begin(), sensitiveScenes.end(), sceneName) != sensitiveScenes.end()) { + + if (std::find(sensitiveScenes.begin(), sensitiveScenes.end(), sceneName) != sensitiveScenes.end()) + { getLogger().info("Starting PTScenePSDiscoveryAgent..."); - auto discoveryAgent = THROW_UNLESS(il2cpp_utils::New()); + auto discoveryAgent = THROW_UNLESS(il2cpp_utils::New()); GlobalNamespace::SharedCoroutineStarter::get_instance() - ->StartCoroutine(reinterpret_cast(discoveryAgent)); + ->StartCoroutine(reinterpret_cast(discoveryAgent)); } } } -void PTInstallHooks() { - auto& logger = getLogger(); +void PTInstallHooks() +{ + auto &logger = getLogger(); logger.info("Adding hooks..."); INSTALL_HOOK(logger, NoteCutParticlesEffect_SpawnParticles); INSTALL_HOOK(logger, SaberClashEffect_LateUpdate); INSTALL_HOOK(logger, SceneManager_Internal_ActiveSceneChanged); + srand(std::chrono::system_clock::now().time_since_epoch().count()); } diff --git a/start-logging.ps1 b/start-logging.ps1 new file mode 100644 index 0000000..0cee364 --- /dev/null +++ b/start-logging.ps1 @@ -0,0 +1,20 @@ +adb shell am force-stop com.beatgames.beatsaber +adb shell am start com.beatgames.beatsaber/com.unity3d.player.UnityPlayerActivity +$timestamp = Get-Date -Format "MM-dd HH:mm:ss.fff" +$bspid = adb shell pidof com.beatgames.beatsaber +while ([string]::IsNullOrEmpty($bspid)) { + Start-Sleep -Milliseconds 100 + $bspid = adb shell pidof com.beatgames.beatsaber +} +if ($args.Count -eq 0) { + echo "Start logging!" + adb logcat -T "$timestamp" --pid $bspid +} +if ($args[0] -eq "--file") { + echo "Logging and saving to file!" + (adb logcat -T "$timestamp" --pid $bspid | Select-String -pattern "(QuestHook|modloader|AndroidRuntime)") | Tee-Object -FilePath $PSScriptRoot/logcat.log +} +if ($args[0] -eq "--log") { + echo "Logging and saving to file!" + adb logcat -T "$timestamp" --pid $bspid > $PSScriptRoot/logcat.log +}