mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2025-09-04 20:58:03 +00:00
Compare commits
20 commits
a9301760f0
...
37df6bac5e
Author | SHA1 | Date | |
---|---|---|---|
|
37df6bac5e | ||
|
d0f0974d1e | ||
|
369b936056 | ||
|
c40e1e3958 | ||
|
0ade24bac4 | ||
|
7370ef3249 | ||
|
b2f162a8ae | ||
|
11fa9b4050 | ||
|
89bd7a3f43 | ||
|
942fb5efc9 | ||
|
c2eff142bd | ||
|
2784fa18c0 | ||
|
ad07fddf89 | ||
|
4768eedd5b | ||
|
f1c3e99a11 | ||
|
eefe8927c4 | ||
|
3ff4f14510 | ||
|
955b0db542 | ||
|
d2df4f0832 | ||
|
923c54bbbc |
2
.github/ISSUE_TEMPLATE/bug.yml
vendored
2
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
@ -59,7 +59,7 @@ body:
|
||||||
attributes:
|
attributes:
|
||||||
label: Version
|
label: Version
|
||||||
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
||||||
placeholder: ex. 0.7.3
|
placeholder: ex. 0.7.4
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
|
2
.github/ISSUE_TEMPLATE/charting.yml
vendored
2
.github/ISSUE_TEMPLATE/charting.yml
vendored
|
@ -36,7 +36,7 @@ body:
|
||||||
attributes:
|
attributes:
|
||||||
label: Version
|
label: Version
|
||||||
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
||||||
placeholder: ex. 0.7.3
|
placeholder: ex. 0.7.4
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
|
2
.github/ISSUE_TEMPLATE/compiling.yml
vendored
2
.github/ISSUE_TEMPLATE/compiling.yml
vendored
|
@ -36,7 +36,7 @@ body:
|
||||||
attributes:
|
attributes:
|
||||||
label: Version
|
label: Version
|
||||||
description: Which version are you compiling? The game version is in the bottom left corner of the main menu or in the project.hxp file.
|
description: Which version are you compiling? The game version is in the bottom left corner of the main menu or in the project.hxp file.
|
||||||
placeholder: ex. 0.7.3
|
placeholder: ex. 0.7.4
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
|
2
.github/ISSUE_TEMPLATE/crash.yml
vendored
2
.github/ISSUE_TEMPLATE/crash.yml
vendored
|
@ -60,7 +60,7 @@ body:
|
||||||
attributes:
|
attributes:
|
||||||
label: Version
|
label: Version
|
||||||
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
||||||
placeholder: ex. 0.7.3
|
placeholder: ex. 0.7.4
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ This section provides guidelines to follow when [opening an issue](https://githu
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
Make sure you're playing:
|
Make sure you're playing:
|
||||||
- the latest version of the game (currently v0.7.3)
|
- the latest version of the game (currently v0.7.4)
|
||||||
- without any mods
|
- without any mods
|
||||||
- on [Newgrounds](https://www.newgrounds.com/portal/view/770371) or downloaded from [itch.io](https://ninja-muffin24.itch.io/funkin)
|
- on [Newgrounds](https://www.newgrounds.com/portal/view/770371) or downloaded from [itch.io](https://ninja-muffin24.itch.io/funkin)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
"name": "EliteMasterEric"
|
"name": "EliteMasterEric"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"api_version": "0.5.0",
|
"api_version": "0.7.0",
|
||||||
"mod_version": "1.0.0",
|
"mod_version": "1.0.0",
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
"name": "EliteMasterEric"
|
"name": "EliteMasterEric"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"api_version": "0.5.0",
|
"api_version": "0.7.0",
|
||||||
"mod_version": "1.0.0",
|
"mod_version": "1.0.0",
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
}
|
}
|
||||||
|
|
156
source/funkin/api/newgrounds/NGSaveSlot.hx
Normal file
156
source/funkin/api/newgrounds/NGSaveSlot.hx
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
package funkin.api.newgrounds;
|
||||||
|
|
||||||
|
#if FEATURE_NEWGROUNDS
|
||||||
|
import io.newgrounds.utils.SaveSlotList;
|
||||||
|
import io.newgrounds.objects.SaveSlot;
|
||||||
|
import io.newgrounds.Call.CallError;
|
||||||
|
import io.newgrounds.objects.events.Outcome;
|
||||||
|
import funkin.save.Save;
|
||||||
|
|
||||||
|
@:nullSafety
|
||||||
|
@:access(funkin.save.Save)
|
||||||
|
class NGSaveSlot
|
||||||
|
{
|
||||||
|
public static var instance(get, never):NGSaveSlot;
|
||||||
|
static var _instance:Null<NGSaveSlot> = null;
|
||||||
|
|
||||||
|
static function get_instance():NGSaveSlot
|
||||||
|
{
|
||||||
|
if (_instance == null)
|
||||||
|
{
|
||||||
|
return loadInstance();
|
||||||
|
}
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadInstance():NGSaveSlot
|
||||||
|
{
|
||||||
|
var loadedSave:NGSaveSlot = loadSlot(Save.BASE_SAVE_SLOT);
|
||||||
|
if (_instance == null) _instance = loadedSave;
|
||||||
|
|
||||||
|
return loadedSave;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function loadSlot(slot:Int):NGSaveSlot
|
||||||
|
{
|
||||||
|
trace('[NEWGROUNDS] Getting save slot from ID $slot');
|
||||||
|
|
||||||
|
var saveSlot:Null<SaveSlot> = NewgroundsClient.instance.saveSlots?.getById(slot);
|
||||||
|
|
||||||
|
var saveSlotObj:NGSaveSlot = new NGSaveSlot(saveSlot);
|
||||||
|
return saveSlotObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public var ngSaveSlot:Null<SaveSlot> = null;
|
||||||
|
|
||||||
|
public function new(?ngSaveSlot:Null<SaveSlot>)
|
||||||
|
{
|
||||||
|
this.ngSaveSlot = ngSaveSlot;
|
||||||
|
|
||||||
|
#if FLX_DEBUG
|
||||||
|
FlxG.console.registerClass(NGSaveSlot);
|
||||||
|
FlxG.console.registerClass(Save);
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves `data` to the newgrounds save slot.
|
||||||
|
* @param data The raw save data.
|
||||||
|
*/
|
||||||
|
public function save(data:RawSaveData):Void
|
||||||
|
{
|
||||||
|
var encodedData:String = haxe.Serializer.run(data);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ngSaveSlot?.save(encodedData, function(outcome:Outcome<CallError>) {
|
||||||
|
switch (outcome)
|
||||||
|
{
|
||||||
|
case SUCCESS:
|
||||||
|
trace('[NEWGROUNDS] Successfully saved save data to save slot!');
|
||||||
|
case FAIL(error):
|
||||||
|
trace('[NEWGROUNDS] Failed to save data to save slot!');
|
||||||
|
trace(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (error:String)
|
||||||
|
{
|
||||||
|
trace('[NEWGROUNDS] Failed to save data to save slot!');
|
||||||
|
trace(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load(?onComplete:Null<Dynamic->Void>, ?onError:Null<CallError->Void>):Void
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ngSaveSlot?.load(function(outcome:SaveSlotOutcome):Void {
|
||||||
|
switch (outcome)
|
||||||
|
{
|
||||||
|
case SUCCESS(value):
|
||||||
|
trace('[NEWGROUNDS] Loaded save slot with the ID of ${ngSaveSlot?.id}!');
|
||||||
|
#if FEATURE_DEBUG_FUNCTIONS
|
||||||
|
trace('Save Slot Data:');
|
||||||
|
trace(value);
|
||||||
|
#end
|
||||||
|
|
||||||
|
if (onComplete != null && value != null)
|
||||||
|
{
|
||||||
|
var decodedData:Dynamic = haxe.Unserializer.run(value);
|
||||||
|
onComplete(decodedData);
|
||||||
|
}
|
||||||
|
case FAIL(error):
|
||||||
|
trace('[NEWGROUNDS] Failed to load save slot with the ID of ${ngSaveSlot?.id}!');
|
||||||
|
trace(error);
|
||||||
|
|
||||||
|
if (onError != null)
|
||||||
|
{
|
||||||
|
onError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (error:String)
|
||||||
|
{
|
||||||
|
trace('[NEWGROUNDS] Failed to load save slot with the ID of ${ngSaveSlot?.id}!');
|
||||||
|
trace(error);
|
||||||
|
|
||||||
|
if (onError != null)
|
||||||
|
{
|
||||||
|
onError(RESPONSE({message: error, code: 500}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clear():Void
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ngSaveSlot?.clear(function(outcome:Outcome<CallError>) {
|
||||||
|
switch (outcome)
|
||||||
|
{
|
||||||
|
case SUCCESS:
|
||||||
|
trace('[NEWGROUNDS] Successfully cleared save slot!');
|
||||||
|
case FAIL(error):
|
||||||
|
trace('[NEWGROUNDS] Failed to clear save slot!');
|
||||||
|
trace(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (error:String)
|
||||||
|
{
|
||||||
|
trace('[NEWGROUNDS] Failed to clear save slot!');
|
||||||
|
trace(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkSlot():Void
|
||||||
|
{
|
||||||
|
trace('[NEWGROUNDS] Checking save slot with the ID of ${ngSaveSlot?.id}...');
|
||||||
|
|
||||||
|
trace(' Is null? ${ngSaveSlot == null}');
|
||||||
|
trace(' Is empty? ${ngSaveSlot?.isEmpty() ?? false}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#end
|
|
@ -10,6 +10,7 @@ import io.newgrounds.NGLite.LoginOutcome;
|
||||||
import io.newgrounds.NGLite.LoginFail;
|
import io.newgrounds.NGLite.LoginFail;
|
||||||
import io.newgrounds.objects.events.Outcome;
|
import io.newgrounds.objects.events.Outcome;
|
||||||
import io.newgrounds.utils.MedalList;
|
import io.newgrounds.utils.MedalList;
|
||||||
|
import io.newgrounds.utils.SaveSlotList;
|
||||||
import io.newgrounds.utils.ScoreBoardList;
|
import io.newgrounds.utils.ScoreBoardList;
|
||||||
import io.newgrounds.objects.User;
|
import io.newgrounds.objects.User;
|
||||||
|
|
||||||
|
@ -29,6 +30,7 @@ class NewgroundsClient
|
||||||
public var user(get, never):Null<User>;
|
public var user(get, never):Null<User>;
|
||||||
public var medals(get, never):Null<MedalList>;
|
public var medals(get, never):Null<MedalList>;
|
||||||
public var leaderboards(get, never):Null<ScoreBoardList>;
|
public var leaderboards(get, never):Null<ScoreBoardList>;
|
||||||
|
public var saveSlots(get, never):Null<SaveSlotList>;
|
||||||
|
|
||||||
private function new()
|
private function new()
|
||||||
{
|
{
|
||||||
|
@ -236,6 +238,8 @@ class NewgroundsClient
|
||||||
|
|
||||||
trace('[NEWGROUNDS] Submitting leaderboard request...');
|
trace('[NEWGROUNDS] Submitting leaderboard request...');
|
||||||
NG.core.scoreBoards.loadList(onFetchedLeaderboards);
|
NG.core.scoreBoards.loadList(onFetchedLeaderboards);
|
||||||
|
trace('[NEWGROUNDS] Submitting save slot request...');
|
||||||
|
NG.core.saveSlots.loadList(onFetchedSaveSlots);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLoginFailed(result:LoginFail):Void
|
function onLoginFailed(result:LoginFail):Void
|
||||||
|
@ -301,6 +305,13 @@ class NewgroundsClient
|
||||||
// trace(funkin.api.newgrounds.Leaderboards.listLeaderboardData());
|
// trace(funkin.api.newgrounds.Leaderboards.listLeaderboardData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onFetchedSaveSlots(outcome:Outcome<CallError>):Void
|
||||||
|
{
|
||||||
|
trace('[NEWGROUNDS] Fetched save slots!');
|
||||||
|
|
||||||
|
NGSaveSlot.instance.checkSlot();
|
||||||
|
}
|
||||||
|
|
||||||
function get_user():Null<User>
|
function get_user():Null<User>
|
||||||
{
|
{
|
||||||
if (NG.core == null || !this.isLoggedIn()) return null;
|
if (NG.core == null || !this.isLoggedIn()) return null;
|
||||||
|
@ -319,6 +330,12 @@ class NewgroundsClient
|
||||||
return NG.core.scoreBoards;
|
return NG.core.scoreBoards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get_saveSlots():Null<SaveSlotList>
|
||||||
|
{
|
||||||
|
if (NG.core == null || !this.isLoggedIn()) return null;
|
||||||
|
return NG.core.saveSlots;
|
||||||
|
}
|
||||||
|
|
||||||
static function getSessionId():Null<String>
|
static function getSessionId():Null<String>
|
||||||
{
|
{
|
||||||
#if js
|
#if js
|
||||||
|
|
|
@ -1356,6 +1356,45 @@ class Save
|
||||||
{
|
{
|
||||||
FileUtil.saveFile(haxe.io.Bytes.ofString(this.serialize()), [FileUtil.FILE_FILTER_JSON], null, null, './save.json', 'Write save data as JSON...');
|
FileUtil.saveFile(haxe.io.Bytes.ofString(this.serialize()), [FileUtil.FILE_FILTER_JSON], null, null, './save.json', 'Write save data as JSON...');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FEATURE_NEWGROUNDS
|
||||||
|
public static function saveToNewgrounds():Void
|
||||||
|
{
|
||||||
|
if (_instance == null) return;
|
||||||
|
trace('[SAVE] Saving Save Data to Newgrounds...');
|
||||||
|
funkin.api.newgrounds.NGSaveSlot.instance.save(_instance.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadFromNewgrounds(onFinish:Void->Void):Void
|
||||||
|
{
|
||||||
|
trace('[SAVE] Loading Save Data from Newgrounds...');
|
||||||
|
funkin.api.newgrounds.NGSaveSlot.instance.load(function(data:Dynamic) {
|
||||||
|
FlxG.save.bind('$SAVE_NAME${BASE_SAVE_SLOT}', SAVE_PATH);
|
||||||
|
|
||||||
|
if (FlxG.save.status != EMPTY)
|
||||||
|
{
|
||||||
|
// best i can do in case the NG file is corrupted or something along those lines
|
||||||
|
var backupSlot:Int = Save.archiveBadSaveData(FlxG.save.data);
|
||||||
|
trace('[SAVE] Backed up current save data in case of emergency to $backupSlot!');
|
||||||
|
}
|
||||||
|
|
||||||
|
FlxG.save.erase();
|
||||||
|
FlxG.save.bind('$SAVE_NAME${BASE_SAVE_SLOT}', SAVE_PATH); // forces regeneration of the file as erase deletes it
|
||||||
|
|
||||||
|
var gameSave = SaveDataMigrator.migrate(data);
|
||||||
|
FlxG.save.mergeData(gameSave.data, true);
|
||||||
|
_instance = gameSave;
|
||||||
|
onFinish();
|
||||||
|
}, function(error:io.newgrounds.Call.CallError) {
|
||||||
|
var errorMsg:String = io.newgrounds.Call.CallErrorTools.toString(error);
|
||||||
|
|
||||||
|
var msg = 'There was an error loading your save data from Newgrounds.';
|
||||||
|
msg += '\n${errorMsg}';
|
||||||
|
msg += '\nAre you sure you are connected to the internet?';
|
||||||
|
lime.app.Application.current.window.alert(msg, "Newgrounds Save Slot Failure");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -48,7 +48,9 @@ class ChartEditorUploadChartDialog extends ChartEditorBaseDialog
|
||||||
|
|
||||||
for (dropTarget in dialog.dropHandlers)
|
for (dropTarget in dialog.dropHandlers)
|
||||||
{
|
{
|
||||||
|
#if FEATURE_FILE_DROP
|
||||||
state.addDropHandler(dropTarget);
|
state.addDropHandler(dropTarget);
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.showDialog(modal ?? true);
|
dialog.showDialog(modal ?? true);
|
||||||
|
|
|
@ -78,23 +78,30 @@ class ChartEditorUploadVocalsDialog extends ChartEditorBaseDialog
|
||||||
this.hasClearedVocals = true;
|
this.hasClearedVocals = true;
|
||||||
// Tell the user the load was successful.
|
// Tell the user the load was successful.
|
||||||
chartEditorState.success('Loaded Vocals', 'Loaded vocals for $charName (${path.file}.${path.ext}), variation ${chartEditorState.selectedVariation}');
|
chartEditorState.success('Loaded Vocals', 'Loaded vocals for $charName (${path.file}.${path.ext}), variation ${chartEditorState.selectedVariation}');
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
vocalsEntry.vocalsEntryLabel.text = 'Voices for $charName (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
|
vocalsEntry.vocalsEntryLabel.text = 'Voices for $charName (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
|
||||||
#else
|
#else
|
||||||
vocalsEntry.vocalsEntryLabel.text = 'Voices for $charName (click to browse)\n${path.file}.${path.ext}';
|
vocalsEntry.vocalsEntryLabel.text = 'Voices for $charName (click to browse)\n${path.file}.${path.ext}';
|
||||||
#end
|
#end
|
||||||
|
|
||||||
dialogNoVocals.hidden = true;
|
dialogNoVocals.hidden = true;
|
||||||
chartEditorState.removeDropHandler(dropHandler);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
var message:String = if (!ChartEditorState.SUPPORTED_MUSIC_FORMATS.contains(path.ext ?? ''))
|
||||||
|
{
|
||||||
|
'File format (${path.ext}) not supported for vocal track (${path.file}.${path.ext})';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
'Failed to load vocal track (${path.file}.${path.ext}) for variation (${chartEditorState.selectedVariation})';
|
||||||
|
}
|
||||||
|
|
||||||
trace('Failed to load vocal track (${path.file}.${path.ext})');
|
trace('Failed to load vocal track (${path.file}.${path.ext})');
|
||||||
|
|
||||||
chartEditorState.error('Failed to Load Vocals',
|
chartEditorState.error('Failed to Load Vocals', message);
|
||||||
'Failed to load vocal track (${path.file}.${path.ext}) for variation (${chartEditorState.selectedVariation})');
|
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
vocalsEntry.vocalsEntryLabel.text = 'Drag and drop vocals for $charName here, or click to browse.';
|
vocalsEntry.vocalsEntryLabel.text = 'Drag and drop vocals for $charName here, or click to browse.';
|
||||||
#else
|
#else
|
||||||
vocalsEntry.vocalsEntryLabel.text = 'Click to browse for vocals for $charName.';
|
vocalsEntry.vocalsEntryLabel.text = 'Click to browse for vocals for $charName.';
|
||||||
|
@ -116,7 +123,7 @@ class ChartEditorUploadVocalsDialog extends ChartEditorBaseDialog
|
||||||
chartEditorState.success('Loaded Vocals',
|
chartEditorState.success('Loaded Vocals',
|
||||||
'Loaded vocals for $charName (${selectedFile.name}), variation ${chartEditorState.selectedVariation}');
|
'Loaded vocals for $charName (${selectedFile.name}), variation ${chartEditorState.selectedVariation}');
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
vocalsEntry.vocalsEntryLabel.text = 'Voices for $charName (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}';
|
vocalsEntry.vocalsEntryLabel.text = 'Voices for $charName (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}';
|
||||||
#else
|
#else
|
||||||
vocalsEntry.vocalsEntryLabel.text = 'Voices for $charName (click to browse)\n${selectedFile.name}';
|
vocalsEntry.vocalsEntryLabel.text = 'Voices for $charName (click to browse)\n${selectedFile.name}';
|
||||||
|
@ -131,7 +138,7 @@ class ChartEditorUploadVocalsDialog extends ChartEditorBaseDialog
|
||||||
chartEditorState.error('Failed to Load Vocals',
|
chartEditorState.error('Failed to Load Vocals',
|
||||||
'Failed to load vocal track (${selectedFile.name}) for variation (${chartEditorState.selectedVariation})');
|
'Failed to load vocal track (${selectedFile.name}) for variation (${chartEditorState.selectedVariation})');
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
vocalsEntry.vocalsEntryLabel.text = 'Drag and drop vocals for $charName here, or click to browse.';
|
vocalsEntry.vocalsEntryLabel.text = 'Drag and drop vocals for $charName here, or click to browse.';
|
||||||
#else
|
#else
|
||||||
vocalsEntry.vocalsEntryLabel.text = 'Click to browse for vocals for $charName.';
|
vocalsEntry.vocalsEntryLabel.text = 'Click to browse for vocals for $charName.';
|
||||||
|
@ -144,9 +151,8 @@ class ChartEditorUploadVocalsDialog extends ChartEditorBaseDialog
|
||||||
dropHandler.handler = onDropFile;
|
dropHandler.handler = onDropFile;
|
||||||
|
|
||||||
// onDropFile
|
// onDropFile
|
||||||
#if FILE_DROP_SUPPORTED
|
|
||||||
dropHandlers.push(dropHandler);
|
dropHandlers.push(dropHandler);
|
||||||
#end
|
|
||||||
|
|
||||||
vocalContainer.addComponent(vocalsEntry);
|
vocalContainer.addComponent(vocalsEntry);
|
||||||
}
|
}
|
||||||
|
@ -162,7 +168,9 @@ class ChartEditorUploadVocalsDialog extends ChartEditorBaseDialog
|
||||||
|
|
||||||
for (dropTarget in dialog.dropHandlers)
|
for (dropTarget in dialog.dropHandlers)
|
||||||
{
|
{
|
||||||
|
#if FEATURE_FILE_DROP
|
||||||
state.addDropHandler(dropTarget);
|
state.addDropHandler(dropTarget);
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.showDialog(modal ?? true);
|
dialog.showDialog(modal ?? true);
|
||||||
|
@ -289,7 +297,7 @@ class ChartEditorUploadVocalsEntry extends Box
|
||||||
|
|
||||||
this.charName = charName;
|
this.charName = charName;
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
vocalsEntryLabel.text = 'Drag and drop vocals for $charName here, or click to browse.';
|
vocalsEntryLabel.text = 'Drag and drop vocals for $charName here, or click to browse.';
|
||||||
#else
|
#else
|
||||||
vocalsEntryLabel.text = 'Click to browse for vocals for $charName.';
|
vocalsEntryLabel.text = 'Click to browse for vocals for $charName.';
|
||||||
|
|
|
@ -476,10 +476,6 @@ class ChartEditorDialogHandler
|
||||||
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
||||||
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Upload Instrumental dialog';
|
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Upload Instrumental dialog';
|
||||||
|
|
||||||
buttonCancel.onClick = function(_) {
|
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
var instrumentalBox:Null<Box> = dialog.findComponent('instrumentalBox', Box);
|
var instrumentalBox:Null<Box> = dialog.findComponent('instrumentalBox', Box);
|
||||||
if (instrumentalBox == null) throw 'Could not locate instrumentalBox in Upload Instrumental dialog';
|
if (instrumentalBox == null) throw 'Could not locate instrumentalBox in Upload Instrumental dialog';
|
||||||
|
|
||||||
|
@ -493,10 +489,15 @@ class ChartEditorDialogHandler
|
||||||
Cursor.cursorMode = Default;
|
Cursor.cursorMode = Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
var instId:String = state.currentInstrumentalId;
|
|
||||||
|
|
||||||
var dropHandler:DialogDropTarget = {component: instrumentalBox, handler: null};
|
var dropHandler:DialogDropTarget = {component: instrumentalBox, handler: null};
|
||||||
|
|
||||||
|
buttonCancel.onClick = function(_) {
|
||||||
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
|
state.removeDropHandler(dropHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
var instId:String = state.currentInstrumentalId;
|
||||||
|
|
||||||
instrumentalBox.onClick = function(_) {
|
instrumentalBox.onClick = function(_) {
|
||||||
Dialogs.openBinaryFile('Open Instrumental', [
|
Dialogs.openBinaryFile('Open Instrumental', [
|
||||||
{label: 'Audio File (.ogg)', extension: 'ogg'}], function(selectedFile:SelectedFileInfo) {
|
{label: 'Audio File (.ogg)', extension: 'ogg'}], function(selectedFile:SelectedFileInfo) {
|
||||||
|
@ -541,14 +542,18 @@ class ChartEditorDialogHandler
|
||||||
'Failed to load instrumental track (${path.file}.${path.ext}) for variation (${state.selectedVariation})';
|
'Failed to load instrumental track (${path.file}.${path.ext}) for variation (${state.selectedVariation})';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the user the load was successful.
|
trace('Failed to load instrumental track (${path.file}.${path.ext})');
|
||||||
|
|
||||||
|
// Tell the user the load was unsuccessful.
|
||||||
state.error('Failed to Load Instrumental', message);
|
state.error('Failed to Load Instrumental', message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
dropHandler.handler = onDropFile;
|
dropHandler.handler = onDropFile;
|
||||||
|
|
||||||
|
#if FEATURE_FILE_DROP
|
||||||
state.addDropHandler(dropHandler);
|
state.addDropHandler(dropHandler);
|
||||||
|
#end
|
||||||
|
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
@ -727,6 +732,7 @@ class ChartEditorDialogHandler
|
||||||
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Open Chart dialog';
|
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Open Chart dialog';
|
||||||
buttonCancel.onClick = function(_) {
|
buttonCancel.onClick = function(_) {
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
|
state.clearDropHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
var chartContainerA:Null<Component> = dialog.findComponent('chartContainerA');
|
var chartContainerA:Null<Component> = dialog.findComponent('chartContainerA');
|
||||||
|
@ -743,6 +749,7 @@ class ChartEditorDialogHandler
|
||||||
state.loadSong(songMetadata, songChartData);
|
state.loadSong(songMetadata, songChartData);
|
||||||
|
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
|
state.clearDropHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
var onDropFileMetadataVariation:String->Label->String->Void;
|
var onDropFileMetadataVariation:String->Label->String->Void;
|
||||||
|
@ -761,18 +768,20 @@ class ChartEditorDialogHandler
|
||||||
var songDefaultChartDataEntry:Component = RuntimeComponentBuilder.fromAsset(CHART_EDITOR_DIALOG_OPEN_CHART_PARTS_ENTRY_LAYOUT);
|
var songDefaultChartDataEntry:Component = RuntimeComponentBuilder.fromAsset(CHART_EDITOR_DIALOG_OPEN_CHART_PARTS_ENTRY_LAYOUT);
|
||||||
var songDefaultChartDataEntryLabel:Null<Label> = songDefaultChartDataEntry.findComponent('chartEntryLabel', Label);
|
var songDefaultChartDataEntryLabel:Null<Label> = songDefaultChartDataEntry.findComponent('chartEntryLabel', Label);
|
||||||
if (songDefaultChartDataEntryLabel == null) throw 'Could not locate chartEntryLabel in Open Chart dialog';
|
if (songDefaultChartDataEntryLabel == null) throw 'Could not locate chartEntryLabel in Open Chart dialog';
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
songDefaultChartDataEntryLabel.text = 'Drag and drop <song>-chart.json file, or click to browse.';
|
songDefaultChartDataEntryLabel.text = 'Drag and drop <song>-chart.json file, or click to browse.';
|
||||||
#else
|
#else
|
||||||
songDefaultChartDataEntryLabel.text = 'Click to browse for <song>-chart.json file.';
|
songDefaultChartDataEntryLabel.text = 'Click to browse for <song>-chart.json file.';
|
||||||
#end
|
#end
|
||||||
|
|
||||||
songDefaultChartDataEntry.onClick = onClickChartDataVariation.bind(Constants.DEFAULT_VARIATION).bind(songDefaultChartDataEntryLabel);
|
songDefaultChartDataEntry.onClick = onClickChartDataVariation.bind(Constants.DEFAULT_VARIATION).bind(songDefaultChartDataEntryLabel);
|
||||||
|
#if FEATURE_FILE_DROP
|
||||||
state.addDropHandler(
|
state.addDropHandler(
|
||||||
{
|
{
|
||||||
component: songDefaultChartDataEntry,
|
component: songDefaultChartDataEntry,
|
||||||
handler: onDropFileChartDataVariation.bind(Constants.DEFAULT_VARIATION).bind(songDefaultChartDataEntryLabel)
|
handler: onDropFileChartDataVariation.bind(Constants.DEFAULT_VARIATION).bind(songDefaultChartDataEntryLabel)
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
chartContainerB.addComponent(songDefaultChartDataEntry);
|
chartContainerB.addComponent(songDefaultChartDataEntry);
|
||||||
|
|
||||||
for (variation in variations)
|
for (variation in variations)
|
||||||
|
@ -781,7 +790,7 @@ class ChartEditorDialogHandler
|
||||||
var songVariationMetadataEntry:Component = RuntimeComponentBuilder.fromAsset(CHART_EDITOR_DIALOG_OPEN_CHART_PARTS_ENTRY_LAYOUT);
|
var songVariationMetadataEntry:Component = RuntimeComponentBuilder.fromAsset(CHART_EDITOR_DIALOG_OPEN_CHART_PARTS_ENTRY_LAYOUT);
|
||||||
var songVariationMetadataEntryLabel:Null<Label> = songVariationMetadataEntry.findComponent('chartEntryLabel', Label);
|
var songVariationMetadataEntryLabel:Null<Label> = songVariationMetadataEntry.findComponent('chartEntryLabel', Label);
|
||||||
if (songVariationMetadataEntryLabel == null) throw 'Could not locate chartEntryLabel in Open Chart dialog';
|
if (songVariationMetadataEntryLabel == null) throw 'Could not locate chartEntryLabel in Open Chart dialog';
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
songVariationMetadataEntryLabel.text = 'Drag and drop <song>-metadata-${variation}.json file, or click to browse.';
|
songVariationMetadataEntryLabel.text = 'Drag and drop <song>-metadata-${variation}.json file, or click to browse.';
|
||||||
#else
|
#else
|
||||||
songVariationMetadataEntryLabel.text = 'Click to browse for <song>-metadata-${variation}.json file.';
|
songVariationMetadataEntryLabel.text = 'Click to browse for <song>-metadata-${variation}.json file.';
|
||||||
|
@ -796,7 +805,7 @@ class ChartEditorDialogHandler
|
||||||
Cursor.cursorMode = Default;
|
Cursor.cursorMode = Default;
|
||||||
}
|
}
|
||||||
songVariationMetadataEntry.onClick = onClickMetadataVariation.bind(variation).bind(songVariationMetadataEntryLabel);
|
songVariationMetadataEntry.onClick = onClickMetadataVariation.bind(variation).bind(songVariationMetadataEntryLabel);
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
state.addDropHandler(
|
state.addDropHandler(
|
||||||
{
|
{
|
||||||
component: songVariationMetadataEntry,
|
component: songVariationMetadataEntry,
|
||||||
|
@ -809,7 +818,7 @@ class ChartEditorDialogHandler
|
||||||
var songVariationChartDataEntry:Component = RuntimeComponentBuilder.fromAsset(CHART_EDITOR_DIALOG_OPEN_CHART_PARTS_ENTRY_LAYOUT);
|
var songVariationChartDataEntry:Component = RuntimeComponentBuilder.fromAsset(CHART_EDITOR_DIALOG_OPEN_CHART_PARTS_ENTRY_LAYOUT);
|
||||||
var songVariationChartDataEntryLabel:Null<Label> = songVariationChartDataEntry.findComponent('chartEntryLabel', Label);
|
var songVariationChartDataEntryLabel:Null<Label> = songVariationChartDataEntry.findComponent('chartEntryLabel', Label);
|
||||||
if (songVariationChartDataEntryLabel == null) throw 'Could not locate chartEntryLabel in Open Chart dialog';
|
if (songVariationChartDataEntryLabel == null) throw 'Could not locate chartEntryLabel in Open Chart dialog';
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
songVariationChartDataEntryLabel.text = 'Drag and drop <song>-chart-${variation}.json file, or click to browse.';
|
songVariationChartDataEntryLabel.text = 'Drag and drop <song>-chart-${variation}.json file, or click to browse.';
|
||||||
#else
|
#else
|
||||||
songVariationChartDataEntryLabel.text = 'Click to browse for <song>-chart-${variation}.json file.';
|
songVariationChartDataEntryLabel.text = 'Click to browse for <song>-chart-${variation}.json file.';
|
||||||
|
@ -824,7 +833,7 @@ class ChartEditorDialogHandler
|
||||||
Cursor.cursorMode = Default;
|
Cursor.cursorMode = Default;
|
||||||
}
|
}
|
||||||
songVariationChartDataEntry.onClick = onClickChartDataVariation.bind(variation).bind(songVariationChartDataEntryLabel);
|
songVariationChartDataEntry.onClick = onClickChartDataVariation.bind(variation).bind(songVariationChartDataEntryLabel);
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
state.addDropHandler(
|
state.addDropHandler(
|
||||||
{
|
{
|
||||||
component: songVariationChartDataEntry,
|
component: songVariationChartDataEntry,
|
||||||
|
@ -864,7 +873,7 @@ class ChartEditorDialogHandler
|
||||||
// Tell the user the load was successful.
|
// Tell the user the load was successful.
|
||||||
state.success('Loaded Metadata', 'Loaded metadata file (${path.file}.${path.ext})');
|
state.success('Loaded Metadata', 'Loaded metadata file (${path.file}.${path.ext})');
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
label.text = 'Metadata file (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
|
label.text = 'Metadata file (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
|
||||||
#else
|
#else
|
||||||
label.text = 'Metadata file (click to browse)\n${path.file}.${path.ext}';
|
label.text = 'Metadata file (click to browse)\n${path.file}.${path.ext}';
|
||||||
|
@ -900,7 +909,7 @@ class ChartEditorDialogHandler
|
||||||
// Tell the user the load was successful.
|
// Tell the user the load was successful.
|
||||||
state.success('Loaded Metadata', 'Loaded metadata file (${selectedFile.name})');
|
state.success('Loaded Metadata', 'Loaded metadata file (${selectedFile.name})');
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
label.text = 'Metadata file (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}';
|
label.text = 'Metadata file (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}';
|
||||||
#else
|
#else
|
||||||
label.text = 'Metadata file (click to browse)\n${selectedFile.name}';
|
label.text = 'Metadata file (click to browse)\n${selectedFile.name}';
|
||||||
|
@ -944,7 +953,7 @@ class ChartEditorDialogHandler
|
||||||
// Tell the user the load was successful.
|
// Tell the user the load was successful.
|
||||||
state.success('Loaded Chart Data', 'Loaded chart data file (${path.file}.${path.ext})');
|
state.success('Loaded Chart Data', 'Loaded chart data file (${path.file}.${path.ext})');
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
label.text = 'Chart data file (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
|
label.text = 'Chart data file (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
|
||||||
#else
|
#else
|
||||||
label.text = 'Chart data file (click to browse)\n${path.file}.${path.ext}';
|
label.text = 'Chart data file (click to browse)\n${path.file}.${path.ext}';
|
||||||
|
@ -987,7 +996,7 @@ class ChartEditorDialogHandler
|
||||||
// Tell the user the load was successful.
|
// Tell the user the load was successful.
|
||||||
state.success('Loaded Chart Data', 'Loaded chart data file (${selectedFile.name})');
|
state.success('Loaded Chart Data', 'Loaded chart data file (${selectedFile.name})');
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
label.text = 'Chart data file (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}';
|
label.text = 'Chart data file (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}';
|
||||||
#else
|
#else
|
||||||
label.text = 'Chart data file (click to browse)\n${selectedFile.name}';
|
label.text = 'Chart data file (click to browse)\n${selectedFile.name}';
|
||||||
|
@ -1001,14 +1010,20 @@ class ChartEditorDialogHandler
|
||||||
var metadataEntryLabel:Null<Label> = metadataEntry.findComponent('chartEntryLabel', Label);
|
var metadataEntryLabel:Null<Label> = metadataEntry.findComponent('chartEntryLabel', Label);
|
||||||
if (metadataEntryLabel == null) throw 'Could not locate chartEntryLabel in Open Chart dialog';
|
if (metadataEntryLabel == null) throw 'Could not locate chartEntryLabel in Open Chart dialog';
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FEATURE_FILE_DROP
|
||||||
metadataEntryLabel.text = 'Drag and drop <song>-metadata.json file, or click to browse.';
|
metadataEntryLabel.text = 'Drag and drop <song>-metadata.json file, or click to browse.';
|
||||||
#else
|
#else
|
||||||
metadataEntryLabel.text = 'Click to browse for <song>-metadata.json file.';
|
metadataEntryLabel.text = 'Click to browse for <song>-metadata.json file.';
|
||||||
#end
|
#end
|
||||||
|
|
||||||
metadataEntry.onClick = onClickMetadataVariation.bind(Constants.DEFAULT_VARIATION).bind(metadataEntryLabel);
|
metadataEntry.onClick = onClickMetadataVariation.bind(Constants.DEFAULT_VARIATION).bind(metadataEntryLabel);
|
||||||
state.addDropHandler({component: metadataEntry, handler: onDropFileMetadataVariation.bind(Constants.DEFAULT_VARIATION).bind(metadataEntryLabel)});
|
#if FEATURE_FILE_DROP
|
||||||
|
state.addDropHandler(
|
||||||
|
{
|
||||||
|
component: metadataEntry,
|
||||||
|
handler: onDropFileMetadataVariation.bind(Constants.DEFAULT_VARIATION).bind(metadataEntryLabel)
|
||||||
|
});
|
||||||
|
#end
|
||||||
metadataEntry.onMouseOver = function(_event) {
|
metadataEntry.onMouseOver = function(_event) {
|
||||||
metadataEntry.swapClass('upload-bg', 'upload-bg-hover');
|
metadataEntry.swapClass('upload-bg', 'upload-bg-hover');
|
||||||
Cursor.cursorMode = Pointer;
|
Cursor.cursorMode = Pointer;
|
||||||
|
@ -1035,6 +1050,20 @@ class ChartEditorDialogHandler
|
||||||
var dialog:Null<Dialog> = openDialog(state, CHART_EDITOR_DIALOG_IMPORT_CHART_LAYOUT, true, closable);
|
var dialog:Null<Dialog> = openDialog(state, CHART_EDITOR_DIALOG_IMPORT_CHART_LAYOUT, true, closable);
|
||||||
if (dialog == null) return null;
|
if (dialog == null) return null;
|
||||||
|
|
||||||
|
var importBox:Null<Box> = dialog.findComponent('importBox', Box);
|
||||||
|
if (importBox == null) throw 'Could not locate importBox in Import Chart dialog';
|
||||||
|
|
||||||
|
importBox.onMouseOver = function(_) {
|
||||||
|
importBox.swapClass('upload-bg', 'upload-bg-hover');
|
||||||
|
Cursor.cursorMode = Pointer;
|
||||||
|
}
|
||||||
|
importBox.onMouseOut = function(_) {
|
||||||
|
importBox.swapClass('upload-bg-hover', 'upload-bg');
|
||||||
|
Cursor.cursorMode = Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dropHandler:DialogDropTarget = {component: importBox, handler: null};
|
||||||
|
|
||||||
var prettyFormat:String = switch (format)
|
var prettyFormat:String = switch (format)
|
||||||
{
|
{
|
||||||
case 'legacy': 'FNF Legacy';
|
case 'legacy': 'FNF Legacy';
|
||||||
|
@ -1063,18 +1092,7 @@ class ChartEditorDialogHandler
|
||||||
buttonCancel.onClick = function(_) {
|
buttonCancel.onClick = function(_) {
|
||||||
state.isHaxeUIDialogOpen = false;
|
state.isHaxeUIDialogOpen = false;
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
}
|
state.removeDropHandler(dropHandler);
|
||||||
|
|
||||||
var importBox:Null<Box> = dialog.findComponent('importBox', Box);
|
|
||||||
if (importBox == null) throw 'Could not locate importBox in Import Chart dialog';
|
|
||||||
|
|
||||||
importBox.onMouseOver = function(_) {
|
|
||||||
importBox.swapClass('upload-bg', 'upload-bg-hover');
|
|
||||||
Cursor.cursorMode = Pointer;
|
|
||||||
}
|
|
||||||
importBox.onMouseOut = function(_) {
|
|
||||||
importBox.swapClass('upload-bg-hover', 'upload-bg');
|
|
||||||
Cursor.cursorMode = Default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var onDropFile:String->Void;
|
var onDropFile:String->Void;
|
||||||
|
@ -1099,6 +1117,7 @@ class ChartEditorDialogHandler
|
||||||
state.loadSong([Constants.DEFAULT_VARIATION => songMetadata], [Constants.DEFAULT_VARIATION => songChartData]);
|
state.loadSong([Constants.DEFAULT_VARIATION => songMetadata], [Constants.DEFAULT_VARIATION => songChartData]);
|
||||||
|
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
|
state.removeDropHandler(dropHandler);
|
||||||
state.success('Success', 'Loaded chart file (${selectedFile.name})');
|
state.success('Success', 'Loaded chart file (${selectedFile.name})');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1121,10 +1140,15 @@ class ChartEditorDialogHandler
|
||||||
state.loadSong([Constants.DEFAULT_VARIATION => songMetadata], [Constants.DEFAULT_VARIATION => songChartData]);
|
state.loadSong([Constants.DEFAULT_VARIATION => songMetadata], [Constants.DEFAULT_VARIATION => songChartData]);
|
||||||
|
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
|
state.removeDropHandler(dropHandler);
|
||||||
state.success('Success', 'Loaded chart file (${path.file}.${path.ext})');
|
state.success('Success', 'Loaded chart file (${path.file}.${path.ext})');
|
||||||
};
|
};
|
||||||
|
|
||||||
state.addDropHandler({component: importBox, handler: onDropFile});
|
dropHandler.handler = onDropFile;
|
||||||
|
|
||||||
|
#if FEATURE_FILE_DROP
|
||||||
|
state.addDropHandler(dropHandler);
|
||||||
|
#end
|
||||||
|
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,8 @@ class OptionsState extends MusicBeatState
|
||||||
optionsCodex = new Codex<OptionsMenuPageName>(Options);
|
optionsCodex = new Codex<OptionsMenuPageName>(Options);
|
||||||
add(optionsCodex);
|
add(optionsCodex);
|
||||||
|
|
||||||
var options:OptionsMenu = optionsCodex.addPage(Options, new OptionsMenu());
|
var saveData:SaveDataMenu = optionsCodex.addPage(SaveData, new SaveDataMenu());
|
||||||
|
var options:OptionsMenu = optionsCodex.addPage(Options, new OptionsMenu(saveData));
|
||||||
var preferences:PreferencesMenu = optionsCodex.addPage(Preferences, new PreferencesMenu());
|
var preferences:PreferencesMenu = optionsCodex.addPage(Preferences, new PreferencesMenu());
|
||||||
var controls:ControlsMenu = optionsCodex.addPage(Controls, new ControlsMenu());
|
var controls:ControlsMenu = optionsCodex.addPage(Controls, new ControlsMenu());
|
||||||
#if FEATURE_INPUT_OFFSETS
|
#if FEATURE_INPUT_OFFSETS
|
||||||
|
@ -84,6 +85,7 @@ class OptionsState extends MusicBeatState
|
||||||
#if FEATURE_INPUT_OFFSETS
|
#if FEATURE_INPUT_OFFSETS
|
||||||
offsets.onExit.add(exitOffsets);
|
offsets.onExit.add(exitOffsets);
|
||||||
#end
|
#end
|
||||||
|
saveData.onExit.add(optionsCodex.switchPage.bind(Options));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -159,7 +161,7 @@ class OptionsMenu extends Page<OptionsMenuPageName>
|
||||||
|
|
||||||
final CAMERA_MARGIN:Int = 150;
|
final CAMERA_MARGIN:Int = 150;
|
||||||
|
|
||||||
public function new()
|
public function new(saveDataMenu:SaveDataMenu)
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
add(items = new TextMenuList());
|
add(items = new TextMenuList());
|
||||||
|
@ -227,9 +229,19 @@ class OptionsMenu extends Page<OptionsMenuPageName>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
createItem("CLEAR SAVE DATA", function() {
|
|
||||||
promptClearSaveData();
|
// no need to show an entire new menu for just one option
|
||||||
});
|
if (saveDataMenu.hasMultipleOptions())
|
||||||
|
{
|
||||||
|
createItem("SAVE DATA OPTIONS", function() {
|
||||||
|
codex.switchPage(SaveData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
createItem("CLEAR SAVE DATA", saveDataMenu.openSaveDataPrompt);
|
||||||
|
}
|
||||||
|
|
||||||
#if NO_FEATURE_TOUCH_CONTROLS
|
#if NO_FEATURE_TOUCH_CONTROLS
|
||||||
createItem("EXIT", exit);
|
createItem("EXIT", exit);
|
||||||
#else
|
#else
|
||||||
|
@ -277,7 +289,6 @@ class OptionsMenu extends Page<OptionsMenuPageName>
|
||||||
|
|
||||||
override function update(elapsed:Float):Void
|
override function update(elapsed:Float):Void
|
||||||
{
|
{
|
||||||
enabled = (prompt == null);
|
|
||||||
#if FEATURE_TOUCH_CONTROLS
|
#if FEATURE_TOUCH_CONTROLS
|
||||||
backButton.active = (!goingBack) ? !items.busy : true;
|
backButton.active = (!goingBack) ? !items.busy : true;
|
||||||
#end
|
#end
|
||||||
|
@ -298,31 +309,6 @@ class OptionsMenu extends Page<OptionsMenuPageName>
|
||||||
{
|
{
|
||||||
return items.length > 2;
|
return items.length > 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
var prompt:Prompt;
|
|
||||||
|
|
||||||
function promptClearSaveData():Void
|
|
||||||
{
|
|
||||||
if (prompt != null) return;
|
|
||||||
prompt = new Prompt("This will delete
|
|
||||||
\nALL your save data.
|
|
||||||
\nAre you sure?
|
|
||||||
", Custom("Delete", "Cancel"));
|
|
||||||
prompt.create();
|
|
||||||
prompt.createBgFromMargin(100, 0xFFFAFD6D);
|
|
||||||
prompt.back.scrollFactor.set(0, 0);
|
|
||||||
add(prompt);
|
|
||||||
prompt.onYes = function() {
|
|
||||||
// Clear the save data.
|
|
||||||
funkin.save.Save.clearData();
|
|
||||||
FlxG.switchState(() -> new funkin.InitState());
|
|
||||||
};
|
|
||||||
prompt.onNo = function() {
|
|
||||||
prompt.close();
|
|
||||||
prompt.destroy();
|
|
||||||
prompt = null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum abstract OptionsMenuPageName(String) to PageName
|
enum abstract OptionsMenuPageName(String) to PageName
|
||||||
|
@ -333,4 +319,5 @@ enum abstract OptionsMenuPageName(String) to PageName
|
||||||
var Mods = "mods";
|
var Mods = "mods";
|
||||||
var Preferences = "preferences";
|
var Preferences = "preferences";
|
||||||
var Offsets = "offsets";
|
var Offsets = "offsets";
|
||||||
|
var SaveData = "saveData";
|
||||||
}
|
}
|
||||||
|
|
125
source/funkin/ui/options/SaveDataMenu.hx
Normal file
125
source/funkin/ui/options/SaveDataMenu.hx
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
package funkin.ui.options;
|
||||||
|
|
||||||
|
#if FEATURE_NEWGROUNDS
|
||||||
|
import funkin.api.newgrounds.NewgroundsClient;
|
||||||
|
#end
|
||||||
|
import funkin.save.Save;
|
||||||
|
|
||||||
|
class SaveDataMenu extends Page<OptionsState.OptionsMenuPageName>
|
||||||
|
{
|
||||||
|
var items:TextMenuList;
|
||||||
|
|
||||||
|
public function new()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
add(items = new TextMenuList());
|
||||||
|
|
||||||
|
createItem("CLEAR SAVE DATA", openSaveDataPrompt);
|
||||||
|
|
||||||
|
#if FEATURE_NEWGROUNDS
|
||||||
|
if (NewgroundsClient.instance.isLoggedIn())
|
||||||
|
{
|
||||||
|
createItem("LOAD FROM NG", function() {
|
||||||
|
openConfirmPrompt("This will overwrite
|
||||||
|
\nALL your save data.
|
||||||
|
\nAre you sure?
|
||||||
|
", "Overwrite", function() {
|
||||||
|
Save.loadFromNewgrounds(function() {
|
||||||
|
FlxG.switchState(() -> new funkin.InitState());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
createItem("SAVE TO NG", function() {
|
||||||
|
openConfirmPrompt("This will overwrite
|
||||||
|
\nALL save data saved
|
||||||
|
\non NG. Are you sure?", "Overwrite", function() {
|
||||||
|
Save.saveToNewgrounds();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
createItem("CLEAR NG SAVE DATA", function() {
|
||||||
|
openConfirmPrompt("This will delete
|
||||||
|
\nALL save data saved
|
||||||
|
\non NG. Are you sure?", "Delete", function() {
|
||||||
|
funkin.api.newgrounds.NGSaveSlot.instance.clear();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
|
createItem("EXIT", exit);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createItem(name:String, callback:Void->Void, fireInstantly = false)
|
||||||
|
{
|
||||||
|
var item = items.createItem(0, 100 + items.length * 100, name, BOLD, callback);
|
||||||
|
item.fireInstantly = fireInstantly;
|
||||||
|
item.screenCenter(X);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
override function update(elapsed:Float)
|
||||||
|
{
|
||||||
|
enabled = (prompt == null);
|
||||||
|
super.update(elapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function set_enabled(value:Bool)
|
||||||
|
{
|
||||||
|
items.enabled = value;
|
||||||
|
return super.set_enabled(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
var prompt:Prompt;
|
||||||
|
|
||||||
|
function openConfirmPrompt(text:String, yesText:String, onYes:Void->Void, ?groupToOpenOn:Null<flixel.group.FlxGroup>):Void
|
||||||
|
{
|
||||||
|
if (prompt != null) return;
|
||||||
|
|
||||||
|
prompt = new Prompt(text, Custom(yesText, "Cancel"));
|
||||||
|
prompt.create();
|
||||||
|
prompt.createBgFromMargin(100, 0xFFFAFD6D);
|
||||||
|
prompt.back.scrollFactor.set(0, 0);
|
||||||
|
FlxG.state.add(prompt);
|
||||||
|
|
||||||
|
prompt.onYes = function() {
|
||||||
|
onYes();
|
||||||
|
|
||||||
|
if (prompt != null)
|
||||||
|
{
|
||||||
|
prompt.close();
|
||||||
|
prompt.destroy();
|
||||||
|
prompt = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
prompt.onNo = function() {
|
||||||
|
prompt.close();
|
||||||
|
prompt.destroy();
|
||||||
|
prompt = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function openSaveDataPrompt()
|
||||||
|
{
|
||||||
|
openConfirmPrompt("This will delete
|
||||||
|
\nALL your save data.
|
||||||
|
\nAre you sure?
|
||||||
|
", "Delete", function() {
|
||||||
|
// Clear the save data.
|
||||||
|
Save.clearData();
|
||||||
|
|
||||||
|
FlxG.switchState(() -> new funkin.InitState());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if this page has multiple options, excluding the exit option.
|
||||||
|
* If false, there's no reason to ever show this page.
|
||||||
|
*/
|
||||||
|
public function hasMultipleOptions():Bool
|
||||||
|
{
|
||||||
|
return items.length > 2;
|
||||||
|
}
|
||||||
|
}
|
|
@ -102,12 +102,19 @@ class WindowUtil
|
||||||
*/
|
*/
|
||||||
public static final windowExit:FlxTypedSignal<Int->Void> = new FlxTypedSignal<Int->Void>();
|
public static final windowExit:FlxTypedSignal<Int->Void> = new FlxTypedSignal<Int->Void>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has `initWindowEvents()` been called already?
|
||||||
|
* This is to prevent multiple instances of the same function.
|
||||||
|
*/
|
||||||
|
private static var _initializedWindowEvents:Bool = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wires up FlxSignals that happen based on window activity.
|
* Wires up FlxSignals that happen based on window activity.
|
||||||
* For example, we can run a callback when the window is closed.
|
* For example, we can run a callback when the window is closed.
|
||||||
*/
|
*/
|
||||||
public static function initWindowEvents():Void
|
public static function initWindowEvents():Void
|
||||||
{
|
{
|
||||||
|
if (_initializedWindowEvents) return; // Fix that annoying
|
||||||
// onUpdate is called every frame just before rendering.
|
// onUpdate is called every frame just before rendering.
|
||||||
|
|
||||||
// onExit is called when the game window is closed.
|
// onExit is called when the game window is closed.
|
||||||
|
@ -137,6 +144,7 @@ class WindowUtil
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
#end
|
#end
|
||||||
|
_initializedWindowEvents = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue