Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9757b002bd | ||
|
|
3140ee8512 | ||
|
|
c96ee6c465 | ||
|
|
1c4c962f4d | ||
|
|
49d4708265 | ||
|
|
ffa5e66bc8 | ||
|
|
18fcacc2b5 | ||
|
|
a2ff5c112e | ||
|
|
3862995213 | ||
|
|
f7e4875097 | ||
|
|
cabdffd058 | ||
|
|
c28e056a8a | ||
|
|
3fd87c8d52 | ||
|
|
eaacc5dfc2 | ||
|
|
4573fef74d | ||
|
|
978022dc0b | ||
|
|
970d294ea1 | ||
|
|
7568cbfd99 | ||
|
|
c5686b09db | ||
|
|
ce4d1a0d61 | ||
|
|
2eac58aaa5 | ||
|
|
ce98ad0645 | ||
|
|
037f564676 | ||
|
|
5227ed3253 | ||
|
|
9e4b6f31c0 | ||
|
|
fe02ba7b4b | ||
|
|
ec63be9e77 | ||
|
|
88ea51064b | ||
|
|
647c70839d | ||
|
|
39237dd01d | ||
|
|
d3bd40baf3 | ||
|
|
7d7db50c19 | ||
|
|
8aa2023057 | ||
|
|
d979b5c33d | ||
|
|
ba50edfc99 | ||
|
|
5acabccd9a | ||
|
|
66c1cd9dde | ||
|
|
ec65cae8fc | ||
|
|
3de652c73e | ||
|
|
8303e7ecfd | ||
|
|
e17b5d6b86 | ||
|
|
0ff829e1c6 | ||
|
|
769a33f138 | ||
|
|
91abb37281 | ||
|
|
32bca0420e | ||
|
|
faa0dbb324 | ||
|
|
14c81ef26d | ||
|
|
62f4819493 | ||
|
|
8ba41990e6 | ||
|
|
6c92fcff8b | ||
|
|
6a802c2281 | ||
|
|
3a6f4819a9 | ||
|
|
e24a62a0b7 | ||
|
|
9c7bb8f073 | ||
|
|
6112e2f759 | ||
|
|
3939439086 | ||
|
|
59b54dfbae | ||
|
|
a83f62ab8a | ||
|
|
f86773223b | ||
|
|
b1133171c7 | ||
|
|
05006802ee | ||
|
|
0eaffe3ea9 | ||
|
|
03df52c542 | ||
|
|
1ca4b64402 | ||
|
|
b8b8d08be5 | ||
|
|
406f76af5d | ||
|
|
1a855e5061 | ||
|
|
41474738c7 | ||
|
|
bcbfa90f37 | ||
|
|
b39f0d993e | ||
|
|
65839283e5 | ||
|
|
d2a113907a | ||
|
|
d3ef27b9c7 | ||
|
|
90fc02c128 | ||
|
|
cbaa5a6155 | ||
|
|
1f479a5b16 | ||
|
|
967bd4cf01 | ||
|
|
3074107322 | ||
|
|
9c7cc22a47 | ||
|
|
7c8dd987dd | ||
|
|
48624554cd | ||
|
|
a86749953f | ||
|
|
482c213079 | ||
|
|
8d8e6e453a | ||
|
|
d6937e866c | ||
|
|
9ce1486269 | ||
|
|
44a19340a4 | ||
|
|
74d37f60f3 | ||
|
|
f5b79bb332 | ||
|
|
dbc3a79e62 | ||
|
|
a262b7e683 | ||
|
|
b43221d527 | ||
|
|
7a9a510c47 | ||
|
|
1716dc48ab | ||
|
|
522256a3cf | ||
|
|
4e3d5d75ec | ||
|
|
3196195790 | ||
|
|
e08fac35d0 | ||
|
|
69f67ce3f9 | ||
|
|
d961fcec30 | ||
|
|
de41464364 | ||
|
|
75cc052c7b | ||
|
|
991a168686 | ||
|
|
1cdaf62088 | ||
|
|
537883d2f4 | ||
|
|
6a1bbb72e3 | ||
|
|
8b43664327 | ||
|
|
d1fa0e5fa7 | ||
|
|
e89c0411c6 | ||
|
|
1993d205ca | ||
|
|
f8aa7201c0 | ||
|
|
07086b5e38 | ||
|
|
70195051ec | ||
|
|
9570de76a8 | ||
|
|
17539a6f39 | ||
|
|
16b080bf84 | ||
|
|
549c1ad441 | ||
|
|
be812cd2ec | ||
|
|
272f862c69 | ||
|
|
cf5a689918 | ||
|
|
84c153d69c |
@@ -2,12 +2,18 @@
|
|||||||
name: Bug Report
|
name: Bug Report
|
||||||
about: Report a bug or critical performance issue
|
about: Report a bug or critical performance issue
|
||||||
title: 'Bug Report: [DESCRIBE YOUR BUG IN DETAIL HERE]'
|
title: 'Bug Report: [DESCRIBE YOUR BUG IN DETAIL HERE]'
|
||||||
labels: bug
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[weed]: <> (MAKE SURE THAT THE ISSUE IS AS COMPLETE AS POSSIBLE. ISSUES THAT HAVE BARELY ANY INFORMATION OR IS ONLY MADE FOR TROLLING WILL BE INSTANTLY CLOSED.)
|
[weed]: <> (MAKE SURE THAT THE ISSUE IS AS COMPLETE AS POSSIBLE. ISSUES THAT HAVE BARELY ANY INFORMATION OR IS ONLY MADE FOR TROLLING WILL BE INSTANTLY CLOSED.)
|
||||||
[weed]: <> (MAKE SURE TO ADD YOUR TARGET OR IT'LL BE IGNORED!)
|
[weed]: <> (MAKE SURE TO ADD YOUR TARGET OR IT'LL BE IGNORED!)
|
||||||
|
|
||||||
|
### What version of the engine are you using?
|
||||||
|
[weed]: <> (IF YOU COMPILED THE ENGINE PLEASE PROVIDE A COMMIT HASH THAT WE CAN BASE OFF OF)
|
||||||
|
Version:
|
||||||
|
|
||||||
### Which target are you using?
|
### Which target are you using?
|
||||||
[weed]: <> (CHANGE [ ] TO [x] IN FRONT OF YOUR TARGET!)
|
[weed]: <> (CHANGE [ ] TO [x] IN FRONT OF YOUR TARGET!)
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
---
|
---
|
||||||
name: Compiling help
|
name: Compiling help
|
||||||
about: If you need help compiling the game, and you're running into issues. (Look through the 'compiling help' label in case it's been solved!)
|
about: If you need help compiling the game, and you're running into issues. (Look
|
||||||
|
through the 'compiling help' label in case it's been solved!)
|
||||||
title: 'Compiling help: [BRIEF DESCRIPTION / ERROR MESSAGE OUTPUT]'
|
title: 'Compiling help: [BRIEF DESCRIPTION / ERROR MESSAGE OUTPUT]'
|
||||||
labels: compiling help
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[weed]: <> (MAKE SURE THAT THE ISSUE IS AS COMPLETE AS POSSIBLE. ISSUES THAT HAVE BARELY ANY INFORMATION OR IS ONLY MADE FOR TROLLING WILL BE INSTANTLY CLOSED.)
|
[weed]: <> (MAKE SURE THAT THE ISSUE IS AS COMPLETE AS POSSIBLE. ISSUES THAT HAVE BARELY ANY INFORMATION OR IS ONLY MADE FOR TROLLING WILL BE INSTANTLY CLOSED.)
|
||||||
|
|||||||
@@ -2,7 +2,10 @@
|
|||||||
name: Enhancement
|
name: Enhancement
|
||||||
about: Suggest a new feature
|
about: Suggest a new feature
|
||||||
title: 'Enhancement: '
|
title: 'Enhancement: '
|
||||||
labels: enhancement
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
#### Please check for duplicates or similar issues before creating this issue.
|
#### Please check for duplicates or similar issues before creating this issue.
|
||||||
## What is your suggestion, and why should it be implemented?
|
## What is your suggestion, and why should it be implemented?
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ jobs:
|
|||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Codename Engine (Executable Only)
|
name: Codename Engine (Executable Only)
|
||||||
path: export/release/macos/bin/CodenameEngine
|
path: export/release/macos/bin/CodenameEngine.app/Contents/MacOS/CodenameEngine
|
||||||
- name: Uploading artifact (entire build)
|
- name: Uploading artifact (entire build)
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -6,5 +6,37 @@
|
|||||||
"*.hscript": "haxe",
|
"*.hscript": "haxe",
|
||||||
"*.hsc": "haxe",
|
"*.hsc": "haxe",
|
||||||
"*.hxs": "haxe"
|
"*.hxs": "haxe"
|
||||||
}
|
},
|
||||||
|
"lime.targetConfigurations": [
|
||||||
|
{
|
||||||
|
"label": "Windows (Test Build)",
|
||||||
|
"target": "windows",
|
||||||
|
"args": ["-DTEST_BUILD"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Linux (Test Build)",
|
||||||
|
"target": "linux",
|
||||||
|
"args": ["-DTEST_BUILD"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "MacOS (Test Build)",
|
||||||
|
"target": "macos",
|
||||||
|
"args": ["-DTEST_BUILD"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Windows / Debug (Test Build)",
|
||||||
|
"target": "windows",
|
||||||
|
"args": ["-debug", "-DTEST_BUILD"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Linux / Debug (Test Build)",
|
||||||
|
"target": "linux",
|
||||||
|
"args": ["-debug", "-DTEST_BUILD"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "MacOS / Debug (Test Build)",
|
||||||
|
"target": "macos",
|
||||||
|
"args": ["-debug", "-DTEST_BUILD"]
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
@@ -79,4 +79,5 @@ _**QOL = Quality of Life**_
|
|||||||
- Features not found in other editors!
|
- Features not found in other editors!
|
||||||
- Every single state & substate can be modified via HScript (`data/states/StateName.hx`)
|
- Every single state & substate can be modified via HScript (`data/states/StateName.hx`)
|
||||||
- **Instances launched via `lime test windows` will automatically use assets from source.**
|
- **Instances launched via `lime test windows` will automatically use assets from source.**
|
||||||
|
- Modcharting features powered by [FunkinModchart](https://lib.haxe.org/p/funkin-modchart/).
|
||||||
</details>
|
</details>
|
||||||
@@ -18,10 +18,10 @@ Codename Engine is a new Friday Night Funkin' Engine aimed at simplifying moddin
|
|||||||
|
|
||||||
## How to download
|
## How to download
|
||||||
|
|
||||||
Latest builds for the engine can be found in the [Actions](https://github.com/YoshiCrafter29/CodenameEngine/actions) tab.<br>
|
Latest builds for the engine can be found in the [Actions](https://github.com/CodenameCrew/CodenameEngine/actions) tab.<br>
|
||||||
In the future (when the engine won't be a WIP anymore) we're gonna also publish the engine on platforms like Gamebanana; stay tuned!
|
In the future (when the engine won't be a WIP anymore) we're gonna also publish the engine on platforms like Gamebanana; stay tuned!
|
||||||
|
|
||||||
If you don't have a github account please go onto https://fnf-cne-devs.github.io/ and click the download button for the respective operating system.
|
If you don't have a github account please go onto https://codename-engine.com/ and click the download button for the respective operating system.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><h2>How to build</h2></summary>
|
<summary><h2>How to build</h2></summary>
|
||||||
@@ -87,4 +87,5 @@ If you don't have a github account please go onto https://fnf-cne-devs.github.io
|
|||||||
- Credits to the [FlxAnimate](https://github.com/Dot-Stuff/flxanimate) team for the Animate Atlas support
|
- Credits to the [FlxAnimate](https://github.com/Dot-Stuff/flxanimate) team for the Animate Atlas support
|
||||||
- Credits to Smokey555 for the backup Animate Atlas to spritesheet code
|
- Credits to Smokey555 for the backup Animate Atlas to spritesheet code
|
||||||
- Credits to MAJigsaw77 for [hxvlc](https://github.com/MAJigsaw77/hxvlc) (video cutscene/mp4 support) and [hxdiscord_rpc](https://github.com/MAJigsaw77/hxdiscord_rpc) (discord rpc integration)
|
- Credits to MAJigsaw77 for [hxvlc](https://github.com/MAJigsaw77/hxvlc) (video cutscene/mp4 support) and [hxdiscord_rpc](https://github.com/MAJigsaw77/hxdiscord_rpc) (discord rpc integration)
|
||||||
|
- Credits to [TheoDev](https://github.com/TheoDevelops) for [FunkinModchart](https://lib.haxe.org/p/funkin-modchart/). ***(library used for modcharting features)***
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
<stepper name="alphaStepper" label="${translate('alpha')}" value="char.alpha / 0.75" x="col(0)" y="curY" precision="2" step="0.01" width="100" />
|
<stepper name="alphaStepper" label="${translate('alpha')}" value="char.alpha / 0.75" x="col(0)" y="curY" precision="2" step="0.01" width="100" />
|
||||||
<stepper name="angleStepper" label="${translate('angle')}" value="char.angle" x="last.x + last.bWidth + XOFFSET - 20" y="curY" precision="2" step="0.01" width="100" />
|
<stepper name="angleStepper" label="${translate('angle')}" value="char.angle" x="last.x + last.bWidth + XOFFSET - 20" y="curY" precision="2" step="0.01" width="100" />
|
||||||
|
|
||||||
<stepper name="zoomFactorStepper" label="${translate('zoomFactor')" value="char.zoomFactor" x="col(1)" y="curY" precision="2" step="0.01" width="100" />
|
<stepper name="zoomFactorStepper" label="${translate('zoomFactor')}" value="char.zoomFactor" x="col(1)" y="curY" precision="2" step="0.01" width="100" />
|
||||||
|
|
||||||
<section if="!StringTools.startsWith(char.name, 'NO_DELETE_')">
|
<section if="!StringTools.startsWith(char.name, 'NO_DELETE_')">
|
||||||
<textbox name="charName" label="${translate('positionName')}" value="char.name" x="col(2)" y="curY" width="100"/>
|
<textbox name="charName" label="${translate('positionName')}" value="char.name" x="col(2)" y="curY" width="100"/>
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
var sound:Sound;
|
var sound:FlxSound;
|
||||||
|
|
||||||
function create()
|
function create() {
|
||||||
sound = Paths.sound('jeffGameover/jeffGameover-' + FlxG.random.int(1, 25, !Options.naughtyness ? [1, 3, 8, 13, 17, 21] : null));
|
sound = FlxG.sound.load(Paths.sound('jeffGameover/jeffGameover-' + FlxG.random.int(1, 25, !Options.naughtyness ? [1, 3, 8, 13, 17, 21] : null)));
|
||||||
|
sound.onComplete = () -> FlxG.sound.music.fadeIn(4, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
function beatHit(cur:Int) if (cur == 0) {
|
function postDeathStart() {
|
||||||
FlxG.sound.play(sound, 1, false, null, true, () -> if (!isEnding) FlxG.sound.music.fadeIn(4, 0.2, 1));
|
sound.play();
|
||||||
FlxG.sound.music.volume = 0.2;
|
FlxG.sound.music.volume = 0.2;
|
||||||
}
|
}
|
||||||
|
After Width: | Height: | Size: 197 B |
|
After Width: | Height: | Size: 210 B |
|
After Width: | Height: | Size: 215 B |
@@ -9,6 +9,8 @@
|
|||||||
<str id="save">Save</str>
|
<str id="save">Save</str>
|
||||||
<str id="saveClose">Save & Close</str>
|
<str id="saveClose">Save & Close</str>
|
||||||
<str id="close">Close</str>
|
<str id="close">Close</str>
|
||||||
|
<str id="notNow">Not Now</str>
|
||||||
|
<str id="yes">Yes</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group name="UIImageExplorer" prefix="uiImageExplorer.">
|
<group name="UIImageExplorer" prefix="uiImageExplorer.">
|
||||||
@@ -43,12 +45,15 @@
|
|||||||
<group name="CharterSelection" prefix="charterSelection.">
|
<group name="CharterSelection" prefix="charterSelection.">
|
||||||
<str id="desc">Select a song to modify the charts from.</str>
|
<str id="desc">Select a song to modify the charts from.</str>
|
||||||
<str id="acceptSong">Press ACCEPT to choose a difficulty to edit.</str>
|
<str id="acceptSong">Press ACCEPT to choose a difficulty to edit.</str>
|
||||||
|
<str id="acceptVariation">Press ACCEPT to choose a song variation to edit.</str>
|
||||||
<str id="acceptDifficulty">Press ACCEPT to edit the chart for the selected difficulty.</str>
|
<str id="acceptDifficulty">Press ACCEPT to edit the chart for the selected difficulty.</str>
|
||||||
<str id="selectDifficulty">Select a difficulty to continue.</str>
|
<str id="selectDifficulty">Select a difficulty to continue.</str>
|
||||||
<str id="newDifficulty">New Difficulty</str>
|
<str id="newDifficulty">New Difficulty</str>
|
||||||
<str id="newDifficultyDesc">Press ACCEPT to create a new chart difficulty.</str>
|
<str id="newDifficultyDesc">Press ACCEPT to create a new chart difficulty.</str>
|
||||||
<str id="newSong">New Song</str>
|
<str id="newSong">New Song</str>
|
||||||
<str id="newSongDesc">Press ACCEPT to create a new song.</str>
|
<str id="newSongDesc">Press ACCEPT to create a new song.</str>
|
||||||
|
<str id="newVariation">New Variation</str>
|
||||||
|
<str id="newVariationDesc">Press ACCEPT to create a new song variation.</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group name="ChartCreationScreen" prefix="chartCreation.">
|
<group name="ChartCreationScreen" prefix="chartCreation.">
|
||||||
@@ -102,6 +107,7 @@
|
|||||||
|
|
||||||
<str id="songData">Song Data</str>
|
<str id="songData">Song Data</str>
|
||||||
<str id="songName">Song Name</str>
|
<str id="songName">Song Name</str>
|
||||||
|
<str id="variation">Song Variation</str>
|
||||||
<str id="bpm">BPM</str>
|
<str id="bpm">BPM</str>
|
||||||
<str id="timeSignature">Time Signature</str>
|
<str id="timeSignature">Time Signature</str>
|
||||||
<str id="menusData">Menus Data (Freeplay/Story)</str>
|
<str id="menusData">Menus Data (Freeplay/Story)</str>
|
||||||
@@ -111,6 +117,7 @@
|
|||||||
<str id="color">Color</str>
|
<str id="color">Color</str>
|
||||||
<str id="difficulties">Difficulties</str>
|
<str id="difficulties">Difficulties</str>
|
||||||
<str id="customValues">Custom Values (Advanced)</str>
|
<str id="customValues">Custom Values (Advanced)</str>
|
||||||
|
<str id="needsVoices">Needs Voices</str>
|
||||||
|
|
||||||
<str id="opponentMode">Opponent Mode</str>
|
<str id="opponentMode">Opponent Mode</str>
|
||||||
<str id="coopAllowed">Co-op Mode</str>
|
<str id="coopAllowed">Co-op Mode</str>
|
||||||
@@ -236,7 +243,7 @@
|
|||||||
<group name="BookmarkMenu" prefix="bookmarks.">
|
<group name="BookmarkMenu" prefix="bookmarks.">
|
||||||
<str id="addBookmarkHere">Add Bookmark Here</str>
|
<str id="addBookmarkHere">Add Bookmark Here</str>
|
||||||
<str id="editBookmarkList">Edit Bookmark List</str>
|
<str id="editBookmarkList">Edit Bookmark List</str>
|
||||||
<str id="goto">Go to "{0}"</str>
|
<str id="goTo">Go to "{0}"</str>
|
||||||
<str id="createBookmarkTitle">Creating New Bookmark...</str>
|
<str id="createBookmarkTitle">Creating New Bookmark...</str>
|
||||||
<str id="createBookmarkName">Bookmark Name:</str>
|
<str id="createBookmarkName">Bookmark Name:</str>
|
||||||
<str id="createBookmarkColor">Bookmark Color:</str>
|
<str id="createBookmarkColor">Bookmark Color:</str>
|
||||||
@@ -571,7 +578,7 @@
|
|||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group name="StageInfoScreen" prefix="stageInfoScreen">
|
<group name="StageInfoScreen" prefix="stageInfoScreen.">
|
||||||
<str id="win-title">Editing Stage "{0}" Infos</str>
|
<str id="win-title">Editing Stage "{0}" Infos</str>
|
||||||
<str id="title">Stage Info</str>
|
<str id="title">Stage Info</str>
|
||||||
<str id="stageName">Stage Name</str>
|
<str id="stageName">Stage Name</str>
|
||||||
@@ -665,4 +672,12 @@
|
|||||||
<str id="saveAndExitToMenu">Save & Exit To Menu</str>
|
<str id="saveAndExitToMenu">Save & Exit To Menu</str>
|
||||||
<str id="cancel">Cancel</str>
|
<str id="cancel">Cancel</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
|
<group name="ModConfigWarning" prefix="modConfigWarning.">
|
||||||
|
<str id="warningTitle">Missing mod folder configuration!</str>
|
||||||
|
<str id="warningDesc">Your mod is currently missing a mod config file!\n\nWould you like to automatically generate one?\n\n(PS: If this is not your mod please disable Developer mode to stop this popup from appearing.)</str>
|
||||||
|
|
||||||
|
<str id="createdTitle">Created mod config!</str>
|
||||||
|
<str id="createdDesc">Your mod config file has been created at {0}!</str>
|
||||||
|
</group>
|
||||||
</language>
|
</language>
|
||||||
@@ -42,6 +42,7 @@
|
|||||||
<str id="back">Back</str>
|
<str id="back">Back</str>
|
||||||
<str id="reset">Reset</str>
|
<str id="reset">Reset</str>
|
||||||
<str id="pause">Pause</str>
|
<str id="pause">Pause</str>
|
||||||
|
<str id="changeMode">Change Mode</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<str id="category.engine">Engine</str>
|
<str id="category.engine">Engine</str>
|
||||||
@@ -50,6 +51,8 @@
|
|||||||
</group>
|
</group>
|
||||||
|
|
||||||
<str id="category.volume">Volume</str>
|
<str id="category.volume">Volume</str>
|
||||||
|
<str id="volume.up">Up</str>
|
||||||
|
<str id="volume.down">Down</str>
|
||||||
<str id="volume.mute">Mute</str>
|
<str id="volume.mute">Mute</str>
|
||||||
|
|
||||||
<str id="category.developer">Developer</str>
|
<str id="category.developer">Developer</str>
|
||||||
|
|||||||
@@ -105,6 +105,7 @@
|
|||||||
<str id="modesAllowed">Modos Permitidos</str>
|
<str id="modesAllowed">Modos Permitidos</str>
|
||||||
<str id="difficulties">Difficultades</str>
|
<str id="difficulties">Difficultades</str>
|
||||||
<str id="customValues">Valores Especiales (Avanzado)</str>
|
<str id="customValues">Valores Especiales (Avanzado)</str>
|
||||||
|
<str id="needsVoices">Necesita Voces</str>
|
||||||
|
|
||||||
<str id="opponentMode">Modo Oponente</str>
|
<str id="opponentMode">Modo Oponente</str>
|
||||||
<str id="coopAllowed">Modo Co-op</str>
|
<str id="coopAllowed">Modo Co-op</str>
|
||||||
@@ -225,7 +226,7 @@
|
|||||||
<group name="BookmarkMenu" prefix="bookmarks.">
|
<group name="BookmarkMenu" prefix="bookmarks.">
|
||||||
<str id="addBookmarkHere">Añadir Marcador Aquí</str>
|
<str id="addBookmarkHere">Añadir Marcador Aquí</str>
|
||||||
<str id="editBookmarkList">Editar Lista de Marcadores</str>
|
<str id="editBookmarkList">Editar Lista de Marcadores</str>
|
||||||
<str id="goto">Ir hacia "{0}"</str>
|
<str id="goTo">Ir hacia "{0}"</str>
|
||||||
<str id="createBookmarkTitle">Creando Nuevo Marcador...</str>
|
<str id="createBookmarkTitle">Creando Nuevo Marcador...</str>
|
||||||
<str id="createBookmarkName">Nombre de Marcador:</str>
|
<str id="createBookmarkName">Nombre de Marcador:</str>
|
||||||
<str id="createBookmarkColor">Color de Marcador:</str>
|
<str id="createBookmarkColor">Color de Marcador:</str>
|
||||||
@@ -544,7 +545,7 @@
|
|||||||
<str id="stagePath">Ubicación de Imágenes</str>
|
<str id="stagePath">Ubicación de Imágenes</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group name="StageInfoScreen" prefix="stageInfoScreen">
|
<group name="StageInfoScreen" prefix="stageInfoScreen.">
|
||||||
<str id="win-title">Editando info. del escenario: "{0}"</str>
|
<str id="win-title">Editando info. del escenario: "{0}"</str>
|
||||||
<str id="title">Info. del Escenario</str>
|
<str id="title">Info. del Escenario</str>
|
||||||
<str id="stageName">Nombre del Escenario</str>
|
<str id="stageName">Nombre del Escenario</str>
|
||||||
|
|||||||
@@ -49,6 +49,8 @@
|
|||||||
</group>
|
</group>
|
||||||
|
|
||||||
<str id="category.volume">Volumen</str>
|
<str id="category.volume">Volumen</str>
|
||||||
|
<str id="volume.up">Arriba</str>
|
||||||
|
<str id="volume.down">Abajo</str>
|
||||||
<str id="volume.mute">mutear</str>
|
<str id="volume.mute">mutear</str>
|
||||||
|
|
||||||
<str id="category.developer">Desarrollador</str>
|
<str id="category.developer">Desarrollador</str>
|
||||||
|
|||||||
@@ -108,8 +108,9 @@
|
|||||||
<str id="color">Colore</str>
|
<str id="color">Colore</str>
|
||||||
<str id="difficulties">Difficoltà</str>
|
<str id="difficulties">Difficoltà</str>
|
||||||
<str id="customValues">Valori Personalizzati (Avanzato)</str>
|
<str id="customValues">Valori Personalizzati (Avanzato)</str>
|
||||||
|
<str id="needsVoices">Bisogno Voci</str>
|
||||||
|
|
||||||
<str id="opponentMode">Modalità Avvers.</str>
|
<str id="opponentMode">Modalità Avvers</str>
|
||||||
<str id="coopAllowed">Modalità Co-op</str>
|
<str id="coopAllowed">Modalità Co-op</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
@@ -231,7 +232,7 @@
|
|||||||
<group name="BookmarkMenu" prefix="bookmarks.">
|
<group name="BookmarkMenu" prefix="bookmarks.">
|
||||||
<str id="addBookmarkHere">Aggiungi Segnalibro Qui</str>
|
<str id="addBookmarkHere">Aggiungi Segnalibro Qui</str>
|
||||||
<str id="editBookmarkList">Modifica Lista Segnalibri</str>
|
<str id="editBookmarkList">Modifica Lista Segnalibri</str>
|
||||||
<str id="goto">Vai a "{0}"</str>
|
<str id="goTo">Vai a "{0}"</str>
|
||||||
<str id="createBookmarkTitle">Creazione nuovo Segnalibro...</str>
|
<str id="createBookmarkTitle">Creazione nuovo Segnalibro...</str>
|
||||||
<str id="createBookmarkName">Nome Segnalibro:</str>
|
<str id="createBookmarkName">Nome Segnalibro:</str>
|
||||||
<str id="createBookmarkColor">Colore Segnalibro:</str>
|
<str id="createBookmarkColor">Colore Segnalibro:</str>
|
||||||
@@ -554,7 +555,7 @@
|
|||||||
<str id="stagePath">Percorso file Palcoscenico</str>
|
<str id="stagePath">Percorso file Palcoscenico</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group name="StageInfoScreen" prefix="stageInfoScreen">
|
<group name="StageInfoScreen" prefix="stageInfoScreen.">
|
||||||
<str id="win-title">Modificando Informazioni Palcoscenico "{0}"</str>
|
<str id="win-title">Modificando Informazioni Palcoscenico "{0}"</str>
|
||||||
<str id="title">Informazioni Palcoscenico</str>
|
<str id="title">Informazioni Palcoscenico</str>
|
||||||
<str id="stageName">Nome Palcoscenico</str>
|
<str id="stageName">Nome Palcoscenico</str>
|
||||||
|
|||||||
@@ -48,6 +48,8 @@
|
|||||||
<str id="switchMod">Cambia Mod</str>
|
<str id="switchMod">Cambia Mod</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
|
<str id="volume.up">Su</str>
|
||||||
|
<str id="volume.down">Giù</str>
|
||||||
<str id="volume.mute">Muto</str>
|
<str id="volume.mute">Muto</str>
|
||||||
|
|
||||||
<str id="category.developer">Sviluppatore</str>
|
<str id="category.developer">Sviluppatore</str>
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
<str id="save">Zapisz</str>
|
<str id="save">Zapisz</str>
|
||||||
<str id="saveClose">Zapisz i Zamknij</str>
|
<str id="saveClose">Zapisz i Zamknij</str>
|
||||||
<str id="close">Zamknij</str>
|
<str id="close">Zamknij</str>
|
||||||
|
<str id="notNow">Nie Teraz</str>
|
||||||
|
<str id="yes">Tak</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group name="UIImageExplorer" prefix="uiImageExplorer.">
|
<group name="UIImageExplorer" prefix="uiImageExplorer.">
|
||||||
@@ -109,6 +111,7 @@
|
|||||||
<str id="color">Kolor</str>
|
<str id="color">Kolor</str>
|
||||||
<str id="difficulties">Trudności</str>
|
<str id="difficulties">Trudności</str>
|
||||||
<str id="customValues">Własna Waluta (Zaawansowane)</str>
|
<str id="customValues">Własna Waluta (Zaawansowane)</str>
|
||||||
|
<str id="needsVoices">Potrzebne Wokale</str>
|
||||||
|
|
||||||
<str id="opponentMode">Tryb Przeciwnika</str>
|
<str id="opponentMode">Tryb Przeciwnika</str>
|
||||||
<str id="coopAllowed">Tryb Ko-operacyjny</str>
|
<str id="coopAllowed">Tryb Ko-operacyjny</str>
|
||||||
@@ -234,7 +237,7 @@
|
|||||||
<group name="BookmarkMenu" prefix="bookmarks.">
|
<group name="BookmarkMenu" prefix="bookmarks.">
|
||||||
<str id="addBookmarkHere">Dodaj Zakładkę Tutaj</str>
|
<str id="addBookmarkHere">Dodaj Zakładkę Tutaj</str>
|
||||||
<str id="editBookmarkList">Edytuj Listę Zakładek</str>
|
<str id="editBookmarkList">Edytuj Listę Zakładek</str>
|
||||||
<str id="goto">Idź do "{0}"</str>
|
<str id="goTo">Idź do "{0}"</str>
|
||||||
<str id="createBookmarkTitle">Tworzenie Nowej Zakładki...</str>
|
<str id="createBookmarkTitle">Tworzenie Nowej Zakładki...</str>
|
||||||
<str id="createBookmarkName">Nazwa Zakładki:</str>
|
<str id="createBookmarkName">Nazwa Zakładki:</str>
|
||||||
<str id="createBookmarkColor">Kolor Zakładki:</str>
|
<str id="createBookmarkColor">Kolor Zakładki:</str>
|
||||||
@@ -559,7 +562,7 @@
|
|||||||
<str id="stagePath">Ścieżka Plikowa Sceny</str>
|
<str id="stagePath">Ścieżka Plikowa Sceny</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group name="StageInfoScreen" prefix="stageInfoScreen">
|
<group name="StageInfoScreen" prefix="stageInfoScreen.">
|
||||||
<str id="win-title">Edytowanie Info Sceny "{0}"</str>
|
<str id="win-title">Edytowanie Info Sceny "{0}"</str>
|
||||||
<str id="title">Info Sceny</str>
|
<str id="title">Info Sceny</str>
|
||||||
<str id="stageName">Nazwa Sceny</str>
|
<str id="stageName">Nazwa Sceny</str>
|
||||||
@@ -653,4 +656,12 @@
|
|||||||
<str id="saveAndExitToMenu">Zapisz i Wyjdź do Menu</str>
|
<str id="saveAndExitToMenu">Zapisz i Wyjdź do Menu</str>
|
||||||
<str id="cancel">Anuluj</str>
|
<str id="cancel">Anuluj</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
|
<group name="ModConfigWarning" prefix="modConfigWarning.">
|
||||||
|
<str id="warningTitle">Brakujący plik konfiguracyjny modu!</str>
|
||||||
|
<str id="warningDesc">Twój mod obecnie brakuje jego pliku konfiguracyjnego!\n\nCzy chcesz go automatycznie wygenerować?\n\n(PS: Jeżeli to nie twój mod, wyłącz Tryb Dewelopera, aby zapobiec wyskakiwaniu się tego okienka.)</str>
|
||||||
|
|
||||||
|
<str id="createdTitle">Utworzono konfigurację modu!</str>
|
||||||
|
<str id="createdDesc">Twój plik konfiguracyjny modu został utworzony w {0}!</str>
|
||||||
|
</group>
|
||||||
</language>
|
</language>
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
<str id="credits.allContributors">Wszyscy współpracownicy silnika! - Naciśnij RESET aby zaktualizować listę (Jeden reset co 2 minuty).</str>
|
<str id="credits.allContributors">Wszyscy współpracownicy silnika! - Naciśnij RESET aby zaktualizować listę (Jeden reset co 2 minuty).</str>
|
||||||
</group>
|
</group>
|
||||||
<group name="CreditsMain">
|
<group name="CreditsMain">
|
||||||
<str id="credits.name">Kredyty</str>
|
<str id="credits.name">Twórcy</str>
|
||||||
<str id="credits.madePossible">Ludzie którzy to umożliwili!</str>
|
<str id="credits.madePossible">Ludzie którzy to umożliwili!</str>
|
||||||
<str id="credits.selectCodename">Wybierz to aby zobaczyć wszystkich współpracowników!</str>
|
<str id="credits.selectCodename">Wybierz to aby zobaczyć wszystkich współpracowników!</str>
|
||||||
<str id="credits.selectBase">Wybierz to aby otworzyć stronę itch.io oryginalnej gry!</str>
|
<str id="credits.selectBase">Wybierz to aby otworzyć stronę itch.io oryginalnej gry!</str>
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
<str id="back">Wstecz</str>
|
<str id="back">Wstecz</str>
|
||||||
<str id="reset">Reset</str>
|
<str id="reset">Reset</str>
|
||||||
<str id="pause">Pauza</str>
|
<str id="pause">Pauza</str>
|
||||||
|
<str id="changeMode">Zmień Tryb</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<str id="category.engine">Silnik</str>
|
<str id="category.engine">Silnik</str>
|
||||||
@@ -46,6 +47,8 @@
|
|||||||
</group>
|
</group>
|
||||||
|
|
||||||
<str id="category.volume">Głośność</str>
|
<str id="category.volume">Głośność</str>
|
||||||
|
<str id="volume.up">Głóśniej</str>
|
||||||
|
<str id="volume.down">Ciszej</str>
|
||||||
<str id="volume.mute">Wycisz</str>
|
<str id="volume.mute">Wycisz</str>
|
||||||
|
|
||||||
<str id="category.developer">Deweloper</str>
|
<str id="category.developer">Deweloper</str>
|
||||||
|
|||||||
|
After Width: | Height: | Size: 68 KiB |
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<TextureAtlas imagePath="credits.png" width="3341" height="162">
|
||||||
|
<SubTexture name="credits basic0000" x="1" y="1" width="440" height="116" frameX="-0" frameY="-0" frameWidth="440" frameHeight="116"/>
|
||||||
|
<SubTexture name="credits basic0001" x="1" y="1" width="440" height="116" frameX="-0" frameY="-0" frameWidth="440" frameHeight="116"/>
|
||||||
|
<SubTexture name="credits basic0002" x="1" y="1" width="440" height="116" frameX="-0" frameY="-0" frameWidth="440" frameHeight="116"/>
|
||||||
|
<SubTexture name="credits basic0003" x="443" y="1" width="440" height="116" frameX="-0" frameY="-0" frameWidth="440" frameHeight="116"/>
|
||||||
|
<SubTexture name="credits basic0004" x="443" y="1" width="440" height="116" frameX="-0" frameY="-0" frameWidth="440" frameHeight="116"/>
|
||||||
|
<SubTexture name="credits basic0005" x="443" y="1" width="440" height="116" frameX="-0" frameY="-0" frameWidth="440" frameHeight="116"/>
|
||||||
|
<SubTexture name="credits basic0006" x="885" y="1" width="440" height="116" frameX="-0" frameY="-0" frameWidth="440" frameHeight="116"/>
|
||||||
|
<SubTexture name="credits basic0007" x="885" y="1" width="440" height="116" frameX="-0" frameY="-0" frameWidth="440" frameHeight="116"/>
|
||||||
|
<SubTexture name="credits basic0008" x="885" y="1" width="440" height="116" frameX="-0" frameY="-0" frameWidth="440" frameHeight="116"/>
|
||||||
|
<SubTexture name="credits white0000" x="2668" y="1" width="672" height="160" frameX="-0" frameY="25" frameWidth="672" frameHeight="160"/>
|
||||||
|
<SubTexture name="credits white0001" x="1327" y="1" width="669" height="156" frameX="-2" frameY="24" frameWidth="672" frameHeight="160"/>
|
||||||
|
<SubTexture name="credits white0002" x="1998" y="1" width="668" height="157" frameX="-4" frameY="22" frameWidth="672" frameHeight="160"/>
|
||||||
|
</TextureAtlas>
|
||||||
|
After Width: | Height: | Size: 126 KiB |
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<TextureAtlas imagePath="freeplay.png" width="1027" height="927">
|
||||||
|
<SubTexture name="freeplay basic0000" x="1" y="556" width="701" height="122" frameX="-0" frameY="-0" frameWidth="701" frameHeight="122"/>
|
||||||
|
<SubTexture name="freeplay basic0001" x="1" y="556" width="701" height="122" frameX="-0" frameY="-0" frameWidth="701" frameHeight="122"/>
|
||||||
|
<SubTexture name="freeplay basic0002" x="1" y="556" width="701" height="122" frameX="-0" frameY="-0" frameWidth="701" frameHeight="122"/>
|
||||||
|
<SubTexture name="freeplay basic0003" x="1" y="680" width="701" height="122" frameX="-0" frameY="-0" frameWidth="701" frameHeight="122"/>
|
||||||
|
<SubTexture name="freeplay basic0004" x="1" y="680" width="701" height="122" frameX="-0" frameY="-0" frameWidth="701" frameHeight="122"/>
|
||||||
|
<SubTexture name="freeplay basic0005" x="1" y="680" width="701" height="122" frameX="-0" frameY="-0" frameWidth="701" frameHeight="122"/>
|
||||||
|
<SubTexture name="freeplay basic0006" x="1" y="804" width="701" height="122" frameX="-0" frameY="-0" frameWidth="701" frameHeight="122"/>
|
||||||
|
<SubTexture name="freeplay basic0007" x="1" y="804" width="701" height="122" frameX="-0" frameY="-0" frameWidth="701" frameHeight="122"/>
|
||||||
|
<SubTexture name="freeplay basic0008" x="1" y="804" width="701" height="122" frameX="-0" frameY="-0" frameWidth="701" frameHeight="122"/>
|
||||||
|
<SubTexture name="freeplay white0000" x="1" y="373" width="1020" height="181" frameX="-7" frameY="30" frameWidth="1027" frameHeight="188"/>
|
||||||
|
<SubTexture name="freeplay white0001" x="1" y="187" width="1021" height="184" frameX="-4" frameY="30" frameWidth="1027" frameHeight="188"/>
|
||||||
|
<SubTexture name="freeplay white0002" x="1" y="1" width="1025" height="184" frameX="-0" frameY="26" frameWidth="1027" frameHeight="188"/>
|
||||||
|
</TextureAtlas>
|
||||||
|
After Width: | Height: | Size: 48 KiB |
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<TextureAtlas imagePath="options.png" width="2449" height="159">
|
||||||
|
<SubTexture name="options basic0000" x="1" y="1" width="343" height="113" frameX="-0" frameY="-0" frameWidth="343" frameHeight="113"/>
|
||||||
|
<SubTexture name="options basic0001" x="1" y="1" width="343" height="113" frameX="-0" frameY="-0" frameWidth="343" frameHeight="113"/>
|
||||||
|
<SubTexture name="options basic0002" x="1" y="1" width="343" height="113" frameX="-0" frameY="-0" frameWidth="343" frameHeight="113"/>
|
||||||
|
<SubTexture name="options basic0003" x="346" y="1" width="343" height="113" frameX="-0" frameY="-0" frameWidth="343" frameHeight="113"/>
|
||||||
|
<SubTexture name="options basic0004" x="346" y="1" width="343" height="113" frameX="-0" frameY="-0" frameWidth="343" frameHeight="113"/>
|
||||||
|
<SubTexture name="options basic0005" x="346" y="1" width="343" height="113" frameX="-0" frameY="-0" frameWidth="343" frameHeight="113"/>
|
||||||
|
<SubTexture name="options basic0006" x="691" y="1" width="343" height="113" frameX="-0" frameY="-0" frameWidth="343" frameHeight="113"/>
|
||||||
|
<SubTexture name="options basic0007" x="691" y="1" width="343" height="113" frameX="-0" frameY="-0" frameWidth="343" frameHeight="113"/>
|
||||||
|
<SubTexture name="options basic0008" x="691" y="1" width="343" height="113" frameX="-0" frameY="-0" frameWidth="343" frameHeight="113"/>
|
||||||
|
<SubTexture name="options white0000" x="1036" y="1" width="474" height="156" frameX="-0" frameY="15" frameWidth="474" frameHeight="157"/>
|
||||||
|
<SubTexture name="options white0001" x="1512" y="1" width="465" height="156" frameX="-6" frameY="14" frameWidth="474" frameHeight="157"/>
|
||||||
|
<SubTexture name="options white0002" x="1979" y="1" width="469" height="157" frameX="-4" frameY="15" frameWidth="474" frameHeight="157"/>
|
||||||
|
</TextureAtlas>
|
||||||
|
After Width: | Height: | Size: 93 KiB |
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<TextureAtlas imagePath="story mode.png" width="1230" height="556">
|
||||||
|
<SubTexture name="story mode basic0000" x="734" y="1" width="495" height="116" frameX="-0" frameY="-0" frameWidth="495" frameHeight="116"/>
|
||||||
|
<SubTexture name="story mode basic0001" x="734" y="1" width="495" height="116" frameX="-0" frameY="-0" frameWidth="495" frameHeight="116"/>
|
||||||
|
<SubTexture name="story mode basic0002" x="734" y="1" width="495" height="116" frameX="-0" frameY="-0" frameWidth="495" frameHeight="116"/>
|
||||||
|
<SubTexture name="story mode basic0003" x="734" y="119" width="495" height="116" frameX="-0" frameY="-0" frameWidth="495" frameHeight="116"/>
|
||||||
|
<SubTexture name="story mode basic0004" x="734" y="119" width="495" height="116" frameX="-0" frameY="-0" frameWidth="495" frameHeight="116"/>
|
||||||
|
<SubTexture name="story mode basic0005" x="734" y="119" width="495" height="116" frameX="-0" frameY="-0" frameWidth="495" frameHeight="116"/>
|
||||||
|
<SubTexture name="story mode basic0006" x="730" y="237" width="495" height="116" frameX="-0" frameY="-0" frameWidth="495" frameHeight="116"/>
|
||||||
|
<SubTexture name="story mode basic0007" x="730" y="237" width="495" height="116" frameX="-0" frameY="-0" frameWidth="495" frameHeight="116"/>
|
||||||
|
<SubTexture name="story mode basic0008" x="730" y="237" width="495" height="116" frameX="-0" frameY="-0" frameWidth="495" frameHeight="116"/>
|
||||||
|
<SubTexture name="story mode white0000" x="1" y="375" width="732" height="180" frameX="-0" frameY="28" frameWidth="732" frameHeight="186"/>
|
||||||
|
<SubTexture name="story mode white0001" x="1" y="1" width="731" height="185" frameX="-0" frameY="30" frameWidth="732" frameHeight="186"/>
|
||||||
|
<SubTexture name="story mode white0002" x="1" y="188" width="727" height="185" frameX="-0" frameY="29" frameWidth="732" frameHeight="186"/>
|
||||||
|
</TextureAtlas>
|
||||||
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
@@ -0,0 +1,60 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
Created with Funkin Packer v0.1.3 https://neeeoo.github.io/funkin-packer/
|
||||||
|
-->
|
||||||
|
<TextureAtlas imagePath="titleEnter.png" width="1186" height="2650">
|
||||||
|
<SubTexture name="ENTER PRESSED0000" x="1" y="1" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="ENTER PRESSED0001" x="1" y="107" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="ENTER PRESSED0002" x="1" y="1" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="ENTER PRESSED0003" x="1" y="107" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="ENTER PRESSED0004" x="1" y="1" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="ENTER PRESSED0005" x="1" y="107" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="ENTER PRESSED0006" x="1" y="1" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="ENTER PRESSED0007" x="1" y="107" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0000" x="1" y="213" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0001" x="1" y="319" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0002" x="1" y="425" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0003" x="1" y="531" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0004" x="1" y="637" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0005" x="1" y="743" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0006" x="1" y="849" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0007" x="1" y="955" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0008" x="1" y="1061" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0009" x="1" y="1167" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0010" x="1" y="1273" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0011" x="1" y="1379" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0012" x="1" y="1485" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0013" x="1" y="1591" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0014" x="1" y="1697" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0015" x="1" y="1803" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0016" x="1" y="1909" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0017" x="1" y="2015" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0018" x="1" y="2121" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0019" x="1" y="2227" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0020" x="1" y="2333" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0021" x="1" y="2439" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0022" x="1" y="2545" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0023" x="1" y="2545" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0024" x="1" y="2439" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0025" x="1" y="2333" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0026" x="1" y="2227" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0027" x="1" y="2121" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0028" x="1" y="2015" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0029" x="1" y="1909" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0030" x="1" y="1803" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0031" x="1" y="1697" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0032" x="1" y="1591" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0033" x="1" y="1485" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0034" x="1" y="1379" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0035" x="1" y="1273" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0036" x="1" y="1167" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0037" x="1" y="1061" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0038" x="1" y="955" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0039" x="1" y="849" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0040" x="1" y="743" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0041" x="1" y="637" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0042" x="1" y="531" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0043" x="1" y="425" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0044" x="1" y="319" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
<SubTexture name="Press Enter to Begin0045" x="1" y="213" width="1184" height="104" frameX="-143" frameY="-1" frameWidth="1494" frameHeight="110"/>
|
||||||
|
</TextureAtlas>
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
name="Polski"
|
name="Polski"
|
||||||
credits="GlitchDotSmh & Kolze"
|
credits="GlitchDotSmh, Kolze & Verwex"
|
||||||
version="1.0.0"
|
version="1.1.0"
|
||||||
|
Before Width: | Height: | Size: 564 KiB |
@@ -1,60 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
Created with Funkin Packer v0.1.3 https://neeeoo.github.io/funkin-packer/
|
|
||||||
-->
|
|
||||||
<TextureAtlas imagePath="titleEnter.png" width="1258" height="1991">
|
|
||||||
<SubTexture name="ENTER PRESSED0001" x="1" y="1" width="1256" height="73" frameX="-105" frameY="-0" frameWidth="1478" frameHeight="78"/>
|
|
||||||
<SubTexture name="ENTER PRESSED0002" x="1" y="77" width="1256" height="73" frameX="-105" frameY="-0" frameWidth="1478" frameHeight="78"/>
|
|
||||||
<SubTexture name="ENTER PRESSED0003" x="1" y="1" width="1256" height="73" frameX="-105" frameY="-0" frameWidth="1478" frameHeight="78"/>
|
|
||||||
<SubTexture name="ENTER PRESSED0004" x="1" y="77" width="1256" height="73" frameX="-105" frameY="-0" frameWidth="1478" frameHeight="78"/>
|
|
||||||
<SubTexture name="ENTER PRESSED0005" x="1" y="1" width="1256" height="73" frameX="-105" frameY="-0" frameWidth="1478" frameHeight="78"/>
|
|
||||||
<SubTexture name="ENTER PRESSED0006" x="1" y="77" width="1256" height="73" frameX="-105" frameY="-0" frameWidth="1478" frameHeight="78"/>
|
|
||||||
<SubTexture name="ENTER PRESSED0007" x="1" y="1" width="1256" height="73" frameX="-105" frameY="-0" frameWidth="1478" frameHeight="78"/>
|
|
||||||
<SubTexture name="ENTER PRESSED0008" x="1" y="77" width="1256" height="73" frameX="-105" frameY="-0" frameWidth="1478" frameHeight="78"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0001" x="1" y="153" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0002" x="1" y="233" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0003" x="1" y="313" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0004" x="1" y="393" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0005" x="1" y="473" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0006" x="1" y="553" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0007" x="1" y="633" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0008" x="1" y="713" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0009" x="1" y="793" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0010" x="1" y="873" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0011" x="1" y="953" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0012" x="1" y="1033" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0013" x="1" y="1113" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0014" x="1" y="1193" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0015" x="1" y="1273" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0016" x="1" y="1353" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0017" x="1" y="1433" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0018" x="1" y="1513" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0019" x="1" y="1593" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0020" x="1" y="1673" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0021" x="1" y="1753" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0022" x="1" y="1833" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0023" x="1" y="1913" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0024" x="1" y="1913" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0025" x="1" y="1833" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0026" x="1" y="1753" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0027" x="1" y="1673" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0028" x="1" y="1593" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0029" x="1" y="1513" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0030" x="1" y="1433" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0031" x="1" y="1353" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0032" x="1" y="1273" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0033" x="1" y="1193" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0034" x="1" y="1113" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0035" x="1" y="1033" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0036" x="1" y="953" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0037" x="1" y="873" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0038" x="1" y="793" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0039" x="1" y="713" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0040" x="1" y="633" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0041" x="1" y="553" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0042" x="1" y="473" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0043" x="1" y="393" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0044" x="1" y="313" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0045" x="1" y="233" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
<SubTexture name="Press Enter to Begin0046" x="1" y="153" width="1255" height="77" frameX="-112" frameY="-3" frameWidth="1494" frameHeight="96"/>
|
|
||||||
</TextureAtlas>
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<git name="hscript-improved" url="https://github.com/CodenameCrew/hscript-improved" ref="codename-dev" />
|
<git name="hscript-improved" url="https://github.com/CodenameCrew/hscript-improved" ref="codename-dev" />
|
||||||
<git name="flxanimate" url="https://github.com/CodenameCrew/cne-flxanimate" />
|
<git name="flxanimate" url="https://github.com/CodenameCrew/cne-flxanimate" />
|
||||||
<git name="hxdiscord_rpc" url="https://github.com/CodenameCrew/cne-hxdiscord_rpc" skipDeps="true" />
|
<git name="hxdiscord_rpc" url="https://github.com/CodenameCrew/cne-hxdiscord_rpc" skipDeps="true" />
|
||||||
<git name="funkin-modchart" url="https://github.com/CodenameCrew/FunkinModchart" skipDeps="true" />
|
<git name="funkin-modchart" url="https://github.com/TheoDevelops/FunkinModchart" ref="f30676579d8de7ccac7d12e13b664e8b2c42c6bf" skipDeps="true" />
|
||||||
<lib name="hxvlc" version="1.9.3" skipDeps="true" />
|
<lib name="hxvlc" version="1.9.3" skipDeps="true" />
|
||||||
|
|
||||||
<!-- Documentation and other features -->
|
<!-- Documentation and other features -->
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
title="Friday Night Funkin' - Codename Engine" main="funkin.backend.system.Main"
|
title="Friday Night Funkin' - Codename Engine" main="funkin.backend.system.Main"
|
||||||
file="CodenameEngine" packageName="com.yoshman29.codenameengine"
|
file="CodenameEngine" packageName="com.yoshman29.codenameengine"
|
||||||
package="com.yoshman29.codenameengine"
|
package="com.yoshman29.codenameengine"
|
||||||
version="1.0.0" company="Yoshman29" />
|
version="1.0.1" company="Yoshman29" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
CHANGE THE SAVE PATH & NAME FOR YOUR MOD HERE!
|
CHANGE THE SAVE PATH & NAME FOR YOUR MOD HERE!
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
<!-- _________________________________ Engine Settings _______________________________ -->
|
<!-- _________________________________ Engine Settings _______________________________ -->
|
||||||
|
|
||||||
<!-- Comment this out to disable updates !-->
|
<!-- Comment this out to disable updates !-->
|
||||||
<!-- <define name="UPDATE_CHECKING" unless="web || hl || neko"/> -->
|
<define name="UPDATE_CHECKING" unless="web || hl || neko"/>
|
||||||
|
|
||||||
<!-- Comment this out to disable Discord RPC !-->
|
<!-- Comment this out to disable Discord RPC !-->
|
||||||
<section if="cpp">
|
<section if="cpp">
|
||||||
@@ -227,9 +227,9 @@
|
|||||||
<setenv name="HAXEPATH" value="./"/>
|
<setenv name="HAXEPATH" value="./"/>
|
||||||
|
|
||||||
<haxedef name="HXCPP_M32" if="32bit" />
|
<haxedef name="HXCPP_M32" if="32bit" />
|
||||||
<haxedef name="HXCPP_CHECK_POINTER" if="release" />
|
|
||||||
<haxedef name="HXCPP_STACK_LINE" if="release" />
|
|
||||||
<haxedef name="HXCPP_DEBUG_LINK" if="debug" />
|
<haxedef name="HXCPP_DEBUG_LINK" if="debug" />
|
||||||
|
<haxedef name="HXCPP_CHECK_POINTER" />
|
||||||
|
<haxedef name="HXCPP_STACK_LINE" />
|
||||||
<haxedef name="HXCPP_CATCH_SEGV" />
|
<haxedef name="HXCPP_CATCH_SEGV" />
|
||||||
|
|
||||||
<haxedef name="hscriptPos" /> <!-- for logging -->
|
<haxedef name="hscriptPos" /> <!-- for logging -->
|
||||||
|
|||||||
@@ -11,13 +11,14 @@ import funkin.backend.system.Controls;
|
|||||||
import funkin.backend.system.GraphicCacheSprite;
|
import funkin.backend.system.GraphicCacheSprite;
|
||||||
import funkin.backend.system.framerate.Framerate;
|
import funkin.backend.system.framerate.Framerate;
|
||||||
import funkin.backend.system.interfaces.IBeatReceiver;
|
import funkin.backend.system.interfaces.IBeatReceiver;
|
||||||
|
import funkin.backend.system.interfaces.IBeatCancellableReceiver;
|
||||||
import funkin.options.PlayerSettings;
|
import funkin.options.PlayerSettings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all the states.
|
* Base class for all the states.
|
||||||
* Handles the scripts, the transitions, and the beat and step events.
|
* Handles the scripts, the transitions, and the beat and step events.
|
||||||
**/
|
**/
|
||||||
class MusicBeatState extends FlxState implements IBeatReceiver
|
class MusicBeatState extends FlxState implements IBeatCancellableReceiver
|
||||||
{
|
{
|
||||||
private var lastBeat:Float = 0;
|
private var lastBeat:Float = 0;
|
||||||
private var lastStep:Float = 0;
|
private var lastStep:Float = 0;
|
||||||
|
|||||||
@@ -9,17 +9,23 @@ import funkin.backend.scripting.events.*;
|
|||||||
import funkin.backend.system.Conductor;
|
import funkin.backend.system.Conductor;
|
||||||
import funkin.backend.system.Controls;
|
import funkin.backend.system.Controls;
|
||||||
import funkin.backend.system.interfaces.IBeatReceiver;
|
import funkin.backend.system.interfaces.IBeatReceiver;
|
||||||
|
import funkin.backend.system.interfaces.IBeatCancellableReceiver;
|
||||||
import funkin.options.PlayerSettings;
|
import funkin.options.PlayerSettings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all the sub states.
|
* Base class for all the sub states.
|
||||||
* Handles the scripts, the transitions, and the beat and step events.
|
* Handles the scripts, the transitions, and the beat and step events.
|
||||||
**/
|
**/
|
||||||
class MusicBeatSubstate extends FlxSubState implements IBeatReceiver
|
class MusicBeatSubstate extends FlxSubState implements IBeatCancellableReceiver
|
||||||
{
|
{
|
||||||
private var lastBeat:Float = 0;
|
private var lastBeat:Float = 0;
|
||||||
private var lastStep:Float = 0;
|
private var lastStep:Float = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whenever the Conductor auto update should be enabled or not.
|
||||||
|
*/
|
||||||
|
public var cancelConductorUpdate:Bool = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this specific substate can open custom transitions
|
* Whether this specific substate can open custom transitions
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -23,8 +23,29 @@ class Paths
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static inline function getPath(file:String, ?library:String)
|
public static inline function getPath(file:String, ?library:String) {
|
||||||
return library != null ? '$library:assets/$library/$file' : 'assets/$file';
|
var returnedPath:String = library != null ? '$library:assets/$library/$file' : 'assets/$file';
|
||||||
|
#if (sys && !windows)
|
||||||
|
returnedPath = Path.normalize(returnedPath);
|
||||||
|
if (OpenFlAssets.exists(returnedPath)) return returnedPath;
|
||||||
|
var fixedPath:String = library != null ? '$library:assets/$library/' : 'assets/';
|
||||||
|
var parts:Array<String> = returnedPath.split("/");
|
||||||
|
for (it=>part in parts) {
|
||||||
|
if (it == 0) continue;
|
||||||
|
var entries:Array<String> = null;
|
||||||
|
if (Path.extension(part) == "") entries = assetsTree.getFolders(fixedPath);
|
||||||
|
else entries = assetsTree.getFiles(fixedPath);
|
||||||
|
for (entry in entries) {
|
||||||
|
if (entry.toLowerCase() == part.toLowerCase()) {
|
||||||
|
fixedPath += entry + (it != parts.length - 1 ? "/" : "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (returnedPath.toLowerCase() == fixedPath.toLowerCase()) returnedPath = fixedPath;
|
||||||
|
#end
|
||||||
|
return returnedPath;
|
||||||
|
}
|
||||||
|
|
||||||
public static inline function video(key:String, ?ext:String)
|
public static inline function video(key:String, ?ext:String)
|
||||||
return getPath('videos/$key.${ext != null ? ext : Flags.VIDEO_EXT}');
|
return getPath('videos/$key.${ext != null ? ext : Flags.VIDEO_EXT}');
|
||||||
@@ -68,18 +89,18 @@ class Paths
|
|||||||
inline static public function music(key:String, ?library:String, ?ext:String)
|
inline static public function music(key:String, ?library:String, ?ext:String)
|
||||||
return getPath('music/$key.${ext != null ? ext : Flags.SOUND_EXT}', library);
|
return getPath('music/$key.${ext != null ? ext : Flags.SOUND_EXT}', library);
|
||||||
|
|
||||||
inline static public function voices(song:String, ?difficulty:String, ?prefix:String = "", ?ext:String) {
|
inline static public function voices(song:String, ?difficulty:String, ?suffix:String = "", ?ext:String) {
|
||||||
if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
||||||
if (ext == null) ext = Flags.SOUND_EXT;
|
if (ext == null) ext = Flags.SOUND_EXT;
|
||||||
var diff = getPath('songs/$song/song/Voices$prefix-${difficulty}.${ext}', null);
|
var diff = getPath('songs/$song/song/Voices$suffix-${difficulty}.${ext}', null);
|
||||||
return OpenFlAssets.exists(diff) ? diff : getPath('songs/$song/song/Voices$prefix.${ext}', null);
|
return OpenFlAssets.exists(diff) ? diff : getPath('songs/$song/song/Voices$suffix.${ext}', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static public function inst(song:String, ?difficulty:String, ?prefix:String = "", ?ext:String) {
|
inline static public function inst(song:String, ?difficulty:String, ?suffix:String = "", ?ext:String) {
|
||||||
if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
||||||
if (ext == null) ext = Flags.SOUND_EXT;
|
if (ext == null) ext = Flags.SOUND_EXT;
|
||||||
var diff = getPath('songs/$song/song/Inst$prefix-${difficulty}.${ext}', null);
|
var diff = getPath('songs/$song/song/Inst$suffix-${difficulty}.${ext}', null);
|
||||||
return OpenFlAssets.exists(diff) ? diff : getPath('songs/$song/song/Inst$prefix.${ext}', null);
|
return OpenFlAssets.exists(diff) ? diff : getPath('songs/$song/song/Inst$suffix.${ext}', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function image(key:String, ?library:String, checkForAtlas:Bool = false, ?ext:String) {
|
static public function image(key:String, ?library:String, checkForAtlas:Bool = false, ?ext:String) {
|
||||||
@@ -107,11 +128,11 @@ class Paths
|
|||||||
return scriptPath;
|
return scriptPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function chart(song:String, ?difficulty:String):String
|
static public function chart(song:String, ?difficulty:String, ?variant:String):String
|
||||||
{
|
{
|
||||||
difficulty = (difficulty != null ? difficulty : Flags.DEFAULT_DIFFICULTY);
|
difficulty = (difficulty != null ? difficulty : Flags.DEFAULT_DIFFICULTY);
|
||||||
|
|
||||||
return getPath('songs/$song/charts/$difficulty.json', null);
|
return getPath('songs/$song/charts/${variant != null ? variant + "/" : ""}$difficulty.json', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function character(character:String):String {
|
public static function character(character:String):String {
|
||||||
|
|||||||
@@ -71,8 +71,9 @@ class Chart {
|
|||||||
return LEGACY;
|
return LEGACY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function loadEventsJson(songName:String) {
|
public static function loadEventsJson(songName:String, ?variant:String) {
|
||||||
var path = Paths.file('songs/${songName}/events.json');
|
var variantSuffix = variant != null && variant != "" ? '-$variant' : "";
|
||||||
|
var path = Paths.file('songs/${songName}/events$variantSuffix.json');
|
||||||
var data:Array<ChartEvent> = null;
|
var data:Array<ChartEvent> = null;
|
||||||
if (Assets.exists(path)) {
|
if (Assets.exists(path)) {
|
||||||
try {
|
try {
|
||||||
@@ -83,62 +84,91 @@ class Chart {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function loadChartMeta(songName:String, ?difficulty:String, fromMods:Bool = true):ChartMetaData {
|
inline public static function defaultChartMetaFields(data:ChartMetaData):ChartMetaData {
|
||||||
if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
data.setFieldDefault("displayName", data.name);
|
||||||
|
|
||||||
var metaPath = Paths.file('songs/${songName}/meta.json');
|
data.setFieldDefault("bpm", Flags.DEFAULT_BPM);
|
||||||
var metaDiffPath = Paths.file('songs/${songName}/meta-${difficulty}.json');
|
data.setFieldDefault("beatsPerMeasure", Flags.DEFAULT_BEATS_PER_MEASURE);
|
||||||
|
data.setFieldDefault("stepsPerBeat", Flags.DEFAULT_STEPS_PER_BEAT);
|
||||||
|
data.setFieldDefault("icon", Flags.DEFAULT_HEALTH_ICON);
|
||||||
|
data.setFieldDefault("coopAllowed", Flags.DEFAULT_COOP_ALLOWED);
|
||||||
|
data.setFieldDefault("opponentModeAllowed", Flags.DEFAULT_OPPONENT_MODE_ALLOWED);
|
||||||
|
data.setFieldDefault("instSuffix", "");
|
||||||
|
data.setFieldDefault("vocalsSuffix", "");
|
||||||
|
data.setFieldDefault("needsVoices", true);
|
||||||
|
data.setFieldDefault("difficulties", []);
|
||||||
|
data.setFieldDefault("variants", []);
|
||||||
|
data.setFieldDefault("metas", []);
|
||||||
|
|
||||||
var data:ChartMetaData = null;
|
return data;
|
||||||
var fromMods:Bool = fromMods;
|
}
|
||||||
for (path in [metaDiffPath, metaPath]) if (Assets.exists(path)) {
|
|
||||||
|
public static function loadChartMeta(songName:String, ?variant:String, ?difficulty:String, fromMods:Bool = true, includeMetaVariations = true):ChartMetaData {
|
||||||
|
var folder = 'songs/$songName', isVariant = false, data:ChartMetaData = null;
|
||||||
|
var defaultPaths = [Paths.file('$folder/meta-$difficulty.json'), Paths.file('$folder/meta.json')], variantPaths = [];
|
||||||
|
if (difficulty != null) defaultPaths.unshift(Paths.file('$folder/meta-$difficulty.json'));
|
||||||
|
|
||||||
|
if (variant != null && variant != '') {
|
||||||
|
variantPaths.push(Paths.file('$folder/meta-$variant.json'));
|
||||||
|
if (difficulty != null) variantPaths.unshift(Paths.file('$folder/meta-$variant-$difficulty.json'));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (path in variantPaths.concat(defaultPaths)) if (Assets.exists(path)) {
|
||||||
fromMods = Paths.assetsTree.existsSpecific(path, "TEXT", MODS);
|
fromMods = Paths.assetsTree.existsSpecific(path, "TEXT", MODS);
|
||||||
try {
|
try {
|
||||||
var tempData = Json.parse(Assets.getText(path));
|
var tempData = Json.parse(Assets.getText(path));
|
||||||
tempData.color = CoolUtil.getColorFromDynamic(tempData.color).getDefault(Flags.DEFAULT_COLOR);
|
tempData.color = CoolUtil.getColorFromDynamic(tempData.color).getDefault(Flags.DEFAULT_COLOR);
|
||||||
data = tempData;
|
data = tempData;
|
||||||
} catch(e) Logs.trace('Failed to load song metadata for ${songName} ($path): ${Std.string(e)}', ERROR);
|
} catch(e) Logs.trace('Failed to load song metadata for $songName ($path): ${Std.string(e)}', ERROR);
|
||||||
if (data != null) break;
|
|
||||||
|
if (data != null) {
|
||||||
|
isVariant = variantPaths.contains(path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data == null) data = {
|
if (data != null) data.name = songName;
|
||||||
|
else data = {
|
||||||
name: songName,
|
name: songName,
|
||||||
bpm: 100
|
color: Flags.DEFAULT_COLOR
|
||||||
};
|
};
|
||||||
|
|
||||||
data.setFieldDefault("name", songName);
|
if (isVariant) data.variant = variant;
|
||||||
data.setFieldDefault("bpm", Flags.DEFAULT_BPM);
|
else data.variant = null;
|
||||||
data.setFieldDefault("beatsPerMeasure", Flags.DEFAULT_BEATS_PER_MEASURE);
|
|
||||||
data.setFieldDefault("stepsPerBeat", Flags.DEFAULT_STEPS_PER_BEAT);
|
defaultChartMetaFields(data);
|
||||||
data.setFieldDefault("needsVoices", true);
|
|
||||||
data.setFieldDefault("icon", Flags.DEFAULT_HEALTH_ICON);
|
|
||||||
data.setFieldDefault("difficulties", []);
|
|
||||||
data.setFieldDefault("coopAllowed", Flags.DEFAULT_COOP_ALLOWED);
|
|
||||||
data.setFieldDefault("opponentModeAllowed", Flags.DEFAULT_OPPONENT_MODE_ALLOWED);
|
|
||||||
data.setFieldDefault("displayName", data.name);
|
|
||||||
|
|
||||||
if (data.difficulties.length <= 0) {
|
if (data.difficulties.length <= 0) {
|
||||||
data.difficulties = [for(f in Paths.getFolderContent('songs/${songName}/charts/', false, fromMods ? MODS : SOURCE)) if (Path.extension(f.toUpperCase()) == "JSON") Path.withoutExtension(f)];
|
var path = 'songs/$songName/charts/';
|
||||||
var tempDiffs = [];
|
if (isVariant) path += '$variant/';
|
||||||
|
|
||||||
|
data.difficulties = [for(f in Paths.getFolderContent(path, false, fromMods ? MODS : SOURCE)) if (Path.extension(f.toUpperCase()) == "JSON") Path.withoutExtension(f)];
|
||||||
if (data.difficulties.length == 3) {
|
if (data.difficulties.length == 3) {
|
||||||
for(d in data.difficulties) {
|
var tempDiffs = [];
|
||||||
switch(d.toLowerCase()) {
|
for (d in data.difficulties) switch(d.toLowerCase()) {
|
||||||
case "easy": tempDiffs.insert(0, d);
|
case "easy": tempDiffs.insert(0, d);
|
||||||
case "normal": tempDiffs.insert(1, d);
|
case "normal": tempDiffs.insert(1, d);
|
||||||
case "hard": tempDiffs.insert(2, d);
|
case "hard": tempDiffs.insert(2, d);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
data.difficulties = tempDiffs;
|
if (tempDiffs.length == 3) data.difficulties = tempDiffs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.metas = [];
|
||||||
|
if (includeMetaVariations && data.variants.length > 0) for (variant in data.variants) {
|
||||||
|
if (!data.metas.exists(variant) && Assets.exists(Paths.file('songs/$songName/meta-$variant.json'))) {
|
||||||
|
var meta = loadChartMeta(songName, variant, fromMods);
|
||||||
|
if (meta.variant != null) data.metas.set(variant, meta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function parse(songName:String, ?difficulty:String):ChartData {
|
public static function parse(songName:String, ?difficulty:String, ?variant:String):ChartData {
|
||||||
if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
||||||
|
|
||||||
var chartPath = Paths.chart(songName, difficulty);
|
var chartPath = Paths.chart(songName, difficulty, variant);
|
||||||
var base:ChartData = {
|
var base:ChartData = {
|
||||||
strumLines: [],
|
strumLines: [],
|
||||||
noteTypes: [],
|
noteTypes: [],
|
||||||
@@ -152,15 +182,15 @@ class Chart {
|
|||||||
fromMods: Paths.assetsTree.existsSpecific(chartPath, "TEXT", MODS)
|
fromMods: Paths.assetsTree.existsSpecific(chartPath, "TEXT", MODS)
|
||||||
};
|
};
|
||||||
|
|
||||||
var valid:Bool = true;
|
var valid:Bool = true, namePrint = '$songName $difficulty' + ((variant != null && variant != '') ? ' ($variant)' : '');
|
||||||
if (!Assets.exists(chartPath)) {
|
if (!Assets.exists(chartPath)) {
|
||||||
Logs.error('Chart for song ${songName} ($difficulty) at "$chartPath" was not found.');
|
Logs.error('Chart for song $namePrint at "$chartPath" was not found.');
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
var data:Dynamic = null;
|
var data:Dynamic = null;
|
||||||
if (valid) {
|
if (valid) {
|
||||||
try data = Json.parse(Assets.getText(chartPath))
|
try data = Json.parse(Assets.getText(chartPath))
|
||||||
catch(e) Logs.trace('Could not parse chart for song ${songName} ($difficulty): ${Std.string(e)}', ERROR, RED);
|
catch(e) Logs.trace('Could not parse chart for song $namePrint: ${Std.string(e)}', ERROR, RED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -192,13 +222,12 @@ class Chart {
|
|||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
|
|
||||||
var loadedMeta = loadChartMeta(songName, difficulty, base.fromMods);
|
var loadedMeta = loadChartMeta(songName, variant, base.fromMods, false);
|
||||||
if (base.meta == null) base.meta = loadedMeta;
|
if (base.meta == null) base.meta = loadedMeta;
|
||||||
else {
|
else {
|
||||||
for (field in Reflect.fields(base.meta)) {
|
for (field in Reflect.fields(base.meta)) {
|
||||||
var f = Reflect.field(base.meta, field);
|
var f = Reflect.field(base.meta, field);
|
||||||
if (f != null)
|
if (f != null) Reflect.setField(loadedMeta, field, f);
|
||||||
Reflect.setField(loadedMeta, field, f);
|
|
||||||
}
|
}
|
||||||
base.meta = loadedMeta;
|
base.meta = loadedMeta;
|
||||||
}
|
}
|
||||||
@@ -207,9 +236,8 @@ class Chart {
|
|||||||
* events.json LOADING
|
* events.json LOADING
|
||||||
*/
|
*/
|
||||||
#if REGION
|
#if REGION
|
||||||
var extraEvents:Array<ChartEvent> = loadEventsJson(songName);
|
var extraEvents:Array<ChartEvent> = loadEventsJson(songName, variant);
|
||||||
if (extraEvents != null)
|
if (extraEvents != null) base.events = base.events.concat(extraEvents);
|
||||||
base.events = base.events.concat(extraEvents);
|
|
||||||
#end
|
#end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -237,61 +265,59 @@ class Chart {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the chart to the specific song folder path.
|
* Saves the chart to the specific song folder path.
|
||||||
* @param songFolderPath Path to the song folder (ex: `mods/your mod/songs/song/`)
|
* @param chart Chart to save.
|
||||||
* @param chart Chart to save
|
* @param difficulty Name of the difficulty (Optional).
|
||||||
* @param difficulty Name of the difficulty
|
* @param variant Name of the Variant (Optional).
|
||||||
* @param saveSettings
|
* @param saveSettings (Optional).
|
||||||
* @return Filtered chart used for saving.
|
* @return Filtered chart used for saving.
|
||||||
*/
|
*/
|
||||||
public static function save(songFolderPath:String, chart:ChartData, ?difficulty:String, ?saveSettings:ChartSaveSettings):ChartData {
|
public static function save(chart:ChartData, ?difficulty:String, ?variant:String, ?saveSettings:ChartSaveSettings):ChartData {
|
||||||
if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
||||||
if (saveSettings == null) saveSettings = {};
|
if (saveSettings == null) saveSettings = {};
|
||||||
|
|
||||||
if (saveSettings.saveMetaInChart == null) saveSettings.saveMetaInChart = true;
|
var filteredChart = filterChartForSaving(chart, saveSettings.saveMetaInChart, saveSettings.saveLocalEvents, saveSettings.saveGlobalEvents && saveSettings.seperateGlobalEvents != true);
|
||||||
if (saveSettings.saveLocalEvents == null) saveSettings.saveLocalEvents = true;
|
|
||||||
if (saveSettings.saveGlobalEvents == null) saveSettings.saveGlobalEvents = false;
|
|
||||||
|
|
||||||
var filteredChart = filterChartForSaving(chart, saveSettings.saveMetaInChart, saveSettings.saveLocalEvents, saveSettings.saveGlobalEvents);
|
|
||||||
var meta = filteredChart.meta;
|
|
||||||
|
|
||||||
#if sys
|
#if sys
|
||||||
var saveFolder:String = saveSettings.folder == null ? "charts" : saveSettings.folder;
|
var songPath = saveSettings.songFolder == null ? 'songs/${chart.meta.name}' : saveSettings.songFolder, variantSuffix = variant != null && variant != "" ? '-$variant' : "";
|
||||||
|
var metaPath = 'meta$variantSuffix.json', prettyPrint = saveSettings.prettyPrint == true ? Flags.JSON_PRETTY_PRINT : null, temp:String;
|
||||||
|
if ((temp = Paths.assetsTree.getPath('assets/$songPath/$metaPath')) != null) {
|
||||||
|
songPath = temp.substr(0, temp.length - metaPath.length - 1);
|
||||||
|
metaPath = temp;
|
||||||
|
}
|
||||||
|
else if (saveSettings.songFolder == null)
|
||||||
|
metaPath = (songPath = '${Paths.getAssetsRoot()}/$songPath') + '/$metaPath';
|
||||||
|
|
||||||
if (!FileSystem.exists('${songFolderPath}/$saveFolder/'))
|
var chartFolder = saveSettings.folder == null ? ((variant == null || variant == '') ? 'charts' : 'charts/$variant') : saveSettings.folder;
|
||||||
FileSystem.createDirectory('${songFolderPath}/$saveFolder/');
|
var chartPath = '$songPath/$chartFolder/${difficulty.trim()}.json';
|
||||||
|
|
||||||
var chartPath = '${songFolderPath}/$saveFolder/${difficulty.trim()}.json';
|
if (saveSettings.saveChart == null || saveSettings.saveChart == true)
|
||||||
var metaPath = '${songFolderPath}/meta.json';
|
CoolUtil.safeSaveFile(chartPath, Json.stringify(filteredChart, null, prettyPrint));
|
||||||
|
|
||||||
CoolUtil.safeSaveFile(chartPath, Json.stringify(filteredChart, null, saveSettings.prettyPrint == true ? Flags.JSON_PRETTY_PRINT : null));
|
if (saveSettings.overrideExistingMeta || !FileSystem.exists(metaPath))
|
||||||
|
CoolUtil.safeSaveFile(metaPath, Json.stringify(filterMetaForSaving(chart.meta), null, prettyPrint));
|
||||||
|
|
||||||
if (saveSettings.overrideExistingMeta == true || !FileSystem.exists(metaPath))
|
if (saveSettings.seperateGlobalEvents == true) {
|
||||||
CoolUtil.safeSaveFile(metaPath, makeMetaSaveable(meta));
|
var eventsPath = '$songPath/events$variantSuffix.json', events = filterEventsForSaving(chart.events, false, true);
|
||||||
|
|
||||||
|
if (events.length != 0) CoolUtil.safeSaveFile(eventsPath, Json.stringify({events: events}, null, prettyPrint));
|
||||||
|
}
|
||||||
#end
|
#end
|
||||||
|
|
||||||
return filteredChart;
|
return filteredChart;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function filterChartForSaving(chart:ChartData, ?saveMetaInChart:Bool, ?saveLocalEvents:Bool, ?saveGlobalEvents:Bool):ChartData {
|
public static function filterChartForSaving(chart:ChartData, saveMetaInChart = true, ?saveLocalEvents:Bool, ?saveGlobalEvents:Bool):ChartData {
|
||||||
|
var meta = chart.meta, events = chart.events;
|
||||||
|
chart.meta = null;
|
||||||
|
chart.events = null;
|
||||||
|
|
||||||
var data = Reflect.copy(chart); // make a copy of the chart to leave the OG intact
|
var data = Reflect.copy(chart); // make a copy of the chart to leave the OG intact
|
||||||
if (saveMetaInChart != true) {
|
|
||||||
data.meta = null;
|
|
||||||
} else {
|
|
||||||
data.meta = Reflect.copy(chart.meta); // also make a copy of the metadata to leave the OG intact.
|
|
||||||
if (data.meta != null && Reflect.hasField(data.meta, "parsedColor")) Reflect.deleteField(data.meta, "parsedColor");
|
|
||||||
}
|
|
||||||
|
|
||||||
// in this part abt the events, i gotta account that these booleans can be null - Nex
|
chart.meta = meta;
|
||||||
if (saveLocalEvents != true && saveGlobalEvents != true) data.events = null;
|
chart.events = events;
|
||||||
else {
|
|
||||||
data.events = [];
|
|
||||||
for (event in chart.events) if ((saveLocalEvents == true && event.global != true) || (saveGlobalEvents == true && event.global == true)) {
|
|
||||||
var copy = Reflect.copy(event);
|
|
||||||
if (saveLocalEvents == true ? event.global != true : event.global == true) Reflect.deleteField(copy, "global"); // should NOT delete the field when saving with the local events and the event should have been global - Nex
|
|
||||||
data.events.push(copy);
|
|
||||||
}
|
|
||||||
if (data.events.length == 0) data.events = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
data.meta = saveMetaInChart ? filterMetaForSaving(meta) : null;
|
||||||
|
data.events = filterEventsForSaving(events, saveLocalEvents, saveGlobalEvents);
|
||||||
data.fromMods = null;
|
data.fromMods = null;
|
||||||
|
|
||||||
var sortedData:Dynamic = {};
|
var sortedData:Dynamic = {};
|
||||||
@@ -303,18 +329,47 @@ class Chart {
|
|||||||
return sortedData;
|
return sortedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static inline function makeMetaSaveable(meta:ChartMetaData, prettyPrint:Bool = true):String {
|
public static function filterEventsForSaving(events:Array<ChartEvent>, saveLocalEvents = true, saveGlobalEvents = false):Array<ChartEvent> {
|
||||||
|
var data = [];
|
||||||
|
if (!saveLocalEvents && !saveGlobalEvents) return data;
|
||||||
|
|
||||||
|
for (event in events) if ((saveLocalEvents && event.global != true) || (saveGlobalEvents && event.global == true)) {
|
||||||
|
var copy = Reflect.copy(event);
|
||||||
|
if (saveLocalEvents ? event.global != true : event.global == true) Reflect.deleteField(copy, "global"); // should NOT delete the field when saving with the local events and the event should have been global - Nex
|
||||||
|
data.push(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static inline function makeMetaSaveable(meta:ChartMetaData, prettyPrint:Bool = true):String
|
||||||
|
return Json.stringify(filterMetaForSaving(meta), null, prettyPrint ? Flags.JSON_PRETTY_PRINT : null);
|
||||||
|
|
||||||
|
public static inline function filterMetaForSaving(meta:ChartMetaData):ChartMetaData {
|
||||||
var data:Dynamic = Reflect.copy(meta);
|
var data:Dynamic = Reflect.copy(meta);
|
||||||
if (data.color != null) data.color = new FlxColor(data.color).toWebString(); // dont even ask me - Nex
|
if (data.color != null) data.color = FlxColor.fromInt(data.color).toWebString(); // dont even ask me - Nex
|
||||||
return Json.stringify(data, null, prettyPrint ? Flags.JSON_PRETTY_PRINT : null);
|
Reflect.deleteField(data, "name");
|
||||||
|
Reflect.deleteField(data, 'parsedColor');
|
||||||
|
Reflect.deleteField(data, 'metas');
|
||||||
|
Reflect.deleteField(data, "variant");
|
||||||
|
if (data.instSuffix != null && data.instSuffix == "") Reflect.deleteField(data, "instSuffix");
|
||||||
|
if (data.vocalsSuffix != null && data.vocalsSuffix == "") Reflect.deleteField(data, "vocalsSuffix");
|
||||||
|
if (data.variants != null && data.variants.length == 0) Reflect.deleteField(data, "variants");
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef ChartSaveSettings = {
|
typedef ChartSaveSettings = {
|
||||||
var ?overrideExistingMeta:Bool;
|
var ?prettyPrint:Bool;
|
||||||
|
|
||||||
var ?saveMetaInChart:Bool;
|
var ?saveMetaInChart:Bool;
|
||||||
var ?saveLocalEvents:Bool;
|
var ?saveLocalEvents:Bool;
|
||||||
var ?saveGlobalEvents:Bool;
|
var ?saveGlobalEvents:Bool;
|
||||||
var ?prettyPrint:Bool;
|
|
||||||
|
var ?saveChart:Bool;
|
||||||
|
var ?overrideExistingMeta:Bool;
|
||||||
|
var ?seperateGlobalEvents:Bool;
|
||||||
|
|
||||||
var ?folder:String;
|
var ?folder:String;
|
||||||
|
var ?songFolder:String;
|
||||||
}
|
}
|
||||||
@@ -18,16 +18,26 @@ typedef ChartData = {
|
|||||||
|
|
||||||
typedef ChartMetaData = {
|
typedef ChartMetaData = {
|
||||||
public var name:String;
|
public var name:String;
|
||||||
public var ?bpm:Float;
|
public var ?variant:String;
|
||||||
public var ?displayName:String;
|
public var ?displayName:String;
|
||||||
|
|
||||||
|
public var ?bpm:Float;
|
||||||
public var ?beatsPerMeasure:Float;
|
public var ?beatsPerMeasure:Float;
|
||||||
public var ?stepsPerBeat:Int;
|
public var ?stepsPerBeat:Int;
|
||||||
|
|
||||||
|
public var ?difficulties:Array<String>;
|
||||||
|
public var ?variants:Array<String>;
|
||||||
|
public var ?customValues:Dynamic;
|
||||||
|
|
||||||
public var ?icon:String;
|
public var ?icon:String;
|
||||||
public var ?color:FlxColor;
|
public var ?color:FlxColor;
|
||||||
public var ?difficulties:Array<String>;
|
|
||||||
public var ?coopAllowed:Bool;
|
public var ?coopAllowed:Bool;
|
||||||
public var ?opponentModeAllowed:Bool;
|
public var ?opponentModeAllowed:Bool;
|
||||||
public var ?customValues:Dynamic;
|
|
||||||
|
public var ?metas:Map<String, ChartMetaData>;
|
||||||
|
public var ?instSuffix:String;
|
||||||
|
public var ?vocalsSuffix:String;
|
||||||
public var ?needsVoices:Bool;
|
public var ?needsVoices:Bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import openfl.Assets;
|
|||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
class EventsData {
|
class EventsData {
|
||||||
public static var defaultEventsList:Array<String> = ["HScript Call", "Camera Movement", "Camera Position", "Add Camera Zoom", "Camera Zoom", "Camera Modulo Change", "Camera Flash", "BPM Change", "Continuous BPM Change", "Time Signature Change", "Scroll Speed Change", "Alt Animation Toggle", "Play Animation"];
|
public static var defaultEventsList:Array<String> = ["HScript Call", "Camera Movement", "Camera Position", "Add Camera Zoom", "Camera Bop", "Camera Zoom", "Camera Modulo Change", "Camera Flash", "BPM Change", "Continuous BPM Change", "Time Signature Change", "Scroll Speed Change", "Alt Animation Toggle", "Play Animation"];
|
||||||
public static var defaultEventsParams:Map<String, Array<EventParamInfo>> = [
|
public static var defaultEventsParams:Map<String, Array<EventParamInfo>> = [
|
||||||
"HScript Call" => [
|
"HScript Call" => [
|
||||||
{name: "Function Name", type: TString, defValue: "myFunc"},
|
{name: "Function Name", type: TString, defValue: "myFunc"},
|
||||||
@@ -56,6 +56,9 @@ class EventsData {
|
|||||||
{name: "Amount", type: TFloat(-10, 10, 0.01, 2), defValue: 0.05},
|
{name: "Amount", type: TFloat(-10, 10, 0.01, 2), defValue: 0.05},
|
||||||
{name: "Camera", type: TDropDown(['camGame', 'camHUD']), defValue: "camGame"}
|
{name: "Camera", type: TDropDown(['camGame', 'camHUD']), defValue: "camGame"}
|
||||||
],
|
],
|
||||||
|
"Camera Bop" => [
|
||||||
|
{name: "Amount", type: TFloat(-10, 10, 0.1, 2), defValue: 0.1}
|
||||||
|
],
|
||||||
"Camera Zoom" => [
|
"Camera Zoom" => [
|
||||||
{name: "Tween Zoom?", type: TBool, defValue: true},
|
{name: "Tween Zoom?", type: TBool, defValue: true},
|
||||||
{name: "New Zoom", type: TFloat(-10, 10, 0.01, 2), defValue: 1},
|
{name: "New Zoom", type: TFloat(-10, 10, 0.01, 2), defValue: 1},
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ class VSliceParser {
|
|||||||
stage: Flags.DEFAULT_STAGE,
|
stage: Flags.DEFAULT_STAGE,
|
||||||
codenameChart: true
|
codenameChart: true
|
||||||
};
|
};
|
||||||
parseChart(Reflect.field(chartData.notes, diff), metaData, chartData.events, base);
|
parseChart(Reflect.field(chartData.notes, diff), metaData, chartData.events, base, resultMeta);
|
||||||
resultCharts.push({diffName: diff, chart: base});
|
resultCharts.push({diffName: diff, chart: base});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function parseChart(data:Dynamic, metaData:Dynamic, events:Dynamic, result:ChartData) {
|
public static function parseChart(data:Dynamic, metaData:Dynamic, events:Dynamic, result:ChartData, resultMeta:ChartMetaData) {
|
||||||
// vslice chart parsing
|
// vslice chart parsing
|
||||||
var data:Array<SwagNote> = data;
|
var data:Array<SwagNote> = data;
|
||||||
var metadata:SwagMetadata = metaData;
|
var metadata:SwagMetadata = metaData;
|
||||||
@@ -45,14 +45,14 @@ class VSliceParser {
|
|||||||
type: 0,
|
type: 0,
|
||||||
position: (p2isGF = metadata.playData.characters.opponent.startsWith("gf")) ? "girlfriend" : "dad",
|
position: (p2isGF = metadata.playData.characters.opponent.startsWith("gf")) ? "girlfriend" : "dad",
|
||||||
notes: [],
|
notes: [],
|
||||||
vocalsSuffix: "-Opponent"
|
vocalsSuffix: '-${metadata.playData.characters.opponent}${resultMeta.vocalsSuffix != null ? resultMeta.vocalsSuffix : ""}'
|
||||||
});
|
});
|
||||||
result.strumLines.push({
|
result.strumLines.push({
|
||||||
characters: [metadata.playData.characters.player],
|
characters: [metadata.playData.characters.player],
|
||||||
type: 1,
|
type: 1,
|
||||||
position: "boyfriend",
|
position: "boyfriend",
|
||||||
notes: [],
|
notes: [],
|
||||||
vocalsSuffix: "-Player"
|
vocalsSuffix: '-${metadata.playData.characters.player}${resultMeta.vocalsSuffix != null ? resultMeta.vocalsSuffix : ""}'
|
||||||
});
|
});
|
||||||
var gfName = metadata.playData.characters.girlfriend;
|
var gfName = metadata.playData.characters.girlfriend;
|
||||||
if (!p2isGF && gfName != "none") {
|
if (!p2isGF && gfName != "none") {
|
||||||
@@ -67,7 +67,7 @@ class VSliceParser {
|
|||||||
|
|
||||||
var timeChanges = metadata.timeChanges;
|
var timeChanges = metadata.timeChanges;
|
||||||
result.meta.bpm = timeChanges[0].bpm;
|
result.meta.bpm = timeChanges[0].bpm;
|
||||||
result.meta.needsVoices = true;
|
result.meta.needsVoices = false;
|
||||||
|
|
||||||
for (note in data)
|
for (note in data)
|
||||||
{
|
{
|
||||||
@@ -108,7 +108,7 @@ class VSliceParser {
|
|||||||
{
|
{
|
||||||
case "FocusCamera":
|
case "FocusCamera":
|
||||||
var isPosOnly = false;
|
var isPosOnly = false;
|
||||||
var arr:Array<Dynamic> = [switch(values.char) {
|
var arr:Array<Dynamic> = [switch(values is Int ? values : values.char) {
|
||||||
// more cases here in the future if they add em? (i hope not) - Nex
|
// more cases here in the future if they add em? (i hope not) - Nex
|
||||||
case 0: 1;
|
case 0: 1;
|
||||||
case 1: 0;
|
case 1: 0;
|
||||||
@@ -177,16 +177,12 @@ class VSliceParser {
|
|||||||
var songID:String = songID == null ? songName.toLowerCase().replace(" ", "-") : songID;
|
var songID:String = songID == null ? songName.toLowerCase().replace(" ", "-") : songID;
|
||||||
var firstTimeChange:SwagTimeChange = data.timeChanges[0];
|
var firstTimeChange:SwagTimeChange = data.timeChanges[0];
|
||||||
|
|
||||||
result.name = songID;
|
|
||||||
result.bpm = firstTimeChange.bpm.getDefault(Flags.DEFAULT_BPM);
|
result.bpm = firstTimeChange.bpm.getDefault(Flags.DEFAULT_BPM);
|
||||||
result.beatsPerMeasure = firstTimeChange.n.getDefault(Flags.DEFAULT_BEATS_PER_MEASURE);
|
result.beatsPerMeasure = firstTimeChange.n.getDefault(Flags.DEFAULT_BEATS_PER_MEASURE);
|
||||||
result.stepsPerBeat = firstTimeChange.d.getDefault(Flags.DEFAULT_STEPS_PER_BEAT);
|
result.stepsPerBeat = firstTimeChange.d.getDefault(Flags.DEFAULT_STEPS_PER_BEAT);
|
||||||
result.displayName = songName;
|
result.displayName = songName;
|
||||||
result.icon = Flags.DEFAULT_HEALTH_ICON;
|
result.difficulties = data.playData.difficulties.copy();
|
||||||
result.color = 0xFFFFFF;
|
if (data.playData.songVariations != null) result.variants = data.playData.songVariations.copy();
|
||||||
result.opponentModeAllowed = true;
|
|
||||||
result.coopAllowed = true;
|
|
||||||
result.difficulties = data.playData.difficulties.concat(data.playData.songVariations.getDefault([]));
|
|
||||||
|
|
||||||
if (result.customValues == null) result.customValues = {};
|
if (result.customValues == null) result.customValues = {};
|
||||||
result.customValues.artist = data.artist;
|
result.customValues.artist = data.artist;
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ final class FreeplaySongSelectEvent extends CancellableEvent {
|
|||||||
* Difficulty name
|
* Difficulty name
|
||||||
*/
|
*/
|
||||||
public var difficulty:String;
|
public var difficulty:String;
|
||||||
|
/**
|
||||||
|
* Variation Name
|
||||||
|
*/
|
||||||
|
public var variant:String;
|
||||||
/**
|
/**
|
||||||
* Whenever opponent mode is enabled or not.
|
* Whenever opponent mode is enabled or not.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import flixel.FlxState;
|
|||||||
import flixel.util.FlxSignal.FlxTypedSignal;
|
import flixel.util.FlxSignal.FlxTypedSignal;
|
||||||
import funkin.backend.chart.ChartData;
|
import funkin.backend.chart.ChartData;
|
||||||
import funkin.backend.system.interfaces.IBeatReceiver;
|
import funkin.backend.system.interfaces.IBeatReceiver;
|
||||||
|
import funkin.backend.system.interfaces.IBeatCancellableReceiver;
|
||||||
import funkin.editors.charter.Charter;
|
import funkin.editors.charter.Charter;
|
||||||
|
|
||||||
enum BeatType {
|
enum BeatType {
|
||||||
@@ -371,8 +372,14 @@ final class Conductor
|
|||||||
private static var __updateMeasure:Bool;
|
private static var __updateMeasure:Bool;
|
||||||
|
|
||||||
private static function update() {
|
private static function update() {
|
||||||
if (FlxG.state != null && FlxG.state is MusicBeatState && cast(FlxG.state, MusicBeatState).cancelConductorUpdate) return;
|
if (FlxG.state == null) return;
|
||||||
|
else {
|
||||||
|
var state = FlxG.state;
|
||||||
|
while (state != null) {
|
||||||
|
if (state is IBeatCancellableReceiver && cast(FlxG.state, IBeatCancellableReceiver).cancelConductorUpdate) return;
|
||||||
|
state = state.subState;
|
||||||
|
}
|
||||||
|
}
|
||||||
__updateSongPos(FlxG.elapsed);
|
__updateSongPos(FlxG.elapsed);
|
||||||
|
|
||||||
var oldStep = curStep, oldBeat = curBeat, oldMeasure = curMeasure, oldChangeIndex = curChangeIndex;
|
var oldStep = curStep, oldBeat = curBeat, oldMeasure = curMeasure, oldChangeIndex = curChangeIndex;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ enum Control
|
|||||||
ACCEPT;
|
ACCEPT;
|
||||||
BACK;
|
BACK;
|
||||||
PAUSE;
|
PAUSE;
|
||||||
|
CHANGE_MODE;
|
||||||
//CHEAT;
|
//CHEAT;
|
||||||
SWITCHMOD;
|
SWITCHMOD;
|
||||||
|
|
||||||
@@ -145,6 +146,11 @@ class Controls extends FlxActionSet
|
|||||||
@:pressed("reset") public var RESET_HOLD(get, set): Bool;
|
@:pressed("reset") public var RESET_HOLD(get, set): Bool;
|
||||||
@:justReleased("reset") public var RESET_R(get, set): Bool;
|
@:justReleased("reset") public var RESET_R(get, set): Bool;
|
||||||
|
|
||||||
|
@:gamepad([FlxGamepadInputID.BACK]) // select button
|
||||||
|
@:justPressed("change-mode") public var CHANGE_MODE(get, set): Bool;
|
||||||
|
@:pressed("change-mode") public var CHANGE_MODE_HOLD(get, set): Bool;
|
||||||
|
@:justReleased("change-mode") public var CHANGE_MODE_R(get, set): Bool;
|
||||||
|
|
||||||
//@:gamepad([])
|
//@:gamepad([])
|
||||||
//@:justPressed("cheat") public var CHEAT(get, set): Bool;
|
//@:justPressed("cheat") public var CHEAT(get, set): Bool;
|
||||||
//@:pressed("cheat") public var CHEAT_HOLD(get, set): Bool;
|
//@:pressed("cheat") public var CHEAT_HOLD(get, set): Bool;
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ class Flags {
|
|||||||
public static var MOD_DOWNLOAD_LINK:String = "";
|
public static var MOD_DOWNLOAD_LINK:String = "";
|
||||||
public static var MOD_DEPENDENCIES:Array<String> = [];
|
public static var MOD_DEPENDENCIES:Array<String> = [];
|
||||||
|
|
||||||
@:noCompletion public static var MOD_ICON64:String = "";
|
|
||||||
@:noCompletion public static var MOD_ICON32:String = "";
|
@:noCompletion public static var MOD_ICON32:String = "";
|
||||||
|
@:noCompletion public static var MOD_ICON24:String = "";
|
||||||
@:noCompletion public static var MOD_ICON16:String = "";
|
@:noCompletion public static var MOD_ICON16:String = "";
|
||||||
public static var MOD_ICON:String = "";
|
public static var MOD_ICON:String = "";
|
||||||
|
|
||||||
@@ -46,6 +46,7 @@ class Flags {
|
|||||||
public static var COMMIT_HASH:String = GitCommitMacro.commitHash;
|
public static var COMMIT_HASH:String = GitCommitMacro.commitHash;
|
||||||
public static var COMMIT_MESSAGE:String = 'Commit $COMMIT_NUMBER ($COMMIT_HASH)';
|
public static var COMMIT_MESSAGE:String = 'Commit $COMMIT_NUMBER ($COMMIT_HASH)';
|
||||||
|
|
||||||
|
@:bypass public static var WINDOW_TITLE_USE_MOD_NAME:Bool = false;
|
||||||
@:lazy public static var TITLE:String = Application.current.meta.get('name');
|
@:lazy public static var TITLE:String = Application.current.meta.get('name');
|
||||||
@:lazy public static var VERSION:String = Application.current.meta.get('version');
|
@:lazy public static var VERSION:String = Application.current.meta.get('version');
|
||||||
|
|
||||||
@@ -126,6 +127,9 @@ class Flags {
|
|||||||
|
|
||||||
public static var DEFAULT_NOTE_MS_LIMIT:Float = 1500;
|
public static var DEFAULT_NOTE_MS_LIMIT:Float = 1500;
|
||||||
public static var DEFAULT_NOTE_SCALE:Float = 0.7;
|
public static var DEFAULT_NOTE_SCALE:Float = 0.7;
|
||||||
|
#if MODCHARTING_FEATURES
|
||||||
|
public static var DEFAULT_MODCHART_HOLD_SUBDIVISIONS:Int = 4;
|
||||||
|
#end
|
||||||
|
|
||||||
@:also(funkin.game.Character.FALLBACK_DEAD_CHARACTER)
|
@:also(funkin.game.Character.FALLBACK_DEAD_CHARACTER)
|
||||||
public static var DEFAULT_GAMEOVER_CHARACTER:String = "bf-dead";
|
public static var DEFAULT_GAMEOVER_CHARACTER:String = "bf-dead";
|
||||||
@@ -136,7 +140,14 @@ class Flags {
|
|||||||
public static var DEFAULT_CAM_ZOOM_STRENGTH:Int = 1;
|
public static var DEFAULT_CAM_ZOOM_STRENGTH:Int = 1;
|
||||||
public static var DEFAULT_CAM_ZOOM:Float = 1.05; // what zoom level it defaults to
|
public static var DEFAULT_CAM_ZOOM:Float = 1.05; // what zoom level it defaults to
|
||||||
public static var DEFAULT_HUD_ZOOM:Float = 1.0;
|
public static var DEFAULT_HUD_ZOOM:Float = 1.0;
|
||||||
public static var MAX_CAMERA_ZOOM_MULT:Float = 1.35;
|
public static var DEFAULT_ZOOM:Float = 1.0;
|
||||||
|
public static var DEFAULT_ZOOM_LERP:Float = 0.05;
|
||||||
|
public static var MAX_CAMERA_ZOOM_MULT:Float = 10;
|
||||||
|
public static var USE_CAM_ZOOM_MULT:Bool = true;
|
||||||
|
public static var DEFAULT_CAM_ZOOM_MULT:Float = 0.015;
|
||||||
|
public static var DEFAULT_HUD_ZOOM_MULT:Float = 0.03;
|
||||||
|
public static var DEFAULT_CAM_ZOOM_LERP:Float = 0.05;
|
||||||
|
public static var DEFAULT_HUD_ZOOM_LERP:Float = 0.05;
|
||||||
|
|
||||||
// to translate these you need to convert them into ids
|
// to translate these you need to convert them into ids
|
||||||
// Resume -> pause.resume
|
// Resume -> pause.resume
|
||||||
@@ -164,11 +175,6 @@ class Flags {
|
|||||||
public static var DEFAULT_INTRO_LENGTH:Int = 5;
|
public static var DEFAULT_INTRO_LENGTH:Int = 5;
|
||||||
public static var DEFAULT_INTRO_SPRITES:Array<String> = [null, 'game/ready', 'game/set', 'game/go'];
|
public static var DEFAULT_INTRO_SPRITES:Array<String> = [null, 'game/ready', 'game/set', 'game/go'];
|
||||||
|
|
||||||
public static var CAM_BOP_STRENGTH:Float = 0.015;
|
|
||||||
public static var HUD_BOP_STRENGTH:Float = 0.03;
|
|
||||||
public static var DEFAULT_CAM_ZOOM_LERP:Float = 0.05;
|
|
||||||
public static var DEFAULT_HUD_ZOOM_LERP:Float = 0.05;
|
|
||||||
|
|
||||||
public static var MAX_SPLASHES:Int = 8;
|
public static var MAX_SPLASHES:Int = 8;
|
||||||
public static var STUNNED_TIME:Float = 5 / 60;
|
public static var STUNNED_TIME:Float = 5 / 60;
|
||||||
|
|
||||||
@@ -193,6 +199,7 @@ class Flags {
|
|||||||
public static var DISABLE_WARNING_SCREEN:Bool = true;
|
public static var DISABLE_WARNING_SCREEN:Bool = true;
|
||||||
public static var DISABLE_TRANSITIONS:Bool = false;
|
public static var DISABLE_TRANSITIONS:Bool = false;
|
||||||
public static var DISABLE_LANGUAGES:Bool = false;
|
public static var DISABLE_LANGUAGES:Bool = false;
|
||||||
|
public static var DISABLE_AUTOUPDATER:Bool = false;
|
||||||
|
|
||||||
@:also(funkin.backend.MusicBeatTransition.script)
|
@:also(funkin.backend.MusicBeatTransition.script)
|
||||||
public static var DEFAULT_TRANSITION_SCRIPT:String = "";
|
public static var DEFAULT_TRANSITION_SCRIPT:String = "";
|
||||||
@@ -265,6 +272,8 @@ class Flags {
|
|||||||
@:bypass public static var customFlags:Map<String, String> = [];
|
@:bypass public static var customFlags:Map<String, String> = [];
|
||||||
|
|
||||||
public static function loadFromData(flags:Map<String, String>, data:String) {
|
public static function loadFromData(flags:Map<String, String>, data:String) {
|
||||||
|
WINDOW_TITLE_USE_MOD_NAME = false;
|
||||||
|
|
||||||
if (!(data.length > 0)) return;
|
if (!(data.length > 0)) return;
|
||||||
var res = IniUtil.parseString(data);
|
var res = IniUtil.parseString(data);
|
||||||
|
|
||||||
@@ -281,6 +290,11 @@ class Flags {
|
|||||||
else trace('Invalid section $name');
|
else trace('Invalid section $name');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!flags.exists("WINDOW_TITLE_USE_MOD_NAME")) WINDOW_TITLE_USE_MOD_NAME = !flags.exists('TITLE') && flags.exists('MOD_NAME');
|
||||||
|
else WINDOW_TITLE_USE_MOD_NAME = parseBool(flags.get("WINDOW_TITLE_USE_MOD_NAME"));
|
||||||
|
|
||||||
|
flags.remove("WINDOW_TITLE_USE_MOD_NAME");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function loadFromDatas(datas:Array<String>) {
|
public static function loadFromDatas(datas:Array<String>) {
|
||||||
@@ -296,6 +310,8 @@ class Flags {
|
|||||||
for(name=>value in flags)
|
for(name=>value in flags)
|
||||||
if(!parse(name, value))
|
if(!parse(name, value))
|
||||||
customFlags.set(name, value);
|
customFlags.set(name, value);
|
||||||
|
|
||||||
|
Options.modchartingHoldSubdivisions = DEFAULT_MODCHART_HOLD_SUBDIVISIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -112,7 +112,8 @@ class MainState extends FlxState {
|
|||||||
TranslationUtil.setLanguage(Flags.DISABLE_LANGUAGES ? Flags.DEFAULT_LANGUAGE : null);
|
TranslationUtil.setLanguage(Flags.DISABLE_LANGUAGES ? Flags.DEFAULT_LANGUAGE : null);
|
||||||
ModsFolder.onModSwitch.dispatch(ModsFolder.currentModFolder); // Loads global.hx
|
ModsFolder.onModSwitch.dispatch(ModsFolder.currentModFolder); // Loads global.hx
|
||||||
MusicBeatTransition.script = Flags.DEFAULT_TRANSITION_SCRIPT;
|
MusicBeatTransition.script = Flags.DEFAULT_TRANSITION_SCRIPT;
|
||||||
WindowUtils.resetTitle();
|
WindowUtils.resetAffixes(false);
|
||||||
|
WindowUtils.setWindow();
|
||||||
Main.refreshAssets();
|
Main.refreshAssets();
|
||||||
DiscordUtil.init();
|
DiscordUtil.init();
|
||||||
EventsData.reloadEvents();
|
EventsData.reloadEvents();
|
||||||
@@ -126,6 +127,8 @@ class MainState extends FlxState {
|
|||||||
CoolUtil.safeAddAttributes('./.temp/', NativeAPI.FileAttribute.HIDDEN);
|
CoolUtil.safeAddAttributes('./.temp/', NativeAPI.FileAttribute.HIDDEN);
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
var startState:Class<FlxState> = Flags.DISABLE_WARNING_SCREEN ? TitleState : funkin.menus.WarningState;
|
||||||
|
|
||||||
if (Options.devMode && Options.allowConfigWarning) {
|
if (Options.devMode && Options.allowConfigWarning) {
|
||||||
var lib:ModsFolderLibrary;
|
var lib:ModsFolderLibrary;
|
||||||
for (e in Paths.assetsTree.libraries) if ((lib = cast AssetsLibraryList.getCleanLibrary(e)) is ModsFolderLibrary
|
for (e in Paths.assetsTree.libraries) if ((lib = cast AssetsLibraryList.getCleanLibrary(e)) is ModsFolderLibrary
|
||||||
@@ -133,12 +136,11 @@ class MainState extends FlxState {
|
|||||||
{
|
{
|
||||||
if (lib.exists(Paths.ini("config/modpack"), lime.utils.AssetType.TEXT)) break;
|
if (lib.exists(Paths.ini("config/modpack"), lime.utils.AssetType.TEXT)) break;
|
||||||
|
|
||||||
FlxG.switchState(new ModConfigWarning(lib));
|
FlxG.switchState(new ModConfigWarning(lib, startState));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Flags.DISABLE_WARNING_SCREEN) FlxG.switchState(new funkin.menus.WarningState());
|
FlxG.switchState(cast Type.createInstance(startState, []));
|
||||||
else FlxG.switchState(new TitleState());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,13 +12,13 @@ import haxe.Exception;
|
|||||||
* Requires the `GITHUB_API` macro to be defined.
|
* Requires the `GITHUB_API` macro to be defined.
|
||||||
* This has no authentication, so it's limited to unauthenticated requests, and rate limits.
|
* This has no authentication, so it's limited to unauthenticated requests, and rate limits.
|
||||||
**/
|
**/
|
||||||
class GitHub {
|
final class GitHub {
|
||||||
/**
|
/**
|
||||||
* Gets all the releases from a specific GitHub repository using the GitHub API.
|
* Gets all the releases from a specific GitHub repository using the GitHub API.
|
||||||
* @param user The user/organization that owns the repository
|
* @param user The user/organization that owns the repository.
|
||||||
* @param repository The repository name
|
* @param repository The repository name.
|
||||||
* @param onError Error Callback
|
* @param onError Error Callback.
|
||||||
* @return Releases
|
* @return Releases in Array.
|
||||||
*/
|
*/
|
||||||
public static function getReleases(user:String, repository:String, ?onError:Exception->Void):Array<GitHubRelease> {
|
public static function getReleases(user:String, repository:String, ?onError:Exception->Void):Array<GitHubRelease> {
|
||||||
#if GITHUB_API
|
#if GITHUB_API
|
||||||
@@ -38,17 +38,16 @@ class GitHub {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the contributors list from a specific GitHub repository using the GitHub API.
|
* Gets the contributors list from a specific GitHub repository using the GitHub API.
|
||||||
* @param user The user/organization that owns the repository
|
* @param user The user/organization that owns the repository.
|
||||||
* @param repository The repository name
|
* @param repository The repository name.
|
||||||
* @param onError Error Callback
|
* @param onError Error Callback.
|
||||||
* @return Contributors List
|
* @return Contributors List as Array.
|
||||||
*/
|
*/
|
||||||
public static function getContributors(user:String, repository:String, ?onError:Exception->Void):Array<GitHubContributor> {
|
public static function getContributors(user:String, repository:String, ?onError:Exception->Void):Array<GitHubContributor> {
|
||||||
#if GITHUB_API
|
#if GITHUB_API
|
||||||
try {
|
try {
|
||||||
var data = Json.parse(HttpUtil.requestText('https://api.github.com/repos/${user}/${repository}/contributors'));
|
var data = Json.parse(HttpUtil.requestText('https://api.github.com/repos/${user}/${repository}/contributors'));
|
||||||
if (!(data is Array))
|
if (!(data is Array)) throw __parseGitHubException(data);
|
||||||
throw __parseGitHubException(data);
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
@@ -61,16 +60,15 @@ class GitHub {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a specific GitHub organization using the GitHub API.
|
* Gets a specific GitHub organization using the GitHub API.
|
||||||
* @param org The organization to get
|
* @param org The organization to get.
|
||||||
* @param onError Error Callback
|
* @param onError Error Callback.
|
||||||
* @return Organization
|
* @return Organization.
|
||||||
*/
|
*/
|
||||||
public static function getOrganization(org:String, ?onError:Exception->Void):GitHubOrganization {
|
public static function getOrganization(org:String, ?onError:Exception->Void):GitHubOrganization {
|
||||||
#if GITHUB_API
|
#if GITHUB_API
|
||||||
try {
|
try {
|
||||||
var data = Json.parse(HttpUtil.requestText('https://api.github.com/orgs/$org'));
|
var data = Json.parse(HttpUtil.requestText('https://api.github.com/orgs/$org'));
|
||||||
if (Reflect.hasField(data, "documentation_url"))
|
if (Reflect.hasField(data, "documentation_url")) throw __parseGitHubException(data);
|
||||||
throw __parseGitHubException(data);
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
@@ -84,16 +82,15 @@ class GitHub {
|
|||||||
/**
|
/**
|
||||||
* Gets the members list from a specific GitHub organization using the GitHub API.
|
* Gets the members list from a specific GitHub organization using the GitHub API.
|
||||||
* NOTE: Members use Contributors' structure!
|
* NOTE: Members use Contributors' structure!
|
||||||
* @param org The organization to get the members from
|
* @param org The organization to get the members from.
|
||||||
* @param onError Error Callback
|
* @param onError Error Callback.
|
||||||
* @return Members List
|
* @return Members List as Array
|
||||||
*/
|
*/
|
||||||
public static function getOrganizationMembers(org:String, ?onError:Exception->Void):Array<GitHubContributor> {
|
public static function getOrganizationMembers(org:String, ?onError:Exception->Void):Array<GitHubContributor> {
|
||||||
#if GITHUB_API
|
#if GITHUB_API
|
||||||
try {
|
try {
|
||||||
var data = Json.parse(HttpUtil.requestText('https://api.github.com/orgs/$org/members'));
|
var data = Json.parse(HttpUtil.requestText('https://api.github.com/orgs/$org/members'));
|
||||||
if (Reflect.hasField(data, "documentation_url"))
|
if (Reflect.hasField(data, "documentation_url")) throw __parseGitHubException(data);
|
||||||
throw __parseGitHubException(data);
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
@@ -107,18 +104,15 @@ class GitHub {
|
|||||||
/**
|
/**
|
||||||
* Gets a specific GitHub user/organization using the GitHub API.
|
* Gets a specific GitHub user/organization using the GitHub API.
|
||||||
* NOTE: If organization, it will be returned with the structure of a normal user; use `getOrganization` if you specifically want an organization!
|
* NOTE: If organization, it will be returned with the structure of a normal user; use `getOrganization` if you specifically want an organization!
|
||||||
* @param user The user/organization to get
|
* @param user The user/organization to get.
|
||||||
* @param onError Error Callback
|
* @param onError Error Callback.
|
||||||
* @return User/Organization
|
* @return User/Organization.
|
||||||
*/
|
*/
|
||||||
public static function getUser(user:String, ?onError:Exception->Void):GitHubUser {
|
public static function getUser(user:String, ?onError:Exception->Void):GitHubUser {
|
||||||
#if GITHUB_API
|
#if GITHUB_API
|
||||||
try {
|
try {
|
||||||
var url = 'https://api.github.com/users/$user';
|
var data = Json.parse(HttpUtil.requestText('https://api.github.com/users/$user'));
|
||||||
|
if (Reflect.hasField(data, "documentation_url")) throw __parseGitHubException(data);
|
||||||
var data = Json.parse(HttpUtil.requestText(url));
|
|
||||||
if (Reflect.hasField(data, "documentation_url"))
|
|
||||||
throw __parseGitHubException(data);
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package funkin.backend.system.interfaces;
|
||||||
|
|
||||||
|
interface IBeatCancellableReceiver extends IBeatReceiver {
|
||||||
|
public var cancelConductorUpdate:Bool;
|
||||||
|
}
|
||||||
@@ -33,11 +33,9 @@ class FlagMacro {
|
|||||||
resetExprs.push(macro $i{"customFlags"} = $v{[]});
|
resetExprs.push(macro $i{"customFlags"} = $v{[]});
|
||||||
|
|
||||||
for (field in fields) {
|
for (field in fields) {
|
||||||
var skip = field.meta.hasMeta(":bypass");
|
if (field.meta.hasMeta(":bypass")) continue;
|
||||||
var hasLazy = field.meta.hasMeta(":lazy");
|
var hasLazy = field.meta.hasMeta(":lazy");
|
||||||
|
|
||||||
if (skip) continue;
|
|
||||||
|
|
||||||
switch (field.kind) {
|
switch (field.kind) {
|
||||||
case FVar(type, expr):
|
case FVar(type, expr):
|
||||||
var isNullable = false;
|
var isNullable = false;
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ class FunkinSaveMacro {
|
|||||||
* SAVE FUNCTION
|
* SAVE FUNCTION
|
||||||
*/
|
*/
|
||||||
var saveFuncBlocks:Array<Expr> = [for(f in fieldNames) macro $i{saveFieldName}.data.$f = $i{f}];
|
var saveFuncBlocks:Array<Expr> = [for(f in fieldNames) macro $i{saveFieldName}.data.$f = $i{f}];
|
||||||
|
|
||||||
saveFuncBlocks.push(macro $i{saveFieldName}.flush());
|
saveFuncBlocks.push(macro $i{saveFieldName}.flush());
|
||||||
|
|
||||||
fields.push({
|
fields.push({
|
||||||
@@ -59,6 +58,8 @@ class FunkinSaveMacro {
|
|||||||
access: [APublic, AStatic]
|
access: [APublic, AStatic]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var loadFuncBlocks:Array<Expr> = [for(f in fieldNames) macro if ($i{saveFieldName}.data.$f != null) $i{f} = $i{saveFieldName}.data.$f];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LOAD FUNCTION
|
* LOAD FUNCTION
|
||||||
*/
|
*/
|
||||||
@@ -69,10 +70,7 @@ class FunkinSaveMacro {
|
|||||||
args: [],
|
args: [],
|
||||||
expr: {
|
expr: {
|
||||||
pos: Context.currentPos(),
|
pos: Context.currentPos(),
|
||||||
expr: EBlock([for(f in fieldNames)
|
expr: EBlock(loadFuncBlocks)
|
||||||
macro if ($i{saveFieldName}.data.$f != null)
|
|
||||||
$i{f} = $i{saveFieldName}.data.$f
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
access: [APublic, AStatic]
|
access: [APublic, AStatic]
|
||||||
|
|||||||
@@ -24,7 +24,11 @@ class UpdateAvailableScreen extends MusicBeatState {
|
|||||||
|
|
||||||
public function new(check:UpdateCheckCallback) {
|
public function new(check:UpdateCheckCallback) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.check = check;
|
this.check = check;
|
||||||
|
if (Date.now().getTime() - check.date.getTime() > 15000) {
|
||||||
|
if ((check = UpdateUtil.checkForUpdates(true)).newUpdate) this.check = check;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override function create() {
|
public override function create() {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class UpdateScreen extends MusicBeatState {
|
|||||||
generalProgress.alignment = CENTER;
|
generalProgress.alignment = CENTER;
|
||||||
add(generalProgress);
|
add(generalProgress);
|
||||||
|
|
||||||
overSound = FlxG.sound.load(Paths.sound(Flags.DEFAULT_GAMEOVER_RETRY_SFX));
|
overSound = FlxG.sound.load(Paths.sound(Flags.DEFAULT_GAMEOVEREND_SOUND));
|
||||||
|
|
||||||
updater.execute();
|
updater.execute();
|
||||||
|
|
||||||
|
|||||||
@@ -2,60 +2,97 @@ package funkin.backend.system.updating;
|
|||||||
|
|
||||||
import funkin.backend.system.github.GitHub;
|
import funkin.backend.system.github.GitHub;
|
||||||
import funkin.backend.system.github.GitHubRelease;
|
import funkin.backend.system.github.GitHubRelease;
|
||||||
import haxe.io.Path;
|
|
||||||
import lime.app.Application;
|
import lime.app.Application;
|
||||||
|
|
||||||
|
import sys.thread.Mutex;
|
||||||
|
import sys.thread.Thread;
|
||||||
import sys.FileSystem;
|
import sys.FileSystem;
|
||||||
|
|
||||||
|
import haxe.io.Path;
|
||||||
|
|
||||||
using funkin.backend.system.github.GitHub;
|
using funkin.backend.system.github.GitHub;
|
||||||
|
|
||||||
class UpdateUtil {
|
class UpdateUtil {
|
||||||
|
public static var lastUpdateCheck:Null<UpdateCheckCallback>;
|
||||||
|
|
||||||
|
private static var __waitCallbacks:Array<UpdateCheckCallback->Void>;
|
||||||
|
private static var __mutex:Mutex;
|
||||||
|
|
||||||
public static function init() {
|
public static function init() {
|
||||||
// deletes old bak file if it exists
|
// deletes old bak file if it exists
|
||||||
#if sys
|
#if sys
|
||||||
var bakPath = '${Path.withoutExtension(Sys.programPath())}.bak';
|
var bakPath = '${Path.withoutExtension(Sys.programPath())}.bak';
|
||||||
if (FileSystem.exists(bakPath))
|
if (FileSystem.exists(bakPath)) FileSystem.deleteFile(bakPath);
|
||||||
FileSystem.deleteFile(bakPath);
|
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
__waitCallbacks = [];
|
||||||
|
__mutex = new Mutex();
|
||||||
|
Thread.create(checkForUpdates.bind(true, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function checkForUpdates():UpdateCheckCallback {
|
public static function waitForUpdates(force = false, callback:UpdateCheckCallback->Void, lazy = false) {
|
||||||
var curTag = 'v${Flags.VERSION}';
|
if (__mutex.tryAcquire()) {
|
||||||
trace(curTag);
|
__mutex.release();
|
||||||
|
if (__shouldCheck(lazy) || force) {
|
||||||
|
__waitCallbacks.push(callback);
|
||||||
|
Thread.create(checkForUpdates.bind(force, false));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
callback(lastUpdateCheck);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
__waitCallbacks.push(callback);
|
||||||
|
}
|
||||||
|
|
||||||
var error = false;
|
public static function checkForUpdates(force = false, lazy = false):UpdateCheckCallback {
|
||||||
|
var wasAcquired = !__mutex.tryAcquire();
|
||||||
|
if (wasAcquired) __mutex.acquire();
|
||||||
|
|
||||||
var newUpdates = __doReleaseFiltering(GitHub.getReleases(Flags.REPO_NAME, Flags.REPO_OWNER, function(e) {
|
if ((!force || wasAcquired) && !__shouldCheck(lazy)) {
|
||||||
|
__mutex.release();
|
||||||
|
return lastUpdateCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastUpdateCheck = __checkForUpdates();
|
||||||
|
__mutex.release();
|
||||||
|
|
||||||
|
FlxG.signals.preUpdate.addOnce(__callWaitCallbacks);
|
||||||
|
|
||||||
|
return lastUpdateCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function __checkForUpdates():UpdateCheckCallback {
|
||||||
|
var curTag = 'v' + (Flags.VERSION == null ? Application.current.meta.get('version') : Flags.VERSION), error = false;
|
||||||
|
var newUpdates = __doReleaseFiltering(GitHub.getReleases(Flags.REPO_OWNER, Flags.REPO_NAME, (e) -> {
|
||||||
error = true;
|
error = true;
|
||||||
}), curTag);
|
}), curTag);
|
||||||
|
|
||||||
if (error) return {
|
var updateCheck:UpdateCheckCallback = {
|
||||||
success: false,
|
success: !error,
|
||||||
newUpdate: false
|
newUpdate: !error && newUpdates.length > 0,
|
||||||
};
|
currentVersionTag: curTag,
|
||||||
|
date: Date.now()
|
||||||
if (newUpdates.length <= 0) {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
newUpdate: false
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
if (updateCheck.newUpdate) updateCheck.newVersionTag = (updateCheck.updates = newUpdates).last().tag_name;
|
||||||
success: true,
|
return updateCheck;
|
||||||
newUpdate: true,
|
}
|
||||||
currentVersionTag: curTag,
|
|
||||||
newVersionTag: newUpdates.last().tag_name,
|
static function __shouldCheck(lazy:Bool):Bool
|
||||||
updates: newUpdates
|
return lastUpdateCheck == null || !lazy && (!lastUpdateCheck.newUpdate || Date.now().getTime() - lastUpdateCheck.date.getTime() > 1800000);
|
||||||
};
|
|
||||||
|
static function __callWaitCallbacks() {
|
||||||
|
for (callback in __waitCallbacks) callback(lastUpdateCheck);
|
||||||
|
__waitCallbacks.resize(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static var __curVersionPos = -2;
|
|
||||||
static function __doReleaseFiltering(releases:Array<GitHubRelease>, currentVersionTag:String) {
|
static function __doReleaseFiltering(releases:Array<GitHubRelease>, currentVersionTag:String) {
|
||||||
releases = releases.filterReleases(Options.betaUpdates, false);
|
releases = releases.filterReleases(Options.betaUpdates, false);
|
||||||
if (releases.length <= 0)
|
if (releases.length <= 0)
|
||||||
return releases;
|
return releases;
|
||||||
|
|
||||||
var newArray:Array<GitHubRelease> = [];
|
var newArray:Array<GitHubRelease> = [], __curVersionPos = -2;
|
||||||
|
|
||||||
var skipNextBinaryChecks:Bool = false;
|
var skipNextBinaryChecks:Bool = false;
|
||||||
for(index in 0...releases.length) {
|
for(index in 0...releases.length) {
|
||||||
@@ -73,13 +110,9 @@ class UpdateUtil {
|
|||||||
}
|
}
|
||||||
if (containsBinary) {
|
if (containsBinary) {
|
||||||
skipNextBinaryChecks = true; // no need to check for older versions
|
skipNextBinaryChecks = true; // no need to check for older versions
|
||||||
if (release.tag_name == currentVersionTag) {
|
if (release.tag_name == currentVersionTag) __curVersionPos = -1;
|
||||||
__curVersionPos = -1;
|
|
||||||
}
|
|
||||||
newArray.insert(0, release);
|
newArray.insert(0, release);
|
||||||
if (__curVersionPos > -2)
|
if (__curVersionPos > -2) __curVersionPos++;
|
||||||
__curVersionPos++;
|
|
||||||
trace(release.tag_name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (__curVersionPos < -1)
|
if (__curVersionPos < -1)
|
||||||
@@ -99,4 +132,6 @@ typedef UpdateCheckCallback = {
|
|||||||
@:optional var newVersionTag:String;
|
@:optional var newVersionTag:String;
|
||||||
|
|
||||||
@:optional var updates:Array<GitHubRelease>;
|
@:optional var updates:Array<GitHubRelease>;
|
||||||
|
|
||||||
|
@:optional var date:Date;
|
||||||
}
|
}
|
||||||
@@ -474,7 +474,7 @@ final class AudioAnalyzer {
|
|||||||
var n = Math.floor((endPos - startPos) * __toBits);
|
var n = Math.floor((endPos - startPos) * __toBits);
|
||||||
if (startPos >= time && startPos < backend.bufferTimes[backend.bufferSizes.length - 1] * 1000) {
|
if (startPos >= time && startPos < backend.bufferTimes[backend.bufferSizes.length - 1] * 1000) {
|
||||||
var pos = Math.floor((startPos - time) * __toBits), buf = backend.bufferDatas[i].buffer, size = backend.bufferSizes[i], c = 0;
|
var pos = Math.floor((startPos - time) * __toBits), buf = backend.bufferDatas[i].buffer, size = backend.bufferSizes[i], c = 0;
|
||||||
while (pos > size) {
|
while (pos >= size) {
|
||||||
if (++i >= backend.bufferSizes.length) {
|
if (++i >= backend.bufferSizes.length) {
|
||||||
n = 0;
|
n = 0;
|
||||||
break;
|
break;
|
||||||
@@ -484,6 +484,7 @@ final class AudioAnalyzer {
|
|||||||
size = backend.bufferSizes[i];
|
size = backend.bufferSizes[i];
|
||||||
}
|
}
|
||||||
pos -= pos % __sampleSize;
|
pos -= pos % __sampleSize;
|
||||||
|
n -= pos % __sampleSize;
|
||||||
|
|
||||||
while (n > 0) {
|
while (n > 0) {
|
||||||
callback(getByte(buf, pos, __wordSize), c);
|
callback(getByte(buf, pos, __wordSize), c);
|
||||||
|
|||||||
@@ -38,6 +38,6 @@ class FlxInterpolateColor {
|
|||||||
alpha = (color.alphaFloat - alpha) * ratio + alpha;
|
alpha = (color.alphaFloat - alpha) * ratio + alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline function fpsLerpTo(color:FlxColor, ratio:Float)
|
public inline function fpsLerpTo(color:FlxColor, ratio:Float, ?delta:Float)
|
||||||
lerpTo(color, ratio * 60 * FlxG.elapsed);
|
lerpTo(color, CoolUtil.getFPSRatio(ratio, delta));
|
||||||
}
|
}
|
||||||
@@ -29,9 +29,6 @@ final class WindowUtils {
|
|||||||
public static inline function resetClosing() __triedClosing = false;
|
public static inline function resetClosing() __triedClosing = false;
|
||||||
|
|
||||||
@:dox(hide) public static inline function init() {
|
@:dox(hide) public static inline function init() {
|
||||||
resetTitle();
|
|
||||||
resetClosing();
|
|
||||||
|
|
||||||
Lib.application.window.onClose.add(function () {
|
Lib.application.window.onClose.add(function () {
|
||||||
if (preventClosing && !__triedClosing) {
|
if (preventClosing && !__triedClosing) {
|
||||||
Lib.application.window.onClose.cancel();
|
Lib.application.window.onClose.cancel();
|
||||||
@@ -45,16 +42,17 @@ final class WindowUtils {
|
|||||||
* Resets the window title to the application name and resets the prefix and suffix.
|
* Resets the window title to the application name and resets the prefix and suffix.
|
||||||
**/
|
**/
|
||||||
public static inline function resetTitle() {
|
public static inline function resetTitle() {
|
||||||
title = Flags.TITLE == null ? Lib.application.meta.get('name') : Flags.TITLE;
|
resetAffixes(false);
|
||||||
resetAffixes();
|
title = Flags.TITLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the prefix and suffix.
|
* Resets the prefix and suffix.
|
||||||
|
* @param update Should it update window title.
|
||||||
**/
|
**/
|
||||||
public static inline function resetAffixes() {
|
public static inline function resetAffixes(update = true) {
|
||||||
prefix = suffix = "";
|
prefix = suffix = "";
|
||||||
updateTitle();
|
if (update) updateTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,9 +60,13 @@ final class WindowUtils {
|
|||||||
* @param title The title to set.
|
* @param title The title to set.
|
||||||
* @param image The image to set as the icon.
|
* @param image The image to set as the icon.
|
||||||
**/
|
**/
|
||||||
public static inline function setWindow(?name:String, ?image:String)
|
public static inline function setWindow(?title:String, ?image:String)
|
||||||
{ Lib.application.window.setIcon(lime.graphics.Image.fromBytes(Assets.getBytes(image != null ? image : Flags.MOD_ICON)));
|
{
|
||||||
title = name != null ? name : Flags.MOD_NAME;
|
// TODO: Implement ICON SIZES in Flags.
|
||||||
|
WindowUtils.title = title != null ? title : (Flags.WINDOW_TITLE_USE_MOD_NAME ? Flags.MOD_NAME : Flags.TITLE);
|
||||||
|
|
||||||
|
var iconPath = image != null ? image : Flags.MOD_ICON;
|
||||||
|
if (Assets.exists(Paths.image(iconPath))) Lib.application.window.setIcon(lime.graphics.Image.fromBytes(Assets.getBytes(Paths.image(iconPath))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ typedef WeekCharacter = {
|
|||||||
|
|
||||||
typedef WeekSong = {
|
typedef WeekSong = {
|
||||||
var name:String;
|
var name:String;
|
||||||
var hide:Bool;
|
var ?hide:Bool;
|
||||||
|
var ?variation:String;
|
||||||
var ?displayName:String;
|
var ?displayName:String;
|
||||||
}
|
}
|
||||||
@@ -56,9 +56,9 @@ LOGO_TEXT=""
|
|||||||
super.createPost();
|
super.createPost();
|
||||||
hadPopup = true;
|
hadPopup = true;
|
||||||
|
|
||||||
var substate = new UIWarningSubstate("Missing mod folder configuration!", "Your mod is currently missing a mod config file!\n\nWould you like to automatically generate one?\n\n(PS: If this is not your mod please disable Developer mode to stop this popup from appearing.)", [
|
var substate = new UIWarningSubstate(TU.translate("modConfigWarning.warningTitle"), TU.translate("modConfigWarning.warningDesc"), [
|
||||||
{
|
{
|
||||||
label: "Not Now",
|
label: TU.translate("editor.notNow"),
|
||||||
color: 0x969533,
|
color: 0x969533,
|
||||||
onClick: function (_) {
|
onClick: function (_) {
|
||||||
MusicBeatState.skipTransOut = MusicBeatState.skipTransIn = false;
|
MusicBeatState.skipTransOut = MusicBeatState.skipTransIn = false;
|
||||||
@@ -66,13 +66,13 @@ LOGO_TEXT=""
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Yes",
|
label: TU.translate("editor.yes"),
|
||||||
onClick: function(_) {
|
onClick: function(_) {
|
||||||
var path = '${library.folderPath}/data/config/modpack.ini';
|
var path = '${library.folderPath}/data/config/modpack.ini';
|
||||||
CoolUtil.safeSaveFile(path, defaultModConfigText);
|
CoolUtil.safeSaveFile(path, defaultModConfigText);
|
||||||
openSubState(new UIWarningSubstate("Created mod config!", "Your mod config file has been created at " + path + "!", [
|
openSubState(new UIWarningSubstate(TU.translate("modConfigWarning.createdTitle"), TU.translate("modConfigWarning.createdDesc", [path]), [
|
||||||
{
|
{
|
||||||
label: "Ok",
|
label: TU.translate("editor.ok"),
|
||||||
onClick: function (_) {
|
onClick: function (_) {
|
||||||
MusicBeatState.skipTransOut = MusicBeatState.skipTransIn = false;
|
MusicBeatState.skipTransOut = MusicBeatState.skipTransIn = false;
|
||||||
FlxG.switchState(cast Type.createInstance(goToState, []));
|
FlxG.switchState(cast Type.createInstance(goToState, []));
|
||||||
|
|||||||
@@ -209,6 +209,9 @@ class AlphabetEditor extends UIState {
|
|||||||
scaleX: 1,
|
scaleX: 1,
|
||||||
scaleY: 1,
|
scaleY: 1,
|
||||||
|
|
||||||
|
flipX: false,
|
||||||
|
flipY: false,
|
||||||
|
|
||||||
hasColorMode: false,
|
hasColorMode: false,
|
||||||
colorMode: bigLetter.colorMode
|
colorMode: bigLetter.colorMode
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -204,6 +204,9 @@ UPPERLETTER and LOWERLETTTER can be used in any backup prefix.";
|
|||||||
cos: 1.0,
|
cos: 1.0,
|
||||||
sin: 0.0,
|
sin: 0.0,
|
||||||
|
|
||||||
|
flipX: false,
|
||||||
|
flipY: false,
|
||||||
|
|
||||||
hasColorMode: false,
|
hasColorMode: false,
|
||||||
colorMode: 0
|
colorMode: 0
|
||||||
}],
|
}],
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ class GlyphInfoWindow extends UIWindow {
|
|||||||
public var angleBox:UINumericStepper;
|
public var angleBox:UINumericStepper;
|
||||||
public var colorModeDrop:UIDropDown;
|
public var colorModeDrop:UIDropDown;
|
||||||
|
|
||||||
|
public var flipXBox:UICheckbox;
|
||||||
|
public var flipYBox:UICheckbox;
|
||||||
|
|
||||||
public var outlineTitle:UIText;
|
public var outlineTitle:UIText;
|
||||||
public var outlineSep:UISprite;
|
public var outlineSep:UISprite;
|
||||||
public var outlineCheck:UICheckbox;
|
public var outlineCheck:UICheckbox;
|
||||||
@@ -145,6 +148,9 @@ class GlyphInfoWindow extends UIWindow {
|
|||||||
cos: compon.cos,
|
cos: compon.cos,
|
||||||
sin: compon.sin,
|
sin: compon.sin,
|
||||||
|
|
||||||
|
flipX: compon.flipX,
|
||||||
|
flipY: compon.flipY,
|
||||||
|
|
||||||
hasColorMode: compon.hasColorMode,
|
hasColorMode: compon.hasColorMode,
|
||||||
colorMode: compon.colorMode
|
colorMode: compon.colorMode
|
||||||
};
|
};
|
||||||
@@ -159,6 +165,22 @@ class GlyphInfoWindow extends UIWindow {
|
|||||||
}
|
}
|
||||||
members.push(outlineCheck);
|
members.push(outlineCheck);
|
||||||
|
|
||||||
|
flipXBox = new UICheckbox(outlineCheck.x, outlineCheck.y - outlineCheck.height - 8, "Flip X?");
|
||||||
|
flipXBox.onChecked = function(check:Bool) {
|
||||||
|
compon.flipX = check;
|
||||||
|
if (outlineCheck.checked)
|
||||||
|
data.components[compon.outIndex].flipX = check;
|
||||||
|
}
|
||||||
|
members.push(flipXBox);
|
||||||
|
|
||||||
|
flipYBox = new UICheckbox(flipXBox.x + flipXBox.width + itemMargin * 5, flipXBox.y, "Flip Y?");
|
||||||
|
flipYBox.onChecked = function(check:Bool) {
|
||||||
|
compon.flipY = check;
|
||||||
|
if (outlineCheck.checked)
|
||||||
|
data.components[compon.outIndex].flipY = check;
|
||||||
|
}
|
||||||
|
members.push(flipYBox);
|
||||||
|
|
||||||
outlineTitle = new UIText(colorModeDrop.x, colorModeDrop.y + colorModeDrop.bHeight + itemMargin, 0, "Outline Data");
|
outlineTitle = new UIText(colorModeDrop.x, colorModeDrop.y + colorModeDrop.bHeight + itemMargin, 0, "Outline Data");
|
||||||
members.push(outlineTitle);
|
members.push(outlineTitle);
|
||||||
outlineSep = new UISprite(x + itemMargin, colorModeDrop.y + colorModeDrop.bHeight + itemMargin + 19);
|
outlineSep = new UISprite(x + itemMargin, colorModeDrop.y + colorModeDrop.bHeight + itemMargin + 19);
|
||||||
@@ -239,6 +261,8 @@ class GlyphInfoWindow extends UIWindow {
|
|||||||
angleBox.value = com.angle;
|
angleBox.value = com.angle;
|
||||||
@:privateAccess colorModeDrop.index = com.hasColorMode ? com.colorMode : AlphabetEditor.instance.tape.colorMode;
|
@:privateAccess colorModeDrop.index = com.hasColorMode ? com.colorMode : AlphabetEditor.instance.tape.colorMode;
|
||||||
@:privateAccess colorModeDrop.label.text = colorModeDrop.options[colorModeDrop.index];
|
@:privateAccess colorModeDrop.label.text = colorModeDrop.options[colorModeDrop.index];
|
||||||
|
flipXBox.checked = com.flipX;
|
||||||
|
flipYBox.checked = com.flipY;
|
||||||
|
|
||||||
outlineCheck.checked = com.outIndex != null;
|
outlineCheck.checked = com.outIndex != null;
|
||||||
outlineBox.label.text = "";
|
outlineBox.label.text = "";
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import flixel.util.FlxColor;
|
|||||||
class Charter extends UIState {
|
class Charter extends UIState {
|
||||||
public static var __song:String;
|
public static var __song:String;
|
||||||
static var __diff:String;
|
static var __diff:String;
|
||||||
|
static var __variant:String;
|
||||||
static var __reload:Bool;
|
static var __reload:Bool;
|
||||||
|
|
||||||
var chart(get, never):ChartData;
|
var chart(get, never):ChartData;
|
||||||
@@ -114,11 +115,12 @@ class Charter extends UIState {
|
|||||||
private var SONGPOSINFO_BPM = TU.getRaw("songPosInfo.bpm");
|
private var SONGPOSINFO_BPM = TU.getRaw("songPosInfo.bpm");
|
||||||
private var SONGPOSINFO_TIMESIGNATURE = TU.getRaw("songPosInfo.timeSignature");
|
private var SONGPOSINFO_TIMESIGNATURE = TU.getRaw("songPosInfo.timeSignature");
|
||||||
|
|
||||||
public function new(song:String, diff:String, reload:Bool = true) {
|
public function new(song:String, diff:String, variant:String, reload:Bool = true) {
|
||||||
super();
|
super();
|
||||||
if (song != null) {
|
if (song != null) {
|
||||||
__song = song;
|
__song = song;
|
||||||
__diff = diff;
|
__diff = diff;
|
||||||
|
__variant = variant;
|
||||||
__reload = reload;
|
__reload = reload;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -578,7 +580,7 @@ class Charter extends UIState {
|
|||||||
dataDisplay.screenCenter(Y);
|
dataDisplay.screenCenter(Y);
|
||||||
dataDisplay.cameras = [charterCamera]; dataDisplay.x = -dataDisplay.width; add(dataDisplay);*/
|
dataDisplay.cameras = [charterCamera]; dataDisplay.x = -dataDisplay.width; add(dataDisplay);*/
|
||||||
|
|
||||||
DiscordUtil.call("onEditorLoaded", ["Chart Editor", __song + " (" + __diff + ")"]);
|
DiscordUtil.call("onEditorLoaded", ["Chart Editor", __song + " (" + __diff + ")" + (__variant != null && __variant != "" ? " (" + __variant + ")" : "")]);
|
||||||
}
|
}
|
||||||
|
|
||||||
override function destroy() {
|
override function destroy() {
|
||||||
@@ -595,29 +597,32 @@ class Charter extends UIState {
|
|||||||
public function loadSong() {
|
public function loadSong() {
|
||||||
if (__reload) {
|
if (__reload) {
|
||||||
EventsData.reloadEvents();
|
EventsData.reloadEvents();
|
||||||
PlayState.loadSong(__song, __diff, false, false);
|
PlayState.loadSong(__song, __diff, __variant, false, false);
|
||||||
__resetStatics();
|
__resetStatics();
|
||||||
}
|
}
|
||||||
|
|
||||||
Conductor.setupSong(PlayState.SONG);
|
Conductor.setupSong(PlayState.SONG);
|
||||||
noteTypes = PlayState.SONG.noteTypes;
|
noteTypes = PlayState.SONG.noteTypes;
|
||||||
|
|
||||||
FlxG.sound.setMusic(FlxG.sound.load(Paths.inst(__song, __diff)));
|
FlxG.sound.setMusic(FlxG.sound.load(Paths.inst(__song, __diff, PlayState.SONG.meta.instSuffix)));
|
||||||
if (PlayState.SONG.meta.needsVoices != false && Assets.exists(Paths.voices(__song, __diff))) // null or true
|
if (Assets.exists(Paths.voices(__song, __diff, PlayState.SONG.meta.vocalsSuffix)))
|
||||||
vocals = FlxG.sound.load(Paths.voices(__song, __diff));
|
vocals = FlxG.sound.load(Paths.voices(__song, __diff, PlayState.SONG.meta.vocalsSuffix));
|
||||||
else
|
else
|
||||||
vocals = new FlxSound();
|
vocals = new FlxSound();
|
||||||
|
|
||||||
|
vocals.muted = !PlayState.SONG.meta.needsVoices;
|
||||||
vocals.group = FlxG.sound.defaultMusicGroup;
|
vocals.group = FlxG.sound.defaultMusicGroup;
|
||||||
|
|
||||||
gridBackdrops.createGrids(PlayState.SONG.strumLines.length);
|
gridBackdrops.createGrids(PlayState.SONG.strumLines.length);
|
||||||
|
|
||||||
for(strL in PlayState.SONG.strumLines)
|
var noteCount:Int = 0;
|
||||||
|
for (strL in PlayState.SONG.strumLines) {
|
||||||
createStrumline(strumLines.members.length, strL, false, false);
|
createStrumline(strumLines.members.length, strL, false, false);
|
||||||
|
noteCount += strL.notes.length;
|
||||||
|
}
|
||||||
|
|
||||||
// create notes
|
// create notes
|
||||||
notesGroup.autoSort = false;
|
notesGroup.autoSort = false;
|
||||||
var noteCount:Int = 0;
|
|
||||||
for (strL in PlayState.SONG.strumLines)
|
|
||||||
noteCount += strL.notes.length;
|
|
||||||
notesGroup.preallocate(noteCount);
|
notesGroup.preallocate(noteCount);
|
||||||
|
|
||||||
var notesCreated:Int = 0;
|
var notesCreated:Int = 0;
|
||||||
@@ -633,22 +638,16 @@ class Charter extends UIState {
|
|||||||
|
|
||||||
// create events
|
// create events
|
||||||
rightEventsGroup.autoSort = leftEventsGroup.autoSort = false;
|
rightEventsGroup.autoSort = leftEventsGroup.autoSort = false;
|
||||||
var lastLeftEvents:CharterEvent = null, lastRightEvents:CharterEvent = null, lastEvents:CharterEvent;
|
var lastLeftEvents:CharterEvent = null, lastRightEvents:CharterEvent = null;
|
||||||
var lastLeftTime = Math.NaN, lastRightTime = Math.NaN, lastTime:Float;
|
var lastLeftTime = Math.NaN, lastRightTime = Math.NaN;
|
||||||
for (e in PlayState.SONG.events) if (e != null) {
|
for (e in PlayState.SONG.events) if (e != null) {
|
||||||
if (e.global) {
|
if (e.global) {
|
||||||
lastEvents = lastRightEvents;
|
if (lastRightEvents != null && lastRightTime == e.time) lastRightEvents.events.push(e);
|
||||||
lastTime = lastRightTime;
|
else rightEventsGroup.add(lastRightEvents = new CharterEvent(Conductor.getStepForTime(lastRightTime = e.time), [e], e.global));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lastEvents = lastLeftEvents;
|
if (lastLeftEvents != null && lastLeftTime == e.time) lastLeftEvents.events.push(e);
|
||||||
lastTime = lastLeftTime;
|
else leftEventsGroup.add(lastLeftEvents = new CharterEvent(Conductor.getStepForTime(lastLeftTime = e.time), [e], e.global));
|
||||||
}
|
|
||||||
|
|
||||||
if (lastEvents != null && lastTime == e.time) lastEvents.events.push(e);
|
|
||||||
else {
|
|
||||||
lastEvents = new CharterEvent(Conductor.getStepForTime(lastTime = e.time), [e], e.global);
|
|
||||||
(e.global ? rightEventsGroup : leftEventsGroup).add(lastEvents);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -687,10 +686,10 @@ class Charter extends UIState {
|
|||||||
var wavesToGenerate:Array<{name:String, sound:FlxSound}> = [];
|
var wavesToGenerate:Array<{name:String, sound:FlxSound}> = [];
|
||||||
|
|
||||||
if (FlxG.sound.music.loaded)
|
if (FlxG.sound.music.loaded)
|
||||||
wavesToGenerate.push({name: "Inst.ogg", sound: FlxG.sound.music});
|
wavesToGenerate.push({name: 'Inst${PlayState.SONG.meta.instSuffix}.ogg', sound: FlxG.sound.music});
|
||||||
|
|
||||||
if (PlayState.SONG.meta.needsVoices != false && vocals.loaded)
|
if (vocals.loaded)
|
||||||
wavesToGenerate.push({name: "Voices.ogg", sound: vocals});
|
wavesToGenerate.push({name: 'Voices${PlayState.SONG.meta.vocalsSuffix}.ogg', sound: vocals});
|
||||||
|
|
||||||
for (strumLine in strumLines)
|
for (strumLine in strumLines)
|
||||||
if (strumLine.vocals != null && strumLine.strumLine.vocalsSuffix != null && strumLine.strumLine.vocalsSuffix != "" && strumLine.vocals.loaded)
|
if (strumLine.vocals != null && strumLine.strumLine.vocalsSuffix != null && strumLine.strumLine.vocalsSuffix != "" && strumLine.vocals.loaded)
|
||||||
@@ -792,12 +791,13 @@ class Charter extends UIState {
|
|||||||
autoSaveTimer = Options.charterAutoSaveTime;
|
autoSaveTimer = Options.charterAutoSaveTime;
|
||||||
if (!autoSaveNotif.cancelled) {
|
if (!autoSaveNotif.cancelled) {
|
||||||
buildChart();
|
buildChart();
|
||||||
var songPath:String = '${Paths.getAssetsRoot()}/songs/${__song.toLowerCase()}';
|
|
||||||
|
|
||||||
if (Options.charterAutoSavesSeparateFolder)
|
if (Options.charterAutoSavesSeparateFolder)
|
||||||
Chart.save(songPath, PlayState.SONG, __autoSaveLocation, {saveMetaInChart: true, saveLocalEvents: true, saveGlobalEvents: true, folder: "autosaves", prettyPrint: Options.editorCharterPrettyPrint});
|
Chart.save(PlayState.SONG, __diff.toLowerCase(), __autoSaveLocation, {saveMetaInChart: true, saveLocalEvents: true, seperateGlobalEvents: true, folder: 'autosaves', prettyPrint: Options.editorCharterPrettyPrint});
|
||||||
else // These two chart saves are particular, to avoid any kind of loss, stuff like meta, global and local events will be save all together - Nex
|
else
|
||||||
Chart.save(songPath, PlayState.SONG, __diff.toLowerCase(), {saveMetaInChart: true, saveLocalEvents: true, saveGlobalEvents: true, prettyPrint: Options.editorCharterPrettyPrint});
|
Chart.save(PlayState.SONG, __diff.toLowerCase(), __variant, {saveMetaInChart: true, saveLocalEvents: true, seperateGlobalEvents: true, prettyPrint: Options.editorCharterPrettyPrint});
|
||||||
|
|
||||||
|
FlxG.sound.play(Paths.sound('editors/save'));
|
||||||
undos.save();
|
undos.save();
|
||||||
}
|
}
|
||||||
autoSaveNotif.cancelled = false;
|
autoSaveNotif.cancelled = false;
|
||||||
@@ -1210,7 +1210,9 @@ class Charter extends UIState {
|
|||||||
|
|
||||||
var strL = strumLines.members[strumLineID].strumLine;
|
var strL = strumLines.members[strumLineID].strumLine;
|
||||||
strumLines.members[strumLineID].destroy();
|
strumLines.members[strumLineID].destroy();
|
||||||
strumLines.members.remove(strumLines.members[strumLineID]);
|
strumLines.members[strumLineID] = strumLines.members[strumLines.members.length - 1];
|
||||||
|
strumLines.members.pop();
|
||||||
|
@:privateAccess strumLines.length--;
|
||||||
strumLines.refreshStrumlineIDs();
|
strumLines.refreshStrumlineIDs();
|
||||||
strumLines.snapStrums();
|
strumLines.snapStrums();
|
||||||
|
|
||||||
@@ -1480,8 +1482,8 @@ class Charter extends UIState {
|
|||||||
|
|
||||||
public static function saveChart(shouldBuild:Bool = true, withEvents:Bool = true) {
|
public static function saveChart(shouldBuild:Bool = true, withEvents:Bool = true) {
|
||||||
#if sys
|
#if sys
|
||||||
FlxG.sound.play(Paths.sound('editors/save'));
|
if (shouldBuild && instance != null) instance.buildChart();
|
||||||
saveTo('${Paths.getAssetsRoot()}/songs/${__song.toLowerCase()}', !withEvents, shouldBuild);
|
Chart.save(PlayState.SONG, __diff.toLowerCase(), __variant, {saveMetaInChart: false, saveLocalEvents: withEvents, prettyPrint: Options.editorCharterPrettyPrint});
|
||||||
if (undos != null) undos.save();
|
if (undos != null) undos.save();
|
||||||
#else
|
#else
|
||||||
saveChartAs(shouldBuild, withEvents);
|
saveChartAs(shouldBuild, withEvents);
|
||||||
@@ -1497,13 +1499,9 @@ class Charter extends UIState {
|
|||||||
|
|
||||||
public static function saveEvents(shouldBuild:Bool = true) {
|
public static function saveEvents(shouldBuild:Bool = true) {
|
||||||
#if sys
|
#if sys
|
||||||
FlxG.sound.play(Paths.sound('editors/save'));
|
|
||||||
if (shouldBuild && instance != null) instance.buildChart();
|
if (shouldBuild && instance != null) instance.buildChart();
|
||||||
var data = {events: Chart.filterChartForSaving(PlayState.SONG, false, false, true).events};
|
Chart.save(PlayState.SONG, __diff.toLowerCase(), __variant, {saveChart: false, seperateGlobalEvents: true, prettyPrint: Options.editorCharterPrettyPrint});
|
||||||
|
if (undos != null) undos.save();
|
||||||
var path = '${Paths.getAssetsRoot()}/songs/${__song.toLowerCase()}/events.json';
|
|
||||||
if (data.events != null && data.events.length > 0) CoolUtil.safeSaveFile(path, Json.stringify(data, null, Options.editorCharterPrettyPrint ? Flags.JSON_PRETTY_PRINT : null));
|
|
||||||
else if (FileSystem.exists(path)) FileSystem.deleteFile(path); // Instead of replacing with a useless empty file, deletes the file directly - Nex
|
|
||||||
#else
|
#else
|
||||||
saveEventsAs(shouldBuild);
|
saveEventsAs(shouldBuild);
|
||||||
#end
|
#end
|
||||||
@@ -1511,7 +1509,7 @@ class Charter extends UIState {
|
|||||||
|
|
||||||
public static function saveEventsAs(shouldBuild:Bool = true) {
|
public static function saveEventsAs(shouldBuild:Bool = true) {
|
||||||
if (shouldBuild && instance != null) instance.buildChart();
|
if (shouldBuild && instance != null) instance.buildChart();
|
||||||
var data = {events: Chart.filterChartForSaving(PlayState.SONG, false, false, true).events};
|
var data = {events: Chart.filterEventsForSaving(PlayState.SONG.events, false, true)};
|
||||||
|
|
||||||
saveAs(data, null, Options.editorCharterPrettyPrint ? Flags.JSON_PRETTY_PRINT : null, {
|
saveAs(data, null, Options.editorCharterPrettyPrint ? Flags.JSON_PRETTY_PRINT : null, {
|
||||||
defaultSaveFile: 'events.json'
|
defaultSaveFile: 'events.json'
|
||||||
@@ -1520,12 +1518,8 @@ class Charter extends UIState {
|
|||||||
|
|
||||||
public static function saveMeta(shouldBuild:Bool = true) {
|
public static function saveMeta(shouldBuild:Bool = true) {
|
||||||
#if sys
|
#if sys
|
||||||
FlxG.sound.play(Paths.sound('editors/save'));
|
|
||||||
if (shouldBuild && instance != null) instance.buildChart();
|
if (shouldBuild && instance != null) instance.buildChart();
|
||||||
CoolUtil.safeSaveFile(
|
Chart.save(PlayState.SONG, __diff.toLowerCase(), __variant, {saveChart: false, overrideExistingMeta: true, prettyPrint: true});
|
||||||
'${Paths.getAssetsRoot()}/songs/${__song.toLowerCase()}/meta.json',
|
|
||||||
Json.stringify(PlayState.SONG.meta == null ? {} : Chart.filterChartForSaving(PlayState.SONG, true, false, false).meta, null, Flags.JSON_PRETTY_PRINT)
|
|
||||||
);
|
|
||||||
#else
|
#else
|
||||||
saveMetaAs(shouldBuild);
|
saveMetaAs(shouldBuild);
|
||||||
#end
|
#end
|
||||||
@@ -1549,9 +1543,7 @@ class Charter extends UIState {
|
|||||||
}, null, shouldBuild);
|
}, null, shouldBuild);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function saveAs(data:Dynamic, ?replacer:(key:Dynamic, value:Dynamic) -> Dynamic, ?space:String, ?options:SaveSubstate.SaveSubstateData, ?saveOptions:Map<String, Bool>, shouldBuild:Bool = true) {
|
public static function saveAs(data:Dynamic, ?replacer:(key:Dynamic, value:Dynamic) -> Dynamic, ?space:String, ?options:SaveSubstate.SaveSubstateData, ?saveOptions:Map<String, Bool>, shouldBuild:Bool = true) { if (shouldBuild && instance != null) instance.buildChart();
|
||||||
FlxG.sound.play(Paths.sound('editors/save'));
|
|
||||||
if (shouldBuild && instance != null) instance.buildChart();
|
|
||||||
var cur = FlxG.state;
|
var cur = FlxG.state;
|
||||||
while(true) {
|
while(true) {
|
||||||
if (instance != null || cur.subState == null) return cur.openSubState(new SaveSubstate(Json.stringify(data, replacer, space), options, saveOptions));
|
if (instance != null || cur.subState == null) return cur.openSubState(new SaveSubstate(Json.stringify(data, replacer, space), options, saveOptions));
|
||||||
@@ -1562,7 +1554,7 @@ class Charter extends UIState {
|
|||||||
#if sys
|
#if sys
|
||||||
public static function saveTo(path:String, separateEvents:Bool = false, shouldBuild:Bool = true) {
|
public static function saveTo(path:String, separateEvents:Bool = false, shouldBuild:Bool = true) {
|
||||||
if (shouldBuild && instance != null) instance.buildChart();
|
if (shouldBuild && instance != null) instance.buildChart();
|
||||||
Chart.save(path, PlayState.SONG, __diff.toLowerCase(), {saveMetaInChart: false, saveLocalEvents: !separateEvents, prettyPrint: Options.editorCharterPrettyPrint});
|
Chart.save(PlayState.SONG, __diff.toLowerCase(), __variant, {saveMetaInChart: false, saveLocalEvents: !separateEvents, songFolder: path, prettyPrint: Options.editorCharterPrettyPrint});
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
@@ -1574,17 +1566,17 @@ class Charter extends UIState {
|
|||||||
else {undos = null; FlxG.switchState(new CharterSelection()); Charter.instance.__clearStatics();}
|
else {undos = null; FlxG.switchState(new CharterSelection()); Charter.instance.__clearStatics();}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _file_save_all(_) saveEverything();
|
function _file_save_all(_) {saveEverything(); FlxG.sound.play(Paths.sound('editors/save'));}
|
||||||
function _file_save(_) saveChart();
|
function _file_save(_) {saveChart(); FlxG.sound.play(Paths.sound('editors/save'));}
|
||||||
function _file_saveas(_) saveChartAs();
|
function _file_saveas(_) {saveChartAs(); FlxG.sound.play(Paths.sound('editors/save'));}
|
||||||
function _file_events_save(_) saveEvents();
|
function _file_events_save(_) {saveEvents(); FlxG.sound.play(Paths.sound('editors/save'));}
|
||||||
function _file_events_saveas(_) saveEventsAs();
|
function _file_events_saveas(_) {saveEventsAs(); FlxG.sound.play(Paths.sound('editors/save'));}
|
||||||
function _file_save_no_events(_) saveChart(true, false);
|
function _file_save_no_events(_) {saveChart(true, false); FlxG.sound.play(Paths.sound('editors/save'));}
|
||||||
function _file_saveas_no_events(_) saveChartAs(true, false);
|
function _file_saveas_no_events(_) {saveChartAs(true, false); FlxG.sound.play(Paths.sound('editors/save'));}
|
||||||
function _file_meta_save(_) saveMeta();
|
function _file_meta_save(_) {saveMeta(); FlxG.sound.play(Paths.sound('editors/save'));}
|
||||||
function _file_meta_saveas(_) saveMetaAs();
|
function _file_meta_saveas(_) {saveMetaAs(); FlxG.sound.play(Paths.sound('editors/save'));}
|
||||||
function _file_saveas_fnflegacy(_) saveLegacyChartAs();
|
function _file_saveas_fnflegacy(_) {saveLegacyChartAs(); FlxG.sound.play(Paths.sound('editors/save'));}
|
||||||
function _file_saveas_psych(_) savePsychChartAs();
|
function _file_saveas_psych(_) {savePsychChartAs(); FlxG.sound.play(Paths.sound('editors/save'));}
|
||||||
|
|
||||||
function _edit_copy(_, playSFX=true) {
|
function _edit_copy(_, playSFX=true) {
|
||||||
if (playSFX) FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_COPY_SOUND));
|
if (playSFX) FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_COPY_SOUND));
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class CharterMetaDataScreen extends UISubstateWindow {
|
|||||||
public var iconSprite:HealthIcon;
|
public var iconSprite:HealthIcon;
|
||||||
public var opponentModeCheckbox:UICheckbox;
|
public var opponentModeCheckbox:UICheckbox;
|
||||||
public var coopAllowedCheckbox:UICheckbox;
|
public var coopAllowedCheckbox:UICheckbox;
|
||||||
|
public var needsVoicesCheckbox:UICheckbox;
|
||||||
public var colorWheel:UIColorwheel;
|
public var colorWheel:UIColorwheel;
|
||||||
public var difficultiesTextBox:UITextBox;
|
public var difficultiesTextBox:UITextBox;
|
||||||
|
|
||||||
@@ -68,6 +69,9 @@ class CharterMetaDataScreen extends UISubstateWindow {
|
|||||||
denominatorStepper = new UINumericStepper(beatsPerMeasureStepper.x + 30 + 24, beatsPerMeasureStepper.y, Math.floor(16 / metadata.stepsPerBeat), 1, 0, 1, null, 54);
|
denominatorStepper = new UINumericStepper(beatsPerMeasureStepper.x + 30 + 24, beatsPerMeasureStepper.y, Math.floor(16 / metadata.stepsPerBeat), 1, 0, 1, null, 54);
|
||||||
add(denominatorStepper);
|
add(denominatorStepper);
|
||||||
|
|
||||||
|
needsVoicesCheckbox = new UICheckbox(beatsPerMeasureStepper.x + 100, beatsPerMeasureStepper.y + 6, translate("needsVoices"), metadata.needsVoices);
|
||||||
|
add(needsVoicesCheckbox);
|
||||||
|
|
||||||
add(title = new UIText(songNameTextBox.x, songNameTextBox.y + 10 + 46, 0, translate("menusData"), 28));
|
add(title = new UIText(songNameTextBox.x, songNameTextBox.y + 10 + 46, 0, translate("menusData"), 28));
|
||||||
|
|
||||||
displayNameTextBox = new UITextBox(title.x, title.y + title.height + 36, metadata.displayName);
|
displayNameTextBox = new UITextBox(title.x, title.y + title.height + 36, metadata.displayName);
|
||||||
@@ -146,20 +150,23 @@ class CharterMetaDataScreen extends UISubstateWindow {
|
|||||||
Reflect.setProperty(customVals, vals.propertyText.label.text, vals.valueText.label.text);
|
Reflect.setProperty(customVals, vals.propertyText.label.text, vals.valueText.label.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayState.SONG.meta = {
|
var meta = PlayState.SONG.meta;
|
||||||
name: songNameTextBox.label.text,
|
if (meta == null) meta = {name: songNameTextBox.label.text};
|
||||||
bpm: bpmStepper.value,
|
else meta.name = songNameTextBox.label.text;
|
||||||
beatsPerMeasure: Std.int(beatsPerMeasureStepper.value),
|
|
||||||
stepsPerBeat: Std.int(16 / denominatorStepper.value),
|
meta.bpm = bpmStepper.value;
|
||||||
displayName: displayNameTextBox.label.text,
|
meta.needsVoices = needsVoicesCheckbox.checked;
|
||||||
icon: iconTextBox.label.text,
|
meta.beatsPerMeasure = Std.int(beatsPerMeasureStepper.value);
|
||||||
color: colorWheel.curColor,
|
meta.stepsPerBeat = Std.int(16 / denominatorStepper.value);
|
||||||
opponentModeAllowed: opponentModeCheckbox.checked,
|
meta.displayName = displayNameTextBox.label.text;
|
||||||
coopAllowed: coopAllowedCheckbox.checked,
|
meta.icon = iconTextBox.label.text;
|
||||||
difficulties: [for (diff in difficultiesTextBox.label.text.split(",")) diff.trim()],
|
meta.color = colorWheel.curColor;
|
||||||
customValues: customVals,
|
meta.opponentModeAllowed = opponentModeCheckbox.checked;
|
||||||
};
|
meta.coopAllowed = coopAllowedCheckbox.checked;
|
||||||
|
meta.difficulties = [for (diff in difficultiesTextBox.label.text.split(",")) diff.trim()];
|
||||||
|
meta.customValues = customVals;
|
||||||
|
|
||||||
Charter.instance.updateBPMEvents();
|
Charter.instance.updateBPMEvents();
|
||||||
|
Charter.instance.vocals.muted = !needsVoicesCheckbox.checked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,55 +25,72 @@ class CharterSelectionScreen extends EditorTreeMenuScreen {
|
|||||||
public var songList:Array<String> = [];
|
public var songList:Array<String> = [];
|
||||||
public var curSong:ChartMetaData;
|
public var curSong:ChartMetaData;
|
||||||
|
|
||||||
inline public function makeChartOption(d:String, name:String):TextOption {
|
inline public function makeChartOption(d:String, v:String, name:String):TextOption {
|
||||||
return new TextOption(d, getID('acceptDifficulty'), () -> FlxG.switchState(new Charter(name, d)));
|
return new TextOption(d, getID('acceptDifficulty'), () -> FlxG.switchState(new Charter(name, d, v)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline public function makeVariationOption(s:ChartMetaData):TextOption {
|
||||||
|
return new TextOption(s.variant, getID('acceptVariation'), " >", () -> openSongOption(s, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function openSongOption(s:ChartMetaData, first = true) {
|
||||||
|
curSong = s;
|
||||||
|
|
||||||
|
var isVariant = s.variant != null && s.variant != '';
|
||||||
|
var screen = new EditorTreeMenuScreen((first || !isVariant) ? (s.name + (isVariant ? ' (${s.variant})' : '')) : s.variant, getID('selectDifficulty'));
|
||||||
|
|
||||||
|
for (d in s.difficulties) if (d != '') screen.add(makeChartOption(d, isVariant ? s.variant : null, s.name));
|
||||||
|
screen.add(new Separator());
|
||||||
|
for (v in s.variants) if (s.metas.get(v) != null) screen.add(makeVariationOption(s.metas.get(v)));
|
||||||
|
|
||||||
|
#if sys
|
||||||
|
screen.insert(0, new NewOption(getID('newDifficulty'), getID('newDifficultyDesc'), () -> {
|
||||||
|
parent.openSubState(new ChartCreationScreen(saveChart));
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!first) screen.curSelected = 1;
|
||||||
|
else {
|
||||||
|
cast(screen.members[0], NewOption).itemHeight = 120;
|
||||||
|
screen.insert(1, new NewOption(getID('newVariation'), getID('newVariationDesc'), () -> {
|
||||||
|
parent.openSubState(new VariationCreationScreen(s, saveSong));
|
||||||
|
}));
|
||||||
|
screen.curSelected = 2;
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
|
parent.addMenu(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function makeSongOption(s:ChartMetaData):IconOption {
|
public function makeSongOption(s:ChartMetaData):IconOption {
|
||||||
songList.push(s.name.toLowerCase());
|
songList.push(s.name.toLowerCase());
|
||||||
|
|
||||||
var opt = new IconOption(s.name, getID('acceptSong'), s.icon, () -> {
|
var opt = new IconOption(s.name, getID('acceptSong'), s.icon, () -> openSongOption(s, true));
|
||||||
curSong = s;
|
opt.suffix = " >";
|
||||||
|
|
||||||
var screen = new EditorTreeMenuScreen(s.name, getID('selectDifficulty'), [
|
|
||||||
for (d in s.difficulties) if (d != '') makeChartOption(d, s.name)
|
|
||||||
]);
|
|
||||||
|
|
||||||
#if sys
|
|
||||||
screen.insert(0, new NewOption(getID('newDifficulty'), getID('newDifficultyDesc'), () -> {
|
|
||||||
parent.openSubState(new ChartCreationScreen(saveChart));
|
|
||||||
}));
|
|
||||||
screen.curSelected = 1;
|
|
||||||
#end
|
|
||||||
|
|
||||||
parent.addMenu(screen);
|
|
||||||
});
|
|
||||||
opt.suffix = ' >';
|
|
||||||
opt.editorFlashColor = s.color.getDefault(FlxColor.WHITE);
|
opt.editorFlashColor = s.color.getDefault(FlxColor.WHITE);
|
||||||
|
|
||||||
return opt;
|
return opt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super('editor.chart.name', 'charterSelection.desc', 'charterSelection.', 'newSong', 'newSongDesc', () -> {
|
super('editor.chart.name', 'charterSelection.desc', 'charterSelection.', 'newSong', 'newSongDesc', #if sys () -> {
|
||||||
parent.openSubState(new SongCreationScreen(saveSong));
|
parent.openSubState(new SongCreationScreen(saveSong));
|
||||||
});
|
} #end);
|
||||||
freeplayList = FreeplaySonglist.get(false);
|
freeplayList = FreeplaySonglist.get(false);
|
||||||
|
|
||||||
for (i => s in freeplayList.songs) add(makeSongOption(s));
|
for (i => s in freeplayList.songs) add(makeSongOption(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if sys
|
#if sys
|
||||||
public function saveSong(creation:SongCreationData, ?callback:String -> SongCreationData -> Void) {
|
public function saveSong(creation:SongCreationData, ?callback:String -> Void) {
|
||||||
var songAlreadyExists:Bool = songList.contains(creation.meta.name.toLowerCase());
|
var variant = creation.meta.variant != null && creation.meta.variant != "" ? creation.meta.variant : null;
|
||||||
if (songAlreadyExists) {
|
if (variant != null && curSong != null ? curSong.metas.exists(variant) : songList.contains(creation.meta.name.toLowerCase())) {
|
||||||
parent.openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.song-exists-title"), TU.translate("chartCreation.warnings.song-exists-body"), [
|
parent.openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.song-exists-title"), TU.translate("chartCreation.warnings.song-exists-body"), [
|
||||||
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}},
|
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}},
|
||||||
]));
|
]));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var songFolder:String = '${Paths.getAssetsRoot()}/songs/${creation.meta.name}';
|
var songFolder:String = '${Paths.getAssetsRoot()}/songs/${variant != null && curSong != null ? curSong.name : creation.meta.name}';
|
||||||
|
|
||||||
#if sys
|
#if sys
|
||||||
// Make Directories
|
// Make Directories
|
||||||
@@ -82,24 +99,37 @@ class CharterSelectionScreen extends EditorTreeMenuScreen {
|
|||||||
sys.FileSystem.createDirectory('$songFolder/charts');
|
sys.FileSystem.createDirectory('$songFolder/charts');
|
||||||
|
|
||||||
// Save Files
|
// Save Files
|
||||||
CoolUtil.safeSaveFile('$songFolder/meta.json', Chart.makeMetaSaveable(creation.meta));
|
var instSuffix = creation.meta.instSuffix != null ? creation.meta.instSuffix : '', vocalsSuffix = creation.meta.vocalsSuffix != null ? creation.meta.vocalsSuffix : '';
|
||||||
if (creation.instBytes != null) sys.io.File.saveBytes('$songFolder/song/Inst.${Flags.SOUND_EXT}', creation.instBytes);
|
CoolUtil.safeSaveFile('$songFolder/meta${variant != null ? "-" + variant : ""}.json', Json.stringify(Chart.filterMetaForSaving(creation.meta), null, Flags.JSON_PRETTY_PRINT));
|
||||||
if (creation.voicesBytes != null) sys.io.File.saveBytes('$songFolder/song/Voices.${Flags.SOUND_EXT}', creation.voicesBytes);
|
if (creation.instBytes != null) sys.io.File.saveBytes('$songFolder/song/Inst$instSuffix.${Flags.SOUND_EXT}', creation.instBytes);
|
||||||
|
if (creation.voicesBytes != null) sys.io.File.saveBytes('$songFolder/song/Voices$vocalsSuffix.${Flags.SOUND_EXT}', creation.voicesBytes);
|
||||||
|
|
||||||
if (creation.playerVocals != null) sys.io.File.saveBytes('$songFolder/song/Voices-Player.${Flags.SOUND_EXT}', creation.playerVocals);
|
if (creation.playerVocals != null) sys.io.File.saveBytes('$songFolder/song/Voices-Player$vocalsSuffix.${Flags.SOUND_EXT}', creation.playerVocals);
|
||||||
if (creation.oppVocals != null) sys.io.File.saveBytes('$songFolder/song/Voices-Opponent.${Flags.SOUND_EXT}', creation.oppVocals);
|
if (creation.oppVocals != null) sys.io.File.saveBytes('$songFolder/song/Voices-Opponent$vocalsSuffix.${Flags.SOUND_EXT}', creation.oppVocals);
|
||||||
#end
|
#end
|
||||||
|
|
||||||
if (callback != null) callback(songFolder, creation);
|
if (callback != null) callback(songFolder);
|
||||||
|
|
||||||
// Add to List
|
// Add to List
|
||||||
freeplayList.songs.insert(0, creation.meta);
|
if (variant != null && curSong != null) {
|
||||||
insert(1, makeSongOption(creation.meta));
|
if (curSong.variants == null) curSong.variants = [];
|
||||||
|
if (!curSong.variants.contains(variant)) curSong.variants.push(variant);
|
||||||
|
|
||||||
|
curSong.metas.set(variant, creation.meta);
|
||||||
|
|
||||||
|
parent.tree.last().add(makeVariationOption(creation.meta));
|
||||||
|
|
||||||
|
var metaPath = '$songFolder/meta${curSong.variant != null && curSong.variant == "" ? "-" + curSong.variant : ""}.json';
|
||||||
|
CoolUtil.safeSaveFile(metaPath, Chart.makeMetaSaveable(curSong));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
freeplayList.songs.insert(0, creation.meta);
|
||||||
|
insert(1, makeSongOption(creation.meta));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function saveChart(name:String, data:ChartData) {
|
public function saveChart(name:String, data:ChartData) {
|
||||||
var difficultyAlreadyExists:Bool = curSong.difficulties.contains(name);
|
if (curSong.difficulties.contains(name)) {
|
||||||
if (difficultyAlreadyExists) {
|
|
||||||
parent.openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.chart-exists-title"), TU.translate("chartCreation.warnings.chart-exists-body"), [
|
parent.openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.chart-exists-title"), TU.translate("chartCreation.warnings.chart-exists-body"), [
|
||||||
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}},
|
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}},
|
||||||
]));
|
]));
|
||||||
@@ -113,14 +143,15 @@ class CharterSelectionScreen extends EditorTreeMenuScreen {
|
|||||||
|
|
||||||
// Add to List
|
// Add to List
|
||||||
curSong.difficulties.push(name);
|
curSong.difficulties.push(name);
|
||||||
parent.tree.last().insert(parent.tree.last().length - 1, makeChartOption(name, curSong.name));
|
|
||||||
|
var screen = parent.tree.last();
|
||||||
|
var idx = 0;
|
||||||
|
while (!(screen.members[idx] is Separator)) idx++;
|
||||||
|
screen.insert(idx, makeChartOption(name, curSong.variant != null && curSong.variant != "" ? curSong.variant : null, curSong.name));
|
||||||
|
|
||||||
// Add to Meta
|
// Add to Meta
|
||||||
var meta = Json.parse(sys.io.File.getContent('$songFolder/meta.json'));
|
var metaPath = '$songFolder/meta${curSong.variant != null && curSong.variant == "" ? "-" + curSong.variant : ""}.json';
|
||||||
if (meta.difficulties != null && !meta.difficulties.contains(name)) {
|
CoolUtil.safeSaveFile(metaPath, Chart.makeMetaSaveable(curSong));
|
||||||
meta.difficulties.push(name);
|
|
||||||
CoolUtil.safeSaveFile('$songFolder/meta.json', Chart.makeMetaSaveable(meta));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ class CharterStrumline extends UISprite {
|
|||||||
var maxRow = Math.floor((icons.length-1) / 4) + 1;
|
var maxRow = Math.floor((icons.length-1) / 4) + 1;
|
||||||
for (i=>icon in icons) {
|
for (i=>icon in icons) {
|
||||||
var healthIcon = new HealthIcon(Character.getIconFromCharName(icon));
|
var healthIcon = new HealthIcon(Character.getIconFromCharName(icon));
|
||||||
healthIcon.scale.x = healthIcon.scale.y = Math.max((0.6 - (icons.length / 20)), 0.35);
|
healthIcon.scale.x = healthIcon.scale.y = Math.max((0.6 - (icons.length / 20)), 0.35) * (150 / Math.max(healthIcon.frameWidth, healthIcon.frameHeight));
|
||||||
healthIcon.updateHitbox();
|
healthIcon.updateHitbox();
|
||||||
healthIcon.x = FlxMath.lerp(0, Math.min(icons.length * 20, 120), (maxCol-1 != 0 ? (i % 4) / (maxCol-1) : 0));
|
healthIcon.x = FlxMath.lerp(0, Math.min(icons.length * 20, 120), (maxCol-1 != 0 ? (i % 4) / (maxCol-1) : 0));
|
||||||
healthIcon.y = (draggable ? 14 : 7) + FlxMath.lerp(0, Math.min(maxRow * 15, 60), (maxRow-1 != 0 ? Math.floor(i / 4) / (maxRow-1) : 0));
|
healthIcon.y = (draggable ? 14 : 7) + FlxMath.lerp(0, Math.min(maxRow * 15, 60), (maxRow-1 != 0 ? Math.floor(i / 4) / (maxRow-1) : 0));
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ class CharterStrumlineScreen extends UISubstateWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vocalsSuffixDropDown = new UIDropDown(typeDropdown.x, hudScaleStepper.y + 128, 200, 32, suffixList, strumLine.vocalsSuffix != null && strumLine.vocalsSuffix != "" ? suffixList.indexOf(strumLine.vocalsSuffix) : 0);
|
vocalsSuffixDropDown = new UIDropDown(typeDropdown.x, hudScaleStepper.y + 128, 200, 32, suffixList, strumLine.vocalsSuffix != null && strumLine.vocalsSuffix != "" && Assets.exists(Paths.voices(Charter.__song.toLowerCase(), "", strumLine.vocalsSuffix)) ? suffixList.indexOf(strumLine.vocalsSuffix) : 0);
|
||||||
add(vocalsSuffixDropDown);
|
add(vocalsSuffixDropDown);
|
||||||
addLabelOn(vocalsSuffixDropDown, TU.translate("charterStrumLine.vocalSuffix"));
|
addLabelOn(vocalsSuffixDropDown, TU.translate("charterStrumLine.vocalSuffix"));
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ package funkin.editors.charter;
|
|||||||
import flixel.group.FlxGroup;
|
import flixel.group.FlxGroup;
|
||||||
import flixel.text.FlxText.FlxTextFormat;
|
import flixel.text.FlxText.FlxTextFormat;
|
||||||
import flixel.text.FlxText.FlxTextFormatMarkerPair;
|
import flixel.text.FlxText.FlxTextFormatMarkerPair;
|
||||||
|
import funkin.backend.chart.Chart;
|
||||||
import funkin.backend.chart.ChartData;
|
import funkin.backend.chart.ChartData;
|
||||||
import funkin.backend.chart.FNFLegacyParser.SwagSong;
|
import funkin.backend.chart.FNFLegacyParser.SwagSong;
|
||||||
import funkin.backend.chart.PsychParser;
|
import funkin.backend.chart.PsychParser;
|
||||||
import funkin.backend.chart.VSliceParser;
|
import funkin.backend.chart.VSliceParser;
|
||||||
|
import funkin.backend.utils.ZipUtil;
|
||||||
import funkin.backend.utils.ZipUtil.ZipReader;
|
import funkin.backend.utils.ZipUtil.ZipReader;
|
||||||
import funkin.game.HealthIcon;
|
import funkin.game.HealthIcon;
|
||||||
import haxe.Json;
|
import haxe.Json;
|
||||||
@@ -22,7 +24,7 @@ typedef SongCreationData = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SongCreationScreen extends UISubstateWindow {
|
class SongCreationScreen extends UISubstateWindow {
|
||||||
private var onSave:Null<SongCreationData> -> Null<String -> SongCreationData -> Void> -> Void = null;
|
private var onSave:Null<SongCreationData> -> Null<String -> Void> -> Void = null;
|
||||||
|
|
||||||
public var songNameTextBox:UITextBox;
|
public var songNameTextBox:UITextBox;
|
||||||
public var bpmStepper:UINumericStepper;
|
public var bpmStepper:UINumericStepper;
|
||||||
@@ -71,7 +73,7 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
|
|
||||||
public var curPage:Int = 0;
|
public var curPage:Int = 0;
|
||||||
|
|
||||||
public function new(?onSave:SongCreationData -> Null<String -> SongCreationData -> Void> -> Void) {
|
public function new(?onSave:SongCreationData -> Null<String -> Void> -> Void) {
|
||||||
super();
|
super();
|
||||||
if (onSave != null) this.onSave = onSave;
|
if (onSave != null) this.onSave = onSave;
|
||||||
}
|
}
|
||||||
@@ -244,7 +246,7 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
var pages = isImporting ? importPages : pages;
|
var pages = isImporting ? importPages : pages;
|
||||||
if (curPage == pages.length-1) {
|
if (curPage == pages.length-1) {
|
||||||
saveSongInfo();
|
saveSongInfo();
|
||||||
close();
|
if (subState == null) close();
|
||||||
} else {
|
} else {
|
||||||
curPage++;
|
curPage++;
|
||||||
refreshPages();
|
refreshPages();
|
||||||
@@ -295,7 +297,7 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
|
|
||||||
if (curPage == 1) {
|
if (curPage == 1) {
|
||||||
importInstExplorer.selectable = importVoicesExplorer.selectable = !project;
|
importInstExplorer.selectable = importVoicesExplorer.selectable = !project;
|
||||||
saveButton.selectable = project ? true : (importInstExplorer.file != null);
|
saveButton.selectable = #if TEST_BUILD true #else project ? true : (importInstExplorer.file != null) #end;
|
||||||
} else if (curPage == 2) {
|
} else if (curPage == 2) {
|
||||||
importIdTextBox.selectable = !project;
|
importIdTextBox.selectable = !project;
|
||||||
importChartFile.fileType = project ? "fnfc" : "json";
|
importChartFile.fileType = project ? "fnfc" : "json";
|
||||||
@@ -355,16 +357,23 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
iconSprite.scrollFactor.set(1, 1);
|
iconSprite.scrollFactor.set(1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for variations
|
||||||
|
function formatMeta(meta:ChartMetaData):ChartMetaData
|
||||||
|
return Chart.defaultChartMetaFields(meta);
|
||||||
|
|
||||||
|
function getChartSavePath(meta:ChartMetaData, diff:String):String
|
||||||
|
return 'charts/${meta.variant != null && meta.variant != "" ? meta.variant + "/" : ""}$diff.json';
|
||||||
|
|
||||||
function saveSongInfo() {
|
function saveSongInfo() {
|
||||||
if (isImporting)
|
if (isImporting)
|
||||||
{
|
{
|
||||||
try switch(engineDropdown.index)
|
try switch(engineDropdown.index)
|
||||||
{
|
{
|
||||||
case 0 /*"V-Slice Project (.fnfc)"*/:
|
case 2 /*"V-Slice Project (.fnfc)"*/:
|
||||||
var files:Map<String, Any> = [];
|
var files:Map<String, Any> = [];
|
||||||
for (field in new ZipReader(new BytesInput(importChartFile.file)).read()) {
|
for (field in new ZipReader(new BytesInput(importChartFile.file)).read()) {
|
||||||
var fileName = field.fileName;
|
var fileName = field.fileName;
|
||||||
var fileContent = field.data;
|
var fileContent = ZipUtil.unzip(field);
|
||||||
files.set(fileName, fileContent);
|
files.set(fileName, fileContent);
|
||||||
}
|
}
|
||||||
saveFromVSlice(files);
|
saveFromVSlice(files);
|
||||||
@@ -378,35 +387,37 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
saveFromVSlice(files, songId);
|
saveFromVSlice(files, songId);
|
||||||
default /*"Psych/Legacy FNF"*/:
|
default /*"Psych/Legacy FNF"*/:
|
||||||
var songId = importIdTextBox.label.text;
|
var songId = importIdTextBox.label.text;
|
||||||
var oldChart:SwagSong = Json.parse(cast importChartFile.file);
|
var oldChart:SwagSong = Chart.cleanSongData(Json.parse(cast importChartFile.file));
|
||||||
var base:ChartData = {
|
var base:ChartData = {
|
||||||
strumLines: [],
|
strumLines: [],
|
||||||
noteTypes: [],
|
noteTypes: [],
|
||||||
events: [],
|
events: [],
|
||||||
meta: {name: null},
|
meta: {name: songId},
|
||||||
scrollSpeed: Flags.DEFAULT_SCROLL_SPEED,
|
scrollSpeed: Flags.DEFAULT_SCROLL_SPEED,
|
||||||
stage: Flags.DEFAULT_STAGE,
|
stage: Flags.DEFAULT_STAGE,
|
||||||
codenameChart: true
|
codenameChart: true
|
||||||
};
|
};
|
||||||
PsychParser.parse(oldChart, base);
|
PsychParser.parse(oldChart, base);
|
||||||
|
var meta = formatMeta({
|
||||||
|
name: songId,
|
||||||
|
difficulties: ['normal'],
|
||||||
|
bpm: oldChart.bpm,
|
||||||
|
beatsPerMeasure: oldChart.beatsPerMeasure,
|
||||||
|
stepsPerBeat: oldChart.stepsPerBeat,
|
||||||
|
displayName: oldChart.song
|
||||||
|
});
|
||||||
if (onSave != null) onSave({
|
if (onSave != null) onSave({
|
||||||
meta: {
|
meta: meta,
|
||||||
name: songId,
|
|
||||||
difficulties: [songId],
|
|
||||||
bpm: oldChart.bpm,
|
|
||||||
beatsPerMeasure: oldChart.beatsPerMeasure,
|
|
||||||
stepsPerBeat: oldChart.stepsPerBeat,
|
|
||||||
displayName: oldChart.song
|
|
||||||
},
|
|
||||||
instBytes: importInstExplorer.file,
|
instBytes: importInstExplorer.file,
|
||||||
voicesBytes: importVoicesExplorer.file,
|
voicesBytes: importVoicesExplorer.file,
|
||||||
}, (songFolder:String, creation:SongCreationData) -> {
|
}, (songFolder:String) -> {
|
||||||
#if sys
|
#if sys
|
||||||
CoolUtil.safeSaveFile('$songFolder/charts/${songId}.json', Json.stringify(base, Flags.JSON_PRETTY_PRINT));
|
CoolUtil.safeSaveFile('$songFolder/${getChartSavePath(meta, "normal")}', Json.stringify(base, Flags.JSON_PRETTY_PRINT));
|
||||||
#end
|
#end
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e:haxe.Exception) {
|
||||||
openSubState(new UIWarningSubstate("Importing Song/Charts: Error!", Std.string(e), [
|
trace(e.stack, e.message);
|
||||||
|
openSubState(new UIWarningSubstate("Importing Song/Charts: Error!", e.details(), [
|
||||||
{label: "Ok", color: 0xFFFF0000, onClick: function(t) {}}
|
{label: "Ok", color: 0xFFFF0000, onClick: function(t) {}}
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
@@ -414,7 +425,7 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
for (stepper in [bpmStepper, beatsPerMeasureStepper, denominatorStepper])
|
for (stepper in [bpmStepper, beatsPerMeasureStepper, denominatorStepper])
|
||||||
@:privateAccess stepper.__onChange(stepper.label.text);
|
@:privateAccess stepper.__onChange(stepper.label.text);
|
||||||
|
|
||||||
var meta:ChartMetaData = {
|
var meta:ChartMetaData = formatMeta({
|
||||||
name: songNameTextBox.label.text,
|
name: songNameTextBox.label.text,
|
||||||
bpm: bpmStepper.value,
|
bpm: bpmStepper.value,
|
||||||
beatsPerMeasure: Std.int(beatsPerMeasureStepper.value),
|
beatsPerMeasure: Std.int(beatsPerMeasureStepper.value),
|
||||||
@@ -424,8 +435,8 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
color: colorWheel.curColor,
|
color: colorWheel.curColor,
|
||||||
opponentModeAllowed: opponentModeCheckbox.checked,
|
opponentModeAllowed: opponentModeCheckbox.checked,
|
||||||
coopAllowed: coopAllowedCheckbox.checked,
|
coopAllowed: coopAllowedCheckbox.checked,
|
||||||
difficulties: [for (diff in difficultiesTextBox.label.text.split(",")) diff.trim()],
|
difficulties: [for (diff in difficultiesTextBox.label.text.split(",")) diff.trim()]
|
||||||
};
|
});
|
||||||
|
|
||||||
if (onSave != null) onSave({
|
if (onSave != null) onSave({
|
||||||
meta: meta,
|
meta: meta,
|
||||||
@@ -441,19 +452,23 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
var vslicechart:NewSwagSong = Json.parse(files.get('${songId}-chart.json'));
|
var vslicechart:NewSwagSong = Json.parse(files.get('${songId}-chart.json'));
|
||||||
var playData = vslicemeta.playData;
|
var playData = vslicemeta.playData;
|
||||||
|
|
||||||
var meta:ChartMetaData = {name: songId};
|
var meta:ChartMetaData = formatMeta({name: songId, needsVoices: files.get('Voices.${Flags.SOUND_EXT}') != null});
|
||||||
var diffCharts:Array<ChartDataWithInfo> = [];
|
var diffCharts:Array<ChartDataWithInfo> = [], events:Array<ChartEvent> = null;
|
||||||
VSliceParser.parse(vslicemeta, vslicechart, meta, diffCharts, songId);
|
VSliceParser.parse(vslicemeta, vslicechart, meta, diffCharts, songId);
|
||||||
|
|
||||||
|
if (diffCharts.length != 0) events = diffCharts[0].chart.events;
|
||||||
|
for (diff in diffCharts) diff.chart.events = [];
|
||||||
|
|
||||||
if (onSave != null) onSave({
|
if (onSave != null) onSave({
|
||||||
meta: meta,
|
meta: meta,
|
||||||
instBytes: files.get('Inst.${Flags.SOUND_EXT}'),
|
instBytes: files.get('Inst.${Flags.SOUND_EXT}'),
|
||||||
voicesBytes: files.get('Voices.${Flags.SOUND_EXT}'), //it may exist
|
voicesBytes: files.get('Voices.${Flags.SOUND_EXT}'), //it may exist
|
||||||
playerVocals: files.get('Voices-${playData.characters.playerVocals != null ? playData.characters.playerVocals[0] : playData.characters.player}.${Flags.SOUND_EXT}'),
|
playerVocals: files.get('Voices-${playData.characters.playerVocals != null ? playData.characters.playerVocals[0] : playData.characters.player}.${Flags.SOUND_EXT}'),
|
||||||
oppVocals: files.get('Voices-${playData.characters.opponentVocals != null ? playData.characters.opponentVocals[0] : playData.characters.opponent}.${Flags.SOUND_EXT}'),
|
oppVocals: files.get('Voices-${playData.characters.opponentVocals != null ? playData.characters.opponentVocals[0] : playData.characters.opponent}.${Flags.SOUND_EXT}'),
|
||||||
}, (songFolder:String, creation:SongCreationData) -> {
|
}, (songFolder:String) -> {
|
||||||
#if sys
|
#if sys
|
||||||
for (diff in diffCharts) CoolUtil.safeSaveFile('$songFolder/charts/${diff.diffName}.json', Json.stringify(diff.chart, Flags.JSON_PRETTY_PRINT));
|
for (diff in diffCharts) CoolUtil.safeSaveFile('$songFolder/${getChartSavePath(meta, diff.diffName)}', Json.stringify(diff.chart, Flags.JSON_PRETTY_PRINT));
|
||||||
|
if (events != null) CoolUtil.safeSaveFile('$songFolder/events${meta.variant != null && meta.variant != "" ? "-" + meta.variant : ""}.json', Json.stringify({events: events}, Flags.JSON_PRETTY_PRINT));
|
||||||
#end
|
#end
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package funkin.editors.charter;
|
||||||
|
|
||||||
|
import flixel.text.FlxText.FlxTextFormat;
|
||||||
|
import flixel.text.FlxText.FlxTextFormatMarkerPair;
|
||||||
|
import funkin.backend.chart.ChartData;
|
||||||
|
import funkin.editors.charter.SongCreationScreen;
|
||||||
|
|
||||||
|
class VariationCreationScreen extends SongCreationScreen {
|
||||||
|
public var parentMeta:ChartMetaData;
|
||||||
|
|
||||||
|
public function new(parent:ChartMetaData, ?onSave:SongCreationData -> Null<String -> Void> -> Void) {
|
||||||
|
super(onSave);
|
||||||
|
this.parentMeta = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
override function create() {
|
||||||
|
super.create();
|
||||||
|
|
||||||
|
songNameTextBox.label.text = translateMeta("variation");
|
||||||
|
cast(songNameTextBox.members[songNameTextBox.members.length - 1], UIText).text = translateMeta("variation");
|
||||||
|
|
||||||
|
cast(importIdTextBox.members[importIdTextBox.members.length - 1], UIText).applyMarkup(
|
||||||
|
translateMeta("variation"),
|
||||||
|
[new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFAD1212), "$")]
|
||||||
|
);
|
||||||
|
|
||||||
|
bpmStepper.value = parentMeta.bpm;
|
||||||
|
beatsPerMeasureStepper.value = parentMeta.beatsPerMeasure;
|
||||||
|
denominatorStepper.value = Std.int(16 / parentMeta.stepsPerBeat);
|
||||||
|
displayNameTextBox.label.text = parentMeta.displayName;
|
||||||
|
iconTextBox.label.text = parentMeta.icon;
|
||||||
|
opponentModeCheckbox.checked = parentMeta.opponentModeAllowed;
|
||||||
|
coopAllowedCheckbox.checked = parentMeta.coopAllowed;
|
||||||
|
colorWheel.setColor(parentMeta.color);
|
||||||
|
difficultiesTextBox.label.text = parentMeta.difficulties.join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
|
override function formatMeta(meta:ChartMetaData):ChartMetaData {
|
||||||
|
meta.variant = meta.name;
|
||||||
|
meta.vocalsSuffix = meta.instSuffix = '-${meta.variant}';
|
||||||
|
meta.name = parentMeta.name;
|
||||||
|
meta.icon = parentMeta.icon;
|
||||||
|
meta.color = parentMeta.color;
|
||||||
|
return super.formatMeta(meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,11 +40,11 @@ class StageCreationScreen extends UISubstateWindow {
|
|||||||
var stageInfo:UIText;
|
var stageInfo:UIText;
|
||||||
add(stageInfo = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, translate("title"), 28));
|
add(stageInfo = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, translate("title"), 28));
|
||||||
|
|
||||||
add(stageNameTextBox = new UITextBox(stageInfo.x, stageInfo.y + stageInfo.height + 36, translate("stage-name")));
|
add(stageNameTextBox = new UITextBox(stageInfo.x, stageInfo.y + stageInfo.height + 36, translate("stageName")));
|
||||||
addLabelOn(stageNameTextBox, translate("stage-name"));
|
addLabelOn(stageNameTextBox, translate("stageName"));
|
||||||
|
|
||||||
add(stagePathTextBox = new UITextBox(stageNameTextBox.x + 320 + 26, stageNameTextBox.y, translate("stage-path")));
|
add(stagePathTextBox = new UITextBox(stageNameTextBox.x + 320 + 26, stageNameTextBox.y, translate("stagePath")));
|
||||||
addLabelOn(stagePathTextBox, translate("stage-path"));
|
addLabelOn(stagePathTextBox, translate("stagePath"));
|
||||||
|
|
||||||
add(saveButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20 - 125, windowSpr.y + windowSpr.bHeight - 16 - 32, TU.translate("editor.saveClose"), function() {
|
add(saveButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20 - 125, windowSpr.y + windowSpr.bHeight - 16 - 32, TU.translate("editor.saveClose"), function() {
|
||||||
saveStageInfo();
|
saveStageInfo();
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ class UIColorwheel extends UISliceSprite {
|
|||||||
hue = curColor.hue; saturation = curColor.saturation; brightness = curColor.brightness;
|
hue = curColor.hue; saturation = curColor.saturation; brightness = curColor.brightness;
|
||||||
|
|
||||||
colorPickerShader = new CustomShader("engine/colorPicker");
|
colorPickerShader = new CustomShader("engine/colorPicker");
|
||||||
colorPickerShader.hset("hue", hue);
|
|
||||||
|
|
||||||
colorPicker = new FlxSprite(x + 12.5, (y + 125/2) - (100/2)).makeGraphic(100, 100, FlxColor.TRANSPARENT);
|
colorPicker = new FlxSprite(x + 12.5, (y + 125/2) - (100/2)).makeGraphic(100, 100, FlxColor.TRANSPARENT);
|
||||||
colorPicker.drawRoundRect(0, 0, 100, 100, 10, 10, FlxColor.WHITE);
|
colorPicker.drawRoundRect(0, 0, 100, 100, 10, 10, FlxColor.WHITE);
|
||||||
@@ -91,6 +90,11 @@ class UIColorwheel extends UISliceSprite {
|
|||||||
updateWheel(false);
|
updateWheel(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setColor(color:FlxColor) {
|
||||||
|
hue = curColor.hue; saturation = curColor.saturation; brightness = curColor.brightness;
|
||||||
|
updateWheel(false);
|
||||||
|
}
|
||||||
|
|
||||||
inline function updateColorPickerSelector()
|
inline function updateColorPickerSelector()
|
||||||
colorPickerSelector.selector.setPosition(colorPicker.x + (colorPicker.width *saturation) - 8, colorPicker.y + (colorPicker.height + (colorPicker.height * -brightness))- 8);
|
colorPickerSelector.selector.setPosition(colorPicker.x + (colorPicker.width *saturation) - 8, colorPicker.y + (colorPicker.height + (colorPicker.height * -brightness))- 8);
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ class UIUtil {
|
|||||||
} else if (member is UITextBox) @:privateAccess {
|
} else if (member is UITextBox) @:privateAccess {
|
||||||
var textbox:UITextBox = cast member;
|
var textbox:UITextBox = cast member;
|
||||||
if (textbox.__wasFocused) {
|
if (textbox.__wasFocused) {
|
||||||
textbox.onChange(textbox.label.text);
|
if (textbox.onChange != null) textbox.onChange(textbox.label.text);
|
||||||
textbox.__wasFocused = false;
|
textbox.__wasFocused = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ class GameOverSubstate extends MusicBeatSubstate
|
|||||||
|
|
||||||
lossSFX = FlxG.sound.play(Paths.sound(lossSFXName));
|
lossSFX = FlxG.sound.play(Paths.sound(lossSFXName));
|
||||||
Conductor.changeBPM(gameOverSongBPM);
|
Conductor.changeBPM(gameOverSongBPM);
|
||||||
|
cancelConductorUpdate = true;
|
||||||
|
|
||||||
DiscordUtil.call("onGameOver", []);
|
DiscordUtil.call("onGameOver", []);
|
||||||
gameoverScript.call("postCreate");
|
gameoverScript.call("postCreate");
|
||||||
@@ -106,22 +107,23 @@ class GameOverSubstate extends MusicBeatSubstate
|
|||||||
|
|
||||||
if (!isEnding && ((!lossSFX.playing) || (character.getAnimName() == "firstDeath" && character.isAnimFinished())) && (FlxG.sound.music == null || !FlxG.sound.music.playing))
|
if (!isEnding && ((!lossSFX.playing) || (character.getAnimName() == "firstDeath" && character.isAnimFinished())) && (FlxG.sound.music == null || !FlxG.sound.music.playing))
|
||||||
{
|
{
|
||||||
|
var event = new CancellableEvent();
|
||||||
|
gameoverScript.call("deathStart", [event]);
|
||||||
|
|
||||||
|
if (event.cancelled) return;
|
||||||
|
|
||||||
CoolUtil.playMusic(Paths.music(gameOverSong), false, 1, true, Flags.DEFAULT_BPM);
|
CoolUtil.playMusic(Paths.music(gameOverSong), false, 1, true, Flags.DEFAULT_BPM);
|
||||||
beatHit(0);
|
character.playAnim("deathLoop", true, DANCE);
|
||||||
|
cancelConductorUpdate = false;
|
||||||
|
|
||||||
|
gameoverScript.call("postDeathStart");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override function beatHit(curBeat:Int)
|
override function beatHit(curBeat:Int)
|
||||||
{
|
{
|
||||||
super.beatHit(curBeat);
|
super.beatHit(curBeat);
|
||||||
|
|
||||||
gameoverScript.call("beatHit", [curBeat]);
|
gameoverScript.call("beatHit", [curBeat]);
|
||||||
|
|
||||||
if (__cancelDefault)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (FlxG.sound.music != null && FlxG.sound.music.playing)
|
|
||||||
character.playAnim("deathLoop", true, DANCE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override function stepHit(curStep:Int)
|
override function stepHit(curStep:Int)
|
||||||
|
|||||||
@@ -178,9 +178,6 @@ class HealthIcon extends FunkinSprite
|
|||||||
|
|
||||||
loadGraphic(iconAsset, true, Std.int(Math.min(iconSize, assetW)), Std.int(Math.min(iconSize, assetH)));
|
loadGraphic(iconAsset, true, Std.int(Math.min(iconSize, assetW)), Std.int(Math.min(iconSize, assetH)));
|
||||||
|
|
||||||
setGraphicSize(150);
|
|
||||||
updateHitbox();
|
|
||||||
|
|
||||||
animation.add(char, [for(i in 0...iconAmt) i], 0, false, isPlayer != iconIsPlayer);
|
animation.add(char, [for(i in 0...iconAmt) i], 0, false, isPlayer != iconIsPlayer);
|
||||||
animation.play(char);
|
animation.play(char);
|
||||||
}
|
}
|
||||||
@@ -388,7 +385,7 @@ class HealthIcon extends FunkinSprite
|
|||||||
}) + sprTrackerOffset.x, sprTracker.y + sprTrackerOffset.y);
|
}) + sprTrackerOffset.x, sprTracker.y + sprTrackerOffset.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animation.curAnim != null || (this.animated && animateAtlas != null)) {
|
if (animation.curAnim != null || this.animated) {
|
||||||
var data = getIconAnim(health);
|
var data = getIconAnim(health);
|
||||||
var localAnimState = data.animState;
|
var localAnimState = data.animState;
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,13 @@ class Note extends FlxSprite
|
|||||||
*/
|
*/
|
||||||
public var nextSustain:Note;
|
public var nextSustain:Note;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parent of the sustain.
|
||||||
|
*
|
||||||
|
* If this note is not sustain, this will be null.
|
||||||
|
*/
|
||||||
|
public var sustainParent:Null<Note>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the splash.
|
* Name of the splash.
|
||||||
*/
|
*/
|
||||||
@@ -125,6 +132,10 @@ class Note extends FlxSprite
|
|||||||
for(field in Reflect.fields(noteData)) if(!DEFAULT_FIELDS.contains(field))
|
for(field in Reflect.fields(noteData)) if(!DEFAULT_FIELDS.contains(field))
|
||||||
this.extra.set(field, Reflect.field(noteData, field));
|
this.extra.set(field, Reflect.field(noteData, field));
|
||||||
|
|
||||||
|
// work around to set the `sustainParent`
|
||||||
|
if (isSustainNote)
|
||||||
|
sustainParent = prevNote.isSustainNote ? prevNote.sustainParent : prevNote;
|
||||||
|
|
||||||
x += 50;
|
x += 50;
|
||||||
// MAKE SURE ITS DEFINITELY OFF SCREEN?
|
// MAKE SURE ITS DEFINITELY OFF SCREEN?
|
||||||
y -= 2000;
|
y -= 2000;
|
||||||
|
|||||||
@@ -61,10 +61,18 @@ class PlayState extends MusicBeatState
|
|||||||
* The remaining songs in the Story Mode playlist.
|
* The remaining songs in the Story Mode playlist.
|
||||||
*/
|
*/
|
||||||
public static var storyPlaylist:Array<String> = [];
|
public static var storyPlaylist:Array<String> = [];
|
||||||
|
/**
|
||||||
|
* The remaining variations to play with the Story Mode
|
||||||
|
*/
|
||||||
|
public static var storyVariations:Array<String> = [];
|
||||||
/**
|
/**
|
||||||
* The selected difficulty name.
|
* The selected difficulty name.
|
||||||
*/
|
*/
|
||||||
public static var difficulty:String = Flags.DEFAULT_DIFFICULTY;
|
public static var difficulty:String = Flags.DEFAULT_DIFFICULTY;
|
||||||
|
/**
|
||||||
|
* The selected variation name. (It can be null)
|
||||||
|
*/
|
||||||
|
public static var variation:Null<String>;
|
||||||
/**
|
/**
|
||||||
* Whenever the week is coming from the mods folder or not.
|
* Whenever the week is coming from the mods folder or not.
|
||||||
*/
|
*/
|
||||||
@@ -362,6 +370,10 @@ class PlayState extends MusicBeatState
|
|||||||
* Speed at which the game camera zoom lerps to.
|
* Speed at which the game camera zoom lerps to.
|
||||||
*/
|
*/
|
||||||
public var camGameZoomLerp:Float = Flags.DEFAULT_CAM_ZOOM_LERP;
|
public var camGameZoomLerp:Float = Flags.DEFAULT_CAM_ZOOM_LERP;
|
||||||
|
/**
|
||||||
|
* The current multiplier for game camera zooming.
|
||||||
|
*/
|
||||||
|
public var camGameZoomMult:Float = Flags.DEFAULT_CAM_ZOOM_MULT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Camera zoom at which the hud lerps to.
|
* Camera zoom at which the hud lerps to.
|
||||||
@@ -371,6 +383,21 @@ class PlayState extends MusicBeatState
|
|||||||
* Speed at which the hud camera zoom lerps to.
|
* Speed at which the hud camera zoom lerps to.
|
||||||
*/
|
*/
|
||||||
public var camHUDZoomLerp:Float = Flags.DEFAULT_HUD_ZOOM_LERP;
|
public var camHUDZoomLerp:Float = Flags.DEFAULT_HUD_ZOOM_LERP;
|
||||||
|
/**
|
||||||
|
* The current multiplier for game camera zooming.
|
||||||
|
*/
|
||||||
|
public var camHUDZoomMult:Float = Flags.DEFAULT_HUD_ZOOM_MULT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Camera zoom at which the cameras that zooms lerps to.
|
||||||
|
* (Only used if useCamZoomMult is on).
|
||||||
|
*/
|
||||||
|
public var defaultZoom:Float = Flags.DEFAULT_ZOOM;
|
||||||
|
/**
|
||||||
|
* Speed at which the cameras that zooms zoom lerps to.
|
||||||
|
* (Only used if useCamZoomMult is on).
|
||||||
|
*/
|
||||||
|
public var camZoomLerp:Float = Flags.DEFAULT_ZOOM_LERP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whenever cam zooming is enabled, enables on a note hit if not cancelled.
|
* Whenever cam zooming is enabled, enables on a note hit if not cancelled.
|
||||||
@@ -401,15 +428,24 @@ class PlayState extends MusicBeatState
|
|||||||
*/
|
*/
|
||||||
public var camZoomingStrength:Float = Flags.DEFAULT_CAM_ZOOM_STRENGTH;
|
public var camZoomingStrength:Float = Flags.DEFAULT_CAM_ZOOM_STRENGTH;
|
||||||
/**
|
/**
|
||||||
* Default multiplier for `maxCamZoom`.
|
* Default multiplier for `maxCamZoom`.
|
||||||
*/
|
*/
|
||||||
public var maxCamZoomMult:Float = Flags.MAX_CAMERA_ZOOM_MULT;
|
public var maxCamZoomMult:Float = Flags.MAX_CAMERA_ZOOM_MULT;
|
||||||
/**
|
/**
|
||||||
* Maximum amount of zoom for the camera (based on `maxCamZoomMult` and the camera's zoom IF not set).
|
* Whether it should use a implementation where it multiplies the current camera zoom instead.
|
||||||
*/
|
*/
|
||||||
|
public var useCamZoomMult:Bool = Flags.USE_CAM_ZOOM_MULT;
|
||||||
|
/**
|
||||||
|
* The current multiplier for camera zooming.
|
||||||
|
* (Only used if useCamZoomMult is on).
|
||||||
|
*/
|
||||||
|
public var camZoomingMult:Float = Flags.DEFAULT_ZOOM;
|
||||||
|
/**
|
||||||
|
* Maximum amount of zoom for the camera (based on `maxCamZoomMult` and the camera's zoom IF not set).
|
||||||
|
*/
|
||||||
public var maxCamZoom(get, default):Float = Math.NaN;
|
public var maxCamZoom(get, default):Float = Math.NaN;
|
||||||
|
|
||||||
private inline function get_maxCamZoom() return Math.isNaN(maxCamZoom) ? maxCamZoomMult * defaultCamZoom : maxCamZoom;
|
private inline function get_maxCamZoom() return Math.isNaN(maxCamZoom) ? defaultCamZoom + (camZoomingMult * camGameZoomMult) : maxCamZoom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zoom for the pixel assets.
|
* Zoom for the pixel assets.
|
||||||
@@ -524,7 +560,7 @@ class PlayState extends MusicBeatState
|
|||||||
@:noCompletion @:dox(hide) private var _endSongCalled:Bool = false;
|
@:noCompletion @:dox(hide) private var _endSongCalled:Bool = false;
|
||||||
|
|
||||||
@:dox(hide)
|
@:dox(hide)
|
||||||
var __vocalSyncTimer:Float = 0;
|
var __vocalSyncTimer:Float = 1;
|
||||||
|
|
||||||
private function get_accuracy():Float {
|
private function get_accuracy():Float {
|
||||||
if (accuracyPressedNotes <= 0) return -1;
|
if (accuracyPressedNotes <= 0) return -1;
|
||||||
@@ -629,7 +665,7 @@ class PlayState extends MusicBeatState
|
|||||||
persistentDraw = true;
|
persistentDraw = true;
|
||||||
|
|
||||||
if (SONG == null)
|
if (SONG == null)
|
||||||
SONG = Chart.parse('tutorial', 'normal');
|
SONG = Chart.parse('tutorial', difficulty = 'normal', variation = null);
|
||||||
|
|
||||||
scrollSpeed = SONG.scrollSpeed;
|
scrollSpeed = SONG.scrollSpeed;
|
||||||
|
|
||||||
@@ -1085,9 +1121,11 @@ class PlayState extends MusicBeatState
|
|||||||
curSong = songData.meta.name.toLowerCase();
|
curSong = songData.meta.name.toLowerCase();
|
||||||
curSongID = curSong.replace(" ", "-");
|
curSongID = curSong.replace(" ", "-");
|
||||||
|
|
||||||
FlxG.sound.setMusic(inst = FlxG.sound.load(Assets.getMusic(Paths.inst(SONG.meta.name, difficulty))));
|
FlxG.sound.setMusic(inst = FlxG.sound.load(Assets.getMusic(Paths.inst(SONG.meta.name, difficulty, SONG.meta.instSuffix))));
|
||||||
if (SONG.meta.needsVoices != false && Assets.exists(Paths.voices(SONG.meta.name, difficulty))) // null or true
|
|
||||||
vocals = FlxG.sound.load(Options.streamedVocals ? Assets.getMusic(Paths.voices(SONG.meta.name, difficulty)) : Paths.voices(SONG.meta.name, difficulty));
|
var vocalsPath = Paths.voices(SONG.meta.name, difficulty, SONG.meta.vocalsSuffix);
|
||||||
|
if (SONG.meta.needsVoices && Assets.exists(vocalsPath))
|
||||||
|
vocals = FlxG.sound.load(Options.streamedVocals ? Assets.getMusic(vocalsPath) : vocalsPath);
|
||||||
else
|
else
|
||||||
vocals = new FlxSound();
|
vocals = new FlxSound();
|
||||||
|
|
||||||
@@ -1196,7 +1234,7 @@ class PlayState extends MusicBeatState
|
|||||||
var time = Conductor.songPosition + Conductor.songOffset;
|
var time = Conductor.songPosition + Conductor.songOffset;
|
||||||
for (strumLine in strumLines.members) strumLine.vocals.play(true, time);
|
for (strumLine in strumLines.members) strumLine.vocals.play(true, time);
|
||||||
vocals.play(true, time);
|
vocals.play(true, time);
|
||||||
inst.play(true, time);
|
if (!inst.playing) inst.play(true, time);
|
||||||
|
|
||||||
gameAndCharsCall("onVocalsResync");
|
gameAndCharsCall("onVocalsResync");
|
||||||
}
|
}
|
||||||
@@ -1322,14 +1360,19 @@ class PlayState extends MusicBeatState
|
|||||||
updateRatingStuff();
|
updateRatingStuff();
|
||||||
|
|
||||||
if (canAccessDebugMenus && chartingMode && controls.DEV_ACCESS)
|
if (canAccessDebugMenus && chartingMode && controls.DEV_ACCESS)
|
||||||
FlxG.switchState(new funkin.editors.charter.Charter(SONG.meta.name, difficulty, false));
|
FlxG.switchState(new funkin.editors.charter.Charter(SONG.meta.name, difficulty, variation, false));
|
||||||
|
|
||||||
if (Options.camZoomOnBeat && camZooming && FlxG.camera.zoom < maxCamZoom) {
|
if (Options.camZoomOnBeat && camZooming) {
|
||||||
var beat = Conductor.getBeats(camZoomingEvery, camZoomingInterval, camZoomingOffset);
|
var beat = Conductor.getBeats(camZoomingEvery, camZoomingInterval, camZoomingOffset);
|
||||||
if (camZoomingLastBeat != beat) {
|
if (camZoomingLastBeat != beat) {
|
||||||
camZoomingLastBeat = beat;
|
camZoomingLastBeat = beat;
|
||||||
FlxG.camera.zoom += 0.015 * camZoomingStrength;
|
if (useCamZoomMult) {
|
||||||
camHUD.zoom += 0.03 * camZoomingStrength;
|
if (camZoomingMult < maxCamZoomMult) camZoomingMult += camZoomingStrength;
|
||||||
|
}
|
||||||
|
else if (FlxG.camera.zoom < maxCamZoom) {
|
||||||
|
FlxG.camera.zoom += camGameZoomMult * camZoomingStrength;
|
||||||
|
camHUD.zoom += camHUDZoomMult * camZoomingStrength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1342,20 +1385,19 @@ class PlayState extends MusicBeatState
|
|||||||
updateIconPositions();
|
updateIconPositions();
|
||||||
|
|
||||||
if (startingSong) {
|
if (startingSong) {
|
||||||
if (startedCountdown) {
|
if (startedCountdown && (Conductor.songPosition += Conductor.songOffset + elapsed * 1000) >= 0) {
|
||||||
Conductor.songPosition += Conductor.songOffset + elapsed * 1000;
|
Conductor.songPosition = Conductor.songOffset;
|
||||||
if (Conductor.songPosition >= 0)
|
startSong();
|
||||||
startSong();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (FlxG.sound.music != null && (__vocalSyncTimer -= elapsed) < 0) {
|
else if (FlxG.sound.music != null && (__vocalSyncTimer -= elapsed) < 0) {
|
||||||
__vocalSyncTimer = 1;
|
__vocalSyncTimer = 1;
|
||||||
|
|
||||||
var instTime = FlxG.sound.music.getActualTime();
|
var instTime = FlxG.sound.music.getActualTime();
|
||||||
var isOffsync:Bool = vocals.loaded && Math.abs(instTime - vocals.getActualTime()) > 30;
|
var isOffsync:Bool = vocals.loaded && Math.abs(instTime - vocals.getActualTime()) > 100;
|
||||||
if (!isOffsync) {
|
if (!isOffsync) {
|
||||||
for (strumLine in strumLines.members) {
|
for (strumLine in strumLines.members) {
|
||||||
if ((isOffsync = strumLine.vocals.loaded && Math.abs(instTime - strumLine.vocals.getActualTime()) > 30)) break;
|
if ((isOffsync = strumLine.vocals.loaded && Math.abs(instTime - strumLine.vocals.getActualTime()) > 100)) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1372,6 +1414,12 @@ class PlayState extends MusicBeatState
|
|||||||
moveCamera();
|
moveCamera();
|
||||||
|
|
||||||
if (camZooming) {
|
if (camZooming) {
|
||||||
|
if (useCamZoomMult) {
|
||||||
|
camZoomingMult = lerp(camZoomingMult, defaultZoom, camZoomLerp) - defaultZoom;
|
||||||
|
FlxG.camera.zoomMultiplier = camZoomingMult * camGameZoomMult + defaultZoom;
|
||||||
|
camHUD.zoomMultiplier = camZoomingMult * camHUDZoomMult + defaultZoom;
|
||||||
|
camZoomingMult += defaultZoom;
|
||||||
|
}
|
||||||
FlxG.camera.zoom = lerp(FlxG.camera.zoom, defaultCamZoom, camGameZoomLerp);
|
FlxG.camera.zoom = lerp(FlxG.camera.zoom, defaultCamZoom, camGameZoomLerp);
|
||||||
camHUD.zoom = lerp(camHUD.zoom, defaultHudZoom, camHUDZoomLerp);
|
camHUD.zoom = lerp(camHUD.zoom, defaultHudZoom, camHUDZoomLerp);
|
||||||
}
|
}
|
||||||
@@ -1530,6 +1578,8 @@ class PlayState extends MusicBeatState
|
|||||||
case "Add Camera Zoom":
|
case "Add Camera Zoom":
|
||||||
var camera:FlxCamera = event.params[1] == "camHUD" ? camHUD : camGame;
|
var camera:FlxCamera = event.params[1] == "camHUD" ? camHUD : camGame;
|
||||||
camera.zoom += event.params[0];
|
camera.zoom += event.params[0];
|
||||||
|
case "Camera Bop":
|
||||||
|
camZoomingMult += event.params[0];
|
||||||
case "Camera Zoom":
|
case "Camera Zoom":
|
||||||
var cam = event.params[2] == "camHUD" ? camHUD : camGame;
|
var cam = event.params[2] == "camHUD" ? camHUD : camGame;
|
||||||
var name = (event.params[2] == "camHUD" ? "camHUD" : "camGame") + ".zoom"; // avoiding having different values from these 2 - Nex
|
var name = (event.params[2] == "camHUD" ? "camHUD" : "camGame") + ".zoom"; // avoiding having different values from these 2 - Nex
|
||||||
@@ -1645,22 +1695,17 @@ class PlayState extends MusicBeatState
|
|||||||
*/
|
*/
|
||||||
public function endSong():Void
|
public function endSong():Void
|
||||||
{
|
{
|
||||||
|
if (gameAndCharsEvent("onSongEnd", new CancellableEvent()).cancelled) return;
|
||||||
endingSong = true;
|
endingSong = true;
|
||||||
gameAndCharsCall("onSongEnd");
|
|
||||||
canPause = false;
|
canPause = false;
|
||||||
inst.volume = 0;
|
|
||||||
vocals.volume = 0;
|
|
||||||
for (strumLine in strumLines.members) {
|
|
||||||
strumLine.vocals.volume = 0;
|
|
||||||
strumLine.vocals.pause();
|
|
||||||
}
|
|
||||||
inst.pause();
|
|
||||||
vocals.pause();
|
|
||||||
|
|
||||||
if (validScore)
|
for (strumLine in strumLines.members) strumLine.vocals.stop();
|
||||||
{
|
inst.stop();
|
||||||
|
vocals.stop();
|
||||||
|
|
||||||
|
if (validScore) {
|
||||||
#if !switch
|
#if !switch
|
||||||
FunkinSave.setSongHighscore(SONG.meta.name, difficulty, {
|
FunkinSave.setSongHighscore(SONG.meta.name, difficulty, variation, {
|
||||||
score: songScore,
|
score: songScore,
|
||||||
misses: misses,
|
misses: misses,
|
||||||
accuracy: accuracy,
|
accuracy: accuracy,
|
||||||
@@ -1686,20 +1731,19 @@ class PlayState extends MusicBeatState
|
|||||||
* Immediately switches to the next song, or goes back to the Story/Freeplay menu.
|
* Immediately switches to the next song, or goes back to the Story/Freeplay menu.
|
||||||
*/
|
*/
|
||||||
public function nextSong() {
|
public function nextSong() {
|
||||||
if (isStoryMode)
|
if (isStoryMode) {
|
||||||
{
|
|
||||||
campaignScore += songScore;
|
campaignScore += songScore;
|
||||||
campaignMisses += misses;
|
campaignMisses += misses;
|
||||||
campaignAccuracyTotal += accuracy;
|
campaignAccuracyTotal += accuracy;
|
||||||
campaignAccuracyCount++;
|
campaignAccuracyCount++;
|
||||||
storyPlaylist.shift();
|
storyPlaylist.shift();
|
||||||
|
storyVariations.shift();
|
||||||
|
|
||||||
if (storyPlaylist.length <= 0)
|
if (storyPlaylist.length <= 0) {
|
||||||
{
|
|
||||||
FlxG.switchState(new StoryMenuState());
|
FlxG.switchState(new StoryMenuState());
|
||||||
|
|
||||||
if (validScore)
|
if (validScore) {
|
||||||
{
|
#if !switch
|
||||||
// TODO: more week info saving
|
// TODO: more week info saving
|
||||||
FunkinSave.setWeekHighscore(storyWeek.id, difficulty, {
|
FunkinSave.setWeekHighscore(storyWeek.id, difficulty, {
|
||||||
score: campaignScore,
|
score: campaignScore,
|
||||||
@@ -1708,29 +1752,23 @@ class PlayState extends MusicBeatState
|
|||||||
hits: [],
|
hits: [],
|
||||||
date: Date.now().toString()
|
date: Date.now().toString()
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
FlxG.save.flush();
|
FlxG.save.flush();
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
Logs.infos('Loading next song (${storyPlaylist[0].toLowerCase()}/$difficulty/${storyVariations[0]})', "PlayState");
|
||||||
Logs.infos('Loading next song (${storyPlaylist[0].toLowerCase()}/$difficulty)', "PlayState");
|
|
||||||
|
|
||||||
registerSmoothTransition();
|
registerSmoothTransition();
|
||||||
|
|
||||||
FlxG.sound.music.stop();
|
__loadSong(storyPlaylist[0], difficulty, storyVariations[0]);
|
||||||
|
|
||||||
__loadSong(storyPlaylist[0], difficulty);
|
|
||||||
|
|
||||||
FlxG.switchState(new PlayState());
|
FlxG.switchState(new PlayState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (chartingMode)
|
||||||
|
FlxG.switchState(new funkin.editors.charter.Charter(SONG.meta.name, difficulty, variation, false));
|
||||||
else
|
else
|
||||||
{
|
FlxG.switchState(new FreeplayState());
|
||||||
if (chartingMode)
|
|
||||||
FlxG.switchState(new funkin.editors.charter.Charter(SONG.meta.name, difficulty, false));
|
|
||||||
else
|
|
||||||
FlxG.switchState(new FreeplayState());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function registerSmoothTransition() {
|
public function registerSmoothTransition() {
|
||||||
@@ -1902,6 +1940,8 @@ class PlayState extends MusicBeatState
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event.deleteNote) strumLine.deleteNote(note);
|
if (event.deleteNote) strumLine.deleteNote(note);
|
||||||
|
|
||||||
|
gameAndCharsEvent("onPostNoteHit", event);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function displayRating(myRating:String, ?evt:NoteHitEvent = null):Void {
|
public function displayRating(myRating:String, ?evt:NoteHitEvent = null):Void {
|
||||||
@@ -2101,43 +2141,51 @@ class PlayState extends MusicBeatState
|
|||||||
if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
||||||
storyWeek = weekData;
|
storyWeek = weekData;
|
||||||
storyPlaylist = [for (e in weekData.songs) e.name];
|
storyPlaylist = [for (e in weekData.songs) e.name];
|
||||||
|
storyVariations = [for (e in weekData.songs) e.variation];
|
||||||
isStoryMode = true;
|
isStoryMode = true;
|
||||||
campaignScore = 0;
|
campaignScore = 0;
|
||||||
campaignMisses = 0;
|
campaignMisses = 0;
|
||||||
campaignAccuracyTotal = 0;
|
campaignAccuracyTotal = 0;
|
||||||
campaignAccuracyCount = 0;
|
campaignAccuracyCount = 0;
|
||||||
chartingMode = false;
|
chartingMode = coopMode = opponentMode = false;
|
||||||
opponentMode = coopMode = false;
|
__loadSong(storyPlaylist[0], difficulty, storyVariations[0]);
|
||||||
__loadSong(storyPlaylist[0], difficulty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a song into PlayState
|
* Loads a song into PlayState
|
||||||
* @param name Song name
|
* @param name Song name
|
||||||
* @param difficulty Chart difficulty (if invalid, will load an empty chart)
|
* @param difficulty Chart difficulty (if invalid, will load an empty chart)
|
||||||
|
* @param variation Song Variation
|
||||||
* @param opponentMode Whenever opponent mode is on
|
* @param opponentMode Whenever opponent mode is on
|
||||||
* @param coopMode Whenever co-op mode is on.
|
* @param coopMode Whenever co-op mode is on.
|
||||||
*/
|
*/
|
||||||
public static function loadSong(_name:String, ?_difficulty:String, _opponentMode:Bool = false, _coopMode:Bool = false) {
|
public static function loadSong(_name:String, ?_difficulty:String, ?_variation:Dynamic, _opponentMode:Bool = false, _coopMode:Bool = false) {
|
||||||
if (_difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
if (_difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
||||||
isStoryMode = false;
|
if (_variation is Bool) { // vackward cumpatibshit
|
||||||
|
_coopMode = _opponentMode;
|
||||||
|
_opponentMode = cast _variation;
|
||||||
|
_variation = null;
|
||||||
|
}
|
||||||
|
else if (!(_variation is String)) _variation = null;
|
||||||
opponentMode = _opponentMode;
|
opponentMode = _opponentMode;
|
||||||
chartingMode = false;
|
|
||||||
coopMode = _coopMode;
|
coopMode = _coopMode;
|
||||||
__loadSong(_name, _difficulty);
|
isStoryMode = chartingMode = false;
|
||||||
|
__loadSong(_name, _difficulty, cast _variation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (INTERNAL) Loads a song without resetting story mode/opponent mode/coop mode values.
|
* (INTERNAL) Loads a song without resetting story mode/opponent mode/coop mode values.
|
||||||
* @param name Song name
|
* @param name Song name
|
||||||
* @param difficulty Song difficulty
|
* @param difficulty Chart difficulty
|
||||||
|
* @param variation Song Variation
|
||||||
*/
|
*/
|
||||||
public static function __loadSong(_name:String, _difficulty:String) {
|
public static function __loadSong(_name:String, _difficulty:String, _variation:String) {
|
||||||
difficulty = _difficulty;
|
difficulty = _difficulty;
|
||||||
|
variation = _variation;
|
||||||
seenCutscene = false;
|
seenCutscene = false;
|
||||||
deathCounter = 0;
|
deathCounter = 0;
|
||||||
|
|
||||||
SONG = Chart.parse(_name, _difficulty);
|
SONG = Chart.parse(_name, _difficulty, _variation);
|
||||||
fromMods = SONG.fromMods;
|
fromMods = SONG.fromMods;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,21 @@ class FreeplayState extends MusicBeatState
|
|||||||
*/
|
*/
|
||||||
public var songs:Array<ChartMetaData> = [];
|
public var songs:Array<ChartMetaData> = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current song metadata
|
||||||
|
*/
|
||||||
|
public var curSong:Null<ChartMetaData>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current song difficulties
|
||||||
|
*/
|
||||||
|
public var curDifficulties:Array<String>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* songs[curSelected].metas.get(curDiffMetaIndices[curDifficulty])
|
||||||
|
*/
|
||||||
|
public var curDiffMetaKeys:Array<String> = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently selected song
|
* Currently selected song
|
||||||
*/
|
*/
|
||||||
@@ -43,7 +58,7 @@ class FreeplayState extends MusicBeatState
|
|||||||
public var diffText:FlxText;
|
public var diffText:FlxText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text containing the current coop/opponent mode ([TAB] Co-Op mode)
|
* Text containing the current coop/opponent mode ([KEYBINDS] Co-Op mode)
|
||||||
*/
|
*/
|
||||||
public var coopText:FlxText;
|
public var coopText:FlxText;
|
||||||
|
|
||||||
@@ -107,14 +122,15 @@ class FreeplayState extends MusicBeatState
|
|||||||
curSelected = k;
|
curSelected = k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (songs[curSelected] != null) {
|
|
||||||
for(k=>diff in songs[curSelected].difficulties) {
|
updateCurDifficulties();
|
||||||
if (diff == Options.freeplayLastDifficulty) {
|
for(i=>diff in curDifficulties) {
|
||||||
curDifficulty = k;
|
if (curDiffMetaKeys[i] == Options.freeplayLastVariation && diff == Options.freeplayLastDifficulty)
|
||||||
}
|
curDifficulty = i;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateCurSong();
|
||||||
|
|
||||||
DiscordUtil.call("onMenuLoaded", ["Freeplay"]);
|
DiscordUtil.call("onMenuLoaded", ["Freeplay"]);
|
||||||
|
|
||||||
super.create();
|
super.create();
|
||||||
@@ -139,8 +155,7 @@ class FreeplayState extends MusicBeatState
|
|||||||
|
|
||||||
var icon:HealthIcon = new HealthIcon(songs[i].icon);
|
var icon:HealthIcon = new HealthIcon(songs[i].icon);
|
||||||
icon.sprTracker = songText;
|
icon.sprTracker = songText;
|
||||||
icon.setUnstretchedGraphicSize(150, 150, true);
|
if (Math.max(icon.width, icon.height) > 150) icon.setUnstretchedGraphicSize(150, 150);
|
||||||
icon.updateHitbox();
|
|
||||||
|
|
||||||
// using a FlxGroup is too much fuss!
|
// using a FlxGroup is too much fuss!
|
||||||
iconArray.push(icon);
|
iconArray.push(icon);
|
||||||
@@ -169,7 +184,6 @@ class FreeplayState extends MusicBeatState
|
|||||||
add(scoreText);
|
add(scoreText);
|
||||||
|
|
||||||
changeSelection(0, true);
|
changeSelection(0, true);
|
||||||
changeDiff(0, true);
|
|
||||||
changeCoopMode(0, true);
|
changeCoopMode(0, true);
|
||||||
|
|
||||||
interpColor = new FlxInterpolateColor(bg.color);
|
interpColor = new FlxInterpolateColor(bg.color);
|
||||||
@@ -225,7 +239,7 @@ class FreeplayState extends MusicBeatState
|
|||||||
if (canSelect) {
|
if (canSelect) {
|
||||||
changeSelection((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0) - FlxG.mouse.wheel);
|
changeSelection((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0) - FlxG.mouse.wheel);
|
||||||
changeDiff((controls.LEFT_P ? -1 : 0) + (controls.RIGHT_P ? 1 : 0));
|
changeDiff((controls.LEFT_P ? -1 : 0) + (controls.RIGHT_P ? 1 : 0));
|
||||||
changeCoopMode((FlxG.keys.justPressed.TAB ? 1 : 0)); // TODO: make this configurable
|
changeCoopMode((controls.CHANGE_MODE ? 1 : 0)); // TODO: make this configurable
|
||||||
// putting it before so that its actually smooth
|
// putting it before so that its actually smooth
|
||||||
updateOptionsAlpha();
|
updateOptionsAlpha();
|
||||||
}
|
}
|
||||||
@@ -238,14 +252,14 @@ class FreeplayState extends MusicBeatState
|
|||||||
scoreText.x = coopText.x = scoreBG.x + 4;
|
scoreText.x = coopText.x = scoreBG.x + 4;
|
||||||
diffText.x = Std.int(scoreBG.x + ((scoreBG.width - diffText.width) / 2));
|
diffText.x = Std.int(scoreBG.x + ((scoreBG.width - diffText.width) / 2));
|
||||||
|
|
||||||
interpColor.fpsLerpTo(songs[curSelected].color, 0.0625);
|
interpColor.fpsLerpTo(curSong.color, 0.0625);
|
||||||
bg.color = interpColor.color;
|
bg.color = interpColor.color;
|
||||||
|
|
||||||
#if PRELOAD_ALL
|
#if PRELOAD_ALL
|
||||||
var dontPlaySongThisFrame = false;
|
var dontPlaySongThisFrame = false;
|
||||||
autoplayElapsed += elapsed;
|
autoplayElapsed += elapsed;
|
||||||
if (!disableAutoPlay && !songInstPlaying && (autoplayElapsed > timeUntilAutoplay || FlxG.keys.justPressed.SPACE)) {
|
if (!disableAutoPlay && !songInstPlaying && (autoplayElapsed > timeUntilAutoplay)) {
|
||||||
if (curPlayingInst != (curPlayingInst = Paths.inst(songs[curSelected].name, songs[curSelected].difficulties[curDifficulty]))) {
|
if (curPlayingInst != (curPlayingInst = Paths.inst(curSong.name, curDifficulties[curDifficulty], curSong.instSuffix))) {
|
||||||
var streamed = false;
|
var streamed = false;
|
||||||
if (Options.streamedMusic) {
|
if (Options.streamedMusic) {
|
||||||
var sound = Assets.getMusic(curPlayingInst, true, false);
|
var sound = Assets.getMusic(curPlayingInst, true, false);
|
||||||
@@ -253,7 +267,7 @@ class FreeplayState extends MusicBeatState
|
|||||||
|
|
||||||
if (streamed && autoplayShouldPlay) {
|
if (streamed && autoplayShouldPlay) {
|
||||||
FlxG.sound.playMusic(sound, 0);
|
FlxG.sound.playMusic(sound, 0);
|
||||||
Conductor.changeBPM(songs[curSelected].bpm, songs[curSelected].beatsPerMeasure, songs[curSelected].stepsPerBeat);
|
Conductor.changeBPM(curSong.bpm, curSong.beatsPerMeasure, curSong.stepsPerBeat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +282,7 @@ class FreeplayState extends MusicBeatState
|
|||||||
|
|
||||||
if (sound != null && autoplayShouldPlay) {
|
if (sound != null && autoplayShouldPlay) {
|
||||||
FlxG.sound.playMusic(sound, 0);
|
FlxG.sound.playMusic(sound, 0);
|
||||||
Conductor.changeBPM(songs[curSelected].bpm, songs[curSelected].beatsPerMeasure, songs[curSelected].stepsPerBeat);
|
Conductor.changeBPM(curSong.bpm, curSong.beatsPerMeasure, curSong.stepsPerBeat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!disableAsyncLoading) Main.execAsync(huh);
|
if (!disableAsyncLoading) Main.execAsync(huh);
|
||||||
@@ -302,7 +316,6 @@ class FreeplayState extends MusicBeatState
|
|||||||
function updateCoopModes() {
|
function updateCoopModes() {
|
||||||
__opponentMode = false;
|
__opponentMode = false;
|
||||||
__coopMode = false;
|
__coopMode = false;
|
||||||
var curSong = songs[curSelected];
|
|
||||||
if (curSong.coopAllowed && curSong.opponentModeAllowed) {
|
if (curSong.coopAllowed && curSong.opponentModeAllowed) {
|
||||||
__opponentMode = curCoopMode % 2 == 1;
|
__opponentMode = curCoopMode % 2 == 1;
|
||||||
__coopMode = curCoopMode >= 2;
|
__coopMode = curCoopMode >= 2;
|
||||||
@@ -319,9 +332,9 @@ class FreeplayState extends MusicBeatState
|
|||||||
public function select() {
|
public function select() {
|
||||||
updateCoopModes();
|
updateCoopModes();
|
||||||
|
|
||||||
if (songs[curSelected].difficulties.length <= 0) return;
|
if (curDifficulties.length == 0) return;
|
||||||
|
|
||||||
var event = event("onSelect", EventManager.get(FreeplaySongSelectEvent).recycle(songs[curSelected].name, songs[curSelected].difficulties[curDifficulty], __opponentMode, __coopMode));
|
var event = event("onSelect", EventManager.get(FreeplaySongSelectEvent).recycle(curSong.name, curDifficulties[curDifficulty], curSong.variant, __opponentMode, __coopMode));
|
||||||
|
|
||||||
if (event.cancelled) return;
|
if (event.cancelled) return;
|
||||||
|
|
||||||
@@ -329,17 +342,18 @@ class FreeplayState extends MusicBeatState
|
|||||||
autoplayShouldPlay = false;
|
autoplayShouldPlay = false;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
Options.freeplayLastSong = songs[curSelected].name;
|
Options.freeplayLastSong = curSong.name;
|
||||||
Options.freeplayLastDifficulty = songs[curSelected].difficulties[curDifficulty];
|
Options.freeplayLastDifficulty = curDifficulties[curDifficulty];
|
||||||
|
Options.freeplayLastVariation = curSong.variant;
|
||||||
|
|
||||||
PlayState.loadSong(event.song, event.difficulty, event.opponentMode, event.coopMode);
|
PlayState.loadSong(event.song, event.difficulty, event.variant, event.opponentMode, event.coopMode);
|
||||||
FlxG.switchState(new PlayState());
|
FlxG.switchState(new PlayState());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function convertChart() {
|
public function convertChart() {
|
||||||
trace('Converting ${songs[curSelected].name} (${songs[curSelected].difficulties[curDifficulty]}) to Codename format...');
|
trace('Converting ${curSong.name} ${curDifficulties[curDifficulty]} ${curSong.variant} to Codename format...');
|
||||||
var chart = Chart.parse(songs[curSelected].name, songs[curSelected].difficulties[curDifficulty]);
|
var chart = Chart.parse(curSong.name, curDifficulties[curDifficulty], curSong.variant);
|
||||||
Chart.save('${Main.pathBack}assets/songs/${songs[curSelected].name}', chart, songs[curSelected].difficulties[curDifficulty]);
|
Chart.save(chart, curDifficulties[curDifficulty], curSong.variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -347,28 +361,35 @@ class FreeplayState extends MusicBeatState
|
|||||||
* @param change How much to change.
|
* @param change How much to change.
|
||||||
* @param force Force the change if `change` is equal to 0
|
* @param force Force the change if `change` is equal to 0
|
||||||
*/
|
*/
|
||||||
public function changeDiff(change:Int = 0, force:Bool = false)
|
public function changeDiff(change:Int = 0, force:Bool = false) {
|
||||||
{
|
|
||||||
if (change == 0 && !force) return;
|
if (change == 0 && !force) return;
|
||||||
|
|
||||||
var curSong = songs[curSelected];
|
var validDifficulties = curDifficulties.length > 0;
|
||||||
var validDifficulties = curSong.difficulties.length > 0;
|
var event = event("onChangeDiff", EventManager.get(MenuChangeEvent).recycle(curDifficulty, validDifficulties ? FlxMath.wrap(curDifficulty + change, 0, curDifficulties.length-1) : 0, change));
|
||||||
var event = event("onChangeDiff", EventManager.get(MenuChangeEvent).recycle(curDifficulty, validDifficulties ? FlxMath.wrap(curDifficulty + change, 0, curSong.difficulties.length-1) : 0, change));
|
|
||||||
|
|
||||||
if (event.cancelled) return;
|
if (event.cancelled) {
|
||||||
|
if (force) updateCurSong();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var prevSong = curSong;
|
||||||
curDifficulty = event.value;
|
curDifficulty = event.value;
|
||||||
|
updateCurSong();
|
||||||
updateScore();
|
updateScore();
|
||||||
|
|
||||||
if (curSong.difficulties.length > 1)
|
#if PRELOAD_ALL
|
||||||
diffText.text = '< ${curSong.difficulties[curDifficulty].toUpperCase()} >';
|
if (curSong != prevSong) {
|
||||||
else
|
autoplayElapsed = 0;
|
||||||
diffText.text = validDifficulties ? curSong.difficulties[curDifficulty].toUpperCase() : "-";
|
songInstPlaying = false;
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
|
var text = validDifficulties ? curDifficulties[curDifficulty].toUpperCase() + (curSong != songs[curSelected] ? ' (${curSong.variant.toUpperCase()})' : '') : '-';
|
||||||
|
diffText.text = curDifficulties.length > 1 ? '< $text >' : text;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateScore() {
|
function updateScore() {
|
||||||
if (songs[curSelected].difficulties.length <= 0) {
|
if (curDifficulties.length == 0) {
|
||||||
intendedScore = 0;
|
intendedScore = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -376,7 +397,7 @@ class FreeplayState extends MusicBeatState
|
|||||||
var changes:Array<HighscoreChange> = [];
|
var changes:Array<HighscoreChange> = [];
|
||||||
if (__coopMode) changes.push(CCoopMode);
|
if (__coopMode) changes.push(CCoopMode);
|
||||||
if (__opponentMode) changes.push(COpponentMode);
|
if (__opponentMode) changes.push(COpponentMode);
|
||||||
var saveData = FunkinSave.getSongHighscore(songs[curSelected].name, songs[curSelected].difficulties[curDifficulty], changes);
|
var saveData = FunkinSave.getSongHighscore(curSong.name, curDifficulties[curDifficulty], curSong.variant, changes);
|
||||||
intendedScore = saveData.score;
|
intendedScore = saveData.score;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,9 +418,9 @@ class FreeplayState extends MusicBeatState
|
|||||||
*/
|
*/
|
||||||
public function changeCoopMode(change:Int = 0, force:Bool = false) {
|
public function changeCoopMode(change:Int = 0, force:Bool = false) {
|
||||||
if (change == 0 && !force) return;
|
if (change == 0 && !force) return;
|
||||||
if (!songs[curSelected].coopAllowed && !songs[curSelected].opponentModeAllowed) return;
|
if (!curSong.coopAllowed && !curSong.opponentModeAllowed) return;
|
||||||
|
|
||||||
var bothEnabled = songs[curSelected].coopAllowed && songs[curSelected].opponentModeAllowed;
|
var bothEnabled = curSong.coopAllowed && curSong.opponentModeAllowed;
|
||||||
var event = event("onChangeCoopMode", EventManager.get(MenuChangeEvent).recycle(curCoopMode, FlxMath.wrap(curCoopMode + change, 0, bothEnabled ? 3 : 1), change));
|
var event = event("onChangeCoopMode", EventManager.get(MenuChangeEvent).recycle(curCoopMode, FlxMath.wrap(curCoopMode + change, 0, bothEnabled ? 3 : 1), change));
|
||||||
|
|
||||||
if (event.cancelled) return;
|
if (event.cancelled) return;
|
||||||
@@ -408,12 +429,16 @@ class FreeplayState extends MusicBeatState
|
|||||||
|
|
||||||
updateScore();
|
updateScore();
|
||||||
|
|
||||||
var key = "[TAB] "; // TODO: make this configurable
|
var coopBinds = [CoolUtil.keyToString(Options.P1_CHANGE_MODE[0]), CoolUtil.keyToString(Options.P2_CHANGE_MODE[0])].filter(x -> x != "---");
|
||||||
|
if (coopBinds.length == 2 && coopBinds[1] == coopBinds[0]) coopBinds.pop();
|
||||||
|
else if (coopBinds.length == 0) coopBinds.push("---");
|
||||||
|
|
||||||
|
var key = '[${coopBinds.join(" / ")}] ';
|
||||||
|
|
||||||
if (bothEnabled) {
|
if (bothEnabled) {
|
||||||
coopText.text = key + coopLabels[curCoopMode];
|
coopText.text = key + coopLabels[curCoopMode];
|
||||||
} else {
|
} else {
|
||||||
coopText.text = key + coopLabels[curCoopMode * (songs[curSelected].coopAllowed ? 2 : 1)];
|
coopText.text = key + coopLabels[curCoopMode * (curSong.coopAllowed ? 2 : 1)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,17 +447,23 @@ class FreeplayState extends MusicBeatState
|
|||||||
* @param change How much to change
|
* @param change How much to change
|
||||||
* @param force Force the change, even if `change` is equal to 0.
|
* @param force Force the change, even if `change` is equal to 0.
|
||||||
*/
|
*/
|
||||||
public function changeSelection(change:Int = 0, force:Bool = false)
|
public function changeSelection(change:Int = 0, force:Bool = false) {
|
||||||
{
|
|
||||||
if (change == 0 && !force) return;
|
if (change == 0 && !force) return;
|
||||||
|
|
||||||
var bothEnabled = songs[curSelected].coopAllowed && songs[curSelected].opponentModeAllowed;
|
|
||||||
var event = event("onChangeSelection", EventManager.get(MenuChangeEvent).recycle(curSelected, FlxMath.wrap(curSelected + change, 0, songs.length-1), change));
|
var event = event("onChangeSelection", EventManager.get(MenuChangeEvent).recycle(curSelected, FlxMath.wrap(curSelected + change, 0, songs.length-1), change));
|
||||||
if (event.cancelled) return;
|
if (event.cancelled) return;
|
||||||
|
|
||||||
curSelected = event.value;
|
curSelected = event.value;
|
||||||
if (event.playMenuSFX) CoolUtil.playMenuSFX(SCROLL, 0.7);
|
if (event.playMenuSFX) CoolUtil.playMenuSFX(SCROLL, 0.7);
|
||||||
|
|
||||||
|
var prevDiff = curDifficulties[curDifficulty], prevVariant = curDiffMetaKeys[curDifficulty];
|
||||||
|
updateCurDifficulties();
|
||||||
|
|
||||||
|
for (i => diff in curDifficulties) if (diff == prevDiff && curDiffMetaKeys[i] == prevVariant) {
|
||||||
|
curDifficulty = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
changeDiff(0, true);
|
changeDiff(0, true);
|
||||||
|
|
||||||
#if PRELOAD_ALL
|
#if PRELOAD_ALL
|
||||||
@@ -440,7 +471,7 @@ class FreeplayState extends MusicBeatState
|
|||||||
songInstPlaying = false;
|
songInstPlaying = false;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
coopText.visible = songs[curSelected].coopAllowed || songs[curSelected].opponentModeAllowed;
|
coopText.visible = curSong.coopAllowed || curSong.opponentModeAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateOptionsAlpha() {
|
function updateOptionsAlpha() {
|
||||||
@@ -465,6 +496,27 @@ class FreeplayState extends MusicBeatState
|
|||||||
item.alpha = selectedAlpha;
|
item.alpha = selectedAlpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateCurDifficulties() {
|
||||||
|
curDiffMetaKeys.resize(0);
|
||||||
|
curDifficulties = songs[curSelected].difficulties.copy();
|
||||||
|
for (i in 0...curDifficulties.length) curDiffMetaKeys.push(null);
|
||||||
|
|
||||||
|
if (songs[curSelected].variants != null) {
|
||||||
|
var meta:ChartMetaData;
|
||||||
|
for (variant in songs[curSelected].variants) if ((meta = songs[curSelected].metas.get(variant)) != null) {
|
||||||
|
curDifficulties = curDifficulties.concat(meta.difficulties);
|
||||||
|
for (i in 0...meta.difficulties.length) curDiffMetaKeys.push(variant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCurSong() {
|
||||||
|
var song = songs[curSelected];
|
||||||
|
if (song == null) curSong = null;
|
||||||
|
else if ((curSong = song.metas.get(curDiffMetaKeys[curDifficulty])) == null)
|
||||||
|
curSong = song;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FreeplaySonglist {
|
class FreeplaySonglist {
|
||||||
@@ -485,7 +537,7 @@ class FreeplaySonglist {
|
|||||||
}
|
}
|
||||||
if (songsFound == null) songsFound = Paths.getFolderDirectories("songs", false, source);
|
if (songsFound == null) songsFound = Paths.getFolderDirectories("songs", false, source);
|
||||||
if (songsFound.length > 0) {
|
if (songsFound.length > 0) {
|
||||||
for (s in songsFound) songs.push(Chart.loadChartMeta(s, Flags.DEFAULT_DIFFICULTY, source == MODS));
|
for (s in songsFound) songs.push(Chart.loadChartMeta(s, source == MODS));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ class MainMenuState extends MusicBeatState
|
|||||||
var camFollow:FlxObject;
|
var camFollow:FlxObject;
|
||||||
var versionText:FunkinText;
|
var versionText:FunkinText;
|
||||||
|
|
||||||
|
var devModeWarning:FunkinText;
|
||||||
|
|
||||||
public var canAccessDebugMenus:Bool = !Flags.DISABLE_EDITORS;
|
public var canAccessDebugMenus:Bool = !Flags.DISABLE_EDITORS;
|
||||||
|
|
||||||
override function create()
|
override function create()
|
||||||
@@ -85,10 +87,17 @@ class MainMenuState extends MusicBeatState
|
|||||||
add(versionText);
|
add(versionText);
|
||||||
|
|
||||||
changeItem();
|
changeItem();
|
||||||
|
|
||||||
|
devModeWarning = new FunkinText(0, FlxG.height - 50, 1280, "You have to enable DEVELOPER MODE in the miscellaneous settings!", 24);
|
||||||
|
devModeWarning.alignment = CENTER;
|
||||||
|
add(devModeWarning);
|
||||||
|
devModeWarning.scrollFactor.set();
|
||||||
|
devModeWarning.alpha = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectedSomethin:Bool = false;
|
var selectedSomethin:Bool = false;
|
||||||
var forceCenterX:Bool = true;
|
var forceCenterX:Bool = true;
|
||||||
|
var devModeCount:Int = 0;
|
||||||
|
|
||||||
override function update(elapsed:Float)
|
override function update(elapsed:Float)
|
||||||
{
|
{
|
||||||
@@ -111,6 +120,17 @@ class MainMenuState extends MusicBeatState
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
if (!Options.devMode && FlxG.keys.justPressed.SEVEN) {
|
||||||
|
FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_DELETE_SOUND));
|
||||||
|
if (devModeCount++ == 2) {
|
||||||
|
FlxTween.tween(devModeWarning, {alpha: 1}, 0.4);
|
||||||
|
}
|
||||||
|
FlxTween.completeTweensOf(devModeWarning);
|
||||||
|
FlxTween.color(devModeWarning, 0.2, 0xFFFF0000, 0xFFFFFFFF);
|
||||||
|
FlxTween.shake(devModeWarning, 0.005, 0.3);
|
||||||
|
devModeWarning.y = FlxG.height - 75;
|
||||||
|
FlxTween.tween(devModeWarning, {y: FlxG.height - 50}, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
var upP = controls.UP_P;
|
var upP = controls.UP_P;
|
||||||
var downP = controls.DOWN_P;
|
var downP = controls.DOWN_P;
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ class PauseSubState extends MusicBeatSubstate
|
|||||||
case "Change Options":
|
case "Change Options":
|
||||||
FlxG.switchState(new OptionsMenu((_) -> FlxG.switchState(new PlayState())));
|
FlxG.switchState(new OptionsMenu((_) -> FlxG.switchState(new PlayState())));
|
||||||
case "Exit to charter":
|
case "Exit to charter":
|
||||||
FlxG.switchState(new Charter(PlayState.SONG.meta.name, PlayState.difficulty, false));
|
FlxG.switchState(new Charter(PlayState.SONG.meta.name, PlayState.difficulty, PlayState.variation, false));
|
||||||
case "Exit to menu":
|
case "Exit to menu":
|
||||||
if (PlayState.chartingMode && Charter.undos.unsaved)
|
if (PlayState.chartingMode && Charter.undos.unsaved)
|
||||||
game.saveWarn(false);
|
game.saveWarn(false);
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ class TitleState extends MusicBeatState
|
|||||||
|
|
||||||
if (pressedEnter && transitioning && skippedIntro) {
|
if (pressedEnter && transitioning && skippedIntro) {
|
||||||
FlxG.camera.stopFX();// FlxG.camera.visible = false;
|
FlxG.camera.stopFX();// FlxG.camera.visible = false;
|
||||||
goToMainMenu();
|
goToMainMenu(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pressedEnter && !transitioning && skippedIntro)
|
if (pressedEnter && !transitioning && skippedIntro)
|
||||||
@@ -152,22 +152,24 @@ class TitleState extends MusicBeatState
|
|||||||
transitioning = true;
|
transitioning = true;
|
||||||
// FlxG.sound.music.stop();
|
// FlxG.sound.music.stop();
|
||||||
|
|
||||||
new FlxTimer().start(2, (_) -> goToMainMenu());
|
new FlxTimer().start(2, (_) -> goToMainMenu(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
function goToMainMenu() {
|
function goToMainMenu(force = true) {
|
||||||
#if UPDATE_CHECKING
|
#if UPDATE_CHECKING
|
||||||
var report = hasCheckedUpdates ? null : funkin.backend.system.updating.UpdateUtil.checkForUpdates();
|
if (!force && !Flags.DISABLE_AUTOUPDATER) {
|
||||||
hasCheckedUpdates = true;
|
funkin.backend.system.updating.UpdateUtil.waitForUpdates(false, (report) -> {
|
||||||
|
hasCheckedUpdates = true;
|
||||||
|
if (FlxG.state != this) return;
|
||||||
|
|
||||||
if (report != null && report.newUpdate) {
|
if (!report.newUpdate) goToMainMenu(true);
|
||||||
FlxG.switchState(new funkin.backend.system.updating.UpdateAvailableScreen(report));
|
else FlxG.switchState(new funkin.backend.system.updating.UpdateAvailableScreen(report));
|
||||||
} else {
|
}, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#end {
|
||||||
FlxG.switchState(new MainMenuState());
|
FlxG.switchState(new MainMenuState());
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
FlxG.switchState(new MainMenuState());
|
|
||||||
#end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createCoolText(textArray:Array<String>)
|
public function createCoolText(textArray:Array<String>)
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ final class AlphabetComponent {
|
|||||||
public var scaleX:Float;
|
public var scaleX:Float;
|
||||||
public var scaleY:Float;
|
public var scaleY:Float;
|
||||||
|
|
||||||
|
public var flipX:Bool;
|
||||||
|
public var flipY:Bool;
|
||||||
|
|
||||||
public var hasColorMode:Bool;
|
public var hasColorMode:Bool;
|
||||||
public var colorMode:ColorMode;
|
public var colorMode:ColorMode;
|
||||||
}
|
}
|
||||||
@@ -346,9 +349,9 @@ class Alphabet extends FlxSprite {
|
|||||||
|
|
||||||
_matrix.translate(_frame.frame.width * -0.5, _frame.frame.height * -0.5);
|
_matrix.translate(_frame.frame.width * -0.5, _frame.frame.height * -0.5);
|
||||||
if (__useDrawScale)
|
if (__useDrawScale)
|
||||||
_matrix.scale(__drawScale.x, __drawScale.y);
|
_matrix.scale(__drawScale.x * (__component.flipX ? -1 : 1), __drawScale.y * (__component.flipY ? -1 : 1));
|
||||||
else
|
else
|
||||||
_matrix.scale(__component.scaleX, __component.scaleY);
|
_matrix.scale(__component.scaleX * (__component.flipX ? -1 : 1), __component.scaleY * (__component.flipY ? -1 : 1));
|
||||||
if(__component.shouldRotate)
|
if(__component.shouldRotate)
|
||||||
_matrix.rotateWithTrig(__component.cos, __component.sin);
|
_matrix.rotateWithTrig(__component.cos, __component.sin);
|
||||||
_matrix.translate(_frame.frame.width * 0.5, _frame.frame.height * 0.5);
|
_matrix.translate(_frame.frame.width * 0.5, _frame.frame.height * 0.5);
|
||||||
@@ -558,6 +561,9 @@ class Alphabet extends FlxSprite {
|
|||||||
cos: angleCos,
|
cos: angleCos,
|
||||||
sin: angleSin,
|
sin: angleSin,
|
||||||
|
|
||||||
|
flipX: node.get("flipX") == "true",
|
||||||
|
flipY: node.get("flipY") == "true",
|
||||||
|
|
||||||
hasColorMode: false,
|
hasColorMode: false,
|
||||||
colorMode: 0
|
colorMode: 0
|
||||||
}],
|
}],
|
||||||
@@ -593,6 +599,9 @@ class Alphabet extends FlxSprite {
|
|||||||
|
|
||||||
var colorMode = ["tint", "offsets", "none"].indexOf(component.get("colorMode"));
|
var colorMode = ["tint", "offsets", "none"].indexOf(component.get("colorMode"));
|
||||||
|
|
||||||
|
var xFlip = component.get("flipX") == "true";
|
||||||
|
var yFlip = component.get("flipY") == "true";
|
||||||
|
|
||||||
if (component.get("hasOutline") == "true") {
|
if (component.get("hasOutline") == "true") {
|
||||||
components.insert(startIndex, {
|
components.insert(startIndex, {
|
||||||
refIndex: componentsPushed,
|
refIndex: componentsPushed,
|
||||||
@@ -608,6 +617,9 @@ class Alphabet extends FlxSprite {
|
|||||||
cos: angleCos,
|
cos: angleCos,
|
||||||
sin: angleSin,
|
sin: angleSin,
|
||||||
|
|
||||||
|
flipX: xFlip,
|
||||||
|
flipY: yFlip,
|
||||||
|
|
||||||
hasColorMode: colorMode >= 0,
|
hasColorMode: colorMode >= 0,
|
||||||
colorMode: colorMode,
|
colorMode: colorMode,
|
||||||
});
|
});
|
||||||
@@ -628,6 +640,9 @@ class Alphabet extends FlxSprite {
|
|||||||
cos: angleCos,
|
cos: angleCos,
|
||||||
sin: angleSin,
|
sin: angleSin,
|
||||||
|
|
||||||
|
flipX: xFlip,
|
||||||
|
flipY: yFlip,
|
||||||
|
|
||||||
hasColorMode: colorMode >= 0,
|
hasColorMode: colorMode >= 0,
|
||||||
colorMode: colorMode,
|
colorMode: colorMode,
|
||||||
});
|
});
|
||||||
@@ -659,6 +674,9 @@ class Alphabet extends FlxSprite {
|
|||||||
var yScale:Float = Std.parseFloat(node.get("scaleY")).getDefaultFloat(1.0);
|
var yScale:Float = Std.parseFloat(node.get("scaleY")).getDefaultFloat(1.0);
|
||||||
var advance:Float = Std.parseFloat(node.get("advance"));
|
var advance:Float = Std.parseFloat(node.get("advance"));
|
||||||
|
|
||||||
|
var xFlip = node.get("flipX") == "true";
|
||||||
|
var yFlip = node.get("flipY") == "true";
|
||||||
|
|
||||||
var colorMode = ["tint", "offsets", "none"].indexOf(node.get("colorMode"));
|
var colorMode = ["tint", "offsets", "none"].indexOf(node.get("colorMode"));
|
||||||
|
|
||||||
var components:Array<AlphabetComponent> = [];
|
var components:Array<AlphabetComponent> = [];
|
||||||
@@ -677,6 +695,9 @@ class Alphabet extends FlxSprite {
|
|||||||
cos: angleCos,
|
cos: angleCos,
|
||||||
sin: angleSin,
|
sin: angleSin,
|
||||||
|
|
||||||
|
flipX: xFlip,
|
||||||
|
flipY: yFlip,
|
||||||
|
|
||||||
hasColorMode: colorMode >= 0,
|
hasColorMode: colorMode >= 0,
|
||||||
colorMode: colorMode,
|
colorMode: colorMode,
|
||||||
});
|
});
|
||||||
@@ -696,6 +717,9 @@ class Alphabet extends FlxSprite {
|
|||||||
cos: angleCos,
|
cos: angleCos,
|
||||||
sin: angleSin,
|
sin: angleSin,
|
||||||
|
|
||||||
|
flipX: xFlip,
|
||||||
|
flipY: yFlip,
|
||||||
|
|
||||||
hasColorMode: colorMode >= 0,
|
hasColorMode: colorMode >= 0,
|
||||||
colorMode: colorMode,
|
colorMode: colorMode,
|
||||||
});
|
});
|
||||||
@@ -758,7 +782,7 @@ class Alphabet extends FlxSprite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static var alphabetProperties:Array<String> = ["fps", "advance", "lineGap", "forceCasing", "useColorOffsets", "antialiasing"];
|
private static var alphabetProperties:Array<String> = ["fps", "advance", "lineGap", "forceCasing", "useColorOffsets", "antialiasing"];
|
||||||
private static var componentProperties:Array<String> = ["name", "anim", "x", "y", "scaleX", "scaleY", "angle", "offsetX", "offsetY"];
|
private static var componentProperties:Array<String> = ["name", "anim", "x", "y", "scaleX", "scaleY", "angle", "offsetX", "offsetY", "flipX", "flipY"];
|
||||||
|
|
||||||
public function buildXML():Xml {
|
public function buildXML():Xml {
|
||||||
var xml = Xml.createElement("alphabet");
|
var xml = Xml.createElement("alphabet");
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ class Options
|
|||||||
*/
|
*/
|
||||||
public static var freeplayLastSong:String = null;
|
public static var freeplayLastSong:String = null;
|
||||||
public static var freeplayLastDifficulty:String = "normal";
|
public static var freeplayLastDifficulty:String = "normal";
|
||||||
|
public static var freeplayLastVariation:String = null;
|
||||||
public static var contributors:Array<funkin.backend.system.github.GitHubContributor.CreditsGitHubContributor> = [];
|
public static var contributors:Array<funkin.backend.system.github.GitHubContributor.CreditsGitHubContributor> = [];
|
||||||
public static var mainDevs:Array<Int> = []; // IDs
|
public static var mainDevs:Array<Int> = []; // IDs
|
||||||
public static var lastUpdated:Null<Float>;
|
public static var lastUpdated:Null<Float>;
|
||||||
@@ -117,6 +118,7 @@ class Options
|
|||||||
public static var P1_ACCEPT:Array<FlxKey> = [ENTER];
|
public static var P1_ACCEPT:Array<FlxKey> = [ENTER];
|
||||||
public static var P1_BACK:Array<FlxKey> = [BACKSPACE];
|
public static var P1_BACK:Array<FlxKey> = [BACKSPACE];
|
||||||
public static var P1_PAUSE:Array<FlxKey> = [ENTER];
|
public static var P1_PAUSE:Array<FlxKey> = [ENTER];
|
||||||
|
public static var P1_CHANGE_MODE:Array<FlxKey> = [TAB];
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
public static var P1_RESET:Array<FlxKey> = [R];
|
public static var P1_RESET:Array<FlxKey> = [R];
|
||||||
@@ -148,6 +150,7 @@ class Options
|
|||||||
public static var P2_ACCEPT:Array<FlxKey> = [SPACE];
|
public static var P2_ACCEPT:Array<FlxKey> = [SPACE];
|
||||||
public static var P2_BACK:Array<FlxKey> = [ESCAPE];
|
public static var P2_BACK:Array<FlxKey> = [ESCAPE];
|
||||||
public static var P2_PAUSE:Array<FlxKey> = [ESCAPE];
|
public static var P2_PAUSE:Array<FlxKey> = [ESCAPE];
|
||||||
|
public static var P2_CHANGE_MODE:Array<FlxKey> = [];
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
public static var P2_RESET:Array<FlxKey> = [];
|
public static var P2_RESET:Array<FlxKey> = [];
|
||||||
@@ -179,6 +182,7 @@ class Options
|
|||||||
public static var SOLO_ACCEPT(get, null):Array<FlxKey>;
|
public static var SOLO_ACCEPT(get, null):Array<FlxKey>;
|
||||||
public static var SOLO_BACK(get, null):Array<FlxKey>;
|
public static var SOLO_BACK(get, null):Array<FlxKey>;
|
||||||
public static var SOLO_PAUSE(get, null):Array<FlxKey>;
|
public static var SOLO_PAUSE(get, null):Array<FlxKey>;
|
||||||
|
public static var SOLO_CHANGE_MODE(get, null):Array<FlxKey>;
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
public static var SOLO_RESET(get, null):Array<FlxKey>;
|
public static var SOLO_RESET(get, null):Array<FlxKey>;
|
||||||
|
|||||||
@@ -151,6 +151,11 @@ class OptionsMenu extends TreeMenu {
|
|||||||
var options:Array<FlxSprite> = [];
|
var options:Array<FlxSprite> = [];
|
||||||
|
|
||||||
for(node in xml.elements) {
|
for(node in xml.elements) {
|
||||||
|
switch(node.name) {
|
||||||
|
case "separator":
|
||||||
|
options.push(new Separator(node.has.height ? Std.parseFloat(node.att.height) : 67));
|
||||||
|
}
|
||||||
|
|
||||||
if (!node.has.name) {
|
if (!node.has.name) {
|
||||||
Logs.warn("An option node requires a name attribute.");
|
Logs.warn("An option node requires a name attribute.");
|
||||||
continue;
|
continue;
|
||||||
@@ -165,7 +170,6 @@ class OptionsMenu extends TreeMenu {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
options.push(new Checkbox(name, desc, node.att.id, null, FlxG.save.data));
|
options.push(new Checkbox(name, desc, node.att.id, null, FlxG.save.data));
|
||||||
|
|
||||||
case "number":
|
case "number":
|
||||||
if (!node.has.id) {
|
if (!node.has.id) {
|
||||||
Logs.warn("A number option requires an \"id\" for option saving.");
|
Logs.warn("A number option requires an \"id\" for option saving.");
|
||||||
@@ -195,7 +199,7 @@ class OptionsMenu extends TreeMenu {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var v:Dynamic = Std.parseFloat(node.att.value);
|
var v:Dynamic = Std.parseFloat(node.att.value);
|
||||||
options.push(new RadioButton(screen, name, desc, node.att.id, v != null ? v : node.att.value, null, FlxG.save.data, node.att.forId));
|
options.push(new RadioButton(screen, name, desc, node.att.id, v != null ? v : node.att.value, null, FlxG.save.data, node.has.forId ? node.att.forId : null));
|
||||||
case 'slider':
|
case 'slider':
|
||||||
if (!node.has.id) {
|
if (!node.has.id) {
|
||||||
Logs.warn("A slider option requires an \"id\" for option saving.");
|
Logs.warn("A slider option requires an \"id\" for option saving.");
|
||||||
@@ -204,10 +208,6 @@ class OptionsMenu extends TreeMenu {
|
|||||||
var step = node.has.change ? Std.parseFloat(node.att.change) : (node.has.step ? Std.parseFloat(node.att.step) : null);
|
var step = node.has.change ? Std.parseFloat(node.att.change) : (node.has.step ? Std.parseFloat(node.att.step) : null);
|
||||||
var segments = node.has.segments ? Std.parseInt(node.att.segments) : 5;
|
var segments = node.has.segments ? Std.parseInt(node.att.segments) : 5;
|
||||||
options.push(new SliderOption(name, desc, Std.parseFloat(node.att.min), Std.parseFloat(node.att.max), step, segments, node.att.id, Std.parseInt(node.att.barWidth), null, FlxG.save.data));
|
options.push(new SliderOption(name, desc, Std.parseFloat(node.att.min), Std.parseFloat(node.att.max), step, segments, node.att.id, Std.parseInt(node.att.barWidth), null, FlxG.save.data));
|
||||||
|
|
||||||
case 'separator':
|
|
||||||
options.push(new Separator(Std.parseInt(node.att.height)));
|
|
||||||
|
|
||||||
case "menu":
|
case "menu":
|
||||||
options.push(new TextOption(name, desc, ' >', () -> {
|
options.push(new TextOption(name, desc, ' >', () -> {
|
||||||
var screen = new TreeMenuScreen(name, desc);
|
var screen = new TreeMenuScreen(name, desc);
|
||||||
|
|||||||
@@ -128,11 +128,12 @@ class TreeMenuScreen extends FlxSpriteGroup {
|
|||||||
var i = curSelected, y = initY, object:FlxSprite = null, itemHeight:Float = 0;
|
var i = curSelected, y = initY, object:FlxSprite = null, itemHeight:Float = 0;
|
||||||
|
|
||||||
inline function updateItem() {
|
inline function updateItem() {
|
||||||
object.y = CoolUtil.fpsLerp(object.y, y - (itemHeight = object.height) * 0.5, r);
|
object.y = CoolUtil.fpsLerp(object.y, y - itemHeight * 0.5, r);
|
||||||
object.x = x + 100 - Math.pow(Math.abs((object.y - (FlxG.height - itemHeight) * 0.5) / itemHeight / FlxG.height * FlxG.initialHeight), 1.6) * 15;
|
object.x = x + 100 - Math.pow(Math.abs((object.y - (FlxG.height - itemHeight) * 0.5) / itemHeight / FlxG.height * FlxG.initialHeight), 1.6) * 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (i < length) if ((object = members[i++]) != null) {
|
while (i < length) if ((object = members[i++]) != null) {
|
||||||
|
itemHeight = object.height;
|
||||||
updateItem();
|
updateItem();
|
||||||
y += itemHeight;
|
y += itemHeight;
|
||||||
}
|
}
|
||||||
@@ -140,7 +141,7 @@ class TreeMenuScreen extends FlxSpriteGroup {
|
|||||||
y = initY;
|
y = initY;
|
||||||
i = curSelected;
|
i = curSelected;
|
||||||
while (i-- > 0) if ((object = members[i]) != null) {
|
while (i-- > 0) if ((object = members[i]) != null) {
|
||||||
y -= itemHeight;
|
y -= (itemHeight = object.height);
|
||||||
updateItem();
|
updateItem();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ class MiscOptions extends TreeMenuScreen {
|
|||||||
#if UPDATE_CHECKING
|
#if UPDATE_CHECKING
|
||||||
add(new Checkbox(getNameID('betaUpdates'), getDescID('betaUpdates'), 'betaUpdates'));
|
add(new Checkbox(getNameID('betaUpdates'), getDescID('betaUpdates'), 'betaUpdates'));
|
||||||
add(new TextOption(getNameID('checkForUpdates'), getDescID('checkForUpdates'), () -> {
|
add(new TextOption(getNameID('checkForUpdates'), getDescID('checkForUpdates'), () -> {
|
||||||
var report = funkin.backend.system.updating.UpdateUtil.checkForUpdates();
|
var report = funkin.backend.system.updating.UpdateUtil.checkForUpdates(true);
|
||||||
if (report.newUpdate) FlxG.switchState(new funkin.backend.system.updating.UpdateAvailableScreen(report));
|
if (report.newUpdate) FlxG.switchState(new funkin.backend.system.updating.UpdateAvailableScreen(report));
|
||||||
else {
|
else {
|
||||||
CoolUtil.playMenuSFX(CANCEL);
|
CoolUtil.playMenuSFX(CANCEL);
|
||||||
updateDescText(translate('checkForUpdates-noUpdateFound'));
|
//updateDescText(translate('checkForUpdates-noUpdateFound'));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
#end
|
#end
|
||||||
|
|||||||