mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-14 11:15:24 -05:00
Convert chart editor to macro-based UIState
This commit is contained in:
parent
bab7d6cf53
commit
47f39b072a
12 changed files with 396 additions and 379 deletions
|
@ -162,10 +162,13 @@
|
|||
<icon path="art/iconOG.png" />
|
||||
<haxedef name="CAN_OPEN_LINKS" unless="switch" />
|
||||
<haxedef name="CAN_CHEAT" if="switch debug" />
|
||||
<!-- I don't -->
|
||||
<!-- I don't remember what this is for. -->
|
||||
<haxedef name="haxeui_no_mouse_reset" />
|
||||
<!-- Clicking outside a dialog should deselect the current focused component. -->
|
||||
<haxedef name="haxeui_focus_out_on_click" />
|
||||
<!-- Required to use haxe.ui.backend.flixel.UIState with build macros. -->
|
||||
<haxedef name="haxeui_dont_impose_base_class" />
|
||||
|
||||
<!-- Skip the Intro -->
|
||||
<section if="debug">
|
||||
<!-- Starts the game at the specified week, at the first song -->
|
||||
|
|
2
assets
2
assets
|
@ -1 +1 @@
|
|||
Subproject commit 4ed2b3084d54899e10d10a97eaafe210158768be
|
||||
Subproject commit 74847831dec229fc1c639ca4ca963973022b8648
|
|
@ -32,6 +32,10 @@ Example:
|
|||
public function checkSyncError(?targetTime:Float):Float
|
||||
```
|
||||
|
||||
## Commenting Unused Code
|
||||
|
||||
Do not comment out sections of code that are unused. Keep these snippets elsewhere or remove them. Older chunks of code can be retrieved by referring to the older Git commits, and having large chunks of commented code makes files longer and more confusing to navigate.
|
||||
|
||||
## License Headers
|
||||
|
||||
Do not include headers specifying code license on individual files in the repo, since the main `LICENSE.md` file covers all of them.
|
||||
|
|
|
@ -233,6 +233,7 @@ class PauseSubState extends MusicBeatSubState
|
|||
|
||||
if (PlayStatePlaylist.isStoryMode)
|
||||
{
|
||||
PlayStatePlaylist.reset();
|
||||
openSubState(new funkin.ui.transition.StickerSubState(null, STORY));
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1354,8 +1354,7 @@ class PlayState extends MusicBeatSubState
|
|||
else
|
||||
{
|
||||
// lolol
|
||||
lime.app.Application.current.window.alert('Nice job, you ignoramus. $id isn\'t a real stage.\nI\'m falling back to the default so the game doesn\'t shit itself.',
|
||||
'Stage Error');
|
||||
lime.app.Application.current.window.alert('Unable to load stage ${id}, is its data corrupted?.', 'Stage Error');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package funkin.ui.debug.charting;
|
||||
|
||||
import haxe.ui.containers.menus.MenuBar;
|
||||
import flixel.addons.display.FlxSliceSprite;
|
||||
import flixel.addons.display.FlxTiledSprite;
|
||||
import flixel.addons.transition.FlxTransitionableState;
|
||||
|
@ -18,17 +17,18 @@ import flixel.tweens.FlxEase;
|
|||
import flixel.tweens.FlxTween;
|
||||
import flixel.tweens.misc.VarTween;
|
||||
import flixel.util.FlxColor;
|
||||
import funkin.ui.mainmenu.MainMenuState;
|
||||
import flixel.util.FlxSort;
|
||||
import flixel.util.FlxTimer;
|
||||
import funkin.audio.visualize.PolygonSpectogram;
|
||||
import funkin.audio.VoicesGroup;
|
||||
import funkin.data.notestyle.NoteStyleRegistry;
|
||||
import funkin.data.song.SongData.SongCharacterData;
|
||||
import funkin.data.song.SongData.SongChartData;
|
||||
import funkin.data.song.SongData.SongEventData;
|
||||
import funkin.data.song.SongData.SongMetadata;
|
||||
import funkin.data.song.SongData.SongNoteData;
|
||||
import funkin.data.song.SongDataUtils;
|
||||
import funkin.data.song.SongRegistry;
|
||||
import funkin.input.Cursor;
|
||||
import funkin.input.TurboKeyHandler;
|
||||
import funkin.modding.events.ScriptEvent;
|
||||
|
@ -39,20 +39,12 @@ import funkin.play.components.HealthIcon;
|
|||
import funkin.play.notes.NoteSprite;
|
||||
import funkin.play.PlayState;
|
||||
import funkin.play.song.Song;
|
||||
import funkin.data.song.SongData.SongChartData;
|
||||
import funkin.data.song.SongRegistry;
|
||||
import funkin.data.song.SongData.SongEventData;
|
||||
import funkin.data.song.SongData.SongMetadata;
|
||||
import funkin.data.song.SongData.SongNoteData;
|
||||
import funkin.data.song.SongData.SongCharacterData;
|
||||
import funkin.data.song.SongDataUtils;
|
||||
import funkin.ui.debug.charting.commands.ChartEditorCommand;
|
||||
import funkin.ui.debug.charting.handlers.ChartEditorShortcutHandler;
|
||||
import funkin.play.stage.StageData;
|
||||
import funkin.save.Save;
|
||||
import funkin.ui.debug.charting.commands.AddEventsCommand;
|
||||
import funkin.ui.debug.charting.commands.AddNotesCommand;
|
||||
import funkin.ui.debug.charting.commands.ChartEditorCommand;
|
||||
import funkin.ui.debug.charting.commands.ChartEditorCommand;
|
||||
import funkin.ui.debug.charting.commands.CutItemsCommand;
|
||||
import funkin.ui.debug.charting.commands.DeselectAllItemsCommand;
|
||||
import funkin.ui.debug.charting.commands.DeselectItemsCommand;
|
||||
|
@ -73,15 +65,21 @@ import funkin.ui.debug.charting.components.ChartEditorEventSprite;
|
|||
import funkin.ui.debug.charting.components.ChartEditorHoldNoteSprite;
|
||||
import funkin.ui.debug.charting.components.ChartEditorNotePreview;
|
||||
import funkin.ui.debug.charting.components.ChartEditorNoteSprite;
|
||||
import funkin.ui.debug.charting.components.ChartEditorPlaybarHead;
|
||||
import funkin.ui.debug.charting.components.ChartEditorSelectionSquareSprite;
|
||||
import funkin.ui.debug.charting.handlers.ChartEditorShortcutHandler;
|
||||
import funkin.ui.haxeui.components.CharacterPlayer;
|
||||
import funkin.ui.haxeui.HaxeUIState;
|
||||
import funkin.ui.mainmenu.MainMenuState;
|
||||
import funkin.util.Constants;
|
||||
import funkin.util.FileUtil;
|
||||
import funkin.util.SortUtil;
|
||||
import funkin.util.WindowUtil;
|
||||
import haxe.DynamicAccess;
|
||||
import haxe.io.Bytes;
|
||||
import haxe.io.Path;
|
||||
import haxe.ui.backend.flixel.UIRuntimeState;
|
||||
import haxe.ui.backend.flixel.UIState;
|
||||
import haxe.ui.components.DropDown;
|
||||
import haxe.ui.components.Label;
|
||||
import haxe.ui.components.NumberStepper;
|
||||
|
@ -90,18 +88,20 @@ import haxe.ui.components.TextField;
|
|||
import haxe.ui.containers.dialogs.CollapsibleDialog;
|
||||
import haxe.ui.containers.Frame;
|
||||
import haxe.ui.containers.menus.Menu;
|
||||
import haxe.ui.containers.menus.MenuBar;
|
||||
import haxe.ui.containers.menus.MenuItem;
|
||||
import haxe.ui.containers.TreeView;
|
||||
import haxe.ui.containers.TreeViewNode;
|
||||
import haxe.ui.core.Component;
|
||||
import haxe.ui.core.Screen;
|
||||
import haxe.ui.events.DragEvent;
|
||||
import haxe.ui.events.MouseEvent;
|
||||
import haxe.ui.events.UIEvent;
|
||||
import haxe.ui.events.UIEvent;
|
||||
import haxe.ui.focus.FocusManager;
|
||||
import haxe.ui.notifications.NotificationManager;
|
||||
import haxe.ui.notifications.NotificationType;
|
||||
import openfl.display.BitmapData;
|
||||
import funkin.util.FileUtil;
|
||||
|
||||
using Lambda;
|
||||
|
||||
|
@ -109,24 +109,22 @@ using Lambda;
|
|||
* A state dedicated to allowing the user to create and edit song charts.
|
||||
* Built with HaxeUI for use by both developers and modders.
|
||||
*
|
||||
* Some functionality is moved to other classes to help maintain my sanity.
|
||||
* Some functionality is split into handler classes to help maintain my sanity.
|
||||
*
|
||||
* @author MasterEric
|
||||
*/
|
||||
@:nullSafety
|
||||
class ChartEditorState extends HaxeUIState
|
||||
// @:nullSafety
|
||||
|
||||
@:build(haxe.ui.ComponentBuilder.build("assets/exclude/data/ui/chart-editor/main-view.xml"))
|
||||
class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||
{
|
||||
/**
|
||||
* CONSTANTS
|
||||
*/
|
||||
// ==============================
|
||||
// XML Layouts
|
||||
public static final CHART_EDITOR_LAYOUT:String = Paths.ui('chart-editor/main-view');
|
||||
|
||||
public static final CHART_EDITOR_NOTIFBAR_LAYOUT:String = Paths.ui('chart-editor/components/notifbar');
|
||||
public static final CHART_EDITOR_PLAYBARHEAD_LAYOUT:String = Paths.ui('chart-editor/components/playbar-head');
|
||||
|
||||
// Layouts
|
||||
public static final CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT:String = Paths.ui('chart-editor/toolbox/notedata');
|
||||
|
||||
public static final CHART_EDITOR_TOOLBOX_EVENTDATA_LAYOUT:String = Paths.ui('chart-editor/toolbox/eventdata');
|
||||
public static final CHART_EDITOR_TOOLBOX_METADATA_LAYOUT:String = Paths.ui('chart-editor/toolbox/metadata');
|
||||
public static final CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT:String = Paths.ui('chart-editor/toolbox/difficulty');
|
||||
|
@ -1199,6 +1197,110 @@ class ChartEditorState extends HaxeUIState
|
|||
return currentSongMetadata.playData.characters.instrumental = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* HAXEUI COMPONENTS
|
||||
*/
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* The layout containing the playbar.
|
||||
* Constructed manually and added to the layout so we can control its position.
|
||||
*/
|
||||
var playbarHeadLayout:Null<ChartEditorPlaybarHead> = null;
|
||||
|
||||
// NOTE: All the components below are automatically assigned via HaxeUI macros.
|
||||
/**
|
||||
* The menubar at the top of the screen.
|
||||
*/
|
||||
// var menubar:MenuBar;
|
||||
/**
|
||||
* The `File -> New Chart` menu item.
|
||||
*/
|
||||
// var menubarItemNewChart:MenuItem;
|
||||
/**
|
||||
* The `File -> Open Chart` menu item.
|
||||
*/
|
||||
// var menubarItemOpenChart:MenuItem;
|
||||
/**
|
||||
* The `File -> Open Recent` menu.
|
||||
*/
|
||||
// var menubarOpenRecent:Menu;
|
||||
/**
|
||||
* The `File -> Save Chart` menu item.
|
||||
*/
|
||||
// var menubarItemSaveChart:MenuItem;
|
||||
/**
|
||||
* The `File -> Save Chart As` menu item.
|
||||
*/
|
||||
// var menubarItemSaveChartAs:MenuItem;
|
||||
/**
|
||||
* The `File -> Preferences` menu item.
|
||||
*/
|
||||
// var menubarItemPreferences:MenuItem;
|
||||
/**
|
||||
* The `File -> Exit` menu item.
|
||||
*/
|
||||
// var menubarItemExit:MenuItem;
|
||||
/**
|
||||
* The `Edit -> Undo` menu item.
|
||||
*/
|
||||
// var menubarItemUndo:MenuItem;
|
||||
/**
|
||||
* The `Edit -> Redo` menu item.
|
||||
*/
|
||||
// var menubarItemRedo:MenuItem;
|
||||
/**
|
||||
* The `Edit -> Cut` menu item.
|
||||
*/
|
||||
// var menubarItemCut:MenuItem;
|
||||
/**
|
||||
* The `Edit -> Copy` menu item.
|
||||
*/
|
||||
// var menubarItemCopy:MenuItem;
|
||||
/**
|
||||
* The `Edit -> Paste` menu item.
|
||||
*/
|
||||
// var menubarItemPaste:MenuItem;
|
||||
/**
|
||||
* The `Edit -> Paste Unsnapped` menu item.
|
||||
*/
|
||||
// var menubarItemPasteUnsnapped:MenuItem;
|
||||
/**
|
||||
* The `Edit -> Delete` menu item.
|
||||
*/
|
||||
// var menubarItemDelete:MenuItem;
|
||||
/**
|
||||
* The label by the playbar telling the song position.
|
||||
*/
|
||||
// var playbarSongPos:Label;
|
||||
/**
|
||||
* The label by the playbar telling the song time remaining.
|
||||
*/
|
||||
// var playbarSongRemaining:Label;
|
||||
/**
|
||||
* The label by the playbar telling the note snap.
|
||||
*/
|
||||
// var playbarNoteSnap:Label;
|
||||
/**
|
||||
* The button by the playbar to jump to the start of the song.
|
||||
*/
|
||||
// var playbarStart:Button;
|
||||
/**
|
||||
* The button by the playbar to jump backwards in the song.
|
||||
*/
|
||||
// var playbarBack:Button;
|
||||
/**
|
||||
* The button by the playbar to play or pause the song.
|
||||
*/
|
||||
// var playbarPlay:Button;
|
||||
/**
|
||||
* The button by the playbar to jump forwards in the song.
|
||||
*/
|
||||
// var playbarForward:Button;
|
||||
/**
|
||||
* The button by the playbar to jump to the end of the song.
|
||||
*/
|
||||
// var playbarEnd:Button;
|
||||
/**
|
||||
* RENDER OBJECTS
|
||||
*/
|
||||
|
@ -1288,41 +1390,6 @@ class ChartEditorState extends HaxeUIState
|
|||
*/
|
||||
var menuBG:Null<FlxSprite> = null;
|
||||
|
||||
/**
|
||||
* The layout containing the playbar head slider.
|
||||
*/
|
||||
var playbarHeadLayout:Null<Component> = null;
|
||||
|
||||
/**
|
||||
* The submenu in the menubar containing recently opened files.
|
||||
*/
|
||||
var menubarOpenRecent:Null<Menu> = null;
|
||||
|
||||
/**
|
||||
* The item in the menubar to save the currently opened chart.
|
||||
*/
|
||||
var menubarItemSaveChart:Null<MenuItem> = null;
|
||||
|
||||
/**
|
||||
* The playbar head slider.
|
||||
*/
|
||||
var playbarHead:Null<Slider> = null;
|
||||
|
||||
/**
|
||||
* The label by the playbar telling the song position.
|
||||
*/
|
||||
var playbarSongPos:Null<Label> = null;
|
||||
|
||||
/**
|
||||
* The label by the playbar telling the song time remaining.
|
||||
*/
|
||||
var playbarSongRemaining:Null<Label> = null;
|
||||
|
||||
/**
|
||||
* The label by the playbar telling the note snap.
|
||||
*/
|
||||
var playbarNoteSnap:Null<Label> = null;
|
||||
|
||||
/**
|
||||
* The sprite group containing the note graphics.
|
||||
* Only displays a subset of the data from `currentSongChartNoteData`,
|
||||
|
@ -1422,9 +1489,7 @@ class ChartEditorState extends HaxeUIState
|
|||
|
||||
public function new(?params:ChartEditorParams)
|
||||
{
|
||||
// Load the HaxeUI XML file.
|
||||
super(CHART_EDITOR_LAYOUT);
|
||||
|
||||
super();
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
|
@ -1471,7 +1536,7 @@ class ChartEditorState extends HaxeUIState
|
|||
// super.create() must be called first, the HaxeUI components get created here.
|
||||
super.create();
|
||||
// Set the z-index of the HaxeUI.
|
||||
this.component.zIndex = 100;
|
||||
this.root.zIndex = 100;
|
||||
|
||||
// Show the mouse cursor.
|
||||
Cursor.show();
|
||||
|
@ -1553,6 +1618,7 @@ class ChartEditorState extends HaxeUIState
|
|||
function setupWelcomeMusic()
|
||||
{
|
||||
this.welcomeMusic.loadEmbedded(Paths.music('chartEditorLoop/chartEditorLoop'));
|
||||
FlxG.sound.list.add(this.welcomeMusic);
|
||||
this.welcomeMusic.looped = true;
|
||||
}
|
||||
|
||||
|
@ -1923,25 +1989,20 @@ class ChartEditorState extends HaxeUIState
|
|||
|
||||
function buildAdditionalUI():Void
|
||||
{
|
||||
playbarHeadLayout = buildComponent(CHART_EDITOR_PLAYBARHEAD_LAYOUT);
|
||||
|
||||
if (playbarHeadLayout == null) throw 'ERROR: Failed to construct playbarHeadLayout! Check "${CHART_EDITOR_PLAYBARHEAD_LAYOUT}".';
|
||||
playbarHeadLayout = new ChartEditorPlaybarHead();
|
||||
|
||||
playbarHeadLayout.zIndex = 110;
|
||||
|
||||
playbarHeadLayout.width = FlxG.width - 8;
|
||||
playbarHeadLayout.height = 10;
|
||||
playbarHeadLayout.x = 4;
|
||||
playbarHeadLayout.y = FlxG.height - 48 - 8;
|
||||
|
||||
playbarHead = playbarHeadLayout.findComponent('playbarHead', Slider);
|
||||
if (playbarHead == null) throw 'ERROR: Failed to fetch playbarHead from playbarHeadLayout! Check "${CHART_EDITOR_PLAYBARHEAD_LAYOUT}".';
|
||||
playbarHead.allowFocus = false;
|
||||
playbarHead.width = FlxG.width;
|
||||
playbarHead.height = 10;
|
||||
playbarHead.styleString = 'padding-left: 0px; padding-right: 0px; border-left: 0px; border-right: 0px;';
|
||||
playbarHeadLayout.playbarHead.allowFocus = false;
|
||||
playbarHeadLayout.playbarHead.width = FlxG.width;
|
||||
playbarHeadLayout.playbarHead.height = 10;
|
||||
playbarHeadLayout.playbarHead.styleString = 'padding-left: 0px; padding-right: 0px; border-left: 0px; border-right: 0px;';
|
||||
|
||||
playbarHead.onDragStart = function(_:DragEvent) {
|
||||
playbarHeadLayout.playbarHead.onDragStart = function(_:DragEvent) {
|
||||
playbarHeadDragging = true;
|
||||
|
||||
// If we were dragging the playhead while the song was playing, resume playing.
|
||||
|
@ -1956,10 +2017,10 @@ class ChartEditorState extends HaxeUIState
|
|||
}
|
||||
}
|
||||
|
||||
playbarHead.onDragEnd = function(_:DragEvent) {
|
||||
playbarHeadLayout.playbarHead.onDragEnd = function(_:DragEvent) {
|
||||
playbarHeadDragging = false;
|
||||
|
||||
var value:Null<Float> = playbarHead?.value;
|
||||
var value:Null<Float> = playbarHeadLayout?.playbarHead?.value;
|
||||
|
||||
// Set the song position to where the playhead was moved to.
|
||||
scrollPositionInPixels = songLengthInPixels * ((value ?? 0.0) / 100);
|
||||
|
@ -1977,14 +2038,6 @@ class ChartEditorState extends HaxeUIState
|
|||
|
||||
add(playbarHeadLayout);
|
||||
|
||||
menubarOpenRecent = findComponent('menubarOpenRecent', Menu);
|
||||
if (menubarOpenRecent == null) throw "Could not find menubarOpenRecent!";
|
||||
|
||||
menubarItemSaveChart = findComponent('menubarItemSaveChart', MenuItem);
|
||||
if (menubarItemSaveChart == null) throw "Could not find menubarItemSaveChart!";
|
||||
|
||||
var menubar = findComponent('menubar', MenuBar);
|
||||
if (menubar == null) throw "Could not find menubar!";
|
||||
if (!Preferences.debugDisplay) menubar.paddingLeft = null;
|
||||
|
||||
// Setup notifications.
|
||||
|
@ -1999,27 +2052,28 @@ class ChartEditorState extends HaxeUIState
|
|||
{
|
||||
// Add functionality to the playbar.
|
||||
|
||||
addUIClickListener('playbarPlay', _ -> toggleAudioPlayback());
|
||||
addUIClickListener('playbarStart', _ -> playbarButtonPressed = 'playbarStart');
|
||||
addUIClickListener('playbarBack', _ -> playbarButtonPressed = 'playbarBack');
|
||||
addUIClickListener('playbarForward', _ -> playbarButtonPressed = 'playbarForward');
|
||||
addUIClickListener('playbarEnd', _ -> playbarButtonPressed = 'playbarEnd');
|
||||
playbarStart.onClick = _ -> playbarButtonPressed = 'playbarStart';
|
||||
playbarBack.onClick = _ -> playbarButtonPressed = 'playbarBack';
|
||||
playbarPlay.onClick = _ -> toggleAudioPlayback();
|
||||
playbarForward.onClick = _ -> playbarButtonPressed = 'playbarForward';
|
||||
playbarEnd.onClick = _ -> playbarButtonPressed = 'playbarEnd';
|
||||
|
||||
// Cycle note snap quant.
|
||||
addUIRightClickListener('playbarNoteSnap', function(_) {
|
||||
playbarNoteSnap.onRightClick = _ -> {
|
||||
noteSnapQuantIndex--;
|
||||
if (noteSnapQuantIndex < 0) noteSnapQuantIndex = SNAP_QUANTS.length - 1;
|
||||
});
|
||||
addUIClickListener('playbarNoteSnap', function(_) {
|
||||
};
|
||||
playbarNoteSnap.onClick = _ -> {
|
||||
noteSnapQuantIndex++;
|
||||
if (noteSnapQuantIndex >= SNAP_QUANTS.length) noteSnapQuantIndex = 0;
|
||||
});
|
||||
};
|
||||
|
||||
// Add functionality to the menu items.
|
||||
|
||||
addUIClickListener('menubarItemNewChart', _ -> ChartEditorDialogHandler.openWelcomeDialog(this, true));
|
||||
addUIClickListener('menubarItemOpenChart', _ -> ChartEditorDialogHandler.openBrowseFNFC(this, true));
|
||||
addUIClickListener('menubarItemSaveChart', _ -> {
|
||||
// File
|
||||
menubarItemNewChart.onClick = _ -> ChartEditorDialogHandler.openWelcomeDialog(this, true);
|
||||
menubarItemOpenChart.onClick = _ -> ChartEditorDialogHandler.openBrowseFNFC(this, true);
|
||||
menubarItemSaveChart.onClick = _ -> {
|
||||
if (currentWorkingFilePath != null)
|
||||
{
|
||||
ChartEditorImportExportHandler.exportAllSongData(this, true, currentWorkingFilePath);
|
||||
|
@ -2028,17 +2082,14 @@ class ChartEditorState extends HaxeUIState
|
|||
{
|
||||
ChartEditorImportExportHandler.exportAllSongData(this, false);
|
||||
}
|
||||
});
|
||||
addUIClickListener('menubarItemSaveChartAs', _ -> ChartEditorImportExportHandler.exportAllSongData(this));
|
||||
addUIClickListener('menubarItemLoadInst', _ -> ChartEditorDialogHandler.openUploadInstDialog(this, true));
|
||||
addUIClickListener('menubarItemImportChart', _ -> ChartEditorDialogHandler.openImportChartDialog(this, 'legacy', true));
|
||||
addUIClickListener('menubarItemExit', _ -> quitChartEditor());
|
||||
};
|
||||
menubarItemSaveChartAs.onClick = _ -> ChartEditorImportExportHandler.exportAllSongData(this);
|
||||
menubarItemExit.onClick = _ -> quitChartEditor();
|
||||
|
||||
addUIClickListener('menubarItemUndo', _ -> undoLastCommand());
|
||||
|
||||
addUIClickListener('menubarItemRedo', _ -> redoLastCommand());
|
||||
|
||||
addUIClickListener('menubarItemCopy', function(_) {
|
||||
// Edit
|
||||
menubarItemUndo.onClick = _ -> undoLastCommand();
|
||||
menubarItemRedo.onClick = _ -> redoLastCommand();
|
||||
menubarItemCopy.onClick = function(_) {
|
||||
// Doesn't use a command because it's not undoable.
|
||||
|
||||
// Calculate a single time offset for all the notes and events.
|
||||
|
@ -2056,24 +2107,23 @@ class ChartEditorState extends HaxeUIState
|
|||
notes: SongDataUtils.buildNoteClipboard(currentNoteSelection, timeOffset),
|
||||
events: SongDataUtils.buildEventClipboard(currentEventSelection, timeOffset),
|
||||
});
|
||||
});
|
||||
};
|
||||
menubarItemCut.onClick = _ -> performCommand(new CutItemsCommand(currentNoteSelection, currentEventSelection));
|
||||
|
||||
addUIClickListener('menubarItemCut', _ -> performCommand(new CutItemsCommand(currentNoteSelection, currentEventSelection)));
|
||||
|
||||
addUIClickListener('menubarItemPaste', _ -> {
|
||||
menubarItemPaste.onClick = _ -> {
|
||||
var targetMs:Float = scrollPositionInMs + playheadPositionInMs;
|
||||
var targetStep:Float = Conductor.getTimeInSteps(targetMs);
|
||||
var targetSnappedStep:Float = Math.floor(targetStep / noteSnapRatio) * noteSnapRatio;
|
||||
var targetSnappedMs:Float = Conductor.getStepTimeInMs(targetSnappedStep);
|
||||
performCommand(new PasteItemsCommand(targetSnappedMs));
|
||||
});
|
||||
};
|
||||
|
||||
addUIClickListener('menubarItemPasteUnsnapped', _ -> {
|
||||
menubarItemPasteUnsnapped.onClick = _ -> {
|
||||
var targetMs:Float = scrollPositionInMs + playheadPositionInMs;
|
||||
performCommand(new PasteItemsCommand(targetMs));
|
||||
});
|
||||
};
|
||||
|
||||
addUIClickListener('menubarItemDelete', function(_) {
|
||||
menubarItemDelete.onClick = _ -> {
|
||||
if (currentNoteSelection.length > 0 && currentEventSelection.length > 0)
|
||||
{
|
||||
performCommand(new RemoveItemsCommand(currentNoteSelection, currentEventSelection));
|
||||
|
@ -2090,120 +2140,108 @@ class ChartEditorState extends HaxeUIState
|
|||
{
|
||||
// Do nothing???
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
addUIClickListener('menubarItemFlipNotes', _ -> performCommand(new FlipNotesCommand(currentNoteSelection)));
|
||||
menubarItemFlipNotes.onClick = _ -> performCommand(new FlipNotesCommand(currentNoteSelection));
|
||||
|
||||
addUIClickListener('menubarItemSelectAll', _ -> performCommand(new SelectAllItemsCommand(currentNoteSelection, currentEventSelection)));
|
||||
menubarItemSelectAll.onClick = _ -> performCommand(new SelectAllItemsCommand(currentNoteSelection, currentEventSelection));
|
||||
|
||||
addUIClickListener('menubarItemSelectInverse', _ -> performCommand(new InvertSelectedItemsCommand(currentNoteSelection, currentEventSelection)));
|
||||
menubarItemSelectInverse.onClick = _ -> performCommand(new InvertSelectedItemsCommand(currentNoteSelection, currentEventSelection));
|
||||
|
||||
addUIClickListener('menubarItemSelectNone', _ -> performCommand(new DeselectAllItemsCommand(currentNoteSelection, currentEventSelection)));
|
||||
menubarItemSelectNone.onClick = _ -> performCommand(new DeselectAllItemsCommand(currentNoteSelection, currentEventSelection));
|
||||
|
||||
addUIClickListener('menubarItemPlaytestFull', _ -> testSongInPlayState(false));
|
||||
addUIClickListener('menubarItemPlaytestMinimal', _ -> testSongInPlayState(true));
|
||||
menubarItemPlaytestFull.onClick = _ -> testSongInPlayState(false);
|
||||
menubarItemPlaytestMinimal.onClick = _ -> testSongInPlayState(true);
|
||||
|
||||
addUIClickListener('menuBarItemNoteSnapDecrease', _ -> {
|
||||
menuBarItemNoteSnapDecrease.onClick = _ -> {
|
||||
noteSnapQuantIndex--;
|
||||
if (noteSnapQuantIndex < 0) noteSnapQuantIndex = SNAP_QUANTS.length - 1;
|
||||
});
|
||||
addUIClickListener('menuBarItemNoteSnapIncrease', _ -> {
|
||||
};
|
||||
menuBarItemNoteSnapIncrease.onClick = _ -> {
|
||||
noteSnapQuantIndex++;
|
||||
if (noteSnapQuantIndex >= SNAP_QUANTS.length) noteSnapQuantIndex = 0;
|
||||
});
|
||||
};
|
||||
|
||||
addUIChangeListener('menuBarItemInputStyleNone', function(event:UIEvent) {
|
||||
menuBarItemInputStyleNone.onClick = function(event:UIEvent) {
|
||||
currentLiveInputStyle = None;
|
||||
});
|
||||
addUIChangeListener('menuBarItemInputStyleNumberKeys', function(event:UIEvent) {
|
||||
};
|
||||
menuBarItemInputStyleNumberKeys.onClick = function(event:UIEvent) {
|
||||
currentLiveInputStyle = NumberKeys;
|
||||
});
|
||||
addUIChangeListener('menuBarItemInputStyleWASD', function(event:UIEvent) {
|
||||
};
|
||||
menuBarItemInputStyleWASD.onClick = function(event:UIEvent) {
|
||||
currentLiveInputStyle = WASD;
|
||||
});
|
||||
};
|
||||
|
||||
addUIClickListener('menubarItemAbout', _ -> this.openAboutDialog());
|
||||
addUIClickListener('menubarItemWelcomeDialog', _ -> this.openWelcomeDialog(true));
|
||||
menubarItemAbout.onClick = _ -> this.openAboutDialog();
|
||||
menubarItemWelcomeDialog.onClick = _ -> this.openWelcomeDialog(true);
|
||||
|
||||
addUIClickListener('menubarItemUserGuide', _ -> this.openUserGuideDialog());
|
||||
menubarItemUserGuide.onClick = _ -> this.openUserGuideDialog();
|
||||
|
||||
addUIChangeListener('menubarItemDownscroll', event -> isViewDownscroll = event.value);
|
||||
setUICheckboxSelected('menubarItemDownscroll', isViewDownscroll);
|
||||
menubarItemDownscroll.onClick = event -> isViewDownscroll = event.value;
|
||||
menubarItemDownscroll.selected = isViewDownscroll;
|
||||
|
||||
addUIClickListener('menubarItemDifficultyUp', _ -> incrementDifficulty(1));
|
||||
addUIClickListener('menubarItemDifficultyDown', _ -> incrementDifficulty(-1));
|
||||
menubarItemDifficultyUp.onClick = _ -> incrementDifficulty(1);
|
||||
menubarItemDifficultyDown.onClick = _ -> incrementDifficulty(-1);
|
||||
|
||||
addUIChangeListener('menubarItemPlaytestStartTime', event -> playtestStartTime = event.value);
|
||||
setUICheckboxSelected('menubarItemPlaytestStartTime', playtestStartTime);
|
||||
menubarItemPlaytestStartTime.onChange = event -> playtestStartTime = event.value;
|
||||
menubarItemPlaytestStartTime.selected = playtestStartTime;
|
||||
|
||||
addUIChangeListener('menuBarItemThemeLight', function(event:UIEvent) {
|
||||
menuBarItemThemeLight.onChange = function(event:UIEvent) {
|
||||
if (event.target.value) currentTheme = ChartEditorTheme.Light;
|
||||
});
|
||||
setUICheckboxSelected('menuBarItemThemeLight', currentTheme == ChartEditorTheme.Light);
|
||||
};
|
||||
menuBarItemThemeLight.selected = currentTheme == ChartEditorTheme.Light;
|
||||
|
||||
addUIChangeListener('menuBarItemThemeDark', function(event:UIEvent) {
|
||||
menuBarItemThemeDark.onChange = function(event:UIEvent) {
|
||||
if (event.target.value) currentTheme = ChartEditorTheme.Dark;
|
||||
});
|
||||
setUICheckboxSelected('menuBarItemThemeDark', currentTheme == ChartEditorTheme.Dark);
|
||||
};
|
||||
menuBarItemThemeDark.selected = currentTheme == ChartEditorTheme.Dark;
|
||||
|
||||
addUIClickListener('menubarItemPlayPause', _ -> toggleAudioPlayback());
|
||||
menubarItemPlayPause.onClick = _ -> toggleAudioPlayback();
|
||||
|
||||
addUIClickListener('menubarItemLoadInstrumental', _ -> this.openUploadInstDialog(true));
|
||||
addUIClickListener('menubarItemLoadVocals', _ -> this.openUploadVocalsDialog(true));
|
||||
menubarItemLoadInstrumental.onClick = _ -> this.openUploadInstDialog(true);
|
||||
menubarItemLoadVocals.onClick = _ -> this.openUploadVocalsDialog(true);
|
||||
|
||||
addUIChangeListener('menubarItemMetronomeEnabled', event -> isMetronomeEnabled = event.value);
|
||||
setUICheckboxSelected('menubarItemMetronomeEnabled', isMetronomeEnabled);
|
||||
menubarItemMetronomeEnabled.onChange = event -> isMetronomeEnabled = event.value;
|
||||
menubarItemMetronomeEnabled.selected = isMetronomeEnabled;
|
||||
|
||||
addUIChangeListener('menubarItemPlayerHitsounds', event -> hitsoundsEnabledPlayer = event.value);
|
||||
setUICheckboxSelected('menubarItemPlayerHitsounds', hitsoundsEnabledPlayer);
|
||||
menubarItemPlayerHitsounds.onChange = event -> hitsoundsEnabledPlayer = event.value;
|
||||
menubarItemPlayerHitsounds.selected = hitsoundsEnabledPlayer;
|
||||
|
||||
addUIChangeListener('menubarItemOpponentHitsounds', event -> hitsoundsEnabledOpponent = event.value);
|
||||
setUICheckboxSelected('menubarItemOpponentHitsounds', hitsoundsEnabledOpponent);
|
||||
menubarItemOpponentHitsounds.onChange = event -> hitsoundsEnabledOpponent = event.value;
|
||||
menubarItemOpponentHitsounds.selected = hitsoundsEnabledOpponent;
|
||||
|
||||
var instVolumeLabel:Null<Label> = findComponent('menubarLabelVolumeInstrumental', Label);
|
||||
if (instVolumeLabel != null)
|
||||
{
|
||||
addUIChangeListener('menubarItemVolumeInstrumental', function(event:UIEvent) {
|
||||
var volume:Float = (event?.value ?? 0) / 100.0;
|
||||
if (audioInstTrack != null) audioInstTrack.volume = volume;
|
||||
instVolumeLabel.text = 'Instrumental - ${Std.int(event.value)}%';
|
||||
});
|
||||
menubarItemVolumeInstrumental.onChange = event -> {
|
||||
var volume:Float = (event?.value ?? 0) / 100.0;
|
||||
if (audioInstTrack != null) audioInstTrack.volume = volume;
|
||||
menubarLabelVolumeInstrumental.text = 'Instrumental - ${Std.int(event.value)}%';
|
||||
};
|
||||
|
||||
menubarItemVolumeVocals.onChange = event -> {
|
||||
var volume:Float = (event?.value ?? 0) / 100.0;
|
||||
if (audioVocalTrackGroup != null) audioVocalTrackGroup.volume = volume;
|
||||
menubarLabelVolumeVocals.text = 'Voices - ${Std.int(event.value)}%';
|
||||
}
|
||||
|
||||
var vocalsVolumeLabel:Null<Label> = findComponent('menubarLabelVolumeVocals', Label);
|
||||
if (vocalsVolumeLabel != null)
|
||||
{
|
||||
addUIChangeListener('menubarItemVolumeVocals', function(event:UIEvent) {
|
||||
var volume:Float = (event?.value ?? 0) / 100.0;
|
||||
if (audioVocalTrackGroup != null) audioVocalTrackGroup.volume = volume;
|
||||
vocalsVolumeLabel.text = 'Voices - ${Std.int(event.value)}%';
|
||||
});
|
||||
menubarItemPlaybackSpeed.onChange = event -> {
|
||||
var pitch:Float = event.value * 2.0 / 100.0;
|
||||
pitch = Math.floor(pitch / 0.25) * 0.25; // Round to nearest 0.25.
|
||||
#if FLX_PITCH
|
||||
if (audioInstTrack != null) audioInstTrack.pitch = pitch;
|
||||
if (audioVocalTrackGroup != null) audioVocalTrackGroup.pitch = pitch;
|
||||
#end
|
||||
var pitchDisplay:Float = Std.int(pitch * 100) / 100; // Round to 2 decimal places.
|
||||
menubarLabelPlaybackSpeed.text = 'Playback Speed - ${pitchDisplay}x';
|
||||
}
|
||||
|
||||
var playbackSpeedLabel:Null<Label> = findComponent('menubarLabelPlaybackSpeed', Label);
|
||||
if (playbackSpeedLabel != null)
|
||||
{
|
||||
addUIChangeListener('menubarItemPlaybackSpeed', function(event:UIEvent) {
|
||||
var pitch:Float = event.value * 2.0 / 100.0;
|
||||
pitch = Math.floor(pitch / 0.25) * 0.25; // Round to nearest 0.25.
|
||||
#if FLX_PITCH
|
||||
if (audioInstTrack != null) audioInstTrack.pitch = pitch;
|
||||
if (audioVocalTrackGroup != null) audioVocalTrackGroup.pitch = pitch;
|
||||
#end
|
||||
var pitchDisplay:Float = Std.int(pitch * 100) / 100; // Round to 2 decimal places.
|
||||
playbackSpeedLabel.text = 'Playback Speed - ${pitchDisplay}x';
|
||||
});
|
||||
}
|
||||
|
||||
addUIChangeListener('menubarItemToggleToolboxDifficulty', event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT, event.value));
|
||||
addUIChangeListener('menubarItemToggleToolboxMetadata', event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT, event.value));
|
||||
addUIChangeListener('menubarItemToggleToolboxNotes', event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT, event.value));
|
||||
addUIChangeListener('menubarItemToggleToolboxEvents', event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_EVENTDATA_LAYOUT, event.value));
|
||||
addUIChangeListener('menubarItemToggleToolboxPlayerPreview', event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT, event.value));
|
||||
addUIChangeListener('menubarItemToggleToolboxOpponentPreview', event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT, event.value));
|
||||
menubarItemToggleToolboxDifficulty.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT, event.value);
|
||||
menubarItemToggleToolboxMetadata.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT, event.value);
|
||||
menubarItemToggleToolboxNotes.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT, event.value);
|
||||
menubarItemToggleToolboxEvents.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_EVENTDATA_LAYOUT, event.value);
|
||||
menubarItemToggleToolboxPlayerPreview.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT, event.value);
|
||||
menubarItemToggleToolboxOpponentPreview.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT, event.value);
|
||||
|
||||
// TODO: Pass specific HaxeUI components to add context menus to them.
|
||||
registerContextMenu(null, Paths.ui('chart-editor/context/test'));
|
||||
// registerContextMenu(null, Paths.ui('chart-editor/context/test'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3816,7 +3854,6 @@ class ChartEditorState extends HaxeUIState
|
|||
function handlePlaybar():Void
|
||||
{
|
||||
if (playbarHeadLayout == null) throw "ERROR: Tried to handle playbar, but playbarHeadLayout is null!";
|
||||
if (playbarHead == null) throw "ERROR: Tried to handle playbar, but playbarHeadLayout is null!";
|
||||
|
||||
// Make sure the playbar is never nudged out of the correct spot.
|
||||
playbarHeadLayout.x = 4;
|
||||
|
@ -3829,26 +3866,22 @@ class ChartEditorState extends HaxeUIState
|
|||
if (!playbarHeadDragging)
|
||||
{
|
||||
var songPosPercent:Float = songPos / songLengthInMs * 100;
|
||||
if (playbarHead.value != songPosPercent) playbarHead.value = songPosPercent;
|
||||
if (playbarHeadLayout.playbarHead.value != songPosPercent) playbarHeadLayout.playbarHead.value = songPosPercent;
|
||||
}
|
||||
|
||||
var songPosSeconds:String = Std.string(Math.floor((songPos / 1000) % 60)).lpad('0', 2);
|
||||
var songPosMinutes:String = Std.string(Math.floor((songPos / 1000) / 60)).lpad('0', 2);
|
||||
var songPosString:String = '${songPosMinutes}:${songPosSeconds}';
|
||||
|
||||
if (playbarSongPos == null) playbarSongPos = findComponent('playbarSongPos', Label);
|
||||
if (playbarSongPos != null && playbarSongPos.value != songPosString) playbarSongPos.value = songPosString;
|
||||
if (playbarSongPos.value != songPosString) playbarSongPos.value = songPosString;
|
||||
|
||||
var songRemainingSeconds:String = Std.string(Math.floor((songRemaining / 1000) % 60)).lpad('0', 2);
|
||||
var songRemainingMinutes:String = Std.string(Math.floor((songRemaining / 1000) / 60)).lpad('0', 2);
|
||||
var songRemainingString:String = '-${songRemainingMinutes}:${songRemainingSeconds}';
|
||||
|
||||
if (playbarSongRemaining == null) playbarSongRemaining = findComponent('playbarSongRemaining', Label);
|
||||
if (playbarSongRemaining != null
|
||||
&& playbarSongRemaining.value != songRemainingString) playbarSongRemaining.value = songRemainingString;
|
||||
if (playbarSongRemaining.value != songRemainingString) playbarSongRemaining.value = songRemainingString;
|
||||
|
||||
if (playbarNoteSnap == null) playbarNoteSnap = findComponent('playbarNoteSnap', Label);
|
||||
if (playbarNoteSnap != null) playbarNoteSnap.text = '1/${noteSnapQuant}';
|
||||
playbarNoteSnap.text = '1/${noteSnapQuant}';
|
||||
}
|
||||
|
||||
function handlePlayhead():Void
|
||||
|
@ -3950,18 +3983,18 @@ class ChartEditorState extends HaxeUIState
|
|||
function handleFileKeybinds():Void
|
||||
{
|
||||
// CTRL + N = New Chart
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.N)
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.N && !isHaxeUIDialogOpen)
|
||||
{
|
||||
this.openWelcomeDialog(true);
|
||||
}
|
||||
|
||||
// CTRL + O = Open Chart
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.O)
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.O && !isHaxeUIDialogOpen)
|
||||
{
|
||||
this.openBrowseFNFC(true);
|
||||
}
|
||||
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.S)
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.S && !isHaxeUIDialogOpen)
|
||||
{
|
||||
if (currentWorkingFilePath == null || FlxG.keys.pressed.SHIFT)
|
||||
{
|
||||
|
@ -3975,10 +4008,11 @@ class ChartEditorState extends HaxeUIState
|
|||
}
|
||||
}
|
||||
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.S)
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.S && !isHaxeUIDialogOpen)
|
||||
{
|
||||
this.exportAllSongData(false);
|
||||
}
|
||||
|
||||
// CTRL + Q = Quit to Menu
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.Q)
|
||||
{
|
||||
|
@ -4309,7 +4343,7 @@ class ChartEditorState extends HaxeUIState
|
|||
FlxG.camera.focusOn(new FlxPoint(FlxG.width / 2, FlxG.height / 2));
|
||||
FlxG.camera.zoom = 1.0;
|
||||
|
||||
add(this.component);
|
||||
add(this.root);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4325,7 +4359,7 @@ class ChartEditorState extends HaxeUIState
|
|||
if (audioVocalTrackGroup != null) audioVocalTrackGroup.play(false, audioInstTrack.time);
|
||||
}
|
||||
|
||||
setComponentText('playbarPlay', '||');
|
||||
playbarPlay.text = '||'; // Pause
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4561,12 +4595,9 @@ class ChartEditorState extends HaxeUIState
|
|||
{
|
||||
moveSongToScrollPosition();
|
||||
|
||||
var instVolumeSlider:Null<Slider> = findComponent('menubarItemVolumeInstrumental', Slider);
|
||||
var vocalVolumeSlider:Null<Slider> = findComponent('menubarItemVolumeVocals', Slider);
|
||||
|
||||
// Reapply the volume.
|
||||
var instTargetVolume:Float = instVolumeSlider?.value ?? 1.0;
|
||||
var vocalTargetVolume:Float = vocalVolumeSlider?.value ?? 1.0;
|
||||
var instTargetVolume:Float = menubarItemVolumeInstrumental.value ?? 1.0;
|
||||
var vocalTargetVolume:Float = menubarItemVolumeVocals.value ?? 1.0;
|
||||
|
||||
if (audioInstTrack != null)
|
||||
{
|
||||
|
@ -4780,48 +4811,30 @@ class ChartEditorState extends HaxeUIState
|
|||
commandHistoryDirty = false;
|
||||
|
||||
// Update the Undo and Redo buttons.
|
||||
var undoButton:Null<MenuItem> = findComponent('menubarItemUndo', MenuItem);
|
||||
|
||||
if (undoButton != null)
|
||||
if (undoHistory.length == 0)
|
||||
{
|
||||
if (undoHistory.length == 0)
|
||||
{
|
||||
// Disable the Undo button.
|
||||
undoButton.disabled = true;
|
||||
undoButton.text = 'Undo';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Change the label to the last command.
|
||||
undoButton.disabled = false;
|
||||
undoButton.text = 'Undo ${undoHistory[undoHistory.length - 1].toString()}';
|
||||
}
|
||||
// Disable the Undo button.
|
||||
menubarItemUndo.disabled = true;
|
||||
menubarItemUndo.text = 'Undo';
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('undoButton is null');
|
||||
// Change the label to the last command.
|
||||
menubarItemUndo.disabled = false;
|
||||
menubarItemUndo.text = 'Undo ${undoHistory[undoHistory.length - 1].toString()}';
|
||||
}
|
||||
|
||||
var redoButton:Null<MenuItem> = findComponent('menubarItemRedo', MenuItem);
|
||||
|
||||
if (redoButton != null)
|
||||
if (redoHistory.length == 0)
|
||||
{
|
||||
if (redoHistory.length == 0)
|
||||
{
|
||||
// Disable the Redo button.
|
||||
redoButton.disabled = true;
|
||||
redoButton.text = 'Redo';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Change the label to the last command.
|
||||
redoButton.disabled = false;
|
||||
redoButton.text = 'Redo ${redoHistory[redoHistory.length - 1].toString()}';
|
||||
}
|
||||
// Disable the Redo button.
|
||||
menubarItemRedo.disabled = true;
|
||||
menubarItemRedo.text = 'Redo';
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('redoButton is null');
|
||||
// Change the label to the last command.
|
||||
menubarItemRedo.disabled = false;
|
||||
menubarItemRedo.text = 'Redo ${redoHistory[redoHistory.length - 1].toString()}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4862,9 +4875,9 @@ class ChartEditorState extends HaxeUIState
|
|||
switch (noteData.getStrumlineIndex())
|
||||
{
|
||||
case 0: // Player
|
||||
if (hitsoundsEnabledPlayer) ChartEditorAudioHandler.playSound(this, Paths.sound('chartingSounds/hitNotePlayer'));
|
||||
if (hitsoundsEnabledPlayer) this.playSound(Paths.sound('chartingSounds/hitNotePlayer'));
|
||||
case 1: // Opponent
|
||||
if (hitsoundsEnabledOpponent) ChartEditorAudioHandler.playSound(this, Paths.sound('chartingSounds/hitNoteOpponent'));
|
||||
if (hitsoundsEnabledOpponent) this.playSound(Paths.sound('chartingSounds/hitNoteOpponent'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4874,7 +4887,7 @@ class ChartEditorState extends HaxeUIState
|
|||
if (audioInstTrack != null) audioInstTrack.pause();
|
||||
if (audioVocalTrackGroup != null) audioVocalTrackGroup.pause();
|
||||
|
||||
setComponentText('playbarPlay', '>');
|
||||
playbarPlay.text = '>';
|
||||
}
|
||||
|
||||
function toggleAudioPlayback():Void
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package funkin.ui.debug.charting.components;
|
||||
|
||||
import haxe.ui.containers.Box;
|
||||
import haxe.ui.components.HorizontalSlider;
|
||||
|
||||
/**
|
||||
* The component which contains the playhead for the chart editor.
|
||||
* This is in a separate component so it can be positioned independently.
|
||||
*/
|
||||
@:build(haxe.ui.ComponentBuilder.build("assets/exclude/data/ui/chart-editor/components/playbar-head.xml"))
|
||||
class ChartEditorPlaybarHead extends Box
|
||||
{
|
||||
// Auto-populated
|
||||
// public var playbarHead:HorizontalSlider;
|
||||
// Auto-populated.
|
||||
// public function new() { }
|
||||
}
|
|
@ -7,28 +7,28 @@ class ChartEditorShortcutHandler
|
|||
{
|
||||
public static function applyPlatformShortcutText(state:ChartEditorState):Void
|
||||
{
|
||||
state.setComponentShortcutText('menubarItemNewChart', ctrlOrCmd('N'));
|
||||
state.setComponentShortcutText('menubarItemOpenChart', ctrlOrCmd('O'));
|
||||
state.setComponentShortcutText('menubarItemSaveChartAs', ctrlOrCmd(shift('S')));
|
||||
state.setComponentShortcutText('menubarItemExit', ctrlOrCmd('Q'));
|
||||
state.menubarItemNewChart.shortcutText = ctrlOrCmd('N');
|
||||
state.menubarItemOpenChart.shortcutText = ctrlOrCmd('O');
|
||||
state.menubarItemSaveChartAs.shortcutText = ctrlOrCmd(shift('S'));
|
||||
state.menubarItemExit.shortcutText = ctrlOrCmd('Q');
|
||||
|
||||
state.setComponentShortcutText('menubarItemUndo', ctrlOrCmd('Z'));
|
||||
state.setComponentShortcutText('menubarItemRedo', ctrlOrCmd('Y'));
|
||||
state.setComponentShortcutText('menubarItemCut', ctrlOrCmd('X'));
|
||||
state.setComponentShortcutText('menubarItemCopy', ctrlOrCmd('C'));
|
||||
state.setComponentShortcutText('menubarItemPaste', ctrlOrCmd('V'));
|
||||
state.menubarItemUndo.shortcutText = ctrlOrCmd('Z');
|
||||
state.menubarItemRedo.shortcutText = ctrlOrCmd('Y');
|
||||
state.menubarItemCut.shortcutText = ctrlOrCmd('X');
|
||||
state.menubarItemCopy.shortcutText = ctrlOrCmd('C');
|
||||
state.menubarItemPaste.shortcutText = ctrlOrCmd('V');
|
||||
|
||||
state.setComponentShortcutText('menubarItemSelectAll', ctrlOrCmd('A'));
|
||||
state.setComponentShortcutText('menubarItemSelectInverse', ctrlOrCmd('I'));
|
||||
state.setComponentShortcutText('menubarItemSelectNone', ctrlOrCmd('D'));
|
||||
state.setComponentShortcutText('menubarItemSelectBeforeCursor', shift('Home'));
|
||||
state.setComponentShortcutText('menubarItemSelectAfterCursor', shift('End'));
|
||||
state.menubarItemSelectAll.shortcutText = ctrlOrCmd('A');
|
||||
state.menubarItemSelectInverse.shortcutText = ctrlOrCmd('I');
|
||||
state.menubarItemSelectNone.shortcutText = ctrlOrCmd('D');
|
||||
state.menubarItemSelectBeforeCursor.shortcutText = shift('Home');
|
||||
state.menubarItemSelectAfterCursor.shortcutText = shift('End');
|
||||
|
||||
state.setComponentShortcutText('menubarItemDifficultyDown', ctrlOrCmd('←'));
|
||||
state.setComponentShortcutText('menubarItemDifficultyUp', ctrlOrCmd('→'));
|
||||
state.menubarItemDifficultyDown.shortcutText = ctrlOrCmd('←');
|
||||
state.menubarItemDifficultyUp.shortcutText = ctrlOrCmd('→');
|
||||
|
||||
state.setComponentShortcutText('menubarItemPlaytestFull', 'Enter');
|
||||
state.setComponentShortcutText('menubarItemPlaytestMinimal', shift('Enter'));
|
||||
state.menubarItemPlaytestFull.shortcutText = 'Enter';
|
||||
state.menubarItemPlaytestMinimal.shortcutText = shift('Enter');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,6 +18,7 @@ import funkin.play.event.SongEvent;
|
|||
import funkin.play.song.SongSerializer;
|
||||
import funkin.play.stage.StageData;
|
||||
import funkin.play.stage.StageData.StageDataParser;
|
||||
import haxe.ui.RuntimeComponentBuilder;
|
||||
import funkin.ui.debug.charting.util.ChartEditorDropdowns;
|
||||
import funkin.ui.haxeui.components.CharacterPlayer;
|
||||
import funkin.util.FileUtil;
|
||||
|
@ -217,7 +218,7 @@ class ChartEditorToolboxHandler
|
|||
|
||||
static function buildToolboxNoteDataLayout(state:ChartEditorState):Null<CollapsibleDialog>
|
||||
{
|
||||
var toolbox:CollapsibleDialog = cast state.buildComponent(ChartEditorState.CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT);
|
||||
var toolbox:CollapsibleDialog = cast RuntimeComponentBuilder.fromAsset(ChartEditorState.CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT);
|
||||
|
||||
if (toolbox == null) return null;
|
||||
|
||||
|
@ -226,7 +227,7 @@ class ChartEditorToolboxHandler
|
|||
toolbox.y = 100;
|
||||
|
||||
toolbox.onDialogClosed = function(event:DialogEvent) {
|
||||
state.setUICheckboxSelected('menubarItemToggleToolboxNotes', false);
|
||||
state.menubarItemToggleToolboxNotes.selected = false;
|
||||
}
|
||||
|
||||
var toolboxNotesNoteKind:Null<DropDown> = toolbox.findComponent('toolboxNotesNoteKind', DropDown);
|
||||
|
@ -269,7 +270,7 @@ class ChartEditorToolboxHandler
|
|||
|
||||
static function buildToolboxEventDataLayout(state:ChartEditorState):Null<CollapsibleDialog>
|
||||
{
|
||||
var toolbox:CollapsibleDialog = cast state.buildComponent(ChartEditorState.CHART_EDITOR_TOOLBOX_EVENTDATA_LAYOUT);
|
||||
var toolbox:CollapsibleDialog = cast RuntimeComponentBuilder.fromAsset(ChartEditorState.CHART_EDITOR_TOOLBOX_EVENTDATA_LAYOUT);
|
||||
|
||||
if (toolbox == null) return null;
|
||||
|
||||
|
@ -278,7 +279,7 @@ class ChartEditorToolboxHandler
|
|||
toolbox.y = 150;
|
||||
|
||||
toolbox.onDialogClosed = function(event:DialogEvent) {
|
||||
state.setUICheckboxSelected('menubarItemToggleToolboxEvents', false);
|
||||
state.menubarItemToggleToolboxEvents.selected = false;
|
||||
}
|
||||
|
||||
var toolboxEventsEventKind:Null<DropDown> = toolbox.findComponent('toolboxEventsEventKind', DropDown);
|
||||
|
@ -418,7 +419,7 @@ class ChartEditorToolboxHandler
|
|||
|
||||
static function buildToolboxDifficultyLayout(state:ChartEditorState):Null<CollapsibleDialog>
|
||||
{
|
||||
var toolbox:CollapsibleDialog = cast state.buildComponent(ChartEditorState.CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT);
|
||||
var toolbox:CollapsibleDialog = cast RuntimeComponentBuilder.fromAsset(ChartEditorState.CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT);
|
||||
|
||||
if (toolbox == null) return null;
|
||||
|
||||
|
@ -427,7 +428,7 @@ class ChartEditorToolboxHandler
|
|||
toolbox.y = 200;
|
||||
|
||||
toolbox.onDialogClosed = function(event:UIEvent) {
|
||||
state.setUICheckboxSelected('menubarItemToggleToolboxDifficulty', false);
|
||||
state.menubarItemToggleToolboxDifficulty.selected = false;
|
||||
}
|
||||
|
||||
var difficultyToolboxAddVariation:Null<Button> = toolbox.findComponent('difficultyToolboxAddVariation', Button);
|
||||
|
@ -505,7 +506,7 @@ class ChartEditorToolboxHandler
|
|||
|
||||
static function buildToolboxMetadataLayout(state:ChartEditorState):Null<CollapsibleDialog>
|
||||
{
|
||||
var toolbox:CollapsibleDialog = cast state.buildComponent(ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT);
|
||||
var toolbox:CollapsibleDialog = cast RuntimeComponentBuilder.fromAsset(ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT);
|
||||
|
||||
if (toolbox == null) return null;
|
||||
|
||||
|
@ -514,7 +515,7 @@ class ChartEditorToolboxHandler
|
|||
toolbox.y = 250;
|
||||
|
||||
toolbox.onDialogClosed = function(event:UIEvent) {
|
||||
state.setUICheckboxSelected('menubarItemToggleToolboxMetadata', false);
|
||||
state.menubarItemToggleToolboxMetadata.selected = false;
|
||||
}
|
||||
|
||||
var inputSongName:Null<TextField> = toolbox.findComponent('inputSongName', TextField);
|
||||
|
@ -667,7 +668,7 @@ class ChartEditorToolboxHandler
|
|||
|
||||
static function buildToolboxPlayerPreviewLayout(state:ChartEditorState):Null<CollapsibleDialog>
|
||||
{
|
||||
var toolbox:CollapsibleDialog = cast state.buildComponent(ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT);
|
||||
var toolbox:CollapsibleDialog = cast RuntimeComponentBuilder.fromAsset(ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT);
|
||||
|
||||
if (toolbox == null) return null;
|
||||
|
||||
|
@ -676,7 +677,7 @@ class ChartEditorToolboxHandler
|
|||
toolbox.y = 350;
|
||||
|
||||
toolbox.onDialogClosed = function(event:DialogEvent) {
|
||||
state.setUICheckboxSelected('menubarItemToggleToolboxPlayerPreview', false);
|
||||
state.menubarItemToggleToolboxPlayerPreview.selected = false;
|
||||
}
|
||||
|
||||
var charPlayer:Null<CharacterPlayer> = toolbox.findComponent('charPlayer');
|
||||
|
@ -696,7 +697,7 @@ class ChartEditorToolboxHandler
|
|||
|
||||
static function buildToolboxOpponentPreviewLayout(state:ChartEditorState):Null<CollapsibleDialog>
|
||||
{
|
||||
var toolbox:CollapsibleDialog = cast state.buildComponent(ChartEditorState.CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT);
|
||||
var toolbox:CollapsibleDialog = cast RuntimeComponentBuilder.fromAsset(ChartEditorState.CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT);
|
||||
|
||||
if (toolbox == null) return null;
|
||||
|
||||
|
@ -705,7 +706,7 @@ class ChartEditorToolboxHandler
|
|||
toolbox.y = 350;
|
||||
|
||||
toolbox.onDialogClosed = (event:DialogEvent) -> {
|
||||
state.setUICheckboxSelected('menubarItemToggleToolboxOpponentPreview', false);
|
||||
state.menubarItemToggleToolboxOpponentPreview.selected = false;
|
||||
}
|
||||
|
||||
var charPlayer:Null<CharacterPlayer> = toolbox.findComponent('charPlayer');
|
||||
|
|
|
@ -8,6 +8,10 @@ import haxe.io.Path;
|
|||
import openfl.net.FileReference;
|
||||
import openfl.events.Event;
|
||||
import openfl.events.IOErrorEvent;
|
||||
import haxe.ui.containers.dialogs.Dialog.DialogButton;
|
||||
import haxe.ui.containers.dialogs.Dialogs;
|
||||
import haxe.ui.containers.dialogs.Dialogs.SelectedFileInfo;
|
||||
import haxe.ui.containers.dialogs.Dialogs.FileDialogExtensionInfo;
|
||||
|
||||
/**
|
||||
* Utilities for reading and writing files on various platforms.
|
||||
|
@ -17,32 +21,81 @@ class FileUtil
|
|||
public static final FILE_FILTER_FNFC:FileFilter = new FileFilter("Friday Night Funkin' Chart (.fnfc)", "*.fnfc");
|
||||
public static final FILE_FILTER_ZIP:FileFilter = new FileFilter("ZIP Archive (.zip)", "*.zip");
|
||||
|
||||
public static final FILE_EXTENSION_INFO_FNFC:FileDialogExtensionInfo =
|
||||
{
|
||||
extension: 'fnfc',
|
||||
label: 'Friday Night Funkin\' Chart',
|
||||
};
|
||||
public static final FILE_EXTENSION_INFO_ZIP:FileDialogExtensionInfo =
|
||||
{
|
||||
extension: 'zip',
|
||||
label: 'ZIP Archive',
|
||||
};
|
||||
|
||||
/**
|
||||
* Browses for a single file, then calls `onSelect(path)` when a path chosen.
|
||||
* Note that on HTML5 this will immediately fail, you should call `openFile(onOpen:Resource->Void)` instead.
|
||||
* Browses for a single file, then calls `onSelect(fileInfo)` when a file is selected.
|
||||
* Powered by HaxeUI, so it works on all platforms.
|
||||
* File contents will be binary, not String.
|
||||
*
|
||||
* @param typeFilter Filters what kinds of files can be selected.
|
||||
* @return Whether the file dialog was opened successfully.
|
||||
* @param typeFilter
|
||||
* @param onSelect A callback that provides a `SelectedFileInfo` object when a file is selected.
|
||||
* @param onCancel A callback that is called when the user closes the dialog without selecting a file.
|
||||
*/
|
||||
public static function browseForFile(?typeFilter:Array<FileFilter>, ?onSelect:String->Void, ?onCancel:Void->Void, ?defaultPath:String,
|
||||
?dialogTitle:String):Bool
|
||||
public static function browseForBinaryFile(dialogTitle:String, ?typeFilter:Array<FileDialogExtensionInfo>, ?onSelect:SelectedFileInfo->Void,
|
||||
?onCancel:Void->Void)
|
||||
{
|
||||
#if desktop
|
||||
var filter:String = convertTypeFilter(typeFilter);
|
||||
var onComplete = function(button, selectedFiles) {
|
||||
if (button == DialogButton.OK && selectedFiles.length > 0)
|
||||
{
|
||||
onSelect(selectedFiles[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
onCancel();
|
||||
}
|
||||
};
|
||||
|
||||
var fileDialog:FileDialog = new FileDialog();
|
||||
if (onSelect != null) fileDialog.onSelect.add(onSelect);
|
||||
if (onCancel != null) fileDialog.onCancel.add(onCancel);
|
||||
Dialogs.openFile(onComplete,
|
||||
{
|
||||
readContents: true,
|
||||
readAsBinary: true, // Binary
|
||||
multiple: false,
|
||||
extensions: typeFilter ?? [],
|
||||
title: dialogTitle,
|
||||
});
|
||||
}
|
||||
|
||||
fileDialog.browse(OPEN, filter, defaultPath, dialogTitle);
|
||||
return true;
|
||||
#elseif html5
|
||||
onCancel();
|
||||
return false;
|
||||
#else
|
||||
onCancel();
|
||||
return false;
|
||||
#end
|
||||
/**
|
||||
* Browses for a single file, then calls `onSelect(fileInfo)` when a file is selected.
|
||||
* Powered by HaxeUI, so it works on all platforms.
|
||||
* File contents will be a String, not binary.
|
||||
*
|
||||
* @param typeFilter
|
||||
* @param onSelect A callback that provides a `SelectedFileInfo` object when a file is selected.
|
||||
* @param onCancel A callback that is called when the user closes the dialog without selecting a file.
|
||||
*/
|
||||
public static function browseForTextFile(dialogTitle:String, ?typeFilter:Array<FileDialogExtensionInfo>, ?onSelect:SelectedFileInfo->Void,
|
||||
?onCancel:Void->Void)
|
||||
{
|
||||
var onComplete = function(button, selectedFiles) {
|
||||
if (button == DialogButton.OK && selectedFiles.length > 0)
|
||||
{
|
||||
onSelect(selectedFiles[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
onCancel();
|
||||
}
|
||||
};
|
||||
|
||||
Dialogs.openFile(onComplete,
|
||||
{
|
||||
readContents: true,
|
||||
readAsBinary: false, // Text
|
||||
multiple: false,
|
||||
extensions: typeFilter ?? [],
|
||||
title: dialogTitle,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,11 +110,9 @@ class FileUtil
|
|||
{
|
||||
#if desktop
|
||||
var filter:String = convertTypeFilter(typeFilter);
|
||||
|
||||
var fileDialog:FileDialog = new FileDialog();
|
||||
if (onSelect != null) fileDialog.onSelect.add(onSelect);
|
||||
if (onCancel != null) fileDialog.onCancel.add(onCancel);
|
||||
|
||||
fileDialog.browse(OPEN_DIRECTORY, filter, defaultPath, dialogTitle);
|
||||
return true;
|
||||
#elseif html5
|
||||
|
@ -84,11 +135,9 @@ class FileUtil
|
|||
{
|
||||
#if desktop
|
||||
var filter:String = convertTypeFilter(typeFilter);
|
||||
|
||||
var fileDialog:FileDialog = new FileDialog();
|
||||
if (onSelect != null) fileDialog.onSelectMultiple.add(onSelect);
|
||||
if (onCancel != null) fileDialog.onCancel.add(onCancel);
|
||||
|
||||
fileDialog.browse(OPEN_MULTIPLE, filter, defaultPath, dialogTitle);
|
||||
return true;
|
||||
#elseif html5
|
||||
|
@ -112,11 +161,9 @@ class FileUtil
|
|||
{
|
||||
#if desktop
|
||||
var filter:String = convertTypeFilter(typeFilter);
|
||||
|
||||
var fileDialog:FileDialog = new FileDialog();
|
||||
if (onSelect != null) fileDialog.onSelect.add(onSelect);
|
||||
if (onCancel != null) fileDialog.onCancel.add(onCancel);
|
||||
|
||||
fileDialog.browse(SAVE, filter, defaultPath, dialogTitle);
|
||||
return true;
|
||||
#elseif html5
|
||||
|
@ -128,48 +175,6 @@ class FileUtil
|
|||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
* Browses for a single file location, then reads it and passes it to `onOpen(resource:haxe.io.Bytes)`.
|
||||
* Works great on desktop and HTML5.
|
||||
*
|
||||
* @param typeFilter TODO What does this do?
|
||||
* @return Whether the file dialog was opened successfully.
|
||||
*/
|
||||
public static function openFile(?typeFilter:Array<FileFilter>, ?onOpen:Bytes->Void, ?onCancel:Void->Void, ?defaultPath:String, ?dialogTitle:String):Bool
|
||||
{
|
||||
#if desktop
|
||||
var filter:String = convertTypeFilter(typeFilter);
|
||||
|
||||
var fileDialog:FileDialog = new FileDialog();
|
||||
if (onOpen != null) fileDialog.onOpen.add(onOpen);
|
||||
if (onCancel != null) fileDialog.onCancel.add(onCancel);
|
||||
|
||||
fileDialog.open(filter, defaultPath, dialogTitle);
|
||||
return true;
|
||||
#elseif html5
|
||||
var onFileLoaded:Event->Void = function(event) {
|
||||
var loadedFileRef:FileReference = event.target;
|
||||
trace('Loaded file: ' + loadedFileRef.name);
|
||||
onOpen(loadedFileRef.data);
|
||||
}
|
||||
|
||||
var onFileSelected:Event->Void = function(event) {
|
||||
var selectedFileRef:FileReference = event.target;
|
||||
trace('Selected file: ' + selectedFileRef.name);
|
||||
selectedFileRef.addEventListener(Event.COMPLETE, onFileLoaded);
|
||||
selectedFileRef.load();
|
||||
}
|
||||
|
||||
var fileRef:FileReference = new FileReference();
|
||||
fileRef.addEventListener(Event.SELECT, onFileSelected);
|
||||
fileRef.browse(typeFilter);
|
||||
return true;
|
||||
#else
|
||||
onCancel();
|
||||
return false;
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
* Browses for a single file location, then writes the provided `haxe.io.Bytes` data and calls `onSave(path)` when done.
|
||||
* Works great on desktop and HTML5.
|
||||
|
@ -181,20 +186,16 @@ class FileUtil
|
|||
{
|
||||
#if desktop
|
||||
var filter:String = convertTypeFilter(typeFilter);
|
||||
|
||||
var fileDialog:FileDialog = new FileDialog();
|
||||
if (onSave != null) fileDialog.onSave.add(onSave);
|
||||
if (onCancel != null) fileDialog.onCancel.add(onCancel);
|
||||
|
||||
fileDialog.save(data, filter, defaultFileName, dialogTitle);
|
||||
return true;
|
||||
#elseif html5
|
||||
var filter:String = defaultFileName != null ? Path.extension(defaultFileName) : null;
|
||||
|
||||
var fileDialog:FileDialog = new FileDialog();
|
||||
if (onSave != null) fileDialog.onSave.add(onSave);
|
||||
if (onCancel != null) fileDialog.onCancel.add(onCancel);
|
||||
|
||||
fileDialog.save(data, filter, defaultFileName, dialogTitle);
|
||||
return true;
|
||||
#else
|
||||
|
@ -241,17 +242,14 @@ class FileUtil
|
|||
}
|
||||
onSaveAll(paths);
|
||||
}
|
||||
|
||||
trace('Browsing for directory to save individual files to...');
|
||||
#if mac
|
||||
defaultPath = null;
|
||||
#end
|
||||
browseForDirectory(null, onSelectDir, onCancel, defaultPath, 'Choose directory to save all files to...');
|
||||
|
||||
return true;
|
||||
#elseif html5
|
||||
saveFilesAsZIP(resources, onSaveAll, onCancel, defaultPath, force);
|
||||
|
||||
return true;
|
||||
#else
|
||||
onCancel();
|
||||
|
@ -266,15 +264,12 @@ class FileUtil
|
|||
{
|
||||
// Create a ZIP file.
|
||||
var zipBytes:Bytes = createZIPFromEntries(resources);
|
||||
|
||||
var onSave:String->Void = function(path:String) {
|
||||
trace('Saved ${resources.length} files to ZIP at "$path".');
|
||||
if (onSave != null) onSave([path]);
|
||||
};
|
||||
|
||||
// Prompt the user to save the ZIP file.
|
||||
saveFile(zipBytes, [FILE_FILTER_ZIP], onSave, onCancel, defaultPath, 'Save files as ZIP...');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -286,15 +281,12 @@ class FileUtil
|
|||
{
|
||||
// Create a ZIP file.
|
||||
var zipBytes:Bytes = createZIPFromEntries(resources);
|
||||
|
||||
var onSave:String->Void = function(path:String) {
|
||||
trace('Saved FNF file to "$path"');
|
||||
if (onSave != null) onSave([path]);
|
||||
};
|
||||
|
||||
// Prompt the user to save the ZIP file.
|
||||
saveFile(zipBytes, [FILE_FILTER_FNFC], onSave, onCancel, defaultPath, 'Save chart as FNFC...');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -309,10 +301,8 @@ class FileUtil
|
|||
#if desktop
|
||||
// Create a ZIP file.
|
||||
var zipBytes:Bytes = createZIPFromEntries(resources);
|
||||
|
||||
// Write the ZIP.
|
||||
writeBytesToPath(path, zipBytes, mode);
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
|
@ -371,7 +361,6 @@ class FileUtil
|
|||
public static function browseFileReference(callback:FileReference->Void)
|
||||
{
|
||||
var file = new FileReference();
|
||||
|
||||
file.addEventListener(Event.SELECT, function(e) {
|
||||
var selectedFileRef:FileReference = e.target;
|
||||
trace('Selected file: ' + selectedFileRef.name);
|
||||
|
@ -382,7 +371,6 @@ class FileUtil
|
|||
});
|
||||
selectedFileRef.load();
|
||||
});
|
||||
|
||||
file.browse();
|
||||
}
|
||||
|
||||
|
@ -439,7 +427,6 @@ class FileUtil
|
|||
{
|
||||
#if sys
|
||||
createDirIfNotExists(Path.directory(path));
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case Force:
|
||||
|
@ -482,7 +469,6 @@ class FileUtil
|
|||
{
|
||||
#if sys
|
||||
createDirIfNotExists(Path.directory(path));
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case Force:
|
||||
|
@ -557,19 +543,15 @@ class FileUtil
|
|||
public static function getTempDir():String
|
||||
{
|
||||
if (tempDir != null) return tempDir;
|
||||
|
||||
#if sys
|
||||
#if windows
|
||||
var path:String = null;
|
||||
|
||||
for (envName in TEMP_ENV_VARS)
|
||||
{
|
||||
path = Sys.getEnv(envName);
|
||||
|
||||
if (path == '') path = null;
|
||||
if (path != null) break;
|
||||
}
|
||||
|
||||
tempDir = Path.join([path, 'funkin/']);
|
||||
return tempDir;
|
||||
#else
|
||||
|
@ -590,10 +572,8 @@ class FileUtil
|
|||
public static function createZIPFromEntries(entries:Array<Entry>):Bytes
|
||||
{
|
||||
var o:haxe.io.BytesOutput = new haxe.io.BytesOutput();
|
||||
|
||||
var zipWriter:haxe.zip.Writer = new haxe.zip.Writer(o);
|
||||
zipWriter.write(entries.list());
|
||||
|
||||
return o.getBytes();
|
||||
}
|
||||
|
||||
|
@ -601,10 +581,8 @@ class FileUtil
|
|||
{
|
||||
trace('TEST: ' + input.length);
|
||||
trace(input.sub(0, 30).toHex());
|
||||
|
||||
var bytesInput = new haxe.io.BytesInput(input);
|
||||
var zippedEntries = haxe.zip.Reader.readZip(bytesInput);
|
||||
|
||||
var results:Array<Entry> = [];
|
||||
for (entry in zippedEntries)
|
||||
{
|
||||
|
@ -637,7 +615,6 @@ class FileUtil
|
|||
public static function makeZIPEntry(name:String, content:String):Entry
|
||||
{
|
||||
var data:Bytes = haxe.io.Bytes.ofString(content, UTF8);
|
||||
|
||||
return makeZIPEntryFromBytes(name, data);
|
||||
}
|
||||
|
||||
|
@ -653,12 +630,9 @@ class FileUtil
|
|||
return {
|
||||
fileName: name,
|
||||
fileSize: data.length,
|
||||
|
||||
data: data,
|
||||
dataSize: data.length,
|
||||
|
||||
compressed: false,
|
||||
|
||||
fileTime: Date.now(),
|
||||
crc32: null,
|
||||
extraFields: null,
|
||||
|
@ -677,7 +651,6 @@ class FileUtil
|
|||
}
|
||||
filter = filters.join(';');
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
|
|
3
source/haxe/ui/backend/flixel/UIStateBase.hx
Normal file
3
source/haxe/ui/backend/flixel/UIStateBase.hx
Normal file
|
@ -0,0 +1,3 @@
|
|||
package haxe.ui.backend.flixel;
|
||||
|
||||
typedef UIStateBase = funkin.ui.MusicBeatState;
|
3
source/haxe/ui/backend/flixel/UISubStateBase.hx
Normal file
3
source/haxe/ui/backend/flixel/UISubStateBase.hx
Normal file
|
@ -0,0 +1,3 @@
|
|||
package haxe.ui.backend.flixel;
|
||||
|
||||
typedef UISubStateBase = funkin.ui.MusicBeatSubState;
|
Loading…
Reference in a new issue