Compare commits
4 Commits
685cb77852
...
e3d4719aa9
Author | SHA1 | Date | |
---|---|---|---|
e3d4719aa9 | |||
a91d849489 | |||
883f093cb9 | |||
b28b2343d8 |
@ -0,0 +1,4 @@
|
||||
function init()
|
||||
{
|
||||
return new Promise(resolve => global.closePage = resolve);
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<objects>
|
||||
<script file="gui/regainFocus/emptyPage.js"/>
|
||||
</objects>
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<page>
|
||||
<include>common/styles.xml</include>
|
||||
<include>regainFocus/emptyPage.xml</include>
|
||||
</page>
|
||||
|
@ -1 +1,4 @@
|
||||
Engine.PushGuiPage("regainFocus/page_emptyPage.xml").then(Engine.PopGuiPage);
|
||||
function init()
|
||||
{
|
||||
return Engine.PushGuiPage("regainFocus/page_emptyPage.xml");
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<page>
|
||||
<include>common/styles.xml</include>
|
||||
<include>resolveReject/resolveReject.xml</include>
|
||||
</page>
|
@ -0,0 +1,5 @@
|
||||
async function init(reject)
|
||||
{
|
||||
if (reject)
|
||||
throw undefined;
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<objects>
|
||||
<script file="gui/resolveReject/resolveReject.js"/>
|
||||
</objects>
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<page>
|
||||
<include>common/styles.xml</include>
|
||||
<include>sequential/sequential.xml</include>
|
||||
</page>
|
@ -0,0 +1,5 @@
|
||||
async function init()
|
||||
{
|
||||
await Engine.PushGuiPage("regainFocus/page_emptyPage.xml");
|
||||
await Engine.PushGuiPage("regainFocus/page_emptyPage.xml");
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<objects>
|
||||
<script file="gui/sequential/sequential.js"/>
|
||||
</objects>
|
@ -7,7 +7,7 @@ class ColorMixer
|
||||
/**
|
||||
* @param {String} color - initial color as RGB string e.g. 100 0 200
|
||||
*/
|
||||
constructor(color)
|
||||
constructor()
|
||||
{
|
||||
this.panel = Engine.GetGUIObjectByName("main");
|
||||
this.colorDisplay = Engine.GetGUIObjectByName("colorDisplay");
|
||||
@ -15,8 +15,6 @@ class ColorMixer
|
||||
this.color = [0, 0, 0];
|
||||
this.sliders = [];
|
||||
this.valuesText = [];
|
||||
|
||||
this.setup(color);
|
||||
}
|
||||
|
||||
async setup(color)
|
||||
@ -68,11 +66,7 @@ class ColorMixer
|
||||
// Update return color on cancel to prevent malformed values from initial input.
|
||||
color = this.color.join(" ");
|
||||
|
||||
const buttonIndex = await closePromise;
|
||||
if (buttonIndex === 0)
|
||||
Engine.PopGuiPage(color);
|
||||
else
|
||||
Engine.PopGuiPage(this.color.join(" "));
|
||||
return await closePromise === 0 ? color : this.color.join(" ");
|
||||
}
|
||||
|
||||
updateFromSlider(index)
|
||||
@ -95,5 +89,5 @@ ColorMixer.prototype.captions = [translate("Cancel"), translate("Save")];
|
||||
|
||||
function init(color)
|
||||
{
|
||||
new ColorMixer(color);
|
||||
return new ColorMixer().setup(color);
|
||||
}
|
||||
|
@ -3,9 +3,5 @@ var g_IncompatibleModsFile = "gui/incompatible_mods/incompatible_mods.txt";
|
||||
function init(data)
|
||||
{
|
||||
Engine.GetGUIObjectByName("mainText").caption = Engine.TranslateLines(Engine.ReadFile(g_IncompatibleModsFile));
|
||||
}
|
||||
|
||||
function closePage()
|
||||
{
|
||||
Engine.PopGuiPage();
|
||||
return new Promise(popGuiPage => { Engine.GetGUIObjectByName("btnClose").onPress = popGuiPage; });
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
<object name="btnClose" type="button" style="ModernButtonRed" size="18 100%-45 100%-18 100%-17" hotkey="cancel">
|
||||
<translatableAttribute id="caption">Ok</translatableAttribute>
|
||||
<action on="Press">closePage();</action>
|
||||
</object>
|
||||
|
||||
</object>
|
||||
|
@ -27,10 +27,10 @@ var g_ModIOState = {
|
||||
/**
|
||||
* Finished status indicators
|
||||
*/
|
||||
"ready": progressData => {
|
||||
"ready": (progressData, popGuiPage) => {
|
||||
// GameID acquired, ready to fetch mod list
|
||||
if (!g_RequestCancelled)
|
||||
updateModList();
|
||||
updateModList(popGuiPage);
|
||||
},
|
||||
"listed": progressData => {
|
||||
// List of available mods acquired
|
||||
@ -65,7 +65,7 @@ var g_ModIOState = {
|
||||
/**
|
||||
* Error/Failure status indicators.
|
||||
*/
|
||||
"failed_gameid": async(progressData) => {
|
||||
"failed_gameid": async(progressData, popGuiPage) => {
|
||||
// Game ID couldn't be retrieved
|
||||
const promise = showErrorMessageBox(
|
||||
sprintf(translateWithContext("mod.io error message", "Game ID could not be retrieved.\n\n%(technicalDetails)s"), {
|
||||
@ -76,11 +76,11 @@ var g_ModIOState = {
|
||||
if (!promise)
|
||||
return;
|
||||
if (await promise === 0)
|
||||
closePage();
|
||||
popGuiPage();
|
||||
else
|
||||
init();
|
||||
},
|
||||
"failed_listing": async(progressData) => {
|
||||
"failed_listing": async(progressData, popGuiPage) => {
|
||||
// Mod list couldn't be retrieved
|
||||
const promise = showErrorMessageBox(
|
||||
sprintf(translateWithContext("mod.io error message", "Mod List could not be retrieved.\n\n%(technicalDetails)s"), {
|
||||
@ -91,9 +91,9 @@ var g_ModIOState = {
|
||||
if (!promise)
|
||||
return;
|
||||
if (await promise === 0)
|
||||
cancelModListUpdate();
|
||||
cancelModListUpdate(popGuiPage);
|
||||
else
|
||||
updateModList();
|
||||
updateModList(popGuiPage);
|
||||
},
|
||||
"failed_downloading": async(progressData) => {
|
||||
// File couldn't be retrieved
|
||||
@ -131,7 +131,7 @@ var g_ModIOState = {
|
||||
}
|
||||
};
|
||||
|
||||
async function init(data)
|
||||
function init(data)
|
||||
{
|
||||
const promise = progressDialog(
|
||||
translate("Initializing mod.io interface."),
|
||||
@ -142,11 +142,16 @@ async function init(data)
|
||||
g_Failure = false;
|
||||
Engine.ModIoStartGetGameId();
|
||||
|
||||
await promise;
|
||||
closePage();
|
||||
return Promise.race([
|
||||
promise,
|
||||
new Promise(popGuiPage => {
|
||||
Engine.GetGUIObjectByName("backButton").onPress = popGuiPage;
|
||||
Engine.GetGUIObjectByName("modio").onTick = onTick.bind(null, popGuiPage);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function onTick()
|
||||
function onTick(popGuiPage)
|
||||
{
|
||||
let progressData = Engine.ModIoGetDownloadProgress();
|
||||
|
||||
@ -157,7 +162,7 @@ function onTick()
|
||||
return;
|
||||
}
|
||||
|
||||
handler(progressData);
|
||||
handler(progressData, popGuiPage);
|
||||
if (!progressData.status.startsWith("failed"))
|
||||
Engine.ModIoAdvanceRequest();
|
||||
}
|
||||
@ -230,13 +235,13 @@ function showModDescription()
|
||||
Engine.GetGUIObjectByName("modError").caption = isSelected && isInvalid ? sprintf(translate("Invalid mod: %(error)s"), {"error": g_ModsAvailableOnline[selected].error }) : "";
|
||||
}
|
||||
|
||||
function cancelModListUpdate()
|
||||
function cancelModListUpdate(popGuiPage)
|
||||
{
|
||||
cancelRequest();
|
||||
|
||||
if (!g_ModsAvailableOnline.length)
|
||||
{
|
||||
closePage();
|
||||
popGuiPage();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -244,7 +249,7 @@ function cancelModListUpdate()
|
||||
Engine.GetGUIObjectByName('refreshButton').enabled = true;
|
||||
}
|
||||
|
||||
async function updateModList()
|
||||
async function updateModList(popGuiPage)
|
||||
{
|
||||
clearModList();
|
||||
Engine.GetGUIObjectByName("refreshButton").enabled = false;
|
||||
@ -260,7 +265,7 @@ async function updateModList()
|
||||
Engine.ModIoStartListMods();
|
||||
|
||||
await promise;
|
||||
cancelModListUpdate();
|
||||
cancelModListUpdate(popGuiPage);
|
||||
}
|
||||
|
||||
async function downloadMod()
|
||||
@ -296,11 +301,6 @@ function cancelRequest()
|
||||
hideDialog();
|
||||
}
|
||||
|
||||
function closePage()
|
||||
{
|
||||
Engine.PopGuiPage();
|
||||
}
|
||||
|
||||
function showErrorMessageBox(caption, title, buttonCaptions)
|
||||
{
|
||||
if (g_Failure)
|
||||
|
@ -8,11 +8,6 @@
|
||||
<object type="image" sprite="ModernFade"/>
|
||||
|
||||
<object name="modio" type="image" style="ModernDialog" size="10% 10% 90% 90%">
|
||||
|
||||
<action on="Tick">
|
||||
onTick();
|
||||
</action>
|
||||
|
||||
<!-- Page Title -->
|
||||
<object style="ModernLabelText" type="text" size="50%-128 -18 50%+128 14">
|
||||
<translatableAttribute id="caption">mod.io Mods</translatableAttribute>
|
||||
@ -84,9 +79,8 @@
|
||||
</object>
|
||||
|
||||
<!-- Buttons -->
|
||||
<object type="button" style="ModernButtonRed" size="100%-552 100%-44 100%-372 100%-16">
|
||||
<object name="backButton" type="button" style="ModernButtonRed" size="100%-552 100%-44 100%-372 100%-16">
|
||||
<translatableAttribute id="caption">Back</translatableAttribute>
|
||||
<action on="Press">closePage();</action>
|
||||
</object>
|
||||
|
||||
<object name="refreshButton" type="button" style="ModernButtonRed" size="100%-368 100%-44 100%-188 100%-16" enabled="false">
|
||||
|
@ -1,4 +1,5 @@
|
||||
function init(data)
|
||||
{
|
||||
Engine.GetGUIObjectByName("mainText").caption = Engine.TranslateLines(Engine.ReadFile("gui/modmod/help/help.txt"));
|
||||
return new Promise(popGuiPage => { Engine.GetGUIObjectByName("closeButton").onPress = popGuiPage; });
|
||||
}
|
||||
|
@ -17,9 +17,8 @@
|
||||
<object name="mainText" type="text" style="ModernTextPanel"/>
|
||||
</object>
|
||||
|
||||
<object type="button" style="ModernButtonRed" tooltip_style="snToolTip" size="100%-602 100%-52 100%-412 100%-24" hotkey="cancel">
|
||||
<object name="closeButton" type="button" style="ModernButtonRed" tooltip_style="snToolTip" size="100%-602 100%-52 100%-412 100%-24" hotkey="cancel">
|
||||
<translatableAttribute id="caption">Close</translatableAttribute>
|
||||
<action on="Press">Engine.PopGuiPage();</action>
|
||||
</object>
|
||||
<object type="button" style="ModernButtonRed" size="100%-408 100%-52 100%-218 100%-24">
|
||||
<translatableAttribute id="caption">Modding Guide</translatableAttribute>
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Currently limited to at most 3 buttons per message box.
|
||||
* The convention is to have "cancel" appear first.
|
||||
*/
|
||||
async function init(data)
|
||||
function init(data)
|
||||
{
|
||||
// Set title
|
||||
Engine.GetGUIObjectByName("mbTitleBar").caption = data.title;
|
||||
@ -15,7 +15,6 @@ async function init(data)
|
||||
|
||||
// Default behaviour
|
||||
let mbCancelHotkey = Engine.GetGUIObjectByName("mbCancelHotkey");
|
||||
mbCancelHotkey.onPress = Engine.PopGuiPage;
|
||||
|
||||
// Calculate size
|
||||
let mbLRDiff = data.width / 2;
|
||||
@ -28,5 +27,5 @@ async function init(data)
|
||||
const closePromise = setButtonCaptionsAndVisibitily(mbButton, captions, mbCancelHotkey, "mbButton");
|
||||
distributeButtonsHorizontally(mbButton, captions);
|
||||
|
||||
Engine.PopGuiPage(await closePromise);
|
||||
return closePromise;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ var g_TermsPage;
|
||||
var g_TermsFile;
|
||||
var g_TermsSprintf;
|
||||
|
||||
function init(data)
|
||||
async function init(data)
|
||||
{
|
||||
g_TermsPage = data.page;
|
||||
g_TermsFile = data.file;
|
||||
@ -20,6 +20,12 @@ function init(data)
|
||||
Engine.GetGUIObjectByName("title").caption = data.title;
|
||||
initURLButtons(data.termsURL, data.urlButtons);
|
||||
initLanguageSelection();
|
||||
|
||||
const accepted = await new Promise(resolve => {
|
||||
Engine.GetGUIObjectByName("cancelButton").onPress = resolve.bind(null, false);
|
||||
Engine.GetGUIObjectByName("connectButton").onPress = resolve.bind(null, true);
|
||||
});
|
||||
return arangeReturnValue(accepted);
|
||||
}
|
||||
|
||||
function initURLButtons(termsURL, urlButtons)
|
||||
@ -83,10 +89,10 @@ function initLanguageSelection()
|
||||
languageDropdown.selected = languageDropdown.list.length - 1;
|
||||
}
|
||||
|
||||
function closeTerms(accepted)
|
||||
function arangeReturnValue(accepted)
|
||||
{
|
||||
Engine.PopGuiPage({
|
||||
return {
|
||||
"page": g_TermsPage,
|
||||
"accepted": accepted
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -29,14 +29,12 @@
|
||||
<object size="170 0 330 100%" type="button" name="button[1]" style="ModernButtonRed" hidden="true"/>
|
||||
|
||||
<object size="100%-355 0 100% 100%">
|
||||
<object type="button" style="ModernButtonRed" size="0 0 160 100%" hotkey="cancel">
|
||||
<object name="cancelButton" type="button" style="ModernButtonRed" size="0 0 160 100%" hotkey="cancel">
|
||||
<translatableAttribute id="caption">Decline</translatableAttribute>
|
||||
<action on="Press">closeTerms(false);</action>
|
||||
</object>
|
||||
|
||||
<object name="connectButton" type="button" style="ModernButtonRed" size="170 0 330 100%">
|
||||
<translatableAttribute id="caption">Accept</translatableAttribute>
|
||||
<action on="Press">closeTerms(true);</action>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
@ -15,15 +15,14 @@ class TimedConfirmation
|
||||
* @param {String|undefined} data.buttonCaptions - The captions used for buttons (if not defined, defaults to 'OK')
|
||||
* @param {String|undefined} data.font - The used font
|
||||
*/
|
||||
constructor(data)
|
||||
constructor()
|
||||
{
|
||||
this.messageObject = Engine.GetGUIObjectByName("tmcText");
|
||||
this.panel = Engine.GetGUIObjectByName("tmcMain");
|
||||
this.panel.onTick = this.onTick.bind(this);
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
async setup(data)
|
||||
setup(data)
|
||||
{
|
||||
Engine.GetGUIObjectByName("tmcTitleBar").caption = data.title;
|
||||
|
||||
@ -37,7 +36,6 @@ class TimedConfirmation
|
||||
this.updateDisplayedTimer(data.timeout);
|
||||
|
||||
const cancelHotkey = Engine.GetGUIObjectByName("tmcCancelHotkey");
|
||||
cancelHotkey.onPress = Engine.PopGuiPage;
|
||||
|
||||
const lRDiff = data.width / 2;
|
||||
const uDDiff = data.height / 2;
|
||||
@ -49,8 +47,7 @@ class TimedConfirmation
|
||||
const closePromise =
|
||||
setButtonCaptionsAndVisibitily(button, captions, cancelHotkey, "tmcButton");
|
||||
distributeButtonsHorizontally(button, captions);
|
||||
|
||||
Engine.PopGuiPage(await closePromise);
|
||||
return closePromise;
|
||||
}
|
||||
|
||||
onTick()
|
||||
@ -73,5 +70,5 @@ class TimedConfirmation
|
||||
|
||||
function init(data)
|
||||
{
|
||||
new TimedConfirmation(data);
|
||||
return new TimedConfirmation().setup(data);
|
||||
}
|
||||
|
@ -5,11 +5,11 @@
|
||||
*/
|
||||
class NewCampaignModal
|
||||
{
|
||||
constructor(campaignTemplate)
|
||||
constructor(campaignTemplate, popGuiPage)
|
||||
{
|
||||
this.template = campaignTemplate;
|
||||
|
||||
Engine.GetGUIObjectByName('cancelButton').onPress = () => Engine.PopGuiPage();
|
||||
Engine.GetGUIObjectByName('cancelButton').onPress = popGuiPage;
|
||||
Engine.GetGUIObjectByName('startButton').onPress = () => this.createAndStartCampaign();
|
||||
Engine.GetGUIObjectByName('runDescription').caption = translateWithContext("Campaign Template", this.template.Name);
|
||||
Engine.GetGUIObjectByName('runDescription').onTextEdit = () => {
|
||||
@ -38,5 +38,7 @@ var g_NewCampaignModal;
|
||||
|
||||
function init(campaign_template_data)
|
||||
{
|
||||
g_NewCampaignModal = new NewCampaignModal(campaign_template_data);
|
||||
return new Promise(popGuiPage => {
|
||||
g_NewCampaignModal = new NewCampaignModal(campaign_template_data, popGuiPage);
|
||||
});
|
||||
}
|
||||
|
@ -59,6 +59,8 @@ function init()
|
||||
category => {
|
||||
Engine.GetGUIObjectByName("creditsText").caption = g_PanelData[category].content;
|
||||
});
|
||||
|
||||
return new Promise(popGuiPage => { Engine.GetGUIObjectByName("closeButton").onPress = popGuiPage; });
|
||||
}
|
||||
|
||||
// Run through a "Content" list and parse elements for formatting and translation
|
||||
|
@ -28,11 +28,8 @@
|
||||
</object>
|
||||
|
||||
<!-- Close dialog -->
|
||||
<object type="button" style="ModernButtonRed" size="100%-200 100%-45 100%-17 100%-17" hotkey="cancel">
|
||||
<object name="closeButton" type="button" style="ModernButtonRed" size="100%-200 100%-45 100%-17 100%-17" hotkey="cancel">
|
||||
<translatableAttribute id="caption">Close</translatableAttribute>
|
||||
<action on="Press">
|
||||
Engine.PopGuiPage();
|
||||
</action>
|
||||
</object>
|
||||
</object>
|
||||
</objects>
|
||||
|
@ -24,7 +24,7 @@ var g_IsRejoining = false;
|
||||
var g_PlayerAssignments; // used when rejoining
|
||||
var g_UserRating;
|
||||
|
||||
function init(attribs)
|
||||
async function init(attribs)
|
||||
{
|
||||
g_UserRating = attribs.rating;
|
||||
|
||||
@ -45,6 +45,8 @@ function init(attribs)
|
||||
}
|
||||
else if (startJoinFromLobby(attribs.name, attribs.hostJID, ""))
|
||||
switchSetupPage("pageConnecting");
|
||||
else if (cancelSetup())
|
||||
return;
|
||||
break;
|
||||
}
|
||||
case "host":
|
||||
@ -68,6 +70,22 @@ function init(attribs)
|
||||
error("Unrecognised multiplayer game type: " + attribs.multiplayerGameType);
|
||||
break;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
await new Promise(resolve => {
|
||||
Engine.GetGUIObjectByName("cancelButton").onPress = () => { resolve(); };
|
||||
Engine.GetGUIObjectByName("multiplayerPages").onTick = () => { onTick() && resolve(); };
|
||||
Engine.GetGUIObjectByName("continueButton").onPress = () => {
|
||||
confirmSetup() && resolve();
|
||||
};
|
||||
Engine.GetGuiObjectByName("confirmPasswordButton").onPress = () => {
|
||||
confirmPassword() && resolve();
|
||||
};
|
||||
});
|
||||
if (cancelSetup())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function cancelSetup()
|
||||
@ -80,10 +98,7 @@ function cancelSetup()
|
||||
|
||||
// Keep the page open if an attempt to join/host by ip failed
|
||||
if (!g_IsConnecting || (Engine.HasXmppClient() && g_GameType == "client"))
|
||||
{
|
||||
Engine.PopGuiPage();
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
|
||||
g_IsConnecting = false;
|
||||
Engine.GetGUIObjectByName("hostFeedback").caption = "";
|
||||
@ -94,17 +109,22 @@ function cancelSetup()
|
||||
switchSetupPage("pageHost");
|
||||
else
|
||||
error("cancelSetup: Unrecognised multiplayer game type: " + g_GameType);
|
||||
return false;
|
||||
}
|
||||
|
||||
function confirmPassword()
|
||||
{
|
||||
if (Engine.GetGUIObjectByName("pagePassword").hidden)
|
||||
return;
|
||||
return false;
|
||||
if (startJoinFromLobby(g_ServerName, g_ServerId, Engine.GetGUIObjectByName("clientPassword").caption))
|
||||
{
|
||||
switchSetupPage("pageConnecting");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function confirmSetup()
|
||||
function confirmSetup(popGuiPage)
|
||||
{
|
||||
if (!Engine.GetGUIObjectByName("pageJoin").hidden)
|
||||
{
|
||||
@ -113,15 +133,20 @@ function confirmSetup()
|
||||
let joinPort = Engine.GetGUIObjectByName("joinPort").caption;
|
||||
|
||||
if (startJoin(joinPlayerName, joinServer, getValidPort(joinPort)))
|
||||
{
|
||||
switchSetupPage("pageConnecting");
|
||||
return false;
|
||||
}
|
||||
return true
|
||||
}
|
||||
else if (!Engine.GetGUIObjectByName("pageHost").hidden)
|
||||
|
||||
if (!Engine.GetGUIObjectByName("pageHost").hidden)
|
||||
{
|
||||
let hostServerName = Engine.GetGUIObjectByName("hostServerName").caption;
|
||||
if (!hostServerName)
|
||||
{
|
||||
Engine.GetGUIObjectByName("hostFeedback").caption = translate("Please enter a valid server name.");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
let hostPort = Engine.GetGUIObjectByName("hostPort").caption;
|
||||
@ -132,13 +157,17 @@ function confirmSetup()
|
||||
"min": g_ValidPorts.min,
|
||||
"max": g_ValidPorts.max
|
||||
});
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
let hostPlayerName = Engine.GetGUIObjectByName("hostPlayerName").caption;
|
||||
let hostPassword = Engine.GetGUIObjectByName("hostPassword").caption;
|
||||
if (startHost(hostPlayerName, hostServerName, getValidPort(hostPort), hostPassword))
|
||||
if (startHost(popGuiPage, hostPlayerName, hostServerName, getValidPort(hostPort), hostPassword))
|
||||
{
|
||||
switchSetupPage("pageConnecting");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,12 +179,12 @@ function startConnectionStatus(type)
|
||||
Engine.GetGUIObjectByName("connectionStatus").caption = translate("Connecting to server...");
|
||||
}
|
||||
|
||||
function onTick()
|
||||
function onTick(popGuiPage)
|
||||
{
|
||||
if (!g_IsConnecting)
|
||||
return;
|
||||
return false;
|
||||
|
||||
pollAndHandleNetworkClient();
|
||||
return pollAndHandleNetworkClient();
|
||||
}
|
||||
|
||||
function getConnectionFailReason(reason)
|
||||
@ -202,9 +231,8 @@ function pollAndHandleNetworkClient()
|
||||
switch (message.status)
|
||||
{
|
||||
case "failed":
|
||||
cancelSetup();
|
||||
reportConnectionFail(message.reason, false);
|
||||
return;
|
||||
return true;
|
||||
|
||||
default:
|
||||
error("Unrecognised netstatus type: " + message.status);
|
||||
@ -216,9 +244,8 @@ function pollAndHandleNetworkClient()
|
||||
switch (message.status)
|
||||
{
|
||||
case "disconnected":
|
||||
cancelSetup();
|
||||
reportDisconnect(message.reason, false);
|
||||
return;
|
||||
return true;
|
||||
|
||||
default:
|
||||
error("Unrecognised netstatus type: " + message.status);
|
||||
@ -238,7 +265,7 @@ function pollAndHandleNetworkClient()
|
||||
});
|
||||
|
||||
// Process further pending netmessages in the session page
|
||||
return;
|
||||
return false;
|
||||
|
||||
case "chat":
|
||||
break;
|
||||
@ -259,9 +286,8 @@ function pollAndHandleNetworkClient()
|
||||
switch (message.status)
|
||||
{
|
||||
case "failed":
|
||||
cancelSetup();
|
||||
reportConnectionFail(message.reason, false);
|
||||
return;
|
||||
return true;
|
||||
|
||||
default:
|
||||
error("Unrecognised netstatus type: " + message.status);
|
||||
@ -281,18 +307,17 @@ function pollAndHandleNetworkClient()
|
||||
{
|
||||
Engine.GetGUIObjectByName("connectionStatus").caption = translate("Game has already started, rejoining...");
|
||||
g_IsRejoining = true;
|
||||
return; // we'll process the game setup messages in the next tick
|
||||
return false; // we'll process the game setup messages in the next tick
|
||||
}
|
||||
Engine.SwitchGuiPage("page_gamesetup.xml", {
|
||||
"serverName": g_ServerName,
|
||||
"hasPassword": g_ServerHasPassword
|
||||
});
|
||||
return; // don't process any more messages - leave them for the game GUI loop
|
||||
return false; // don't process any more messages - leave them for the game GUI loop
|
||||
|
||||
case "disconnected":
|
||||
cancelSetup();
|
||||
reportDisconnect(message.reason, false);
|
||||
return;
|
||||
return true;
|
||||
|
||||
default:
|
||||
error("Unrecognised netstatus type: " + message.status);
|
||||
@ -350,14 +375,13 @@ function startHost(playername, servername, port, password)
|
||||
Engine.ConfigDB_CreateValue("user", "playername.multiplayer", playername);
|
||||
Engine.ConfigDB_CreateValue("user", "multiplayerhosting.port", port);
|
||||
Engine.ConfigDB_SaveChanges("user");
|
||||
|
||||
|
||||
let hostFeedback = Engine.GetGUIObjectByName("hostFeedback");
|
||||
|
||||
// Disallow identically named games in the multiplayer lobby
|
||||
if (Engine.HasXmppClient() &&
|
||||
Engine.GetGameList().some(game => game.name == servername))
|
||||
{
|
||||
cancelSetup();
|
||||
hostFeedback.caption = translate("Game name already in use.");
|
||||
return false;
|
||||
}
|
||||
@ -370,7 +394,6 @@ function startHost(playername, servername, port, password)
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
cancelSetup();
|
||||
messageBox(
|
||||
400, 200,
|
||||
sprintf(translate("Cannot host game: %(message)s."), { "message": e.message }),
|
||||
@ -399,7 +422,6 @@ function startJoin(playername, ip, port)
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
cancelSetup();
|
||||
messageBox(
|
||||
400, 200,
|
||||
sprintf(translate("Cannot join game: %(message)s."), { "message": e.message }),
|
||||
@ -429,7 +451,6 @@ function startJoinFromLobby(playername, hostJID, password)
|
||||
{
|
||||
if (!Engine.HasXmppClient())
|
||||
{
|
||||
cancelSetup();
|
||||
messageBox(
|
||||
400, 200,
|
||||
sprintf("You cannot join a lobby game without logging in to the lobby."),
|
||||
@ -444,7 +465,6 @@ function startJoinFromLobby(playername, hostJID, password)
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
cancelSetup();
|
||||
messageBox(
|
||||
400, 200,
|
||||
sprintf(translate("Cannot join game: %(message)s."), { "message": e.message }),
|
||||
|
@ -10,10 +10,6 @@
|
||||
|
||||
<object name="multiplayerPages" type="image" style="ModernDialog" size="50%-230 50%-120 50%+230 50%+120">
|
||||
|
||||
<action on="Tick">
|
||||
onTick();
|
||||
</action>
|
||||
|
||||
<object style="ModernLabelText" type="text" size="50%-128 0%-16 50%+128 16">
|
||||
<translatableAttribute id="caption">Multiplayer</translatableAttribute>
|
||||
</object>
|
||||
@ -134,12 +130,10 @@
|
||||
|
||||
<object name="continueButton" hotkey="confirm" type="button" size="50%+5 100%-45 100%-18 100%-17" style="ModernButtonRed">
|
||||
<translatableAttribute id="caption">Continue</translatableAttribute>
|
||||
<action on="Press">confirmSetup();</action>
|
||||
</object>
|
||||
|
||||
<object type="button" style="ModernButtonRed" size="18 100%-45 50%-5 100%-17" hotkey="cancel">
|
||||
<object name="cancelButton" type="button" style="ModernButtonRed" size="18 100%-45 50%-5 100%-17" hotkey="cancel">
|
||||
<translatableAttribute id="caption">Cancel</translatableAttribute>
|
||||
<action on="Press">cancelSetup();</action>
|
||||
</object>
|
||||
|
||||
<object name="pageConnecting" hidden="true">
|
||||
@ -160,7 +154,6 @@
|
||||
</object>
|
||||
<object name="confirmPasswordButton" hotkey="confirm" type="button" size="50%+5 100%-45 100%-18 100%-17" style="ModernButtonRed">
|
||||
<translatableAttribute id="caption">Confirm</translatableAttribute>
|
||||
<action on="Press">confirmPassword();</action>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
@ -1,6 +1,6 @@
|
||||
class HotkeysPage
|
||||
{
|
||||
constructor(metadata)
|
||||
constructor(metadata, popGuiPage)
|
||||
{
|
||||
this.metadata = metadata;
|
||||
|
||||
@ -23,7 +23,7 @@ class HotkeysPage
|
||||
this.saveButton = Engine.GetGUIObjectByName("hotkeySave");
|
||||
this.saveButton.enabled = false;
|
||||
|
||||
Engine.GetGUIObjectByName("hotkeyClose").onPress = () => Engine.PopGuiPage();
|
||||
Engine.GetGUIObjectByName("hotkeyClose").onPress = popGuiPage;
|
||||
Engine.GetGUIObjectByName("hotkeyReset").onPress = () => this.resetUserHotkeys();
|
||||
this.saveButton.onPress = () => {
|
||||
this.saveUserHotkeys();
|
||||
@ -190,7 +190,9 @@ class HotkeysPage
|
||||
|
||||
function init()
|
||||
{
|
||||
let hotkeyPage = new HotkeysPage(new HotkeyMetadata());
|
||||
return new Promise(popGuiPage => {
|
||||
let hotkeyPage = new HotkeysPage(new HotkeyMetadata(), popGuiPage);
|
||||
});
|
||||
}
|
||||
|
||||
HotkeysPage.prototype.UnavailableTooltipString = markForTranslation("No tooltip available.");
|
||||
|
@ -3,8 +3,9 @@
|
||||
*/
|
||||
class SavegameLoader
|
||||
{
|
||||
constructor()
|
||||
constructor(popGuiPage)
|
||||
{
|
||||
this.popGuiPage = popGuiPage;
|
||||
this.confirmButton = Engine.GetGUIObjectByName("confirmButton");
|
||||
this.confirmButton.caption = translate("Load");
|
||||
this.confirmButton.enabled = false;
|
||||
@ -27,7 +28,7 @@ class SavegameLoader
|
||||
|
||||
if (sameEngineVersion && sameMods)
|
||||
{
|
||||
Engine.PopGuiPage(gameId);
|
||||
this.popGuiPage(gameId);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -60,6 +61,6 @@ class SavegameLoader
|
||||
translate("Warning"),
|
||||
[translate("No"), translate("Yes")]);
|
||||
if (buttonIndex === 1)
|
||||
Engine.PopGuiPage(gameId);
|
||||
this.popGuiPage(gameId);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
class SavegamePage
|
||||
{
|
||||
constructor(data)
|
||||
constructor(data, popGuiPage)
|
||||
{
|
||||
this.savegameList = new SavegameList(data && data.campaignRun || null);
|
||||
|
||||
@ -18,7 +18,7 @@ class SavegamePage
|
||||
const savePage = !!data?.savedGameData;
|
||||
if (savePage)
|
||||
{
|
||||
this.savegameWriter = new SavegameWriter(data.savedGameData);
|
||||
this.savegameWriter = new SavegameWriter(popGuiPage, data.savedGameData);
|
||||
this.savegameList.registerSelectionChangeHandler(this.savegameWriter);
|
||||
let size = this.savegameList.gameSelection.size;
|
||||
size.bottom -= 24;
|
||||
@ -26,13 +26,13 @@ class SavegamePage
|
||||
}
|
||||
else
|
||||
{
|
||||
this.savegameLoader = new SavegameLoader();
|
||||
this.savegameLoader = new SavegameLoader(popGuiPage);
|
||||
this.savegameList.registerSelectionChangeHandler(this.savegameLoader);
|
||||
this.savegameList.selectFirst();
|
||||
}
|
||||
|
||||
Engine.GetGUIObjectByName("title").caption = savePage ? translate("Save Game") : translate("Load Game");
|
||||
Engine.GetGUIObjectByName("cancel").onPress = () => { Engine.PopGuiPage(); };
|
||||
Engine.GetGUIObjectByName("cancel").onPress = popGuiPage;
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,5 +40,5 @@ var g_SavegamePage;
|
||||
|
||||
function init(data)
|
||||
{
|
||||
g_SavegamePage = new SavegamePage(data);
|
||||
return new Promise(popGuiPage => { g_SavegamePage = new SavegamePage(data, popGuiPage); });
|
||||
}
|
||||
|
@ -4,8 +4,9 @@
|
||||
*/
|
||||
class SavegameWriter
|
||||
{
|
||||
constructor(savedGameData)
|
||||
constructor(popGuiPage, savedGameData)
|
||||
{
|
||||
this.popGuiPage = popGuiPage;
|
||||
this.savedGameData = savedGameData;
|
||||
|
||||
let saveNew = () => {
|
||||
@ -58,6 +59,6 @@ class SavegameWriter
|
||||
|
||||
Engine[gameID ? "SaveGame" : "SaveGamePrefix"](name, desc, this.savedGameData);
|
||||
|
||||
Engine.PopGuiPage();
|
||||
this.popGuiPage();
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ class LobbyHandler
|
||||
|
||||
this.profilePage = new ProfilePage(this.xmppMessages);
|
||||
this.leaderboardPage = new LeaderboardPage(this.xmppMessages);
|
||||
this.lobbyPage = new LobbyPage(dialog, this.xmppMessages, this.leaderboardPage, this.profilePage);
|
||||
this.lobbyPage = new LobbyPage(popGuiPage, dialog, this.xmppMessages, this.leaderboardPage, this.profilePage);
|
||||
|
||||
this.xmppMessages.processHistoricMessages();
|
||||
|
||||
|
@ -3,8 +3,9 @@
|
||||
*/
|
||||
class QuitButton
|
||||
{
|
||||
constructor(dialog, leaderboardPage, profilePage)
|
||||
constructor(popGuiPage, dialog, leaderboardPage, profilePage)
|
||||
{
|
||||
this.popGuiPage = popGuiPage;
|
||||
let closeDialog = this.closeDialog.bind(this);
|
||||
let returnToMainMenu = this.returnToMainMenu.bind(this);
|
||||
let onPress = dialog ? closeDialog : returnToMainMenu;
|
||||
@ -29,7 +30,7 @@ class QuitButton
|
||||
closeDialog()
|
||||
{
|
||||
Engine.LobbySetPlayerPresence("playing");
|
||||
Engine.PopGuiPage();
|
||||
this.popGuiPage();
|
||||
}
|
||||
|
||||
returnToMainMenu()
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
class LobbyPage
|
||||
{
|
||||
constructor(dialog, xmppMessages, leaderboardPage, profilePage)
|
||||
constructor(popGuiPage, dialog, xmppMessages, leaderboardPage, profilePage)
|
||||
{
|
||||
Engine.ProfileStart("Create LobbyPage");
|
||||
let mapCache = new MapCache();
|
||||
@ -19,7 +19,7 @@ class LobbyPage
|
||||
"joinButton": new JoinButton(dialog, gameList),
|
||||
"leaderboardButton": new LeaderboardButton(xmppMessages, leaderboardPage),
|
||||
"profileButton": new ProfileButton(xmppMessages, profilePage),
|
||||
"quitButton": new QuitButton(dialog, leaderboardPage, profilePage)
|
||||
"quitButton": new QuitButton(popGuiPage, dialog, leaderboardPage, profilePage)
|
||||
},
|
||||
"panels": {
|
||||
"chatPanel": new ChatPanel(xmppMessages),
|
||||
|
@ -34,7 +34,9 @@ var g_LobbyHandler;
|
||||
function init(attribs)
|
||||
{
|
||||
if (g_Settings)
|
||||
g_LobbyHandler = new LobbyHandler(attribs && attribs.dialog);
|
||||
else
|
||||
error("Could not load settings");
|
||||
return new Promise(popGuiPage => {
|
||||
g_LobbyHandler = new LobbyHandler(popGuiPage, attribs && attribs.dialog)
|
||||
};
|
||||
|
||||
error("Could not load settings");
|
||||
}
|
||||
|
@ -21,11 +21,8 @@ function init()
|
||||
localeText.caption = "long";
|
||||
else
|
||||
localeText.caption = currentLocale;
|
||||
}
|
||||
|
||||
function cancelSetup()
|
||||
{
|
||||
Engine.PopGuiPage();
|
||||
return new Promise(popGuiPage => { Engine.GetGUIObjectByName("cancelButton").onPress = popGuiPage; });
|
||||
}
|
||||
|
||||
function applySelectedLocale()
|
||||
|
@ -32,9 +32,8 @@
|
||||
</object>
|
||||
<object name="localeText" type="text" size="40%+10 80 100% 105" textcolor="white" />
|
||||
|
||||
<object type="button" size="0 100%-60 33% 100%-32" style="ModernButtonRed" hotkey="cancel">
|
||||
<object name="cancelButton" type="button" size="0 100%-60 33% 100%-32" style="ModernButtonRed" hotkey="cancel">
|
||||
<translatableAttribute id="caption">Cancel</translatableAttribute>
|
||||
<action on="Press">cancelSetup();</action>
|
||||
</object>
|
||||
|
||||
<object type="button" size="33%+5 100%-60 66% 100%-32" style="ModernButtonRed">
|
||||
|
@ -46,6 +46,13 @@ function init(initData)
|
||||
|
||||
// fill the script
|
||||
scriptInput.caption = Engine.GetLocaleScript(initData.locale);
|
||||
|
||||
return new Promise(popGuiPage => {
|
||||
Engine.GetGUIObjectByName("cancelButton").onPress = popGuiPage;
|
||||
Engine.GetGUIObjectByName("acceptButton").onPress = () => {
|
||||
popGuiPage(applySelectedLocale());
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: an onChanged event for input boxes would be useful and would allow us to avoid a tick event here.
|
||||
@ -54,11 +61,6 @@ function onTick()
|
||||
updateResultingLocale();
|
||||
}
|
||||
|
||||
function cancelSetup()
|
||||
{
|
||||
Engine.PopGuiPage();
|
||||
}
|
||||
|
||||
function updateResultingLocale()
|
||||
{
|
||||
var languageList = Engine.GetGUIObjectByName("languageList");
|
||||
@ -113,6 +115,5 @@ function autoDetectLocale()
|
||||
|
||||
function applySelectedLocale()
|
||||
{
|
||||
var resultingLocaleText = Engine.GetGUIObjectByName("resultingLocale");
|
||||
Engine.PopGuiPage(resultingLocaleText.caption);
|
||||
return Engine.GetGUIObjectByName("resultingLocale").caption;
|
||||
}
|
||||
|
@ -61,9 +61,8 @@
|
||||
</object>
|
||||
<object name="dictionaryFile" type="text" size="50%+10 260 100% 345" style="ModernText" />
|
||||
|
||||
<object type="button" size="0 100%-60 33% 100%-25" style="ModernButtonRed" hotkey="cancel">
|
||||
<object name="cancelButton" type="button" size="0 100%-60 33% 100%-25" style="ModernButtonRed" hotkey="cancel">
|
||||
<translatableAttribute id="caption">Cancel</translatableAttribute>
|
||||
<action on="Press">cancelSetup();</action>
|
||||
</object>
|
||||
|
||||
<object type="button" size="33%+5 100%-60 66% 100%-25" style="ModernButtonRed">
|
||||
@ -73,7 +72,6 @@
|
||||
|
||||
<object name="acceptButton" type="button" style="ModernButtonRed" size="66%+5 100%-60 100% 100%-25">
|
||||
<translatableAttribute id="caption">Accept</translatableAttribute>
|
||||
<action on="Press">applySelectedLocale();</action>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
@ -7,4 +7,6 @@ function init()
|
||||
|
||||
// Replace anything starting with 'hotkey.' with its hotkey.
|
||||
mainText.caption = text.replace(/hotkey\.([a-z0-9_\.]+)/g, (_, k) => formatHotkeyCombinations(hotkeys[k]));
|
||||
|
||||
return new Promise(popGuiPage => { Engine.GetGUIObjectByName("closeButton").onPress = popGuiPage; });
|
||||
}
|
||||
|
@ -17,9 +17,8 @@
|
||||
<object name="mainText" type="text" style="ModernTextPanel" />
|
||||
</object>
|
||||
|
||||
<object type="button" style="ModernButtonRed" tooltip_style="snToolTip" size="100%-408 100%-52 100%-218 100%-24" hotkey="cancel">
|
||||
<object name="closeButton" type="button" style="ModernButtonRed" tooltip_style="snToolTip" size="100%-408 100%-52 100%-218 100%-24" hotkey="cancel">
|
||||
<translatableAttribute id="caption">Close</translatableAttribute>
|
||||
<action on="Press">Engine.PopGuiPage();</action>
|
||||
</object>
|
||||
|
||||
<object name="url" type="button" style="ModernButtonRed" size="100%-214 100%-52 100%-24 100%-24">
|
||||
|
@ -8,7 +8,7 @@ function init()
|
||||
let cache = new MapCache();
|
||||
let filters = new MapFilters(cache);
|
||||
let browser = new MapBrowser(cache, filters);
|
||||
browser.registerClosePageHandler(() => Engine.PopGuiPage());
|
||||
browser.openPage(false);
|
||||
browser.controls.MapFiltering.select("default", "skirmish");
|
||||
return new Promise(popGuiPage => { browser.registerClosePageHandler(popGuiPage); });
|
||||
}
|
||||
|
@ -225,6 +225,12 @@ function init(data, hotloadData)
|
||||
g_TabButtonDist,
|
||||
selectPanel,
|
||||
displayOptions);
|
||||
|
||||
return new Promise(popGuiPage => {
|
||||
Engine.GetGUIObjectByName("closeButton").onPress = () => {
|
||||
closePage() && popGuiPage(g_ChangedKeys);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function getHotloadData()
|
||||
@ -448,8 +454,8 @@ async function closePage()
|
||||
translate("Warning"),
|
||||
[translate("No"), translate("Yes")]);
|
||||
if (buttonIndex === 0)
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
Engine.PopGuiPage(g_ChangedKeys);
|
||||
return true;
|
||||
}
|
||||
|
@ -58,10 +58,9 @@
|
||||
<action on="Press">saveChanges();</action>
|
||||
</object>
|
||||
|
||||
<object type="button" style="ModernButtonRed" size="50%+186 100%-44 50%+336 100%-16" hotkey="cancel">
|
||||
<object name="closeButton" type="button" style="ModernButtonRed" size="50%+186 100%-44 50%+336 100%-16" hotkey="cancel">
|
||||
<translatableAttribute id="caption">Close</translatableAttribute>
|
||||
<translatableAttribute id="tooltip">Unsaved changes affect this session only</translatableAttribute>
|
||||
<action on="Press">closePage();</action>
|
||||
</object>
|
||||
|
||||
</object>
|
||||
|
@ -37,9 +37,9 @@ function setFeedback(feedbackText)
|
||||
Engine.GetGUIObjectByName("continue").enabled = !feedbackText;
|
||||
}
|
||||
|
||||
function cancelButton()
|
||||
async function cancelButton()
|
||||
{
|
||||
await new Promise(resolve => { Engine.GetGUIPageByName("cancel").onPress = resolve; });
|
||||
if (Engine.HasXmppClient())
|
||||
Engine.StopXmppClient();
|
||||
Engine.PopGuiPage();
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
<object name="cancel" type="button" size="0 0 50%-5 100%" style="ModernButtonRed" hotkey="cancel">
|
||||
<translatableAttribute id="caption">Cancel</translatableAttribute>
|
||||
<action on="Press">cancelButton();</action>
|
||||
</object>
|
||||
|
||||
<object name="continue" hotkey="confirm" type="button" size="50%+5 0 100% 100%" style="ModernButtonRed" enabled="false">
|
||||
|
@ -2,6 +2,8 @@ function init()
|
||||
{
|
||||
if (Engine.ConfigDB_GetValue("user", "lobby.login"))
|
||||
loginButton();
|
||||
|
||||
return new Promise(popGuiPage => { Engine.GetGUIObjectByName("cancel").onPress = popGuiPage; });
|
||||
}
|
||||
|
||||
function loginButton()
|
||||
@ -13,8 +15,3 @@ function registerButton()
|
||||
{
|
||||
Engine.PushGuiPage("page_prelobby_register.xml");
|
||||
}
|
||||
|
||||
function cancelButton()
|
||||
{
|
||||
Engine.PopGuiPage();
|
||||
}
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
<object name="cancel" type="button" size="18 100%-45 50%-5 100%-17" style="ModernButtonRed" hotkey="cancel">
|
||||
<translatableAttribute id="caption">Cancel</translatableAttribute>
|
||||
<action on="Press">cancelButton();</action>
|
||||
</object>
|
||||
|
||||
</object>
|
||||
|
@ -13,6 +13,8 @@ function init()
|
||||
initRememberPassword();
|
||||
|
||||
updateFeedback();
|
||||
|
||||
return cancelButton();
|
||||
}
|
||||
|
||||
function updateFeedback()
|
||||
|
@ -1,7 +1,5 @@
|
||||
function init()
|
||||
{
|
||||
g_LobbyMessages.registered = onRegistered;
|
||||
|
||||
Engine.GetGUIObjectByName("continue").caption = translate("Register");
|
||||
|
||||
initLobbyTerms();
|
||||
@ -9,6 +7,8 @@ function init()
|
||||
initRememberPassword();
|
||||
|
||||
updateFeedback();
|
||||
|
||||
return Promise.race([ onRegistered(), cancelButton() ]);
|
||||
}
|
||||
|
||||
function updateFeedback()
|
||||
@ -32,14 +32,14 @@ function continueButton()
|
||||
Engine.ConnectXmppClient();
|
||||
}
|
||||
|
||||
function onRegistered()
|
||||
async function onRegistered()
|
||||
{
|
||||
await new Promise(resolve => { g_LobbyMessages.registered = resolve; });
|
||||
saveCredentials();
|
||||
|
||||
setFeedback(translate("Registered"));
|
||||
|
||||
Engine.StopXmppClient();
|
||||
|
||||
Engine.PopGuiPage();
|
||||
Engine.PushGuiPage("page_prelobby_login.xml");
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
class CatafalquePage extends ReferencePage
|
||||
{
|
||||
constructor(data)
|
||||
constructor(popGuiPage)
|
||||
{
|
||||
super();
|
||||
super(popGuiPage);
|
||||
|
||||
this.Canvas = Engine.GetGUIObjectByName("canvas");
|
||||
this.Emblems = [];
|
||||
@ -31,7 +31,7 @@ class CatafalquePage extends ReferencePage
|
||||
|
||||
closePage()
|
||||
{
|
||||
Engine.PopGuiPage({ "page": "page_catafalque.xml" });
|
||||
this.popGuiPage({ "page": "page_catafalque.xml" });
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
function init(data = {})
|
||||
{
|
||||
g_Page = new CatafalquePage(data);
|
||||
return new Promise(popGuiPage => { g_Page = new CatafalquePage(popGuiPage); });
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
class CivInfoPage extends ReferencePage
|
||||
{
|
||||
constructor(data)
|
||||
constructor(popGuiPage)
|
||||
{
|
||||
super();
|
||||
super(popGuiPage);
|
||||
|
||||
this.civSelection = new CivSelectDropdown(this.civData);
|
||||
this.civSelection.registerHandler(this.selectCiv.bind(this));
|
||||
@ -17,7 +17,7 @@ class CivInfoPage extends ReferencePage
|
||||
|
||||
switchToStructreePage()
|
||||
{
|
||||
Engine.PopGuiPage({
|
||||
this.popGuiPage({
|
||||
"nextPage": "page_structree.xml",
|
||||
"args": {
|
||||
"civ": this.activeCiv
|
||||
@ -27,7 +27,7 @@ class CivInfoPage extends ReferencePage
|
||||
|
||||
closePage()
|
||||
{
|
||||
Engine.PopGuiPage({
|
||||
this.popGuiPage({
|
||||
"page": "page_civinfo.xml",
|
||||
"args": {
|
||||
"civ": this.activeCiv
|
||||
|
@ -3,10 +3,12 @@
|
||||
*/
|
||||
function init(data = {})
|
||||
{
|
||||
g_Page = new CivInfoPage(data);
|
||||
const promise = new Promise(popGuiPage => { g_Page = new CivInfoPage(data, popGuiPage); });
|
||||
|
||||
if (data.civ)
|
||||
g_Page.civSelection.selectCiv(data.civ);
|
||||
else
|
||||
g_Page.civSelection.selectFirstCiv();
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ class CivInfoButton
|
||||
|
||||
onPress()
|
||||
{
|
||||
Engine.PopGuiPage({
|
||||
this.parentPage.popGuiPage({
|
||||
"nextPage": "page_civinfo.xml",
|
||||
"args": {
|
||||
"civ": this.parentPage.activeCiv
|
||||
|
@ -12,7 +12,7 @@ class StructreeButton
|
||||
|
||||
onPress()
|
||||
{
|
||||
Engine.PopGuiPage({
|
||||
this.parentPage.popGuiPage({
|
||||
"nextPage": "page_structree.xml",
|
||||
"args": {
|
||||
"civ": this.parentPage.activeCiv
|
||||
|
@ -3,8 +3,9 @@
|
||||
*/
|
||||
class ReferencePage
|
||||
{
|
||||
constructor()
|
||||
constructor(popGuiPage)
|
||||
{
|
||||
this.popGuiPage = popGuiPage;
|
||||
this.civData = loadCivData(true, false);
|
||||
|
||||
this.TemplateLoader = new TemplateLoader();
|
||||
|
@ -5,9 +5,9 @@
|
||||
*/
|
||||
class StructreePage extends ReferencePage
|
||||
{
|
||||
constructor(data)
|
||||
constructor(popGuiPage)
|
||||
{
|
||||
super();
|
||||
super(popGuiPage);
|
||||
|
||||
this.structureBoxes = [];
|
||||
this.trainerBoxes = [];
|
||||
@ -39,7 +39,7 @@ class StructreePage extends ReferencePage
|
||||
|
||||
closePage()
|
||||
{
|
||||
Engine.PopGuiPage({
|
||||
this.popGuiPage({
|
||||
"page": "page_structree.xml",
|
||||
"args": {
|
||||
"civ": this.activeCiv
|
||||
|
@ -5,10 +5,12 @@
|
||||
*/
|
||||
function init(data = {})
|
||||
{
|
||||
g_Page = new StructreePage(data);
|
||||
const promise = new Promise(popGuiPage => {g_Page = new StructreePage(popGuiPage)};
|
||||
|
||||
if (data.civ)
|
||||
g_Page.civSelection.selectCiv(data.civ);
|
||||
else
|
||||
g_Page.civSelection.selectFirstCiv();
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
@ -3,9 +3,9 @@
|
||||
*/
|
||||
class ViewerPage extends ReferencePage
|
||||
{
|
||||
constructor(data)
|
||||
constructor(popGuiPage)
|
||||
{
|
||||
super();
|
||||
super(popGuiPage);
|
||||
|
||||
this.currentTemplate = undefined;
|
||||
|
||||
@ -140,7 +140,7 @@ class ViewerPage extends ReferencePage
|
||||
|
||||
closePage()
|
||||
{
|
||||
Engine.PopGuiPage({ "civ": this.activeCiv, "page": "page_viewer.xml" });
|
||||
this.popGuiPage({ "civ": this.activeCiv, "page": "page_viewer.xml" });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ g_TooltipTextFormats.nameSecondary.font = "sans-bold-16";
|
||||
*/
|
||||
function init(data)
|
||||
{
|
||||
g_Page = new ViewerPage();
|
||||
const promise = new Promise(popGuiPage => { g_Page = new ViewerPage(popGuiPage); });
|
||||
g_Page.selectTemplate(data);
|
||||
return promise;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
class CampaignSession
|
||||
{
|
||||
constructor(data)
|
||||
constructor(data, popGuiPage)
|
||||
{
|
||||
this.run = new CampaignRun(data.run).load();
|
||||
registerPlayersFinishedHandler(this.onFinish.bind(this));
|
||||
registerPlayersFinishedHandler(this.onFinish.bind(this, popGuiPage));
|
||||
this.endGameData = {
|
||||
"won": false,
|
||||
"initData": data,
|
||||
@ -11,7 +11,7 @@ class CampaignSession
|
||||
};
|
||||
}
|
||||
|
||||
onFinish(players, won)
|
||||
onFinish(popGuiPage, players, won)
|
||||
{
|
||||
let playerID = Engine.GetPlayerID();
|
||||
if (players.indexOf(playerID) === -1)
|
||||
@ -24,7 +24,7 @@ class CampaignSession
|
||||
|
||||
// Run the endgame script.
|
||||
Engine.PushGuiPage(this.getEndGame(), this.endGameData);
|
||||
Engine.PopGuiPage();
|
||||
popGuiPage();
|
||||
}
|
||||
|
||||
getMenu()
|
||||
|
@ -270,8 +270,10 @@ function init(initData, hotloadData)
|
||||
restoreSavedGameData(initData.savedGUIData);
|
||||
}
|
||||
|
||||
if (g_InitAttributes.campaignData)
|
||||
g_CampaignSession = new CampaignSession(g_InitAttributes.campaignData);
|
||||
const promise = new Promise(popGuiPage => {
|
||||
if (g_InitAttributes.campaignData)
|
||||
g_CampaignSession = new CampaignSession(g_InitAttributes.campaignData, popGuiPage);
|
||||
});
|
||||
|
||||
let mapCache = new MapCache();
|
||||
g_Cheats = new Cheats();
|
||||
@ -332,6 +334,8 @@ function init(initData, hotloadData)
|
||||
onSimulationUpdate();
|
||||
|
||||
setTimeout(displayGamestateNotifications, 1000);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function registerPlayersInitHandler(handler)
|
||||
|
@ -1,15 +1,15 @@
|
||||
var g_SplashScreenFile = "gui/splashscreen/splashscreen.txt";
|
||||
|
||||
function init(data)
|
||||
async function init(data)
|
||||
{
|
||||
Engine.GetGUIObjectByName("mainText").caption = Engine.TranslateLines(Engine.ReadFile(g_SplashScreenFile));
|
||||
Engine.GetGUIObjectByName("displaySplashScreen").checked = Engine.ConfigDB_GetValue("user", "gui.splashscreen.enable") === "true";
|
||||
}
|
||||
|
||||
function closePage()
|
||||
{
|
||||
await new Promise(resolve => {
|
||||
Engine.GetGUIObjectByName("btnOK").onPress = resolve;
|
||||
});
|
||||
|
||||
Engine.ConfigDB_CreateValue("user", "gui.splashscreen.enable", String(Engine.GetGUIObjectByName("displaySplashScreen").checked));
|
||||
Engine.ConfigDB_CreateValue("user", "gui.splashscreen.version", Engine.GetFileMTime(g_SplashScreenFile));
|
||||
Engine.ConfigDB_SaveChanges("user");
|
||||
Engine.PopGuiPage();
|
||||
}
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
<object name="btnOK" type="button" style="ModernButtonRed" size="18 100%-45 50%-5 100%-17" hotkey="cancel">
|
||||
<translatableAttribute id="caption">OK</translatableAttribute>
|
||||
<action on="Press">closePage();</action>
|
||||
</object>
|
||||
|
||||
<object type="button" style="ModernButtonRed" size="50%+5 100%-45 100%-18 100%-17">
|
||||
|
@ -135,10 +135,25 @@ var g_SelectedChart = {
|
||||
"type": [0, 0]
|
||||
};
|
||||
|
||||
function init(data)
|
||||
async function init(data)
|
||||
{
|
||||
initSummaryData(data);
|
||||
initGUISummary();
|
||||
|
||||
while (true)
|
||||
{
|
||||
const branchless await new Promise(popGuiPage => {
|
||||
Engine.GetGUIObjectByName("summaryHotkey").onPress = resolve(true);
|
||||
Engine.GetGUIObjectByName("cancelHotkey").onPress = resolve(false);
|
||||
});
|
||||
|
||||
if (branchless || g_GameData.gui.isInGame)
|
||||
{
|
||||
const result = continueButton();
|
||||
if (result !== undefined)
|
||||
return result ?? undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initSummaryData(data)
|
||||
@ -461,11 +476,11 @@ function continueButton()
|
||||
"teamCharts": Engine.GetGUIObjectByName("toggleTeamBox").checked
|
||||
};
|
||||
if (g_GameData.gui.isInGame)
|
||||
Engine.PopGuiPage({
|
||||
return {
|
||||
"summarySelection": summarySelection
|
||||
});
|
||||
else if (g_GameData.gui.dialog)
|
||||
Engine.PopGuiPage();
|
||||
};
|
||||
if (g_GameData.gui.dialog)
|
||||
return null;
|
||||
else if (Engine.HasXmppClient())
|
||||
Engine.SwitchGuiPage("page_lobby.xml", { "dialog": false });
|
||||
else if (g_GameData.gui.isReplay)
|
||||
@ -477,6 +492,8 @@ function continueButton()
|
||||
Engine.SwitchGuiPage(g_GameData.nextPage, g_GameData.campaignData);
|
||||
else
|
||||
Engine.SwitchGuiPage("page_pregame.xml");
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function startReplay()
|
||||
|
@ -5,16 +5,8 @@
|
||||
<script directory="gui/common/"/>
|
||||
<script directory="gui/summary/"/>
|
||||
|
||||
<object hotkey="summary">
|
||||
<action on="Press">continueButton();</action>
|
||||
</object>
|
||||
|
||||
<object hotkey="cancel">
|
||||
<action on="Press">
|
||||
if (g_GameData.gui.isInGame)
|
||||
continueButton();
|
||||
</action>
|
||||
</object>
|
||||
<object name="summaryHotkey" hotkey="summary"/>
|
||||
<object name="cancelHotkey" hotkey="cancel"/>
|
||||
|
||||
<object type="image" sprite="ModernFade" name="fadeImage"/>
|
||||
|
||||
@ -112,7 +104,7 @@
|
||||
</repeat>
|
||||
</object>
|
||||
</object>
|
||||
|
||||
|
||||
<object name="chartsPanel" type="image" sprite="ModernTabHorizontalFrame" size="20 120 100%-20 100%-54">
|
||||
<repeat count="2" var="k">
|
||||
<object name="chart[k]Part" size="15 0 50%-10 100%-35">
|
||||
|
@ -137,26 +137,8 @@ JS::Value CGUIManager::PushPage(const CStrW& pageName, Script::StructuredClone i
|
||||
return promise;
|
||||
}
|
||||
|
||||
void CGUIManager::PopPage(Script::StructuredClone args)
|
||||
{
|
||||
if (m_PageStack.size() < 2)
|
||||
{
|
||||
debug_warn(L"Tried to pop GUI page when there's < 2 in the stack");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we unfocus anything on the current page.
|
||||
m_PageStack.back().gui->SendFocusMessage(GUIM_LOST_FOCUS);
|
||||
|
||||
m_PageStack.pop_back();
|
||||
m_PageStack.back().ResolvePromise(args);
|
||||
|
||||
// We return to a page where some object might have been focused.
|
||||
m_PageStack.back().gui->SendFocusMessage(GUIM_GOT_FOCUS);
|
||||
}
|
||||
|
||||
CGUIManager::SGUIPage::SGUIPage(const CStrW& pageName, const Script::StructuredClone initData)
|
||||
: m_Name(pageName), initData(initData), inputs(), gui(), callbackFunction()
|
||||
: m_Name(pageName), initData(initData)
|
||||
{
|
||||
}
|
||||
|
||||
@ -178,6 +160,9 @@ void CGUIManager::SGUIPage::LoadPage(ScriptContext& scriptContext)
|
||||
g_VideoMode.ResetCursor();
|
||||
inputs.clear();
|
||||
gui.reset(new CGUI(scriptContext));
|
||||
const ScriptRequest rq{gui->GetScriptInterface()};
|
||||
sendingPromise = std::make_shared<JS::PersistentRootedObject>(rq.cx,
|
||||
JS::NewPromiseObject(rq.cx, nullptr));
|
||||
|
||||
gui->AddObjectTypes();
|
||||
|
||||
@ -232,9 +217,6 @@ void CGUIManager::SGUIPage::LoadPage(ScriptContext& scriptContext)
|
||||
|
||||
gui->LoadedXmlFiles();
|
||||
|
||||
std::shared_ptr<ScriptInterface> scriptInterface = gui->GetScriptInterface();
|
||||
ScriptRequest rq(scriptInterface);
|
||||
|
||||
JS::RootedValue initDataVal(rq.cx);
|
||||
JS::RootedValue hotloadDataVal(rq.cx);
|
||||
JS::RootedValue global(rq.cx, rq.globalValue());
|
||||
@ -245,40 +227,68 @@ void CGUIManager::SGUIPage::LoadPage(ScriptContext& scriptContext)
|
||||
if (hotloadData)
|
||||
Script::ReadStructuredClone(rq, hotloadData, &hotloadDataVal);
|
||||
|
||||
if (Script::HasProperty(rq, global, "init") &&
|
||||
!ScriptFunction::CallVoid(rq, global, "init", initDataVal, hotloadDataVal))
|
||||
if (!Script::HasProperty(rq, global, "init"))
|
||||
return;
|
||||
|
||||
JS::RootedValue returnValue{rq.cx};
|
||||
if (!ScriptFunction::Call(rq, global, "init", &returnValue, initDataVal, hotloadDataVal))
|
||||
{
|
||||
LOGERROR("GUI page '%s': Failed to call init() function", utf8_from_wstring(m_Name));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!returnValue.isObject())
|
||||
return;
|
||||
|
||||
JS::RootedObject returnObject{rq.cx, &returnValue.toObject()};
|
||||
if (!JS::IsPromiseObject(returnObject))
|
||||
return;
|
||||
|
||||
sendingPromise = std::make_shared<JS::PersistentRootedObject>(rq.cx, returnObject);
|
||||
}
|
||||
|
||||
JS::Value CGUIManager::SGUIPage::ReplacePromise(ScriptInterface& scriptInterface)
|
||||
{
|
||||
JSContext* generalContext{scriptInterface.GetGeneralJSContext()};
|
||||
callbackFunction = std::make_shared<JS::PersistentRootedObject>(generalContext,
|
||||
JS::NewPromiseObject(generalContext, nullptr));
|
||||
return JS::ObjectValue(**callbackFunction);
|
||||
receivingPromise = std::make_shared<JS::PersistentRootedObject>(generalContext,
|
||||
JS::NewPromiseObject(generalContext, nullptr));
|
||||
|
||||
return JS::ObjectValue(**receivingPromise);
|
||||
}
|
||||
|
||||
void CGUIManager::SGUIPage::ResolvePromise(Script::StructuredClone args)
|
||||
CGUIManager::SGUIPage::CloseResult CGUIManager::SGUIPage::Close()
|
||||
{
|
||||
if (!callbackFunction)
|
||||
return;
|
||||
// Make sure we unfocus anything on the current page.
|
||||
gui->SendFocusMessage(GUIM_LOST_FOCUS);
|
||||
|
||||
const ScriptRequest rq{gui->GetScriptInterface()};
|
||||
JS::RootedValue arg{rq.cx, JS::GetPromiseResult(*sendingPromise)};
|
||||
return {Script::WriteStructuredClone(rq, arg),
|
||||
JS::GetPromiseState(*sendingPromise) == JS::PromiseState::Rejected};
|
||||
}
|
||||
|
||||
void CGUIManager::SGUIPage::Refocus(const CloseResult& result)
|
||||
{
|
||||
ENSURE(receivingPromise);
|
||||
|
||||
std::shared_ptr<ScriptInterface> scriptInterface = gui->GetScriptInterface();
|
||||
ScriptRequest rq(scriptInterface);
|
||||
|
||||
JS::RootedObject globalObj(rq.cx, rq.glob);
|
||||
|
||||
JS::RootedObject funcVal(rq.cx, *callbackFunction);
|
||||
JS::RootedObject recv(rq.cx, *receivingPromise);
|
||||
|
||||
// Delete the callback function, so that it is not called again
|
||||
callbackFunction.reset();
|
||||
receivingPromise.reset();
|
||||
|
||||
JS::RootedValue argVal(rq.cx);
|
||||
if (args)
|
||||
Script::ReadStructuredClone(rq, args, &argVal);
|
||||
Script::ReadStructuredClone(rq, result.arg, &argVal);
|
||||
|
||||
// This only resolves the promise, it doesn't call the continuation.
|
||||
JS::ResolvePromise(rq.cx, funcVal, argVal);
|
||||
(result.rejected ? JS::RejectPromise : JS::ResolvePromise)(rq.cx, recv, argVal);
|
||||
|
||||
// We return to a page where some object might have been focused.
|
||||
gui->SendFocusMessage(GUIM_GOT_FOCUS);
|
||||
}
|
||||
|
||||
Status CGUIManager::ReloadChangedFile(const VfsPath& path)
|
||||
@ -368,6 +378,19 @@ void CGUIManager::TickObjects()
|
||||
{
|
||||
PROFILE3("gui tick");
|
||||
|
||||
while (!m_PageStack.empty() &&
|
||||
JS::GetPromiseState(*m_PageStack.back().sendingPromise) != JS::PromiseState::Pending)
|
||||
{
|
||||
const size_t stackSize{m_PageStack.size()};
|
||||
const SGUIPage::CloseResult result{m_PageStack.back().Close()};
|
||||
ENSURE(m_PageStack.size() == stackSize);
|
||||
m_PageStack.pop_back();
|
||||
if (!m_PageStack.empty())
|
||||
m_PageStack.back().Refocus(result);
|
||||
|
||||
g_ScriptContext->RunJobs();
|
||||
}
|
||||
|
||||
// We share the script context with everything else that runs in the same thread.
|
||||
// This call makes sure we trigger GC regularly even if the simulation is not running.
|
||||
m_ScriptContext.MaybeIncrementalGC(1.0f);
|
||||
|
@ -72,12 +72,6 @@ public:
|
||||
*/
|
||||
JS::Value PushPage(const CStrW& pageName, Script::StructuredClone initData);
|
||||
|
||||
/**
|
||||
* Unload the currently active GUI page, and make the previous page active.
|
||||
* (There must be at least two pages when you call this.)
|
||||
*/
|
||||
void PopPage(Script::StructuredClone args);
|
||||
|
||||
/**
|
||||
* Called when a file has been modified, to hotload changes.
|
||||
*/
|
||||
@ -151,10 +145,17 @@ private:
|
||||
*/
|
||||
JS::Value ReplacePromise(ScriptInterface& scriptInterface);
|
||||
|
||||
struct CloseResult
|
||||
{
|
||||
Script::StructuredClone arg;
|
||||
bool rejected;
|
||||
};
|
||||
CloseResult Close();
|
||||
|
||||
/**
|
||||
* Execute the stored callback function with the given arguments.
|
||||
*/
|
||||
void ResolvePromise(Script::StructuredClone args);
|
||||
void Refocus(const CloseResult& result);
|
||||
|
||||
std::wstring m_Name;
|
||||
std::unordered_set<VfsPath> inputs; // for hotloading
|
||||
@ -162,10 +163,16 @@ private:
|
||||
std::shared_ptr<CGUI> gui; // the actual GUI page
|
||||
|
||||
/**
|
||||
* Function executed by this parent GUI page when the child GUI page it pushed is popped.
|
||||
* Notice that storing it in the SGUIPage instead of CGUI means that it will survive the hotloading CGUI reset.
|
||||
* When this promise is setteled this page wants to be closed. It
|
||||
* fullfils with the page completion value.
|
||||
*/
|
||||
std::shared_ptr<JS::PersistentRootedObject> callbackFunction;
|
||||
std::shared_ptr<JS::PersistentRootedObject> sendingPromise;
|
||||
|
||||
/**
|
||||
* The parrent page waits on this promise. It also gets the
|
||||
* completion value through this promise.
|
||||
*/
|
||||
std::shared_ptr<JS::PersistentRootedObject> receivingPromise;
|
||||
};
|
||||
|
||||
std::shared_ptr<CGUI> top() const;
|
||||
|
@ -43,17 +43,6 @@ void SwitchGuiPage(const ScriptInterface& scriptInterface, const std::wstring& n
|
||||
g_GUI->SwitchPage(name, &scriptInterface, initData);
|
||||
}
|
||||
|
||||
void PopGuiPage(const ScriptRequest& rq, JS::HandleValue args)
|
||||
{
|
||||
if (g_GUI->GetPageCount() < 2)
|
||||
{
|
||||
ScriptException::Raise(rq, "Can't pop GUI pages when less than two pages are opened!");
|
||||
return;
|
||||
}
|
||||
|
||||
g_GUI->PopPage(Script::WriteStructuredClone(rq, args));
|
||||
}
|
||||
|
||||
void SetCursor(const std::wstring& name)
|
||||
{
|
||||
g_VideoMode.SetCursor(name);
|
||||
@ -79,7 +68,6 @@ void RegisterScriptFunctions(const ScriptRequest& rq)
|
||||
{
|
||||
ScriptFunction::Register<&PushGuiPage>(rq, "PushGuiPage");
|
||||
ScriptFunction::Register<&SwitchGuiPage>(rq, "SwitchGuiPage");
|
||||
ScriptFunction::Register<&PopGuiPage>(rq, "PopGuiPage");
|
||||
ScriptFunction::Register<&SetCursor>(rq, "SetCursor");
|
||||
ScriptFunction::Register<&ResetCursor>(rq, "ResetCursor");
|
||||
ScriptFunction::Register<&TemplateExists>(rq, "TemplateExists");
|
||||
|
@ -26,12 +26,14 @@
|
||||
#include "ps/GameSetup/GameSetup.h"
|
||||
#include "ps/Hotkey.h"
|
||||
#include "ps/XML/Xeromyces.h"
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/ScriptContext.h"
|
||||
#include "scriptinterface/ScriptRequest.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
#include "scriptinterface/StructuredClone.h"
|
||||
#include "scriptinterface/Object.h"
|
||||
|
||||
#include "js/Promise.h"
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
@ -202,35 +204,71 @@ public:
|
||||
UnloadHotkeys();
|
||||
}
|
||||
|
||||
static void CloseTopmostPage()
|
||||
{
|
||||
ScriptRequest rq{g_GUI->GetActiveGUI()->GetScriptInterface()};
|
||||
JS::RootedValue global{rq.cx, rq.globalValue()};
|
||||
TS_ASSERT(ScriptFunction::CallVoid(rq, global, "closePage"));
|
||||
// Check if some promise are setteled and flush the promise-jobQueue.
|
||||
g_GUI->TickObjects();
|
||||
}
|
||||
|
||||
void test_PageRegainedFocusEvent()
|
||||
{
|
||||
// Load up a test page.
|
||||
ScriptRequest rq{g_GUI->GetScriptInterface()};
|
||||
JS::RootedValue val(rq.cx);
|
||||
Script::CreateObject(rq, &val);
|
||||
const Script::StructuredClone undefined{
|
||||
Script::WriteStructuredClone(rq, JS::UndefinedHandleValue)};
|
||||
|
||||
TS_ASSERT_EQUALS(g_GUI->GetPageCount(), 0);
|
||||
Script::StructuredClone data = Script::WriteStructuredClone(rq, JS::NullHandleValue);
|
||||
g_GUI->PushPage(L"regainFocus/page_emptyPage.xml", data);
|
||||
|
||||
const ScriptInterface& pageScriptInterface = *(g_GUI->GetActiveGUI()->GetScriptInterface());
|
||||
ScriptRequest prq(pageScriptInterface);
|
||||
JS::RootedValue global(prq.cx, prq.globalValue());
|
||||
|
||||
TS_ASSERT_EQUALS(g_GUI->GetPageCount(), 1);
|
||||
g_GUI->PushPage(L"regainFocus/page_emptyPage.xml", data);
|
||||
TS_ASSERT_EQUALS(g_GUI->GetPageCount(), 2);
|
||||
g_GUI->PopPage(data);
|
||||
g_GUI->PushPage(L"regainFocus/page_emptyPage.xml", undefined);
|
||||
TS_ASSERT_EQUALS(g_GUI->GetPageCount(), 1);
|
||||
|
||||
// This page instantly pushes an empty page with a callback that pops another page again.
|
||||
g_GUI->PushPage(L"regainFocus/page_pushWithPopOnInit.xml", data);
|
||||
g_GUI->PushPage(L"regainFocus/page_pushWithPopOnInit.xml", undefined);
|
||||
TS_ASSERT_EQUALS(g_GUI->GetPageCount(), 3);
|
||||
|
||||
// Pop the empty page
|
||||
g_GUI->PopPage(data);
|
||||
TS_ASSERT_EQUALS(g_GUI->GetPageCount(), 2);
|
||||
scriptInterface->GetContext().RunJobs();
|
||||
// Pop the empty page and execute the continuation.
|
||||
CloseTopmostPage();
|
||||
TS_ASSERT_EQUALS(g_GUI->GetPageCount(), 1);
|
||||
|
||||
CloseTopmostPage();
|
||||
TS_ASSERT_EQUALS(g_GUI->GetPageCount(), 0);
|
||||
}
|
||||
|
||||
void test_ResolveReject()
|
||||
{
|
||||
TestLogger logger;
|
||||
constexpr std::array<std::tuple<bool, JS::PromiseState>, 2> testSteps{{
|
||||
{false, JS::PromiseState::Fulfilled},
|
||||
{true, JS::PromiseState::Rejected}}};
|
||||
|
||||
const ScriptRequest rq{g_GUI->GetScriptInterface()};
|
||||
|
||||
const Script::StructuredClone undefined{
|
||||
Script::WriteStructuredClone(rq, JS::UndefinedHandleValue)};
|
||||
g_GUI->PushPage(L"regainFocus/page_emptyPage.xml", undefined);
|
||||
|
||||
|
||||
for (const auto& [reject, result] : testSteps)
|
||||
{
|
||||
const JS::RootedValue value{rq.cx, JS::BooleanValue(reject)};
|
||||
const Script::StructuredClone clonedValue{Script::WriteStructuredClone(rq, value)};
|
||||
|
||||
const JS::RootedValue promise{rq.cx,
|
||||
g_GUI->PushPage(L"resolveReject/page_resolveReject.xml", clonedValue)};
|
||||
|
||||
// Check if some promise are setteled and flush the promise-jobQueue.
|
||||
g_GUI->TickObjects();
|
||||
const JS::RootedObject promiseObject{rq.cx, &promise.toObject()};
|
||||
TS_ASSERT_EQUALS(JS::GetPromiseState(promiseObject), result);
|
||||
}
|
||||
}
|
||||
|
||||
void test_Sequential()
|
||||
{
|
||||
const ScriptRequest rq{g_GUI->GetScriptInterface()};
|
||||
const Script::StructuredClone undefined{
|
||||
Script::WriteStructuredClone(rq, JS::UndefinedHandleValue)};
|
||||
g_GUI->PushPage(L"sequential/page_sequential.xml", undefined);
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user