mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2025-03-25 22:29:42 -04:00
add prompt, finalize login UI
This commit is contained in:
parent
d3a873037d
commit
80e7539deb
6 changed files with 538 additions and 118 deletions
|
@ -166,6 +166,12 @@
|
|||
|
||||
|
||||
<!-- <haxedef name="SKIP_TO_PLAYSTATE" if="debug" /> -->
|
||||
<haxedef name="NG_LOGIN" if="newgrounds" />
|
||||
|
||||
<!-- Enables Ng.core.verbose -->
|
||||
<!-- <haxedef name="NG_VERBOSE" /> -->
|
||||
<!-- Enables a NG debug session, so medals don't permently unlock -->
|
||||
<!-- <haxedef name="NG_DEBUG" /> -->
|
||||
<!-- pretends that the saved session Id was expired, forcing the reconnect prompt -->
|
||||
<!-- <haxedef name="NG_FORCE_EXPIRED_SESSION" if="debug" /> -->
|
||||
|
||||
</project>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package;
|
||||
|
||||
import NGio;
|
||||
import flixel.ui.FlxButton;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxObject;
|
||||
import flixel.FlxSprite;
|
||||
|
@ -17,12 +19,13 @@ import io.newgrounds.NG;
|
|||
import lime.app.Application;
|
||||
|
||||
import ui.MenuItemList;
|
||||
import ui.Prompt;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class MainMenuState extends MusicBeatState
|
||||
{
|
||||
var menuItems:MenuItemList;
|
||||
var menuItems:MainMenuItemList;
|
||||
|
||||
var magenta:FlxSprite;
|
||||
var camFollow:FlxObject;
|
||||
|
@ -63,7 +66,7 @@ class MainMenuState extends MusicBeatState
|
|||
add(magenta);
|
||||
// magenta.scrollFactor.set();
|
||||
|
||||
menuItems = new MenuItemList('FNF_main_menu_assets');
|
||||
menuItems = new MainMenuItemList('FNF_main_menu_assets');
|
||||
add(menuItems);
|
||||
menuItems.onChange.add(onMenuItemChange);
|
||||
menuItems.onAcceptPress.add(function(_)
|
||||
|
@ -74,17 +77,18 @@ class MainMenuState extends MusicBeatState
|
|||
|
||||
var hasPopupBlocker = #if web true #else false #end;
|
||||
|
||||
menuItems.addItem('story mode', function () startExitState(new StoryMenuState()));
|
||||
menuItems.addItem('freeplay', function () startExitState(new FreeplayState()));
|
||||
menuItems.enabled = false;// disable for intro
|
||||
menuItems.createItem('story mode', function () startExitState(new StoryMenuState()));
|
||||
menuItems.createItem('freeplay', function () startExitState(new FreeplayState()));
|
||||
// addMenuItem('options', function () startExitState(new OptionMenu()));
|
||||
#if (!switch)
|
||||
menuItems.addItem('donate', selectDonate, hasPopupBlocker);
|
||||
menuItems.createItem('donate', selectDonate, hasPopupBlocker);
|
||||
#end
|
||||
#if newgrounds
|
||||
if (NG.core.loggedIn)
|
||||
menuItems.addItem("logout", selectLogout);
|
||||
menuItems.createItem("logout", selectLogout);
|
||||
else
|
||||
menuItems.addItem("login", selectLogin, hasPopupBlocker);
|
||||
menuItems.createItem("login", selectLogin);
|
||||
#end
|
||||
|
||||
// center vertically
|
||||
|
@ -109,6 +113,16 @@ class MainMenuState extends MusicBeatState
|
|||
super.create();
|
||||
}
|
||||
|
||||
override function finishTransIn()
|
||||
{
|
||||
super.finishTransIn();
|
||||
|
||||
menuItems.enabled = true;
|
||||
|
||||
if (NGio.savedSessionFailed)
|
||||
showSavedSessionFailed();
|
||||
}
|
||||
|
||||
function onMenuItemChange(selected:MenuItem)
|
||||
{
|
||||
camFollow.setPosition(selected.getGraphicMidpoint().x, selected.getGraphicMidpoint().y);
|
||||
|
@ -123,13 +137,101 @@ class MainMenuState extends MusicBeatState
|
|||
#end
|
||||
}
|
||||
|
||||
#if newgrounds
|
||||
function selectLogin()
|
||||
{
|
||||
showNgPrompt(true);
|
||||
}
|
||||
|
||||
function showSavedSessionFailed()
|
||||
{
|
||||
showNgPrompt(false);
|
||||
}
|
||||
|
||||
function showNgPrompt(fromUi:Bool)
|
||||
{
|
||||
menuItems.enabled = false;
|
||||
|
||||
var prompt = new Prompt("prompt-ng_login", "Talking to server...", None);
|
||||
prompt.closeCallback = function() menuItems.enabled = true;
|
||||
openSubState(prompt);
|
||||
function onLoginComplete(result:ConnectionResult)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case Success:
|
||||
menuItems.resetItem("login", "logout", selectLogout);
|
||||
prompt.setText("Login Successful");
|
||||
prompt.setButtons(Ok);
|
||||
prompt.onYes = prompt.close;
|
||||
case Fail(msg):
|
||||
trace("Login Error:" + msg);
|
||||
prompt.setText("Login failed");
|
||||
prompt.setButtons(Ok);
|
||||
prompt.onYes = prompt.close;
|
||||
case Cancelled:
|
||||
if (prompt != null)
|
||||
{
|
||||
prompt.setText("Login cancelled by user");
|
||||
prompt.setButtons(Ok);
|
||||
prompt.onYes = prompt.close;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NGio.login
|
||||
(
|
||||
function popupLauncher(openPassportUrl)
|
||||
{
|
||||
var choiceMsg = fromUi
|
||||
? #if web "Log in to Newgrounds?" #else null #end // User-input needed to allow popups
|
||||
: "Your session has expired.\n Please login again.";
|
||||
|
||||
if (choiceMsg != null)
|
||||
{
|
||||
prompt.setText(choiceMsg);
|
||||
prompt.setButtons(Yes_No);
|
||||
#if web
|
||||
prompt.buttons.getItem("yes").fireInstantly = true;
|
||||
#end
|
||||
prompt.onYes = function()
|
||||
{
|
||||
prompt.setText("Connecting...");
|
||||
prompt.setButtons(None);
|
||||
openPassportUrl();
|
||||
};
|
||||
prompt.onNo = function()
|
||||
{
|
||||
prompt.close();
|
||||
prompt = null;
|
||||
NG.core.cancelLoginRequest();
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
prompt.setText("Connecting...");
|
||||
openPassportUrl();
|
||||
}
|
||||
},
|
||||
onLoginComplete
|
||||
);
|
||||
}
|
||||
|
||||
function selectLogout()
|
||||
{
|
||||
menuItems.enabled = false;
|
||||
var prompt = new Prompt("prompt-ng_login", "Log out of " + NG.core.user.name + "?", Yes_No);
|
||||
prompt.closeCallback = function () menuItems.enabled = true;
|
||||
prompt.onYes = function()
|
||||
{
|
||||
NGio.logout();
|
||||
prompt.close();
|
||||
menuItems.resetItem("logout", "login", selectLogin);
|
||||
};
|
||||
prompt.onNo = prompt.close;
|
||||
openSubState(prompt);
|
||||
}
|
||||
#end
|
||||
|
||||
function startExitState(state:FlxState)
|
||||
{
|
||||
|
@ -156,9 +258,57 @@ class MainMenuState extends MusicBeatState
|
|||
FlxG.sound.music.volume += 0.5 * FlxG.elapsed;
|
||||
}
|
||||
|
||||
if (menuItems.active && controls.BACK)
|
||||
if (menuItems.enabled && controls.BACK)
|
||||
FlxG.switchState(new TitleState());
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class MainMenuItemList extends MenuTypedItemList<MainMenuItem>
|
||||
{
|
||||
public var atlas:FlxAtlasFrames;
|
||||
|
||||
public function new (atlas)
|
||||
{
|
||||
super(Vertical);
|
||||
|
||||
if (Std.is(atlas, String))
|
||||
this.atlas = Paths.getSparrowAtlas(cast atlas);
|
||||
else
|
||||
this.atlas = cast atlas;
|
||||
}
|
||||
|
||||
public function createItem(x = 0.0, y = 0.0, name:String, callback, fireInstantly = false)
|
||||
{
|
||||
var i = length;
|
||||
var item = new MainMenuItem(x, y, name, atlas, callback);
|
||||
item.fireInstantly = fireInstantly;
|
||||
item.ID = i;
|
||||
|
||||
return addItem(name, item);
|
||||
}
|
||||
|
||||
override function destroy()
|
||||
{
|
||||
super.destroy();
|
||||
atlas = null;
|
||||
}
|
||||
}
|
||||
private class MainMenuItem extends MenuItem
|
||||
{
|
||||
public function new(x = 0.0, y = 0.0, name, atlas, callback)
|
||||
{
|
||||
super(x, y, name, atlas, callback);
|
||||
scrollFactor.set();
|
||||
}
|
||||
|
||||
override function changeAnim(anim:String)
|
||||
{
|
||||
super.changeAnim(anim);
|
||||
// position by center
|
||||
centerOrigin();
|
||||
offset.copyFrom(origin);
|
||||
}
|
||||
}
|
156
source/NGio.hx
156
source/NGio.hx
|
@ -6,6 +6,7 @@ import flixel.util.FlxTimer;
|
|||
import io.newgrounds.NG;
|
||||
import io.newgrounds.NGLite;
|
||||
import io.newgrounds.components.ScoreBoardComponent.Period;
|
||||
import io.newgrounds.objects.Error;
|
||||
import io.newgrounds.objects.Medal;
|
||||
import io.newgrounds.objects.Score;
|
||||
import io.newgrounds.objects.ScoreBoard;
|
||||
|
@ -22,6 +23,11 @@ using StringTools;
|
|||
*/
|
||||
class NGio
|
||||
{
|
||||
/**
|
||||
* True, if the saved sessionId was used in the initial login, and failed to connect.
|
||||
* Used in MainMenuState to show a popup to establish a new connection
|
||||
*/
|
||||
public static var savedSessionFailed(default, null):Bool = false;
|
||||
public static var isLoggedIn:Bool = false;
|
||||
public static var scoreboardsLoaded:Bool = false;
|
||||
|
||||
|
@ -31,54 +37,68 @@ class NGio
|
|||
public static var ngScoresLoaded(default, null):FlxSignal = new FlxSignal();
|
||||
|
||||
public static var GAME_VER:String = "";
|
||||
public static var GAME_VER_NUMS:String = '';
|
||||
public static var gotOnlineVer:Bool = false;
|
||||
|
||||
|
||||
public static function noLogin(api:String)
|
||||
static public function checkVersion(callback:String->Void)
|
||||
{
|
||||
trace('INIT NOLOGIN');
|
||||
trace('checking NG.io version');
|
||||
GAME_VER = "v" + Application.current.meta.get('version');
|
||||
|
||||
if (api.length != 0)
|
||||
{
|
||||
NG.create(api);
|
||||
|
||||
new FlxTimer().start(2, function(tmr:FlxTimer)
|
||||
NG.core.calls.app.getCurrentVersion(GAME_VER)
|
||||
.addDataHandler(function(response)
|
||||
{
|
||||
var call = NG.core.calls.app.getCurrentVersion(GAME_VER).addDataHandler(function(response:Response<GetCurrentVersionResult>)
|
||||
{
|
||||
GAME_VER = response.result.data.currentVersion;
|
||||
GAME_VER_NUMS = GAME_VER.split(" ")[0].trim();
|
||||
trace('CURRENT NG VERSION: ' + GAME_VER);
|
||||
gotOnlineVer = true;
|
||||
});
|
||||
|
||||
call.send();
|
||||
});
|
||||
}
|
||||
GAME_VER = response.result.data.currentVersion;
|
||||
trace('CURRENT NG VERSION: ' + GAME_VER);
|
||||
callback(GAME_VER);
|
||||
})
|
||||
.send();
|
||||
}
|
||||
|
||||
public function new(api:String, encKey:String)
|
||||
static public function init(api:String, encKey:String)
|
||||
{
|
||||
var api = APIStuff.API;
|
||||
if (api == null || api.length == 0)
|
||||
{
|
||||
trace("Missing Newgrounds API key, aborting connection");
|
||||
return;
|
||||
}
|
||||
trace("connecting to newgrounds");
|
||||
|
||||
var sessionId:String = NGLite.getSessionId();
|
||||
if (sessionId != null)
|
||||
trace("found web session id");
|
||||
#if NG_FORCE_EXPIRED_SESSION
|
||||
var sessionId:String = "fake_session_id";
|
||||
function onSessionFail(error:Error)
|
||||
{
|
||||
trace("Forcing an expired saved session. "
|
||||
+ "To disable, comment out NG_FORCE_EXPIRED_SESSION in Project.xml");
|
||||
savedSessionFailed = true;
|
||||
}
|
||||
#else
|
||||
var sessionId:String = NGLite.getSessionId();
|
||||
if (sessionId != null)
|
||||
trace("found web session id");
|
||||
|
||||
#if (debug)
|
||||
if (sessionId == null && APIStuff.SESSION != null)
|
||||
{
|
||||
trace("using debug session id");
|
||||
sessionId = APIStuff.SESSION;
|
||||
}
|
||||
#end
|
||||
|
||||
#if (debug)
|
||||
if (sessionId == null && APIStuff.SESSION != null)
|
||||
{
|
||||
sessionId = APIStuff.SESSION;
|
||||
trace("using debug session id");
|
||||
}
|
||||
var onSessionFail:Error->Void = null;
|
||||
if (sessionId == null && FlxG.save.data.sessionId != null)
|
||||
{
|
||||
trace("using stored session id");
|
||||
sessionId = FlxG.save.data.sessionId;
|
||||
onSessionFail = function (error) savedSessionFailed = true;
|
||||
}
|
||||
#end
|
||||
|
||||
NG.create(api, sessionId, #if NG_DEBUG true #else false #end, onSessionFail);
|
||||
|
||||
NG.create(api, sessionId);
|
||||
NG.core.verbose = true;
|
||||
#if NG_VERBOSE NG.core.verbose = true; #end
|
||||
// Set the encryption cipher/format to RC4/Base64. AES128 and Hex are not implemented yet
|
||||
NG.core.initEncryption(encKey); // Found in you NG project view
|
||||
NG.core.initEncryption(APIStuff.EncKey); // Found in you NG project view
|
||||
|
||||
if (NG.core.attemptingLogin)
|
||||
{
|
||||
|
@ -89,21 +109,53 @@ class NGio
|
|||
NG.core.onLogin.add(onNGLogin);
|
||||
}
|
||||
//GK: taking out auto login, adding a login button to the main menu
|
||||
else
|
||||
// else
|
||||
// {
|
||||
// /* They are NOT playing on newgrounds.com, no session id was found. We must start one manually, if we want to.
|
||||
// * Note: This will cause a new browser window to pop up where they can log in to newgrounds
|
||||
// */
|
||||
// NG.core.requestLogin(onNGLogin);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to log in to newgrounds by requesting a new session ID, only call if no session ID was found automatically
|
||||
* @param popupLauncher The function to call to open the login url, must be inside
|
||||
* a user input event or the popup blocker will block it.
|
||||
* @param onComplete A callback with the result of the connection.
|
||||
*/
|
||||
static public function login(?popupLauncher:(Void->Void)->Void, onComplete:ConnectionResult->Void)
|
||||
{
|
||||
trace("Logging in manually");
|
||||
var onPending:Void->Void = null;
|
||||
if (popupLauncher != null)
|
||||
{
|
||||
/* They are NOT playing on newgrounds.com, no session id was found. We must start one manually, if we want to.
|
||||
* Note: This will cause a new browser window to pop up where they can log in to newgrounds
|
||||
*/
|
||||
NG.core.requestLogin(onNGLogin);
|
||||
onPending = function () popupLauncher(NG.core.openPassportUrl);
|
||||
}
|
||||
|
||||
var onSuccess:Void->Void = onNGLogin;
|
||||
var onFail:Error->Void = null;
|
||||
var onCancel:Void->Void = null;
|
||||
if (onComplete != null)
|
||||
{
|
||||
onSuccess = function ()
|
||||
{
|
||||
onNGLogin();
|
||||
onComplete(Success);
|
||||
}
|
||||
onFail = function (e) onComplete(Fail(e.message));
|
||||
onCancel = function() onComplete(Cancelled);
|
||||
}
|
||||
|
||||
NG.core.requestLogin(onSuccess, onPending, onFail, onCancel);
|
||||
}
|
||||
|
||||
function onNGLogin():Void
|
||||
static function onNGLogin():Void
|
||||
{
|
||||
trace('logged in! user:${NG.core.user.name}');
|
||||
isLoggedIn = true;
|
||||
FlxG.save.data.sessionId = NG.core.sessionId;
|
||||
// FlxG.save.flush();
|
||||
FlxG.save.flush();
|
||||
// Load medals then call onNGMedalFetch()
|
||||
NG.core.requestMedals(onNGMedalFetch);
|
||||
|
||||
|
@ -112,9 +164,17 @@ class NGio
|
|||
|
||||
ngDataLoaded.dispatch();
|
||||
}
|
||||
|
||||
static public function logout()
|
||||
{
|
||||
NG.core.logOut();
|
||||
|
||||
FlxG.save.data.sessionId = null;
|
||||
FlxG.save.flush();
|
||||
}
|
||||
|
||||
// --- MEDALS
|
||||
function onNGMedalFetch():Void
|
||||
static function onNGMedalFetch():Void
|
||||
{
|
||||
/*
|
||||
// Reading medal info
|
||||
|
@ -132,7 +192,7 @@ class NGio
|
|||
}
|
||||
|
||||
// --- SCOREBOARDS
|
||||
function onNGBoardsFetch():Void
|
||||
static function onNGBoardsFetch():Void
|
||||
{
|
||||
/*
|
||||
// Reading medal info
|
||||
|
@ -174,7 +234,7 @@ class NGio
|
|||
}
|
||||
}
|
||||
|
||||
function onNGScoresFetch():Void
|
||||
static function onNGScoresFetch():Void
|
||||
{
|
||||
scoreboardsLoaded = true;
|
||||
|
||||
|
@ -209,3 +269,13 @@ class NGio
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum ConnectionResult
|
||||
{
|
||||
/** Log in successful */
|
||||
Success;
|
||||
/** Could not login */
|
||||
Fail(msg:String);
|
||||
/** User cancelled the login */
|
||||
Cancelled;
|
||||
}
|
||||
|
|
|
@ -54,17 +54,11 @@ class TitleState extends MusicBeatState
|
|||
|
||||
super.create();
|
||||
|
||||
NGio.noLogin(APIStuff.API);
|
||||
|
||||
#if ng
|
||||
var ng:NGio = new NGio(APIStuff.API, APIStuff.EncKey);
|
||||
trace('NEWGROUNDS LOL');
|
||||
#end
|
||||
|
||||
FlxG.save.bind('funkin', 'ninjamuffin99');
|
||||
|
||||
Highscore.load();
|
||||
|
||||
NGio.init(APIStuff.API, APIStuff.EncKey);
|
||||
|
||||
if (FlxG.save.data.weekUnlocked != null)
|
||||
{
|
||||
// FIX LATER!!!
|
||||
|
@ -264,22 +258,26 @@ class TitleState extends MusicBeatState
|
|||
transitioning = true;
|
||||
// FlxG.sound.music.stop();
|
||||
|
||||
new FlxTimer().start(2, function(tmr:FlxTimer)
|
||||
if (!OutdatedSubState.leftState)
|
||||
{
|
||||
// Check if version is outdated
|
||||
|
||||
var version:String = "v" + Application.current.meta.get('version');
|
||||
|
||||
if (version.trim() != NGio.GAME_VER_NUMS && !OutdatedSubState.leftState)
|
||||
NGio.checkVersion(function(version)
|
||||
{
|
||||
trace('OLD VERSION!');
|
||||
FlxG.switchState(new OutdatedSubState());
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
});
|
||||
// Check if version is outdated
|
||||
|
||||
var localVersion:String = "v" + Application.current.meta.get('version');
|
||||
var onlineVersion = version.split(" ")[0].trim();
|
||||
|
||||
if (version.trim() != onlineVersion)
|
||||
{
|
||||
trace('OLD VERSION!');
|
||||
FlxG.switchState(new OutdatedSubState());
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
});
|
||||
}
|
||||
// FlxG.sound.play(Paths.music('titleShoot'), 0.7);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,53 +10,110 @@ import flixel.tweens.FlxEase;
|
|||
import flixel.tweens.FlxTween;
|
||||
import flixel.util.FlxSignal;
|
||||
|
||||
typedef ItemAsset = OneOfTwo<String, FlxAtlasFrames>
|
||||
typedef AtlasAsset = OneOfTwo<String, FlxAtlasFrames>;
|
||||
|
||||
class MenuItemList extends MenuTypedItemList<MenuItem>
|
||||
{
|
||||
public function addItem(x = 0.0, y = 0.0, name, callback, fireInstantly = false)
|
||||
public var atlas:FlxAtlasFrames;
|
||||
|
||||
public function new (atlas, navControls:NavControls = Vertical)
|
||||
{
|
||||
var i = length;
|
||||
var menuItem = new MenuItem(name, tex, callback, x, y);
|
||||
menuItem.fireInstantly = fireInstantly;
|
||||
menuItem.ID = i;
|
||||
add(menuItem);
|
||||
super(navControls);
|
||||
|
||||
if (i == selectedIndex)
|
||||
menuItem.select();
|
||||
|
||||
return menuItem;
|
||||
if (Std.is(atlas, String))
|
||||
this.atlas = Paths.getSparrowAtlas(cast atlas);
|
||||
else
|
||||
this.atlas = cast atlas;
|
||||
}
|
||||
|
||||
public function createItem(x = 0.0, y = 0.0, name, callback, fireInstantly = false)
|
||||
{
|
||||
var item = new MenuItem(x, y, name, atlas, callback);
|
||||
item.fireInstantly = fireInstantly;
|
||||
return addItem(name, item);
|
||||
}
|
||||
|
||||
override function destroy()
|
||||
{
|
||||
super.destroy();
|
||||
atlas = null;
|
||||
}
|
||||
}
|
||||
|
||||
class MenuTypedItemList<T:MenuItem> extends FlxTypedGroup<T>
|
||||
{
|
||||
public var tex:FlxAtlasFrames;
|
||||
public var selectedIndex = 0;
|
||||
public var selectedIndex(default, null) = 0;
|
||||
/** Called when a new item is highlighted */
|
||||
public var onChange(default, null) = new FlxTypedSignal<T->Void>();
|
||||
/** Called when an item is accepted */
|
||||
public var onAcceptPress(default, null) = new FlxTypedSignal<T->Void>();
|
||||
/** The navigation control scheme to use */
|
||||
public var navControls:NavControls;
|
||||
/** Set to false to disable nav control */
|
||||
public var enabled:Bool = true;
|
||||
|
||||
public function new (asset:ItemAsset)
|
||||
var byName = new Map<String, T>();
|
||||
/** Set to true, internally to disable controls, without affecting vars like `enabled` */
|
||||
var busy:Bool = false;
|
||||
|
||||
public function new (navControls:NavControls = Vertical)
|
||||
{
|
||||
this.navControls = navControls;
|
||||
super();
|
||||
}
|
||||
|
||||
function addItem(name:String, item:T):T
|
||||
{
|
||||
if (length == selectedIndex)
|
||||
item.select();
|
||||
|
||||
if (Std.is(asset, String))
|
||||
tex = Paths.getSparrowAtlas(cast asset);
|
||||
else
|
||||
tex = cast asset;
|
||||
byName[name] = item;
|
||||
return add(item);
|
||||
}
|
||||
|
||||
public function resetItem(oldName:String, newName:String, ?callback:Void->Void):T
|
||||
{
|
||||
if (!byName.exists(oldName))
|
||||
throw "No item named:" + oldName;
|
||||
|
||||
var item = byName[oldName];
|
||||
byName.remove(oldName);
|
||||
byName[newName] = item;
|
||||
item.setItem(newName, callback);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (enabled && !busy)
|
||||
updateControls();
|
||||
}
|
||||
|
||||
inline function updateControls()
|
||||
{
|
||||
var controls = PlayerSettings.player1.controls;
|
||||
|
||||
if (controls.UP_P)
|
||||
prev();
|
||||
|
||||
if (controls.DOWN_P)
|
||||
next();
|
||||
switch(navControls)
|
||||
{
|
||||
case Vertical:
|
||||
{
|
||||
if (controls.UP_P ) prev();
|
||||
if (controls.DOWN_P) next();
|
||||
}
|
||||
case Horizontal:
|
||||
{
|
||||
if (controls.LEFT_P ) prev();
|
||||
if (controls.RIGHT_P) next();
|
||||
}
|
||||
case Both:
|
||||
{
|
||||
if (controls.LEFT_P || controls.UP_P ) prev();
|
||||
if (controls.RIGHT_P || controls.DOWN_P) next();
|
||||
}
|
||||
}
|
||||
|
||||
if (controls.ACCEPT)
|
||||
accept();
|
||||
|
@ -71,12 +128,12 @@ class MenuTypedItemList<T:MenuItem> extends FlxTypedGroup<T>
|
|||
selected.callback();
|
||||
else
|
||||
{
|
||||
active = false;
|
||||
busy = true;
|
||||
FlxG.sound.play(Paths.sound('confirmMenu'));
|
||||
FlxFlicker.flicker(selected, 1, 0.06, true, false, function(_)
|
||||
{
|
||||
busy = false;
|
||||
selected.callback();
|
||||
active = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -87,24 +144,35 @@ class MenuTypedItemList<T:MenuItem> extends FlxTypedGroup<T>
|
|||
function changeItem(amount:Int)
|
||||
{
|
||||
FlxG.sound.play(Paths.sound('scrollMenu'));
|
||||
var index = selectedIndex + amount;
|
||||
if (index >= length)
|
||||
index = 0;
|
||||
else if (index < 0)
|
||||
index = length - 1;
|
||||
|
||||
selectItem(index);
|
||||
}
|
||||
|
||||
public function selectItem(index:Int)
|
||||
{
|
||||
members[selectedIndex].idle();
|
||||
|
||||
selectedIndex += amount;
|
||||
|
||||
if (selectedIndex >= length)
|
||||
selectedIndex = 0;
|
||||
else if (selectedIndex < 0)
|
||||
selectedIndex = length - 1;
|
||||
selectedIndex = index;
|
||||
|
||||
var selected = members[selectedIndex];
|
||||
selected.select();
|
||||
onChange.dispatch(selected);
|
||||
}
|
||||
|
||||
public function getItem(name:String)
|
||||
{
|
||||
return byName[name];
|
||||
}
|
||||
|
||||
override function destroy()
|
||||
{
|
||||
super.destroy();
|
||||
tex = null;
|
||||
byName.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,41 +184,49 @@ class MenuItem extends flixel.FlxSprite
|
|||
*/
|
||||
public var fireInstantly = false;
|
||||
|
||||
public function new (name, tex, callback, x = 0.0, y = 0.0)
|
||||
public function new (x = 0.0, y = 0.0, name, tex, callback)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
frames = tex;
|
||||
setItem(name, callback);
|
||||
antialiasing = true;
|
||||
}
|
||||
|
||||
public function setItem(name:String, callback:Void->Void)
|
||||
public function setItem(name:String, ?callback:Void->Void)
|
||||
{
|
||||
this.callback = callback;
|
||||
if (callback != null)
|
||||
this.callback = callback;
|
||||
|
||||
var selected = animation.curAnim != null && animation.curAnim.name == "selected";
|
||||
|
||||
animation.addByPrefix('idle', '$name basic', 24);
|
||||
animation.addByPrefix('selected', '$name white', 24);
|
||||
idle();
|
||||
scrollFactor.set();
|
||||
antialiasing = true;
|
||||
if (selected)
|
||||
select();
|
||||
}
|
||||
|
||||
function updateSize()
|
||||
function changeAnim(anim:String)
|
||||
{
|
||||
animation.play(anim);
|
||||
updateHitbox();
|
||||
centerOrigin();
|
||||
offset.copyFrom(origin);
|
||||
}
|
||||
|
||||
public function idle()
|
||||
{
|
||||
animation.play('idle');
|
||||
updateSize();
|
||||
changeAnim('idle');
|
||||
}
|
||||
|
||||
public function select()
|
||||
{
|
||||
animation.play('selected');
|
||||
updateSize();
|
||||
changeAnim('selected');
|
||||
}
|
||||
}
|
||||
|
||||
enum NavControls
|
||||
{
|
||||
Horizontal;
|
||||
Vertical;
|
||||
Both;
|
||||
}
|
120
source/ui/Prompt.hx
Normal file
120
source/ui/Prompt.hx
Normal file
|
@ -0,0 +1,120 @@
|
|||
package ui;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
|
||||
class Prompt extends flixel.FlxSubState
|
||||
{
|
||||
inline static var MARGIN = 100;
|
||||
|
||||
public var onYes:Void->Void;
|
||||
public var onNo:Void->Void;
|
||||
public var buttons:MenuItemList;
|
||||
public var field:FlxText;
|
||||
public var back:FlxSprite;
|
||||
|
||||
var style:ButtonStyle;
|
||||
|
||||
public function new (atlas, text:String, style:ButtonStyle = Ok)
|
||||
{
|
||||
this.style = style;
|
||||
super();
|
||||
|
||||
var texture:FlxAtlasFrames;
|
||||
if (Std.is(atlas, String))
|
||||
texture = Paths.getSparrowAtlas(cast atlas);
|
||||
else
|
||||
texture = cast atlas;
|
||||
|
||||
back = new FlxSprite();
|
||||
back.frames = texture;
|
||||
back.animation.addByPrefix("idle", "back");
|
||||
back.scrollFactor.set(0, 0);
|
||||
|
||||
buttons = new MenuItemList(texture, Horizontal);
|
||||
|
||||
field = new FlxText();
|
||||
field.setFormat(Paths.font("vcr.ttf"), 64, FlxColor.BLACK, CENTER);
|
||||
field.text = text;
|
||||
field.scrollFactor.set(0, 0);
|
||||
}
|
||||
|
||||
override function create()
|
||||
{
|
||||
super.create();
|
||||
|
||||
back.animation.play("idle");
|
||||
back.updateHitbox();
|
||||
back.screenCenter(XY);
|
||||
add(back);
|
||||
|
||||
field.y = back.y + MARGIN;
|
||||
field.screenCenter(X);
|
||||
add(field);
|
||||
|
||||
createButtons();
|
||||
add(buttons);
|
||||
}
|
||||
|
||||
public function setButtons(style:ButtonStyle)
|
||||
{
|
||||
if (this.style != style)
|
||||
{
|
||||
this.style = style;
|
||||
createButtons();
|
||||
}
|
||||
}
|
||||
|
||||
function createButtons()
|
||||
{
|
||||
// destroy previous buttons
|
||||
while(buttons.members.length > 0)
|
||||
{
|
||||
buttons.remove(buttons.members[0], true).destroy();
|
||||
}
|
||||
|
||||
switch(style)
|
||||
{
|
||||
case Yes_No : createButtonsHelper("yes", "no");
|
||||
case Ok : createButtonsHelper("ok");
|
||||
case Custom(yes, no): createButtonsHelper(yes, no);
|
||||
case None : buttons.exists = false;
|
||||
};
|
||||
}
|
||||
|
||||
function createButtonsHelper(yes:String, ?no:String)
|
||||
{
|
||||
buttons.exists = true;
|
||||
// pass anonymous functions rather than the current callbacks, in case they change later
|
||||
var yesButton = buttons.createItem(yes, function() onYes());
|
||||
yesButton.screenCenter(X);
|
||||
yesButton.y = back.y + back.height - yesButton.height - MARGIN;
|
||||
yesButton.scrollFactor.set(0, 0);
|
||||
if (no != null)
|
||||
{
|
||||
// place right
|
||||
yesButton.x = back.x + back.width - yesButton.width - MARGIN;
|
||||
|
||||
var noButton = buttons.createItem(no, function() onNo());
|
||||
noButton.x = back.x + MARGIN;
|
||||
noButton.y = back.y + back.height - noButton.height - MARGIN;
|
||||
noButton.scrollFactor.set(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public function setText(text:String)
|
||||
{
|
||||
field.text = text;
|
||||
field.screenCenter(X);
|
||||
}
|
||||
}
|
||||
|
||||
enum ButtonStyle
|
||||
{
|
||||
Ok;
|
||||
Yes_No;
|
||||
Custom(yes:String, no:Null<String>);//Todo: more than 2
|
||||
None;
|
||||
}
|
Loading…
Add table
Reference in a new issue