From 0f09306a44c5dc7b204355e0e1a3b9707bf1e639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=8D=9A=7ENex?= <87421482+NexIsDumb@users.noreply.github.com> Date: Tue, 1 Apr 2025 01:36:23 +0200 Subject: [PATCH] normal vslice SUPPORT --- source/funkin/editors/charter/Charter.hx | 4 +- .../editors/charter/SongCreationScreen.hx | 186 ++++++++++-------- source/funkin/game/GameOverSubstate.hx | 1 - source/funkin/game/PlayState.hx | 12 +- source/funkin/menus/GitarooPause.hx | 2 - source/funkin/menus/PauseSubState.hx | 1 - 6 files changed, 115 insertions(+), 91 deletions(-) diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index 391454a6..de8e1793 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -1308,7 +1308,7 @@ class Charter extends UIState { #if REGION function _file_exit(_) { if (undos.unsaved) SaveWarning.triggerWarning(); - else {undos = null; FlxG.switchState(new CharterSelection()); PlayState.resetSongInfos(); Charter.instance.__clearStatics();} + else {undos = null; FlxG.switchState(new CharterSelection()); Charter.instance.__clearStatics();} } function _file_save(_) { @@ -1931,7 +1931,7 @@ class Charter extends UIState { } @:noCompletion public function __clearStatics() { - selection = null; undos = null; clipboard = null; playtestInfo = null; + selection = null; undos = null; clipboard = null; playtestInfo = null; waveformHandler.destroy(); Charter.waveformHandler = null; autoSaveTimer = 0; } diff --git a/source/funkin/editors/charter/SongCreationScreen.hx b/source/funkin/editors/charter/SongCreationScreen.hx index 52eb8d7f..8dd5864c 100644 --- a/source/funkin/editors/charter/SongCreationScreen.hx +++ b/source/funkin/editors/charter/SongCreationScreen.hx @@ -43,7 +43,9 @@ class SongCreationScreen extends UISubstateWindow { public var importInstExplorer:UIFileExplorer; public var importVoicesExplorer:UIFileExplorer; + public var importIdTextBox:UITextBox; public var importChartFile:UIFileExplorer; + public var importMetaFile:UIFileExplorer; public var backButton:UIButton; public var saveButton:UIButton; @@ -54,7 +56,7 @@ class SongCreationScreen extends UISubstateWindow { public var selectFormatGroup:FlxGroup = new FlxGroup(); public var importAudioGroup:FlxGroup = new FlxGroup(); - public var importChartGroup:FlxGroup = new FlxGroup(); + public var importDataGroup:FlxGroup = new FlxGroup(); public var pages:Array = []; public var pageSizes:Array = []; @@ -166,7 +168,7 @@ class SongCreationScreen extends UISubstateWindow { var menuTitle:UIText; selectFormatGroup.add(menuTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Import From:", 28)); - engineDropdown = new UIDropDown(menuTitle.x, menuTitle.y + menuTitle.height + 36, 320, 32, ["Psych/Legacy FNF", "V-Slice Project (.fnfc)"]); + engineDropdown = new UIDropDown(menuTitle.x, menuTitle.y + menuTitle.height + 36, 480, 32, ["Psych/Legacy FNF (Can also work on runtime)", "V-Slice", "V-Slice Project (.fnfc)"]); selectFormatGroup.add(engineDropdown); addLabelOn(engineDropdown, "Chart Format"); @@ -200,12 +202,23 @@ class SongCreationScreen extends UISubstateWindow { addLabelOn(importVoicesExplorer, "Vocal Audio File"); var menuTitle:UIText; - importChartGroup.add(menuTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Add Chart", 28)); + importDataGroup.add(menuTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Add Data", 28)); - importChartFile = new UIFileExplorer(menuTitle.x, menuTitle.y + menuTitle.height + 36, null, null, "fnfc"); - importChartGroup.add(importChartFile); - addLabelOn(importChartFile, "Chart File").applyMarkup( - "Chart File $* Required$", + importDataGroup.add(importIdTextBox = new UITextBox(menuTitle.x, menuTitle.y + menuTitle.height + 36, "satin-panties")); + addLabelOn(importIdTextBox, "Song file name").applyMarkup( + "Song file name $* Required$", + [new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFAD1212), "$")]); + + importChartFile = new UIFileExplorer(importIdTextBox.x, importIdTextBox.y + importIdTextBox.height + 56, null, null, "fnfc"); + importDataGroup.add(importChartFile); + addLabelOn(importChartFile, "Data/Chart File").applyMarkup( + "Data/Chart File $* Required$", + [new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFAD1212), "$")]); + + importMetaFile = new UIFileExplorer(importChartFile.x + 320 + 26, importChartFile.y, null, null, "json"); + importDataGroup.add(importMetaFile); + addLabelOn(importMetaFile, "Meta File").applyMarkup( + "Meta File $* Required$", [new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFAD1212), "$")]); saveButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20 - 125, windowSpr.y + windowSpr.bHeight - 16 - 32, "Save & Close", function() { @@ -248,8 +261,8 @@ class SongCreationScreen extends UISubstateWindow { importPages.push(cast add(importAudioGroup)); importPageSizes.push(FlxPoint.get(705, 250)); - importPages.push(cast add(importChartGroup)); - importPageSizes.push(FlxPoint.get(460, 250)); + importPages.push(cast add(importDataGroup)); + importPageSizes.push(FlxPoint.get(705, 300)); refreshPages(); updatePagesTexts(); @@ -258,12 +271,17 @@ class SongCreationScreen extends UISubstateWindow { public override function update(elapsed:Float) { if (isImporting) { + var name = engineDropdown.options[engineDropdown.index]; + var project = name == "V-Slice Project (.fnfc)"; + if (curPage == 1) { - importInstExplorer.selectable = importVoicesExplorer.selectable = (engineDropdown.index != 1); - saveButton.selectable = (engineDropdown.index == 1) ? true : (importInstExplorer.file != null); + importInstExplorer.selectable = importVoicesExplorer.selectable = !project; + saveButton.selectable = project ? true : (importInstExplorer.file != null); } else if (curPage == 2) { - importChartFile.fileType = (engineDropdown.index == 1) ? "fnfc" : "json"; - saveButton.selectable = (importChartFile.file != null); + importIdTextBox.selectable = !project; + importChartFile.fileType = project ? "fnfc" : "json"; + importMetaFile.selectable = name == "V-Slice"; + saveButton.selectable = importChartFile.file != null && (!importMetaFile.selectable || importMetaFile.file != null) && (!importIdTextBox.selectable || importIdTextBox.label.text.trim().length > 0); } else saveButton.selectable = true; } else { @@ -329,74 +347,25 @@ class SongCreationScreen extends UISubstateWindow { function saveSongInfo() { if (isImporting) { - if (engineDropdown.index == 1) + switch(engineDropdown.options[engineDropdown.index]) { - var reader = new ZipReader(new BytesInput(importChartFile.file)); - var fields = reader.read(); - var files:Map = []; - - for(k=>field in fields) { - var fileName = field.fileName; - var fileContent = field.data; - files.set(fileName, fileContent); - } - - var manifest = Json.parse(files.get("manifest.json")); - var vslicemeta = Json.parse(files.get('${manifest.songId}-metadata.json')); - var firstTimeChange = vslicemeta.timeChanges[0]; - var vslicechart = Json.parse(files.get('${manifest.songId}-chart.json')); - var difficulties = Reflect.fields(vslicechart.notes); - - var playData = vslicemeta.playData; - - var instFile = files.get('Inst.${Flags.SOUND_EXT}'); - var voicesFiles = files.get('Voices.${Flags.SOUND_EXT}'); //it may exist - var playerVoices = files.get('Voices-${playData.characters.playerVocals[0]}.${Flags.SOUND_EXT}'); - var oppVoices = files.get('Voices-${playData.characters.opponentVocals[0]}.${Flags.SOUND_EXT}'); - - var meta:ChartMetaData = { - name: manifest.songId, - bpm: CoolUtil.getDefault(firstTimeChange.bpm, 100), - beatsPerMeasure: CoolUtil.getDefault(firstTimeChange.n, Flags.DEFAULT_BEATS_PER_MEASURE), - stepsPerBeat: CoolUtil.getDefault(firstTimeChange.d, 4), - displayName: vslicemeta.songName, - icon: Flags.DEFAULT_HEALTH_ICON, - color: "#FFFFFF", - parsedColor: 0xFFFFFF, - opponentModeAllowed: true, - coopAllowed: true, - difficulties: difficulties, - }; - - if (onSave != null) onSave({ - meta: meta, - instBytes: instFile, - voicesBytes: voicesFiles, - playerVocals: playerVoices, - oppVocals: oppVoices, - }, (songFolder:String, creation: SongCreationData) -> { - #if sys - for (diff in difficulties) - { - var vsliceChartData = Reflect.field(vslicechart.notes, diff); - var chartPath = Paths.chart(manifest.songId, diff); - var base:ChartData = { - strumLines: [], - noteTypes: [], - events: [], - meta: { - name: null - }, - scrollSpeed: Reflect.field(vslicechart.scrollSpeed, diff), - stage: Flags.DEFAULT_STAGE, - codenameChart: true, - fromMods: Paths.assetsTree.existsSpecific(chartPath, "TEXT", MODS) - }; - BaseGameParser.parseChart(vsliceChartData, vslicemeta, vslicechart.events, base); - CoolUtil.safeSaveFile('$songFolder/charts/$diff.json', Json.stringify(base, Flags.JSON_PRETTY_PRINT)); + case "V-Slice Project (.fnfc)": + var files:Map = []; + for (field in new ZipReader(new BytesInput(importChartFile.file)).read()) { + var fileName = field.fileName; + var fileContent = field.data; + files.set(fileName, fileContent); } - #end - }); + saveVslice(files); + + case "V-Slice": + var songId = importIdTextBox.label.text; + var files:Map = []; + files.set('${songId}-metadata.json', importMetaFile.file); + files.set('${songId}-chart.json', importChartFile.file); + files.set('Inst.${Flags.SOUND_EXT}', importInstExplorer.file); + files.set('Voices.${Flags.SOUND_EXT}', importVoicesExplorer.file); + saveVslice(files, songId); } } else { for (stepper in [bpmStepper, beatsPerMeasureStepper, stepsPerBeatStepper]) @@ -423,4 +392,63 @@ class SongCreationScreen extends UISubstateWindow { }, null); } } + + function saveVslice(files:Map, ?name:String) { + var songId = name == null && files.exists("manifest.json") ? Json.parse(files.get("manifest.json")).songId : name; + var vslicemeta = Json.parse(files.get('${songId}-metadata.json')); + var firstTimeChange = vslicemeta.timeChanges[0]; + var vslicechart = Json.parse(files.get('${songId}-chart.json')); + var difficulties = Reflect.fields(vslicechart.notes); + + var playData = vslicemeta.playData; + + var instFile = files.get('Inst.${Flags.SOUND_EXT}'); + var voicesFiles = files.get('Voices.${Flags.SOUND_EXT}'); //it may exist + var playerVoices = files.get('Voices-${playData.characters.playerVocals != null ? playData.characters.playerVocals[0] : playData.characters.player}.${Flags.SOUND_EXT}'); + var oppVoices = files.get('Voices-${playData.characters.opponentVocals != null ? playData.characters.opponentVocals[0] : playData.characters.opponent}.${Flags.SOUND_EXT}'); + + var meta:ChartMetaData = { + name: songId, + bpm: CoolUtil.getDefault(firstTimeChange.bpm, 100), + beatsPerMeasure: CoolUtil.getDefault(firstTimeChange.n, Flags.DEFAULT_BEATS_PER_MEASURE), + stepsPerBeat: CoolUtil.getDefault(firstTimeChange.d, 4), + displayName: vslicemeta.songName, + icon: Flags.DEFAULT_HEALTH_ICON, + color: "#FFFFFF", + parsedColor: 0xFFFFFF, + opponentModeAllowed: true, + coopAllowed: true, + difficulties: difficulties, + }; + + if (onSave != null) onSave({ + meta: meta, + instBytes: instFile, + voicesBytes: voicesFiles, + playerVocals: playerVoices, + oppVocals: oppVoices, + }, (songFolder:String, creation: SongCreationData) -> { + #if sys + for (diff in difficulties) + { + var vsliceChartData = Reflect.field(vslicechart.notes, diff); + var chartPath = Paths.chart(songId, diff); + var base:ChartData = { + strumLines: [], + noteTypes: [], + events: [], + meta: { + name: null + }, + scrollSpeed: Reflect.field(vslicechart.scrollSpeed, diff), + stage: Flags.DEFAULT_STAGE, + codenameChart: true, + fromMods: Paths.assetsTree.existsSpecific(chartPath, "TEXT", MODS) + }; + BaseGameParser.parseChart(vsliceChartData, vslicemeta, vslicechart.events, base); + CoolUtil.safeSaveFile('$songFolder/charts/$diff.json', Json.stringify(base, Flags.JSON_PRETTY_PRINT)); + } + #end + }); + } } \ No newline at end of file diff --git a/source/funkin/game/GameOverSubstate.hx b/source/funkin/game/GameOverSubstate.hx index 2d7af30d..06862457 100644 --- a/source/funkin/game/GameOverSubstate.hx +++ b/source/funkin/game/GameOverSubstate.hx @@ -111,7 +111,6 @@ class GameOverSubstate extends MusicBeatSubstate if (PlayState.chartingMode && Charter.undos.unsaved) game.saveWarn(false); else { - PlayState.resetSongInfos(); if (Charter.instance != null) Charter.instance.__clearStatics(); if (FlxG.sound.music != null) diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx index c089652f..312a0b30 100644 --- a/source/funkin/game/PlayState.hx +++ b/source/funkin/game/PlayState.hx @@ -581,6 +581,9 @@ class PlayState extends MusicBeatState @:dox(hide) override public function create() { Note.__customNoteTypeExists = []; + seenCutscene = false; + deathCounter = 0; + // SCRIPTING & DATA INITIALIZATION #if REGION instance = this; @@ -1028,10 +1031,9 @@ class PlayState extends MusicBeatState Note.__customNoteTypeExists = []; } - public static function resetSongInfos() { - deathCounter = 0; - seenCutscene = false; - } + // keping this for backwards compat - Nex + @:deprecated("resetSongInfos is deprecated, it's now handled in new PlayState()") + public static function resetSongInfos() {} @:dox(hide) private function generateSong(?songData:ChartData):Void { @@ -1545,8 +1547,6 @@ class PlayState extends MusicBeatState * Immediately switches to the next song, or goes back to the Story/Freeplay menu. */ public function nextSong() { - resetSongInfos(); - if (isStoryMode) { campaignScore += songScore; diff --git a/source/funkin/menus/GitarooPause.hx b/source/funkin/menus/GitarooPause.hx index cff8aec9..f72e7d2b 100644 --- a/source/funkin/menus/GitarooPause.hx +++ b/source/funkin/menus/GitarooPause.hx @@ -64,9 +64,7 @@ class GitarooPause extends MusicBeatState } else { - PlayState.resetSongInfos(); if (Charter.instance != null) Charter.instance.__clearStatics(); - FlxG.switchState(new MainMenuState()); } } diff --git a/source/funkin/menus/PauseSubState.hx b/source/funkin/menus/PauseSubState.hx index 8badd60a..e8ad62af 100644 --- a/source/funkin/menus/PauseSubState.hx +++ b/source/funkin/menus/PauseSubState.hx @@ -165,7 +165,6 @@ class PauseSubState extends MusicBeatSubstate if (PlayState.chartingMode && Charter.undos.unsaved) game.saveWarn(false); else { - PlayState.resetSongInfos(); if (Charter.instance != null) Charter.instance.__clearStatics(); // prevents certain notes to disappear early when exiting - Nex