mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2024-12-25 22:47:52 +00:00
Fix 5 or 6 issues with charting
This commit is contained in:
parent
8c002393e3
commit
20e6c7a2be
|
@ -156,9 +156,13 @@
|
||||||
<haxeflag name="--macro" value="include('funkin')" />
|
<haxeflag name="--macro" value="include('funkin')" />
|
||||||
|
|
||||||
<!-- Ensure all UI components are available at runtime. -->
|
<!-- Ensure all UI components are available at runtime. -->
|
||||||
|
<haxeflag name="--macro" value="include('haxe.ui.backend.flixel.components')" />
|
||||||
|
<haxeflag name="--macro" value="include('haxe.ui.containers.dialogs')" />
|
||||||
|
<haxeflag name="--macro" value="include('haxe.ui.containers.menus')" />
|
||||||
|
<haxeflag name="--macro" value="include('haxe.ui.containers.properties')" />
|
||||||
|
<haxeflag name="--macro" value="include('haxe.ui.core')" />
|
||||||
<haxeflag name="--macro" value="include('haxe.ui.components')" />
|
<haxeflag name="--macro" value="include('haxe.ui.components')" />
|
||||||
<haxeflag name="--macro" value="include('haxe.ui.containers')" />
|
<haxeflag name="--macro" value="include('haxe.ui.containers')" />
|
||||||
<haxeflag name="--macro" value="include('haxe.ui.containers.menus')" />
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Ensure additional class packages are available at runtime (some only really used by scripts).
|
Ensure additional class packages are available at runtime (some only really used by scripts).
|
||||||
|
|
3
haxe_libraries/README.md
Normal file
3
haxe_libraries/README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# haxe_libraries
|
||||||
|
|
||||||
|
Used by Lix
|
|
@ -1,5 +1,6 @@
|
||||||
package funkin.ui.debug.charting;
|
package funkin.ui.debug.charting;
|
||||||
|
|
||||||
|
import haxe.io.Path;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.util.FlxTimer;
|
import flixel.util.FlxTimer;
|
||||||
import funkin.input.Cursor;
|
import funkin.input.Cursor;
|
||||||
|
@ -8,6 +9,7 @@ import funkin.play.character.CharacterData.CharacterDataParser;
|
||||||
import funkin.play.song.SongData.SongDataParser;
|
import funkin.play.song.SongData.SongDataParser;
|
||||||
import funkin.play.song.SongData.SongPlayableChar;
|
import funkin.play.song.SongData.SongPlayableChar;
|
||||||
import funkin.play.song.SongData.SongTimeChange;
|
import funkin.play.song.SongData.SongTimeChange;
|
||||||
|
import haxe.ui.core.Component;
|
||||||
import haxe.ui.components.Button;
|
import haxe.ui.components.Button;
|
||||||
import haxe.ui.components.DropDown;
|
import haxe.ui.components.DropDown;
|
||||||
import haxe.ui.components.Image;
|
import haxe.ui.components.Image;
|
||||||
|
@ -18,7 +20,6 @@ import haxe.ui.components.TextField;
|
||||||
import haxe.ui.containers.Box;
|
import haxe.ui.containers.Box;
|
||||||
import haxe.ui.containers.dialogs.Dialog;
|
import haxe.ui.containers.dialogs.Dialog;
|
||||||
import haxe.ui.containers.dialogs.Dialogs;
|
import haxe.ui.containers.dialogs.Dialogs;
|
||||||
import haxe.ui.containers.properties.Property;
|
|
||||||
import haxe.ui.containers.properties.PropertyGrid;
|
import haxe.ui.containers.properties.PropertyGrid;
|
||||||
import haxe.ui.containers.properties.PropertyGroup;
|
import haxe.ui.containers.properties.PropertyGroup;
|
||||||
import haxe.ui.containers.VBox;
|
import haxe.ui.containers.VBox;
|
||||||
|
@ -27,16 +28,19 @@ import haxe.ui.events.UIEvent;
|
||||||
|
|
||||||
using Lambda;
|
using Lambda;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles dialogs for the new Chart Editor.
|
||||||
|
*/
|
||||||
class ChartEditorDialogHandler
|
class ChartEditorDialogHandler
|
||||||
{
|
{
|
||||||
static final CHART_EDITOR_DIALOG_ABOUT_LAYOUT = Paths.ui('chart-editor/dialogs/about');
|
static final CHART_EDITOR_DIALOG_ABOUT_LAYOUT:String = Paths.ui('chart-editor/dialogs/about');
|
||||||
static final CHART_EDITOR_DIALOG_WELCOME_LAYOUT = Paths.ui('chart-editor/dialogs/welcome');
|
static final CHART_EDITOR_DIALOG_WELCOME_LAYOUT:String = 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_UPLOAD_INST_LAYOUT:String = Paths.ui('chart-editor/dialogs/upload-inst');
|
||||||
static final CHART_EDITOR_DIALOG_SONG_METADATA_LAYOUT = Paths.ui('chart-editor/dialogs/song-metadata');
|
static final CHART_EDITOR_DIALOG_SONG_METADATA_LAYOUT:String = Paths.ui('chart-editor/dialogs/song-metadata');
|
||||||
static final CHART_EDITOR_DIALOG_SONG_METADATA_CHARGROUP_LAYOUT = Paths.ui('chart-editor/dialogs/song-metadata-chargroup');
|
static final CHART_EDITOR_DIALOG_SONG_METADATA_CHARGROUP_LAYOUT:String = Paths.ui('chart-editor/dialogs/song-metadata-chargroup');
|
||||||
static final CHART_EDITOR_DIALOG_UPLOAD_VOCALS_LAYOUT = Paths.ui('chart-editor/dialogs/upload-vocals');
|
static final CHART_EDITOR_DIALOG_UPLOAD_VOCALS_LAYOUT:String = Paths.ui('chart-editor/dialogs/upload-vocals');
|
||||||
static final CHART_EDITOR_DIALOG_UPLOAD_VOCALS_ENTRY_LAYOUT = Paths.ui('chart-editor/dialogs/upload-vocals-entry');
|
static final CHART_EDITOR_DIALOG_UPLOAD_VOCALS_ENTRY_LAYOUT:String = Paths.ui('chart-editor/dialogs/upload-vocals-entry');
|
||||||
static final CHART_EDITOR_DIALOG_USER_GUIDE_LAYOUT = Paths.ui('chart-editor/dialogs/user-guide');
|
static final CHART_EDITOR_DIALOG_USER_GUIDE_LAYOUT:String = Paths.ui('chart-editor/dialogs/user-guide');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -55,55 +59,23 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
// TODO: Add callbacks to the dialog buttons
|
// TODO: Add callbacks to the dialog buttons
|
||||||
|
|
||||||
// Switch the graphic for frames.
|
|
||||||
var bfSpritePlaceholder:Image = dialog.findComponent('bfSprite', Image);
|
|
||||||
|
|
||||||
// TODO: Replace this bullshit with a custom HaxeUI component that loads the sprite from the game's assets.
|
|
||||||
|
|
||||||
if (bfSpritePlaceholder != null)
|
|
||||||
{
|
|
||||||
var bfSprite:FlxSprite = new FlxSprite(0, 0);
|
|
||||||
|
|
||||||
bfSprite.visible = false;
|
|
||||||
|
|
||||||
var frames = Paths.getSparrowAtlas(bfSpritePlaceholder.resource);
|
|
||||||
bfSprite.frames = frames;
|
|
||||||
|
|
||||||
bfSprite.animation.addByPrefix('idle', 'Boyfriend DJ0', 24, true);
|
|
||||||
bfSprite.animation.play('idle');
|
|
||||||
|
|
||||||
bfSpritePlaceholder.rootComponent.add(bfSprite);
|
|
||||||
bfSpritePlaceholder.visible = false;
|
|
||||||
|
|
||||||
new FlxTimer().start(0.10, (_timer:FlxTimer) ->
|
|
||||||
{
|
|
||||||
bfSprite.x = bfSpritePlaceholder.screenLeft;
|
|
||||||
bfSprite.y = bfSpritePlaceholder.screenTop;
|
|
||||||
bfSprite.setGraphicSize(Std.int(bfSpritePlaceholder.width), Std.int(bfSpritePlaceholder.height));
|
|
||||||
bfSprite.visible = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add handlers to the "Create From Song" section.
|
// Add handlers to the "Create From Song" section.
|
||||||
var linkCreateBasic:Link = dialog.findComponent('splashCreateFromSongBasic', Link);
|
var linkCreateBasic:Link = dialog.findComponent('splashCreateFromSongBasic', Link);
|
||||||
linkCreateBasic.onClick = (_event) ->
|
linkCreateBasic.onClick = (_event) -> {
|
||||||
{
|
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
|
|
||||||
// Create song wizard
|
// Create song wizard
|
||||||
var uploadInstDialog = openUploadInstDialog(state, false);
|
var uploadInstDialog = openUploadInstDialog(state, false);
|
||||||
uploadInstDialog.onDialogClosed = (_event) ->
|
uploadInstDialog.onDialogClosed = (_event) -> {
|
||||||
{
|
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (_event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
var songMetadataDialog = openSongMetadataDialog(state);
|
var songMetadataDialog = openSongMetadataDialog(state);
|
||||||
songMetadataDialog.onDialogClosed = (_event) ->
|
songMetadataDialog.onDialogClosed = (_event) -> {
|
||||||
{
|
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
if (_event.button == DialogButton.APPLY)
|
if (_event.button == DialogButton.APPLY)
|
||||||
{
|
{
|
||||||
var uploadVocalsDialog = openUploadVocalsDialog(state);
|
var uploadVocalsDialog = openUploadVocalsDialog(state, false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -145,8 +117,7 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var linkTemplateSong:Link = new Link();
|
var linkTemplateSong:Link = new Link();
|
||||||
linkTemplateSong.text = songName;
|
linkTemplateSong.text = songName;
|
||||||
linkTemplateSong.onClick = (_event) ->
|
linkTemplateSong.onClick = (_event) -> {
|
||||||
{
|
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
|
|
||||||
// Load song from template
|
// Load song from template
|
||||||
|
@ -165,72 +136,111 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var instrumentalBox:Box = dialog.findComponent('instrumentalBox', Box);
|
var instrumentalBox:Box = dialog.findComponent('instrumentalBox', Box);
|
||||||
|
|
||||||
instrumentalBox.onMouseOver = (_event) ->
|
instrumentalBox.onMouseOver = (_event) -> {
|
||||||
{
|
|
||||||
instrumentalBox.swapClass('upload-bg', 'upload-bg-hover');
|
instrumentalBox.swapClass('upload-bg', 'upload-bg-hover');
|
||||||
Cursor.cursorMode = Pointer;
|
Cursor.cursorMode = Pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
instrumentalBox.onMouseOut = (_event) ->
|
instrumentalBox.onMouseOut = (_event) -> {
|
||||||
{
|
|
||||||
instrumentalBox.swapClass('upload-bg-hover', 'upload-bg');
|
instrumentalBox.swapClass('upload-bg-hover', 'upload-bg');
|
||||||
Cursor.cursorMode = Default;
|
Cursor.cursorMode = Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
var onDropFile:String->Void;
|
var onDropFile:String->Void;
|
||||||
|
|
||||||
instrumentalBox.onClick = (_event) ->
|
instrumentalBox.onClick = (_event) -> {
|
||||||
{
|
|
||||||
Dialogs.openBinaryFile("Open Instrumental", [
|
Dialogs.openBinaryFile("Open Instrumental", [
|
||||||
{label: "Audio File (.ogg)", extension: "ogg"}], function(selectedFile)
|
{label: "Audio File (.ogg)", extension: "ogg"}], function(selectedFile) {
|
||||||
{
|
if (selectedFile != null)
|
||||||
if (selectedFile != null)
|
{
|
||||||
{
|
trace('Selected file: ' + selectedFile);
|
||||||
trace('Selected file: ' + selectedFile);
|
state.loadInstrumentalFromBytes(selectedFile.bytes);
|
||||||
state.loadInstrumentalFromBytes(selectedFile.bytes);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
removeDropHandler(onDropFile);
|
||||||
removeDropHandler(onDropFile);
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onDropFile = (path:String) ->
|
onDropFile = (path:String) -> {
|
||||||
{
|
|
||||||
trace('Dropped file: ' + path);
|
trace('Dropped file: ' + path);
|
||||||
state.loadInstrumentalFromPath(path);
|
state.loadInstrumentalFromPath(path);
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
removeDropHandler(onDropFile);
|
removeDropHandler(onDropFile);
|
||||||
};
|
};
|
||||||
|
|
||||||
addDropHandler(onDropFile);
|
addDropHandler(instrumentalBox, onDropFile);
|
||||||
|
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function addDropHandler(handler:String->Void)
|
static var dropHandlers:Array<
|
||||||
|
{
|
||||||
|
component:Component,
|
||||||
|
handler:(String->Void)
|
||||||
|
}> = [];
|
||||||
|
|
||||||
|
static function addDropHandler(component:Component, handler:String->Void):Void
|
||||||
{
|
{
|
||||||
#if desktop
|
#if desktop
|
||||||
FlxG.stage.window.onDropFile.add(handler);
|
if (!FlxG.stage.window.onDropFile.has(onDropFile)) FlxG.stage.window.onDropFile.add(onDropFile);
|
||||||
|
|
||||||
|
dropHandlers.push(
|
||||||
|
{
|
||||||
|
component: component,
|
||||||
|
handler: handler
|
||||||
|
});
|
||||||
#else
|
#else
|
||||||
trace('addDropHandler not implemented for this platform');
|
trace('addDropHandler not implemented for this platform');
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
static function removeDropHandler(handler:String->Void)
|
static function removeDropHandler(handler:String->Void):Void
|
||||||
{
|
{
|
||||||
#if desktop
|
#if desktop
|
||||||
FlxG.stage.window.onDropFile.remove(handler);
|
FlxG.stage.window.onDropFile.remove(handler);
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function clearDropHandlers():Void
|
||||||
|
{
|
||||||
|
#if desktop
|
||||||
|
dropHandlers = [];
|
||||||
|
FlxG.stage.window.onDropFile.remove(onDropFile);
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
static function onDropFile(path:String):Void
|
||||||
|
{
|
||||||
|
// a VERY short timer to wait for the mouse position to update
|
||||||
|
new FlxTimer().start(0.01, function(_) {
|
||||||
|
trace("mouseX: " + FlxG.mouse.screenX + ", mouseY: " + FlxG.mouse.screenY);
|
||||||
|
|
||||||
|
for (handler in dropHandlers)
|
||||||
|
{
|
||||||
|
if (handler.component.hitTest(FlxG.mouse.screenX, FlxG.mouse.screenY))
|
||||||
|
{
|
||||||
|
trace('File dropped on component! ' + handler.component.id);
|
||||||
|
handler.handler(path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trace('File dropped on nothing!' + path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the dialog in the wizard where the user can set song metadata like name and artist and BPM.
|
||||||
|
* @param state The ChartEditorState instance.
|
||||||
|
* @return The dialog to open.
|
||||||
|
*/
|
||||||
public static function openSongMetadataDialog(state:ChartEditorState):Dialog
|
public static function openSongMetadataDialog(state:ChartEditorState):Dialog
|
||||||
{
|
{
|
||||||
var dialog:Dialog = openDialog(state, CHART_EDITOR_DIALOG_SONG_METADATA_LAYOUT, true, false);
|
var dialog:Dialog = openDialog(state, CHART_EDITOR_DIALOG_SONG_METADATA_LAYOUT, true, false);
|
||||||
|
|
||||||
var dialogSongName:TextField = dialog.findComponent('dialogSongName', TextField);
|
var dialogSongName:TextField = dialog.findComponent('dialogSongName', TextField);
|
||||||
dialogSongName.onChange = (event:UIEvent) ->
|
dialogSongName.onChange = function(event:UIEvent) {
|
||||||
{
|
var valid:Bool = event.target.text != null && event.target.text != '';
|
||||||
var valid = event.target.text != null && event.target.text != "";
|
|
||||||
|
|
||||||
if (valid)
|
if (valid)
|
||||||
{
|
{
|
||||||
|
@ -245,9 +255,8 @@ class ChartEditorDialogHandler
|
||||||
state.currentSongMetadata.songName = null;
|
state.currentSongMetadata.songName = null;
|
||||||
|
|
||||||
var dialogSongArtist:TextField = dialog.findComponent('dialogSongArtist', TextField);
|
var dialogSongArtist:TextField = dialog.findComponent('dialogSongArtist', TextField);
|
||||||
dialogSongArtist.onChange = (event:UIEvent) ->
|
dialogSongArtist.onChange = function(event:UIEvent) {
|
||||||
{
|
var valid:Bool = event.target.text != null && event.target.text != '';
|
||||||
var valid = event.target.text != null && event.target.text != "";
|
|
||||||
|
|
||||||
if (valid)
|
if (valid)
|
||||||
{
|
{
|
||||||
|
@ -262,8 +271,7 @@ class ChartEditorDialogHandler
|
||||||
state.currentSongMetadata.artist = null;
|
state.currentSongMetadata.artist = null;
|
||||||
|
|
||||||
var dialogStage:DropDown = dialog.findComponent('dialogStage', DropDown);
|
var dialogStage:DropDown = dialog.findComponent('dialogStage', DropDown);
|
||||||
dialogStage.onChange = (event:UIEvent) ->
|
dialogStage.onChange = function(event:UIEvent) {
|
||||||
{
|
|
||||||
var valid = event.data != null && event.data.id != null;
|
var valid = event.data != null && event.data.id != null;
|
||||||
|
|
||||||
if (event.data.id == null) return;
|
if (event.data.id == null) return;
|
||||||
|
@ -272,16 +280,14 @@ class ChartEditorDialogHandler
|
||||||
state.currentSongMetadata.playData.stage = null;
|
state.currentSongMetadata.playData.stage = null;
|
||||||
|
|
||||||
var dialogNoteSkin:DropDown = dialog.findComponent('dialogNoteSkin', DropDown);
|
var dialogNoteSkin:DropDown = dialog.findComponent('dialogNoteSkin', DropDown);
|
||||||
dialogNoteSkin.onChange = (event:UIEvent) ->
|
dialogNoteSkin.onChange = (event:UIEvent) -> {
|
||||||
{
|
|
||||||
if (event.data.id == null) return;
|
if (event.data.id == null) return;
|
||||||
state.currentSongMetadata.playData.noteSkin = event.data.id;
|
state.currentSongMetadata.playData.noteSkin = event.data.id;
|
||||||
};
|
};
|
||||||
state.currentSongMetadata.playData.noteSkin = null;
|
state.currentSongMetadata.playData.noteSkin = null;
|
||||||
|
|
||||||
var dialogBPM:NumberStepper = dialog.findComponent('dialogBPM', NumberStepper);
|
var dialogBPM:NumberStepper = dialog.findComponent('dialogBPM', NumberStepper);
|
||||||
dialogBPM.onChange = (event:UIEvent) ->
|
dialogBPM.onChange = (event:UIEvent) -> {
|
||||||
{
|
|
||||||
if (event.value == null || event.value <= 0) return;
|
if (event.value == null || event.value <= 0) return;
|
||||||
|
|
||||||
var timeChanges = state.currentSongMetadata.timeChanges;
|
var timeChanges = state.currentSongMetadata.timeChanges;
|
||||||
|
@ -301,11 +307,9 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var dialogCharGrid:PropertyGrid = dialog.findComponent('dialogCharGrid', PropertyGrid);
|
var dialogCharGrid:PropertyGrid = dialog.findComponent('dialogCharGrid', PropertyGrid);
|
||||||
var dialogCharAdd:Button = dialog.findComponent('dialogCharAdd', Button);
|
var dialogCharAdd:Button = dialog.findComponent('dialogCharAdd', Button);
|
||||||
dialogCharAdd.onClick = (_event) ->
|
dialogCharAdd.onClick = (_event) -> {
|
||||||
{
|
|
||||||
var charGroup:PropertyGroup;
|
var charGroup:PropertyGroup;
|
||||||
charGroup = buildCharGroup(state, null, () ->
|
charGroup = buildCharGroup(state, null, () -> {
|
||||||
{
|
|
||||||
dialogCharGrid.removeComponent(charGroup);
|
dialogCharGrid.removeComponent(charGroup);
|
||||||
});
|
});
|
||||||
dialogCharGrid.addComponent(charGroup);
|
dialogCharGrid.addComponent(charGroup);
|
||||||
|
@ -317,8 +321,7 @@ class ChartEditorDialogHandler
|
||||||
dialogCharGrid.addComponent(buildCharGroup(state, 'bf', null));
|
dialogCharGrid.addComponent(buildCharGroup(state, 'bf', null));
|
||||||
|
|
||||||
var dialogContinue:Button = dialog.findComponent('dialogContinue', Button);
|
var dialogContinue:Button = dialog.findComponent('dialogContinue', Button);
|
||||||
dialogContinue.onClick = (_event) ->
|
dialogContinue.onClick = (_event) -> {
|
||||||
{
|
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -329,8 +332,7 @@ class ChartEditorDialogHandler
|
||||||
{
|
{
|
||||||
var groupKey = key;
|
var groupKey = key;
|
||||||
|
|
||||||
var getCharData = () ->
|
var getCharData = () -> {
|
||||||
{
|
|
||||||
if (groupKey == null) groupKey = 'newChar${state.currentSongMetadata.playData.playableChars.keys().count()}';
|
if (groupKey == null) groupKey = 'newChar${state.currentSongMetadata.playData.playableChars.keys().count()}';
|
||||||
|
|
||||||
var result = state.currentSongMetadata.playData.playableChars.get(groupKey);
|
var result = state.currentSongMetadata.playData.playableChars.get(groupKey);
|
||||||
|
@ -342,16 +344,14 @@ class ChartEditorDialogHandler
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
var moveCharGroup = (target:String) ->
|
var moveCharGroup = (target:String) -> {
|
||||||
{
|
|
||||||
var charData = getCharData();
|
var charData = getCharData();
|
||||||
state.currentSongMetadata.playData.playableChars.remove(groupKey);
|
state.currentSongMetadata.playData.playableChars.remove(groupKey);
|
||||||
state.currentSongMetadata.playData.playableChars.set(target, charData);
|
state.currentSongMetadata.playData.playableChars.set(target, charData);
|
||||||
groupKey = target;
|
groupKey = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
var removeGroup = () ->
|
var removeGroup = () -> {
|
||||||
{
|
|
||||||
state.currentSongMetadata.playData.playableChars.remove(groupKey);
|
state.currentSongMetadata.playData.playableChars.remove(groupKey);
|
||||||
removeFunc();
|
removeFunc();
|
||||||
}
|
}
|
||||||
|
@ -361,8 +361,7 @@ class ChartEditorDialogHandler
|
||||||
var charGroup:PropertyGroup = cast state.buildComponent(CHART_EDITOR_DIALOG_SONG_METADATA_CHARGROUP_LAYOUT);
|
var charGroup:PropertyGroup = cast state.buildComponent(CHART_EDITOR_DIALOG_SONG_METADATA_CHARGROUP_LAYOUT);
|
||||||
|
|
||||||
var charGroupPlayer:DropDown = charGroup.findComponent('charGroupPlayer', DropDown);
|
var charGroupPlayer:DropDown = charGroup.findComponent('charGroupPlayer', DropDown);
|
||||||
charGroupPlayer.onChange = (event:UIEvent) ->
|
charGroupPlayer.onChange = (event:UIEvent) -> {
|
||||||
{
|
|
||||||
charGroup.text = event.data.text;
|
charGroup.text = event.data.text;
|
||||||
moveCharGroup(event.data.id);
|
moveCharGroup(event.data.id);
|
||||||
};
|
};
|
||||||
|
@ -374,22 +373,19 @@ class ChartEditorDialogHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
var charGroupOpponent:DropDown = charGroup.findComponent('charGroupOpponent', DropDown);
|
var charGroupOpponent:DropDown = charGroup.findComponent('charGroupOpponent', DropDown);
|
||||||
charGroupOpponent.onChange = (event:UIEvent) ->
|
charGroupOpponent.onChange = (event:UIEvent) -> {
|
||||||
{
|
|
||||||
charData.opponent = event.data.id;
|
charData.opponent = event.data.id;
|
||||||
};
|
};
|
||||||
charGroupOpponent.value = getCharData().opponent;
|
charGroupOpponent.value = getCharData().opponent;
|
||||||
|
|
||||||
var charGroupGirlfriend:DropDown = charGroup.findComponent('charGroupGirlfriend', DropDown);
|
var charGroupGirlfriend:DropDown = charGroup.findComponent('charGroupGirlfriend', DropDown);
|
||||||
charGroupGirlfriend.onChange = (event:UIEvent) ->
|
charGroupGirlfriend.onChange = (event:UIEvent) -> {
|
||||||
{
|
|
||||||
charData.girlfriend = event.data.id;
|
charData.girlfriend = event.data.id;
|
||||||
};
|
};
|
||||||
charGroupGirlfriend.value = getCharData().girlfriend;
|
charGroupGirlfriend.value = getCharData().girlfriend;
|
||||||
|
|
||||||
var charGroupRemove:Button = charGroup.findComponent('charGroupRemove', Button);
|
var charGroupRemove:Button = charGroup.findComponent('charGroupRemove', Button);
|
||||||
charGroupRemove.onClick = (_event:MouseEvent) ->
|
charGroupRemove.onClick = (_event:MouseEvent) -> {
|
||||||
{
|
|
||||||
removeGroup();
|
removeGroup();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -413,7 +409,11 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
var dialogContainer = dialog.findComponent('vocalContainer');
|
var dialogContainer = dialog.findComponent('vocalContainer');
|
||||||
|
|
||||||
var onDropFile:String->Void;
|
var dialogNoVocals:Button = dialog.findComponent('dialogNoVocals', Button);
|
||||||
|
dialogNoVocals.onClick = function(_event) {
|
||||||
|
// Dismiss
|
||||||
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
|
};
|
||||||
|
|
||||||
for (charKey in charIdsForVocals)
|
for (charKey in charIdsForVocals)
|
||||||
{
|
{
|
||||||
|
@ -426,39 +426,46 @@ class ChartEditorDialogHandler
|
||||||
var vocalsEntryLabel:Label = vocalsEntry.findComponent('vocalsEntryLabel', Label);
|
var vocalsEntryLabel:Label = vocalsEntry.findComponent('vocalsEntryLabel', Label);
|
||||||
vocalsEntryLabel.text = 'Click to browse for a vocal track for $charName.';
|
vocalsEntryLabel.text = 'Click to browse for a vocal track for $charName.';
|
||||||
|
|
||||||
vocalsEntry.onClick = (_event) ->
|
var onDropFile:String->Void = function(fullPath:String) {
|
||||||
{
|
trace('Selected file: $fullPath');
|
||||||
|
var directory:String = Path.directory(fullPath);
|
||||||
|
var filename:String = Path.withoutDirectory(directory);
|
||||||
|
|
||||||
|
vocalsEntryLabel.text = 'Vocals for $charName (click to browse)\n${filename}';
|
||||||
|
state.loadVocalsFromPath(fullPath, charKey);
|
||||||
|
dialogNoVocals.hidden = true;
|
||||||
|
removeDropHandler(onDropFile);
|
||||||
|
};
|
||||||
|
|
||||||
|
vocalsEntry.onClick = function(_event) {
|
||||||
Dialogs.openBinaryFile('Open $charName Vocals', [
|
Dialogs.openBinaryFile('Open $charName Vocals', [
|
||||||
{label: "Audio File (.ogg)", extension: "ogg"}], function(selectedFile)
|
{label: 'Audio File (.ogg)', extension: 'ogg'}], function(selectedFile) {
|
||||||
{
|
if (selectedFile != null)
|
||||||
if (selectedFile != null)
|
{
|
||||||
{
|
trace('Selected file: ' + selectedFile.name);
|
||||||
trace('Selected file: ' + selectedFile.name + "~" + selectedFile.fullPath);
|
vocalsEntryLabel.text = 'Vocals for $charName (click to browse)\n${selectedFile.name}';
|
||||||
vocalsEntryLabel.text = 'Vocals for $charName (click to browse)\n${selectedFile.name}';
|
state.loadVocalsFromBytes(selectedFile.bytes, charKey);
|
||||||
state.loadVocalsFromBytes(selectedFile.bytes);
|
dialogNoVocals.hidden = true;
|
||||||
removeDropHandler(onDropFile);
|
removeDropHandler(onDropFile);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// onDropFile
|
||||||
|
addDropHandler(vocalsEntry, onDropFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
dialogContainer.addComponent(vocalsEntry);
|
dialogContainer.addComponent(vocalsEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dialogContinue:Button = dialog.findComponent('dialogContinue', Button);
|
var dialogContinue:Button = dialog.findComponent('dialogContinue', Button);
|
||||||
dialogContinue.onClick = (_event) ->
|
dialogContinue.onClick = function(_event) {
|
||||||
{
|
// Dismiss
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Redo the logic for file drop handler to be more robust.
|
// TODO: Redo the logic for file drop handler to be more robust.
|
||||||
// We need to distinguish which component the mouse is over when the file is dropped.
|
// We need to distinguish which component the mouse is over when the file is dropped.
|
||||||
|
|
||||||
onDropFile = (path:String) ->
|
|
||||||
{
|
|
||||||
trace('Dropped file: ' + path);
|
|
||||||
};
|
|
||||||
addDropHandler(onDropFile);
|
|
||||||
|
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,8 +490,7 @@ class ChartEditorDialogHandler
|
||||||
dialog.showDialog(modal);
|
dialog.showDialog(modal);
|
||||||
|
|
||||||
state.isHaxeUIDialogOpen = true;
|
state.isHaxeUIDialogOpen = true;
|
||||||
dialog.onDialogClosed = (_event) ->
|
dialog.onDialogClosed = (_event) -> {
|
||||||
{
|
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package funkin.ui.debug.charting;
|
package funkin.ui.debug.charting;
|
||||||
|
|
||||||
import flixel.FlxObject;
|
import flixel.FlxObject;
|
||||||
import flixel.FlxBasic;
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.graphics.frames.FlxFramesCollection;
|
import flixel.graphics.frames.FlxFramesCollection;
|
||||||
import flixel.graphics.frames.FlxTileFrames;
|
import flixel.graphics.frames.FlxTileFrames;
|
||||||
|
@ -14,6 +13,14 @@ import funkin.play.song.SongData.SongNoteData;
|
||||||
*/
|
*/
|
||||||
class ChartEditorNoteSprite extends FlxSprite
|
class ChartEditorNoteSprite extends FlxSprite
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The list of available note skin to validate against.
|
||||||
|
*/
|
||||||
|
public static final NOTE_STYLES:Array<String> = ['Normal', 'Pixel'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ChartEditorState this note belongs to.
|
||||||
|
*/
|
||||||
public var parentState:ChartEditorState;
|
public var parentState:ChartEditorState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,6 +29,11 @@ class ChartEditorNoteSprite extends FlxSprite
|
||||||
*/
|
*/
|
||||||
public var noteData(default, set):SongNoteData;
|
public var noteData(default, set):SongNoteData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the note style currently in use.
|
||||||
|
*/
|
||||||
|
public var noteStyle(get, null):String;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This note is the previous sprite in a sustain chain.
|
* This note is the previous sprite in a sustain chain.
|
||||||
*/
|
*/
|
||||||
|
@ -222,14 +234,20 @@ class ChartEditorNoteSprite extends FlxSprite
|
||||||
return this.childNoteSprite;
|
return this.childNoteSprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function playNoteAnimation()
|
function get_noteStyle():String
|
||||||
|
{
|
||||||
|
// Fall back to 'Normal' if it's not a valid note style.
|
||||||
|
return if (NOTE_STYLES.contains(this.parentState.currentSongNoteSkin)) this.parentState.currentSongNoteSkin else 'Normal';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function playNoteAnimation():Void
|
||||||
{
|
{
|
||||||
// Decide whether to display a note or a sustain.
|
// Decide whether to display a note or a sustain.
|
||||||
var baseAnimationName:String = 'tap';
|
var baseAnimationName:String = 'tap';
|
||||||
if (this.parentNoteSprite != null) baseAnimationName = (this.childNoteSprite != null) ? 'hold' : 'holdEnd';
|
if (this.parentNoteSprite != null) baseAnimationName = (this.childNoteSprite != null) ? 'hold' : 'holdEnd';
|
||||||
|
|
||||||
// Play the appropriate animation for the type, direction, and skin.
|
// Play the appropriate animation for the type, direction, and skin.
|
||||||
var animationName = '${baseAnimationName}${this.noteData.getDirectionName()}${this.parentState.currentSongNoteSkin}';
|
var animationName:String = '${baseAnimationName}${this.noteData.getDirectionName()}${this.noteStyle}';
|
||||||
|
|
||||||
this.animation.play(animationName);
|
this.animation.play(animationName);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package funkin.ui.debug.charting;
|
package funkin.ui.debug.charting;
|
||||||
|
|
||||||
|
import haxe.ui.notifications.NotificationType;
|
||||||
|
import haxe.ui.notifications.NotificationManager;
|
||||||
import haxe.DynamicAccess;
|
import haxe.DynamicAccess;
|
||||||
import haxe.io.Path;
|
import haxe.io.Path;
|
||||||
import flixel.addons.display.FlxSliceSprite;
|
import flixel.addons.display.FlxSliceSprite;
|
||||||
|
@ -92,6 +94,9 @@ class ChartEditorState extends HaxeUIState
|
||||||
static final CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT = Paths.ui('chart-editor/toolbox/player-preview');
|
static final CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT = Paths.ui('chart-editor/toolbox/player-preview');
|
||||||
static final CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT = Paths.ui('chart-editor/toolbox/opponent-preview');
|
static final CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT = Paths.ui('chart-editor/toolbox/opponent-preview');
|
||||||
|
|
||||||
|
// Validation
|
||||||
|
static final SUPPORTED_MUSIC_FORMATS:Array<String> = ['ogg'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base grid size for the chart editor.
|
* The base grid size for the chart editor.
|
||||||
*/
|
*/
|
||||||
|
@ -124,9 +129,9 @@ class ChartEditorState extends HaxeUIState
|
||||||
static final GRID_TOP_PAD:Int = 8;
|
static final GRID_TOP_PAD:Int = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Duration, in seconds, until toast notifications are automatically hidden.
|
* Duration, in milliseconds, until toast notifications are automatically hidden.
|
||||||
*/
|
*/
|
||||||
static final NOTIFICATION_DISMISS_TIME:Float = 3.0;
|
static final NOTIFICATION_DISMISS_TIME:Int = 5000;
|
||||||
|
|
||||||
// Start performing rapid undo after this many seconds.
|
// Start performing rapid undo after this many seconds.
|
||||||
static final RAPID_UNDO_DELAY:Float = 0.4;
|
static final RAPID_UNDO_DELAY:Float = 0.4;
|
||||||
|
@ -898,7 +903,6 @@ class ChartEditorState extends HaxeUIState
|
||||||
|
|
||||||
var renderedSelectionSquares:FlxTypedSpriteGroup<FlxSprite>;
|
var renderedSelectionSquares:FlxTypedSpriteGroup<FlxSprite>;
|
||||||
|
|
||||||
var notifBar:SideBar;
|
|
||||||
var playbarHead:Slider;
|
var playbarHead:Slider;
|
||||||
|
|
||||||
public function new()
|
public function new()
|
||||||
|
@ -1090,9 +1094,6 @@ class ChartEditorState extends HaxeUIState
|
||||||
|
|
||||||
function buildAdditionalUI():Void
|
function buildAdditionalUI():Void
|
||||||
{
|
{
|
||||||
notifBar = cast buildComponent(CHART_EDITOR_NOTIFBAR_LAYOUT);
|
|
||||||
add(notifBar);
|
|
||||||
|
|
||||||
playbarHeadLayout = buildComponent(CHART_EDITOR_PLAYBARHEAD_LAYOUT);
|
playbarHeadLayout = buildComponent(CHART_EDITOR_PLAYBARHEAD_LAYOUT);
|
||||||
|
|
||||||
playbarHeadLayout.width = FlxG.width - 8;
|
playbarHeadLayout.width = FlxG.width - 8;
|
||||||
|
@ -1281,7 +1282,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
if (audioInstTrack != null) audioInstTrack.pitch = pitch;
|
if (audioInstTrack != null) audioInstTrack.pitch = pitch;
|
||||||
if (audioVocalTrackGroup != null) audioVocalTrackGroup.pitch = pitch;
|
if (audioVocalTrackGroup != null) audioVocalTrackGroup.pitch = pitch;
|
||||||
#end
|
#end
|
||||||
playbackSpeedLabel.text = 'Playback Speed - ${Std.int(event.value * 100) / 100}x';
|
playbackSpeedLabel.text = 'Playback Speed - ${Std.int(pitch * 100) / 100}x';
|
||||||
});
|
});
|
||||||
|
|
||||||
addUIChangeListener('menubarItemToggleToolboxTools', (event:UIEvent) -> {
|
addUIChangeListener('menubarItemToggleToolboxTools', (event:UIEvent) -> {
|
||||||
|
@ -1340,7 +1341,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
function onWindowClose(exitCode:Int)
|
function onWindowClose(exitCode:Int):Void
|
||||||
{
|
{
|
||||||
trace('Window exited with exit code: $exitCode');
|
trace('Window exited with exit code: $exitCode');
|
||||||
trace('Should save chart? $saveDataDirty');
|
trace('Should save chart? $saveDataDirty');
|
||||||
|
@ -1351,12 +1352,12 @@ class ChartEditorState extends HaxeUIState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanupAutoSave()
|
function cleanupAutoSave():Void
|
||||||
{
|
{
|
||||||
WindowUtil.windowExit.remove(onWindowClose);
|
WindowUtil.windowExit.remove(onWindowClose);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override function update(elapsed:Float)
|
public override function update(elapsed:Float):Void
|
||||||
{
|
{
|
||||||
// dispatchEvent gets called here.
|
// dispatchEvent gets called here.
|
||||||
super.update(elapsed);
|
super.update(elapsed);
|
||||||
|
@ -1387,10 +1388,16 @@ class ChartEditorState extends HaxeUIState
|
||||||
#if debug
|
#if debug
|
||||||
if (FlxG.keys.justPressed.F)
|
if (FlxG.keys.justPressed.F)
|
||||||
{
|
{
|
||||||
// This breaks the layout don't use it.
|
NotificationManager.instance.addNotification(
|
||||||
// showNotification('Hi there :)');
|
{
|
||||||
|
title: 'This is a Notification',
|
||||||
// autoSave();
|
body: 'Hello, world!',
|
||||||
|
type: NotificationType.Info,
|
||||||
|
expiryMs: NOTIFICATION_DISMISS_TIME
|
||||||
|
// styleNames: 'cssStyleName',
|
||||||
|
// icon: 'assetPath',
|
||||||
|
// actions: ['action1', 'action2']
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FlxG.keys.justPressed.E)
|
if (FlxG.keys.justPressed.E)
|
||||||
|
@ -1416,7 +1423,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
// dispatchEvent gets called here.
|
// dispatchEvent gets called here.
|
||||||
if (!super.beatHit()) return false;
|
if (!super.beatHit()) return false;
|
||||||
|
|
||||||
if (shouldPlayMetronome && audioInstTrack.playing)
|
if (shouldPlayMetronome && (audioInstTrack != null && audioInstTrack.playing))
|
||||||
{
|
{
|
||||||
playMetronomeTick(Conductor.currentBeat % 4 == 0);
|
playMetronomeTick(Conductor.currentBeat % 4 == 0);
|
||||||
}
|
}
|
||||||
|
@ -1432,7 +1439,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
// dispatchEvent gets called here.
|
// dispatchEvent gets called here.
|
||||||
if (!super.stepHit()) return false;
|
if (!super.stepHit()) return false;
|
||||||
|
|
||||||
if (audioInstTrack.playing)
|
if (audioInstTrack != null && audioInstTrack.playing)
|
||||||
{
|
{
|
||||||
healthIconDad.onStepHit(Conductor.currentStep);
|
healthIconDad.onStepHit(Conductor.currentStep);
|
||||||
healthIconBF.onStepHit(Conductor.currentStep);
|
healthIconBF.onStepHit(Conductor.currentStep);
|
||||||
|
@ -1447,7 +1454,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
/**
|
/**
|
||||||
* Handle keybinds for scrolling the chart editor grid.
|
* Handle keybinds for scrolling the chart editor grid.
|
||||||
**/
|
**/
|
||||||
function handleScrollKeybinds()
|
function handleScrollKeybinds():Void
|
||||||
{
|
{
|
||||||
// Don't scroll when the cursor is over the UI.
|
// Don't scroll when the cursor is over the UI.
|
||||||
if (isCursorOverHaxeUI) return;
|
if (isCursorOverHaxeUI) return;
|
||||||
|
@ -1456,16 +1463,17 @@ class ChartEditorState extends HaxeUIState
|
||||||
var scrollAmount:Float = 0;
|
var scrollAmount:Float = 0;
|
||||||
// Amount to scroll the playhead relative to the grid.
|
// Amount to scroll the playhead relative to the grid.
|
||||||
var playheadAmount:Float = 0;
|
var playheadAmount:Float = 0;
|
||||||
|
var shouldPause:Bool = false;
|
||||||
|
|
||||||
// Up Arrow = Scroll Up
|
// Up Arrow = Scroll Up
|
||||||
if (FlxG.keys.justPressed.UP)
|
if (FlxG.keys.justPressed.UP)
|
||||||
{
|
{
|
||||||
scrollAmount = -GRID_SIZE * 0.25;
|
scrollAmount = -GRID_SIZE * 0.25 * 5;
|
||||||
}
|
}
|
||||||
// Down Arrow = Scroll Down
|
// Down Arrow = Scroll Down
|
||||||
if (FlxG.keys.justPressed.DOWN)
|
if (FlxG.keys.justPressed.DOWN)
|
||||||
{
|
{
|
||||||
scrollAmount = GRID_SIZE * 0.25;
|
scrollAmount = GRID_SIZE * 0.25 * 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PAGE UP = Jump Up 1 Measure
|
// PAGE UP = Jump Up 1 Measure
|
||||||
|
@ -2089,7 +2097,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
/**
|
/**
|
||||||
* Handle using `renderedNotes` to display notes from `currentSongChartNoteData`.
|
* Handle using `renderedNotes` to display notes from `currentSongChartNoteData`.
|
||||||
*/
|
*/
|
||||||
function handleNoteDisplay()
|
function handleNoteDisplay():Void
|
||||||
{
|
{
|
||||||
if (noteDisplayDirty)
|
if (noteDisplayDirty)
|
||||||
{
|
{
|
||||||
|
@ -2963,10 +2971,20 @@ class ChartEditorState extends HaxeUIState
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads an instrumental from an absolute file path, replacing the current instrumental.
|
* Loads an instrumental from an absolute file path, replacing the current instrumental.
|
||||||
|
*
|
||||||
|
* @param path The absolute path to the audio file.
|
||||||
*/
|
*/
|
||||||
public function loadInstrumentalFromPath(path:String):Void
|
public function loadInstrumentalFromPath(path:String):Void
|
||||||
{
|
{
|
||||||
#if sys
|
#if sys
|
||||||
|
// Validate file extension.
|
||||||
|
var fileExtension:String = Path.extension(path);
|
||||||
|
if (!SUPPORTED_MUSIC_FORMATS.contains(fileExtension))
|
||||||
|
{
|
||||||
|
trace('[WARN] Unsupported file extension: $fileExtension');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var fileBytes:haxe.io.Bytes = sys.io.File.getBytes(path);
|
var fileBytes:haxe.io.Bytes = sys.io.File.getBytes(path);
|
||||||
loadInstrumentalFromBytes(fileBytes);
|
loadInstrumentalFromBytes(fileBytes);
|
||||||
#else
|
#else
|
||||||
|
@ -3025,17 +3043,17 @@ class ChartEditorState extends HaxeUIState
|
||||||
/**
|
/**
|
||||||
* Loads a vocal track from an absolute file path.
|
* Loads a vocal track from an absolute file path.
|
||||||
*/
|
*/
|
||||||
public function loadVocalsFromPath(path:String):Void
|
public function loadVocalsFromPath(path:String, ?charKey:String):Void
|
||||||
{
|
{
|
||||||
#if sys
|
#if sys
|
||||||
var fileBytes:haxe.io.Bytes = sys.io.File.getBytes(path);
|
var fileBytes:haxe.io.Bytes = sys.io.File.getBytes(path);
|
||||||
loadVocalsFromBytes(fileBytes);
|
loadVocalsFromBytes(fileBytes, charKey);
|
||||||
#else
|
#else
|
||||||
trace("[WARN] This platform can't load audio from a file path, you'll need to fetch the bytes some other way.");
|
trace("[WARN] This platform can't load audio from a file path, you'll need to fetch the bytes some other way.");
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadVocalsFromAsset(path:String):Void
|
public function loadVocalsFromAsset(path:String, ?charKey:String):Void
|
||||||
{
|
{
|
||||||
var vocalTrack:FlxSound = FlxG.sound.load(path, 1.0, false);
|
var vocalTrack:FlxSound = FlxG.sound.load(path, 1.0, false);
|
||||||
audioVocalTrackGroup.add(vocalTrack);
|
audioVocalTrackGroup.add(vocalTrack);
|
||||||
|
@ -3044,7 +3062,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
/**
|
/**
|
||||||
* Loads a vocal track from audio byte data.
|
* Loads a vocal track from audio byte data.
|
||||||
*/
|
*/
|
||||||
public function loadVocalsFromBytes(bytes:haxe.io.Bytes):Void
|
public function loadVocalsFromBytes(bytes:haxe.io.Bytes, ?charKey:String):Void
|
||||||
{
|
{
|
||||||
var openflSound = new openfl.media.Sound();
|
var openflSound = new openfl.media.Sound();
|
||||||
openflSound.loadCompressedDataFromByteArray(openfl.utils.ByteArray.fromBytes(bytes), bytes.length);
|
openflSound.loadCompressedDataFromByteArray(openfl.utils.ByteArray.fromBytes(bytes), bytes.length);
|
||||||
|
@ -3065,7 +3083,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
|
|
||||||
if (song == null)
|
if (song == null)
|
||||||
{
|
{
|
||||||
// showNotification('Failed to load song template.');
|
// showNotification('Failed to load song.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3218,24 +3236,12 @@ class ChartEditorState extends HaxeUIState
|
||||||
ChartEditorNoteSprite.noteFrameCollection = null;
|
ChartEditorNoteSprite.noteFrameCollection = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays a notification to the user. The only action is to dismiss.
|
|
||||||
*/
|
|
||||||
function showNotification(text:String)
|
|
||||||
{
|
|
||||||
// Make it appear.
|
|
||||||
notifBar.show();
|
|
||||||
|
|
||||||
// Auto dismiss.
|
|
||||||
new FlxTimer().start(NOTIFICATION_DISMISS_TIME, (_:FlxTimer) -> dismissNotification());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dismiss any existing notifications, if there are any.
|
* Dismiss any existing notifications, if there are any.
|
||||||
*/
|
*/
|
||||||
function dismissNotification():Void
|
function dismissNotifications():Void
|
||||||
{
|
{
|
||||||
notifBar.hide();
|
NotificationManager.instance.clearNotifications();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,14 +7,13 @@
|
||||||
This needs to be done HERE and not via the `include` macro because `Toolkit.init()`
|
This needs to be done HERE and not via the `include` macro because `Toolkit.init()`
|
||||||
reads this to build the component registry.
|
reads this to build the component registry.
|
||||||
-->
|
-->
|
||||||
<class package="haxe.ui.core" loadAll="true" />
|
<class package="haxe.ui.backend.flixel.components" loadAll="true" />
|
||||||
|
|
||||||
<class package="haxe.ui.components" loadAll="true" />
|
<class package="haxe.ui.components" loadAll="true" />
|
||||||
|
|
||||||
<class package="haxe.ui.containers" loadAll="true" />
|
|
||||||
<class package="haxe.ui.containers.menus" loadAll="true" />
|
|
||||||
<class package="haxe.ui.containers.dialogs" loadAll="true" />
|
<class package="haxe.ui.containers.dialogs" loadAll="true" />
|
||||||
|
<class package="haxe.ui.containers.menus" loadAll="true" />
|
||||||
<class package="haxe.ui.containers.properties" loadAll="true" />
|
<class package="haxe.ui.containers.properties" loadAll="true" />
|
||||||
|
<class package="haxe.ui.containers" loadAll="true" />
|
||||||
|
<class package="haxe.ui.core" loadAll="true" />
|
||||||
|
|
||||||
<!-- Custom components. -->
|
<!-- Custom components. -->
|
||||||
<class package="funkin.ui.haxeui.components" loadAll="true" />
|
<class package="funkin.ui.haxeui.components" loadAll="true" />
|
||||||
|
|
Loading…
Reference in a new issue