normal vslice SUPPORT

This commit is contained in:
⍚~Nex
2025-04-01 01:36:23 +02:00
parent d67f537cdf
commit 0f09306a44
6 changed files with 115 additions and 91 deletions
+2 -2
View File
@@ -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;
}
@@ -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<FlxGroup> = [];
public var pageSizes:Array<FlxPoint> = [];
@@ -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<String, Any> = [];
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<String, Any> = [];
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<String, Any> = [];
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<String, Any>, ?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
});
}
}
-1
View File
@@ -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)
+6 -6
View File
@@ -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;
-2
View File
@@ -64,9 +64,7 @@ class GitarooPause extends MusicBeatState
}
else
{
PlayState.resetSongInfos();
if (Charter.instance != null) Charter.instance.__clearStatics();
FlxG.switchState(new MainMenuState());
}
}
-1
View File
@@ -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