mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2025-06-19 16:52:03 +00:00
WIP on new chart wizard
This commit is contained in:
parent
20ac91bbd9
commit
3f6cbb61d4
|
@ -1,5 +1,9 @@
|
||||||
package funkin.ui.debug.charting;
|
package funkin.ui.debug.charting;
|
||||||
|
|
||||||
|
import funkin.input.Cursor;
|
||||||
|
import haxe.ui.containers.Box;
|
||||||
|
import haxe.ui.containers.dialogs.Dialogs;
|
||||||
|
import haxe.ui.components.Link;
|
||||||
import flixel.util.FlxTimer;
|
import flixel.util.FlxTimer;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import haxe.ui.containers.dialogs.Dialog;
|
import haxe.ui.containers.dialogs.Dialog;
|
||||||
|
@ -9,7 +13,8 @@ import haxe.ui.components.Image;
|
||||||
class ChartEditorDialogHandler
|
class ChartEditorDialogHandler
|
||||||
{
|
{
|
||||||
static final CHART_EDITOR_DIALOG_ABOUT_LAYOUT = Paths.ui('chart-editor/dialogs/about');
|
static final CHART_EDITOR_DIALOG_ABOUT_LAYOUT = Paths.ui('chart-editor/dialogs/about');
|
||||||
static final CHART_EDITOR_DIALOG_SPLASH_LAYOUT = Paths.ui('chart-editor/dialogs/splash');
|
static final CHART_EDITOR_DIALOG_WELCOME_LAYOUT = Paths.ui('chart-editor/dialogs/welcome');
|
||||||
|
static final CHART_EDITOR_DIALOG_UPLOAD_INST_LAYOUT = Paths.ui('chart-editor/dialogs/upload-inst');
|
||||||
static final CHART_EDITOR_DIALOG_USER_GUIDE_LAYOUT = Paths.ui('chart-editor/dialogs/user-guide');
|
static final CHART_EDITOR_DIALOG_USER_GUIDE_LAYOUT = Paths.ui('chart-editor/dialogs/user-guide');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,9 +28,9 @@ class ChartEditorDialogHandler
|
||||||
/**
|
/**
|
||||||
* Builds and opens a dialog letting the user create a new chart, open a recent chart, or load from a template.
|
* Builds and opens a dialog letting the user create a new chart, open a recent chart, or load from a template.
|
||||||
*/
|
*/
|
||||||
public static function openSplashDialog(state:ChartEditorState, closable:Bool = true):Void
|
public static function openWelcomeDialog(state:ChartEditorState, closable:Bool = true):Void
|
||||||
{
|
{
|
||||||
var dialog:Dialog = openDialog(state, CHART_EDITOR_DIALOG_SPLASH_LAYOUT, true, closable);
|
var dialog:Dialog = openDialog(state, CHART_EDITOR_DIALOG_WELCOME_LAYOUT, true, closable);
|
||||||
|
|
||||||
// TODO: Add callbacks to the dialog buttons
|
// TODO: Add callbacks to the dialog buttons
|
||||||
|
|
||||||
|
@ -57,6 +62,77 @@ class ChartEditorDialogHandler
|
||||||
bfSprite.visible = true;
|
bfSprite.visible = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add handlers to the "Create From Song" section.
|
||||||
|
var linkCreateBasic:Link = dialog.findComponent('splashCreateFromSongBasic', Link);
|
||||||
|
linkCreateBasic.onClick = (_event) ->
|
||||||
|
{
|
||||||
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
|
openUploadInstDialog(state, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the list of songs and insert them as links into the "Create From Song" section.
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function openUploadInstDialog(state:ChartEditorState, ?closable:Bool = true):Void
|
||||||
|
{
|
||||||
|
var dialog:Dialog = openDialog(state, CHART_EDITOR_DIALOG_UPLOAD_INST_LAYOUT, true, closable);
|
||||||
|
|
||||||
|
var instrumentalBox:Box = dialog.findComponent('instrumentalBox', Box);
|
||||||
|
|
||||||
|
instrumentalBox.onMouseOver = (_event) ->
|
||||||
|
{
|
||||||
|
instrumentalBox.swapClass('upload-bg', 'upload-bg-hover');
|
||||||
|
Cursor.cursorMode = Pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
instrumentalBox.onMouseOut = (_event) ->
|
||||||
|
{
|
||||||
|
instrumentalBox.swapClass('upload-bg-hover', 'upload-bg');
|
||||||
|
Cursor.cursorMode = Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
var onDropFile:String->Void;
|
||||||
|
|
||||||
|
instrumentalBox.onClick = (_event) ->
|
||||||
|
{
|
||||||
|
Dialogs.openBinaryFile("Open Instrumental", [{label: "Audio File (.ogg)", extension: "ogg"}], function(selectedFile)
|
||||||
|
{
|
||||||
|
if (selectedFile != null)
|
||||||
|
{
|
||||||
|
trace('Selected file: ' + selectedFile);
|
||||||
|
state.loadInstrumentalFromBytes(selectedFile.bytes);
|
||||||
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
|
removeDropHandler(onDropFile);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onDropFile = (path:String) ->
|
||||||
|
{
|
||||||
|
trace('Dropped file: ' + path);
|
||||||
|
state.loadInstrumentalFromPath(path);
|
||||||
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
|
removeDropHandler(onDropFile);
|
||||||
|
};
|
||||||
|
|
||||||
|
addDropHandler(onDropFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function addDropHandler(handler:String->Void)
|
||||||
|
{
|
||||||
|
#if desktop
|
||||||
|
FlxG.stage.window.onDropFile.add(handler);
|
||||||
|
#else
|
||||||
|
trace('addDropHandler not implemented for this platform');
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
static function removeDropHandler(handler:String->Void)
|
||||||
|
{
|
||||||
|
#if desktop
|
||||||
|
FlxG.stage.window.onDropFile.remove(handler);
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package funkin.ui.debug.charting;
|
package funkin.ui.debug.charting;
|
||||||
|
|
||||||
|
import lime.media.AudioBuffer;
|
||||||
import funkin.input.Cursor;
|
import funkin.input.Cursor;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.addons.display.FlxSliceSprite;
|
import flixel.addons.display.FlxSliceSprite;
|
||||||
|
@ -184,7 +185,15 @@ class ChartEditorState extends HaxeUIState
|
||||||
/**
|
/**
|
||||||
* This is the song's length in PIXELS, same format as scrollPosition.
|
* This is the song's length in PIXELS, same format as scrollPosition.
|
||||||
*/
|
*/
|
||||||
var songLength:Int;
|
var songLength(get, default):Int;
|
||||||
|
|
||||||
|
function get_songLength():Int
|
||||||
|
{
|
||||||
|
if (songLength <= 0)
|
||||||
|
return 1000;
|
||||||
|
|
||||||
|
return songLength;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* songLength, converted to steps.
|
* songLength, converted to steps.
|
||||||
|
@ -278,6 +287,14 @@ class ChartEditorState extends HaxeUIState
|
||||||
return Screen.instance.hasSolidComponentUnderPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
|
return Screen.instance.hasSolidComponentUnderPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isCursorOverHaxeUIButton(get, null):Bool;
|
||||||
|
|
||||||
|
function get_isCursorOverHaxeUIButton():Bool
|
||||||
|
{
|
||||||
|
return Screen.instance.hasSolidComponentUnderPoint(FlxG.mouse.screenX, FlxG.mouse.screenY, haxe.ui.components.Button)
|
||||||
|
|| Screen.instance.hasSolidComponentUnderPoint(FlxG.mouse.screenX, FlxG.mouse.screenY, haxe.ui.components.Link);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The variation ID for the difficulty which is currently being edited.
|
* The variation ID for the difficulty which is currently being edited.
|
||||||
*/
|
*/
|
||||||
|
@ -734,7 +751,9 @@ class ChartEditorState extends HaxeUIState
|
||||||
setupUIListeners();
|
setupUIListeners();
|
||||||
|
|
||||||
// TODO: We should be loading the music later when the user requests it.
|
// TODO: We should be loading the music later when the user requests it.
|
||||||
loadMusic();
|
// loadDefaultMusic();
|
||||||
|
|
||||||
|
ChartEditorDialogHandler.openSplashDialog(this, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildDefaultSongData()
|
function buildDefaultSongData()
|
||||||
|
@ -955,6 +974,9 @@ class ChartEditorState extends HaxeUIState
|
||||||
|
|
||||||
// Add functionality to the menu items.
|
// Add functionality to the menu items.
|
||||||
|
|
||||||
|
addUIClickListener('menubarItemNewChart', (event:MouseEvent) -> ChartEditorDialogHandler.openSplashDialog(this, true));
|
||||||
|
addUIClickListener('menubarItemLoadInst', (event:MouseEvent) -> ChartEditorDialogHandler.openUploadInstDialog(this, true));
|
||||||
|
|
||||||
addUIClickListener('menubarItemUndo', (event:MouseEvent) -> undoLastCommand());
|
addUIClickListener('menubarItemUndo', (event:MouseEvent) -> undoLastCommand());
|
||||||
|
|
||||||
addUIClickListener('menubarItemRedo', (event:MouseEvent) -> redoLastCommand());
|
addUIClickListener('menubarItemRedo', (event:MouseEvent) -> redoLastCommand());
|
||||||
|
@ -1688,8 +1710,11 @@ class ChartEditorState extends HaxeUIState
|
||||||
gridCursor.visible = false;
|
gridCursor.visible = false;
|
||||||
gridCursor.x = -9999;
|
gridCursor.x = -9999;
|
||||||
gridCursor.y = -9999;
|
gridCursor.y = -9999;
|
||||||
|
}
|
||||||
|
|
||||||
Cursor.cursorMode = Default;
|
if (isCursorOverHaxeUIButton && Cursor.cursorMode == Default)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2203,7 +2228,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
*/
|
*/
|
||||||
function handleMusicPlayback()
|
function handleMusicPlayback()
|
||||||
{
|
{
|
||||||
if (audioInstTrack.playing)
|
if (audioInstTrack != null && audioInstTrack.playing)
|
||||||
{
|
{
|
||||||
if (FlxG.mouse.pressedMiddle)
|
if (FlxG.mouse.pressedMiddle)
|
||||||
{
|
{
|
||||||
|
@ -2227,7 +2252,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
|
|
||||||
Conductor.update(audioInstTrack.time);
|
Conductor.update(audioInstTrack.time);
|
||||||
// Resync vocals.
|
// Resync vocals.
|
||||||
if (Math.abs(audioInstTrack.time - audioVocalTrack.time) > 100)
|
if (audioVocalTrack != null && Math.abs(audioInstTrack.time - audioVocalTrack.time) > 100)
|
||||||
audioVocalTrack.time = audioInstTrack.time;
|
audioVocalTrack.time = audioInstTrack.time;
|
||||||
|
|
||||||
// We need time in fractional steps here to allow the song to actually play.
|
// We need time in fractional steps here to allow the song to actually play.
|
||||||
|
@ -2249,18 +2274,25 @@ class ChartEditorState extends HaxeUIState
|
||||||
|
|
||||||
function startAudioPlayback()
|
function startAudioPlayback()
|
||||||
{
|
{
|
||||||
audioInstTrack.play();
|
if (audioInstTrack != null)
|
||||||
audioVocalTrack.play();
|
audioInstTrack.play();
|
||||||
|
if (audioVocalTrack != null)
|
||||||
|
audioVocalTrack.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopAudioPlayback()
|
function stopAudioPlayback()
|
||||||
{
|
{
|
||||||
audioInstTrack.pause();
|
if (audioInstTrack != null)
|
||||||
audioVocalTrack.pause();
|
audioInstTrack.pause();
|
||||||
|
if (audioVocalTrack != null)
|
||||||
|
audioVocalTrack.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleAudioPlayback()
|
function toggleAudioPlayback()
|
||||||
{
|
{
|
||||||
|
if (audioInstTrack == null)
|
||||||
|
return;
|
||||||
|
|
||||||
if (audioInstTrack.playing)
|
if (audioInstTrack.playing)
|
||||||
{
|
{
|
||||||
stopAudioPlayback();
|
stopAudioPlayback();
|
||||||
|
@ -2377,15 +2409,32 @@ class ChartEditorState extends HaxeUIState
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a music track for playback.
|
* Loads an instrumental from an absolute file path, replacing the current instrumental.
|
||||||
*/
|
*/
|
||||||
function loadMusic()
|
public function loadInstrumentalFromPath(path:String):Void
|
||||||
{
|
{
|
||||||
// TODO: How to load music by selecting with a file dialog?
|
var fileBytes:haxe.io.Bytes = sys.io.File.getBytes(path);
|
||||||
audioInstTrack = FlxG.sound.play(Paths.inst('dadbattle'), 1.0, false);
|
loadInstrumentalFromBytes(fileBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads an instrumental from audio byte data, replacing the current instrumental.
|
||||||
|
*/
|
||||||
|
public function loadInstrumentalFromBytes(bytes:haxe.io.Bytes):Void
|
||||||
|
{
|
||||||
|
audioInstTrack = FlxG.sound.load(openfl.media.Sound.loadCompressedDataFromByteArray(ByteArray.fromBytes(bytes)), 1.0, false);
|
||||||
audioInstTrack.autoDestroy = false;
|
audioInstTrack.autoDestroy = false;
|
||||||
audioInstTrack.pause();
|
audioInstTrack.pause();
|
||||||
|
|
||||||
|
// Tell the user the load was successful.
|
||||||
|
// TODO: Un-bork this.
|
||||||
|
// showNotification('Loaded instrumental track successfully.');
|
||||||
|
|
||||||
|
postLoadInstrumental();
|
||||||
|
}
|
||||||
|
|
||||||
|
function postLoadInstrumental()
|
||||||
|
{
|
||||||
// Prevent the time from skipping back to 0 when the song ends.
|
// Prevent the time from skipping back to 0 when the song ends.
|
||||||
audioInstTrack.onComplete = function()
|
audioInstTrack.onComplete = function()
|
||||||
{
|
{
|
||||||
|
@ -2393,11 +2442,6 @@ class ChartEditorState extends HaxeUIState
|
||||||
audioVocalTrack.pause();
|
audioVocalTrack.pause();
|
||||||
};
|
};
|
||||||
|
|
||||||
audioVocalTrack = FlxG.sound.play(Paths.voices('dadbattle'), 1.0, false);
|
|
||||||
audioVocalTrack.autoDestroy = false;
|
|
||||||
audioVocalTrack.pause();
|
|
||||||
|
|
||||||
// TODO: Make sure Conductor works properly with changing BPMs.
|
|
||||||
var DAD_BATTLE_BPM = 180;
|
var DAD_BATTLE_BPM = 180;
|
||||||
var BOPEEBO_BPM = 100;
|
var BOPEEBO_BPM = 100;
|
||||||
Conductor.forceBPM(DAD_BATTLE_BPM);
|
Conductor.forceBPM(DAD_BATTLE_BPM);
|
||||||
|
@ -2416,6 +2460,23 @@ class ChartEditorState extends HaxeUIState
|
||||||
moveSongToScrollPosition();
|
moveSongToScrollPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a music track for playback.
|
||||||
|
*/
|
||||||
|
function loadDefaultMusic()
|
||||||
|
{
|
||||||
|
// TODO: How to load music by selecting with a file dialog?
|
||||||
|
audioInstTrack = FlxG.sound.play(Paths.inst('dadbattle'), 1.0, false);
|
||||||
|
audioInstTrack.autoDestroy = false;
|
||||||
|
audioInstTrack.pause();
|
||||||
|
|
||||||
|
audioVocalTrack = FlxG.sound.play(Paths.voices('dadbattle'), 1.0, false);
|
||||||
|
audioVocalTrack.autoDestroy = false;
|
||||||
|
audioVocalTrack.pause();
|
||||||
|
|
||||||
|
postLoadInstrumental();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When setting the scroll position, except when automatically scrolling during song playback,
|
* When setting the scroll position, except when automatically scrolling during song playback,
|
||||||
* we need to update the conductor's current step time and the timestamp of the audio tracks.
|
* we need to update the conductor's current step time and the timestamp of the audio tracks.
|
||||||
|
@ -2426,8 +2487,10 @@ class ChartEditorState extends HaxeUIState
|
||||||
Conductor.update(scrollPositionInMs);
|
Conductor.update(scrollPositionInMs);
|
||||||
|
|
||||||
// Update the songPosition in the audio tracks.
|
// Update the songPosition in the audio tracks.
|
||||||
audioInstTrack.time = scrollPositionInMs + playheadPositionInMs;
|
if (audioInstTrack != null)
|
||||||
audioVocalTrack.time = scrollPositionInMs + playheadPositionInMs;
|
audioInstTrack.time = scrollPositionInMs + playheadPositionInMs;
|
||||||
|
if (audioVocalTrack != null)
|
||||||
|
audioVocalTrack.time = scrollPositionInMs + playheadPositionInMs;
|
||||||
|
|
||||||
// We need to update the note sprites because we changed the scroll position.
|
// We need to update the note sprites because we changed the scroll position.
|
||||||
noteDisplayDirty = true;
|
noteDisplayDirty = true;
|
||||||
|
|
Loading…
Reference in a new issue