Index: ps/trunk/binaries/data/mods/public/gui/session/Menu.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/Menu.js
+++ ps/trunk/binaries/data/mods/public/gui/session/Menu.js
@@ -0,0 +1,120 @@
+/**
+ * This class constructs and positions the menu buttons and assigns the handlers defined in MenuButtons.
+ */
+class Menu
+{
+ constructor(pauseControl, playerViewControl, chat)
+ {
+ this.menuButton = Engine.GetGUIObjectByName("menuButton");
+ this.menuButton.onPress = this.toggle.bind(this);
+ registerHotkeyChangeHandler(this.rebuild.bind(this));
+
+ this.isOpen = false;
+ this.lastTick = undefined;
+
+ this.menuButtonPanel = Engine.GetGUIObjectByName("menuButtonPanel");
+ let menuButtons = this.menuButtonPanel.children;
+ this.margin = menuButtons[0].size.top;
+ this.buttonHeight = menuButtons[0].size.bottom;
+
+ let handlerNames = this.getHandlerNames();
+ if (handlerNames.length > menuButtons.length)
+ throw new Error(
+ "There are " + handlerNames.length + " menu buttons defined, " +
+ "but only " + menuButtons.length + " objects!");
+
+ this.buttons = handlerNames.map((handlerName, i) => {
+ let handler = new MenuButtons.prototype[handlerName](menuButtons[i], pauseControl, playerViewControl, chat);
+ this.initButton(handler, menuButtons[i], i);
+ return handler;
+ });
+
+ this.endPosition = this.margin + this.buttonHeight * (1 + handlerNames.length);
+ let size = this.menuButtonPanel.size;
+ size.top = -this.endPosition;
+ size.bottom = 0;
+ this.menuButtonPanel.size = size;
+ }
+
+ rebuild()
+ {
+ this.menuButton.tooltip = sprintf(translate("Press %(hotkey)s to toggle this menu."), {
+ "hotkey": colorizeHotkey("%(hotkey)s", this.menuButton.hotkey),
+ });
+ }
+
+ /**
+ * This function may be overwritten to change the button order.
+ */
+ getHandlerNames()
+ {
+ return Object.keys(MenuButtons.prototype);
+ }
+
+ toggle()
+ {
+ this.isOpen = !this.isOpen;
+ this.startAnimation();
+ }
+
+ close()
+ {
+ this.isOpen = false;
+ this.startAnimation();
+ }
+
+ initButton(handler, button, i)
+ {
+ button.onPress = () => {
+ this.close();
+ handler.onPress();
+ };
+
+ let size = button.size;
+ size.top = this.buttonHeight * (i + 1) + this.margin;
+ size.bottom = this.buttonHeight * (i + 2);
+ button.size = size;
+
+ button.hidden = false;
+ }
+
+ startAnimation()
+ {
+ this.lastTick = Date.now();
+ this.menuButtonPanel.onTick = this.onTick.bind(this);
+ }
+
+ /**
+ * Animate menu panel.
+ */
+ onTick()
+ {
+ let tickLength = Date.now() - this.lastTick;
+ this.lastTick = Date.now();
+
+ let maxOffset =
+ this.endPosition + (
+ this.isOpen ?
+ -this.menuButtonPanel.size.bottom :
+ +this.menuButtonPanel.size.top);
+
+
+ if (maxOffset <= 0)
+ {
+ // TODO: support actually deleting the handler
+ this.menuButtonPanel.onTick = () => {};
+ return;
+ }
+
+ let offset = Math.min(this.Speed * tickLength, maxOffset) * (this.isOpen ? +1 : -1);
+ let size = this.menuButtonPanel.size;
+ size.top += offset;
+ size.bottom += offset;
+ this.menuButtonPanel.size = size;
+ }
+}
+
+/**
+ * Number of pixels per millisecond to move.
+ */
+Menu.prototype.Speed = 1.2;
Index: ps/trunk/binaries/data/mods/public/gui/session/Menu.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/Menu.xml
+++ ps/trunk/binaries/data/mods/public/gui/session/Menu.xml
@@ -0,0 +1,17 @@
+
+
Index: ps/trunk/binaries/data/mods/public/gui/session/MenuButtons.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/MenuButtons.js
+++ ps/trunk/binaries/data/mods/public/gui/session/MenuButtons.js
@@ -0,0 +1,309 @@
+/**
+ * This class is extended in subclasses.
+ * Each subclass represents one button in the session menu.
+ * All subclasses store the button member so that mods can change it easily.
+ */
+class MenuButtons
+{
+}
+
+MenuButtons.prototype.Manual = class
+{
+ constructor(button, pauseControl)
+ {
+ this.button = button;
+ this.button.caption = translate(translate("Manual"));
+ this.pauseControl = pauseControl;
+ }
+
+ onPress()
+ {
+ closeOpenDialogs();
+ this.pauseControl.implicitPause();
+ Engine.PushGuiPage("page_manual.xml", {}, resumeGame);
+ }
+};
+
+MenuButtons.prototype.Chat = class
+{
+ constructor(button, pauseControl, playerViewControl, chat)
+ {
+ this.button = button;
+ this.button.caption = translate("Chat");
+ this.chat = chat;
+ registerHotkeyChangeHandler(this.rebuild.bind(this));
+ }
+
+ rebuild()
+ {
+ this.button.tooltip = this.chat.getOpenHotkeyTooltip().trim();
+ }
+
+ onPress()
+ {
+ this.chat.openPage();
+ }
+};
+
+MenuButtons.prototype.Save = class
+{
+ constructor(button, pauseControl)
+ {
+ this.button = button;
+ this.button.caption = translate("Save");
+ this.pauseControl = pauseControl;
+ }
+
+ onPress()
+ {
+ closeOpenDialogs();
+ this.pauseControl.implicitPause();
+
+ Engine.PushGuiPage(
+ "page_loadgame.xml",
+ { "savedGameData": getSavedGameData() },
+ resumeGame);
+ }
+};
+
+MenuButtons.prototype.Summary = class
+{
+ constructor(button, pauseControl)
+ {
+ this.button = button;
+ this.button.caption = translate("Summary");
+ this.button.hotkey = "summary";
+ // TODO: Atlas should pass g_GameAttributes.settings
+ this.button.enabled = !Engine.IsAtlasRunning();
+
+ this.pauseControl = pauseControl;
+ this.selectedData = undefined;
+
+ registerHotkeyChangeHandler(this.rebuild.bind(this));
+ }
+
+ rebuild()
+ {
+ this.button.tooltip = sprintf(translate("Press %(hotkey)s to open the summary screen."), {
+ "hotkey": colorizeHotkey("%(hotkey)s", this.button.hotkey),
+ });
+ }
+
+ onPress()
+ {
+ if (Engine.IsAtlasRunning())
+ return;
+
+ closeOpenDialogs();
+ this.pauseControl.implicitPause();
+ // Allows players to see their own summary.
+ // If they have shared ally vision researched, they are able to see the summary of there allies too.
+ let simState = Engine.GuiInterfaceCall("GetExtendedSimulationState");
+ Engine.PushGuiPage(
+ "page_summary.xml",
+ {
+ "sim": {
+ "mapSettings": g_GameAttributes.settings,
+ "playerStates": simState.players.filter((state, player) =>
+ g_IsObserver || player == 0 || player == g_ViewedPlayer ||
+ simState.players[g_ViewedPlayer].hasSharedLos && g_Players[player].isMutualAlly[g_ViewedPlayer]),
+ "timeElapsed": simState.timeElapsed
+ },
+ "gui": {
+ "dialog": true,
+ "isInGame": true
+ },
+ "selectedData": this.selectedData
+ },
+ data =>
+ {
+ this.selectedData = data.summarySelectedData;
+ this.pauseControl.implicitResume();
+ });
+ }
+};
+
+MenuButtons.prototype.Lobby = class
+{
+ constructor(button)
+ {
+ this.button = button;
+ this.button.caption = translate("Lobby");
+ this.button.hotkey = "lobby";
+ this.button.enabled = Engine.HasXmppClient();
+
+ registerHotkeyChangeHandler(this.rebuild.bind(this));
+ }
+
+ rebuild()
+ {
+ this.button.tooltip = sprintf(translate("Press %(hotkey)s to open the multiplayer lobby page without leaving the game."), {
+ "hotkey": colorizeHotkey("%(hotkey)s", this.button.hotkey),
+ });
+ }
+
+ onPress()
+ {
+ if (!Engine.HasXmppClient())
+ return;
+ closeOpenDialogs();
+ Engine.PushGuiPage("page_lobby.xml", { "dialog": true });
+ }
+};
+
+MenuButtons.prototype.Options = class
+{
+ constructor(button, pauseControl)
+ {
+ this.button = button;
+ this.button.caption = translate("Options");
+ this.pauseControl = pauseControl;
+ }
+
+ onPress()
+ {
+ closeOpenDialogs();
+ this.pauseControl.implicitPause();
+
+ Engine.PushGuiPage(
+ "page_options.xml",
+ {},
+ callbackFunctionNames => {
+ for (let functionName of callbackFunctionNames)
+ if (global[functionName])
+ global[functionName]();
+
+ resumeGame();
+ });
+ }
+};
+
+MenuButtons.prototype.Pause = class
+{
+ constructor(button, pauseControl, playerViewControl)
+ {
+ this.button = button;
+ this.button.hotkey = "pause";
+ this.pauseControl = pauseControl;
+
+ registerPlayersInitHandler(this.rebuild.bind(this));
+ registerPlayersFinishedHandler(this.rebuild.bind(this));
+ playerViewControl.registerPlayerIDChangeHandler(this.rebuild.bind(this));
+ pauseControl.registerPauseHandler(this.rebuild.bind(this));
+ registerHotkeyChangeHandler(this.rebuild.bind(this));
+ }
+
+ rebuild()
+ {
+ this.button.enabled = !g_IsObserver || !g_IsNetworked || g_IsController;
+ this.button.caption = this.pauseControl.explicitPause ? translate("Resume") : translate("Pause");
+ this.button.tooltip = sprintf(translate("Press %(hotkey)s to pause or resume the game."), {
+ "hotkey": colorizeHotkey("%(hotkey)s", this.button.hotkey),
+ });
+ }
+
+ onPress()
+ {
+ this.pauseControl.setPaused(!g_PauseControl.explicitPause, true);
+ }
+};
+
+MenuButtons.prototype.Resign = class
+{
+ constructor(button, pauseControl, playerViewControl)
+ {
+ this.button = button;
+ this.button.caption = translate("Resign");
+ this.pauseControl = pauseControl;
+
+ registerPlayersInitHandler(this.rebuild.bind(this));
+ registerPlayersFinishedHandler(this.rebuild.bind(this));
+ playerViewControl.registerPlayerIDChangeHandler(this.rebuild.bind(this));
+ }
+
+ rebuild()
+ {
+ this.button.enabled = !g_IsObserver;
+ }
+
+ onPress()
+ {
+ closeOpenDialogs();
+ this.pauseControl.implicitPause();
+
+ messageBox(
+ 400, 200,
+ translate("Are you sure you want to resign?"),
+ translate("Confirmation"),
+ [translate("No"), translate("Yes")],
+ [
+ resumeGame,
+ () => {
+ Engine.PostNetworkCommand({
+ "type": "resign"
+ });
+ resumeGame();
+ }
+ ]);
+ }
+};
+
+MenuButtons.prototype.Exit = class
+{
+ constructor(button, pauseControl)
+ {
+ this.button = button;
+ this.button.caption = translate("Exit");
+ this.button.enabled = !Engine.IsAtlasRunning();
+ this.pauseControl = pauseControl;
+ }
+
+ onPress()
+ {
+ closeOpenDialogs();
+ this.pauseControl.implicitPause();
+
+ let messageType = g_IsNetworked && g_IsController ? "host" :
+ (g_IsNetworked && !g_IsObserver ? "client" : "singleplayer");
+
+ messageBox(
+ 400, 200,
+ this.Confirmation[messageType].caption(),
+ translate("Confirmation"),
+ [translate("No"), translate("Yes")],
+ this.Confirmation[messageType].buttons());
+ }
+};
+
+MenuButtons.prototype.Exit.prototype.Confirmation = {
+ "host": {
+ "caption": () => translate("Are you sure you want to quit? Leaving will disconnect all other players."),
+ "buttons": () => [resumeGame, endGame]
+ },
+ "client": {
+ "caption": () => translate("Are you sure you want to quit?"),
+ "buttons": () => [
+ resumeGame,
+ () => {
+ messageBox(
+ 400, 200,
+ translate("Do you want to resign or will you return soon?"),
+ translate("Confirmation"),
+ [translate("I will return"), translate("I resign")],
+ [
+ endGame,
+ () => {
+ Engine.PostNetworkCommand({
+ "type": "resign"
+ });
+ resumeGame();
+ }
+ ]);
+ }
+ ]
+ },
+ "singleplayer": {
+ "caption": () => translate("Are you sure you want to quit?"),
+ "buttons": () => [resumeGame, endGame]
+ }
+};
Index: ps/trunk/binaries/data/mods/public/gui/session/chat/Chat.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/chat/Chat.js
+++ ps/trunk/binaries/data/mods/public/gui/session/chat/Chat.js
@@ -68,6 +68,11 @@
this.ChatWindow.closePage();
}
+ getOpenHotkeyTooltip()
+ {
+ return this.ChatInput.getOpenHotkeyTooltip();
+ }
+
/**
* Send the given chat message.
*/
Index: ps/trunk/binaries/data/mods/public/gui/session/chat/ChatInput.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/chat/ChatInput.js
+++ ps/trunk/binaries/data/mods/public/gui/session/chat/ChatInput.js
@@ -12,18 +12,29 @@
this.chatInput = Engine.GetGUIObjectByName("chatInput");
this.chatInput.onPress = this.submitChatInput.bind(this);
this.chatInput.onTab = this.autoComplete.bind(this);
- this.chatInput.tooltip = this.getHotkeyTooltip();
this.sendChat = Engine.GetGUIObjectByName("sendChat");
this.sendChat.onPress = this.submitChatInput.bind(this);
- this.sendChat.tooltip = this.getHotkeyTooltip();
+
+ registerHotkeyChangeHandler(this.onHotkeyChange.bind(this));
+ }
+
+ onHotkeyChange()
+ {
+ let tooltip = this.getInputHotkeyTooltip() + this.getOpenHotkeyTooltip();
+ this.chatInput.tooltip = tooltip;
+ this.sendChat.tooltip = tooltip;
+ }
+
+ getInputHotkeyTooltip()
+ {
+ return translateWithContext("chat input", "Type the message to send.") + "\n" +
+ colorizeAutocompleteHotkey();
}
- getHotkeyTooltip()
+ getOpenHotkeyTooltip()
{
- return translateWithContext("chat input", "Type the message to send.") + "\n" +
- colorizeAutocompleteHotkey() +
- colorizeHotkey("\n" + translate("Press %(hotkey)s to open the public chat."), "chat") +
+ return colorizeHotkey("\n" + translate("Press %(hotkey)s to open the public chat."), "chat") +
colorizeHotkey(
"\n" + (g_IsObserver ?
translate("Press %(hotkey)s to open the observer chat.") :
Index: ps/trunk/binaries/data/mods/public/gui/session/hotkeys/misc.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/hotkeys/misc.xml
+++ ps/trunk/binaries/data/mods/public/gui/session/hotkeys/misc.xml
@@ -8,26 +8,10 @@
toggleGUI();
-
- toggleMenu();
-
-
toggleTutorial();
-
- openGameSummary();
-
-
-
- openStrucTree("page_civinfo.xml");
-
-
-
- openStrucTree("page_structree.xml");
-
-
toggleConfigBool("silhouettes");
Index: ps/trunk/binaries/data/mods/public/gui/session/input.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/input.js
+++ ps/trunk/binaries/data/mods/public/gui/session/input.js
@@ -478,7 +478,7 @@
// Close the menu when interacting with the game world
if (!mouseIsOverObject && (ev.type =="mousebuttonup" || ev.type == "mousebuttondown")
&& (ev.button == SDL_BUTTON_LEFT || ev.button == SDL_BUTTON_RIGHT))
- closeMenu();
+ g_Menu.close();
// State-machine processing:
//
Index: ps/trunk/binaries/data/mods/public/gui/session/menu.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/menu.js
+++ ps/trunk/binaries/data/mods/public/gui/session/menu.js
@@ -1,311 +0,0 @@
-// Menu / panel border size
-var MARGIN = 4;
-
-// Includes the main menu button
-const NUM_BUTTONS = 10;
-
-// Regular menu buttons
-var BUTTON_HEIGHT = 32;
-
-// The position where the bottom of the menu will end up (currently 228)
-const END_MENU_POSITION = (BUTTON_HEIGHT * NUM_BUTTONS) + MARGIN;
-
-// Menu starting position: bottom
-const MENU_BOTTOM = 0;
-
-// Menu starting position: top
-const MENU_TOP = MENU_BOTTOM - END_MENU_POSITION;
-
-// Number of pixels per millisecond to move
-var MENU_SPEED = 1.2;
-
-/**
- * Store civilization code and page (structree or history) opened in civilization info.
- */
-var g_CivInfo = {
- "civ": "",
- "page": "page_structree.xml"
-};
-
-var g_IsMenuOpen = false;
-
-/**
- * Remember last viewed summary panel and charts.
- */
-var g_SummarySelectedData;
-
-function initMenu(playerViewControl, pauseControl)
-{
- Engine.GetGUIObjectByName("menu").size = "100%-164 " + MENU_TOP + " 100% " + MENU_BOTTOM;
- Engine.GetGUIObjectByName("lobbyButton").enabled = Engine.HasXmppClient();
- playerViewControl.registerViewedPlayerChangeHandler(updateResignButton);
- updatePauseButton();
- pauseControl.registerPauseHandler(updatePauseButton);
-
- // TODO: Atlas should pass g_GameAttributes.settings
- for (let button of ["menuExitButton", "summaryButton"])
- Engine.GetGUIObjectByName(button).enabled = !Engine.IsAtlasRunning();
-}
-
-function updateMenuPosition(dt)
-{
- let menu = Engine.GetGUIObjectByName("menu");
-
- let maxOffset = g_IsMenuOpen ?
- END_MENU_POSITION - menu.size.bottom :
- menu.size.top - MENU_TOP;
-
- if (maxOffset <= 0)
- return;
-
- let offset = Math.min(MENU_SPEED * dt, maxOffset) * (g_IsMenuOpen ? +1 : -1);
-
- let size = menu.size;
- size.top += offset;
- size.bottom += offset;
- menu.size = size;
-}
-
-// Opens the menu by revealing the screen which contains the menu
-function openMenu()
-{
- g_IsMenuOpen = true;
-}
-
-// Closes the menu and resets position
-function closeMenu()
-{
- g_IsMenuOpen = false;
-}
-
-function toggleMenu()
-{
- g_IsMenuOpen = !g_IsMenuOpen;
-}
-
-function updatePauseButton()
-{
- let pauseButton = Engine.GetGUIObjectByName("pauseButton");
- pauseButton.caption = g_PauseControl.explicitPause ? translate("Resume") : translate("Pause");
- pauseButton.enabled = !g_IsObserver || !g_IsNetworked || g_IsController;
- pauseButton.onPress = () => {
- closeMenu();
- g_PauseControl.setPaused(!g_PauseControl.explicitPause, true);
- };
-}
-
-function updateResignButton()
-{
- Engine.GetGUIObjectByName("menuResignButton").enabled = !g_IsObserver;
-}
-
-function optionsMenuButton()
-{
- closeOpenDialogs();
- openOptions();
-}
-
-function lobbyDialogButton()
-{
- if (!Engine.HasXmppClient())
- return;
-
- closeOpenDialogs();
- Engine.PushGuiPage("page_lobby.xml", { "dialog": true });
-}
-
-function chatMenuButton()
-{
- g_Chat.openPage();
-}
-
-function resignMenuButton()
-{
- closeOpenDialogs();
- g_PauseControl.implicitPause();
-
- messageBox(
- 400, 200,
- translate("Are you sure you want to resign?"),
- translate("Confirmation"),
- [translate("No"), translate("Yes")],
- [resumeGame, resignGame]);
-}
-
-function exitMenuButton()
-{
- closeOpenDialogs();
- g_PauseControl.implicitPause();
-
- let messageTypes = {
- "host": {
- "caption": translate("Are you sure you want to quit? Leaving will disconnect all other players."),
- "buttons": [resumeGame, endGame]
- },
- "client": {
- "caption": translate("Are you sure you want to quit?"),
- "buttons": [resumeGame, resignQuestion]
- },
- "singleplayer": {
- "caption": translate("Are you sure you want to quit?"),
- "buttons": [resumeGame, endGame]
- }
- };
-
- let messageType = g_IsNetworked && g_IsController ? "host" :
- (g_IsNetworked && !g_IsObserver ? "client" : "singleplayer");
-
- messageBox(
- 400, 200,
- messageTypes[messageType].caption,
- translate("Confirmation"),
- [translate("No"), translate("Yes")],
- messageTypes[messageType].buttons
- );
-}
-
-function resignQuestion()
-{
- messageBox(
- 400, 200,
- translate("Do you want to resign or will you return soon?"),
- translate("Confirmation"),
- [translate("I will return"), translate("I resign")],
- [endGame, resignGame]);
-}
-
-function openDeleteDialog(selection)
-{
- closeOpenDialogs();
- g_PauseControl.implicitPause();
-
- let deleteSelectedEntities = function(selectionArg)
- {
- Engine.PostNetworkCommand({
- "type": "delete-entities",
- "entities": selectionArg
- });
- resumeGame();
- };
-
- messageBox(
- 400, 200,
- translate("Destroy everything currently selected?"),
- translate("Delete"),
- [translate("No"), translate("Yes")],
- [resumeGame, deleteSelectedEntities],
- [null, selection]
- );
-}
-
-function openSave()
-{
- closeOpenDialogs();
- g_PauseControl.implicitPause();
-
- Engine.PushGuiPage(
- "page_loadgame.xml",
- { "savedGameData": getSavedGameData() },
- resumeGame);
-}
-
-function openOptions()
-{
- closeOpenDialogs();
- g_PauseControl.implicitPause();
-
- Engine.PushGuiPage(
- "page_options.xml",
- {},
- callbackFunctionNames => {
- for (let functionName of callbackFunctionNames)
- if (global[functionName])
- global[functionName]();
-
- resumeGame();
- });
-}
-
-function toggleTutorial()
-{
- let tutorialPanel = Engine.GetGUIObjectByName("tutorialPanel");
- tutorialPanel.hidden = !tutorialPanel.hidden ||
- !Engine.GetGUIObjectByName("tutorialText").caption;
-}
-
-/**
- * Allows players to see their own summary.
- * If they have shared ally vision researched, they are able to see the summary of there allies too.
- */
-function openGameSummary()
-{
- closeOpenDialogs();
- g_PauseControl.implicitPause();
-
- let extendedSimState = Engine.GuiInterfaceCall("GetExtendedSimulationState");
- Engine.PushGuiPage(
- "page_summary.xml",
- {
- "sim": {
- "mapSettings": g_GameAttributes.settings,
- "playerStates": extendedSimState.players.filter((state, player) =>
- g_IsObserver || player == 0 || player == g_ViewedPlayer ||
- extendedSimState.players[g_ViewedPlayer].hasSharedLos && g_Players[player].isMutualAlly[g_ViewedPlayer]),
- "timeElapsed": extendedSimState.timeElapsed
- },
- "gui": {
- "dialog": true,
- "isInGame": true
- },
- "selectedData": g_SummarySelectedData
- },
- data =>
- {
- g_SummarySelectedData = data.summarySelectedData;
- g_PauseControl.implicitResume();
- });
-}
-
-function openStrucTree(page)
-{
- closeOpenDialogs();
- g_PauseControl.implicitPause();
-
- Engine.PushGuiPage(
- page,
- {
- "civ": g_CivInfo.civ || g_Players[g_ViewedPlayer].civ
- // TODO add info about researched techs and unlocked entities
- },
- storeCivInfoPage);
-}
-
-function storeCivInfoPage(data)
-{
- if (data.nextPage)
- Engine.PushGuiPage(
- data.nextPage,
- { "civ": data.civ },
- storeCivInfoPage);
- else
- {
- g_CivInfo = data;
- resumeGame();
- }
-}
-
-function openManual()
-{
- closeOpenDialogs();
- g_PauseControl.implicitPause();
- Engine.PushGuiPage("page_manual.xml", {}, resumeGame);
-}
-
-function closeOpenDialogs()
-{
- closeMenu();
- g_Chat.closePage();
- g_DiplomacyDialog.close();
- g_ObjectivesDialog.close();
- g_TradeDialog.close();
-}
Index: ps/trunk/binaries/data/mods/public/gui/session/menu.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/menu.xml
+++ ps/trunk/binaries/data/mods/public/gui/session/menu.xml
@@ -1,112 +0,0 @@
-
-
-
-
-
-
- Manual
- openManual();
-
-
-
-
- Chat
- chatMenuButton();
-
-
-
-
- Save
-
- openSave();
-
-
-
-
-
- Summary
- openGameSummary();
-
-
-
-
- Lobby
- Show the multiplayer lobby in a dialog window.
- lobbyDialogButton();
-
-
-
-
- Options
- optionsMenuButton();
-
-
-
-
-
-
-
- Resign
- resignMenuButton();
-
-
-
-
- Exit
- exitMenuButton();
-
-
-
-
-
Index: ps/trunk/binaries/data/mods/public/gui/session/messages.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/messages.js
+++ ps/trunk/binaries/data/mods/public/gui/session/messages.js
@@ -359,6 +359,12 @@
}
}
+function toggleTutorial()
+{
+ let tutorialPanel = Engine.GetGUIObjectByName("tutorialPanel");
+ tutorialPanel.hidden = !tutorialPanel.hidden || !Engine.GetGUIObjectByName("tutorialText").caption;
+}
+
/**
* Updates the tutorial panel when a new goal.
*/
Index: ps/trunk/binaries/data/mods/public/gui/session/session.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/session.js
+++ ps/trunk/binaries/data/mods/public/gui/session/session.js
@@ -14,6 +14,7 @@
var g_DiplomacyColors;
var g_DiplomacyDialog;
var g_GameSpeedControl;
+var g_Menu;
var g_MiniMapPanel;
var g_ObjectivesDialog;
var g_PauseControl;
@@ -287,6 +288,7 @@
g_ObjectivesDialog = new ObjectivesDialog(g_PlayerViewControl);
g_PauseControl = new PauseControl();
g_PauseOverlay = new PauseOverlay(g_PauseControl);
+ g_Menu = new Menu(g_PauseControl, g_PlayerViewControl, g_Chat);
g_TradeDialog = new TradeDialog(g_PlayerViewControl);
g_TopPanel = new TopPanel(g_PlayerViewControl, g_DiplomacyDialog, g_TradeDialog, g_ObjectivesDialog, g_GameSpeedControl);
@@ -294,7 +296,6 @@
LoadModificationTemplates();
updatePlayerData();
initializeMusic(); // before changing the perspective
- initMenu(g_PlayerViewControl, g_PauseControl);
initPanelEntities();
Engine.SetBoundingBoxDebugOverlay(false);
updateEnabledRangeOverlayTypes();
@@ -504,13 +505,7 @@
// TODO: The other calls in this function should move too
for (let handler of g_PlayerFinishedHandlers)
- handler();
-
- if (players.indexOf(g_ViewedPlayer) == -1)
- return;
-
- // Select "observer" item on loss. On win enable observermode without changing perspective
- g_PlayerViewControl.selectViewPlayer(won ? g_ViewedPlayer + 1 : 0);
+ handler(players, won);
if (players.indexOf(Engine.GetPlayerID()) == -1 || Engine.IsAtlasRunning())
return;
@@ -529,12 +524,13 @@
g_PauseControl.implicitResume();
}
-function resignGame()
+function closeOpenDialogs()
{
- Engine.PostNetworkCommand({
- "type": "resign"
- });
- g_PauseControl.implicitResume();
+ g_Menu.close();
+ g_Chat.closePage();
+ g_DiplomacyDialog.close();
+ g_ObjectivesDialog.close();
+ g_TradeDialog.close();
}
function endGame()
@@ -638,7 +634,6 @@
recalculateStatusBarDisplay();
updateTimers();
- updateMenuPosition(tickLength);
Engine.GuiInterfaceCall("ClearRenamedEntities");
}
Index: ps/trunk/binaries/data/mods/public/gui/session/session.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/session.xml
+++ ps/trunk/binaries/data/mods/public/gui/session/session.xml
@@ -96,7 +96,7 @@
-
+
Index: ps/trunk/binaries/data/mods/public/gui/session/top_panel/CivIcon.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/top_panel/CivIcon.js
+++ ps/trunk/binaries/data/mods/public/gui/session/top_panel/CivIcon.js
@@ -6,16 +6,53 @@
{
constructor(playerViewControl)
{
+ this.dialogSelection = {
+ "civ": "",
+ "page": "page_structree.xml"
+ };
+
this.civIcon = Engine.GetGUIObjectByName("civIcon");
this.civIconOverlay = Engine.GetGUIObjectByName("civIconOverlay");
this.civIconOverlay.onPress = this.onPress.bind(this);
+
playerViewControl.registerViewedPlayerChangeHandler(this.rebuild.bind(this));
registerHotkeyChangeHandler(this.rebuild.bind(this));
+
+ Engine.SetGlobalHotkey("civinfo", () => this.openPage("page_civinfo.xml"));
+ Engine.SetGlobalHotkey("structree", () => this.openPage("page_structree.xml"));
}
onPress()
{
- openStrucTree(g_CivInfo.page);
+ this.openPage(this.dialogSelection.page);
+ }
+
+ openPage(page)
+ {
+ closeOpenDialogs();
+ g_PauseControl.implicitPause();
+
+ Engine.PushGuiPage(
+ page,
+ {
+ "civ": this.dialogSelection.civ || g_Players[g_ViewedPlayer].civ
+ // TODO add info about researched techs and unlocked entities
+ },
+ this.storePageSelection.bind(this));
+ }
+
+ storePageSelection(data)
+ {
+ if (data.nextPage)
+ Engine.PushGuiPage(
+ data.nextPage,
+ { "civ": data.civ },
+ this.storePageSelection.bind(this));
+ else
+ {
+ this.dialogSelection = data;
+ resumeGame();
+ }
}
rebuild()
@@ -28,7 +65,7 @@
let civData = g_CivData[g_Players[g_ViewedPlayer].civ];
this.civIcon.sprite = "stretched:" + civData.Emblem;
- this.civIconOverlay.tooltip = sprintf(translate(this.OverlayTooltip), {
+ this.civIconOverlay.tooltip = sprintf(translate(this.Tooltip), {
"civ": setStringTags(civData.Name, this.CivTags),
"hotkey_civinfo": colorizeHotkey("%(hotkey)s", "civinfo"),
"hotkey_structree": colorizeHotkey("%(hotkey)s", "structree")
@@ -36,7 +73,7 @@
}
}
-CivIcon.prototype.OverlayTooltip =
+CivIcon.prototype.Tooltip =
markForTranslation("%(civ)s\n%(hotkey_civinfo)s / %(hotkey_structree)s: View History / Structure Tree\nLast opened will be reopened on click.");
CivIcon.prototype.CivTags = { "font": "sans-bold-stroke-14" };
Index: ps/trunk/binaries/data/mods/public/gui/session/top_panel/MenuButton.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/top_panel/MenuButton.xml
+++ ps/trunk/binaries/data/mods/public/gui/session/top_panel/MenuButton.xml
@@ -1,6 +1,7 @@
Menu
-
- toggleMenu();
-
Index: ps/trunk/binaries/data/mods/public/gui/session/top_panel/PlayerViewControl.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/top_panel/PlayerViewControl.js
+++ ps/trunk/binaries/data/mods/public/gui/session/top_panel/PlayerViewControl.js
@@ -20,6 +20,7 @@
// Events
this.viewPlayer.onSelectionChange = this.onSelectionChange.bind(this);
registerPlayersInitHandler(this.onPlayersInit.bind(this));
+ registerPlayersFinishedHandler(this.onPlayersFinished.bind(this));
this.registerViewedPlayerChangeHandler(this.rebuild.bind(this));
}
@@ -48,13 +49,24 @@
this.observerText.hidden = g_ViewedPlayer > 0;
}
+ /**
+ * Select "observer" in the view player dropdown when rejoining as a defeated player.
+ */
onPlayersInit()
{
this.rebuild();
- // Select "observer" in the view player dropdown when rejoining as a defeated player
let playerState = g_Players[Engine.GetPlayerID()];
- this.viewPlayer.selected = playerState && playerState.state == "defeated" ? 0 : Engine.GetPlayerID() + 1;
+ this.selectViewPlayer(playerState && playerState.state == "defeated" ? 0 : Engine.GetPlayerID() + 1);
+ }
+
+ /**
+ * Select "observer" item on loss. On win enable observermode without changing perspective.
+ */
+ onPlayersFinished(playerIDs, won)
+ {
+ if (playerIDs.indexOf(g_ViewedPlayer) != -1)
+ this.selectViewPlayer(won ? g_ViewedPlayer + 1 : 0);
}
setChangePerspective(enabled)
Index: ps/trunk/binaries/data/mods/public/gui/session/unit_actions.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/unit_actions.js
+++ ps/trunk/binaries/data/mods/public/gui/session/unit_actions.js
@@ -1063,16 +1063,41 @@
},
"execute": function(entStates)
{
- if (!entStates.length || entStates.every(entState => isUndeletable(entState)))
+ let entityIDs = entStates.reduce(
+ (ids, entState) => {
+ if (!isUndeletable(entState))
+ ids.push(entState.id);
+ return ids;
+ },
+ []);
+
+ if (!entityIDs.length)
return;
+ let deleteSelection = () => Engine.PostNetworkCommand({
+ "type": "delete-entities",
+ "entities": entityIDs
+ });
+
if (Engine.HotkeyIsPressed("session.noconfirmation"))
- Engine.PostNetworkCommand({
- "type": "delete-entities",
- "entities": entStates.map(entState => entState.id)
- });
+ deleteSelection();
else
- openDeleteDialog(entStates.map(entState => entState.id));
+ {
+ closeOpenDialogs();
+ g_PauseControl.implicitPause();
+ messageBox(
+ 400, 200,
+ translate("Destroy everything currently selected?"),
+ translate("Delete"),
+ [translate("No"), translate("Yes")],
+ [
+ resumeGame,
+ () => {
+ deleteSelection();
+ resumeGame();
+ }
+ ]);
+ };
},
},