more progress + psych/legacy importer

This commit is contained in:
⍚~Nex
2025-04-05 03:38:36 +02:00
parent cfe209067c
commit 226c7f84a6
4 changed files with 51 additions and 10 deletions
+1 -1
View File
@@ -195,7 +195,7 @@ class Chart {
base = data; base = data;
case PSYCH_NEW: PsychParser.parse(data, base); case PSYCH_NEW: PsychParser.parse(data, base);
case VSLICE: // TODO case VSLICE: Logs.trace("Couldn't parse V-Slice chart because it's not supported on runtime, it MUST be imported and converted in the new song editor window.", ERROR, RED);
case LEGACY: FNFLegacyParser.parse(data, base); case LEGACY: FNFLegacyParser.parse(data, base);
} }
#end #end
@@ -3,8 +3,10 @@ package funkin.editors.charter;
import flixel.group.FlxGroup; import flixel.group.FlxGroup;
import flixel.text.FlxText.FlxTextFormat; import flixel.text.FlxText.FlxTextFormat;
import flixel.text.FlxText.FlxTextFormatMarkerPair; import flixel.text.FlxText.FlxTextFormatMarkerPair;
import funkin.backend.chart.VSliceParser;
import funkin.backend.chart.ChartData; 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;
import haxe.Json; import haxe.Json;
import haxe.io.Bytes; import haxe.io.Bytes;
@@ -168,7 +170,7 @@ class SongCreationScreen extends UISubstateWindow {
var menuTitle:UIText; var menuTitle:UIText;
selectFormatGroup.add(menuTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Import From:", 28)); 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, 480, 32, ["Psych/Legacy FNF", "V-Slice", "V-Slice Project (.fnfc)"]); engineDropdown = new UIDropDown(menuTitle.x, menuTitle.y + menuTitle.height + 36, 480, 32, ["Psych/Legacy FNF", "V-Slice", "V-Slice Project (.fnfc)"], 0, ["Supports runtime"]);
selectFormatGroup.add(engineDropdown); selectFormatGroup.add(engineDropdown);
addLabelOn(engineDropdown, "Chart Format"); addLabelOn(engineDropdown, "Chart Format");
@@ -204,12 +206,12 @@ class SongCreationScreen extends UISubstateWindow {
var menuTitle:UIText; var menuTitle:UIText;
importDataGroup.add(menuTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Add Data", 28)); importDataGroup.add(menuTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Add Data", 28));
importDataGroup.add(importIdTextBox = new UITextBox(menuTitle.x, menuTitle.y + menuTitle.height + 36, "satin-panties")); importDataGroup.add(importIdTextBox = new UITextBox(menuTitle.x, menuTitle.y + menuTitle.height + 36));
addLabelOn(importIdTextBox, "Song file name").applyMarkup( addLabelOn(importIdTextBox, "Song file name").applyMarkup(
"Song file name $* Required$", "Song file name $* Required$",
[new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFAD1212), "$")]); [new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFAD1212), "$")]);
importChartFile = new UIFileExplorer(importIdTextBox.x, importIdTextBox.y + importIdTextBox.height + 56, null, null, "fnfc"); importChartFile = new UIFileExplorer(importIdTextBox.x, importIdTextBox.y + importIdTextBox.height + 56, null, null, "fnfc", function (_) importIdTextBox.label.text = new haxe.io.Path(importChartFile.filePath).file);
importDataGroup.add(importChartFile); importDataGroup.add(importChartFile);
addLabelOn(importChartFile, "Data/Chart File").applyMarkup( addLabelOn(importChartFile, "Data/Chart File").applyMarkup(
"Data/Chart File $* Required$", "Data/Chart File $* Required$",
@@ -347,7 +349,7 @@ class SongCreationScreen extends UISubstateWindow {
function saveSongInfo() { function saveSongInfo() {
if (isImporting) if (isImporting)
{ {
switch(engineDropdown.options[engineDropdown.index]) try switch(engineDropdown.options[engineDropdown.index])
{ {
case "V-Slice Project (.fnfc)": case "V-Slice Project (.fnfc)":
var files:Map<String, Any> = []; var files:Map<String, Any> = [];
@@ -365,6 +367,39 @@ class SongCreationScreen extends UISubstateWindow {
files.set('Inst.${Flags.SOUND_EXT}', importInstExplorer.file); files.set('Inst.${Flags.SOUND_EXT}', importInstExplorer.file);
files.set('Voices.${Flags.SOUND_EXT}', importVoicesExplorer.file); files.set('Voices.${Flags.SOUND_EXT}', importVoicesExplorer.file);
saveFromVSlice(files, songId); saveFromVSlice(files, songId);
default /*"Psych/Legacy FNF"*/:
var songId = importIdTextBox.label.text;
var oldChart:SwagSong = Json.parse(cast importChartFile.file);
var base:ChartData = {
strumLines: [],
noteTypes: [],
events: [],
meta: {name: null},
scrollSpeed: Flags.DEFAULT_SCROLL_SPEED,
stage: Flags.DEFAULT_STAGE,
codenameChart: true
};
PsychParser.parse(oldChart, base);
if (onSave != null) onSave({
meta: {
name: songId,
difficulties: [songId],
bpm: oldChart.bpm,
beatsPerMeasure: oldChart.beatsPerMeasure,
stepsPerBeat: oldChart.stepsPerBeat,
displayName: oldChart.song
},
instBytes: importInstExplorer.file,
voicesBytes: importVoicesExplorer.file,
}, (songFolder:String, creation:SongCreationData) -> {
#if sys
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), [
{label: "Ok", color: 0xFFFF0000, onClick: function(t) {}}
]));
} }
} else { } else {
for (stepper in [bpmStepper, beatsPerMeasureStepper, stepsPerBeatStepper]) for (stepper in [bpmStepper, beatsPerMeasureStepper, stepsPerBeatStepper])
+7 -3
View File
@@ -5,17 +5,20 @@ class UIDropDown extends UISliceSprite {
public var label:UIText; public var label:UIText;
public var index:Int = 0; public var index:Int = 0;
public var options:Array<String>; public var options:Array<String> = [];
public var subTexts:Array<String> = [];
public var onChange:Int->Void; public var onChange:Int->Void;
var curMenu:UIContextMenu = null; var curMenu:UIContextMenu = null;
public function new(x:Float, y:Float, width:Int = 320, height:Int = 32, options:Array<String>, index:Int = 0) { public function new(x:Float, y:Float, width:Int = 320, height:Int = 32, options:Array<String>, index:Int = 0, ?subTexts:Array<String>) {
super(x, y, width - height, height, 'editors/ui/inputbox'); // using same sprite cause fuck you super(x, y, width - height, height, 'editors/ui/inputbox'); // using same sprite cause fuck you
this.options = options; this.options = options;
this.index = index; this.index = index;
if (subTexts != null)
this.subTexts = subTexts;
cursor = BUTTON; cursor = BUTTON;
@@ -55,7 +58,8 @@ class UIDropDown extends UISliceSprite {
curMenu = UIState.state.openContextMenu([ curMenu = UIState.state.openContextMenu([
for(k=>o in options) { for(k=>o in options) {
icon: (k == index) ? 1 : 0, icon: (k == index) ? 1 : 0,
label: o label: o,
keybindText: subTexts[k]
} }
], function(_, i, _) { ], function(_, i, _) {
setOption(i); setOption(i);
+3 -1
View File
@@ -10,6 +10,7 @@ class UIFileExplorer extends UISliceSprite {
public var deleteButton:UIButton; public var deleteButton:UIButton;
public var deleteIcon:FlxSprite; public var deleteIcon:FlxSprite;
public var filePath:String = null;
public var file:Bytes = null; public var file:Bytes = null;
public var onFile:Bytes->Void; public var onFile:Bytes->Void;
@@ -26,7 +27,8 @@ class UIFileExplorer extends UISliceSprite {
uploadButton = new UIButton(x + 8, y+ 8, "", function () { uploadButton = new UIButton(x + 8, y+ 8, "", function () {
if (!selectable) return; if (!selectable) return;
var fileDialog = new FileDialog(); var fileDialog = new FileDialog();
fileDialog.onOpen.add(function(res) { fileDialog.onOpenFile.add(function(res, path) {
filePath = path;
file = cast res; file = cast res;
deleteButton.visible = deleteButton.selectable = deleteIcon.visible = !(uploadButton.visible = uploadButton.selectable = false); deleteButton.visible = deleteButton.selectable = deleteIcon.visible = !(uploadButton.visible = uploadButton.selectable = false);