mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2025-08-30 10:25:00 +00:00
Compare commits
33 commits
c3a01d09c2
...
b5b336316e
Author | SHA1 | Date | |
---|---|---|---|
|
b5b336316e | ||
|
fc0e6712d8 | ||
|
d0f0974d1e | ||
|
369b936056 | ||
|
c40e1e3958 | ||
|
0ade24bac4 | ||
|
7370ef3249 | ||
|
b2f162a8ae | ||
|
11fa9b4050 | ||
|
89bd7a3f43 | ||
|
942fb5efc9 | ||
|
c2eff142bd | ||
|
2784fa18c0 | ||
|
ad07fddf89 | ||
|
2586154376 | ||
|
4768eedd5b | ||
|
7c675ecf17 | ||
|
f1c3e99a11 | ||
|
eefe8927c4 | ||
|
3ff4f14510 | ||
|
955b0db542 | ||
|
d2df4f0832 | ||
|
351719ab13 | ||
|
4ecfe9863e | ||
|
48e140e5c0 | ||
|
e6bb965d6b | ||
|
b00376c88c | ||
|
541bb78da9 | ||
|
5f5fff870c | ||
|
52acd86cdf | ||
|
29f7aca135 | ||
|
35d4d24731 | ||
|
c0dde5c936 |
24
.github/ISSUE_TEMPLATE/bug.yml
vendored
24
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
@ -20,13 +20,13 @@ body:
|
|||
label: Platform
|
||||
description: Which platform are you playing on?
|
||||
options:
|
||||
- Android
|
||||
- iOS/iPadOS
|
||||
- Newgrounds (Web/HTML5)
|
||||
- Itch.io (Web/HTML5)
|
||||
- Itch.io (Downloadable Build) - Windows
|
||||
- Itch.io (Downloadable Build) - MacOS
|
||||
- Itch.io (Downloadable Build) - Linux
|
||||
- Google Playstore - Android
|
||||
- App Store - iOS
|
||||
- Windows (Downloadable Build)
|
||||
- MacOS (Downloadable Build)
|
||||
- Linux (Downloadable Build)
|
||||
- Compiled from GitHub Source Code
|
||||
validations:
|
||||
required: true
|
||||
|
@ -43,11 +43,23 @@ body:
|
|||
- Safari
|
||||
- Other (Specify in Description field)
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Mobile Device Model
|
||||
description: (Mobile users only) What mobile device are you playing on?
|
||||
placeholder: ex. iPhone 16, Galaxy S25, iPad 11th Gen
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Mobile OS Version
|
||||
description: (Mobile users only) What version is your Operating System?
|
||||
placeholder: ex. iOS 18.5, Android 15, iPadOS 18.5
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Version
|
||||
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
||||
placeholder: ex. 0.6.4
|
||||
placeholder: ex. 0.7.4
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
|
28
.github/ISSUE_TEMPLATE/charting.yml
vendored
28
.github/ISSUE_TEMPLATE/charting.yml
vendored
|
@ -6,7 +6,7 @@ body:
|
|||
- type: markdown
|
||||
attributes:
|
||||
value: "# PLEASE READ THE [CONTRIBUTING GUIDE](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md) BEFORE OPENING ISSUES!"
|
||||
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Issue Checklist
|
||||
|
@ -21,35 +21,25 @@ body:
|
|||
label: Platform
|
||||
description: Which platform are you playing on?
|
||||
options:
|
||||
- Android
|
||||
- iOS/iPadOS
|
||||
- Newgrounds (Web/HTML5)
|
||||
- Itch.io (Web/HTML5)
|
||||
- Itch.io (Downloadable Build) - Windows
|
||||
- Itch.io (Downloadable Build) - MacOS
|
||||
- Itch.io (Downloadable Build) - Linux
|
||||
- Windows (Downloadable Build)
|
||||
- MacOS (Downloadable Build)
|
||||
- Linux (Downloadable Build)
|
||||
- Compiled from GitHub Source Code
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Browser
|
||||
description: (Web/HTML5 users only) Which browser are you playing on?
|
||||
options:
|
||||
- Google Chrome
|
||||
- Microsoft Edge
|
||||
- Firefox
|
||||
- Opera
|
||||
- Safari
|
||||
- Other (Specify in Description field)
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Version
|
||||
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
||||
placeholder: ex. 0.6.4
|
||||
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
||||
placeholder: ex. 0.7.4
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "## Describe the charting issue(s)."
|
||||
|
|
10
.github/ISSUE_TEMPLATE/compiling.yml
vendored
10
.github/ISSUE_TEMPLATE/compiling.yml
vendored
|
@ -6,7 +6,7 @@ body:
|
|||
- type: markdown
|
||||
attributes:
|
||||
value: "# PLEASE READ THE [CONTRIBUTING GUIDE](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md) BEFORE OPENING ISSUES!"
|
||||
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Issue Checklist
|
||||
|
@ -22,6 +22,8 @@ body:
|
|||
label: Platform
|
||||
description: Which platform are you compiling for?
|
||||
options:
|
||||
- Android
|
||||
- iOS/iPadOS
|
||||
- Web/HTML5
|
||||
- Desktop (Windows)
|
||||
- Desktop (Mac)
|
||||
|
@ -33,11 +35,11 @@ body:
|
|||
- type: input
|
||||
attributes:
|
||||
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.
|
||||
placeholder: ex. 0.6.4
|
||||
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.4
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "## Describe your compiling issue."
|
||||
|
|
30
.github/ISSUE_TEMPLATE/crash.yml
vendored
30
.github/ISSUE_TEMPLATE/crash.yml
vendored
|
@ -6,7 +6,7 @@ body:
|
|||
- type: markdown
|
||||
attributes:
|
||||
value: "# PLEASE READ THE [CONTRIBUTING GUIDE](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md) BEFORE OPENING ISSUES!"
|
||||
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Issue Checklist
|
||||
|
@ -21,11 +21,13 @@ body:
|
|||
label: Platform
|
||||
description: Which platform are you playing on?
|
||||
options:
|
||||
- Android
|
||||
- iOS/iPadOS
|
||||
- Newgrounds (Web/HTML5)
|
||||
- Itch.io (Web/HTML5)
|
||||
- Itch.io (Downloadable Build) - Windows
|
||||
- Itch.io (Downloadable Build) - MacOS
|
||||
- Itch.io (Downloadable Build) - Linux
|
||||
- Windows (Downloadable Build)
|
||||
- MacOS (Downloadable Build)
|
||||
- Linux (Downloadable Build)
|
||||
- Compiled from GitHub Source Code
|
||||
validations:
|
||||
required: true
|
||||
|
@ -42,11 +44,23 @@ body:
|
|||
- Safari
|
||||
- Other (Specify in Description field)
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Mobile Device Model
|
||||
description: (Mobile users only) What mobile device are you playing on?
|
||||
placeholder: ex. iPhone 16, Galaxy S25, iPad 11th Gen
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Mobile OS Version
|
||||
description: (Mobile users only) What version is your Operating System?
|
||||
placeholder: ex. iOS 18.5, Android 15, iPadOS 18.5
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Version
|
||||
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
||||
placeholder: ex. 0.6.4
|
||||
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
||||
placeholder: ex. 0.7.4
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
@ -61,7 +75,7 @@ body:
|
|||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: Include screenshots or videos of the crash happening. Provide as much detail as you can.
|
||||
description: Include screenshots or videos of the crash happening. Provide as much detail as you can.
|
||||
placeholder: Describe the crash here...
|
||||
validations:
|
||||
required: true
|
||||
|
@ -77,7 +91,7 @@ body:
|
|||
- type: textarea
|
||||
attributes:
|
||||
label: Crash logs
|
||||
description: These can be found in the logs folder where Funkin.exe is.
|
||||
description: These can be found in the logs folder where Funkin.exe is, or in your mobile device's file explorer.
|
||||
placeholder: Upload your logs here...
|
||||
validations:
|
||||
required: true
|
||||
|
|
|
@ -432,7 +432,7 @@ Select. ([3d3e2bd](https://github.com/FunkinCrew/Funkin/commit/3d3e2bd3786b85814
|
|||
* @JackXson-Real made their first contribution in [#4346](https://github.com/FunkinCrew/Funkin/pull/4346)
|
||||
* @VioletSnowLeopard made their first contribution in [#4382](https://github.com/FunkinCrew/Funkin/pull/4382)
|
||||
* @superpowers04 made their first contribution in [#4729](https://github.com/FunkinCrew/Funkin/pull/4729)
|
||||
* @ShadzXD made their first contribution in [#62](https://github.com/FunkinCrew/Funkin/pull/4729)
|
||||
* @ShadzXD made their first contribution in [funkin.assets#62](https://github.com/FunkinCrew/funkin.assets/pull/62)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ This section provides guidelines to follow when [opening an issue](https://githu
|
|||
|
||||
## Requirements
|
||||
Make sure you're playing:
|
||||
- the latest version of the game (currently v0.6.4)
|
||||
- the latest version of the game (currently v0.7.4)
|
||||
- without any mods
|
||||
- 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"
|
||||
}
|
||||
],
|
||||
"api_version": "0.5.0",
|
||||
"api_version": "0.7.0",
|
||||
"mod_version": "1.0.0",
|
||||
"license": "Apache-2.0"
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"name": "EliteMasterEric"
|
||||
}
|
||||
],
|
||||
"api_version": "0.5.0",
|
||||
"api_version": "0.7.0",
|
||||
"mod_version": "1.0.0",
|
||||
"license": "Apache-2.0"
|
||||
}
|
||||
|
|
6
hmm.json
6
hmm.json
|
@ -46,7 +46,7 @@
|
|||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "08fc955ca87f192a971719a675f1d3b21709725d",
|
||||
"url": "https://github.com/FunkinCrew/flixel-mobile"
|
||||
"url": "https://github.com/FunkinCrew/flixel"
|
||||
},
|
||||
{
|
||||
"name": "flixel-addons",
|
||||
|
@ -171,7 +171,7 @@
|
|||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "c750ebf6b48c4bc018abe9855fbae5ffdbc4771a",
|
||||
"url": "https://github.com/FunkinCrew/lime-mobile"
|
||||
"url": "https://github.com/FunkinCrew/lime"
|
||||
},
|
||||
{
|
||||
"name": "mconsole",
|
||||
|
@ -213,7 +213,7 @@
|
|||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "a0df7c3afe360c9af59a76e45007dbf4e53b5131",
|
||||
"url": "https://github.com/FunkinCrew/openfl-mobile"
|
||||
"url": "https://github.com/FunkinCrew/openfl"
|
||||
},
|
||||
{
|
||||
"name": "polymod",
|
||||
|
|
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.objects.events.Outcome;
|
||||
import io.newgrounds.utils.MedalList;
|
||||
import io.newgrounds.utils.SaveSlotList;
|
||||
import io.newgrounds.utils.ScoreBoardList;
|
||||
import io.newgrounds.objects.User;
|
||||
|
||||
|
@ -29,6 +30,7 @@ class NewgroundsClient
|
|||
public var user(get, never):Null<User>;
|
||||
public var medals(get, never):Null<MedalList>;
|
||||
public var leaderboards(get, never):Null<ScoreBoardList>;
|
||||
public var saveSlots(get, never):Null<SaveSlotList>;
|
||||
|
||||
private function new()
|
||||
{
|
||||
|
@ -236,6 +238,8 @@ class NewgroundsClient
|
|||
|
||||
trace('[NEWGROUNDS] Submitting leaderboard request...');
|
||||
NG.core.scoreBoards.loadList(onFetchedLeaderboards);
|
||||
trace('[NEWGROUNDS] Submitting save slot request...');
|
||||
NG.core.saveSlots.loadList(onFetchedSaveSlots);
|
||||
}
|
||||
|
||||
function onLoginFailed(result:LoginFail):Void
|
||||
|
@ -301,6 +305,13 @@ class NewgroundsClient
|
|||
// 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>
|
||||
{
|
||||
if (NG.core == null || !this.isLoggedIn()) return null;
|
||||
|
@ -319,6 +330,12 @@ class NewgroundsClient
|
|||
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>
|
||||
{
|
||||
#if js
|
||||
|
|
|
@ -714,8 +714,6 @@ class PlayState extends MusicBeatSubState
|
|||
#if mobile
|
||||
// Force allowScreenTimeout to be disabled
|
||||
lime.system.System.allowScreenTimeout = false;
|
||||
// TODO: For some reason the touch pointer's positioning gets weird in playstate, find a way to fix it! -Zack
|
||||
funkin.util.plugins.TouchPointerPlugin.enabled = false;
|
||||
#end
|
||||
|
||||
// This state receives update() even when a substate is active.
|
||||
|
@ -1761,7 +1759,6 @@ class PlayState extends MusicBeatSubState
|
|||
#if mobile
|
||||
// Syncing allowScreenTimeout with Preferences option.
|
||||
lime.system.System.allowScreenTimeout = Preferences.screenTimeout;
|
||||
funkin.util.plugins.TouchPointerPlugin.enabled = true;
|
||||
#end
|
||||
|
||||
#if !mobile
|
||||
|
|
|
@ -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...');
|
||||
}
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -69,7 +69,8 @@ class OptionsState extends MusicBeatState
|
|||
optionsCodex = new Codex<OptionsMenuPageName>(Options);
|
||||
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 controls:ControlsMenu = optionsCodex.addPage(Controls, new ControlsMenu());
|
||||
#if FEATURE_INPUT_OFFSETS
|
||||
|
@ -84,6 +85,7 @@ class OptionsState extends MusicBeatState
|
|||
#if FEATURE_INPUT_OFFSETS
|
||||
offsets.onExit.add(exitOffsets);
|
||||
#end
|
||||
saveData.onExit.add(optionsCodex.switchPage.bind(Options));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -159,7 +161,7 @@ class OptionsMenu extends Page<OptionsMenuPageName>
|
|||
|
||||
final CAMERA_MARGIN:Int = 150;
|
||||
|
||||
public function new()
|
||||
public function new(saveDataMenu:SaveDataMenu)
|
||||
{
|
||||
super();
|
||||
add(items = new TextMenuList());
|
||||
|
@ -227,9 +229,19 @@ class OptionsMenu extends Page<OptionsMenuPageName>
|
|||
});
|
||||
}
|
||||
#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
|
||||
createItem("EXIT", exit);
|
||||
#else
|
||||
|
@ -277,7 +289,6 @@ class OptionsMenu extends Page<OptionsMenuPageName>
|
|||
|
||||
override function update(elapsed:Float):Void
|
||||
{
|
||||
enabled = (prompt == null);
|
||||
#if FEATURE_TOUCH_CONTROLS
|
||||
backButton.active = (!goingBack) ? !items.busy : true;
|
||||
#end
|
||||
|
@ -298,31 +309,6 @@ class OptionsMenu extends Page<OptionsMenuPageName>
|
|||
{
|
||||
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
|
||||
|
@ -333,4 +319,5 @@ enum abstract OptionsMenuPageName(String) to PageName
|
|||
var Mods = "mods";
|
||||
var Preferences = "preferences";
|
||||
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>();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* For example, we can run a callback when the window is closed.
|
||||
*/
|
||||
public static function initWindowEvents():Void
|
||||
{
|
||||
if (_initializedWindowEvents) return; // Fix that annoying
|
||||
// onUpdate is called every frame just before rendering.
|
||||
|
||||
// onExit is called when the game window is closed.
|
||||
|
@ -137,6 +144,7 @@ class WindowUtil
|
|||
}
|
||||
});
|
||||
#end
|
||||
_initializedWindowEvents = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package funkin.util.plugins;
|
||||
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxCamera;
|
||||
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
||||
import flixel.input.touch.FlxTouch;
|
||||
import flixel.math.FlxAngle;
|
||||
|
@ -33,6 +33,11 @@ class TouchPointerPlugin extends FlxTypedSpriteGroup<TouchPointer>
|
|||
*/
|
||||
private static var instance:TouchPointerPlugin = null;
|
||||
|
||||
/**
|
||||
* A camera dedicated to displaying the pointers.
|
||||
*/
|
||||
private static var pointerCamera:FlxCamera;
|
||||
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
@ -43,7 +48,7 @@ class TouchPointerPlugin extends FlxTypedSpriteGroup<TouchPointer>
|
|||
*/
|
||||
public static function initialize():Void
|
||||
{
|
||||
var pointerCamera:FlxCamera = new FlxCamera();
|
||||
pointerCamera = new FlxCamera();
|
||||
pointerCamera.bgColor.alpha = 0;
|
||||
instance = new TouchPointerPlugin();
|
||||
instance.cameras = [pointerCamera];
|
||||
|
@ -125,7 +130,7 @@ class TouchPointerPlugin extends FlxTypedSpriteGroup<TouchPointer>
|
|||
add(pointer);
|
||||
}
|
||||
|
||||
pointer.updateFromTouch(touch);
|
||||
pointer.updateFromTouch(touch, pointerCamera);
|
||||
}
|
||||
|
||||
for (pointer in members)
|
||||
|
@ -226,6 +231,12 @@ class TouchPointer extends FlxSprite
|
|||
*/
|
||||
public var touchId:Int = -1;
|
||||
|
||||
/**
|
||||
* An internal point for grabbing the view position of the camera.
|
||||
* Useful for reducing point allocation.
|
||||
*/
|
||||
private var viewPoint:FlxPoint;
|
||||
|
||||
/**
|
||||
* Stores the last position of the touch pointer.
|
||||
*/
|
||||
|
@ -240,6 +251,7 @@ class TouchPointer extends FlxSprite
|
|||
super();
|
||||
makeGraphic(16, 16, FlxColor.RED);
|
||||
scrollFactor.set(0, 0);
|
||||
viewPoint = FlxPoint.get();
|
||||
lastPosition = FlxPoint.get();
|
||||
}
|
||||
|
||||
|
@ -260,12 +272,16 @@ class TouchPointer extends FlxSprite
|
|||
* Used in TouchPointerPlugin's update method.
|
||||
*
|
||||
* @param touch The FlxTouch object containing the current touch input data.
|
||||
* @param camera The FlxCamera to grab the touch's view position from.
|
||||
*/
|
||||
public function updateFromTouch(touch:FlxTouch):Void
|
||||
public function updateFromTouch(touch:FlxTouch, camera:FlxCamera):Void
|
||||
{
|
||||
// Grab the view coordinates
|
||||
touch.getViewPosition(camera, viewPoint);
|
||||
|
||||
// Update position
|
||||
x = touch.viewX - width / 2;
|
||||
y = touch.viewY - height / 2;
|
||||
x = viewPoint.x - width / 2;
|
||||
y = viewPoint.y - height / 2;
|
||||
|
||||
if (camera.target != null)
|
||||
{
|
||||
|
@ -274,7 +290,7 @@ class TouchPointer extends FlxSprite
|
|||
}
|
||||
|
||||
// Calculate angle if moving
|
||||
if (lastPosition.distanceTo(FlxPoint.weak(touch.viewX, touch.viewY)) > 3)
|
||||
if (lastPosition.distanceTo(FlxPoint.weak(viewPoint.x, viewPoint.y)) > 3)
|
||||
{
|
||||
var angle = FlxAngle.angleBetweenPoint(this, lastPosition, true);
|
||||
this.angle = angle;
|
||||
|
@ -286,11 +302,12 @@ class TouchPointer extends FlxSprite
|
|||
loadGraphic("assets/images/cursor/michael.png");
|
||||
}
|
||||
|
||||
lastPosition.set(touch.viewX, touch.viewY);
|
||||
lastPosition.copyFrom(viewPoint);
|
||||
}
|
||||
|
||||
override public function destroy():Void
|
||||
{
|
||||
viewPoint.put();
|
||||
lastPosition.put();
|
||||
super.destroy();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue