Compare commits
32
Commits
v1.0.1-rc1
...
v1.0.1-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a6f4819a9 | ||
|
|
e24a62a0b7 | ||
|
|
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 |
@@ -2,12 +2,18 @@
|
||||
name: Bug Report
|
||||
about: Report a bug or critical performance issue
|
||||
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 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?
|
||||
[weed]: <> (CHANGE [ ] TO [x] IN FRONT OF YOUR TARGET!)
|
||||
|
||||
@@ -17,4 +23,4 @@ labels: bug
|
||||
|
||||
### Explain your issue
|
||||
##### Please check first if your issue haven't already been reported yet.
|
||||
[weed]: <> (MAKE SURE TO ADD A SCREENSHOT OF THE CRASH HANDLER, IF AVAILABLE, AND STEPS TO REPRODUCE THE BUG!)
|
||||
[weed]: <> (MAKE SURE TO ADD A SCREENSHOT OF THE CRASH HANDLER, IF AVAILABLE, AND STEPS TO REPRODUCE THE BUG!)
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
---
|
||||
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]'
|
||||
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.)
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
name: Enhancement
|
||||
about: Suggest a new feature
|
||||
title: 'Enhancement: '
|
||||
labels: enhancement
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
#### Please check for duplicates or similar issues before creating this issue.
|
||||
## What is your suggestion, and why should it be implemented?
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
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)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
|
||||
Vendored
+33
-1
@@ -6,5 +6,37 @@
|
||||
"*.hscript": "haxe",
|
||||
"*.hsc": "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"]
|
||||
},
|
||||
]
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 210 B |
Binary file not shown.
|
After Width: | Height: | Size: 215 B |
@@ -9,6 +9,8 @@
|
||||
<str id="save">Save</str>
|
||||
<str id="saveClose">Save & Close</str>
|
||||
<str id="close">Close</str>
|
||||
<str id="notNow">Not Now</str>
|
||||
<str id="yes">Yes</str>
|
||||
</group>
|
||||
|
||||
<group name="UIImageExplorer" prefix="uiImageExplorer.">
|
||||
@@ -111,6 +113,7 @@
|
||||
<str id="color">Color</str>
|
||||
<str id="difficulties">Difficulties</str>
|
||||
<str id="customValues">Custom Values (Advanced)</str>
|
||||
<str id="needsVoices">Needs Voices</str>
|
||||
|
||||
<str id="opponentMode">Opponent Mode</str>
|
||||
<str id="coopAllowed">Co-op Mode</str>
|
||||
@@ -665,4 +668,12 @@
|
||||
<str id="saveAndExitToMenu">Save & Exit To Menu</str>
|
||||
<str id="cancel">Cancel</str>
|
||||
</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>
|
||||
@@ -42,6 +42,7 @@
|
||||
<str id="back">Back</str>
|
||||
<str id="reset">Reset</str>
|
||||
<str id="pause">Pause</str>
|
||||
<str id="changeMode">Change Mode</str>
|
||||
</group>
|
||||
|
||||
<str id="category.engine">Engine</str>
|
||||
@@ -50,6 +51,8 @@
|
||||
</group>
|
||||
|
||||
<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="category.developer">Developer</str>
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
<str id="modesAllowed">Modos Permitidos</str>
|
||||
<str id="difficulties">Difficultades</str>
|
||||
<str id="customValues">Valores Especiales (Avanzado)</str>
|
||||
<str id="needsVoices">Necesita Voces</str>
|
||||
|
||||
<str id="opponentMode">Modo Oponente</str>
|
||||
<str id="coopAllowed">Modo Co-op</str>
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
</group>
|
||||
|
||||
<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="category.developer">Desarrollador</str>
|
||||
|
||||
@@ -108,8 +108,9 @@
|
||||
<str id="color">Colore</str>
|
||||
<str id="difficulties">Difficoltà</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>
|
||||
</group>
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@
|
||||
<str id="switchMod">Cambia Mod</str>
|
||||
</group>
|
||||
|
||||
<str id="volume.up">Su</str>
|
||||
<str id="volume.down">Giù</str>
|
||||
<str id="volume.mute">Muto</str>
|
||||
|
||||
<str id="category.developer">Sviluppatore</str>
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
<str id="save">Zapisz</str>
|
||||
<str id="saveClose">Zapisz i Zamknij</str>
|
||||
<str id="close">Zamknij</str>
|
||||
<str id="notNow">Nie Teraz</str>
|
||||
<str id="yes">Tak</str>
|
||||
</group>
|
||||
|
||||
<group name="UIImageExplorer" prefix="uiImageExplorer.">
|
||||
@@ -109,6 +111,7 @@
|
||||
<str id="color">Kolor</str>
|
||||
<str id="difficulties">Trudności</str>
|
||||
<str id="customValues">Własna Waluta (Zaawansowane)</str>
|
||||
<str id="needsVoices">Potrzebne Wokale</str>
|
||||
|
||||
<str id="opponentMode">Tryb Przeciwnika</str>
|
||||
<str id="coopAllowed">Tryb Ko-operacyjny</str>
|
||||
@@ -653,4 +656,12 @@
|
||||
<str id="saveAndExitToMenu">Zapisz i Wyjdź do Menu</str>
|
||||
<str id="cancel">Anuluj</str>
|
||||
</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>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<str id="credits.allContributors">Wszyscy współpracownicy silnika! - Naciśnij RESET aby zaktualizować listę (Jeden reset co 2 minuty).</str>
|
||||
</group>
|
||||
<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.selectCodename">Wybierz to aby zobaczyć wszystkich współpracowników!</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="reset">Reset</str>
|
||||
<str id="pause">Pauza</str>
|
||||
<str id="changeMode">Zmień Tryb</str>
|
||||
</group>
|
||||
|
||||
<str id="category.engine">Silnik</str>
|
||||
@@ -46,6 +47,8 @@
|
||||
</group>
|
||||
|
||||
<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="category.developer">Deweloper</str>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 68 KiB |
@@ -1,15 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<TextureAtlas imagePath="credits.png" width="3020" height="169">
|
||||
<SubTexture name="credits basic0000" x="1" y="1" width="430" height="114" frameX="-0" frameY="-0" frameWidth="430" frameHeight="114"/>
|
||||
<SubTexture name="credits basic0001" x="1" y="1" width="430" height="114" frameX="-0" frameY="-0" frameWidth="430" frameHeight="114"/>
|
||||
<SubTexture name="credits basic0002" x="1" y="1" width="430" height="114" frameX="-0" frameY="-0" frameWidth="430" frameHeight="114"/>
|
||||
<SubTexture name="credits basic0003" x="433" y="1" width="430" height="114" frameX="-0" frameY="-0" frameWidth="430" frameHeight="114"/>
|
||||
<SubTexture name="credits basic0004" x="433" y="1" width="430" height="114" frameX="-0" frameY="-0" frameWidth="430" frameHeight="114"/>
|
||||
<SubTexture name="credits basic0005" x="433" y="1" width="430" height="114" frameX="-0" frameY="-0" frameWidth="430" frameHeight="114"/>
|
||||
<SubTexture name="credits basic0006" x="865" y="1" width="430" height="114" frameX="-0" frameY="-0" frameWidth="430" frameHeight="114"/>
|
||||
<SubTexture name="credits basic0007" x="865" y="1" width="430" height="114" frameX="-0" frameY="-0" frameWidth="430" frameHeight="114"/>
|
||||
<SubTexture name="credits basic0008" x="865" y="1" width="430" height="114" frameX="-0" frameY="-0" frameWidth="430" frameHeight="114"/>
|
||||
<SubTexture name="credits white0000" x="1297" y="1" width="574" height="164" frameX="-0" frameY="24" frameWidth="574" frameHeight="169"/>
|
||||
<SubTexture name="credits white0001" x="2446" y="1" width="573" height="167" frameX="-0" frameY="25" frameWidth="574" frameHeight="169"/>
|
||||
<SubTexture name="credits white0002" x="1873" y="1" width="571" height="165" frameX="-0" frameY="21" frameWidth="574" frameHeight="169"/>
|
||||
<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>
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
title="Friday Night Funkin' - Codename Engine" main="funkin.backend.system.Main"
|
||||
file="CodenameEngine" packageName="com.yoshman29.codenameengine"
|
||||
package="com.yoshman29.codenameengine"
|
||||
version="1.0.1" company="Yoshman29" />
|
||||
version="1.0.1-rc2" company="Yoshman29" />
|
||||
|
||||
<!--
|
||||
CHANGE THE SAVE PATH & NAME FOR YOUR MOD HERE!
|
||||
|
||||
@@ -38,6 +38,7 @@ class Paths
|
||||
for (entry in entries) {
|
||||
if (entry.toLowerCase() == part.toLowerCase()) {
|
||||
fixedPath += entry + (it != parts.length - 1 ? "/" : "");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,18 +89,18 @@ class Paths
|
||||
inline static public function music(key:String, ?library:String, ?ext:String)
|
||||
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 (ext == null) ext = Flags.SOUND_EXT;
|
||||
var diff = getPath('songs/$song/song/Voices$prefix-${difficulty}.${ext}', null);
|
||||
return OpenFlAssets.exists(diff) ? diff : getPath('songs/$song/song/Voices$prefix.${ext}', null);
|
||||
var diff = getPath('songs/$song/song/Voices$suffix-${difficulty}.${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 (ext == null) ext = Flags.SOUND_EXT;
|
||||
var diff = getPath('songs/$song/song/Inst$prefix-${difficulty}.${ext}', null);
|
||||
return OpenFlAssets.exists(diff) ? diff : getPath('songs/$song/song/Inst$prefix.${ext}', null);
|
||||
var diff = getPath('songs/$song/song/Inst$suffix-${difficulty}.${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) {
|
||||
|
||||
@@ -83,13 +83,11 @@ class Chart {
|
||||
return data;
|
||||
}
|
||||
|
||||
public static function loadChartMeta(songName:String, ?difficulty:String, fromMods:Bool = true):ChartMetaData {
|
||||
if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY;
|
||||
|
||||
public static function loadChartMeta(songName:String, difficulty:String = '', fromMods:Bool = true, includeMetaDifficulties:Bool = true):ChartMetaData {
|
||||
var metaPath = Paths.file('songs/${songName}/meta.json');
|
||||
var metaDiffPath = Paths.file('songs/${songName}/meta-${difficulty}.json');
|
||||
|
||||
var data:ChartMetaData = null;
|
||||
var data:ChartMetaData = null, fromDifficulty = false;
|
||||
var fromMods:Bool = fromMods;
|
||||
for (path in [metaDiffPath, metaPath]) if (Assets.exists(path)) {
|
||||
fromMods = Paths.assetsTree.existsSpecific(path, "TEXT", MODS);
|
||||
@@ -98,24 +96,33 @@ class Chart {
|
||||
tempData.color = CoolUtil.getColorFromDynamic(tempData.color).getDefault(Flags.DEFAULT_COLOR);
|
||||
data = tempData;
|
||||
} catch(e) Logs.trace('Failed to load song metadata for ${songName} ($path): ${Std.string(e)}', ERROR);
|
||||
if (data != null) break;
|
||||
if (data != null) {
|
||||
fromDifficulty = path == metaDiffPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (data == null) data = {
|
||||
name: songName,
|
||||
bpm: 100
|
||||
};
|
||||
if (data == null) {
|
||||
data = {
|
||||
name: songName,
|
||||
bpm: Flags.DEFAULT_BPM
|
||||
};
|
||||
}
|
||||
else {
|
||||
data.name = songName;
|
||||
data.setFieldDefault("bpm", Flags.DEFAULT_BPM);
|
||||
}
|
||||
|
||||
data.name = songName;
|
||||
data.setFieldDefault("bpm", Flags.DEFAULT_BPM);
|
||||
data.setFieldDefault("displayName", data.name);
|
||||
data.setFieldDefault("beatsPerMeasure", Flags.DEFAULT_BEATS_PER_MEASURE);
|
||||
data.setFieldDefault("stepsPerBeat", Flags.DEFAULT_STEPS_PER_BEAT);
|
||||
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);
|
||||
data.setFieldDefault("instSuffix", "");
|
||||
data.setFieldDefault("vocalsSuffix", "");
|
||||
data.setFieldDefault("needsVoices", true);
|
||||
|
||||
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)];
|
||||
@@ -132,6 +139,14 @@ class Chart {
|
||||
}
|
||||
}
|
||||
|
||||
if (includeMetaDifficulties && !fromDifficulty) {
|
||||
data.metas = [];
|
||||
for (difficulty in data.difficulties) {
|
||||
if (!data.metas.exists(difficulty) && Assets.exists(Paths.file('songs/${songName}/meta-${difficulty}.json')))
|
||||
data.metas.set(difficulty, loadChartMeta(songName, difficulty, fromMods, false));
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -265,7 +280,7 @@ class Chart {
|
||||
|
||||
CoolUtil.safeSaveFile(chartPath, Json.stringify(filteredChart, null, saveSettings.prettyPrint == true ? Flags.JSON_PRETTY_PRINT : null));
|
||||
|
||||
if (saveSettings.overrideExistingMeta == true || !FileSystem.exists(metaPath))
|
||||
if (meta != null && (saveSettings.overrideExistingMeta || !FileSystem.exists(metaPath)))
|
||||
CoolUtil.safeSaveFile(metaPath, makeMetaSaveable(meta));
|
||||
#end
|
||||
return filteredChart;
|
||||
@@ -305,7 +320,8 @@ class Chart {
|
||||
|
||||
public static inline function makeMetaSaveable(meta:ChartMetaData, prettyPrint:Bool = true):String {
|
||||
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
|
||||
Reflect.deleteField(data, 'metas');
|
||||
return Json.stringify(data, null, prettyPrint ? Flags.JSON_PRETTY_PRINT : null);
|
||||
}
|
||||
}
|
||||
@@ -317,4 +333,4 @@ typedef ChartSaveSettings = {
|
||||
var ?saveGlobalEvents:Bool;
|
||||
var ?prettyPrint:Bool;
|
||||
var ?folder:String;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@ typedef ChartMetaData = {
|
||||
public var ?coopAllowed: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;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ class VSliceParser {
|
||||
|
||||
var timeChanges = metadata.timeChanges;
|
||||
result.meta.bpm = timeChanges[0].bpm;
|
||||
result.meta.needsVoices = true;
|
||||
result.meta.needsVoices = false;
|
||||
|
||||
for (note in data)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@ enum Control
|
||||
ACCEPT;
|
||||
BACK;
|
||||
PAUSE;
|
||||
CHANGE_MODE;
|
||||
//CHEAT;
|
||||
SWITCHMOD;
|
||||
|
||||
@@ -145,6 +146,11 @@ class Controls extends FlxActionSet
|
||||
@:pressed("reset") public var RESET_HOLD(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([])
|
||||
//@:justPressed("cheat") public var CHEAT(get, set): Bool;
|
||||
//@:pressed("cheat") public var CHEAT_HOLD(get, set): Bool;
|
||||
|
||||
@@ -196,6 +196,7 @@ class Flags {
|
||||
public static var DISABLE_WARNING_SCREEN:Bool = true;
|
||||
public static var DISABLE_TRANSITIONS:Bool = false;
|
||||
public static var DISABLE_LANGUAGES:Bool = false;
|
||||
public static var DISABLE_AUTOUPDATER:Bool = false;
|
||||
|
||||
@:also(funkin.backend.MusicBeatTransition.script)
|
||||
public static var DEFAULT_TRANSITION_SCRIPT:String = "";
|
||||
@@ -285,7 +286,10 @@ class Flags {
|
||||
}
|
||||
}
|
||||
|
||||
if (!flags.exists("WINDOW_TITLE_USE_MOD_NAME")) flags.set("WINDOW_TITLE_USE_MOD_NAME", flags.exists('TITLE') ? 'false' : 'true');
|
||||
if (!flags.exists("WINDOW_TITLE_USE_MOD_NAME")) WINDOW_TITLE_USE_MOD_NAME = !flags.exists('TITLE');
|
||||
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>) {
|
||||
|
||||
@@ -12,13 +12,13 @@ import haxe.Exception;
|
||||
* Requires the `GITHUB_API` macro to be defined.
|
||||
* 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.
|
||||
* @param user The user/organization that owns the repository
|
||||
* @param repository The repository name
|
||||
* @param onError Error Callback
|
||||
* @return Releases
|
||||
* @param user The user/organization that owns the repository.
|
||||
* @param repository The repository name.
|
||||
* @param onError Error Callback.
|
||||
* @return Releases in Array.
|
||||
*/
|
||||
public static function getReleases(user:String, repository:String, ?onError:Exception->Void):Array<GitHubRelease> {
|
||||
#if GITHUB_API
|
||||
@@ -38,17 +38,16 @@ class GitHub {
|
||||
|
||||
/**
|
||||
* Gets the contributors list from a specific GitHub repository using the GitHub API.
|
||||
* @param user The user/organization that owns the repository
|
||||
* @param repository The repository name
|
||||
* @param onError Error Callback
|
||||
* @return Contributors List
|
||||
* @param user The user/organization that owns the repository.
|
||||
* @param repository The repository name.
|
||||
* @param onError Error Callback.
|
||||
* @return Contributors List as Array.
|
||||
*/
|
||||
public static function getContributors(user:String, repository:String, ?onError:Exception->Void):Array<GitHubContributor> {
|
||||
#if GITHUB_API
|
||||
try {
|
||||
var data = Json.parse(HttpUtil.requestText('https://api.github.com/repos/${user}/${repository}/contributors'));
|
||||
if (!(data is Array))
|
||||
throw __parseGitHubException(data);
|
||||
if (!(data is Array)) throw __parseGitHubException(data);
|
||||
|
||||
return data;
|
||||
} catch(e) {
|
||||
@@ -61,16 +60,15 @@ class GitHub {
|
||||
|
||||
/**
|
||||
* Gets a specific GitHub organization using the GitHub API.
|
||||
* @param org The organization to get
|
||||
* @param onError Error Callback
|
||||
* @return Organization
|
||||
* @param org The organization to get.
|
||||
* @param onError Error Callback.
|
||||
* @return Organization.
|
||||
*/
|
||||
public static function getOrganization(org:String, ?onError:Exception->Void):GitHubOrganization {
|
||||
#if GITHUB_API
|
||||
try {
|
||||
var data = Json.parse(HttpUtil.requestText('https://api.github.com/orgs/$org'));
|
||||
if (Reflect.hasField(data, "documentation_url"))
|
||||
throw __parseGitHubException(data);
|
||||
if (Reflect.hasField(data, "documentation_url")) throw __parseGitHubException(data);
|
||||
|
||||
return data;
|
||||
} catch(e) {
|
||||
@@ -84,16 +82,15 @@ class GitHub {
|
||||
/**
|
||||
* Gets the members list from a specific GitHub organization using the GitHub API.
|
||||
* NOTE: Members use Contributors' structure!
|
||||
* @param org The organization to get the members from
|
||||
* @param onError Error Callback
|
||||
* @return Members List
|
||||
* @param org The organization to get the members from.
|
||||
* @param onError Error Callback.
|
||||
* @return Members List as Array
|
||||
*/
|
||||
public static function getOrganizationMembers(org:String, ?onError:Exception->Void):Array<GitHubContributor> {
|
||||
#if GITHUB_API
|
||||
try {
|
||||
var data = Json.parse(HttpUtil.requestText('https://api.github.com/orgs/$org/members'));
|
||||
if (Reflect.hasField(data, "documentation_url"))
|
||||
throw __parseGitHubException(data);
|
||||
if (Reflect.hasField(data, "documentation_url")) throw __parseGitHubException(data);
|
||||
|
||||
return data;
|
||||
} catch(e) {
|
||||
@@ -107,18 +104,15 @@ class GitHub {
|
||||
/**
|
||||
* 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!
|
||||
* @param user The user/organization to get
|
||||
* @param onError Error Callback
|
||||
* @return User/Organization
|
||||
* @param user The user/organization to get.
|
||||
* @param onError Error Callback.
|
||||
* @return User/Organization.
|
||||
*/
|
||||
public static function getUser(user:String, ?onError:Exception->Void):GitHubUser {
|
||||
#if GITHUB_API
|
||||
try {
|
||||
var url = 'https://api.github.com/users/$user';
|
||||
|
||||
var data = Json.parse(HttpUtil.requestText(url));
|
||||
if (Reflect.hasField(data, "documentation_url"))
|
||||
throw __parseGitHubException(data);
|
||||
var data = Json.parse(HttpUtil.requestText('https://api.github.com/users/$user'));
|
||||
if (Reflect.hasField(data, "documentation_url")) throw __parseGitHubException(data);
|
||||
|
||||
return data;
|
||||
} catch(e) {
|
||||
|
||||
@@ -33,11 +33,9 @@ class FlagMacro {
|
||||
resetExprs.push(macro $i{"customFlags"} = $v{[]});
|
||||
|
||||
for (field in fields) {
|
||||
var skip = field.meta.hasMeta(":bypass");
|
||||
if (field.meta.hasMeta(":bypass")) continue;
|
||||
var hasLazy = field.meta.hasMeta(":lazy");
|
||||
|
||||
if (skip) continue;
|
||||
|
||||
switch (field.kind) {
|
||||
case FVar(type, expr):
|
||||
var isNullable = false;
|
||||
|
||||
@@ -24,7 +24,11 @@ class UpdateAvailableScreen extends MusicBeatState {
|
||||
|
||||
public function new(check:UpdateCheckCallback) {
|
||||
super();
|
||||
|
||||
this.check = check;
|
||||
if (Date.now().getTime() - check.date.getTime() > 15000) {
|
||||
if ((check = UpdateUtil.checkForUpdates(true)).newUpdate) this.check = check;
|
||||
}
|
||||
}
|
||||
|
||||
public override function create() {
|
||||
|
||||
@@ -2,60 +2,97 @@ package funkin.backend.system.updating;
|
||||
|
||||
import funkin.backend.system.github.GitHub;
|
||||
import funkin.backend.system.github.GitHubRelease;
|
||||
import haxe.io.Path;
|
||||
|
||||
import lime.app.Application;
|
||||
|
||||
import sys.thread.Mutex;
|
||||
import sys.thread.Thread;
|
||||
import sys.FileSystem;
|
||||
|
||||
import haxe.io.Path;
|
||||
|
||||
using funkin.backend.system.github.GitHub;
|
||||
|
||||
class UpdateUtil {
|
||||
public static var lastUpdateCheck:Null<UpdateCheckCallback>;
|
||||
|
||||
private static var __waitCallbacks:Array<UpdateCheckCallback->Void>;
|
||||
private static var __mutex:Mutex;
|
||||
|
||||
public static function init() {
|
||||
// deletes old bak file if it exists
|
||||
#if sys
|
||||
var bakPath = '${Path.withoutExtension(Sys.programPath())}.bak';
|
||||
if (FileSystem.exists(bakPath))
|
||||
FileSystem.deleteFile(bakPath);
|
||||
if (FileSystem.exists(bakPath)) FileSystem.deleteFile(bakPath);
|
||||
#end
|
||||
|
||||
__waitCallbacks = [];
|
||||
__mutex = new Mutex();
|
||||
Thread.create(checkForUpdates.bind(true, false));
|
||||
}
|
||||
|
||||
public static function checkForUpdates():UpdateCheckCallback {
|
||||
var curTag = 'v${Flags.VERSION}';
|
||||
trace("Current version: " + curTag);
|
||||
public static function waitForUpdates(force = false, callback:UpdateCheckCallback->Void, lazy = false) {
|
||||
if (__mutex.tryAcquire()) {
|
||||
__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_OWNER, Flags.REPO_NAME, 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}', error = false;
|
||||
var newUpdates = __doReleaseFiltering(GitHub.getReleases(Flags.REPO_OWNER, Flags.REPO_NAME, (e) -> {
|
||||
error = true;
|
||||
}), curTag);
|
||||
|
||||
if (error) return {
|
||||
success: false,
|
||||
newUpdate: false
|
||||
};
|
||||
|
||||
if (newUpdates.length <= 0) {
|
||||
return {
|
||||
success: true,
|
||||
newUpdate: false
|
||||
};
|
||||
var updateCheck:UpdateCheckCallback = {
|
||||
success: !error,
|
||||
newUpdate: !error && newUpdates.length > 0,
|
||||
currentVersionTag: curTag,
|
||||
date: Date.now()
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
newUpdate: true,
|
||||
currentVersionTag: curTag,
|
||||
newVersionTag: newUpdates.last().tag_name,
|
||||
updates: newUpdates
|
||||
};
|
||||
if (updateCheck.newUpdate) updateCheck.newVersionTag = (updateCheck.updates = newUpdates).last().tag_name;
|
||||
return updateCheck;
|
||||
}
|
||||
|
||||
static function __shouldCheck(lazy:Bool):Bool
|
||||
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) {
|
||||
releases = releases.filterReleases(Options.betaUpdates, false);
|
||||
if (releases.length <= 0)
|
||||
return releases;
|
||||
|
||||
var newArray:Array<GitHubRelease> = [];
|
||||
var newArray:Array<GitHubRelease> = [], __curVersionPos = -2;
|
||||
|
||||
var skipNextBinaryChecks:Bool = false;
|
||||
for(index in 0...releases.length) {
|
||||
@@ -73,12 +110,9 @@ class UpdateUtil {
|
||||
}
|
||||
if (containsBinary) {
|
||||
skipNextBinaryChecks = true; // no need to check for older versions
|
||||
if (release.tag_name == currentVersionTag) {
|
||||
__curVersionPos = -1;
|
||||
}
|
||||
if (release.tag_name == currentVersionTag) __curVersionPos = -1;
|
||||
newArray.insert(0, release);
|
||||
if (__curVersionPos > -2)
|
||||
__curVersionPos++;
|
||||
if (__curVersionPos > -2) __curVersionPos++;
|
||||
}
|
||||
}
|
||||
if (__curVersionPos < -1)
|
||||
@@ -98,4 +132,6 @@ typedef UpdateCheckCallback = {
|
||||
@:optional var newVersionTag:String;
|
||||
|
||||
@:optional var updates:Array<GitHubRelease>;
|
||||
|
||||
@:optional var date:Date;
|
||||
}
|
||||
@@ -474,7 +474,7 @@ final class AudioAnalyzer {
|
||||
var n = Math.floor((endPos - startPos) * __toBits);
|
||||
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;
|
||||
while (pos > size) {
|
||||
while (pos >= size) {
|
||||
if (++i >= backend.bufferSizes.length) {
|
||||
n = 0;
|
||||
break;
|
||||
@@ -484,6 +484,7 @@ final class AudioAnalyzer {
|
||||
size = backend.bufferSizes[i];
|
||||
}
|
||||
pos -= pos % __sampleSize;
|
||||
n -= pos % __sampleSize;
|
||||
|
||||
while (n > 0) {
|
||||
callback(getByte(buf, pos, __wordSize), c);
|
||||
|
||||
@@ -29,9 +29,6 @@ final class WindowUtils {
|
||||
public static inline function resetClosing() __triedClosing = false;
|
||||
|
||||
@:dox(hide) public static inline function init() {
|
||||
resetTitle();
|
||||
resetClosing();
|
||||
|
||||
Lib.application.window.onClose.add(function () {
|
||||
if (preventClosing && !__triedClosing) {
|
||||
Lib.application.window.onClose.cancel();
|
||||
|
||||
@@ -56,9 +56,9 @@ LOGO_TEXT=""
|
||||
super.createPost();
|
||||
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,
|
||||
onClick: function (_) {
|
||||
MusicBeatState.skipTransOut = MusicBeatState.skipTransIn = false;
|
||||
@@ -66,13 +66,13 @@ LOGO_TEXT=""
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "Yes",
|
||||
label: TU.translate("editor.yes"),
|
||||
onClick: function(_) {
|
||||
var path = '${library.folderPath}/data/config/modpack.ini';
|
||||
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 (_) {
|
||||
MusicBeatState.skipTransOut = MusicBeatState.skipTransIn = false;
|
||||
FlxG.switchState(cast Type.createInstance(goToState, []));
|
||||
|
||||
@@ -209,6 +209,9 @@ class AlphabetEditor extends UIState {
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
|
||||
flipX: false,
|
||||
flipY: false,
|
||||
|
||||
hasColorMode: false,
|
||||
colorMode: bigLetter.colorMode
|
||||
};
|
||||
|
||||
@@ -204,6 +204,9 @@ UPPERLETTER and LOWERLETTTER can be used in any backup prefix.";
|
||||
cos: 1.0,
|
||||
sin: 0.0,
|
||||
|
||||
flipX: false,
|
||||
flipY: false,
|
||||
|
||||
hasColorMode: false,
|
||||
colorMode: 0
|
||||
}],
|
||||
|
||||
@@ -11,6 +11,9 @@ class GlyphInfoWindow extends UIWindow {
|
||||
public var angleBox:UINumericStepper;
|
||||
public var colorModeDrop:UIDropDown;
|
||||
|
||||
public var flipXBox:UICheckbox;
|
||||
public var flipYBox:UICheckbox;
|
||||
|
||||
public var outlineTitle:UIText;
|
||||
public var outlineSep:UISprite;
|
||||
public var outlineCheck:UICheckbox;
|
||||
@@ -145,6 +148,9 @@ class GlyphInfoWindow extends UIWindow {
|
||||
cos: compon.cos,
|
||||
sin: compon.sin,
|
||||
|
||||
flipX: compon.flipX,
|
||||
flipY: compon.flipY,
|
||||
|
||||
hasColorMode: compon.hasColorMode,
|
||||
colorMode: compon.colorMode
|
||||
};
|
||||
@@ -159,6 +165,22 @@ class GlyphInfoWindow extends UIWindow {
|
||||
}
|
||||
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");
|
||||
members.push(outlineTitle);
|
||||
outlineSep = new UISprite(x + itemMargin, colorModeDrop.y + colorModeDrop.bHeight + itemMargin + 19);
|
||||
@@ -239,6 +261,8 @@ class GlyphInfoWindow extends UIWindow {
|
||||
angleBox.value = com.angle;
|
||||
@:privateAccess colorModeDrop.index = com.hasColorMode ? com.colorMode : AlphabetEditor.instance.tape.colorMode;
|
||||
@:privateAccess colorModeDrop.label.text = colorModeDrop.options[colorModeDrop.index];
|
||||
flipXBox.checked = com.flipX;
|
||||
flipYBox.checked = com.flipY;
|
||||
|
||||
outlineCheck.checked = com.outIndex != null;
|
||||
outlineBox.label.text = "";
|
||||
|
||||
@@ -601,11 +601,13 @@ class Charter extends UIState {
|
||||
Conductor.setupSong(PlayState.SONG);
|
||||
noteTypes = PlayState.SONG.noteTypes;
|
||||
|
||||
FlxG.sound.setMusic(FlxG.sound.load(Paths.inst(__song, __diff)));
|
||||
if (PlayState.SONG.meta.needsVoices != false && Assets.exists(Paths.voices(__song, __diff))) // null or true
|
||||
vocals = FlxG.sound.load(Paths.voices(__song, __diff));
|
||||
FlxG.sound.setMusic(FlxG.sound.load(Paths.inst(__song, __diff, PlayState.SONG.meta.instSuffix)));
|
||||
if (Assets.exists(Paths.voices(__song, __diff, PlayState.SONG.meta.vocalsSuffix)))
|
||||
vocals = FlxG.sound.load(Paths.voices(__song, __diff, PlayState.SONG.meta.vocalsSuffix));
|
||||
else
|
||||
vocals = new FlxSound();
|
||||
|
||||
vocals.muted = !PlayState.SONG.meta.needsVoices;
|
||||
vocals.group = FlxG.sound.defaultMusicGroup;
|
||||
|
||||
gridBackdrops.createGrids(PlayState.SONG.strumLines.length);
|
||||
@@ -683,7 +685,7 @@ class Charter extends UIState {
|
||||
if (FlxG.sound.music.loaded)
|
||||
wavesToGenerate.push({name: "Inst.ogg", sound: FlxG.sound.music});
|
||||
|
||||
if (PlayState.SONG.meta.needsVoices != false && vocals.loaded)
|
||||
if (vocals.loaded)
|
||||
wavesToGenerate.push({name: "Voices.ogg", sound: vocals});
|
||||
|
||||
for (strumLine in strumLines)
|
||||
|
||||
@@ -23,6 +23,7 @@ class CharterMetaDataScreen extends UISubstateWindow {
|
||||
public var iconSprite:HealthIcon;
|
||||
public var opponentModeCheckbox:UICheckbox;
|
||||
public var coopAllowedCheckbox:UICheckbox;
|
||||
public var needsVoicesCheckbox:UICheckbox;
|
||||
public var colorWheel:UIColorwheel;
|
||||
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);
|
||||
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));
|
||||
|
||||
displayNameTextBox = new UITextBox(title.x, title.y + title.height + 36, metadata.displayName);
|
||||
@@ -149,6 +153,7 @@ class CharterMetaDataScreen extends UISubstateWindow {
|
||||
PlayState.SONG.meta = {
|
||||
name: songNameTextBox.label.text,
|
||||
bpm: bpmStepper.value,
|
||||
needsVoices: needsVoicesCheckbox.checked,
|
||||
beatsPerMeasure: Std.int(beatsPerMeasureStepper.value),
|
||||
stepsPerBeat: Std.int(16 / denominatorStepper.value),
|
||||
displayName: displayNameTextBox.label.text,
|
||||
@@ -161,5 +166,6 @@ class CharterMetaDataScreen extends UISubstateWindow {
|
||||
};
|
||||
|
||||
Charter.instance.updateBPMEvents();
|
||||
Charter.instance.vocals.muted = !needsVoicesCheckbox.checked;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
addLabelOn(vocalsSuffixDropDown, TU.translate("charterStrumLine.vocalSuffix"));
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import funkin.backend.chart.ChartData;
|
||||
import funkin.backend.chart.FNFLegacyParser.SwagSong;
|
||||
import funkin.backend.chart.PsychParser;
|
||||
import funkin.backend.chart.VSliceParser;
|
||||
import funkin.backend.utils.ZipUtil;
|
||||
import funkin.backend.utils.ZipUtil.ZipReader;
|
||||
import funkin.game.HealthIcon;
|
||||
import haxe.Json;
|
||||
@@ -360,11 +361,11 @@ class SongCreationScreen extends UISubstateWindow {
|
||||
{
|
||||
try switch(engineDropdown.index)
|
||||
{
|
||||
case 0 /*"V-Slice Project (.fnfc)"*/:
|
||||
case 2 /*"V-Slice Project (.fnfc)"*/:
|
||||
var files:Map<String, Any> = [];
|
||||
for (field in new ZipReader(new BytesInput(importChartFile.file)).read()) {
|
||||
var fileName = field.fileName;
|
||||
var fileContent = field.data;
|
||||
var fileContent = ZipUtil.unzip(field);
|
||||
files.set(fileName, fileContent);
|
||||
}
|
||||
saveFromVSlice(files);
|
||||
@@ -405,8 +406,8 @@ class SongCreationScreen extends UISubstateWindow {
|
||||
CoolUtil.safeSaveFile('$songFolder/charts/${songId}.json', Json.stringify(base, Flags.JSON_PRETTY_PRINT));
|
||||
#end
|
||||
});
|
||||
} catch (e) {
|
||||
openSubState(new UIWarningSubstate("Importing Song/Charts: Error!", Std.string(e), [
|
||||
} catch (e:haxe.Exception) {
|
||||
openSubState(new UIWarningSubstate("Importing Song/Charts: Error!", e.details(), [
|
||||
{label: "Ok", color: 0xFFFF0000, onClick: function(t) {}}
|
||||
]));
|
||||
}
|
||||
|
||||
@@ -552,7 +552,7 @@ class PlayState extends MusicBeatState
|
||||
@:noCompletion @:dox(hide) private var _endSongCalled:Bool = false;
|
||||
|
||||
@:dox(hide)
|
||||
var __vocalSyncTimer:Float = 0;
|
||||
var __vocalSyncTimer:Float = 1;
|
||||
|
||||
private function get_accuracy():Float {
|
||||
if (accuracyPressedNotes <= 0) return -1;
|
||||
@@ -1113,9 +1113,11 @@ class PlayState extends MusicBeatState
|
||||
curSong = songData.meta.name.toLowerCase();
|
||||
curSongID = curSong.replace(" ", "-");
|
||||
|
||||
FlxG.sound.setMusic(inst = FlxG.sound.load(Assets.getMusic(Paths.inst(SONG.meta.name, difficulty))));
|
||||
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));
|
||||
FlxG.sound.setMusic(inst = FlxG.sound.load(Assets.getMusic(Paths.inst(SONG.meta.name, difficulty, SONG.meta.instSuffix))));
|
||||
|
||||
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
|
||||
vocals = new FlxSound();
|
||||
|
||||
@@ -1224,7 +1226,7 @@ class PlayState extends MusicBeatState
|
||||
var time = Conductor.songPosition + Conductor.songOffset;
|
||||
for (strumLine in strumLines.members) strumLine.vocals.play(true, time);
|
||||
vocals.play(true, time);
|
||||
inst.play(true, time);
|
||||
if (!inst.playing) inst.play(true, time);
|
||||
|
||||
gameAndCharsCall("onVocalsResync");
|
||||
}
|
||||
@@ -1375,20 +1377,19 @@ class PlayState extends MusicBeatState
|
||||
updateIconPositions();
|
||||
|
||||
if (startingSong) {
|
||||
if (startedCountdown) {
|
||||
Conductor.songPosition += Conductor.songOffset + elapsed * 1000;
|
||||
if (Conductor.songPosition >= 0)
|
||||
startSong();
|
||||
if (startedCountdown && (Conductor.songPosition += Conductor.songOffset + elapsed * 1000) >= 0) {
|
||||
Conductor.songPosition = Conductor.songOffset;
|
||||
startSong();
|
||||
}
|
||||
}
|
||||
else if (FlxG.sound.music != null && (__vocalSyncTimer -= elapsed) < 0) {
|
||||
__vocalSyncTimer = 1;
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1689,17 +1690,12 @@ class PlayState extends MusicBeatState
|
||||
endingSong = true;
|
||||
gameAndCharsCall("onSongEnd");
|
||||
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
|
||||
FunkinSave.setSongHighscore(SONG.meta.name, difficulty, {
|
||||
score: songScore,
|
||||
@@ -1727,20 +1723,18 @@ class PlayState extends MusicBeatState
|
||||
* Immediately switches to the next song, or goes back to the Story/Freeplay menu.
|
||||
*/
|
||||
public function nextSong() {
|
||||
if (isStoryMode)
|
||||
{
|
||||
if (isStoryMode) {
|
||||
campaignScore += songScore;
|
||||
campaignMisses += misses;
|
||||
campaignAccuracyTotal += accuracy;
|
||||
campaignAccuracyCount++;
|
||||
storyPlaylist.shift();
|
||||
|
||||
if (storyPlaylist.length <= 0)
|
||||
{
|
||||
if (storyPlaylist.length <= 0) {
|
||||
FlxG.switchState(new StoryMenuState());
|
||||
|
||||
if (validScore)
|
||||
{
|
||||
if (validScore) {
|
||||
#if !switch
|
||||
// TODO: more week info saving
|
||||
FunkinSave.setWeekHighscore(storyWeek.id, difficulty, {
|
||||
score: campaignScore,
|
||||
@@ -1749,29 +1743,23 @@ class PlayState extends MusicBeatState
|
||||
hits: [],
|
||||
date: Date.now().toString()
|
||||
});
|
||||
#end
|
||||
}
|
||||
FlxG.save.flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
Logs.infos('Loading next song (${storyPlaylist[0].toLowerCase()}/$difficulty)', "PlayState");
|
||||
|
||||
registerSmoothTransition();
|
||||
|
||||
FlxG.sound.music.stop();
|
||||
|
||||
__loadSong(storyPlaylist[0], difficulty);
|
||||
|
||||
FlxG.switchState(new PlayState());
|
||||
}
|
||||
}
|
||||
else if (chartingMode)
|
||||
FlxG.switchState(new funkin.editors.charter.Charter(SONG.meta.name, difficulty, false));
|
||||
else
|
||||
{
|
||||
if (chartingMode)
|
||||
FlxG.switchState(new funkin.editors.charter.Charter(SONG.meta.name, difficulty, false));
|
||||
else
|
||||
FlxG.switchState(new FreeplayState());
|
||||
}
|
||||
FlxG.switchState(new FreeplayState());
|
||||
}
|
||||
|
||||
public function registerSmoothTransition() {
|
||||
@@ -1943,6 +1931,8 @@ class PlayState extends MusicBeatState
|
||||
}
|
||||
|
||||
if (event.deleteNote) strumLine.deleteNote(note);
|
||||
|
||||
gameAndCharsEvent("onPostNoteHit", event);
|
||||
}
|
||||
|
||||
public function displayRating(myRating:String, ?evt:NoteHitEvent = null):Void {
|
||||
|
||||
@@ -19,6 +19,16 @@ class FreeplayState extends MusicBeatState
|
||||
*/
|
||||
public var songs:Array<ChartMetaData> = [];
|
||||
|
||||
/**
|
||||
* Current song metadata
|
||||
*/
|
||||
public var curSong:Null<ChartMetaData>;
|
||||
|
||||
/**
|
||||
* Current song metadata difficulty
|
||||
*/
|
||||
public var curSongDifficulty:Null<String>;
|
||||
|
||||
/**
|
||||
* Currently selected song
|
||||
*/
|
||||
@@ -43,7 +53,7 @@ class FreeplayState extends MusicBeatState
|
||||
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;
|
||||
|
||||
@@ -107,7 +117,9 @@ class FreeplayState extends MusicBeatState
|
||||
curSelected = k;
|
||||
}
|
||||
}
|
||||
if (songs[curSelected] != null) {
|
||||
updateCurSongMeta();
|
||||
|
||||
if (curSong != null) {
|
||||
for(k=>diff in songs[curSelected].difficulties) {
|
||||
if (diff == Options.freeplayLastDifficulty) {
|
||||
curDifficulty = k;
|
||||
@@ -225,7 +237,7 @@ class FreeplayState extends MusicBeatState
|
||||
if (canSelect) {
|
||||
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));
|
||||
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
|
||||
updateOptionsAlpha();
|
||||
}
|
||||
@@ -238,14 +250,14 @@ class FreeplayState extends MusicBeatState
|
||||
scoreText.x = coopText.x = scoreBG.x + 4;
|
||||
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;
|
||||
|
||||
#if PRELOAD_ALL
|
||||
var dontPlaySongThisFrame = false;
|
||||
autoplayElapsed += elapsed;
|
||||
if (!disableAutoPlay && !songInstPlaying && (autoplayElapsed > timeUntilAutoplay || FlxG.keys.justPressed.SPACE)) {
|
||||
if (curPlayingInst != (curPlayingInst = Paths.inst(songs[curSelected].name, songs[curSelected].difficulties[curDifficulty]))) {
|
||||
if (!disableAutoPlay && !songInstPlaying && (autoplayElapsed > timeUntilAutoplay)) {
|
||||
if (curPlayingInst != (curPlayingInst = Paths.inst(curSong.name, curSongDifficulty, curSong.instSuffix))) {
|
||||
var streamed = false;
|
||||
if (Options.streamedMusic) {
|
||||
var sound = Assets.getMusic(curPlayingInst, true, false);
|
||||
@@ -253,7 +265,7 @@ class FreeplayState extends MusicBeatState
|
||||
|
||||
if (streamed && autoplayShouldPlay) {
|
||||
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 +280,7 @@ class FreeplayState extends MusicBeatState
|
||||
|
||||
if (sound != null && autoplayShouldPlay) {
|
||||
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);
|
||||
@@ -302,7 +314,6 @@ class FreeplayState extends MusicBeatState
|
||||
function updateCoopModes() {
|
||||
__opponentMode = false;
|
||||
__coopMode = false;
|
||||
var curSong = songs[curSelected];
|
||||
if (curSong.coopAllowed && curSong.opponentModeAllowed) {
|
||||
__opponentMode = curCoopMode % 2 == 1;
|
||||
__coopMode = curCoopMode >= 2;
|
||||
@@ -321,7 +332,7 @@ class FreeplayState extends MusicBeatState
|
||||
|
||||
if (songs[curSelected].difficulties.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, curSongDifficulty, __opponentMode, __coopMode));
|
||||
|
||||
if (event.cancelled) return;
|
||||
|
||||
@@ -329,17 +340,17 @@ class FreeplayState extends MusicBeatState
|
||||
autoplayShouldPlay = false;
|
||||
#end
|
||||
|
||||
Options.freeplayLastSong = songs[curSelected].name;
|
||||
Options.freeplayLastDifficulty = songs[curSelected].difficulties[curDifficulty];
|
||||
Options.freeplayLastSong = curSong.name;
|
||||
Options.freeplayLastDifficulty = curSongDifficulty;
|
||||
|
||||
PlayState.loadSong(event.song, event.difficulty, event.opponentMode, event.coopMode);
|
||||
FlxG.switchState(new PlayState());
|
||||
}
|
||||
|
||||
public function convertChart() {
|
||||
trace('Converting ${songs[curSelected].name} (${songs[curSelected].difficulties[curDifficulty]}) to Codename format...');
|
||||
var chart = Chart.parse(songs[curSelected].name, songs[curSelected].difficulties[curDifficulty]);
|
||||
Chart.save('${Main.pathBack}assets/songs/${songs[curSelected].name}', chart, songs[curSelected].difficulties[curDifficulty]);
|
||||
trace('Converting ${curSong.name} (${curSongDifficulty}) to Codename format...');
|
||||
var chart = Chart.parse(curSong.name, curSongDifficulty);
|
||||
Chart.save('${Main.pathBack}assets/songs/${curSong.name}', chart, curSongDifficulty);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -351,20 +362,31 @@ class FreeplayState extends MusicBeatState
|
||||
{
|
||||
if (change == 0 && !force) return;
|
||||
|
||||
var curSong = songs[curSelected];
|
||||
var validDifficulties = curSong.difficulties.length > 0;
|
||||
var event = event("onChangeDiff", EventManager.get(MenuChangeEvent).recycle(curDifficulty, validDifficulties ? FlxMath.wrap(curDifficulty + change, 0, curSong.difficulties.length-1) : 0, change));
|
||||
var song = songs[curSelected];
|
||||
var validDifficulties = song.difficulties.length > 0;
|
||||
var event = event("onChangeDiff", EventManager.get(MenuChangeEvent).recycle(curDifficulty, validDifficulties ? FlxMath.wrap(curDifficulty + change, 0, song.difficulties.length-1) : 0, change));
|
||||
|
||||
if (event.cancelled) return;
|
||||
if (event.cancelled) {
|
||||
if (force) updateCurSongMeta();
|
||||
return;
|
||||
}
|
||||
|
||||
var prevInstSuffix = curSong.instSuffix;
|
||||
curDifficulty = event.value;
|
||||
|
||||
updateCurSongMeta();
|
||||
updateScore();
|
||||
|
||||
if (curSong.difficulties.length > 1)
|
||||
diffText.text = '< ${curSong.difficulties[curDifficulty].toUpperCase()} >';
|
||||
#if PRELOAD_ALL
|
||||
if (curSong.instSuffix != prevInstSuffix) {
|
||||
autoplayElapsed = 0;
|
||||
songInstPlaying = false;
|
||||
}
|
||||
#end
|
||||
|
||||
if (song.difficulties.length > 1)
|
||||
diffText.text = '< ${song.difficulties[curDifficulty].toUpperCase()} >';
|
||||
else
|
||||
diffText.text = validDifficulties ? curSong.difficulties[curDifficulty].toUpperCase() : "-";
|
||||
diffText.text = validDifficulties ? song.difficulties[curDifficulty].toUpperCase() : "-";
|
||||
}
|
||||
|
||||
function updateScore() {
|
||||
@@ -376,7 +398,7 @@ class FreeplayState extends MusicBeatState
|
||||
var changes:Array<HighscoreChange> = [];
|
||||
if (__coopMode) changes.push(CCoopMode);
|
||||
if (__opponentMode) changes.push(COpponentMode);
|
||||
var saveData = FunkinSave.getSongHighscore(songs[curSelected].name, songs[curSelected].difficulties[curDifficulty], changes);
|
||||
var saveData = FunkinSave.getSongHighscore(curSong.name, curSongDifficulty, changes);
|
||||
intendedScore = saveData.score;
|
||||
}
|
||||
|
||||
@@ -397,9 +419,9 @@ class FreeplayState extends MusicBeatState
|
||||
*/
|
||||
public function changeCoopMode(change:Int = 0, force:Bool = false) {
|
||||
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));
|
||||
|
||||
if (event.cancelled) return;
|
||||
@@ -408,12 +430,16 @@ class FreeplayState extends MusicBeatState
|
||||
|
||||
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) {
|
||||
coopText.text = key + coopLabels[curCoopMode];
|
||||
} else {
|
||||
coopText.text = key + coopLabels[curCoopMode * (songs[curSelected].coopAllowed ? 2 : 1)];
|
||||
coopText.text = key + coopLabels[curCoopMode * (curSong.coopAllowed ? 2 : 1)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,7 +452,6 @@ class FreeplayState extends MusicBeatState
|
||||
{
|
||||
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));
|
||||
if (event.cancelled) return;
|
||||
|
||||
@@ -440,7 +465,7 @@ class FreeplayState extends MusicBeatState
|
||||
songInstPlaying = false;
|
||||
#end
|
||||
|
||||
coopText.visible = songs[curSelected].coopAllowed || songs[curSelected].opponentModeAllowed;
|
||||
coopText.visible = curSong.coopAllowed || curSong.opponentModeAllowed;
|
||||
}
|
||||
|
||||
function updateOptionsAlpha() {
|
||||
@@ -465,6 +490,16 @@ class FreeplayState extends MusicBeatState
|
||||
item.alpha = selectedAlpha;
|
||||
}
|
||||
}
|
||||
|
||||
function updateCurSongMeta() {
|
||||
var song = songs[curSelected];
|
||||
if (song == null) {
|
||||
curSong = null;
|
||||
curSongDifficulty = null;
|
||||
}
|
||||
else if ((curSong = song.metas.get(curSongDifficulty = song.difficulties[curDifficulty])) == null)
|
||||
curSong = song;
|
||||
}
|
||||
}
|
||||
|
||||
class FreeplaySonglist {
|
||||
@@ -485,7 +520,7 @@ class FreeplaySonglist {
|
||||
}
|
||||
if (songsFound == null) songsFound = Paths.getFolderDirectories("songs", false, source);
|
||||
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 true;
|
||||
|
||||
@@ -129,7 +129,7 @@ class TitleState extends MusicBeatState
|
||||
|
||||
if (pressedEnter && transitioning && skippedIntro) {
|
||||
FlxG.camera.stopFX();// FlxG.camera.visible = false;
|
||||
goToMainMenu();
|
||||
goToMainMenu(false);
|
||||
}
|
||||
|
||||
if (pressedEnter && !transitioning && skippedIntro)
|
||||
@@ -152,22 +152,24 @@ class TitleState extends MusicBeatState
|
||||
transitioning = true;
|
||||
// FlxG.sound.music.stop();
|
||||
|
||||
new FlxTimer().start(2, (_) -> goToMainMenu());
|
||||
new FlxTimer().start(2, (_) -> goToMainMenu(false));
|
||||
}
|
||||
|
||||
function goToMainMenu() {
|
||||
function goToMainMenu(force = true) {
|
||||
#if UPDATE_CHECKING
|
||||
var report = hasCheckedUpdates ? null : funkin.backend.system.updating.UpdateUtil.checkForUpdates();
|
||||
hasCheckedUpdates = true;
|
||||
if (!force && !Flags.DISABLE_AUTOUPDATER) {
|
||||
funkin.backend.system.updating.UpdateUtil.waitForUpdates(false, (report) -> {
|
||||
hasCheckedUpdates = true;
|
||||
if (FlxG.state != this) return;
|
||||
|
||||
if (report != null && report.newUpdate) {
|
||||
FlxG.switchState(new funkin.backend.system.updating.UpdateAvailableScreen(report));
|
||||
} else {
|
||||
if (!report.newUpdate) goToMainMenu(true);
|
||||
else FlxG.switchState(new funkin.backend.system.updating.UpdateAvailableScreen(report));
|
||||
}, true);
|
||||
}
|
||||
else
|
||||
#end {
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
#else
|
||||
FlxG.switchState(new MainMenuState());
|
||||
#end
|
||||
}
|
||||
|
||||
public function createCoolText(textArray:Array<String>)
|
||||
|
||||
@@ -37,6 +37,9 @@ final class AlphabetComponent {
|
||||
public var scaleX:Float;
|
||||
public var scaleY:Float;
|
||||
|
||||
public var flipX:Bool;
|
||||
public var flipY:Bool;
|
||||
|
||||
public var hasColorMode:Bool;
|
||||
public var colorMode:ColorMode;
|
||||
}
|
||||
@@ -346,9 +349,9 @@ class Alphabet extends FlxSprite {
|
||||
|
||||
_matrix.translate(_frame.frame.width * -0.5, _frame.frame.height * -0.5);
|
||||
if (__useDrawScale)
|
||||
_matrix.scale(__drawScale.x, __drawScale.y);
|
||||
_matrix.scale(__drawScale.x * (__component.flipX ? -1 : 1), __drawScale.y * (__component.flipY ? -1 : 1));
|
||||
else
|
||||
_matrix.scale(__component.scaleX, __component.scaleY);
|
||||
_matrix.scale(__component.scaleX * (__component.flipX ? -1 : 1), __component.scaleY * (__component.flipY ? -1 : 1));
|
||||
if(__component.shouldRotate)
|
||||
_matrix.rotateWithTrig(__component.cos, __component.sin);
|
||||
_matrix.translate(_frame.frame.width * 0.5, _frame.frame.height * 0.5);
|
||||
@@ -558,6 +561,9 @@ class Alphabet extends FlxSprite {
|
||||
cos: angleCos,
|
||||
sin: angleSin,
|
||||
|
||||
flipX: node.get("flipX") == "true",
|
||||
flipY: node.get("flipY") == "true",
|
||||
|
||||
hasColorMode: false,
|
||||
colorMode: 0
|
||||
}],
|
||||
@@ -593,6 +599,9 @@ class Alphabet extends FlxSprite {
|
||||
|
||||
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") {
|
||||
components.insert(startIndex, {
|
||||
refIndex: componentsPushed,
|
||||
@@ -608,6 +617,9 @@ class Alphabet extends FlxSprite {
|
||||
cos: angleCos,
|
||||
sin: angleSin,
|
||||
|
||||
flipX: xFlip,
|
||||
flipY: yFlip,
|
||||
|
||||
hasColorMode: colorMode >= 0,
|
||||
colorMode: colorMode,
|
||||
});
|
||||
@@ -628,6 +640,9 @@ class Alphabet extends FlxSprite {
|
||||
cos: angleCos,
|
||||
sin: angleSin,
|
||||
|
||||
flipX: xFlip,
|
||||
flipY: yFlip,
|
||||
|
||||
hasColorMode: colorMode >= 0,
|
||||
colorMode: colorMode,
|
||||
});
|
||||
@@ -659,6 +674,9 @@ class Alphabet extends FlxSprite {
|
||||
var yScale:Float = Std.parseFloat(node.get("scaleY")).getDefaultFloat(1.0);
|
||||
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 components:Array<AlphabetComponent> = [];
|
||||
@@ -677,6 +695,9 @@ class Alphabet extends FlxSprite {
|
||||
cos: angleCos,
|
||||
sin: angleSin,
|
||||
|
||||
flipX: xFlip,
|
||||
flipY: yFlip,
|
||||
|
||||
hasColorMode: colorMode >= 0,
|
||||
colorMode: colorMode,
|
||||
});
|
||||
@@ -696,6 +717,9 @@ class Alphabet extends FlxSprite {
|
||||
cos: angleCos,
|
||||
sin: angleSin,
|
||||
|
||||
flipX: xFlip,
|
||||
flipY: yFlip,
|
||||
|
||||
hasColorMode: colorMode >= 0,
|
||||
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 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 {
|
||||
var xml = Xml.createElement("alphabet");
|
||||
|
||||
@@ -117,6 +117,7 @@ class Options
|
||||
public static var P1_ACCEPT:Array<FlxKey> = [ENTER];
|
||||
public static var P1_BACK:Array<FlxKey> = [BACKSPACE];
|
||||
public static var P1_PAUSE:Array<FlxKey> = [ENTER];
|
||||
public static var P1_CHANGE_MODE:Array<FlxKey> = [TAB];
|
||||
|
||||
// Misc
|
||||
public static var P1_RESET:Array<FlxKey> = [R];
|
||||
@@ -148,6 +149,7 @@ class Options
|
||||
public static var P2_ACCEPT:Array<FlxKey> = [SPACE];
|
||||
public static var P2_BACK:Array<FlxKey> = [ESCAPE];
|
||||
public static var P2_PAUSE:Array<FlxKey> = [ESCAPE];
|
||||
public static var P2_CHANGE_MODE:Array<FlxKey> = [];
|
||||
|
||||
// Misc
|
||||
public static var P2_RESET:Array<FlxKey> = [];
|
||||
@@ -179,6 +181,7 @@ class Options
|
||||
public static var SOLO_ACCEPT(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_CHANGE_MODE(get, null):Array<FlxKey>;
|
||||
|
||||
// Misc
|
||||
public static var SOLO_RESET(get, null):Array<FlxKey>;
|
||||
|
||||
@@ -11,7 +11,7 @@ class MiscOptions extends TreeMenuScreen {
|
||||
#if UPDATE_CHECKING
|
||||
add(new Checkbox(getNameID('betaUpdates'), getDescID('betaUpdates'), 'betaUpdates'));
|
||||
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));
|
||||
else {
|
||||
CoolUtil.playMenuSFX(CANCEL);
|
||||
|
||||
@@ -97,17 +97,21 @@ class KeybindsOptions extends MusicBeatSubstate {
|
||||
name: translate("ui.pause"),
|
||||
control: 'PAUSE'
|
||||
},
|
||||
{
|
||||
name: translate("ui.changeMode"),
|
||||
control: 'CHANGE_MODE'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: translate("category.volume"),
|
||||
settings: [
|
||||
{
|
||||
name: translate("up"),
|
||||
name: translate("volume.up"),
|
||||
control: 'VOLUME_UP'
|
||||
},
|
||||
{
|
||||
name: translate("down"),
|
||||
name: translate("volume.down"),
|
||||
control: 'VOLUME_DOWN'
|
||||
},
|
||||
{
|
||||
|
||||
@@ -25,10 +25,10 @@ import lime.utils.ArrayBufferView;
|
||||
@:access(lime.media.AudioBuffer)
|
||||
@:access(lime.utils.ArrayBufferView)
|
||||
class NativeAudioSource {
|
||||
private static var STREAM_BUFFER_SAMPLES:Int = 0x1000;
|
||||
private static var STREAM_MAX_BUFFERS:Int = 32;
|
||||
private static var STREAM_BUFFER_SAMPLES:Int = 0x4000;
|
||||
private static var STREAM_MAX_BUFFERS:Int = 8;
|
||||
private static var STREAM_TIMER_FREQUENCY:Int = 100;
|
||||
private static var STREAM_BUFFER_FREQUENCY:Int = 6;
|
||||
private static var STREAM_BUFFER_FREQUENCY:Int = 3;
|
||||
|
||||
private var parent:AudioSource;
|
||||
private var disposed:Bool;
|
||||
|
||||
Reference in New Issue
Block a user