mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-23 08:07:54 -05:00
Merge remote-tracking branch 'origin/rewrite/master' into feature/chart-editor-offsets-part-1
This commit is contained in:
commit
e23c1464f6
11 changed files with 237 additions and 97 deletions
2
assets
2
assets
|
@ -1 +1 @@
|
||||||
Subproject commit f3e9cd8355f20445fcad7030fdb6363a2325adb3
|
Subproject commit 830127dcc38e4f0fc35b162bd0f696a77679b046
|
|
@ -32,10 +32,7 @@ class SongDataUtils
|
||||||
return new SongNoteData(time, data, length, kind);
|
return new SongNoteData(time, data, length, kind);
|
||||||
};
|
};
|
||||||
|
|
||||||
trace(notes);
|
|
||||||
trace(notes[0]);
|
|
||||||
var result = [for (i in 0...notes.length) offsetNote(notes[i])];
|
var result = [for (i in 0...notes.length) offsetNote(notes[i])];
|
||||||
trace(result);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +51,36 @@ class SongDataUtils
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an array of SongNoteData objects, return a new array of SongNoteData objects
|
||||||
|
* which excludes any notes whose timestamps are outside of the given range.
|
||||||
|
* @param notes The notes to modify.
|
||||||
|
* @param startTime The start of the range in milliseconds.
|
||||||
|
* @param endTime The end of the range in milliseconds.
|
||||||
|
* @return The filtered array of notes.
|
||||||
|
*/
|
||||||
|
public static function clampSongNoteData(notes:Array<SongNoteData>, startTime:Float, endTime:Float):Array<SongNoteData>
|
||||||
|
{
|
||||||
|
return notes.filter(function(note:SongNoteData):Bool {
|
||||||
|
return note.time >= startTime && note.time <= endTime;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an array of SongEventData objects, return a new array of SongEventData objects
|
||||||
|
* which excludes any events whose timestamps are outside of the given range.
|
||||||
|
* @param events The events to modify.
|
||||||
|
* @param startTime The start of the range in milliseconds.
|
||||||
|
* @param endTime The end of the range in milliseconds.
|
||||||
|
* @return The filtered array of events.
|
||||||
|
*/
|
||||||
|
public static function clampSongEventData(events:Array<SongEventData>, startTime:Float, endTime:Float):Array<SongEventData>
|
||||||
|
{
|
||||||
|
return events.filter(function(event:SongEventData):Bool {
|
||||||
|
return event.time >= startTime && event.time <= endTime;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a new array without a certain subset of notes from an array of SongNoteData objects.
|
* Return a new array without a certain subset of notes from an array of SongNoteData objects.
|
||||||
* Does not mutate the original array.
|
* Does not mutate the original array.
|
||||||
|
|
|
@ -477,6 +477,8 @@ class PlayState extends MusicBeatSubState
|
||||||
var generatedMusic:Bool = false;
|
var generatedMusic:Bool = false;
|
||||||
var perfectMode:Bool = false;
|
var perfectMode:Bool = false;
|
||||||
|
|
||||||
|
static final BACKGROUND_COLOR:FlxColor = FlxColor.MAGENTA;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a new PlayState.
|
* Instantiate a new PlayState.
|
||||||
* @param params The parameters used to initialize the PlayState.
|
* @param params The parameters used to initialize the PlayState.
|
||||||
|
@ -641,6 +643,24 @@ class PlayState extends MusicBeatSubState
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override function draw():Void
|
||||||
|
{
|
||||||
|
// if (FlxG.renderBlit)
|
||||||
|
// {
|
||||||
|
// camGame.fill(BACKGROUND_COLOR);
|
||||||
|
// }
|
||||||
|
// else if (FlxG.renderTile)
|
||||||
|
// {
|
||||||
|
// FlxG.log.warn("PlayState background not displayed properly on tile renderer!");
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// FlxG.log.warn("PlayState background not displayed properly, unknown renderer!");
|
||||||
|
// }
|
||||||
|
|
||||||
|
super.draw();
|
||||||
|
}
|
||||||
|
|
||||||
function assertChartExists():Bool
|
function assertChartExists():Bool
|
||||||
{
|
{
|
||||||
// Returns null if the song failed to load or doesn't have the selected difficulty.
|
// Returns null if the song failed to load or doesn't have the selected difficulty.
|
||||||
|
@ -1272,6 +1292,7 @@ class PlayState extends MusicBeatSubState
|
||||||
function initCameras():Void
|
function initCameras():Void
|
||||||
{
|
{
|
||||||
camGame = new SwagCamera();
|
camGame = new SwagCamera();
|
||||||
|
camGame.bgColor = BACKGROUND_COLOR; // Show a pink background behind the stage.
|
||||||
camHUD = new FlxCamera();
|
camHUD = new FlxCamera();
|
||||||
camHUD.bgColor.alpha = 0; // Show the game scene behind the camera.
|
camHUD.bgColor.alpha = 0; // Show the game scene behind the camera.
|
||||||
camCutscene = new FlxCamera();
|
camCutscene = new FlxCamera();
|
||||||
|
|
|
@ -2223,11 +2223,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
#if sys
|
#if sys
|
||||||
menubarItemGoToBackupsFolder.onClick = _ -> this.openBackupsFolder();
|
menubarItemGoToBackupsFolder.onClick = _ -> this.openBackupsFolder();
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Disable the menu item if we're not on a desktop platform.
|
// Disable the menu item if we're not on a desktop platform.
|
||||||
var menubarItemGoToBackupsFolder = findComponent('menubarItemGoToBackupsFolder', MenuItem);
|
var menubarItemGoToBackupsFolder = findComponent('menubarItemGoToBackupsFolder', MenuItem);
|
||||||
if (menubarItemGoToBackupsFolder != null) menubarItemGoToBackupsFolder.disabled = true;
|
if (menubarItemGoToBackupsFolder != null) menubarItemGoToBackupsFolder.disabled = true;
|
||||||
|
|
||||||
#end
|
#end
|
||||||
|
|
||||||
menubarItemUserGuide.onClick = _ -> this.openUserGuideDialog();
|
menubarItemUserGuide.onClick = _ -> this.openUserGuideDialog();
|
||||||
|
@ -4345,7 +4343,16 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
var startTimestamp:Float = 0;
|
var startTimestamp:Float = 0;
|
||||||
if (playtestStartTime) startTimestamp = scrollPositionInMs + playheadPositionInMs;
|
if (playtestStartTime) startTimestamp = scrollPositionInMs + playheadPositionInMs;
|
||||||
|
|
||||||
var targetSong:Song = Song.buildRaw(currentSongId, songMetadata.values(), availableVariations, songChartData, false);
|
var targetSong:Song;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
targetSong = Song.buildRaw(currentSongId, songMetadata.values(), availableVariations, songChartData, false);
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
this.error("Could Not Playtest", 'Got an error trying to playtest the song.\n${e}');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Rework asset system so we can remove this.
|
// TODO: Rework asset system so we can remove this.
|
||||||
switch (currentSongStage)
|
switch (currentSongStage)
|
||||||
|
@ -4389,6 +4396,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
// Override music.
|
// Override music.
|
||||||
if (audioInstTrack != null) FlxG.sound.music = audioInstTrack;
|
if (audioInstTrack != null) FlxG.sound.music = audioInstTrack;
|
||||||
if (audioVocalTrackGroup != null) targetState.vocals = audioVocalTrackGroup;
|
if (audioVocalTrackGroup != null) targetState.vocals = audioVocalTrackGroup;
|
||||||
|
|
||||||
|
this.persistentUpdate = false;
|
||||||
|
this.persistentDraw = false;
|
||||||
stopWelcomeMusic();
|
stopWelcomeMusic();
|
||||||
openSubState(targetState);
|
openSubState(targetState);
|
||||||
}
|
}
|
||||||
|
@ -4603,6 +4613,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
var prevDifficulty = availableDifficulties[availableDifficulties.length - 1];
|
var prevDifficulty = availableDifficulties[availableDifficulties.length - 1];
|
||||||
selectedDifficulty = prevDifficulty;
|
selectedDifficulty = prevDifficulty;
|
||||||
|
|
||||||
|
Conductor.mapTimeChanges(this.currentSongMetadata.timeChanges);
|
||||||
|
|
||||||
refreshDifficultyTreeSelection();
|
refreshDifficultyTreeSelection();
|
||||||
refreshMetadataToolbox();
|
refreshMetadataToolbox();
|
||||||
}
|
}
|
||||||
|
@ -4721,6 +4733,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
@:nullSafety(Off)
|
@:nullSafety(Off)
|
||||||
function resetConductorAfterTest(_:FlxSubState = null):Void
|
function resetConductorAfterTest(_:FlxSubState = null):Void
|
||||||
{
|
{
|
||||||
|
this.persistentUpdate = true;
|
||||||
|
this.persistentDraw = true;
|
||||||
|
|
||||||
moveSongToScrollPosition();
|
moveSongToScrollPosition();
|
||||||
|
|
||||||
// Reapply the volume.
|
// Reapply the volume.
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
package funkin.ui.debug.charting.commands;
|
||||||
|
|
||||||
|
import funkin.data.song.SongData.SongTimeChange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A command which changes the starting BPM of the song.
|
||||||
|
*/
|
||||||
|
@:nullSafety
|
||||||
|
@:access(funkin.ui.debug.charting.ChartEditorState)
|
||||||
|
class ChangeStartingBPMCommand implements ChartEditorCommand
|
||||||
|
{
|
||||||
|
var targetBPM:Float;
|
||||||
|
|
||||||
|
var previousBPM:Float = 100;
|
||||||
|
|
||||||
|
public function new(targetBPM:Float)
|
||||||
|
{
|
||||||
|
this.targetBPM = targetBPM;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(state:ChartEditorState):Void
|
||||||
|
{
|
||||||
|
var timeChanges:Array<SongTimeChange> = state.currentSongMetadata.timeChanges;
|
||||||
|
if (timeChanges == null || timeChanges.length == 0)
|
||||||
|
{
|
||||||
|
previousBPM = 100;
|
||||||
|
timeChanges = [new SongTimeChange(0, targetBPM)];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
previousBPM = timeChanges[0].bpm;
|
||||||
|
timeChanges[0].bpm = targetBPM;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.currentSongMetadata.timeChanges = timeChanges;
|
||||||
|
|
||||||
|
Conductor.mapTimeChanges(state.currentSongMetadata.timeChanges);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function undo(state:ChartEditorState):Void
|
||||||
|
{
|
||||||
|
var timeChanges:Array<SongTimeChange> = state.currentSongMetadata.timeChanges;
|
||||||
|
if (timeChanges == null || timeChanges.length == 0)
|
||||||
|
{
|
||||||
|
timeChanges = [new SongTimeChange(0, previousBPM)];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeChanges[0].bpm = previousBPM;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.currentSongMetadata.timeChanges = timeChanges;
|
||||||
|
|
||||||
|
Conductor.mapTimeChanges(state.currentSongMetadata.timeChanges);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toString():String
|
||||||
|
{
|
||||||
|
return 'Change Starting BPM to ${targetBPM}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,10 +32,14 @@ class PasteItemsCommand implements ChartEditorCommand
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace(currentClipboard.notes);
|
var stepEndOfSong:Float = Conductor.getTimeInSteps(state.songLengthInMs);
|
||||||
|
var stepCutoff:Float = stepEndOfSong - 1.0;
|
||||||
|
var msCutoff:Float = Conductor.getStepTimeInMs(stepCutoff);
|
||||||
|
|
||||||
addedNotes = SongDataUtils.offsetSongNoteData(currentClipboard.notes, Std.int(targetTimestamp));
|
addedNotes = SongDataUtils.offsetSongNoteData(currentClipboard.notes, Std.int(targetTimestamp));
|
||||||
|
addedNotes = SongDataUtils.clampSongNoteData(addedNotes, 0.0, msCutoff);
|
||||||
addedEvents = SongDataUtils.offsetSongEventData(currentClipboard.events, Std.int(targetTimestamp));
|
addedEvents = SongDataUtils.offsetSongEventData(currentClipboard.events, Std.int(targetTimestamp));
|
||||||
|
addedEvents = SongDataUtils.clampSongEventData(addedEvents, 0.0, msCutoff);
|
||||||
|
|
||||||
state.currentSongChartNoteData = state.currentSongChartNoteData.concat(addedNotes);
|
state.currentSongChartNoteData = state.currentSongChartNoteData.concat(addedNotes);
|
||||||
state.currentSongChartEventData = state.currentSongChartEventData.concat(addedEvents);
|
state.currentSongChartEventData = state.currentSongChartEventData.concat(addedEvents);
|
||||||
|
|
|
@ -110,12 +110,12 @@ class ChartEditorDialogHandler
|
||||||
{
|
{
|
||||||
var dialog:Null<Dialog> = openDialog(state, CHART_EDITOR_DIALOG_BACKUP_AVAILABLE_LAYOUT, true, true);
|
var dialog:Null<Dialog> = openDialog(state, CHART_EDITOR_DIALOG_BACKUP_AVAILABLE_LAYOUT, true, true);
|
||||||
if (dialog == null) throw 'Could not locate Backup Available dialog';
|
if (dialog == null) throw 'Could not locate Backup Available dialog';
|
||||||
dialog.onDialogClosed = function(_event) {
|
dialog.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
// User loaded the backup! Close the welcome dialog behind this.
|
// User loaded the backup! Close the welcome dialog behind this.
|
||||||
if (welcomeDialog != null) welcomeDialog.hideDialog(DialogButton.CANCEL);
|
if (welcomeDialog != null) welcomeDialog.hideDialog(DialogButton.APPLY);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -137,22 +137,22 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
||||||
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Backup Available dialog';
|
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Backup Available dialog';
|
||||||
buttonCancel.onClick = function(_event) {
|
buttonCancel.onClick = function(_) {
|
||||||
// Don't hide the welcome dialog behind this.
|
// Don't hide the welcome dialog behind this.
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
var buttonGoToFolder:Null<Button> = dialog.findComponent('buttonGoToFolder', Button);
|
var buttonGoToFolder:Null<Button> = dialog.findComponent('buttonGoToFolder', Button);
|
||||||
if (buttonGoToFolder == null) throw 'Could not locate buttonGoToFolder button in Backup Available dialog';
|
if (buttonGoToFolder == null) throw 'Could not locate buttonGoToFolder button in Backup Available dialog';
|
||||||
buttonGoToFolder.onClick = function(_event) {
|
buttonGoToFolder.onClick = function(_) {
|
||||||
state.openBackupsFolder();
|
state.openBackupsFolder();
|
||||||
// Don't hide the welcome dialog behind this.
|
// Don't hide the welcome dialog behind this.
|
||||||
// dialog.hideDialog(DialogButton.CANCEL);
|
// Don't close this dialog.
|
||||||
}
|
}
|
||||||
|
|
||||||
var buttonOpenBackup:Null<Button> = dialog.findComponent('buttonOpenBackup', Button);
|
var buttonOpenBackup:Null<Button> = dialog.findComponent('buttonOpenBackup', Button);
|
||||||
if (buttonOpenBackup == null) throw 'Could not locate buttonOpenBackup button in Backup Available dialog';
|
if (buttonOpenBackup == null) throw 'Could not locate buttonOpenBackup button in Backup Available dialog';
|
||||||
buttonOpenBackup.onClick = function(_event) {
|
buttonOpenBackup.onClick = function(_) {
|
||||||
var latestBackupPath:Null<String> = ChartEditorImportExportHandler.getLatestBackupPath();
|
var latestBackupPath:Null<String> = ChartEditorImportExportHandler.getLatestBackupPath();
|
||||||
|
|
||||||
var result:Null<Array<String>> = (latestBackupPath != null) ? state.loadFromFNFCPath(latestBackupPath) : null;
|
var result:Null<Array<String>> = (latestBackupPath != null) ? state.loadFromFNFCPath(latestBackupPath) : null;
|
||||||
|
@ -210,20 +210,20 @@ class ChartEditorDialogHandler
|
||||||
// Open the "Open Chart" wizard
|
// Open the "Open Chart" wizard
|
||||||
// Step 1. Open Chart
|
// Step 1. Open Chart
|
||||||
var openChartDialog:Dialog = openChartDialog(state);
|
var openChartDialog:Dialog = openChartDialog(state);
|
||||||
openChartDialog.onDialogClosed = function(_event) {
|
openChartDialog.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
// Step 2. Upload instrumental
|
// Step 2. Upload instrumental
|
||||||
var uploadInstDialog:Dialog = openUploadInstDialog(state, closable);
|
var uploadInstDialog:Dialog = openUploadInstDialog(state, closable);
|
||||||
uploadInstDialog.onDialogClosed = function(_event) {
|
uploadInstDialog.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
// Step 3. Upload Vocals
|
// Step 3. Upload Vocals
|
||||||
// NOTE: Uploading vocals is optional, so we don't need to check if the user cancelled the wizard.
|
// NOTE: Uploading vocals is optional, so we don't need to check if the user cancelled the wizard.
|
||||||
var uploadVocalsDialog:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog
|
var uploadVocalsDialog:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog
|
||||||
uploadVocalsDialog.onDialogClosed = function(_event) {
|
uploadVocalsDialog.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
state.currentWorkingFilePath = null; // Built from parts, so no .fnfc to save to.
|
state.currentWorkingFilePath = null; // Built from parts, so no .fnfc to save to.
|
||||||
state.switchToCurrentInstrumental();
|
state.switchToCurrentInstrumental();
|
||||||
|
@ -251,20 +251,20 @@ class ChartEditorDialogHandler
|
||||||
// Step 1. Open Chart
|
// Step 1. Open Chart
|
||||||
var openChartDialog:Null<Dialog> = openImportChartDialog(state, format);
|
var openChartDialog:Null<Dialog> = openImportChartDialog(state, format);
|
||||||
if (openChartDialog == null) throw 'Could not locate Import Chart dialog';
|
if (openChartDialog == null) throw 'Could not locate Import Chart dialog';
|
||||||
openChartDialog.onDialogClosed = function(_event) {
|
openChartDialog.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
// Step 2. Upload instrumental
|
// Step 2. Upload instrumental
|
||||||
var uploadInstDialog:Dialog = openUploadInstDialog(state, closable);
|
var uploadInstDialog:Dialog = openUploadInstDialog(state, closable);
|
||||||
uploadInstDialog.onDialogClosed = function(_event) {
|
uploadInstDialog.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
// Step 3. Upload Vocals
|
// Step 3. Upload Vocals
|
||||||
// NOTE: Uploading vocals is optional, so we don't need to check if the user cancelled the wizard.
|
// NOTE: Uploading vocals is optional, so we don't need to check if the user cancelled the wizard.
|
||||||
var uploadVocalsDialog:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog
|
var uploadVocalsDialog:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog
|
||||||
uploadVocalsDialog.onDialogClosed = function(_event) {
|
uploadVocalsDialog.onDialogClosed = function(_) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
state.currentWorkingFilePath = null; // New file, so no path.
|
state.currentWorkingFilePath = null; // New file, so no path.
|
||||||
state.switchToCurrentInstrumental();
|
state.switchToCurrentInstrumental();
|
||||||
|
@ -289,21 +289,21 @@ class ChartEditorDialogHandler
|
||||||
public static function openCreateSongWizardBasicOnly(state:ChartEditorState, closable:Bool):Void
|
public static function openCreateSongWizardBasicOnly(state:ChartEditorState, closable:Bool):Void
|
||||||
{
|
{
|
||||||
// Step 1. Song Metadata
|
// Step 1. Song Metadata
|
||||||
var songMetadataDialog:Dialog = openSongMetadataDialog(state, false, Constants.DEFAULT_VARIATION);
|
var songMetadataDialog:Dialog = openSongMetadataDialog(state, false, Constants.DEFAULT_VARIATION, true);
|
||||||
songMetadataDialog.onDialogClosed = function(_event) {
|
songMetadataDialog.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
// Step 2. Upload Instrumental
|
// Step 2. Upload Instrumental
|
||||||
var uploadInstDialog:Dialog = openUploadInstDialog(state, closable);
|
var uploadInstDialog:Dialog = openUploadInstDialog(state, closable);
|
||||||
uploadInstDialog.onDialogClosed = function(_event) {
|
uploadInstDialog.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
// Step 3. Upload Vocals
|
// Step 3. Upload Vocals
|
||||||
// NOTE: Uploading vocals is optional, so we don't need to check if the user cancelled the wizard.
|
// NOTE: Uploading vocals is optional, so we don't need to check if the user cancelled the wizard.
|
||||||
var uploadVocalsDialog:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog
|
var uploadVocalsDialog:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog
|
||||||
uploadVocalsDialog.onDialogClosed = function(_event) {
|
uploadVocalsDialog.onDialogClosed = function(_) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
state.currentWorkingFilePath = null; // New file, so no path.
|
state.currentWorkingFilePath = null; // New file, so no path.
|
||||||
state.switchToCurrentInstrumental();
|
state.switchToCurrentInstrumental();
|
||||||
|
@ -328,21 +328,21 @@ class ChartEditorDialogHandler
|
||||||
public static function openCreateSongWizardErectOnly(state:ChartEditorState, closable:Bool):Void
|
public static function openCreateSongWizardErectOnly(state:ChartEditorState, closable:Bool):Void
|
||||||
{
|
{
|
||||||
// Step 1. Song Metadata
|
// Step 1. Song Metadata
|
||||||
var songMetadataDialog:Dialog = openSongMetadataDialog(state, true, Constants.DEFAULT_VARIATION);
|
var songMetadataDialog:Dialog = openSongMetadataDialog(state, true, Constants.DEFAULT_VARIATION, true);
|
||||||
songMetadataDialog.onDialogClosed = function(_event) {
|
songMetadataDialog.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
// Step 2. Upload Instrumental
|
// Step 2. Upload Instrumental
|
||||||
var uploadInstDialog:Dialog = openUploadInstDialog(state, closable);
|
var uploadInstDialog:Dialog = openUploadInstDialog(state, closable);
|
||||||
uploadInstDialog.onDialogClosed = function(_event) {
|
uploadInstDialog.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
// Step 3. Upload Vocals
|
// Step 3. Upload Vocals
|
||||||
// NOTE: Uploading vocals is optional, so we don't need to check if the user cancelled the wizard.
|
// NOTE: Uploading vocals is optional, so we don't need to check if the user cancelled the wizard.
|
||||||
var uploadVocalsDialog:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog
|
var uploadVocalsDialog:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog
|
||||||
uploadVocalsDialog.onDialogClosed = function(_event) {
|
uploadVocalsDialog.onDialogClosed = function(_) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
state.currentWorkingFilePath = null; // New file, so no path.
|
state.currentWorkingFilePath = null; // New file, so no path.
|
||||||
state.switchToCurrentInstrumental();
|
state.switchToCurrentInstrumental();
|
||||||
|
@ -367,41 +367,41 @@ class ChartEditorDialogHandler
|
||||||
public static function openCreateSongWizardBasicErect(state:ChartEditorState, closable:Bool):Void
|
public static function openCreateSongWizardBasicErect(state:ChartEditorState, closable:Bool):Void
|
||||||
{
|
{
|
||||||
// Step 1. Song Metadata
|
// Step 1. Song Metadata
|
||||||
var songMetadataDialog:Dialog = openSongMetadataDialog(state, false, Constants.DEFAULT_VARIATION);
|
var songMetadataDialog:Dialog = openSongMetadataDialog(state, false, Constants.DEFAULT_VARIATION, true);
|
||||||
songMetadataDialog.onDialogClosed = function(_event) {
|
songMetadataDialog.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
// Step 2. Upload Instrumental
|
// Step 2. Upload Instrumental
|
||||||
var uploadInstDialog:Dialog = openUploadInstDialog(state, closable);
|
var uploadInstDialog:Dialog = openUploadInstDialog(state, closable);
|
||||||
uploadInstDialog.onDialogClosed = function(_event) {
|
uploadInstDialog.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
// Step 3. Upload Vocals
|
// Step 3. Upload Vocals
|
||||||
// NOTE: Uploading vocals is optional, so we don't need to check if the user cancelled the wizard.
|
// NOTE: Uploading vocals is optional, so we don't need to check if the user cancelled the wizard.
|
||||||
var uploadVocalsDialog:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog
|
var uploadVocalsDialog:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog
|
||||||
uploadVocalsDialog.onDialogClosed = function(_event) {
|
uploadVocalsDialog.onDialogClosed = function(_) {
|
||||||
state.switchToCurrentInstrumental();
|
state.switchToCurrentInstrumental();
|
||||||
// Step 4. Song Metadata (Erect)
|
// Step 4. Song Metadata (Erect)
|
||||||
var songMetadataDialogErect:Dialog = openSongMetadataDialog(state, true, 'erect');
|
var songMetadataDialogErect:Dialog = openSongMetadataDialog(state, true, 'erect', false);
|
||||||
songMetadataDialogErect.onDialogClosed = function(_event) {
|
songMetadataDialogErect.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
// Switch to the Erect variation so uploading the instrumental applies properly.
|
// Switch to the Erect variation so uploading the instrumental applies properly.
|
||||||
state.selectedVariation = 'erect';
|
state.selectedVariation = 'erect';
|
||||||
|
|
||||||
// Step 5. Upload Instrumental (Erect)
|
// Step 5. Upload Instrumental (Erect)
|
||||||
var uploadInstDialogErect:Dialog = openUploadInstDialog(state, closable);
|
var uploadInstDialogErect:Dialog = openUploadInstDialog(state, closable);
|
||||||
uploadInstDialogErect.onDialogClosed = function(_event) {
|
uploadInstDialogErect.onDialogClosed = function(event) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
// Step 6. Upload Vocals (Erect)
|
// Step 6. Upload Vocals (Erect)
|
||||||
// NOTE: Uploading vocals is optional, so we don't need to check if the user cancelled the wizard.
|
// NOTE: Uploading vocals is optional, so we don't need to check if the user cancelled the wizard.
|
||||||
var uploadVocalsDialogErect:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog
|
var uploadVocalsDialogErect:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog
|
||||||
uploadVocalsDialogErect.onDialogClosed = function(_event) {
|
uploadVocalsDialogErect.onDialogClosed = function(_) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
state.currentWorkingFilePath = null; // New file, so no path.
|
state.currentWorkingFilePath = null; // New file, so no path.
|
||||||
state.switchToCurrentInstrumental();
|
state.switchToCurrentInstrumental();
|
||||||
|
@ -453,19 +453,19 @@ class ChartEditorDialogHandler
|
||||||
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
||||||
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Upload Instrumental dialog';
|
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Upload Instrumental dialog';
|
||||||
|
|
||||||
buttonCancel.onClick = function(_event) {
|
buttonCancel.onClick = function(_) {
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
var instrumentalBox:Null<Box> = dialog.findComponent('instrumentalBox', Box);
|
var instrumentalBox:Null<Box> = dialog.findComponent('instrumentalBox', Box);
|
||||||
if (instrumentalBox == null) throw 'Could not locate instrumentalBox in Upload Instrumental dialog';
|
if (instrumentalBox == null) throw 'Could not locate instrumentalBox in Upload Instrumental dialog';
|
||||||
|
|
||||||
instrumentalBox.onMouseOver = function(_event) {
|
instrumentalBox.onMouseOver = function(_) {
|
||||||
instrumentalBox.swapClass('upload-bg', 'upload-bg-hover');
|
instrumentalBox.swapClass('upload-bg', 'upload-bg-hover');
|
||||||
Cursor.cursorMode = Pointer;
|
Cursor.cursorMode = Pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
instrumentalBox.onMouseOut = function(_event) {
|
instrumentalBox.onMouseOut = function(_) {
|
||||||
instrumentalBox.swapClass('upload-bg-hover', 'upload-bg');
|
instrumentalBox.swapClass('upload-bg-hover', 'upload-bg');
|
||||||
Cursor.cursorMode = Default;
|
Cursor.cursorMode = Default;
|
||||||
}
|
}
|
||||||
|
@ -474,7 +474,7 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var dropHandler:DialogDropTarget = {component: instrumentalBox, handler: null};
|
var dropHandler:DialogDropTarget = {component: instrumentalBox, handler: null};
|
||||||
|
|
||||||
instrumentalBox.onClick = function(_event) {
|
instrumentalBox.onClick = function(_) {
|
||||||
Dialogs.openBinaryFile('Open Instrumental', [
|
Dialogs.openBinaryFile('Open Instrumental', [
|
||||||
{label: 'Audio File (.ogg)', extension: 'ogg'}], function(selectedFile:SelectedFileInfo) {
|
{label: 'Audio File (.ogg)', extension: 'ogg'}], function(selectedFile:SelectedFileInfo) {
|
||||||
if (selectedFile != null && selectedFile.bytes != null)
|
if (selectedFile != null && selectedFile.bytes != null)
|
||||||
|
@ -533,10 +533,13 @@ class ChartEditorDialogHandler
|
||||||
/**
|
/**
|
||||||
* Opens the dialog in the wizard where the user can set song metadata like name and artist and BPM.
|
* Opens the dialog in the wizard where the user can set song metadata like name and artist and BPM.
|
||||||
* @param state The ChartEditorState instance.
|
* @param state The ChartEditorState instance.
|
||||||
|
* @param erect Whether to create erect difficulties or normal ones.
|
||||||
|
* @param targetVariation The variation to create difficulties for.
|
||||||
|
* @param clearExistingMetadata Whether to clear existing metadata when confirming.
|
||||||
* @return The dialog to open.
|
* @return The dialog to open.
|
||||||
*/
|
*/
|
||||||
@:haxe.warning("-WVarInit")
|
@:haxe.warning("-WVarInit")
|
||||||
public static function openSongMetadataDialog(state:ChartEditorState, erect:Bool, targetVariation:String):Dialog
|
public static function openSongMetadataDialog(state:ChartEditorState, erect:Bool, targetVariation:String, clearExistingMetadata:Bool):Dialog
|
||||||
{
|
{
|
||||||
var dialog:Null<Dialog> = openDialog(state, CHART_EDITOR_DIALOG_SONG_METADATA_LAYOUT, true, false);
|
var dialog:Null<Dialog> = openDialog(state, CHART_EDITOR_DIALOG_SONG_METADATA_LAYOUT, true, false);
|
||||||
if (dialog == null) throw 'Could not locate Song Metadata dialog';
|
if (dialog == null) throw 'Could not locate Song Metadata dialog';
|
||||||
|
@ -549,7 +552,7 @@ class ChartEditorDialogHandler
|
||||||
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
||||||
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Song Metadata dialog';
|
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Song Metadata dialog';
|
||||||
state.isHaxeUIDialogOpen = true;
|
state.isHaxeUIDialogOpen = true;
|
||||||
buttonCancel.onClick = function(_event) {
|
buttonCancel.onClick = function(_) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
}
|
}
|
||||||
|
@ -661,8 +664,12 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var dialogContinue:Null<Button> = dialog.findComponent('dialogContinue', Button);
|
var dialogContinue:Null<Button> = dialog.findComponent('dialogContinue', Button);
|
||||||
if (dialogContinue == null) throw 'Could not locate dialogContinue button in Song Metadata dialog';
|
if (dialogContinue == null) throw 'Could not locate dialogContinue button in Song Metadata dialog';
|
||||||
dialogContinue.onClick = (_event) -> {
|
dialogContinue.onClick = (_) -> {
|
||||||
if (targetVariation == Constants.DEFAULT_VARIATION) state.songMetadata.clear();
|
if (clearExistingMetadata)
|
||||||
|
{
|
||||||
|
state.songMetadata.clear();
|
||||||
|
state.songChartData.clear();
|
||||||
|
}
|
||||||
|
|
||||||
state.songMetadata.set(targetVariation, newSongMetadata);
|
state.songMetadata.set(targetVariation, newSongMetadata);
|
||||||
|
|
||||||
|
@ -702,13 +709,13 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
||||||
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Upload Vocals dialog';
|
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Upload Vocals dialog';
|
||||||
buttonCancel.onClick = function(_event) {
|
buttonCancel.onClick = function(_) {
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dialogNoVocals:Null<Button> = dialog.findComponent('dialogNoVocals', Button);
|
var dialogNoVocals:Null<Button> = dialog.findComponent('dialogNoVocals', Button);
|
||||||
if (dialogNoVocals == null) throw 'Could not locate dialogNoVocals button in Upload Vocals dialog';
|
if (dialogNoVocals == null) throw 'Could not locate dialogNoVocals button in Upload Vocals dialog';
|
||||||
dialogNoVocals.onClick = function(_event) {
|
dialogNoVocals.onClick = function(_) {
|
||||||
// Dismiss
|
// Dismiss
|
||||||
state.wipeVocalData();
|
state.wipeVocalData();
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
|
@ -820,7 +827,7 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var dialogContinue:Null<Button> = dialog.findComponent('dialogContinue', Button);
|
var dialogContinue:Null<Button> = dialog.findComponent('dialogContinue', Button);
|
||||||
if (dialogContinue == null) throw 'Could not locate dialogContinue button in Upload Vocals dialog';
|
if (dialogContinue == null) throw 'Could not locate dialogContinue button in Upload Vocals dialog';
|
||||||
dialogContinue.onClick = function(_event) {
|
dialogContinue.onClick = function(_) {
|
||||||
// Dismiss
|
// Dismiss
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
};
|
};
|
||||||
|
@ -842,7 +849,7 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
||||||
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Open Chart dialog';
|
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Open Chart dialog';
|
||||||
buttonCancel.onClick = function(_event) {
|
buttonCancel.onClick = function(_) {
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -856,7 +863,7 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var buttonContinue:Null<Button> = dialog.findComponent('dialogContinue', Button);
|
var buttonContinue:Null<Button> = dialog.findComponent('dialogContinue', Button);
|
||||||
if (buttonContinue == null) throw 'Could not locate dialogContinue button in Open Chart dialog';
|
if (buttonContinue == null) throw 'Could not locate dialogContinue button in Open Chart dialog';
|
||||||
buttonContinue.onClick = function(_event) {
|
buttonContinue.onClick = function(_) {
|
||||||
state.loadSong(songMetadata, songChartData);
|
state.loadSong(songMetadata, songChartData);
|
||||||
|
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
|
@ -904,11 +911,11 @@ class ChartEditorDialogHandler
|
||||||
songVariationMetadataEntryLabel.text = 'Click to browse for <song>-metadata-${variation}.json file.';
|
songVariationMetadataEntryLabel.text = 'Click to browse for <song>-metadata-${variation}.json file.';
|
||||||
#end
|
#end
|
||||||
|
|
||||||
songVariationMetadataEntry.onMouseOver = function(_event) {
|
songVariationMetadataEntry.onMouseOver = function(_) {
|
||||||
songVariationMetadataEntry.swapClass('upload-bg', 'upload-bg-hover');
|
songVariationMetadataEntry.swapClass('upload-bg', 'upload-bg-hover');
|
||||||
Cursor.cursorMode = Pointer;
|
Cursor.cursorMode = Pointer;
|
||||||
}
|
}
|
||||||
songVariationMetadataEntry.onMouseOut = function(_event) {
|
songVariationMetadataEntry.onMouseOut = function(_) {
|
||||||
songVariationMetadataEntry.swapClass('upload-bg-hover', 'upload-bg');
|
songVariationMetadataEntry.swapClass('upload-bg-hover', 'upload-bg');
|
||||||
Cursor.cursorMode = Default;
|
Cursor.cursorMode = Default;
|
||||||
}
|
}
|
||||||
|
@ -928,11 +935,11 @@ class ChartEditorDialogHandler
|
||||||
songVariationChartDataEntryLabel.text = 'Click to browse for <song>-chart-${variation}.json file.';
|
songVariationChartDataEntryLabel.text = 'Click to browse for <song>-chart-${variation}.json file.';
|
||||||
#end
|
#end
|
||||||
|
|
||||||
songVariationChartDataEntry.onMouseOver = function(_event) {
|
songVariationChartDataEntry.onMouseOver = function(_) {
|
||||||
songVariationChartDataEntry.swapClass('upload-bg', 'upload-bg-hover');
|
songVariationChartDataEntry.swapClass('upload-bg', 'upload-bg-hover');
|
||||||
Cursor.cursorMode = Pointer;
|
Cursor.cursorMode = Pointer;
|
||||||
}
|
}
|
||||||
songVariationChartDataEntry.onMouseOut = function(_event) {
|
songVariationChartDataEntry.onMouseOut = function(_) {
|
||||||
songVariationChartDataEntry.swapClass('upload-bg-hover', 'upload-bg');
|
songVariationChartDataEntry.swapClass('upload-bg-hover', 'upload-bg');
|
||||||
Cursor.cursorMode = Default;
|
Cursor.cursorMode = Default;
|
||||||
}
|
}
|
||||||
|
@ -982,7 +989,7 @@ class ChartEditorDialogHandler
|
||||||
if (variation == Constants.DEFAULT_VARIATION) constructVariationEntries(songMetadataVariation.playData.songVariations);
|
if (variation == Constants.DEFAULT_VARIATION) constructVariationEntries(songMetadataVariation.playData.songVariations);
|
||||||
};
|
};
|
||||||
|
|
||||||
onClickMetadataVariation = function(variation:String, label:Label, _event:UIEvent) {
|
onClickMetadataVariation = function(variation:String, label:Label, _:UIEvent) {
|
||||||
Dialogs.openBinaryFile('Open Chart ($variation) Metadata', [
|
Dialogs.openBinaryFile('Open Chart ($variation) Metadata', [
|
||||||
{label: 'JSON File (.json)', extension: 'json'}], function(selectedFile) {
|
{label: 'JSON File (.json)', extension: 'json'}], function(selectedFile) {
|
||||||
if (selectedFile != null && selectedFile.bytes != null)
|
if (selectedFile != null && selectedFile.bytes != null)
|
||||||
|
@ -1066,7 +1073,7 @@ class ChartEditorDialogHandler
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onClickChartDataVariation = function(variation:String, label:Label, _event:UIEvent) {
|
onClickChartDataVariation = function(variation:String, label:Label, _:UIEvent) {
|
||||||
Dialogs.openBinaryFile('Open Chart ($variation) Metadata', [
|
Dialogs.openBinaryFile('Open Chart ($variation) Metadata', [
|
||||||
{label: 'JSON File (.json)', extension: 'json'}], function(selectedFile) {
|
{label: 'JSON File (.json)', extension: 'json'}], function(selectedFile) {
|
||||||
if (selectedFile != null && selectedFile.bytes != null)
|
if (selectedFile != null && selectedFile.bytes != null)
|
||||||
|
@ -1122,7 +1129,7 @@ class ChartEditorDialogHandler
|
||||||
metadataEntry.swapClass('upload-bg', 'upload-bg-hover');
|
metadataEntry.swapClass('upload-bg', 'upload-bg-hover');
|
||||||
Cursor.cursorMode = Pointer;
|
Cursor.cursorMode = Pointer;
|
||||||
}
|
}
|
||||||
metadataEntry.onMouseOut = function(_event) {
|
metadataEntry.onMouseOut = function(_) {
|
||||||
metadataEntry.swapClass('upload-bg-hover', 'upload-bg');
|
metadataEntry.swapClass('upload-bg-hover', 'upload-bg');
|
||||||
Cursor.cursorMode = Default;
|
Cursor.cursorMode = Default;
|
||||||
}
|
}
|
||||||
|
@ -1162,7 +1169,7 @@ class ChartEditorDialogHandler
|
||||||
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Import Chart dialog';
|
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Import Chart dialog';
|
||||||
|
|
||||||
state.isHaxeUIDialogOpen = true;
|
state.isHaxeUIDialogOpen = true;
|
||||||
buttonCancel.onClick = function(_event) {
|
buttonCancel.onClick = function(_) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
}
|
}
|
||||||
|
@ -1170,18 +1177,18 @@ class ChartEditorDialogHandler
|
||||||
var importBox:Null<Box> = dialog.findComponent('importBox', Box);
|
var importBox:Null<Box> = dialog.findComponent('importBox', Box);
|
||||||
if (importBox == null) throw 'Could not locate importBox in Import Chart dialog';
|
if (importBox == null) throw 'Could not locate importBox in Import Chart dialog';
|
||||||
|
|
||||||
importBox.onMouseOver = function(_event) {
|
importBox.onMouseOver = function(_) {
|
||||||
importBox.swapClass('upload-bg', 'upload-bg-hover');
|
importBox.swapClass('upload-bg', 'upload-bg-hover');
|
||||||
Cursor.cursorMode = Pointer;
|
Cursor.cursorMode = Pointer;
|
||||||
}
|
}
|
||||||
importBox.onMouseOut = function(_event) {
|
importBox.onMouseOut = function(_) {
|
||||||
importBox.swapClass('upload-bg-hover', 'upload-bg');
|
importBox.swapClass('upload-bg-hover', 'upload-bg');
|
||||||
Cursor.cursorMode = Default;
|
Cursor.cursorMode = Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
var onDropFile:String->Void;
|
var onDropFile:String->Void;
|
||||||
|
|
||||||
importBox.onClick = function(_event) {
|
importBox.onClick = function(_) {
|
||||||
Dialogs.openBinaryFile('Import Chart - ${prettyFormat}', fileFilter != null ? [fileFilter] : [], function(selectedFile:SelectedFileInfo) {
|
Dialogs.openBinaryFile('Import Chart - ${prettyFormat}', fileFilter != null ? [fileFilter] : [], function(selectedFile:SelectedFileInfo) {
|
||||||
if (selectedFile != null && selectedFile.bytes != null)
|
if (selectedFile != null && selectedFile.bytes != null)
|
||||||
{
|
{
|
||||||
|
@ -1251,13 +1258,13 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
||||||
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Add Variation dialog';
|
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Add Variation dialog';
|
||||||
buttonCancel.onClick = function(_event) {
|
buttonCancel.onClick = function(_) {
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
var buttonAdd:Null<Button> = dialog.findComponent('dialogAdd', Button);
|
var buttonAdd:Null<Button> = dialog.findComponent('dialogAdd', Button);
|
||||||
if (buttonAdd == null) throw 'Could not locate dialogAdd button in Add Variation dialog';
|
if (buttonAdd == null) throw 'Could not locate dialogAdd button in Add Variation dialog';
|
||||||
buttonAdd.onClick = function(_event) {
|
buttonAdd.onClick = function(_) {
|
||||||
// This performs validation before the onSubmit callback is called.
|
// This performs validation before the onSubmit callback is called.
|
||||||
variationForm.submit();
|
variationForm.submit();
|
||||||
}
|
}
|
||||||
|
@ -1296,12 +1303,13 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var dialogBPM:Null<NumberStepper> = dialog.findComponent('dialogBPM', NumberStepper);
|
var dialogBPM:Null<NumberStepper> = dialog.findComponent('dialogBPM', NumberStepper);
|
||||||
if (dialogBPM == null) throw 'Could not locate dialogBPM NumberStepper in Add Variation dialog';
|
if (dialogBPM == null) throw 'Could not locate dialogBPM NumberStepper in Add Variation dialog';
|
||||||
dialogBPM.value = state.currentSongMetadata.timeChanges[0].bpm;
|
var currentStartingBPM:Float = state.currentSongMetadata.timeChanges[0].bpm;
|
||||||
|
dialogBPM.value = currentStartingBPM;
|
||||||
|
|
||||||
// If all validators succeeded, this callback is called.
|
// If all validators succeeded, this callback is called.
|
||||||
|
|
||||||
state.isHaxeUIDialogOpen = true;
|
state.isHaxeUIDialogOpen = true;
|
||||||
variationForm.onSubmit = function(_event) {
|
variationForm.onSubmit = function(_) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
trace('Add Variation dialog submitted, validation succeeded!');
|
trace('Add Variation dialog submitted, validation succeeded!');
|
||||||
|
|
||||||
|
@ -1317,6 +1325,8 @@ class ChartEditorDialogHandler
|
||||||
state.songMetadata.set(pendingVariation.variation, pendingVariation);
|
state.songMetadata.set(pendingVariation.variation, pendingVariation);
|
||||||
state.difficultySelectDirty = true; // Force the Difficulty toolbox to update.
|
state.difficultySelectDirty = true; // Force the Difficulty toolbox to update.
|
||||||
|
|
||||||
|
// Don't update conductor since we haven't switched to the new variation yet.
|
||||||
|
|
||||||
state.success('Add Variation', 'Added new variation "${pendingVariation.variation}"');
|
state.success('Add Variation', 'Added new variation "${pendingVariation.variation}"');
|
||||||
|
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
|
@ -1341,13 +1351,13 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
||||||
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Add Difficulty dialog';
|
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Add Difficulty dialog';
|
||||||
buttonCancel.onClick = function(_event) {
|
buttonCancel.onClick = function(_) {
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
var buttonAdd:Null<Button> = dialog.findComponent('dialogAdd', Button);
|
var buttonAdd:Null<Button> = dialog.findComponent('dialogAdd', Button);
|
||||||
if (buttonAdd == null) throw 'Could not locate dialogAdd button in Add Difficulty dialog';
|
if (buttonAdd == null) throw 'Could not locate dialogAdd button in Add Difficulty dialog';
|
||||||
buttonAdd.onClick = function(_event) {
|
buttonAdd.onClick = function(_) {
|
||||||
// This performs validation before the onSubmit callback is called.
|
// This performs validation before the onSubmit callback is called.
|
||||||
difficultyForm.submit();
|
difficultyForm.submit();
|
||||||
}
|
}
|
||||||
|
@ -1367,7 +1377,7 @@ class ChartEditorDialogHandler
|
||||||
inputScrollSpeed.value = state.currentSongChartScrollSpeed;
|
inputScrollSpeed.value = state.currentSongChartScrollSpeed;
|
||||||
labelScrollSpeed.text = 'Scroll Speed: ${inputScrollSpeed.value}x';
|
labelScrollSpeed.text = 'Scroll Speed: ${inputScrollSpeed.value}x';
|
||||||
|
|
||||||
difficultyForm.onSubmit = function(_event) {
|
difficultyForm.onSubmit = function(_) {
|
||||||
trace('Add Difficulty dialog submitted, validation succeeded!');
|
trace('Add Difficulty dialog submitted, validation succeeded!');
|
||||||
|
|
||||||
var dialogDifficultyName:Null<TextField> = dialog.findComponent('dialogDifficultyName', TextField);
|
var dialogDifficultyName:Null<TextField> = dialog.findComponent('dialogDifficultyName', TextField);
|
||||||
|
|
|
@ -21,7 +21,7 @@ class ChartEditorNotificationHandler
|
||||||
*/
|
*/
|
||||||
public static function success(state:ChartEditorState, title:String, body:String):Notification
|
public static function success(state:ChartEditorState, title:String, body:String):Notification
|
||||||
{
|
{
|
||||||
return sendNotification(title, body, NotificationType.Success);
|
return sendNotification(state, title, body, NotificationType.Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,7 +30,7 @@ class ChartEditorNotificationHandler
|
||||||
*/
|
*/
|
||||||
public static function warning(state:ChartEditorState, title:String, body:String):Notification
|
public static function warning(state:ChartEditorState, title:String, body:String):Notification
|
||||||
{
|
{
|
||||||
return sendNotification(title, body, NotificationType.Warning);
|
return sendNotification(state, title, body, NotificationType.Warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,7 +48,7 @@ class ChartEditorNotificationHandler
|
||||||
*/
|
*/
|
||||||
public static function error(state:ChartEditorState, title:String, body:String):Notification
|
public static function error(state:ChartEditorState, title:String, body:String):Notification
|
||||||
{
|
{
|
||||||
return sendNotification(title, body, NotificationType.Error);
|
return sendNotification(state, title, body, NotificationType.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,7 +66,7 @@ class ChartEditorNotificationHandler
|
||||||
*/
|
*/
|
||||||
public static function info(state:ChartEditorState, title:String, body:String):Notification
|
public static function info(state:ChartEditorState, title:String, body:String):Notification
|
||||||
{
|
{
|
||||||
return sendNotification(title, body, NotificationType.Info);
|
return sendNotification(state, title, body, NotificationType.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,7 +79,7 @@ class ChartEditorNotificationHandler
|
||||||
*/
|
*/
|
||||||
public static function infoWithActions(state:ChartEditorState, title:String, body:String, actions:Array<NotificationAction>):Notification
|
public static function infoWithActions(state:ChartEditorState, title:String, body:String, actions:Array<NotificationAction>):Notification
|
||||||
{
|
{
|
||||||
return sendNotification(title, body, NotificationType.Info, actions);
|
return sendNotification(state, title, body, NotificationType.Info, actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,7 +101,7 @@ class ChartEditorNotificationHandler
|
||||||
NotificationManager.instance.removeNotification(notif);
|
NotificationManager.instance.removeNotification(notif);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function sendNotification(title:String, body:String, ?type:NotificationType, ?actions:Array<NotificationAction>):Notification
|
static function sendNotification(state:ChartEditorState, title:String, body:String, ?type:NotificationType, ?actions:Array<NotificationAction>):Notification
|
||||||
{
|
{
|
||||||
#if !mac
|
#if !mac
|
||||||
var actionNames:Array<String> = actions == null ? [] : actions.map(action -> action.text);
|
var actionNames:Array<String> = actions == null ? [] : actions.map(action -> action.text);
|
||||||
|
@ -127,6 +127,8 @@ class ChartEditorNotificationHandler
|
||||||
if (action != null && action.callback != null)
|
if (action != null && action.callback != null)
|
||||||
{
|
{
|
||||||
button.onClick = function(_) {
|
button.onClick = function(_) {
|
||||||
|
// Don't allow actions to be clicked while the playtest is open.
|
||||||
|
if (state.subState != null) return;
|
||||||
action.callback();
|
action.callback();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -137,6 +139,8 @@ class ChartEditorNotificationHandler
|
||||||
|
|
||||||
return notif;
|
return notif;
|
||||||
#else
|
#else
|
||||||
|
// TODO: Implement notifications on Mac OS OR... make sure the null is handled properly on mac?
|
||||||
|
return null;
|
||||||
trace('WARNING: Notifications are not supported on Mac OS.');
|
trace('WARNING: Notifications are not supported on Mac OS.');
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import funkin.play.character.BaseCharacter.CharacterType;
|
||||||
import funkin.play.event.SongEvent;
|
import funkin.play.event.SongEvent;
|
||||||
import funkin.data.event.SongEventData;
|
import funkin.data.event.SongEventData;
|
||||||
import funkin.data.song.SongData.SongTimeChange;
|
import funkin.data.song.SongData.SongTimeChange;
|
||||||
|
import funkin.ui.debug.charting.commands.ChangeStartingBPMCommand;
|
||||||
import funkin.play.character.BaseCharacter.CharacterType;
|
import funkin.play.character.BaseCharacter.CharacterType;
|
||||||
import funkin.play.character.CharacterData;
|
import funkin.play.character.CharacterData;
|
||||||
import funkin.play.character.CharacterData.CharacterDataParser;
|
import funkin.play.character.CharacterData.CharacterDataParser;
|
||||||
|
@ -610,19 +611,12 @@ class ChartEditorToolboxHandler
|
||||||
inputBPM.onChange = function(event:UIEvent) {
|
inputBPM.onChange = function(event:UIEvent) {
|
||||||
if (event.value == null || event.value <= 0) return;
|
if (event.value == null || event.value <= 0) return;
|
||||||
|
|
||||||
var timeChanges:Array<SongTimeChange> = state.currentSongMetadata.timeChanges;
|
// Use a command so we can undo/redo this action.
|
||||||
if (timeChanges == null || timeChanges.length == 0)
|
var startingBPM = state.currentSongMetadata.timeChanges[0].bpm;
|
||||||
|
if (event.value != startingBPM)
|
||||||
{
|
{
|
||||||
timeChanges = [new SongTimeChange(0, event.value)];
|
state.performCommand(new ChangeStartingBPMCommand(event.value));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
timeChanges[0].bpm = event.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.currentSongMetadata.timeChanges = timeChanges;
|
|
||||||
|
|
||||||
Conductor.mapTimeChanges(state.currentSongMetadata.timeChanges);
|
|
||||||
};
|
};
|
||||||
inputBPM.value = state.currentSongMetadata.timeChanges[0].bpm;
|
inputBPM.value = state.currentSongMetadata.timeChanges[0].bpm;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package funkin.util.macro;
|
package funkin.util.macro;
|
||||||
|
|
||||||
|
#if !display
|
||||||
#if macro
|
#if macro
|
||||||
class FlxMacro
|
class FlxMacro
|
||||||
{
|
{
|
||||||
|
@ -33,3 +34,4 @@ class FlxMacro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
|
#end
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package funkin.util.macro;
|
package funkin.util.macro;
|
||||||
|
|
||||||
|
#if !display
|
||||||
#if (debug || FORCE_DEBUG_VERSION)
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
class GitCommit
|
class GitCommit
|
||||||
{
|
{
|
||||||
|
@ -65,3 +66,4 @@ class GitCommit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
|
#end
|
||||||
|
|
Loading…
Reference in a new issue