Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a61abcde2d | ||
|
|
a93a74aede | ||
|
|
9207e46105 | ||
|
|
d113fc40cb | ||
|
|
45a2f28cf6 | ||
|
|
45d47677ac | ||
|
|
a485080c27 | ||
|
|
cb4ecc521f | ||
|
|
0e269ddfc7 |
@@ -1,149 +0,0 @@
|
||||
name: Linux Builds
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Linux Build
|
||||
permissions: write-all
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Pulling the new commit
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setting up Haxe
|
||||
uses: krdlab/setup-haxe@v2
|
||||
with:
|
||||
haxe-version: 4.3.7
|
||||
- name: Restore existing build cache for faster compilation
|
||||
uses: actions/cache@v4.2.3
|
||||
with:
|
||||
# not caching the bin folder to prevent asset duplication and stuff like that
|
||||
key: cache-build-linux
|
||||
path: |
|
||||
.haxelib/
|
||||
export/release/linux/haxe/
|
||||
export/release/linux/obj/
|
||||
- run: |
|
||||
echo "HXCPP_COMPILE_CACHE=~/.hxcpp" >> $GITHUB_ENV
|
||||
- name: Installing LibVLC
|
||||
run: |
|
||||
sudo apt-get install libvlc-dev libvlccore-dev
|
||||
- name: Installing/Updating libraries
|
||||
run: |
|
||||
haxe -cp commandline -D analyzer-optimize --run Main setup -s
|
||||
- name: Building the game
|
||||
run: |
|
||||
haxelib run lime build linux -DCOMPILE_EXPERIMENTAL
|
||||
# - name: Tar files
|
||||
# run: tar -zcvf CodenameEngine.tar.gz -C export/release/linux/bin .
|
||||
- name: Uploading artifact (executable)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Codename Engine (Executable Only)
|
||||
path: export/release/linux/bin/CodenameEngine
|
||||
- name: Uploading artifact (entire build)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Codename Engine
|
||||
path: export/release/linux/bin/
|
||||
- name: Clearing already existing cache
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const caches = await github.rest.actions.getActionsCacheList({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
})
|
||||
for (const cache of caches.data.actions_caches) {
|
||||
if (cache.key == "cache-build-linux") {
|
||||
console.log('Clearing ' + cache.key + '...')
|
||||
await github.rest.actions.deleteActionsCacheById({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
cache_id: cache.id,
|
||||
})
|
||||
console.log("Cache cleared.")
|
||||
}
|
||||
}
|
||||
- name: Uploading new cache
|
||||
uses: actions/cache@v4.2.3
|
||||
with:
|
||||
# caching again since for some reason it doesnt work with the first post cache shit
|
||||
key: cache-build-linux
|
||||
path: |
|
||||
.haxelib/
|
||||
export/release/linux/haxe/
|
||||
export/release/linux/obj/
|
||||
|
||||
# didnt compile debug in the same job or github would have said that job wasn't completed until debug was done too (debug uploads are not essential)
|
||||
debug_build:
|
||||
name: Linux Debug Build
|
||||
permissions: write-all
|
||||
runs-on: ubuntu-24.04
|
||||
needs: build # since its low priority, it'll run after, so actions will concentrate first on normal builds
|
||||
steps:
|
||||
- name: Pulling the new commit
|
||||
uses: actions/checkout@v4
|
||||
- name: Setting up Haxe
|
||||
uses: krdlab/setup-haxe@v2
|
||||
with:
|
||||
haxe-version: 4.3.7
|
||||
- name: Restore existing build cache for faster compilation
|
||||
uses: actions/cache@v4.2.3
|
||||
with:
|
||||
# not caching the bin folder to prevent asset duplication and stuff like that
|
||||
key: cache-build-linux-debug
|
||||
path: |
|
||||
.haxelib/
|
||||
export/debug/linux/haxe/
|
||||
export/debug/linux/obj/
|
||||
- run: |
|
||||
echo "HXCPP_COMPILE_CACHE=~/.hxcpp" >> $GITHUB_ENV
|
||||
- name: Installing LibVLC
|
||||
run: |
|
||||
sudo apt-get install libvlc-dev libvlccore-dev
|
||||
- name: Installing/Updating libraries
|
||||
run: |
|
||||
haxe -cp commandline -D analyzer-optimize --run Main setup -s
|
||||
- name: Building the game
|
||||
run: |
|
||||
haxelib run lime build linux -debug
|
||||
# - name: Tar files
|
||||
# run: tar -zcvf CodenameEngine.tar.gz -C export/debug/linux/bin .
|
||||
- name: Uploading artifact (entire build)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Codename Engine Debug
|
||||
path: export/debug/linux/bin/
|
||||
- name: Clearing already existing cache
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const caches = await github.rest.actions.getActionsCacheList({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
})
|
||||
for (const cache of caches.data.actions_caches) {
|
||||
if (cache.key == "cache-build-linux-debug") {
|
||||
console.log('Clearing ' + cache.key + '...')
|
||||
await github.rest.actions.deleteActionsCacheById({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
cache_id: cache.id,
|
||||
})
|
||||
console.log("Cache cleared.")
|
||||
}
|
||||
}
|
||||
- name: Uploading new cache
|
||||
uses: actions/cache@v4.2.3
|
||||
with:
|
||||
# caching again since for some reason it doesnt work with the first post cache shit
|
||||
key: cache-build-linux-debug
|
||||
path: |
|
||||
.haxelib/
|
||||
export/debug/linux/haxe/
|
||||
export/debug/linux/obj/
|
||||
@@ -1,143 +0,0 @@
|
||||
name: Mac OS Builds
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Mac OS Build
|
||||
permissions: write-all
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- name: Pulling the new commit
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setting up Haxe
|
||||
uses: krdlab/setup-haxe@v2
|
||||
with:
|
||||
haxe-version: 4.3.7
|
||||
- name: Restore existing build cache for faster compilation
|
||||
uses: actions/cache@v4.2.3
|
||||
with:
|
||||
# not caching the bin folder to prevent asset duplication and stuff like that
|
||||
key: cache-build-mac
|
||||
path: |
|
||||
.haxelib/
|
||||
export/release/macos/haxe/
|
||||
export/release/macos/obj/
|
||||
- run: |
|
||||
echo "HXCPP_COMPILE_CACHE=~/.hxcpp" >> $GITHUB_ENV
|
||||
- name: Installing/Updating libraries
|
||||
run: |
|
||||
haxe -cp commandline -D analyzer-optimize --run Main setup -s
|
||||
- name: Building the game
|
||||
run: |
|
||||
arch -x86_64 haxelib run lime build mac -DCOMPILE_EXPERIMENTAL
|
||||
- name: Tar files
|
||||
run: tar -zcvf CodenameEngine.tar.gz -C export/release/macos/bin .
|
||||
- name: Uploading artifact (executable)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Codename Engine (Executable Only)
|
||||
path: export/release/macos/bin/CodenameEngine.app/Contents/MacOS/CodenameEngine
|
||||
- name: Uploading artifact (entire build)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Codename Engine
|
||||
path: CodenameEngine.tar.gz
|
||||
- name: Clearing already existing cache
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const caches = await github.rest.actions.getActionsCacheList({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
})
|
||||
for (const cache of caches.data.actions_caches) {
|
||||
if (cache.key == "cache-build-mac") {
|
||||
console.log('Clearing ' + cache.key + '...')
|
||||
await github.rest.actions.deleteActionsCacheById({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
cache_id: cache.id,
|
||||
})
|
||||
console.log("Cache cleared.")
|
||||
}
|
||||
}
|
||||
- name: Uploading new cache
|
||||
uses: actions/cache@v4.2.3
|
||||
with:
|
||||
# caching again since for some reason it doesnt work with the first post cache shit
|
||||
key: cache-build-mac
|
||||
path: |
|
||||
.haxelib/
|
||||
export/release/macos/haxe/
|
||||
export/release/macos/obj/
|
||||
|
||||
# didnt compile debug in the same job or github would have said that job wasn't completed until debug was done too (debug uploads are not essential)
|
||||
debug_build:
|
||||
name: Mac OS Debug Build
|
||||
permissions: write-all
|
||||
runs-on: macos-14
|
||||
needs: build # since its low priority, it'll run after, so actions will concentrate first on normal builds
|
||||
steps:
|
||||
- name: Pulling the new commit
|
||||
uses: actions/checkout@v4
|
||||
- name: Setting up Haxe
|
||||
uses: krdlab/setup-haxe@v2
|
||||
with:
|
||||
haxe-version: 4.3.7
|
||||
- name: Restore existing build cache for faster compilation
|
||||
uses: actions/cache@v4.2.3
|
||||
with:
|
||||
# not caching the bin folder to prevent asset duplication and stuff like that
|
||||
key: cache-build-mac-debug
|
||||
path: |
|
||||
.haxelib/
|
||||
export/debug/macos/haxe/
|
||||
export/debug/macos/obj/
|
||||
- run: |
|
||||
echo "HXCPP_COMPILE_CACHE=~/.hxcpp" >> $GITHUB_ENV
|
||||
- name: Installing/Updating libraries
|
||||
run: |
|
||||
haxe -cp commandline -D analyzer-optimize --run Main setup -s
|
||||
- name: Building the game
|
||||
run: |
|
||||
arch -x86_64 haxelib run lime build mac -debug
|
||||
- name: Tar files
|
||||
run: tar -zcvf CodenameEngine.tar.gz -C export/debug/macos/bin .
|
||||
- name: Uploading artifact (entire build)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Codename Engine Debug
|
||||
path: CodenameEngine.tar.gz
|
||||
- name: Clearing already existing cache
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const caches = await github.rest.actions.getActionsCacheList({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
})
|
||||
for (const cache of caches.data.actions_caches) {
|
||||
if (cache.key == "cache-build-mac-debug") {
|
||||
console.log('Clearing ' + cache.key + '...')
|
||||
await github.rest.actions.deleteActionsCacheById({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
cache_id: cache.id,
|
||||
})
|
||||
console.log("Cache cleared.")
|
||||
}
|
||||
}
|
||||
- name: Uploading new cache
|
||||
uses: actions/cache@v4.2.3
|
||||
with:
|
||||
# caching again since for some reason it doesnt work with the first post cache shit
|
||||
key: cache-build-mac-debug
|
||||
path: |
|
||||
.haxelib/
|
||||
export/debug/macos/haxe/
|
||||
export/debug/macos/obj/
|
||||
@@ -1,199 +0,0 @@
|
||||
name: Create Release Builds
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag_name:
|
||||
description: "Release name (e.g. v1.0.5 or v1.2-rc1)"
|
||||
required: true
|
||||
prerelease:
|
||||
description: "Is this a prerelease?"
|
||||
required: true
|
||||
type: boolean
|
||||
custom_message:
|
||||
description: "Optional pre-changelog message"
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
collect-release:
|
||||
name: Release ${{ github.event.inputs.tag_name }} Builds
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download Windows Full Build
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
workflow: windows.yml
|
||||
name: Codename Engine
|
||||
path: artifacts/windows/full_build
|
||||
allow_forks: false
|
||||
|
||||
- name: Download Windows Executable
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
workflow: windows.yml
|
||||
name: Codename Engine (Executable Only)
|
||||
path: artifacts/windows/executable
|
||||
allow_forks: false
|
||||
|
||||
- name: Download Mac OS Full Build
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
workflow: macos.yml
|
||||
name: Codename Engine
|
||||
path: artifacts/macos/full_build
|
||||
allow_forks: false
|
||||
|
||||
- name: Download Mac OS Executable
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
workflow: macos.yml
|
||||
name: Codename Engine (Executable Only)
|
||||
path: artifacts/macos/executable
|
||||
allow_forks: false
|
||||
|
||||
- name: Download Linux Full Build
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
workflow: linux.yml
|
||||
name: Codename Engine
|
||||
path: artifacts/linux/full_build
|
||||
allow_forks: false
|
||||
|
||||
- name: Download Linux Executable
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
workflow: linux.yml
|
||||
name: Codename Engine (Executable Only)
|
||||
path: artifacts/linux/executable
|
||||
allow_forks: false
|
||||
|
||||
- name: Prepare artifacts
|
||||
run: |
|
||||
mkdir -p renamed
|
||||
|
||||
# Windows
|
||||
mv artifacts/windows/executable/CodenameEngine.exe renamed/update-windows.exe
|
||||
cd artifacts/windows/full_build
|
||||
zip -r ../../../renamed/"Codename Engine-Windows.zip" *
|
||||
cd -
|
||||
|
||||
# Mac OS
|
||||
mv artifacts/macos/executable/CodenameEngine renamed/update-mac
|
||||
cd artifacts/macos/full_build
|
||||
if [ -f CodenameEngine.tar.gz ]; then
|
||||
# Keep tar.gz as-is
|
||||
cp CodenameEngine.tar.gz ../../../renamed/"Codename Engine-Mac.tar.gz"
|
||||
else
|
||||
# Zip contents at root
|
||||
zip -r ../../../renamed/"Codename Engine-Mac.zip" *
|
||||
fi
|
||||
cd -
|
||||
|
||||
# Linux
|
||||
mv artifacts/linux/executable/CodenameEngine renamed/update-linux
|
||||
cd artifacts/linux/full_build
|
||||
zip -r ../../../renamed/"Codename Engine-Linux.zip" *
|
||||
cd -
|
||||
|
||||
- name: Find Base Release
|
||||
id: get_base_release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
echo "Looking for base release..."
|
||||
PRERELEASE="${{ github.event.inputs.prerelease }}"
|
||||
|
||||
if [[ "$PRERELEASE" == "true" ]]; then
|
||||
BASE=$(gh release list --repo ${{ github.repository }} --json tagName,isPrerelease,isDraft \
|
||||
-L 50 -q '.[] | select(.isPrerelease==false and .isDraft==false) | .tagName' | head -n 1)
|
||||
|
||||
if [ -z "$BASE" ]; then
|
||||
echo "No stable release found, resorting to prereleases."
|
||||
BASE=$(gh release list --repo ${{ github.repository }} --json tagName,isDraft \
|
||||
-L 1 -q '.[] | select(.isDraft==false) | .tagName')
|
||||
fi
|
||||
else
|
||||
BASE=$(gh release list --repo ${{ github.repository }} --json tagName,isPrerelease,isDraft \
|
||||
-L 50 -q '.[] | select(.isPrerelease==false and .isDraft==false) | .tagName' | head -n 1)
|
||||
fi
|
||||
|
||||
if [ -z "$BASE" ]; then
|
||||
echo "No older release found; please make sure to have at least one older release containing the 'update-assets.zip' file in order to generate the differences."
|
||||
exit 1
|
||||
else
|
||||
echo "Base release: $BASE"
|
||||
echo "base_release=$BASE" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Prepare update-assets.zip
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
echo "Looking for 'update-assets.zip' from release '${{ steps.get_base_release.outputs.base_release }}'"
|
||||
ASSETS=$(gh release view "${{ steps.get_base_release.outputs.base_release }}" \
|
||||
--repo "${{ github.repository }}" \
|
||||
--json assets \
|
||||
| jq -r '.assets[].name')
|
||||
|
||||
if echo "$ASSETS" | grep -xq "update-assets.zip"; then
|
||||
mkdir -p update_assets_temp renamed
|
||||
echo "Downloading assets from release '${{ steps.get_base_release.outputs.base_release }}'"
|
||||
gh release download "${{ steps.get_base_release.outputs.base_release }}" \
|
||||
--repo ${{ github.repository }} \
|
||||
--pattern "update-assets.zip" \
|
||||
-D update_assets_temp
|
||||
|
||||
unzip -q update_assets_temp/update-assets.zip -d update_assets_temp
|
||||
cd update_assets_temp
|
||||
zip -r ../renamed/update-assets.zip . -i assets
|
||||
else
|
||||
echo "No 'update-assets.zip' file found in release '${{ steps.get_base_release.outputs.base_release }}'; please make sure to have this file in that older release in order to generate the differences."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Prepare pre-changelog message
|
||||
id: pre_changelog_message
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
echo "Preparing a pre-changelog message..."
|
||||
|
||||
BODY="If you would like to download the full builds of the engine from this release, please ignore the files starting with 'update-' as they're needed for the engine's internal autoupdater.\n\n"
|
||||
|
||||
if [ -n "${{ github.event.inputs.custom_message }}" ]; then
|
||||
BODY="${{ github.event.inputs.custom_message }}\n${BODY}"
|
||||
fi
|
||||
|
||||
{
|
||||
echo "body<<EOF"
|
||||
echo -e "$BODY"
|
||||
echo "EOF"
|
||||
} >> $GITHUB_OUTPUT
|
||||
echo -e "Final pre-changelog message:\n\n$BODY"
|
||||
|
||||
- name: Create GitHub Release with Assets
|
||||
uses: softprops/action-gh-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.event.inputs.tag_name }}
|
||||
name: Release ${{ github.event.inputs.tag_name }}
|
||||
draft: true
|
||||
prerelease: ${{ github.event.inputs.prerelease }}
|
||||
body: ${{ steps.build_body.outputs.body }}
|
||||
generate_release_notes: true
|
||||
files: |
|
||||
renamed/Codename Engine-Windows.zip
|
||||
renamed/Codename Engine-Mac.zip
|
||||
renamed/Codename Engine-Mac.tar.gz
|
||||
renamed/Codename Engine-Linux.zip
|
||||
renamed/update-assets.zip
|
||||
renamed/update-windows.exe
|
||||
renamed/update-mac
|
||||
renamed/update-linux
|
||||
@@ -1,139 +0,0 @@
|
||||
name: Windows Builds
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Windows Build
|
||||
permissions: write-all
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Pulling the new commit
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setting up Haxe
|
||||
uses: krdlab/setup-haxe@v2
|
||||
with:
|
||||
haxe-version: 4.3.7
|
||||
- name: Restore existing build cache for faster compilation
|
||||
uses: actions/cache@v4.2.3
|
||||
with:
|
||||
# not caching the bin folder to prevent asset duplication and stuff like that
|
||||
key: cache-build-windows
|
||||
path: |
|
||||
.haxelib/
|
||||
export/release/windows/haxe/
|
||||
export/release/windows/obj/
|
||||
- run: |
|
||||
echo "HXCPP_COMPILE_CACHE=~/.hxcpp" >> $GITHUB_ENV
|
||||
- name: Installing/Updating libraries
|
||||
run: |
|
||||
haxe -cp commandline -D analyzer-optimize --run Main setup -s --no-vscheck
|
||||
- name: Building the game
|
||||
run: |
|
||||
haxelib run lime build windows -DCOMPILE_EXPERIMENTAL
|
||||
- name: Uploading artifact (executable)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Codename Engine (Executable Only)
|
||||
path: export/release/windows/bin/CodenameEngine.exe
|
||||
- name: Uploading artifact (entire build)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Codename Engine
|
||||
path: export/release/windows/bin
|
||||
- name: Clearing already existing cache
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const caches = await github.rest.actions.getActionsCacheList({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
})
|
||||
for (const cache of caches.data.actions_caches) {
|
||||
if (cache.key == "cache-build-windows") {
|
||||
console.log('Clearing ' + cache.key + '...')
|
||||
await github.rest.actions.deleteActionsCacheById({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
cache_id: cache.id,
|
||||
})
|
||||
console.log("Cache cleared.")
|
||||
}
|
||||
}
|
||||
- name: Uploading new cache
|
||||
uses: actions/cache@v4.2.3
|
||||
with:
|
||||
# caching again since for some reason it doesnt work with the first post cache shit
|
||||
key: cache-build-windows
|
||||
path: |
|
||||
.haxelib/
|
||||
export/release/windows/haxe/
|
||||
export/release/windows/obj/
|
||||
|
||||
# didnt compile debug in the same job or github would have said that job wasn't completed until debug was done too (debug uploads are not essential)
|
||||
debug_build:
|
||||
name: Windows Debug Build
|
||||
permissions: write-all
|
||||
runs-on: windows-latest
|
||||
needs: build # since its low priority, it'll run after, so actions will concentrate first on normal builds
|
||||
steps:
|
||||
- name: Pulling the new commit
|
||||
uses: actions/checkout@v4
|
||||
- name: Setting up Haxe
|
||||
uses: krdlab/setup-haxe@v2
|
||||
with:
|
||||
haxe-version: 4.3.7
|
||||
- name: Restore existing build cache for faster compilation
|
||||
uses: actions/cache@v4.2.3
|
||||
with:
|
||||
# not caching the bin folder to prevent asset duplication and stuff like that
|
||||
key: cache-build-windows-debug
|
||||
path: |
|
||||
.haxelib/
|
||||
export/debug/windows/haxe/
|
||||
export/debug/windows/obj/
|
||||
- run: |
|
||||
echo "HXCPP_COMPILE_CACHE=~/.hxcpp" >> $GITHUB_ENV
|
||||
- name: Installing/Updating libraries
|
||||
run: |
|
||||
haxe -cp commandline -D analyzer-optimize --run Main setup -s --no-vscheck
|
||||
- name: Building the game
|
||||
run: |
|
||||
haxelib run lime build windows -debug
|
||||
- name: Uploading artifact (entire build)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Codename Engine Debug
|
||||
path: export/debug/windows/bin
|
||||
- name: Clearing already existing cache
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const caches = await github.rest.actions.getActionsCacheList({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
})
|
||||
for (const cache of caches.data.actions_caches) {
|
||||
if (cache.key == "cache-build-windows-debug") {
|
||||
console.log('Clearing ' + cache.key + '...')
|
||||
await github.rest.actions.deleteActionsCacheById({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
cache_id: cache.id,
|
||||
})
|
||||
console.log("Cache cleared.")
|
||||
}
|
||||
}
|
||||
- name: Uploading new cache
|
||||
uses: actions/cache@v4.2.3
|
||||
with:
|
||||
# caching again since for some reason it doesnt work with the first post cache shit
|
||||
key: cache-build-windows-debug
|
||||
path: |
|
||||
.haxelib/
|
||||
export/debug/windows/haxe/
|
||||
export/debug/windows/obj/
|
||||
@@ -75,7 +75,7 @@ function onCountdown(event) {
|
||||
};
|
||||
}
|
||||
|
||||
function onPlayerHit(event:NoteHitEvent) {
|
||||
function onRatingsShown(event:RatingsShowEvent) {
|
||||
if (!enablePixelUI) return;
|
||||
event.ratingPrefix = "stages/school/ui/";
|
||||
event.ratingScale = daPixelZoom * 0.7;
|
||||
|
||||
@@ -1,19 +1,98 @@
|
||||
package funkin.backend;
|
||||
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxG;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
import funkin.backend.system.Flags;
|
||||
|
||||
class FunkinText extends FlxText {
|
||||
public function new(X:Float = 0, Y:Float = 0, FieldWidth:Float = 0, ?Text:String, ?Size:Int, Border:Bool = true) {
|
||||
if (Size == null) Size = Flags.DEFAULT_FONT_SIZE;
|
||||
class FunkinText extends FlxText
|
||||
{
|
||||
public var zoomFactor:Float = 1;
|
||||
public var zoomFactorEnabled:Bool = true;
|
||||
|
||||
public function new(X:Float = 0, Y:Float = 0, FieldWidth:Float = 0, ?Text:String, ?Size:Int, Border:Bool = true)
|
||||
{
|
||||
if (Size == null)
|
||||
Size = Flags.DEFAULT_FONT_SIZE;
|
||||
|
||||
super(X, Y, FieldWidth, Text, Size);
|
||||
|
||||
setFormat(Paths.font(Flags.DEFAULT_FONT), Size, FlxColor.WHITE);
|
||||
if (Border) {
|
||||
|
||||
if (Border)
|
||||
{
|
||||
borderStyle = OUTLINE;
|
||||
borderSize = 1;
|
||||
borderColor = 0xFF000000;
|
||||
}
|
||||
}
|
||||
|
||||
private inline function __shouldDoZoomFactor():Bool
|
||||
{
|
||||
return zoomFactorEnabled && zoomFactor != 1;
|
||||
}
|
||||
|
||||
private inline function __getZoomScaleX(camera:FlxCamera):Float
|
||||
{
|
||||
return (camera.scaleX > 0 ? Math.max : Math.min)(0, FlxMath.lerp(1 / camera.scaleX, 1, zoomFactor));
|
||||
}
|
||||
|
||||
private inline function __getZoomScaleY(camera:FlxCamera):Float
|
||||
{
|
||||
return (camera.scaleY > 0 ? Math.max : Math.min)(0, FlxMath.lerp(1 / camera.scaleY, 1, zoomFactor));
|
||||
}
|
||||
|
||||
private inline function __getZoomAnchorX(camera:FlxCamera):Float
|
||||
{
|
||||
if (Flags.USE_LEGACY_ZOOM_FACTOR)
|
||||
return camera.width * 0.5;
|
||||
|
||||
return camera.width * 0.5 + camera.scroll.x * scrollFactor.x;
|
||||
}
|
||||
|
||||
private inline function __getZoomAnchorY(camera:FlxCamera):Float
|
||||
{
|
||||
if (Flags.USE_LEGACY_ZOOM_FACTOR)
|
||||
return camera.height * 0.5;
|
||||
|
||||
return camera.height * 0.5 + camera.scroll.y * scrollFactor.y;
|
||||
}
|
||||
|
||||
override public function draw():Void
|
||||
{
|
||||
if (!__shouldDoZoomFactor())
|
||||
{
|
||||
super.draw();
|
||||
return;
|
||||
}
|
||||
|
||||
var camera:FlxCamera = this.camera;
|
||||
|
||||
if (camera == null)
|
||||
camera = FlxG.camera;
|
||||
|
||||
var oldX:Float = x;
|
||||
var oldY:Float = y;
|
||||
var oldScaleX:Float = scale.x;
|
||||
var oldScaleY:Float = scale.y;
|
||||
|
||||
var zoomScaleX:Float = __getZoomScaleX(camera);
|
||||
var zoomScaleY:Float = __getZoomScaleY(camera);
|
||||
|
||||
var anchorX:Float = __getZoomAnchorX(camera);
|
||||
var anchorY:Float = __getZoomAnchorY(camera);
|
||||
|
||||
x = (x - anchorX) * zoomScaleX + anchorX;
|
||||
y = (y - anchorY) * zoomScaleY + anchorY;
|
||||
|
||||
scale.set(scale.x * zoomScaleX, scale.y * zoomScaleY);
|
||||
|
||||
super.draw();
|
||||
|
||||
x = oldX;
|
||||
y = oldY;
|
||||
scale.set(oldScaleX, oldScaleY);
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,9 @@ import lime.media.AudioBuffer;
|
||||
import lime.text.Font;
|
||||
import lime.utils.Bytes;
|
||||
import openfl.utils.AssetLibrary;
|
||||
#if sys
|
||||
import sys.io.File;
|
||||
#end
|
||||
|
||||
#if MOD_SUPPORT
|
||||
import funkin.backend.utils.SysZip.SysZipEntry;
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
package funkin.backend.scripting.events.gameplay;
|
||||
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.tweens.FlxTween;
|
||||
|
||||
final class RatingsShowEvent extends CancellableEvent
|
||||
{
|
||||
/**
|
||||
* Rating sprite (may be null)
|
||||
*/
|
||||
public var ratingSprite:Null<FlxSprite>;
|
||||
/**
|
||||
* Number sprite (may be null)
|
||||
*/
|
||||
public var numberSprite:Null<FlxSprite>;
|
||||
/**
|
||||
* Combo sprite (may be null)
|
||||
*/
|
||||
public var comboSprite:Null<FlxSprite>;
|
||||
/**
|
||||
* Scale of combo numbers. (may be null)
|
||||
*/
|
||||
public var numScale:Null<Float> = 0.5;
|
||||
/**
|
||||
* Whenever antialiasing should be enabled on combo numbers. (may be null)
|
||||
*/
|
||||
public var numAntialiasing:Null<Bool> = true;
|
||||
/**
|
||||
* Scale of the rating sprites. (may be null)
|
||||
*/
|
||||
public var ratingScale:Null<Float> = 0.7;
|
||||
/**
|
||||
* Whenever antialiasing should be enabled on ratings. (may be null)
|
||||
*/
|
||||
public var ratingAntialiasing:Null<Bool> = true;
|
||||
/**
|
||||
* Prefix of the rating sprite path. Defaults to "game/score/"
|
||||
*/
|
||||
public var ratingPrefix:String;
|
||||
/**
|
||||
* Suffix of the rating sprite path.
|
||||
*/
|
||||
public var ratingSuffix:String;
|
||||
/**
|
||||
* The sprite's acceleration.
|
||||
*/
|
||||
public var acceleration:Float;
|
||||
/**
|
||||
* A FlxPoint which x or y properties preposition the sprites current velocity.
|
||||
*/
|
||||
public var velocity:FlxPoint;
|
||||
/**
|
||||
* The duration of the sprite's alpha tween.
|
||||
*/
|
||||
public var tweenDuration:Float;
|
||||
/**
|
||||
* The start delay of the sprite's alpha tween.
|
||||
*/
|
||||
public var startDelay:Float;
|
||||
/**
|
||||
* Whenever the Rating sprites should be shown or not.
|
||||
*/
|
||||
public var displayRating:Bool;
|
||||
/**
|
||||
* Whenever the Rating sprites should be shown or not.
|
||||
*/
|
||||
public var displayNumbers:Bool;
|
||||
/**
|
||||
* Whenever the Combo sprite should be shown or not (like old Week 7 patches).
|
||||
*/
|
||||
public var displayCombo:Bool;
|
||||
/**
|
||||
* Whether the sprite should be tweened or not.
|
||||
*/
|
||||
public var playTween:Bool;
|
||||
/**
|
||||
* The amount of spacing for the combo numbers. (may be null)
|
||||
*/
|
||||
public var numSpacing:Null<Float>;
|
||||
/**
|
||||
* The position of the sprite.
|
||||
*/
|
||||
public var position:FlxPoint;
|
||||
/**
|
||||
* Whether to reset the sprite or not.
|
||||
*/
|
||||
public var resetSprite:Bool;
|
||||
/**
|
||||
* The rating name of the rating sprite. (may be null)
|
||||
*/
|
||||
public var rating:Null<String>;
|
||||
/**
|
||||
* The FlxTween instance. (null before "onPostRatingsShown")
|
||||
*/
|
||||
public var tween:Null<FlxTween>;
|
||||
}
|
||||
@@ -34,11 +34,11 @@ final class NoteHitEvent extends CancellableEvent {
|
||||
/**
|
||||
* Whenever the Rating sprites should be shown or not.
|
||||
*/
|
||||
public var displayRating:Bool;
|
||||
public var displayRating:Null<Bool>;
|
||||
/**
|
||||
* Whenever the Combo sprite should be shown or not (like old Week 7 patches).
|
||||
*/
|
||||
public var displayCombo:Bool;
|
||||
public var displayCombo:Null<Bool>;
|
||||
/**
|
||||
* Note that has been pressed
|
||||
*/
|
||||
@@ -66,11 +66,11 @@ final class NoteHitEvent extends CancellableEvent {
|
||||
/**
|
||||
* Prefix of the rating sprite path. Defaults to "game/score/"
|
||||
*/
|
||||
public var ratingPrefix:String;
|
||||
public var ratingPrefix:Null<String>;
|
||||
/**
|
||||
* Suffix of the rating sprite path.
|
||||
*/
|
||||
public var ratingSuffix:String;
|
||||
public var ratingSuffix:Null<String>;
|
||||
/**
|
||||
* Direction of the press (0 = Left, 1 = Down, 2 = Up, 3 = Right)
|
||||
*/
|
||||
@@ -98,19 +98,19 @@ final class NoteHitEvent extends CancellableEvent {
|
||||
/**
|
||||
* Scale of combo numbers.
|
||||
*/
|
||||
public var numScale:Float = 0.5;
|
||||
public var numScale:Null<Float>;
|
||||
/**
|
||||
* Whenever antialiasing should be enabled on combo number.
|
||||
*/
|
||||
public var numAntialiasing:Bool = true;
|
||||
public var numAntialiasing:Null<Bool>;
|
||||
/**
|
||||
* Scale of ratings.
|
||||
*/
|
||||
public var ratingScale:Float = 0.7;
|
||||
public var ratingScale:Null<Float>;
|
||||
/**
|
||||
* Whenever antialiasing should be enabled on ratings.
|
||||
*/
|
||||
public var ratingAntialiasing:Bool = true;
|
||||
public var ratingAntialiasing:Null<Bool>;
|
||||
/**
|
||||
* Whenever the animation should be forced to play (if it's null it will be forced based on the sprite's data xml, if it has one).
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,766 @@
|
||||
package funkin.backend.shaders;
|
||||
|
||||
import haxe.Timer;
|
||||
import openfl.filters.BitmapFilter;
|
||||
import openfl.filters.BitmapFilterShader;
|
||||
import openfl.display.BitmapData;
|
||||
import openfl.display.DisplayObjectRenderer;
|
||||
import openfl.display.BlendMode;
|
||||
import openfl.display.Shader;
|
||||
import openfl.geom.Point;
|
||||
import openfl.geom.Rectangle;
|
||||
|
||||
/**
|
||||
This BloomEffect was modified by heihua based on openfl.filters.BlurFilter.
|
||||
The BloomEffect class applies a bloom/glow visual effect to display objects.
|
||||
A bloom effect extracts bright areas from an image, blurs them, and combines
|
||||
them back to create a glowing halo around bright objects. This effect is
|
||||
commonly used to simulate intense light, emissive materials, or to add a
|
||||
dreamy, atmospheric quality to scenes.
|
||||
|
||||
The effect consists of three stages:
|
||||
1. Extraction - Bright pixels above a threshold are extracted
|
||||
2. Blurring - The extracted bright areas are blurred horizontally and vertically
|
||||
3. Combination - The blurred result is blended back with the original image
|
||||
**/
|
||||
|
||||
@:noCustomClass
|
||||
class BloomEffect extends BitmapFilter
|
||||
{
|
||||
@:noCompletion private static var __blurShader:BlurShader;
|
||||
@:noCompletion private static var __combineShader:CombineShader;
|
||||
@:noCompletion private static var __extractShader:ExtractShader;
|
||||
@:noCompletion private static var __extractLowShader:ExtractLowShader;
|
||||
|
||||
/**
|
||||
Values that are a power of 2 (such as 2, 4, 8, 16 and 32) are optimized to render
|
||||
more quickly than other values.
|
||||
**/
|
||||
public var blurX(get, set):Float;
|
||||
|
||||
/**
|
||||
Values that are a power of 2 (such as 2, 4, 8, 16 and 32) are optimized to render
|
||||
more quickly than other values.
|
||||
**/
|
||||
public var blurY(get, set):Float;
|
||||
|
||||
/**
|
||||
The downscaling factor for bloom rendering. Higher values significantly reduce
|
||||
GPU performance cost, but setting values too high may cause noticeable flickering.
|
||||
Recommended range is 8-24.
|
||||
**/
|
||||
public var quality(get, set):Float;
|
||||
|
||||
/**
|
||||
The intensity of the bloom effect. Higher values produce more pronounced bloom.
|
||||
**/
|
||||
public var strength(get, set):Float;
|
||||
|
||||
/**
|
||||
The brightness threshold for bloom extraction. Pixels brighter than this value
|
||||
will contribute to the bloom effect. Value range is 0.0 to 1.0.
|
||||
**/
|
||||
public var threshold(get, set):Float;
|
||||
|
||||
/**
|
||||
The smoothness of the threshold transition in blur shader.
|
||||
Higher values create a smoother transition for brightness correction.
|
||||
Value range is 0.0 to 1.0. Default is 0.1.
|
||||
**/
|
||||
public var smoothness(get, set):Float;
|
||||
|
||||
/**
|
||||
Enables extended rendering area to avoid edge artifacts. Enabling this option
|
||||
will increase performance cost. Generally not required when rendering to camera.
|
||||
**/
|
||||
public var extension(get, set):Bool;
|
||||
|
||||
/**
|
||||
Low-quality pixel sampling mode. Disabling it significantly reduces screen flickering,
|
||||
with minimal performance impact on desktop platforms but a higher
|
||||
performance cost on non-desktop platforms.
|
||||
**/
|
||||
public var useLowQualityExtract(get, set):Bool;
|
||||
|
||||
/**
|
||||
The weights for calculating brightness (RGB to grayscale).
|
||||
Order: [Red, Green, Blue]. Default is [0.2126, 0.7152, 0.0722].
|
||||
**/
|
||||
public var weights(get, set):Array<Float>;
|
||||
|
||||
/**
|
||||
The blend mode used when combining the bloom with the original image.
|
||||
BlendMode currently supports: (BlendMode.ADD, BlendMode.ALPHA, BlendMode.HARDLIGHT,
|
||||
BlendMode.LIGHTEN, BlendMode.MULTIPLY, BlendMode.OVERLAY, BlendMode.SCREEN,
|
||||
BlendMode.COLORDODGE, BlendMode.SOFTLIGHT).
|
||||
Default is BlendMode.ADD.
|
||||
**/
|
||||
public var blendMode(get, set):BlendMode;
|
||||
|
||||
@:noCompletion private var __blurX:Float;
|
||||
@:noCompletion private var __blurY:Float;
|
||||
@:noCompletion private var __horizontalPasses:Int;
|
||||
@:noCompletion private var __quality:Float;
|
||||
@:noCompletion private var __verticalPasses:Int;
|
||||
@:noCompletion private var __strength:Float;
|
||||
@:noCompletion private var __threshold:Float;
|
||||
@:noCompletion private var __smoothness:Float;
|
||||
@:noCompletion private var __extension:Bool;
|
||||
@:noCompletion private var __useLowQualityExtract:Bool;
|
||||
@:noCompletion private var __weights:Array<Float>;
|
||||
@:noCompletion private var __blendMode:BlendMode;
|
||||
|
||||
#if openfljs
|
||||
@:noCompletion private static function __init__()
|
||||
{
|
||||
untyped Object.defineProperties(BloomEffect.prototype, {
|
||||
"blurX": {
|
||||
get: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_blurX (); }"),
|
||||
set: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function (v) { return this.set_blurX (v); }")
|
||||
},
|
||||
"blurY": {
|
||||
get: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_blurY (); }"),
|
||||
set: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function (v) { return this.set_blurY (v); }")
|
||||
},
|
||||
"quality": {
|
||||
get: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_quality (); }"),
|
||||
set: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function (v) { return this.set_quality (v); }")
|
||||
},
|
||||
"strength": {
|
||||
get: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_strength (); }"),
|
||||
set: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function (v) { return this.set_strength (v); }")
|
||||
},
|
||||
"threshold": {
|
||||
get: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_threshold (); }"),
|
||||
set: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function (v) { return this.set_threshold (v); }")
|
||||
},
|
||||
"useLowQualityExtract": {
|
||||
get: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_useLowQualityExtract (); }"),
|
||||
set: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function (v) { return this.set_useLowQualityExtract (v); }")
|
||||
},
|
||||
"weights": {
|
||||
get: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_weights (); }"),
|
||||
set: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function (v) { return this.set_weights (v); }")
|
||||
},
|
||||
"blendMode": {
|
||||
get: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_blendMode (); }"),
|
||||
set: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function (v) { return this.set_blendMode (v); }")
|
||||
},
|
||||
});
|
||||
}
|
||||
#end
|
||||
|
||||
/**
|
||||
Initializes the bloom filter with the specified parameters.
|
||||
|
||||
@param blurX The amount to blur horizontally.
|
||||
@param blurY The amount to blur vertically.
|
||||
@param quality The downscaling factor for bloom rendering (higher values reduce
|
||||
GPU cost but may cause flickering if too high).
|
||||
@param strength The intensity of the bloom effect.
|
||||
@param threshold The brightness threshold for bloom extraction (0.0 to 1.0).
|
||||
@param smoothness The smoothness of threshold transition in blur (0.0 to 1.0).
|
||||
@param useLowQualityExtract Enables performance-optimized extraction with
|
||||
potentially more flickering.
|
||||
**/
|
||||
public function new(blurX:Float = 50, blurY:Float = 50, quality:Float = 8, strength:Float = 0.6, threshold:Float = 0.6, smoothness:Float = 0.1, useLowQualityExtract:Bool = true)
|
||||
{
|
||||
super();
|
||||
|
||||
if (__blurShader == null) __blurShader = new BlurShader();
|
||||
if (__combineShader == null) __combineShader = new CombineShader();
|
||||
if (__extractShader == null) __extractShader = new ExtractShader();
|
||||
if (__extractLowShader == null) __extractLowShader = new ExtractLowShader();
|
||||
|
||||
this.blurX = blurX;
|
||||
this.blurY = blurY;
|
||||
this.quality = quality;
|
||||
this.strength = strength;
|
||||
this.threshold = threshold;
|
||||
this.smoothness = smoothness;
|
||||
this.extension = false;
|
||||
this.useLowQualityExtract = useLowQualityExtract;
|
||||
this.weights = [0.2126, 0.7152, 0.0722];
|
||||
this.blendMode = BlendMode.ADD;
|
||||
|
||||
__needSecondBitmapData = true;
|
||||
__preserveObject = true;
|
||||
__renderDirty = true;
|
||||
}
|
||||
|
||||
public override function clone():BitmapFilter
|
||||
{
|
||||
var cloned = new BloomEffect(__blurX, __blurY, __quality, __strength, __threshold, __smoothness, __useLowQualityExtract);
|
||||
cloned.weights = __weights != null ? __weights.copy() : [0.2126, 0.7152, 0.0722];
|
||||
cloned.blendMode = __blendMode;
|
||||
return cloned;
|
||||
}
|
||||
|
||||
@:noCompletion private override function __applyFilter(bitmapData:BitmapData, sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point):BitmapData
|
||||
{
|
||||
trace("Due to technical limitations, I'm unable to implement the bitmapData rendering method. If you know how to implement it, you're welcome to contribute this feature.");
|
||||
return sourceBitmapData;
|
||||
}
|
||||
|
||||
@:noCompletion private override function __initShader(renderer:DisplayObjectRenderer, pass:Int, sourceBitmapData:BitmapData):Shader
|
||||
{
|
||||
final numBlurPasses = __horizontalPasses + __verticalPasses;
|
||||
|
||||
switch pass
|
||||
{
|
||||
case 0:
|
||||
if (__useLowQualityExtract)
|
||||
{
|
||||
__extractLowShader.uThreshold.value[0] = __threshold;
|
||||
__extractLowShader.uSmoothness.value[0] = __smoothness;
|
||||
__extractLowShader.uQuality.value[0] = __quality;
|
||||
__extractLowShader.uWeights.value = __weights;
|
||||
return __extractLowShader;
|
||||
}
|
||||
else
|
||||
{
|
||||
__extractShader.uThreshold.value[0] = __threshold;
|
||||
__extractShader.uSmoothness.value[0] = __smoothness;
|
||||
__extractShader.uQuality.value[0] = __quality;
|
||||
__extractShader.uWeights.value = __weights;
|
||||
return __extractShader;
|
||||
}
|
||||
|
||||
case _ if (pass <= numBlurPasses):
|
||||
final blurPass = pass - 1;
|
||||
final isHorizontal = blurPass < __horizontalPasses;
|
||||
|
||||
final scalePass = isHorizontal ? blurPass : blurPass - __horizontalPasses;
|
||||
|
||||
final scale = Math.pow(0.5, scalePass >> 1);
|
||||
final blurRadius = isHorizontal ? blurX * scale : blurY * scale;
|
||||
|
||||
if (isHorizontal)
|
||||
{
|
||||
__blurShader.uRadius.value[0] = blurRadius / __quality;
|
||||
__blurShader.uRadius.value[1] = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
__blurShader.uRadius.value[0] = 0.0;
|
||||
__blurShader.uRadius.value[1] = blurRadius / __quality;
|
||||
}
|
||||
__blurShader.uQuality.value[0] = __quality;
|
||||
__blurShader.uStrength.value[0] = Math.pow(__strength, 1.0 / numBlurPasses);
|
||||
|
||||
return __blurShader;
|
||||
|
||||
default:
|
||||
__combineShader.sourceBitmap.input = sourceBitmapData;
|
||||
__combineShader.uThreshold.value[0] = __threshold;
|
||||
__combineShader.uQuality.value[0] = __quality;
|
||||
__combineShader.uBlendMode.value[0] = cast __blendMode;
|
||||
return __combineShader;
|
||||
}
|
||||
}
|
||||
|
||||
// Get & Set Methods
|
||||
@:noCompletion private function get_blurX():Float
|
||||
{
|
||||
return __blurX;
|
||||
}
|
||||
|
||||
@:noCompletion private function set_blurX(value:Float):Float
|
||||
{
|
||||
if (value != __blurX)
|
||||
{
|
||||
__blurX = value;
|
||||
__renderDirty = true;
|
||||
|
||||
if (!__extension)
|
||||
{
|
||||
// Setting it to 1 prevents bloom flickering at the screen edges
|
||||
__leftExtension = 1;
|
||||
__rightExtension = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
__leftExtension = (value > 0 ? Math.ceil(value) : 0);
|
||||
__rightExtension = __leftExtension;
|
||||
}
|
||||
|
||||
__horizontalPasses = (value <= 0) ? 0 : Math.ceil(value * 0.0625 / quality) + 1;
|
||||
__numShaderPasses = __horizontalPasses + __verticalPasses + 2;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@:noCompletion private function get_blurY():Float
|
||||
{
|
||||
return __blurY;
|
||||
}
|
||||
|
||||
@:noCompletion private function set_blurY(value:Float):Float
|
||||
{
|
||||
if (value != __blurY)
|
||||
{
|
||||
__blurY = value;
|
||||
__renderDirty = true;
|
||||
|
||||
if (!__extension)
|
||||
{
|
||||
// Setting it to 1 prevents bloom flickering at the screen edges
|
||||
__topExtension = 1;
|
||||
__bottomExtension = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
__topExtension = (value > 0 ? Math.ceil(value) : 0);
|
||||
__bottomExtension = __topExtension;
|
||||
}
|
||||
|
||||
__verticalPasses = (value <= 0) ? 0 : Math.ceil(value * 0.0625 / quality) + 1;
|
||||
__numShaderPasses = __horizontalPasses + __verticalPasses + 2;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@:noCompletion private function get_quality():Float
|
||||
{
|
||||
return __quality;
|
||||
}
|
||||
|
||||
@:noCompletion private function set_quality(value:Float):Float
|
||||
{
|
||||
__horizontalPasses = (__blurX <= 0) ? 0 : Math.round(__blurX * 0.125 / value) + 1;
|
||||
__verticalPasses = (__blurY <= 0) ? 0 : Math.round(__blurY * 0.125 / value) + 1;
|
||||
__numShaderPasses = __horizontalPasses + __verticalPasses + 2;
|
||||
|
||||
if (value != __quality)
|
||||
__renderDirty = true;
|
||||
return __quality = value;
|
||||
}
|
||||
|
||||
@:noCompletion private function get_strength():Float
|
||||
{
|
||||
return __strength;
|
||||
}
|
||||
|
||||
@:noCompletion private function set_strength(value:Float):Float
|
||||
{
|
||||
if (value != __strength)
|
||||
{
|
||||
__strength = value;
|
||||
__renderDirty = true;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@:noCompletion private function get_threshold():Float
|
||||
{
|
||||
return __threshold;
|
||||
}
|
||||
|
||||
@:noCompletion private function set_threshold(value:Float):Float
|
||||
{
|
||||
if (value != __threshold)
|
||||
{
|
||||
__threshold = value;
|
||||
__renderDirty = true;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@:noCompletion private function get_smoothness():Float
|
||||
{
|
||||
return __smoothness;
|
||||
}
|
||||
|
||||
@:noCompletion private function set_smoothness(value:Float):Float
|
||||
{
|
||||
if (value != __smoothness)
|
||||
{
|
||||
__smoothness = value;
|
||||
__renderDirty = true;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@:noCompletion private function get_extension():Bool
|
||||
{
|
||||
return __extension;
|
||||
}
|
||||
|
||||
@:noCompletion private function set_extension(value:Bool):Bool
|
||||
{
|
||||
if (value != __extension)
|
||||
{
|
||||
__extension = value;
|
||||
|
||||
if (!value)
|
||||
__leftExtension = __rightExtension = __topExtension = __bottomExtension = 0;
|
||||
else
|
||||
{
|
||||
__leftExtension = __rightExtension = (__blurX > 0 ? Math.ceil(__blurX) : 0);
|
||||
__topExtension = __bottomExtension = (__blurY > 0 ? Math.ceil(__blurY) : 0);
|
||||
}
|
||||
|
||||
__renderDirty = true;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@:noCompletion private function get_useLowQualityExtract():Bool
|
||||
{
|
||||
return __useLowQualityExtract;
|
||||
}
|
||||
|
||||
@:noCompletion private function set_useLowQualityExtract(value:Bool):Bool
|
||||
{
|
||||
if (value != __useLowQualityExtract)
|
||||
{
|
||||
__useLowQualityExtract = value;
|
||||
__renderDirty = true;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@:noCompletion private function get_weights():Array<Float>
|
||||
{
|
||||
return __weights;
|
||||
}
|
||||
|
||||
@:noCompletion private function set_weights(value:Array<Float>):Array<Float>
|
||||
{
|
||||
if (value != __weights)
|
||||
{
|
||||
__weights = value;
|
||||
__renderDirty = true;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@:noCompletion private function get_blendMode():BlendMode
|
||||
{
|
||||
return __blendMode;
|
||||
}
|
||||
|
||||
@:noCompletion private function set_blendMode(value:BlendMode):BlendMode
|
||||
{
|
||||
if (value != __blendMode)
|
||||
{
|
||||
__blendMode = value;
|
||||
__renderDirty = true;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
private class BlurShader extends BitmapFilterShader
|
||||
{
|
||||
@:glFragmentSource("
|
||||
uniform sampler2D openfl_Texture;
|
||||
uniform float uStrength;
|
||||
|
||||
varying mat2 vBlurCoord0;
|
||||
varying mat2 vBlurCoord1;
|
||||
varying vec2 vBlurCoord2;
|
||||
varying mat2 vBlurCoord3;
|
||||
varying mat2 vBlurCoord4;
|
||||
|
||||
varying float invQuality;
|
||||
|
||||
void main(void) {
|
||||
if ((all(greaterThanEqual(vBlurCoord2, vec2(0.0))) && all(lessThanEqual(vBlurCoord2, vec2(1.0)))) == false) return;
|
||||
|
||||
vec4 sum = texture2D(openfl_Texture, clamp(vBlurCoord0[0], 0.0, invQuality)) * 0.028532;
|
||||
sum += texture2D(openfl_Texture, clamp(vBlurCoord0[1], 0.0, invQuality)) * 0.067234;
|
||||
sum += texture2D(openfl_Texture, clamp(vBlurCoord1[0], 0.0, invQuality)) * 0.124009;
|
||||
sum += texture2D(openfl_Texture, clamp(vBlurCoord1[1], 0.0, invQuality)) * 0.179044;
|
||||
sum += texture2D(openfl_Texture, clamp(vBlurCoord2, 0.0, invQuality)) * 0.202360;
|
||||
sum += texture2D(openfl_Texture, clamp(vBlurCoord3[0], 0.0, invQuality)) * 0.179044;
|
||||
sum += texture2D(openfl_Texture, clamp(vBlurCoord3[1], 0.0, invQuality)) * 0.124009;
|
||||
sum += texture2D(openfl_Texture, clamp(vBlurCoord4[0], 0.0, invQuality)) * 0.067234;
|
||||
sum += texture2D(openfl_Texture, clamp(vBlurCoord4[1], 0.0, invQuality)) * 0.028532;
|
||||
gl_FragColor = sum * uStrength;
|
||||
}
|
||||
")
|
||||
@:glVertexSource("
|
||||
attribute vec4 openfl_Position;
|
||||
attribute vec2 openfl_TextureCoord;
|
||||
|
||||
uniform mat4 openfl_Matrix;
|
||||
|
||||
uniform vec2 uRadius;
|
||||
uniform vec2 uTextureSize;
|
||||
uniform float uQuality;
|
||||
|
||||
varying mat2 vBlurCoord0;
|
||||
varying mat2 vBlurCoord1;
|
||||
varying vec2 vBlurCoord2;
|
||||
varying mat2 vBlurCoord3;
|
||||
varying mat2 vBlurCoord4;
|
||||
|
||||
varying float invQuality;
|
||||
|
||||
void main(void) {
|
||||
vec4 pos = openfl_Position;
|
||||
invQuality = 1.0 / uQuality;
|
||||
|
||||
pos.xy *= invQuality;
|
||||
gl_Position = openfl_Matrix * pos;
|
||||
|
||||
vec2 r = uRadius / uTextureSize;
|
||||
vec2 coord = openfl_TextureCoord * invQuality;
|
||||
vBlurCoord0[0] = coord - r;
|
||||
vBlurCoord0[1] = coord - r * 0.25;
|
||||
vBlurCoord1[0] = coord - r * 0.5;
|
||||
vBlurCoord1[1] = coord - r * 0.75;
|
||||
vBlurCoord2 = coord;
|
||||
vBlurCoord3[0] = coord + r * 0.25;
|
||||
vBlurCoord3[1] = coord + r * 0.5;
|
||||
vBlurCoord4[0] = coord + r * 0.75;
|
||||
vBlurCoord4[1] = coord + r;
|
||||
}
|
||||
")
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
||||
uStrength.value = [1.0];
|
||||
uRadius.value = [0, 0];
|
||||
uQuality.value = [8];
|
||||
uTextureSize.value = [1, 1];
|
||||
}
|
||||
|
||||
@:noCompletion private override function __update():Void
|
||||
{
|
||||
#if !macro
|
||||
uTextureSize.value[0] = __texture.input.width;
|
||||
uTextureSize.value[1] = __texture.input.height;
|
||||
#end
|
||||
|
||||
super.__update();
|
||||
}
|
||||
}
|
||||
|
||||
private class ExtractLowShader extends BitmapFilterShader
|
||||
{
|
||||
@:glFragmentSource("
|
||||
uniform sampler2D openfl_Texture;
|
||||
uniform float uThreshold;
|
||||
uniform float uSmoothness;
|
||||
uniform vec3 uWeights;
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main(void) {
|
||||
if ((all(greaterThanEqual(vTexCoord, vec2(0.0))) && all(lessThanEqual(vTexCoord, vec2(1.0)))) == false) return;
|
||||
|
||||
vec4 texel = texture2D(openfl_Texture, vTexCoord);
|
||||
float brightness = min(dot(texel.rgb, uWeights), 1.0);
|
||||
float mask = smoothstep(uThreshold, uThreshold + uSmoothness, brightness);
|
||||
gl_FragColor = texel * mask;
|
||||
}
|
||||
")
|
||||
@:glVertexSource("
|
||||
attribute vec4 openfl_Position;
|
||||
attribute vec2 openfl_TextureCoord;
|
||||
uniform mat4 openfl_Matrix;
|
||||
uniform vec2 openfl_TextureSize;
|
||||
uniform float uQuality;
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main(void) {
|
||||
vec4 pos = openfl_Position;
|
||||
pos.xy /= uQuality;
|
||||
gl_Position = openfl_Matrix * pos;
|
||||
vTexCoord = openfl_TextureCoord;
|
||||
}
|
||||
")
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
||||
uThreshold.value = [0.6];
|
||||
uSmoothness.value = [0.1];
|
||||
uQuality.value = [8];
|
||||
uWeights.value = [0.2126, 0.7152, 0.0722];
|
||||
}
|
||||
}
|
||||
|
||||
private class ExtractShader extends BitmapFilterShader
|
||||
{
|
||||
@:glFragmentSource("
|
||||
uniform sampler2D openfl_Texture;
|
||||
uniform vec2 openfl_TextureSize;
|
||||
uniform float uThreshold;
|
||||
uniform float uSmoothness;
|
||||
uniform float uQuality;
|
||||
uniform vec3 uWeights;
|
||||
varying vec2 vTexCoord;
|
||||
varying vec4 border;
|
||||
|
||||
void main(void) {
|
||||
if ((all(greaterThanEqual(vTexCoord, border.xy)) && all(lessThanEqual(vTexCoord, border.zw))) == false) return;
|
||||
|
||||
float quality = floor(uQuality) / 2.0;
|
||||
vec2 texelSize = 1.0 / openfl_TextureSize;
|
||||
|
||||
vec4 accumulated = vec4(0.0);
|
||||
int sampleCount = 0;
|
||||
|
||||
|
||||
for (float dx = -quality; dx <= quality; dx += 2.0) {
|
||||
for (float dy = -quality; dy <= quality; dy += 2.0) {
|
||||
vec2 sampleCoord = vTexCoord + vec2(dx, dy) * texelSize;
|
||||
|
||||
vec4 texel = texture2D(openfl_Texture, sampleCoord);
|
||||
float brightness = min(dot(texel.rgb, uWeights), 1.0);
|
||||
float mask = smoothstep(uThreshold, uThreshold + uSmoothness, brightness);
|
||||
accumulated += texel * mask;
|
||||
sampleCount++;
|
||||
}
|
||||
}
|
||||
|
||||
gl_FragColor = accumulated / float(sampleCount);
|
||||
}
|
||||
")
|
||||
@:glVertexSource("
|
||||
attribute vec4 openfl_Position;
|
||||
attribute vec2 openfl_TextureCoord;
|
||||
uniform mat4 openfl_Matrix;
|
||||
uniform vec2 openfl_TextureSize;
|
||||
uniform float uQuality;
|
||||
varying vec2 vTexCoord;
|
||||
varying vec4 border;
|
||||
|
||||
void main(void) {
|
||||
vec4 pos = openfl_Position;
|
||||
pos.xy /= uQuality;
|
||||
|
||||
vec2 size = 1.0 / openfl_TextureSize * uQuality;
|
||||
border = vec4(size, vec2(1.0) - size);
|
||||
|
||||
gl_Position = openfl_Matrix * pos;
|
||||
vTexCoord = openfl_TextureCoord;
|
||||
}
|
||||
")
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
||||
uThreshold.value = [0.6];
|
||||
uSmoothness.value = [0.1];
|
||||
uQuality.value = [8];
|
||||
uWeights.value = [0.2126, 0.7152, 0.0722];
|
||||
}
|
||||
}
|
||||
|
||||
private class CombineShader extends BitmapFilterShader
|
||||
{
|
||||
@:glFragmentSource("
|
||||
uniform sampler2D openfl_Texture;
|
||||
uniform sampler2D sourceBitmap;
|
||||
uniform float uThreshold;
|
||||
uniform int uBlendMode;
|
||||
varying vec4 textureCoords;
|
||||
|
||||
vec4 blendScreen(vec4 src, vec4 bloom) {
|
||||
return vec4(1.0) - (vec4(1.0) - src) * (vec4(1.0) - bloom);
|
||||
}
|
||||
|
||||
vec4 blendMultiply(vec4 src, vec4 bloom) {
|
||||
return src * bloom;
|
||||
}
|
||||
|
||||
vec4 blendLighten(vec4 src, vec4 bloom) {
|
||||
return max(src, bloom);
|
||||
}
|
||||
|
||||
vec4 blendOverlay(vec4 src, vec4 bloom) {
|
||||
vec4 result = vec4(0.0);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (src[i] < 0.5) {
|
||||
result[i] = 2.0 * src[i] * bloom[i];
|
||||
} else {
|
||||
result[i] = 1.0 - 2.0 * (1.0 - src[i]) * (1.0 - bloom[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
vec4 blendColorDodge(vec4 src, vec4 bloom) {
|
||||
vec4 result = vec4(0.0);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (bloom[i] < 1.0) {
|
||||
result[i] = min(1.0, src[i] / (1.0 - bloom[i]));
|
||||
} else {
|
||||
result[i] = 1.0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
vec4 blendSoftLight(vec4 src, vec4 bloom) {
|
||||
vec4 result = vec4(0.0);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (bloom[i] < 0.5) {
|
||||
result[i] = src[i] - (1.0 - 2.0 * bloom[i]) * src[i] * (1.0 - src[i]);
|
||||
} else {
|
||||
float d = (src[i] <= 0.25) ? ((16.0 * src[i] - 12.0) * src[i] + 4.0) * src[i] : sqrt(src[i]);
|
||||
result[i] = src[i] + (2.0 * bloom[i] - 1.0) * (d - src[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
vec4 blendAlpha(vec4 src, vec4 bloom) {
|
||||
return src + bloom * (1.0 - src.a);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
vec4 src = texture2D(sourceBitmap, textureCoords.xy);
|
||||
vec4 bloom = texture2D(openfl_Texture, textureCoords.zw);
|
||||
|
||||
vec4 result;
|
||||
if(uBlendMode == 0)
|
||||
result = src + bloom;
|
||||
else if(uBlendMode == 1)
|
||||
result = blendAlpha(src, bloom);
|
||||
else if(uBlendMode == 5)
|
||||
result = blendOverlay(src, bloom);
|
||||
else if(uBlendMode == 8)
|
||||
result = blendLighten(src, bloom);
|
||||
else if(uBlendMode == 9)
|
||||
result = blendMultiply(src, bloom);
|
||||
else if(uBlendMode == 11)
|
||||
result = blendOverlay(src, bloom);
|
||||
else if(uBlendMode == 12)
|
||||
result = blendScreen(src, bloom);
|
||||
else if(uBlendMode == 15)
|
||||
result = blendColorDodge(src, bloom);
|
||||
else if(uBlendMode == 17)
|
||||
result = blendSoftLight(src, bloom);
|
||||
else
|
||||
result = src + bloom;
|
||||
|
||||
gl_FragColor = result;
|
||||
}
|
||||
")
|
||||
@:glVertexSource("
|
||||
attribute vec4 openfl_Position;
|
||||
attribute vec2 openfl_TextureCoord;
|
||||
uniform mat4 openfl_Matrix;
|
||||
uniform vec2 openfl_TextureSize;
|
||||
uniform float uQuality;
|
||||
varying vec4 textureCoords;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = openfl_Matrix * openfl_Position;
|
||||
textureCoords = vec4(openfl_TextureCoord, openfl_TextureCoord / uQuality);
|
||||
}
|
||||
")
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
||||
uQuality.value = [8];
|
||||
uThreshold.value = [0.6];
|
||||
uBlendMode.value = [0];
|
||||
}
|
||||
}
|
||||
@@ -106,7 +106,7 @@ class Flags {
|
||||
public static var DEFAULT_BEATS_PER_MEASURE:Int = 4;
|
||||
public static var DEFAULT_STEPS_PER_BEAT:Int = 4;
|
||||
public static var DEFAULT_LOOP_TIME:Float = 0.0;
|
||||
|
||||
public static var ICONS_AUTOPOSITION:Bool = true;
|
||||
public static var SUPPORTED_CHART_RUNTIME_FORMATS:Array<String> = ["Legacy", "Psych Engine"];
|
||||
public static var SUPPORTED_CHART_FORMATS:Array<String> = ["BaseGame"];
|
||||
|
||||
@@ -130,6 +130,9 @@ class Flags {
|
||||
@:also(funkin.game.PlayState.opponentMode)
|
||||
public static var DEFAULT_OPPONENT_MODE:Bool = false;
|
||||
|
||||
public static var EARLY_HIT_WINDOW_RANGE:Float = 1.0; // was 0.5 for easier early hitting, but now 1 to demotivate mashing and getting away with it.
|
||||
public static var LATE_HIT_WINDOW_RANGE:Float = 1.0;
|
||||
public static var SHITS_BREAK_COMBO:Bool = true;
|
||||
public static var USE_LEGACY_TIMING:Null<Bool> = null;
|
||||
|
||||
public static var DEFAULT_NOTE_MS_LIMIT:Float = 1500;
|
||||
|
||||
@@ -21,8 +21,10 @@ import openfl.Lib;
|
||||
import openfl.display.Sprite;
|
||||
import openfl.text.TextFormat;
|
||||
import openfl.utils.AssetLibrary;
|
||||
#if sys
|
||||
import sys.FileSystem;
|
||||
import sys.io.File;
|
||||
#end
|
||||
#if android
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
@@ -59,7 +61,9 @@ class Main extends Sprite
|
||||
|
||||
public static function preInit() {
|
||||
funkin.backend.utils.NativeAPI.registerAsDPICompatible();
|
||||
#if sys
|
||||
funkin.backend.system.CommandLineHandler.parseCommandLine(Sys.args());
|
||||
#end
|
||||
funkin.backend.system.Main.fixWorkingDirectory();
|
||||
}
|
||||
|
||||
|
||||
@@ -157,13 +157,16 @@ class MainState extends FlxState {
|
||||
CoolUtil.safeAddAttributes('./.temp/', NativeAPI.FileAttribute.HIDDEN);
|
||||
#end
|
||||
|
||||
#if MOD_SUPPORT
|
||||
for (lib in ModsFolder.getLoadedModsLibs()) {
|
||||
if (!(lib is ZipFolderLibrary)) continue;
|
||||
if (cast(lib, ZipFolderLibrary).PRELOAD_VIDEOS) cast(lib, ZipFolderLibrary).precacheVideos();
|
||||
}
|
||||
#end
|
||||
|
||||
var startState:Class<FlxState> = Flags.DISABLE_WARNING_SCREEN ? TitleState : funkin.menus.WarningState;
|
||||
|
||||
#if MOD_SUPPORT
|
||||
// In this case if the mod we just loaded a compressed modpack, we can't edit or modify files without decompressing it.
|
||||
if (Options.devMode && Options.allowConfigWarning && !isZipMod) {
|
||||
var lib:ModsFolderLibrary;
|
||||
@@ -176,6 +179,7 @@ class MainState extends FlxState {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#end
|
||||
|
||||
FlxG.switchState(cast Type.createInstance(startState, []));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ package funkin.backend.utils;
|
||||
|
||||
import flixel.sound.FlxSound;
|
||||
import lime.media.AudioBuffer;
|
||||
#if !js
|
||||
import lime.utils.ArrayBufferView.ArrayBufferIO;
|
||||
#end
|
||||
import lime.utils.ArrayBuffer;
|
||||
|
||||
#if (lime_cffi && lime_vorbis)
|
||||
@@ -30,6 +32,7 @@ final class AudioAnalyzer {
|
||||
* @param wordSize How many bytes to get with to one byte (Usually it's bitsPerSample / 8 or bitsPerSample >> 3).
|
||||
* @return Byte from the audio buffer with specified position.
|
||||
*/
|
||||
#if sys
|
||||
public static function getByte(buffer:ArrayBuffer, position:Int, wordSize:Int):Int {
|
||||
if (wordSize == 2) return inline ArrayBufferIO.getInt16(buffer, position);
|
||||
else if (wordSize == 3) {
|
||||
@@ -40,6 +43,19 @@ final class AudioAnalyzer {
|
||||
else if (wordSize == 4) return inline ArrayBufferIO.getInt32(buffer, position);
|
||||
else return inline ArrayBufferIO.getUint8(buffer, position) - 128;
|
||||
}
|
||||
#elseif js
|
||||
public static function getByte(buffer:lime.utils.UInt8Array, position:Int, wordSize:Int):Int {
|
||||
var view = new lime.utils.DataView(buffer.buffer);
|
||||
if (wordSize == 2) return inline view.getInt16(position, true);
|
||||
else if (wordSize == 3) {
|
||||
var b = inline view.getUint16(position, true) | (view.getUint8(position + 2) << 16);
|
||||
if (b & 0x800000 != 0) return b - 0x1000000;
|
||||
else return b;
|
||||
}
|
||||
else if (wordSize == 4) return inline view.getInt32(position, true);
|
||||
else return inline view.getUint8(position) - 128;
|
||||
}
|
||||
#end
|
||||
|
||||
/**
|
||||
* Gets levels from the frequencies with specified sample rate.
|
||||
@@ -450,12 +466,16 @@ final class AudioAnalyzer {
|
||||
}
|
||||
|
||||
inline function __readData(startPos:Float, endPos:Float, callback:AudioAnalyzerCallback) {
|
||||
var pos = Math.floor(startPos * __toBits), end = Math.min(Math.floor(endPos * __toBits), buffer.data.buffer.length), c = 0;
|
||||
var pos = Math.floor(startPos * __toBits), end = Math.min(Math.floor(endPos * __toBits), buffer.data.buffer.byteLength), c = 0;
|
||||
pos -= pos % __sampleSize;
|
||||
end -= end % __sampleSize;
|
||||
|
||||
while (pos < end) {
|
||||
#if sys
|
||||
callback(getByte(buffer.data.buffer, pos, __wordSize), c);
|
||||
#elseif js
|
||||
callback(getByte(buffer.data, pos, __wordSize), c);
|
||||
#end
|
||||
if (++c > buffer.channels) c = 0;
|
||||
pos += __wordSize;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package funkin.backend.utils;
|
||||
|
||||
import lime.utils.AssetType;
|
||||
#if cpp
|
||||
import cpp.Float64;
|
||||
#end
|
||||
@@ -1240,9 +1241,9 @@ final class CoolUtil
|
||||
* @return Bool
|
||||
*/
|
||||
public static function imageHasFrameData(path:String):String {
|
||||
if (FileSystem.exists(Path.withExtension(path, "xml"))) return "xml";
|
||||
if (FileSystem.exists(Path.withExtension(path, "txt"))) return "txt";
|
||||
if (FileSystem.exists(Path.withExtension(path, "json"))) return "json";
|
||||
if (Paths.assetsTree.existsSpecific(Path.withExtension(path, "xml"), AssetType.TEXT)) return "xml";
|
||||
if (Paths.assetsTree.existsSpecific(Path.withExtension(path, "txt"), AssetType.TEXT)) return "txt";
|
||||
if (Paths.assetsTree.existsSpecific(Path.withExtension(path, "json"), AssetType.TEXT)) return "json";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package funkin.backend.utils;
|
||||
|
||||
#if !macro
|
||||
import funkin.backend.system.Logs;
|
||||
#end
|
||||
#if (target.threaded)
|
||||
import sys.thread.Deque;
|
||||
import sys.thread.Thread;
|
||||
@@ -8,9 +11,6 @@ import sys.thread.Mutex;
|
||||
private typedef Thread = Dynamic;
|
||||
#end
|
||||
|
||||
#if !macro
|
||||
import funkin.backend.system.Logs;
|
||||
#end
|
||||
|
||||
final class ThreadUtil {
|
||||
inline static function error(text:String) {
|
||||
|
||||
@@ -254,6 +254,7 @@ final class TranslationUtil
|
||||
|
||||
// todo make it load the default languages in a second string map
|
||||
|
||||
#if MOD_SUPPORT
|
||||
for(mod in ModsFolder.getLoadedModsLibs(true)) for(file in mod.getFiles("assets/" + mainPath).sortAlphabetically().map((v)->'$mainPath/$v')) {
|
||||
if(Path.extension(file).toLowerCase() != "xml") continue;
|
||||
|
||||
@@ -277,6 +278,7 @@ final class TranslationUtil
|
||||
|
||||
parseXml(langNode, prefix);
|
||||
}
|
||||
#end
|
||||
|
||||
for(pair in translations) {
|
||||
var node = pair.node;
|
||||
|
||||
@@ -17,8 +17,10 @@ import funkin.game.Character;
|
||||
import haxe.xml.Access;
|
||||
import haxe.xml.Printer;
|
||||
import funkin.editors.ui.UIImageExplorer.ImageSaveData;
|
||||
#if sys
|
||||
import sys.FileSystem;
|
||||
import sys.io.File;
|
||||
#end
|
||||
|
||||
class CharacterEditor extends UIState {
|
||||
static var __character:String;
|
||||
@@ -518,6 +520,7 @@ class CharacterEditor extends UIState {
|
||||
characterPropertiesWindow.editCharacterInfo(oldInfo, false);
|
||||
case CCharEditSprite(fileID):
|
||||
var cneisdPath:String = './.temp/__undo__${Type.getClassName(Type.getClass(FlxG.state))}__${fileID}.cneisd';
|
||||
#if sys
|
||||
if (FileSystem.exists(cneisdPath)) {
|
||||
try {
|
||||
var cneisdData:String = File.getContent(cneisdPath);
|
||||
@@ -530,6 +533,7 @@ class CharacterEditor extends UIState {
|
||||
trace('ERROR COMPLETING UNDO: $e');
|
||||
};
|
||||
}
|
||||
#end
|
||||
case CAnimCreate(animID, animData):
|
||||
characterAnimsWindow.deleteAnimation(characterAnimsWindow.buttons.members[animID], false);
|
||||
case CAnimDelete(animID, animData):
|
||||
@@ -592,6 +596,7 @@ class CharacterEditor extends UIState {
|
||||
characterPropertiesWindow.editCharacterInfo(newInfo, false);
|
||||
case CCharEditSprite(fileID):
|
||||
var cneisdPath:String = './.temp/__redo__${Type.getClassName(Type.getClass(FlxG.state))}__${fileID}.cneisd';
|
||||
#if sys
|
||||
if (FileSystem.exists(cneisdPath)) {
|
||||
try {
|
||||
var cneisdData:String = File.getContent(cneisdPath);
|
||||
@@ -604,6 +609,7 @@ class CharacterEditor extends UIState {
|
||||
trace('ERROR COMPLETING UNDO: $e');
|
||||
};
|
||||
}
|
||||
#end
|
||||
case CAnimCreate(animID, animData):
|
||||
characterAnimsWindow.addAnimation(animData, animID, false);
|
||||
playAnimation(animData.name);
|
||||
|
||||
@@ -371,12 +371,14 @@ class SongCreationScreen extends UISubstateWindow {
|
||||
{
|
||||
case 2 /*"V-Slice Project (.fnfc)"*/:
|
||||
var files:Map<String, Any> = [];
|
||||
#if sys
|
||||
for (field in new ZipReader(new BytesInput(importChartFile.file)).read()) {
|
||||
var fileName = field.fileName;
|
||||
var fileContent = ZipUtil.unzip(field);
|
||||
files.set(fileName, fileContent);
|
||||
}
|
||||
saveFromVSlice(files);
|
||||
#end
|
||||
case 1 /*"V-Slice"*/:
|
||||
var songId = importIdTextBox.label.text;
|
||||
var files:Map<String, Any> = [];
|
||||
|
||||
@@ -62,7 +62,11 @@ class UIFileExplorer extends UISliceSprite {
|
||||
}
|
||||
|
||||
public function loadFile(path:String) {
|
||||
#if sys
|
||||
file = cast sys.io.File.getBytes(filePath = path);
|
||||
#else
|
||||
file = null;
|
||||
#end
|
||||
deleteButton.visible = deleteButton.selectable = deleteIcon.visible = !(uploadButton.visible = uploadButton.selectable = false);
|
||||
|
||||
if (this.onFile != null) this.onFile(filePath, file);
|
||||
|
||||
@@ -8,8 +8,10 @@ import haxe.Json;
|
||||
import haxe.io.Bytes;
|
||||
import haxe.io.Path;
|
||||
import openfl.display.BitmapData;
|
||||
#if sys
|
||||
import sys.FileSystem;
|
||||
import sys.io.File;
|
||||
#end
|
||||
import animate.FlxAnimateJson;
|
||||
|
||||
using StringTools;
|
||||
@@ -60,13 +62,19 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
directoryBG.members.push(directoryTextBox);
|
||||
|
||||
if (image != null) {
|
||||
#if sys
|
||||
var fullImagePath:String = '${Path.normalize(Sys.getCwd())}/${Paths.image(image)}'.replace('/', '\\');
|
||||
#else
|
||||
var fullImagePath = null;
|
||||
#end
|
||||
var noExt = Path.withoutExtension(fullImagePath);
|
||||
#if sys
|
||||
if (FileSystem.exists('$noExt\\spritemap1.png'))
|
||||
fullImagePath = '$noExt\\spritemap1.png';
|
||||
|
||||
if (FileSystem.exists(fullImagePath))
|
||||
loadFile(fullImagePath);
|
||||
#end
|
||||
}
|
||||
|
||||
allowDirectories = CoolUtil.isMapEmpty(imageFiles); __firstLoad = false;
|
||||
@@ -100,7 +108,11 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
// CHECK ATLAS
|
||||
if(allowAtlases && ANIMATE_ATLAS_REGEX.match(fileName)) {
|
||||
// check if directory has the other files
|
||||
#if sys
|
||||
files = FileSystem.readDirectory(directoryPath);
|
||||
#else
|
||||
files = null;
|
||||
#end
|
||||
var hasAnimationJson:Bool = false;
|
||||
var hasSpritemapJson:Bool = false;
|
||||
for(file in files) {
|
||||
@@ -116,12 +128,20 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
}
|
||||
} else if(allowAtlases && Path.extension(fileName) == "png") {
|
||||
// check if the spritemap json files point to the image
|
||||
#if sys
|
||||
files = FileSystem.readDirectory(directoryPath);
|
||||
#else
|
||||
files = null;
|
||||
#end
|
||||
var hasAnimationJson:Bool = false;
|
||||
var foundSpritemapJson:Bool = false;
|
||||
for(file in files) {
|
||||
if(SPRITEMAP_JSON_REGEX.match(file)) {
|
||||
#if sys
|
||||
var content:String = CoolUtil.removeBOM(File.getContent(Path.join([directoryPath, file])));
|
||||
#else
|
||||
var content = null;
|
||||
#end
|
||||
var json:SpritemapJson = Json.parse(content);
|
||||
if(json.meta.image.toLowerCase() == fileName.toLowerCase())
|
||||
foundSpritemapJson = true;
|
||||
@@ -146,7 +166,11 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
|
||||
spritemaps.sort(Reflect.compare);
|
||||
for(spritemap in spritemaps) {
|
||||
#if sys
|
||||
var content:String = CoolUtil.removeBOM(File.getContent(Path.join([directoryPath, spritemap])));
|
||||
#else
|
||||
var content = null;
|
||||
#end
|
||||
var json:SpritemapJson = Json.parse(content);
|
||||
var imageToFind:String = json.meta.image.toLowerCase();
|
||||
for(file in files) {
|
||||
@@ -168,17 +192,23 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
if (isAtlas) {
|
||||
var dataPath:String = '$directoryPath/Animation.json'.replace('/', '\\');
|
||||
|
||||
#if sys
|
||||
if (FileSystem.exists(dataPath)) {
|
||||
var dataPathFile:String = File.getContent(dataPath);
|
||||
animationList = CoolUtil.getAnimsListFromAtlas(cast haxe.Json.parse(dataPathFile));
|
||||
|
||||
imageFiles.set(Path.withoutDirectory(dataPath), dataPathFile);
|
||||
}
|
||||
#end
|
||||
} else {
|
||||
var dataPathExt:String = CoolUtil.imageHasFrameData(imagePath);
|
||||
var dataPath:String = Path.withExtension(imagePath, dataPathExt);
|
||||
#if sys
|
||||
var dataPathFile:String = !isAtlas && dataPathExt != null ? File.getContent(dataPath) : null;
|
||||
|
||||
#else
|
||||
var dataPathFile = null;
|
||||
#end
|
||||
|
||||
if (dataPathExt != null) {
|
||||
frames = CoolUtil.loadFramesFromData(dataPathFile, dataPathExt);
|
||||
animationList = CoolUtil.getAnimsListFromFrames(frames, dataPathExt);
|
||||
@@ -200,14 +230,24 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
for(spritemap in spritemapImages) {
|
||||
var spritemapPath:String = Path.join([directoryPath, spritemap]);
|
||||
|
||||
#if sys
|
||||
var info = FileSystem.stat(spritemapPath);
|
||||
#else
|
||||
var info = null;
|
||||
#end
|
||||
size += info.size;
|
||||
|
||||
spritemapPath = spritemapPath.replace('/', '\\');
|
||||
#if sys
|
||||
imageFiles.set(Path.withoutDirectory(spritemapPath), sys.io.File.getBytes(spritemapPath));
|
||||
#end
|
||||
}
|
||||
|
||||
#if sys
|
||||
file = cast sys.io.File.getBytes(filePath = spritemapPath);
|
||||
#else
|
||||
file = null;
|
||||
#end
|
||||
image = BitmapData.fromBytes(file).crop();
|
||||
|
||||
} else {
|
||||
@@ -321,12 +361,16 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
|
||||
var alreadlyExistingFiles:Array<String> = [];
|
||||
for (name => file in imageData.imageFiles)
|
||||
#if sys
|
||||
if (FileSystem.exists('$directory/$name'))
|
||||
alreadlyExistingFiles.push('$directory/$name');
|
||||
#end
|
||||
|
||||
function deleteExistingFiles() {
|
||||
#if sys
|
||||
for (file in alreadlyExistingFiles)
|
||||
FileSystem.deleteFile(file);
|
||||
#end
|
||||
alreadlyExistingFiles = [];
|
||||
}
|
||||
|
||||
@@ -346,8 +390,10 @@ class UIImageExplorer extends UIFileExplorer {
|
||||
label: TU.translate("uiImageExplorer.override"),
|
||||
color: 0xFFFF0000,
|
||||
onClick: (_) -> {
|
||||
#if sys
|
||||
deleteExistingFiles();
|
||||
acuttalySaveFiles();
|
||||
#end
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package funkin.game;
|
||||
|
||||
#if sys
|
||||
import sys.FileSystem;
|
||||
#end
|
||||
import flixel.util.FlxSpriteUtil;
|
||||
import openfl.display.Graphics;
|
||||
import flixel.util.typeLimit.OneOfTwo;
|
||||
|
||||
@@ -317,9 +317,8 @@ class Note extends FlxSprite
|
||||
return super.isOnScreen(camera);
|
||||
}
|
||||
|
||||
// The * 0.5 is so that it's easier to hit them too late, instead of too early
|
||||
public var earlyPressWindow:Float = 0.5;
|
||||
public var latePressWindow:Float = 1;
|
||||
public var earlyPressWindow:Float = Flags.EARLY_HIT_WINDOW_RANGE;
|
||||
public var latePressWindow:Float = Flags.LATE_HIT_WINDOW_RANGE;
|
||||
|
||||
public function updateSustain(strum:Strum) {
|
||||
var scrollSpeed = strum.getScrollSpeed(this);
|
||||
|
||||
+118
-63
@@ -943,7 +943,7 @@ class PlayState extends MusicBeatState
|
||||
|
||||
// Make icons appear in the correct spot during cutscenes
|
||||
healthBar.update(0);
|
||||
if (updateIconPositions != null)
|
||||
if (updateIconPositions != null && Flags.ICONS_AUTOPOSITION)
|
||||
updateIconPositions();
|
||||
|
||||
__updateNote_event = EventManager.get(NoteUpdateEvent);
|
||||
@@ -1966,9 +1966,9 @@ class PlayState extends MusicBeatState
|
||||
|
||||
var event:NoteHitEvent;
|
||||
if (strumLine != null && !strumLine.cpu)
|
||||
event = EventManager.get(NoteHitEvent).recycle(rating.breaksCombo, !note.isSustainNote, !note.isSustainNote, null, defaultDisplayRating, defaultDisplayCombo, note, strumLine.characters, true, note.noteType, note.animSuffix.getDefault(note.strumID < strumLine.members.length ? strumLine.members[note.strumID].animSuffix : strumLine.animSuffix), "game/score/", "", note.strumID, rating.score, note.isSustainNote ? null : rating.accuracy, rating.health, rating.name, Options.splashesEnabled && !note.isSustainNote && rating.splash, 0.5, true, 0.7, true, true, iconP1);
|
||||
event = EventManager.get(NoteHitEvent).recycle(rating.breaksCombo, !note.isSustainNote, !note.isSustainNote, null, null, null, note, strumLine.characters, true, note.noteType, note.animSuffix.getDefault(note.strumID < strumLine.members.length ? strumLine.members[note.strumID].animSuffix : strumLine.animSuffix), null, null, note.strumID, rating.score, note.isSustainNote ? null : rating.accuracy, rating.health, rating.name, Options.splashesEnabled && !note.isSustainNote && rating.splash, null, null, null, null, null, iconP1);
|
||||
else
|
||||
event = EventManager.get(NoteHitEvent).recycle(rating.breaksCombo, false, false, null, defaultDisplayRating, defaultDisplayCombo, note, strumLine.characters, false, note.noteType, note.animSuffix.getDefault(note.strumID < strumLine.members.length ? strumLine.members[note.strumID].animSuffix : strumLine.animSuffix), "game/score/", "", note.strumID, 0, null, 0, rating.name, false, 0.5, true, 0.7, true, true, iconP2);
|
||||
event = EventManager.get(NoteHitEvent).recycle(rating.breaksCombo, false, false, null, null, null, note, strumLine.characters, false, note.noteType, note.animSuffix.getDefault(note.strumID < strumLine.members.length ? strumLine.members[note.strumID].animSuffix : strumLine.animSuffix), null, null, note.strumID, 0, null, 0, rating.name, false, null, null, null, null, true, iconP2);
|
||||
event.deleteNote = !note.isSustainNote; // work around, to allow sustain notes to be deleted
|
||||
event = scripts.event(strumLine != null && !strumLine.cpu ? "onPlayerHit" : "onDadHit", event);
|
||||
strumLine.onHit.dispatch(event);
|
||||
@@ -1993,8 +1993,8 @@ class PlayState extends MusicBeatState
|
||||
if (event.showRating || (event.showRating == null && event.player))
|
||||
{
|
||||
displayCombo(event);
|
||||
if (event.displayRating)
|
||||
displayRating(event.rating, event);
|
||||
displayRatingNumbers(event);
|
||||
displayRating(event.rating, event);
|
||||
ratingNum += 1;
|
||||
}
|
||||
if (event.player) hits[rating.name] += 1;
|
||||
@@ -2031,81 +2031,136 @@ class PlayState extends MusicBeatState
|
||||
gameAndCharsEvent("onPostNoteHit", event);
|
||||
}
|
||||
|
||||
public function displayRating(myRating:String, ?evt:NoteHitEvent = null):Void {
|
||||
var hasEvent = evt != null;
|
||||
var pre:String = hasEvent ? evt.ratingPrefix : "";
|
||||
var suf:String = hasEvent ? evt.ratingSuffix : "";
|
||||
public function displayRating(myRating:String, ?evt:NoteHitEvent):Void
|
||||
{
|
||||
var event:RatingsShowEvent = EventManager.get(RatingsShowEvent).recycle(comboGroup.recycleLoop(FlxSprite), null, null, null, null, 0.7, true, "game/score/", "", 550, FlxPoint.get(FlxG.random.int(0, 10), FlxG.random.int(140, 175)), 0.2, (Conductor.crochet * 0.001), true, false, false, true, null, FlxPoint.get(comboGroup.x + -40, comboGroup.y + -60), true, myRating, null);
|
||||
gameAndCharsEvent("onRatingsShown", event);
|
||||
|
||||
var rating:FlxSprite = comboGroup.recycleLoop(FlxSprite);
|
||||
CoolUtil.resetSprite(rating, comboGroup.x + -40, comboGroup.y + -60);
|
||||
rating.loadAnimatedGraphic(Paths.image('${pre}${myRating}${suf}'));
|
||||
rating.acceleration.y = 550;
|
||||
rating.velocity.y -= FlxG.random.int(140, 175);
|
||||
rating.velocity.x -= FlxG.random.int(0, 10);
|
||||
if (hasEvent) {
|
||||
rating.scale.set(evt.ratingScale, evt.ratingScale);
|
||||
rating.antialiasing = evt.ratingAntialiasing;
|
||||
if (event.cancelled || !event.displayRating) { // TODO: Find a better way for this?
|
||||
event.ratingSprite.kill();
|
||||
return;
|
||||
}
|
||||
|
||||
var hasEvent:Bool = evt != null;
|
||||
|
||||
var pre:String = hasEvent && evt.ratingPrefix != null ? evt.ratingPrefix : event.ratingPrefix;
|
||||
var suf:String = hasEvent && evt.ratingSuffix != null ? evt.ratingSuffix : event.ratingSuffix;
|
||||
|
||||
var ratingScale:Float = hasEvent && evt.ratingScale != null ? evt.ratingScale : event.ratingScale;
|
||||
|
||||
var rating:FlxSprite = event.ratingSprite.loadAnimatedGraphic(Paths.image('${pre}${event.rating}${suf}'));
|
||||
if (event.resetSprite) {
|
||||
CoolUtil.resetSprite(rating, event.position.x, event.position.y);
|
||||
}
|
||||
rating.acceleration.y = event.acceleration;
|
||||
rating.velocity.y -= event.velocity.y;
|
||||
rating.velocity.x -= event.velocity.x;
|
||||
rating.scale.set(ratingScale, ratingScale);
|
||||
rating.antialiasing = hasEvent && evt.ratingAntialiasing != null ? evt.ratingAntialiasing : event.ratingAntialiasing;
|
||||
rating.updateHitbox();
|
||||
|
||||
FlxTween.tween(rating, {alpha: 0}, 0.2, {
|
||||
startDelay: Conductor.crochet * 0.001,
|
||||
onComplete: function(tween:FlxTween) {
|
||||
rating.kill();
|
||||
}
|
||||
});
|
||||
if (event.playTween) {
|
||||
event.tween = FlxTween.tween(rating, {alpha: 0}, event.tweenDuration, {
|
||||
startDelay: event.startDelay,
|
||||
onComplete: function(tween:FlxTween) {
|
||||
rating.kill();
|
||||
}
|
||||
});
|
||||
}
|
||||
gameAndCharsEvent("onPostRatingsShown", event);
|
||||
|
||||
event.velocity.put();
|
||||
event.position.put();
|
||||
}
|
||||
|
||||
public function displayCombo(?evt:NoteHitEvent = null):Void {
|
||||
public function displayCombo(?evt:NoteHitEvent):Void {
|
||||
if (minDigitDisplay >= 0 && (combo == 0 || combo >= minDigitDisplay)) {
|
||||
var hasEvent = evt != null;
|
||||
var pre:String = hasEvent ? evt.ratingPrefix : "";
|
||||
var suf:String = hasEvent ? evt.ratingSuffix : "";
|
||||
var event:RatingsShowEvent = EventManager.get(RatingsShowEvent).recycle(null, null, comboGroup.recycleLoop(FlxSprite), null, null, 0.7, true, "game/score/", "", 600, FlxPoint.get(FlxG.random.int(0, 10), 150), 0.2, (Conductor.crochet * 0.001), false, false, evt != null && evt.displayCombo != null ? evt.displayCombo : defaultDisplayCombo, true, null, FlxPoint.get(comboGroup.x, comboGroup.y), true, null, null);
|
||||
gameAndCharsEvent("onRatingsShown", event);
|
||||
|
||||
if (evt.displayCombo) {
|
||||
var comboSpr:FlxSprite = comboGroup.recycleLoop(FlxSprite).loadAnimatedGraphic(Paths.image('${pre}combo${suf}'));
|
||||
CoolUtil.resetSprite(comboSpr, comboGroup.x, comboGroup.y);
|
||||
comboSpr.acceleration.y = 600;
|
||||
comboSpr.velocity.y -= 150;
|
||||
comboSpr.velocity.x += FlxG.random.int(1, 10);
|
||||
|
||||
if (hasEvent) {
|
||||
comboSpr.scale.set(evt.ratingScale, evt.ratingScale);
|
||||
comboSpr.antialiasing = evt.ratingAntialiasing;
|
||||
}
|
||||
comboSpr.updateHitbox();
|
||||
|
||||
FlxTween.tween(comboSpr, {alpha: 0}, 0.2, {
|
||||
onComplete: function(tween:FlxTween)
|
||||
{
|
||||
comboSpr.kill();
|
||||
},
|
||||
startDelay: Conductor.crochet * 0.001
|
||||
});
|
||||
if (event.cancelled || !event.displayCombo) { // TODO: Find a better way for this?
|
||||
event.comboSprite.kill();
|
||||
return;
|
||||
}
|
||||
|
||||
var hasEvent:Bool = evt != null;
|
||||
|
||||
var pre:String = hasEvent && evt.ratingPrefix != null ? evt.ratingPrefix : event.ratingPrefix;
|
||||
var suf:String = hasEvent && evt.ratingSuffix != null ? evt.ratingSuffix : event.ratingSuffix;
|
||||
|
||||
var ratingScale:Float = hasEvent && evt.ratingScale != null ? evt.ratingScale : event.ratingScale;
|
||||
|
||||
var comboSpr:FlxSprite = event.comboSprite.loadAnimatedGraphic(Paths.image('${pre}combo${suf}'));
|
||||
if (event.resetSprite) {
|
||||
CoolUtil.resetSprite(comboSpr, event.position.x, event.position.y);
|
||||
}
|
||||
comboSpr.acceleration.y = event.acceleration;
|
||||
comboSpr.velocity.y -= event.velocity.y;
|
||||
comboSpr.velocity.x += event.velocity.x;
|
||||
comboSpr.scale.set(ratingScale, ratingScale);
|
||||
comboSpr.antialiasing = hasEvent && evt.ratingAntialiasing != null ? evt.ratingAntialiasing : event.ratingAntialiasing;
|
||||
comboSpr.updateHitbox();
|
||||
|
||||
if (event.playTween) {
|
||||
event.tween = FlxTween.tween(comboSpr, {alpha: 0}, event.tweenDuration, {
|
||||
onComplete: function(tween:FlxTween) {
|
||||
comboSpr.kill();
|
||||
},
|
||||
startDelay: event.startDelay
|
||||
});
|
||||
}
|
||||
gameAndCharsEvent("onPostRatingsShown", event);
|
||||
|
||||
event.velocity.put();
|
||||
event.position.put();
|
||||
}
|
||||
}
|
||||
|
||||
public function displayRatingNumbers(?evt:NoteHitEvent):Void {
|
||||
if (minDigitDisplay >= 0 && (combo == 0 || combo >= minDigitDisplay)) {
|
||||
var separatedScore:String = Std.string(combo).addZeros(3);
|
||||
for (i in 0...separatedScore.length)
|
||||
{
|
||||
var numScore:FlxSprite = comboGroup.recycleLoop(FlxSprite).loadAnimatedGraphic(Paths.image('${pre}num${separatedScore.charAt(i)}${suf}'));
|
||||
CoolUtil.resetSprite(numScore, comboGroup.x + (43 * i) - 90, comboGroup.y + 80);
|
||||
if (hasEvent) {
|
||||
numScore.antialiasing = evt.numAntialiasing;
|
||||
numScore.scale.set(evt.numScale, evt.numScale);
|
||||
var event:RatingsShowEvent = EventManager.get(RatingsShowEvent).recycle(null, comboGroup.recycleLoop(FlxSprite), null, 0.5, true, null, null, "game/score/", "", FlxG.random.int(200, 300), FlxPoint.get(FlxG.random.float(-5, 5), FlxG.random.int(140, 160)), 0.2, (Conductor.crochet * 0.002), false, true, false, true, 43, FlxPoint.get(comboGroup.x - 90, comboGroup.y + 80), true, null, null);
|
||||
gameAndCharsEvent("onRatingsShown", event);
|
||||
|
||||
if (event.cancelled || !event.displayNumbers) { // TODO: Find a better way for this?
|
||||
event.numberSprite.kill();
|
||||
continue;
|
||||
}
|
||||
|
||||
var hasEvent:Bool = evt != null;
|
||||
|
||||
var pre:String = hasEvent && evt.ratingPrefix != null ? evt.ratingPrefix : event.ratingPrefix;
|
||||
var suf:String = hasEvent && evt.ratingSuffix != null ? evt.ratingSuffix : event.ratingSuffix;
|
||||
|
||||
var numScale:Float = hasEvent && evt.numScale != null ? evt.numScale : event.numScale;
|
||||
|
||||
var numScore:FlxSprite = event.numberSprite.loadAnimatedGraphic(Paths.image('${pre}num${separatedScore.charAt(i)}${suf}'));
|
||||
event.position.x += event.numSpacing * i;
|
||||
if (event.resetSprite) {
|
||||
CoolUtil.resetSprite(numScore, event.position.x, event.position.y);
|
||||
}
|
||||
numScore.antialiasing = hasEvent && evt.numAntialiasing != null ? evt.numAntialiasing : event.numAntialiasing;
|
||||
numScore.scale.set(numScale, numScale);
|
||||
numScore.updateHitbox();
|
||||
|
||||
numScore.acceleration.y = FlxG.random.int(200, 300);
|
||||
numScore.velocity.y -= FlxG.random.int(140, 160);
|
||||
numScore.velocity.x = FlxG.random.float(-5, 5);
|
||||
numScore.acceleration.y = event.acceleration;
|
||||
numScore.velocity.y -= event.velocity.y;
|
||||
numScore.velocity.x = event.velocity.x;
|
||||
|
||||
FlxTween.tween(numScore, {alpha: 0}, 0.2, {
|
||||
onComplete: function(tween:FlxTween)
|
||||
{
|
||||
numScore.kill();
|
||||
},
|
||||
startDelay: Conductor.crochet * 0.002
|
||||
});
|
||||
if (event.playTween) {
|
||||
event.tween = FlxTween.tween(numScore, {alpha: 0}, event.tweenDuration, {
|
||||
onComplete: function(tween:FlxTween) {
|
||||
numScore.kill();
|
||||
},
|
||||
startDelay: event.startDelay
|
||||
});
|
||||
}
|
||||
gameAndCharsEvent("onPostRatingsShown", event);
|
||||
|
||||
event.velocity.put();
|
||||
event.position.put();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class RatingManager
|
||||
addRating({name: "sick", window: getWindow("sick"), accuracy: 1, score: 300, splash: true});
|
||||
addRating({name: "good", window: getWindow("good"), accuracy: 0.75, score: 200, health: 0.015});
|
||||
addRating({name: "bad", window: getWindow("bad"), accuracy: 0.45, score: 100, health: 0});
|
||||
addRating({name: "shit", window: getWindow("shit"), accuracy: 0.25, score: 50, health: -0.05, breaksCombo: true});
|
||||
addRating({name: "shit", window: getWindow("shit"), accuracy: 0.25, score: 50, health: -0.05, breaksCombo: Flags.SHITS_BREAK_COMBO});
|
||||
}
|
||||
|
||||
public function addRating(data:Dynamic)
|
||||
|
||||
@@ -35,4 +35,9 @@ class Config {
|
||||
public static final DISALLOW_ABSTRACT_AND_ENUM = [
|
||||
"funkin.backend.scripting.events.sprite.PlayAnimContext", // Error: expected member name or ';' after declaration specifiers, Due to define macro from math.h
|
||||
];
|
||||
}
|
||||
|
||||
@:unreflective
|
||||
public static final IMPORT_BLACKLIST:Array<String> = [
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ class HTML5AudioSource
|
||||
private var parent:AudioSource;
|
||||
private var playing:Bool;
|
||||
private var position:Vector4;
|
||||
private var loopTime:Float;
|
||||
|
||||
public function new(parent:AudioSource)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user