1
0
forked from 0ad/0ad

# Restructured GUI implementation

CGUI now represents a single 'page'. CGUIManager maintains multiple
pages and switches between them.
Split the XML files into pregame, loading, session and messagebox pages.
Added hotloading of GUI pages.
Minor GUI cleanups.
(Merge from hg 81862d33780c)

This was SVN commit r7214.
This commit is contained in:
Ykkrosh 2009-12-03 20:17:22 +00:00
parent f85f0c0c2e
commit f0d9806b3f
73 changed files with 1062 additions and 1053 deletions

View File

@ -0,0 +1,35 @@
/*
DESCRIPTION : Contains global GUI functions, which will later be accessible from every GUI script/file.
NOTES : So far, only the message box-related functions are implemented.
*/
// *******************************************
// messageBox
// *******************************************
// @params: int mbWidth, int mbHeight, string mbMessage, string mbTitle, int mbMode, arr mbButtonCaptions
// @return: void
// @desc: Displays a new modal message box.
// *******************************************
function messageBox (mbWidth, mbHeight, mbMessage, mbTitle, mbMode, mbButtonCaptions, mbButtonsCode)
{
pushGuiPage("page_msgbox.xml", {
width: mbWidth,
height: mbHeight,
message: mbMessage,
title: mbTitle,
mode: mbMode,
buttonCaptions: mbButtonCaptions,
buttonCode: mbButtonsCode
});
}
// ====================================================================
function updateFPS()
{
getGUIObjectByName("fpsCounter").caption = "FPS: " + getFPS();
}
// ====================================================================

View File

@ -0,0 +1,60 @@
/*
DESCRIPTION : Functions used load/end the game session and manipulate the loading screen.
NOTES :
*/
// ====================================================================
function launchGame ()
{
// Starts the map, closing the session setup window.
var mapName = getCurrItemValue("pgSessionSetupMapName");
var gameMode = getCurrItemValue("pgSessionSetupGameMode");
var screenshotMode = getGUIObjectByName("pgSessionSetupScreenshotMode").checked;
var losSetting = getGUIObjectByName("pgSessionSetupLosSetting").selected;
var fogOfWar = getGUIObjectByName("pgSessionSetupFoW").checked;
if(screenshotMode)
{
losSetting = 2;
fogOfWar = false;
}
// Check whether we have a correct file extension, to avoid crashes
var extension = mapName.substring (mapName.length, mapName.length-4);
if (extension != ".pmp")
{
// Add .pmp to the file name.
var mapName = mapName + ".pmp";
}
// Set up game
g_GameAttributes.mapFile = mapName;
g_GameAttributes.losSetting = losSetting;
g_GameAttributes.fogOfWar = fogOfWar;
g_GameAttributes.gameMode = gameMode
g_GameAttributes.screenshotMode = screenshotMode;
// Close setup window
closeMainMenuSubWindow ("pgSessionSetup");
// Display loading screen.
switchGuiPage("page_loading.xml");
console.write( "running startGame()" );
// Begin game session.
if (! startGame())
{
// Failed to start the game; go back to the main menu.
switchGuiPage("page_pregame.xml");
// Restore default cursor.
setCursor ("arrow-default");
// Show an error message
messageBox(400, 200, "The game could not be started with the given parameters. You probably have entered an invalid map name.", "Error", 0, ["OK"], [undefined]);
}
console.write( "done running startGame()" );
}
// ====================================================================

View File

@ -6,18 +6,14 @@
// ====================================================================
function initCoord()
{
// Initialise coordinate set for this page.
Crd = new Array();
Crd.last = new Object(-1);
// Initialise coordinate set for this page.
Crd = { last: -1 };
// Set corner constants.
rb = 0;
lb = 1;
lt = 2;
rt = 3;
}
// Set corner constants.
rb = 0;
lb = 1;
lt = 2;
rt = 3;
// ====================================================================
@ -284,4 +280,4 @@ function setSkin (skinName)
*/
}
// ====================================================================
// ====================================================================

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
<!DOCTYPE objects SYSTEM "../gui.dtd">
<objects>
<!--
==========================================
- GLOBAL OBJECTS -
==========================================
-->
<object>
<!--
==========================================
- FPS COUNTER
==========================================
-->
<object name="fpsCounter"
type="text"
ghost="true"
hidden="true"
hotkey="fps.toggle"
font="verdana16"
textcolor="100 100 0"
size="18 18 200 35"
z="199"
>
<action on="Load"><![CDATA[
setInterval (updateFPS, 1, 200);
]]></action>
<action on="Press"><![CDATA[
guiToggle (this.name);
]]></action>
</object>
<!--
==========================================
- WATERMARK - USED WHEN TAKING OFFICIAL SCREENSHOTS
==========================================
-->
<object name="glbWaterMark"
hidden="true"
hotkey="screenshot.watermark"
z="200"
>
<action on="Press"><![CDATA[
guiToggle ("glbWaterMark");
]]></action>
<object name="glbWaterMarkProductLogo"
type="image"
size="0 100%-88 190 100%"
sprite="watermarkProduct"
/>
<object name="glbWaterMarkCompanyLogo"
type="image"
size="100%-207 100%-28 100% 100%"
sprite="watermarkCompany"
/>
</object>
</object>
</objects>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
<!DOCTYPE objects SYSTEM "../gui.dtd">
<objects>
<!--
==========================================
- INCLUDE SCRIPT - UTILITY FUNCTIONS
==========================================
-->
<script file="gui/common/functions_utility.js" />
<script file="gui/common/functions_utility_list.js" />
<script file="gui/common/functions_utility_object.js" />
<script file="gui/common/functions_utility_coord.js" />
<script file="gui/common/functions_utility_music.js" />
<script file="gui/common/functions_utility_animation.js" />
<!--
==========================================
- INCLUDE SCRIPT - GLOBAL OBJECT FUNCTIONS
==========================================
-->
<script file="gui/common/functions_global_object.js" />
<!--
==========================================
- INCLUDE SCRIPT - GUI PAGE FUNCTIONS
==========================================
-->
<script file="gui/common/functions_page_pregame.js" />
<script file="gui/common/functions_page_pregame_multiplayer.js" />
<script file="gui/common/functions_page_pregame_setup.js" />
<script file="gui/common/functions_page_pregame_load.js" />
<script file="gui/common/functions_page_session.js"/>
<script file="gui/common/functions_page_session_status_pane.js" />
<script file="gui/common/functions_page_session_status_commands.js" />
<script file="gui/common/functions_page_session_manual.js" />
<!--
==========================================
- INCLUDE SCRIPT - SIMULATION FUNCTIONS
==========================================
-->
<script file="gui/common/functions_sim_player.js"/>
<script file="gui/common/functions_sim_entity.js"/>
</objects>

View File

@ -0,0 +1,47 @@
function init()
{
// Set to "hourglass" cursor.
setCursor("cursor-wait");
console.write ("Loading " + g_GameAttributes.mapFile + " (" + g_GameAttributes.numPlayers + " players) ...");
// Choose random concept art for loading screen background (should depend on the selected civ later when this is specified).
var sprite = "";
var loadingBkgArray = buildDirEntList("art/textures/ui/loading/", "*.dds", false);
if (loadingBkgArray.length == 0)
console.write ("ERROR: Failed to find any matching textures for the loading screen background.");
else
{
// Get a random index from the list of loading screen backgrounds.
sprite = "stretched:" + loadingBkgArray[getRandom (0, loadingBkgArray.length-1)];
sprite = sprite.replace ("art/textures/ui/", "");
}
getGUIObjectByName ("ldConcept").sprite = sprite;
// janwas: main loop now sets progress / description, but that won't
// happen until the first timeslice completes, so set initial values.
getGUIObjectByName ("ldTitleBar").caption = "Loading Scenario ...";
getGUIObjectByName ("ldProgressBarText").caption = "";
getGUIObjectByName ("ldProgressBar").caption = 0;
getGUIObjectByName ("ldText").caption = "LOADING " + g_GameAttributes.mapFile + " ...\nPlease wait ...";
// Pick a random tip of the day (each line is a separate tip).
var tipArray = readFileLines("gui/text/tips.txt");
// Set tip string.
getGUIObjectByName ("ldTip").caption = tipArray[getRandom(0, tipArray.length-1)];
}
// ====================================================================
function reallyStartGame()
{
// This is a reserved function name that is executed by the engine when it is ready
// to start the game (ie loading progress has reached 100%).
// Switch GUI from loading screen to game session.
writeLog(uneval(switchGuiPage));
switchGuiPage("page_session.xml");
// Restore default cursor.
setCursor ("arrow-default");
}

View File

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
<!DOCTYPE objects SYSTEM "../gui.dtd">
<?xml version="1.0" encoding="utf-8"?>
<!--
==========================================
@ -10,9 +8,10 @@
<objects>
<script file="gui/loading/loading.js"/>
<object name="ld"
type="image"
hidden="true"
sprite="bkFillBlack"
>
<!--

View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<objects>
<script>
function init(data)
{
var mbMainObj = getGUIObjectByName ("mbMain");
var mbTitleObj = getGUIObjectByName ("mbTitleBar");
var mbTextObj = getGUIObjectByName ("mbText");
var mbButton1Obj = getGUIObjectByName ("mbButton1");
var mbButton2Obj = getGUIObjectByName ("mbButton2");
var mbButton3Obj = getGUIObjectByName ("mbButton3");
// Calculate size
var mbLRDiff = data.width / 2; // Message box left/right difference from 50% of screen
var mbUDDiff = data.height / 2; // Message box up/down difference from 50% of screen
var mbSizeString = "50%-" + mbLRDiff + " 50%-" + mbUDDiff + " 50%+" + mbLRDiff + " 50%+" + mbUDDiff;
mbMainObj.size = mbSizeString;
// Texts
mbTitleObj.caption = data.title;
mbTextObj.caption = data.message;
// Message box modes
// There is a number of standard modes, and if none of these is used (mbMode == 0), the button captions will be
// taken from the array mbButtonCaptions; there currently is a maximum of three buttons.
switch (data.mode)
{
case 1:
// Simple Yes/No question box
data.buttonCaptions = ["Yes", "No"];
break;
case 2:
// Okay-only box
data.buttonCaptions = ["OK"];
break;
case 3:
// Retry/Abort/Ignore box (will we ever need this?!)
data.buttonCaptions = ["Retry", "Ignore", "Abort"];
default:
break;
}
// Buttons
var codes = data.buttonCode;
if (data.buttonCaptions.length >= 1)
{
mbButton1Obj.caption = data.buttonCaptions[0];
mbButton1Obj.onPress = function () { popGuiPage(); if (codes[0]) codes[0](); }
mbButton1Obj.hidden = false;
}
if (data.buttonCaptions.length >= 2)
{
mbButton2Obj.caption = data.buttonCaptions[1];
mbButton2Obj.onPress = function () { popGuiPage(); if (codes[1]) codes[1](); }
mbButton2Obj.hidden = false;
}
if (data.buttonCaptions.length >= 3)
{
mbButton3Obj.caption = data.buttonCaptions[2];
mbButton3Obj.onPress = function () { popGuiPage(); if (codes[2]) codes[2](); }
mbButton3Obj.hidden = false;
}
switch (data.buttonCaptions.length)
{
case 1:
mbButton1Obj.size = "30% 100%-80 70% 100%-50";
break;
case 2:
mbButton1Obj.size = "10% 100%-80 45% 100%-50";
mbButton2Obj.size = "55% 100%-80 90% 100%-50";
break;
case 3:
mbButton1Obj.size = "10% 100%-80 30% 100%-50";
mbButton2Obj.size = "40% 100%-80 60% 100%-50";
mbButton3Obj.size = "70% 100%-80 90% 100%-50";
break;
}
}
</script>
<object>
<object name="mbMain"
style="wheatWindow"
type="image"
size="50%-400 50%-200 50%+400 50%+200"
z="198"
>
<object name="mbTitleBar"
style="wheatWindowTitleBar"
type="button"
/>
<object name="mbText"
style="fancyTextTitleBlack"
type="text"
size="30 30 100%-30 100%-100"
/>
<object name="mbButton1"
style="wheatButtonFancy"
type="button"
hidden="true"
size="40 100%-50 33%-30 100%-20"
/>
<object name="mbButton2"
style="wheatButtonFancy"
type="button"
hidden="true"
size="33%+30 100%-50 66%-40 100%-20"
/>
<object name="mbButton3"
style="wheatButtonFancy"
type="button"
hidden="true"
size="66%+30 100%-50 100%-40 100%-20"
/>
</object>
</object>
</objects>

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<page>
</page>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<page>
<include>common/setup.xml</include>
<include>common/styles.xml</include>
<include>common/sprite1.xml</include>
<include>common/init.xml</include>
<include>loading/loading.xml</include>
<include>common/global.xml</include>
</page>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<page>
<include>common/setup.xml</include>
<include>common/styles.xml</include>
<include>common/sprite1.xml</include>
<include>msgbox/msgbox.xml</include>
</page>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<page>
<include>common/setup.xml</include>
<include>common/styles.xml</include>
<include>common/sprite1.xml</include>
<include>common/init.xml</include>
<include>pregame/mainmenu.xml</include>
<include>common/global.xml</include>
</page>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<page>
<include>common/setup.xml</include>
<include>common/styles.xml</include>
<include>common/sprite1.xml</include>
<include>common/init.xml</include>
<include>session/session.xml</include>
<include>session/manual.xml</include>
<include>common/global.xml</include>
</page>

View File

@ -4,6 +4,10 @@
<objects>
<script>
function init () { }
</script>
<!--
==========================================
- PROGRESS BAR FOR ARCHIVE BUILDER
@ -13,6 +17,7 @@
<object name="ab"
type="button"
size="0 0 100% 100%"
hidden="true"
ghost="false"
hotkey="archive.abort"
sprite="bkFillBlack"
@ -62,7 +67,6 @@
<object name="pg"
type="image"
sprite="pgBackground"
hidden="true"
>
<!--
==========================================
@ -300,10 +304,9 @@
tooltip="These are the guys who made this game. Visit them at http://www.wildfiregames.com/0ad/"
>
<action on="Press"><![CDATA[
btCode = new Array("guiHide('mbMain');");
messageBox (420, 420, "[icon=iconProduct] A.D. - History Is Yours For The Taking\nby Wildfire Games, 2002-2005\n\nVersion 0.1.2 (PASAP II)\n\n" +
"This is a confidental pre-release version of the game!\n\nVisit http://www.wildfiregames.com/0ad/ " +
"to learn more about [icon=iconProduct] A.D., participate in the community and meet the developers.\n\n", "About [icon=iconProduct] A.D.", 2, new Array(), btCode);
"to learn more about [icon=iconProduct] A.D., participate in the community and meet the developers.\n\n", "About [icon=iconProduct] A.D.", 2, [], []);
]]></action>
</object>
@ -320,8 +323,8 @@
tooltip="Tired of 0 A.D. ? Click here to leave and reenter the real world."
>
<action on="Press"><![CDATA[
btCaptions = new Array("Yes, let me out!", "Nooooo!");
btCode = new Array("exit();", "");
btCaptions = ["Yes, let me out!", "Nooooo!"];
btCode = [exit, null];
messageBox (400, 200, "Do you really want to quit [icon=iconProduct] A.D.? This will cause a sudden return to reality.", "Confirmation", 0, btCaptions, btCode);
]]></action>
</object>

View File

@ -0,0 +1,82 @@
function init()
{
// Set starting UI layout.
GUIType=rb;
// Set session UI sprites to match the skin for the player's civilisation.
// (We don't have skins for all civs yet, so we're using the standard menu skin. But it should be settable from here later.)
setSkin ("wheat");
// Set GUI coordinates to starting orientation.
flipGUI (GUIType);
// Create resource pools for each player, etc.
setupSession();
}
// ====================================================================
function setupSession ()
{
// Do essentials that can only be done when the session has been loaded ...
// For example, create the resource types, scores, etc, for each player.
/*
if (sessionType == "Skirmish")
{
// Set up a bunch of players so we can see them pretty colours. :P
console.write ("Setting Up Temporary Single Players");
// The first player is by default allocated to the local player in SP, so
// adding 7 players means that we'll have 8 players in total
for (var i=0; i<7; i++)
{
g_GameAttributes.slots[i+1].assignLocal();
console.write ("Slot "+(i+1)+" is assigned: " + g_GameAttributes.slots[i+1].assignment);
}
}
*/
// Select session peace track.
curr_session_playlist_1 = newRandomSound("music", "peace");
// Fade out main theme and fade in session theme.
crossFade(curr_music, curr_session_playlist_1, 1)
// Create the resouce counters
createResourceCounters();
// Start refreshing the session controls.
setInterval( snRefresh, 1, 100 );
}
// ====================================================================
function endSession (closeType)
{
// Occurs when the player chooses to close the current game.
switch (closeType)
{
case ("return"):
// If the player has chosen to quit game and return to main menu,
// End the session.
endGame();
// Fade out current music and return to playing menu theme.
//curr_music = newRandomSound("music", "menu");
//crossFade(curr_session_playlist_1, curr_music, 1);
// Stop refreshing the session controls.
cancelInterval();
// Swap GUIs to display main menu.
switchGuiPage("page_pregame.xml");
break;
case ("exit"):
// If the player has chosen to shutdown and immediately return to operating system,
exit();
break;
}
}

View File

@ -10,10 +10,15 @@
<objects>
<script file="gui/session/session.js"/>
<object name="sn"
hidden="true"
hotkey="session.gui.toggle"
>
<action on="Load"><![CDATA[
initSession();
]]></action>
<action on="Press"><![CDATA[
guiToggle (this.name);
]]></action>
@ -23,8 +28,8 @@
hotkey="leave"
>
<action on="Press"><![CDATA[
btCaptions = new Array("Yes", "No!");
btCode = new Array("confirmLeave()", "");
btCaptions = ["Yes", "No!"];
btCode = [confirmLeave, null];
messageBox (400, 200, "Do you really want to quit?", "Confirmation", 0, btCaptions, btCode);
]]></action>
</object>

View File

@ -1,75 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
<!DOCTYPE objects SYSTEM "../gui.dtd">
<objects>
<!--
==========================================
- INCLUDE SCRIPT - UTILITY FUNCTIONS
==========================================
-->
<script file="gui/test/functions_utility.js" />
<script file="gui/test/functions_utility_list.js" />
<script file="gui/test/functions_utility_object.js" />
<script file="gui/test/functions_utility_coord.js" />
<script file="gui/test/functions_utility_music.js" />
<script file="gui/test/functions_utility_animation.js" />
<!--
==========================================
- INCLUDE SCRIPT - GLOBAL OBJECT FUNCTIONS
==========================================
-->
<script file="gui/test/functions_global_object.js" />
<!--
==========================================
- INCLUDE SCRIPT - GUI PAGE FUNCTIONS
==========================================
-->
<script file="gui/test/functions_page_pregame.js" />
<script file="gui/test/functions_page_pregame_multiplayer.js" />
<script file="gui/test/functions_page_pregame_setup.js" />
<script file="gui/test/functions_page_pregame_load.js" />
<script file="gui/test/functions_page_session.js"/>
<script file="gui/test/functions_page_session_status_pane.js" />
<script file="gui/test/functions_page_session_status_commands.js" />
<script file="gui/test/functions_page_session_manual.js" />
<!--
==========================================
- INCLUDE SCRIPT - SIMULATION FUNCTIONS
==========================================
-->
<script file="gui/test/functions_sim_player.js"/>
<script file="gui/test/functions_sim_entity.js"/>
<!--
==========================================
- INCLUDE SCRIPT - INITIALISATION FUNCTIONS
==========================================
-->
<script file="gui/test/functions_global_init.js"><![CDATA[
init();
]]></script>
</objects>

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
<!DOCTYPE objects SYSTEM "../gui.dtd">
<!--
==========================================
- JUKEBOX DEFINITION -
==========================================
-->
<objects>
<object name="jb" >
</object>
</objects>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
<!DOCTYPE objects SYSTEM "../gui.dtd">
<!--
==========================================
- SESSION GUI SUB-WINDOW DEFINITIONS -
==========================================
-->
<objects>
</objects>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
<!DOCTYPE objects SYSTEM "../gui.dtd">
<!--
==========================================
- ATLAS SCENARIO EDITOR DEFINITION -
==========================================
-->
<objects>
</objects>

View File

@ -1,134 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
<!DOCTYPE objects SYSTEM "../gui.dtd">
<objects>
<!--
==========================================
- GLOBAL OBJECTS -
==========================================
-->
<object>
<!--
==========================================
- MESSAGE BOX -
==========================================
-->
<object name="mbMain"
style="wheatWindow"
type="image"
hidden="true"
size="50%-400 50%-200 50%+400 50%+200"
z="198"
>
<!-- control for blocking access to other controls in background -->
<object name="mbBlocker"
type="image"
hidden="false"
/>
<object name="mbTitleBar"
style="wheatWindowTitleBar"
type="button"
>mbTitle
</object>
<!-- text -->
<object name="mbText"
style="fancyTextTitleBlack"
type="text"
size="30 30 100%-30 100%-100"
>mbMessage
</object>
<!-- buttons -->
<object name="mbButton1"
style="wheatButtonFancy"
type="button"
size="40 100%-50 33%-30 100%-20"
>mbButton1Caption
<action on="Press"><![CDATA[
eval (getGUIGlobal().mbButton1Code);
guiHide ("mbMain");
]]></action>
</object>
<object name="mbButton2"
style="wheatButtonFancy"
type="button"
size="33%+30 100%-50 66%-40 100%-20"
>mbButton2Caption
<action on="Press"><![CDATA[
eval (getGUIGlobal().mbButton2Code);
guiHide ("mbMain");
]]></action>
</object>
<object name="mbButton3"
style="wheatButtonFancy"
type="button"
size="66%+30 100%-50 100%-40 100%-20"
>mbButton3Caption
<action on="Press"><![CDATA[
eval (getGUIGlobal().mbButton2Code);
guiHide ("mbMain");
]]></action>
</object>
</object>
<!--
==========================================
- FPS COUNTER
==========================================
-->
<object name="fpsCounter"
type="text"
ghost="true"
hidden="true"
hotkey="fps.toggle"
font="verdana16"
textcolor="100 100 0"
size="18 18 200 35"
z="199"
>
<action on="Load"><![CDATA[
setInterval (updateFPS, 1, 200);
]]></action>
<action on="Press"><![CDATA[
guiToggle (this.name);
]]></action>
</object>
<!--
==========================================
- WATERMARK - USED WHEN TAKING OFFICIAL SCREENSHOTS
==========================================
-->
<object name="glbWaterMark"
hidden="true"
hotkey="screenshot.watermark"
z="200"
>
<action on="Press"><![CDATA[
guiToggle ("glbWaterMark");
]]></action>
<object name="glbWaterMarkProductLogo"
type="image"
size="0 100%-88 190 100%"
sprite="watermarkProduct"
/>
<object name="glbWaterMarkCompanyLogo"
type="image"
size="100%-207 100%-28 100% 100%"
sprite="watermarkCompany"
/>
</object>
</object>
</objects>

View File

@ -1,16 +0,0 @@
/*
DESCRIPTION : Global initialisation functions, called when scripts first included at startup.
NOTES : Use for any initialisation that cannot be mapped to an object.
*/
// ====================================================================
function init ()
{
// Root point for anything that needs to be globally initialised at startup.
initCoord();
initSession();
}
// ====================================================================

View File

@ -1,132 +0,0 @@
/*
DESCRIPTION : Contains global GUI functions, which will later be accessible from every GUI script/file.
NOTES : So far, only the message box-related functions are implemented.
*/
/*
***************************************
File version: 0.1
Edited by: Malte, Nov 14 2004
***************************************
Further comments:
Changelog:
v0.1: - first version.
***************************************
*/
// *******************************************
// messageBox
// *******************************************
// @params: int mbWidth, int mbHeight, string mbMessage, string mbTitle, int mbMode, arr mbButtonCaptions
// @return: void
// @desc: Displays a new message box. So far, we can only display one message box at
// a time, since the message box is based on one base-object which is modified
// according to the parameters. Later, we should probably be able to create GUI
// Objects (like the message box) at runtime.
// *******************************************
/*
TODO: Make button code work for any number of buttons without extending the code each time! ((arrays | nested variables) & calculating sizes)
*/
// ====================================================================
function messageBox (mbWidth, mbHeight, mbMessage, mbTitle, mbMode, mbButtonCaptions, mbButtonsCode)
{
mbMainObj = getGUIObjectByName ("mbMain");
mbTitleObj = getGUIObjectByName ("mbTitleBar");
mbTextObj = getGUIObjectByName ("mbText");
mbButton1Obj = getGUIObjectByName ("mbButton1");
mbButton2Obj = getGUIObjectByName ("mbButton2");
mbButton3Obj = getGUIObjectByName ("mbButton3");
// Calculate size
mbLRDiff = mbWidth / 2; // Message box left/right difference from 50% of screen
mbUDDiff = mbHeight / 2; // Message box up/down difference from 50% of screen
mbSizeString = "50%-" + mbLRDiff + " 50%-" + mbUDDiff + " 50%+" + mbLRDiff + " 50%+" + mbUDDiff;
mbMainObj.size = mbSizeString;
// Texts
mbTitleObj.caption = mbTitle;
mbTextObj.caption = mbMessage;
// Message box modes
// There is a number of standard modes, and if none of these is used (mbMode == 0), the button captions will be
// taken from the array mbButtonCaptions; there currently is a maximum of three buttons.
switch (mbMode)
{
case 1:
// Simple Yes/No question box
mbButtonCaptions = new Array("Yes", "No");
break;
case 2:
// Okay-only box
mbButtonCaptions = new Array("OK");
break;
case 3:
// Retry/Abort/Ignore box (will we ever need this?!)
mbButtonCaptions = new Array("Retry", "Ignore", "Abort");
default:
break;
}
// Buttons
switch (mbButtonCaptions.length)
{
case 1:
// One Button only
mbButton1Obj.caption = mbButtonCaptions[0];
mbButton1Obj.size = "30% 100%-80 70% 100%-50";
mbButton1Obj.hidden = false;
mbButton2Obj.hidden = true;
mbButton3Obj.hidden = true;
break;
case 2:
// Two Buttons
mbButton1Obj.caption = mbButtonCaptions[0];
mbButton2Obj.caption = mbButtonCaptions[1];
mbButton1Obj.size = "10% 100%-80 45% 100%-50";
mbButton2Obj.size = "55% 100%-80 90% 100%-50";
mbButton1Obj.hidden = false;
mbButton2Obj.hidden = false;
mbButton3Obj.hidden = true;
break;
case 3:
// Three Buttons
mbButton1Obj.caption = mbButtonCaptions[0];
mbButton2Obj.caption = mbButtonCaptions[1];
mbButton3Obj.caption = mbButtonCaptions[2];
mbButton1Obj.size = "10% 100%-80 30% 100%-50";
mbButton2Obj.size = "40% 100%-80 60% 100%-50";
mbButton3Obj.size = "70% 100%-80 90% 100%-50";
mbButton1Obj.hidden = false;
mbButton2Obj.hidden = false;
mbButton3Obj.hidden = false;
break;
}
// Show the message box
guiUnHide (mbMainObj.name);
// Testing
getGUIGlobal().mbButton1Code = mbButtonsCode[0];
getGUIGlobal().mbButton2Code = mbButtonsCode[1];
getGUIGlobal().mbButton3Code = mbButtonsCode[2];
}
// ====================================================================
function updateFPS()
{
getGUIObjectByName("fpsCounter").caption = "FPS: " + getFPS();
}
// ====================================================================

View File

@ -1,190 +0,0 @@
/*
DESCRIPTION : Functions used load/end the game session and manipulate the loading screen.
NOTES :
*/
// ====================================================================
function launchGame ()
{
// Starts the map, closing the session setup window.
var mapName = getCurrItemValue("pgSessionSetupMapName");
var gameMode = getCurrItemValue("pgSessionSetupGameMode");
var screenshotMode = getGUIObjectByName("pgSessionSetupScreenshotMode").checked;
var losSetting = getGUIObjectByName("pgSessionSetupLosSetting").selected;
var fogOfWar = getGUIObjectByName("pgSessionSetupFoW").checked;
if(screenshotMode)
{
losSetting = 2;
fogOfWar = false;
}
// Check whether we have a correct file extension, to avoid crashes
var extension = mapName.substring (mapName.length, mapName.length-4);
if (extension != ".pmp")
{
// Add .pmp to the file name.
var mapName = mapName + ".pmp";
}
// Set up game
g_GameAttributes.mapFile = mapName;
g_GameAttributes.losSetting = losSetting;
g_GameAttributes.fogOfWar = fogOfWar;
g_GameAttributes.gameMode = gameMode
g_GameAttributes.screenshotMode = screenshotMode;
// Close setup window
closeMainMenuSubWindow ("pgSessionSetup");
// Display loading screen.
startLoadingScreen();
console.write( "running startGame()" );
// Begin game session.
if (! startGame())
{
// Failed to start the game; go back to the main menu.
guiSwitch ("ld", "pg");
// Restore default cursor.
setCursor ("arrow-default");
// Show an error message
btCaptions = new Array("OK");
btCode = new Array("");
messageBox(400, 200, "The game could not be started with the given parameters. You probably have entered an invalid map name.", "Error", 0, btCaptions, btCode);
}
console.write( "done running startGame()" );
// Set starting UI layout.
GUIType=rb;
// Set session UI sprites to match the skin for the player's civilisation.
// (We don't have skins for all civs yet, so we're using the standard menu skin. But it should be settable from here later.)
setSkin ("wheat");
// Set GUI coordinates to starting orientation.
flipGUI (GUIType);
}
// ====================================================================
function startLoadingScreen()
{
// Switch screens from main menu to loading screen.
guiSwitch ("pg", "ld");
// Set to "hourglass" cursor.
setCursor("cursor-wait");
console.write ("Loading " + g_GameAttributes.mapFile + " (" + g_GameAttributes.numPlayers + " players) ...");
// Choose random concept art for loading screen background (should depend on the selected civ later when this is specified).
var sprite = "";
var loadingBkgArray = buildDirEntList("art/textures/ui/loading/", "*.dds", false);
if (loadingBkgArray.length == 0)
console.write ("ERROR: Failed to find any matching textures for the loading screen background.");
else
{
// Get a random index from the list of loading screen backgrounds.
sprite = "stretched:" + loadingBkgArray[getRandom (0, loadingBkgArray.length-1)];
sprite = sprite.replace ("art/textures/ui/", "");
}
getGUIObjectByName ("ldConcept").sprite = sprite;
// janwas: main loop now sets progress / description, but that won't
// happen until the first timeslice completes, so set initial values.
getGUIObjectByName ("ldTitleBar").caption = "Loading Scenario ...";
getGUIObjectByName ("ldProgressBarText").caption = "";
getGUIObjectByName ("ldProgressBar").caption = 0;
getGUIObjectByName ("ldText").caption = "LOADING " + g_GameAttributes.mapFile + " ...\nPlease wait ...";
// Pick a random tip of the day (each line is a separate tip).
var tipArray = readFileLines("gui/text/tips.txt");
// Set tip string.
getGUIObjectByName ("ldTip").caption = tipArray[getRandom(0, tipArray.length-1)];
}
// ====================================================================
function reallyStartGame()
{
// This is a reserved function name that is executed by the engine when it is ready
// to start the game (ie loading progress has reached 100%).
// Create resource pools for each player, etc.
setupSession();
// Switch GUI from loading screen to game session.
guiSwitch ("ld", "sn");
// Restore default cursor.
setCursor ("arrow-default");
}
// ====================================================================
function setupSession ()
{
// Do essentials that can only be done when the session has been loaded ...
// For example, create the resource types, scores, etc, for each player.
/*
if (sessionType == "Skirmish")
{
// Set up a bunch of players so we can see them pretty colours. :P
console.write ("Setting Up Temporary Single Players");
// The first player is by default allocated to the local player in SP, so
// adding 7 players means that we'll have 8 players in total
for (var i=0; i<7; i++)
{
g_GameAttributes.slots[i+1].assignLocal();
console.write ("Slot "+(i+1)+" is assigned: " + g_GameAttributes.slots[i+1].assignment);
}
}
*/
// Select session peace track.
curr_session_playlist_1 = newRandomSound("music", "peace");
// Fade out main theme and fade in session theme.
crossFade(curr_music, curr_session_playlist_1, 1)
// Create the resouce counters
createResourceCounters();
// Start refreshing the session controls.
setInterval( snRefresh, 1, 100 );
}
// ====================================================================
function endSession (closeType)
{
// Occurs when the player chooses to close the current game.
switch (closeType)
{
case ("return"):
// If the player has chosen to quit game and return to main menu,
// End the session.
endGame();
// Fade out current music and return to playing menu theme.
//curr_music = newRandomSound("music", "menu");
//crossFade(curr_session_playlist_1, curr_music, 1);
// Stop refreshing the session controls.
cancelInterval();
// Swap GUIs to display main menu.
guiSwitch ("sn", "pg");
break;
case ("exit"):
// If the player has chosen to shutdown and immediately return to operating system,
exit();
break;
}
}
// ====================================================================

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
<!DOCTYPE objects SYSTEM "../gui.dtd">
<!--
==========================================
- TEST STUFF, MISCELLANEOUS, ARCHIVE -
==========================================
-->
<objects>
</objects>

View File

@ -41,6 +41,7 @@ CGUI
#include "CProgressBar.h"
#include "CTooltip.h"
#include "MiniMap.h"
#include "scripting/JSInterface_GUITypes.h"
#include "ps/XML/Xeromyces.h"
#include "ps/Font.h"
@ -67,23 +68,43 @@ const double SELECT_DBLCLICK_RATE = 0.5;
// Class for global JavaScript object
JSClass GUIClass = {
"GUIClass", 0,
"GUIClass", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
};
//-------------------------------------------------------------------
// called from main loop when (input) events are received.
// event is passed to other handlers if false is returned.
// trampoline: we don't want to make the implementation (in CGUI) static
//-------------------------------------------------------------------
InReaction gui_handler(const SDL_Event_* ev)
static JSBool GetGUIObjectByName(JSContext* cx, JSObject* obj, uintN UNUSED(argc), jsval* argv, jsval* rval)
{
PROFILE( "GUI event handler" );
return g_GUI.HandleEvent(ev);
CGUI* gui = (CGUI*)JS_GetInstancePrivate(cx, obj, &GUIClass, argv);
if (! gui)
return JS_FALSE;
try
{
CStr name = ToPrimitive<CStr>(cx, argv[0]);
IGUIObject* guiObj = gui->FindObjectByName(name);
if (guiObj)
*rval = OBJECT_TO_JSVAL(guiObj->GetJSObject());
else
*rval = JSVAL_NULL;
return JS_TRUE;
}
catch (PSERROR_Scripting&)
{
return JS_FALSE;
}
}
JSFunctionSpec GUIClassFunctions[] = {
{ "getGUIObjectByName", GetGUIObjectByName, 1, 0, 0 },
{ NULL }
};
void CGUI::ScriptingInit()
{
JSI_IGUIObject::init();
JSI_GUITypes::init();
g_ScriptingHost.DefineCustomObjectType(&GUIClass, NULL, 0, NULL, GUIClassFunctions, NULL, NULL);
}
InReaction CGUI::HandleEvent(const SDL_Event_* ev)
{
@ -131,8 +152,6 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev)
}
}
// JW: (pre|post)process omitted; what're they for? why would we need any special button_released handling?
// Only one object can be hovered
IGUIObject *pNearest = NULL;
@ -366,19 +385,23 @@ CGUI::CGUI() : m_MouseButtons(0), m_FocusedObject(NULL), m_InternalNameNumber(0)
m_ScriptObject = JS_NewObject(g_ScriptingHost.getContext(), &GUIClass, NULL, NULL);
debug_assert(m_ScriptObject != NULL); // How should it handle errors?
JS_AddRoot(g_ScriptingHost.getContext(), &m_ScriptObject);
// This will make this invisible, not add
//m_BaseObject->SetName(BASE_OBJECT_NAME);
JS_SetPrivate(g_ScriptingHost.getContext(), m_ScriptObject, this);
}
CGUI::~CGUI()
{
Destroy();
if (m_BaseObject)
delete m_BaseObject;
if (m_ScriptObject)
{
// Make sure it doesn't have dangling references to this CGUI
JS_SetPrivate(g_ScriptingHost.getContext(), m_ScriptObject, NULL);
// Let it be garbage-collected
JS_RemoveRoot(g_ScriptingHost.getContext(), &m_ScriptObject);
}
}
//-------------------------------------------------------------------
@ -407,86 +430,12 @@ void CGUI::Initialize()
AddObjectType("checkbox", &CCheckBox::ConstructObject);
AddObjectType("radiobutton", &CRadioButton::ConstructObject);
AddObjectType("progressbar", &CProgressBar::ConstructObject);
AddObjectType("minimap", &CMiniMap::ConstructObject);
AddObjectType("minimap", &CMiniMap::ConstructObject);
AddObjectType("input", &CInput::ConstructObject);
// The following line was commented out, I don't know if that's me or not, or
// for what reason, but I'm gonna uncomment, if anything breaks, just let me
// know, or if it wasn't I that commented it out, do let me know why.
// -- Gee 20-07-2005
AddObjectType("list", &CList::ConstructObject);
//
AddObjectType("dropdown", &CDropDown::ConstructObject);
}
void CGUI::Process()
{
/*
// TODO Gee: check if m_pInput is valid, otherwise return
/// debug_assert(m_pInput);
// Pre-process all objects
try
{
GUI<EGUIMessage>::RecurseObject(0, m_BaseObject, &IGUIObject::HandleMessage, GUIM_PREPROCESS);
}
catch (PSERROR_GUI& e)
{
return;
}
// Check mouse over
try
{
// Only one object can be hovered
// check which one it is, if any !
IGUIObject *pNearest = NULL;
GUI<IGUIObject*>::RecurseObject(GUIRR_HIDDEN, m_BaseObject, &IGUIObject::ChooseMouseOverAndClosest, pNearest);
// Now we'll call UpdateMouseOver on *all* objects,
// we'll input the one hovered, and they will each
// update their own data and send messages accordingly
GUI<IGUIObject*>::RecurseObject(GUIRR_HIDDEN, m_BaseObject, &IGUIObject::UpdateMouseOver, pNearest);
// If pressed
if (m_pInput->mPress(NEMM_BUTTON1) && pNearest)
{
pNearest->HandleMessage(GUIM_MOUSE_PRESS_LEFT);
}
else
// If released
if (m_pInput->mRelease(NEMM_BUTTON1) && pNearest)
{
pNearest->HandleMessage(GUIM_MOUSE_RELEASE_LEFT);
}
// Generally if just mouse is clicked
if (m_pInput->mDown(NEMM_BUTTON1) && pNearest)
{
pNearest->HandleMessage(GUIM_MOUSE_DOWN_LEFT);
}
}
catch (PSERROR_GUI& e)
{
return;
}
// Post-process all objects
try
{
GUI<EGUIMessage>::RecurseObject(0, m_BaseObject, &IGUIObject::HandleMessage, GUIM_POSTPROCESS);
}
catch (PSERROR_GUI& e)
{
return;
}
*/
}
void CGUI::Draw()
{
// Clear the depth buffer, so the GUI is
@ -504,12 +453,7 @@ void CGUI::Draw()
}
catch (PSERROR_GUI& e)
{
UNUSED2(e);
glPopMatrix();
// TODO Gee: Report error.
debug_warn(L"CGUI::Draw error");
return;
LOGERROR(L"GUI draw error: %hs", e.what());
}
glPopMatrix();
}
@ -1034,35 +978,12 @@ bool CGUI::GetPreDefinedColor(const CStr& name, CColor &Output)
}
}
void CGUI::ReportParseError(const wchar_t* str, ...)
{
va_list argp;
wchar_t buffer[512]={0};
va_start(argp, str);
sys_vswprintf(buffer, ARRAY_SIZE(buffer), str, argp);
va_end(argp);
// Print header
if (m_Errors==0)
{
LOG(CLogger::Error, LOG_CATEGORY, L"*** GUI Tree Creation Errors:");
}
// Important, set ParseError to true
++m_Errors;
LOG(CLogger::Error, LOG_CATEGORY, L"%ls", buffer);
}
/**
* @callgraph
*/
void CGUI::LoadXmlFile(const VfsPath& Filename)
void CGUI::LoadXmlFile(const VfsPath& Filename, std::set<VfsPath>& Paths)
{
// Reset parse error
// we can later check if this has increased
m_Errors = 0;
Paths.insert(Filename);
CXeromyces XeroFile;
if (XeroFile.Load(Filename) != PSRETURN_OK)
@ -1080,7 +1001,7 @@ void CGUI::LoadXmlFile(const VfsPath& Filename)
if (root_name == "objects")
{
Xeromyces_ReadRootObjects(node, &XeroFile);
Xeromyces_ReadRootObjects(node, &XeroFile, Paths);
// Re-cache all values so these gets cached too.
//UpdateResolution();
@ -1111,20 +1032,13 @@ void CGUI::LoadXmlFile(const VfsPath& Filename)
LOG(CLogger::Error, LOG_CATEGORY, L"Errors loading GUI file %ls (%d)", Filename.string().c_str(), e.getCode());
return;
}
// Now report if any other errors occured
if (m_Errors > 0)
{
/// g_console.submit("echo GUI Tree Creation Reports %d errors", m_Errors);
}
}
//===================================================================
// XML Reading Xeromyces Specific Sub-Routines
//===================================================================
void CGUI::Xeromyces_ReadRootObjects(XMBElement Element, CXeromyces* pFile)
void CGUI::Xeromyces_ReadRootObjects(XMBElement Element, CXeromyces* pFile, std::set<VfsPath>& Paths)
{
int el_script = pFile->GetElementID("script");
@ -1138,10 +1052,10 @@ void CGUI::Xeromyces_ReadRootObjects(XMBElement Element, CXeromyces* pFile)
if (child.GetNodeName() == el_script)
// Execute the inline script
Xeromyces_ReadScript(child, pFile);
Xeromyces_ReadScript(child, pFile, Paths);
else
// Read in this whole object into the GUI
Xeromyces_ReadObject(child, pFile, m_BaseObject);
Xeromyces_ReadObject(child, pFile, m_BaseObject, Paths);
}
}
@ -1212,7 +1126,7 @@ void CGUI::Xeromyces_ReadRootSetup(XMBElement Element, CXeromyces* pFile)
}
}
void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObject *pParent)
void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObject *pParent, std::set<VfsPath>& Paths)
{
debug_assert(pParent);
int i;
@ -1235,7 +1149,7 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
if (!object)
{
// Report error that object was unsuccessfully loaded
ReportParseError(L"Unrecognized type \"%hs\"", type.c_str());
LOGERROR(L"GUI: Unrecognized object type \"%hs\"", type.c_str());
return;
}
@ -1269,7 +1183,7 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
// additional check
if (m_Styles.count(argStyle) == 0)
{
ReportParseError(L"Trying to use style '%hs' that doesn't exist.", argStyle.c_str());
LOGERROR(L"GUI: Trying to use style '%hs' that doesn't exist.", argStyle.c_str());
}
else object->LoadStyle(*this, argStyle);
}
@ -1315,7 +1229,7 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
// Try setting the value
if (object->SetSetting(pFile->GetAttributeString(attr.Name), CStr(attr.Value), true) != PSRETURN_OK)
{
ReportParseError(L"(object: %hs) Can't set \"%hs\" to \"%ls\"", object->GetPresentableName().c_str(), pFile->GetAttributeString(attr.Name).c_str(), CStrW(attr.Value).c_str());
LOGERROR(L"GUI: (object: %hs) Can't set \"%hs\" to \"%ls\"", object->GetPresentableName().c_str(), pFile->GetAttributeString(attr.Name).c_str(), CStrW(attr.Value).c_str());
// This is not a fatal error
}
@ -1360,7 +1274,7 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
if (element_name == elmt_object)
{
// Call this function on the child
Xeromyces_ReadObject(child, pFile, object);
Xeromyces_ReadObject(child, pFile, object, Paths);
}
else if (element_name == elmt_action)
{
@ -1374,10 +1288,11 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
// If there is a file, open it and use it as the code
if (! filename.empty())
{
Paths.insert(filename);
CVFSFile scriptfile;
if (scriptfile.Load(filename) != PSRETURN_OK)
{
LOG(CLogger::Error, LOG_CATEGORY, L"Error opening action file '%ls'", filename.c_str());
LOGERROR(L"Error opening GUI script action file '%ls'", filename.c_str());
throw PSERROR_GUI_JSOpenFailed();
}
@ -1395,7 +1310,7 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
// Try making the object read the tag.
if (!object->HandleAdditionalChildren(child, pFile))
{
LOG(CLogger::Error, LOG_CATEGORY, L"(object: %hs) Reading unknown children for its type", object->GetPresentableName().c_str());
LOGERROR(L"GUI: (object: %hs) Reading unknown children for its type", object->GetPresentableName().c_str());
}
}
}
@ -1406,27 +1321,19 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
if (!ManuallySetZ)
{
// Set it automatically to 10 plus its parents
if (pParent==NULL)
bool absolute;
GUI<bool>::GetSetting(object, "absolute", absolute);
// If the object is absolute, we'll have to get the parent's Z buffered,
// and add to that!
if (absolute)
{
debug_warn(L"CGUI::Xeromyces_ReadObject error");
// TODO Gee: Report error
GUI<float>::SetSetting(object, "z", pParent->GetBufferedZ() + 10.f, true);
}
else
// If the object is relative, then we'll just store Z as "10"
{
bool absolute;
GUI<bool>::GetSetting(object, "absolute", absolute);
// If the object is absolute, we'll have to get the parent's Z buffered,
// and add to that!
if (absolute)
{
GUI<float>::SetSetting(object, "z", pParent->GetBufferedZ() + 10.f, true);
}
else
// If the object is relative, then we'll just store Z as "10"
{
GUI<float>::SetSetting(object, "z", 10.f, true);
}
GUI<float>::SetSetting(object, "z", 10.f, true);
}
}
@ -1444,20 +1351,21 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
}
catch (PSERROR_GUI& e)
{
CStrW what(e.what());
ReportParseError(L"%ls", what.c_str());
LOGERROR(L"GUI error: %hs", e.what());
}
}
void CGUI::Xeromyces_ReadScript(XMBElement Element, CXeromyces* pFile)
void CGUI::Xeromyces_ReadScript(XMBElement Element, CXeromyces* pFile, std::set<VfsPath>& Paths)
{
// Check for a 'file' parameter
CStr file (Element.GetAttributes().GetNamedItem( pFile->GetAttributeID("file") ));
CStrW file (Element.GetAttributes().GetNamedItem( pFile->GetAttributeID("file") ));
// If there is a file specified, open and execute it
if (! file.empty())
g_ScriptingHost.RunScript(CStrW(file), m_ScriptObject);
{
Paths.insert(file);
g_ScriptingHost.RunScript(file, m_ScriptObject);
}
// Execute inline scripts
CStr code (Element.GetText());
@ -1481,7 +1389,7 @@ void CGUI::Xeromyces_ReadSprite(XMBElement Element, CXeromyces* pFile)
name = Element.GetAttributes().GetNamedItem( pFile->GetAttributeID("name") );
if (m_Sprites.find(name) != m_Sprites.end())
LOG(CLogger::Warning, LOG_CATEGORY, L"Sprite name '%hs' used more than once; first definition will be discarded", name.c_str());
LOGWARNING(L"GUI sprite name '%hs' used more than once; first definition will be discarded", name.c_str());
//
// Read Children (the images)
@ -1505,9 +1413,15 @@ void CGUI::Xeromyces_ReadSprite(XMBElement Element, CXeromyces* pFile)
}
else if (ElementName == "effect")
{
debug_assert(! effects); // DTD should only allow one effect per sprite
effects = new SGUIImageEffects;
Xeromyces_ReadEffects(child, pFile, *effects);
if (effects)
{
LOGERROR(L"GUI <sprite> must not have more than one <effect>");
}
else
{
effects = new SGUIImageEffects;
Xeromyces_ReadEffects(child, pFile, *effects);
}
}
else
{
@ -1537,9 +1451,9 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
// Image object we're adding
SGUIImage image;
// Set defaults (or maybe do that in DTD?)
image.m_TextureSize = CClientArea("0 0 100% 100%");
image.m_Size = CClientArea("0 0 100% 100%");
// Set defaults to "0 0 100% 100%"
image.m_TextureSize = CClientArea(CRect(0, 0, 0, 0), CRect(0, 0, 100, 100));
image.m_Size = CClientArea(CRect(0, 0, 0, 0), CRect(0, 0, 100, 100));
// TODO Gee: Setup defaults here (or maybe they are in the SGUIImage ctor)
@ -1564,7 +1478,7 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
{
CClientArea ca;
if (!GUI<CClientArea>::ParseString(attr_value, ca))
ReportParseError(L"Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
else image.m_Size = ca;
}
else
@ -1572,7 +1486,7 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
{
CClientArea ca;
if (!GUI<CClientArea>::ParseString(attr_value, ca))
ReportParseError(L"Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
else image.m_TextureSize = ca;
}
else
@ -1580,7 +1494,7 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
{
CRect rect;
if (!GUI<CRect>::ParseString(attr_value, rect))
ReportParseError(L"Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
else image.m_TexturePlacementInFile = rect;
}
else
@ -1588,7 +1502,7 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
{
CSize size;
if (!GUI<CSize>::ParseString(attr_value, size))
ReportParseError(L"Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
else image.m_CellSize = size;
}
else
@ -1596,7 +1510,7 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
{
float z_level;
if (!GUI<float>::ParseString(attr_value, z_level))
ReportParseError(L"Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
else image.m_DeltaZ = z_level/100.f;
}
else
@ -1604,7 +1518,7 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
{
CColor color;
if (!GUI<CColor>::ParseString(attr_value, color))
ReportParseError(L"Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
else image.m_BackColor = color;
}
else
@ -1612,7 +1526,7 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
{
CColor color;
if (!GUI<CColor>::ParseString(attr_value, color))
ReportParseError(L"Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
else image.m_BorderColor = color;
}
else
@ -1620,7 +1534,7 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
{
bool b;
if (!GUI<bool>::ParseString(attr_value, b))
ReportParseError(L"Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
else image.m_Border = b;
}
else
@ -1637,9 +1551,15 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
CStr ElementName (pFile->GetElementString(child.GetNodeName()));
if (ElementName == "effect")
{
debug_assert(! image.m_Effects); // DTD should only allow one effect per sprite
image.m_Effects = new SGUIImageEffects;
Xeromyces_ReadEffects(child, pFile, *image.m_Effects);
if (image.m_Effects)
{
LOGERROR(L"GUI <image> must not have more than one <effect>");
}
else
{
image.m_Effects = new SGUIImageEffects;
Xeromyces_ReadEffects(child, pFile, *image.m_Effects);
}
}
else
{
@ -1668,7 +1588,7 @@ void CGUI::Xeromyces_ReadEffects(XMBElement Element, CXeromyces* pFile, SGUIImag
{ \
CColor color; \
if (!GUI<int>::ParseColor(attr_value, color, alpha)) \
ReportParseError(L"Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str()); \
LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str()); \
else effects.m_##mem = color; \
} \
else
@ -1752,20 +1672,18 @@ void CGUI::Xeromyces_ReadScrollBarStyle(XMBElement Element, CXeromyces* pFile)
{
float f;
if (!GUI<float>::ParseString(attr_value, f))
{
ReportParseError(L"Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
}
scrollbar.m_Width = f;
LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
else
scrollbar.m_Width = f;
}
else
if (attr_name == "minimum_bar_size")
{
float f;
if (!GUI<float>::ParseString(attr_value, f))
{
ReportParseError(L"Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
}
scrollbar.m_MinimumBarSize = f;
LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
else
scrollbar.m_MinimumBarSize = f;
}
else
if (attr_name == "sprite_button_top")
@ -1838,16 +1756,18 @@ void CGUI::Xeromyces_ReadIcon(XMBElement Element, CXeromyces* pFile)
{
CSize size;
if (!GUI<CSize>::ParseString(attr_value, size))
ReportParseError(L"Error parsing '%hs' (\"%hs\") inside <icon>.", attr_name.c_str(), attr_value.c_str());
icon.m_Size = size;
LOGERROR(L"Error parsing '%hs' (\"%hs\") inside <icon>.", attr_name.c_str(), attr_value.c_str());
else
icon.m_Size = size;
}
else
if (attr_name == "cell_id")
{
int cell_id;
if (!GUI<int>::ParseString(attr_value, cell_id))
ReportParseError(L"Error parsing '%hs' (\"%hs\") inside <icon>.", attr_name.c_str(), attr_value.c_str());
icon.m_CellID = cell_id;
LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\") inside <icon>.", attr_name.c_str(), attr_value.c_str());
else
icon.m_CellID = cell_id;
}
else
{
@ -1902,7 +1822,7 @@ void CGUI::Xeromyces_ReadColor(XMBElement Element, CXeromyces* pFile)
// Try setting color to value
if (!color.ParseString(value, 255.f))
{
ReportParseError(L"Unable to create custom color '%hs'. Invalid color syntax.", name.c_str());
LOGERROR(L"GUI: Unable to create custom color '%hs'. Invalid color syntax.", name.c_str());
}
else
{

View File

@ -43,13 +43,10 @@ CGUI
#include "ps/Overlay.h" // CPos and CRect
#include "ps/Singleton.h"
#include "lib/input.h"
#include "ps/XML/Xeromyces.h"
extern InReaction gui_handler(const SDL_Event_* ev);
//--------------------------------------------------------
// Macros
//--------------------------------------------------------
@ -96,7 +93,7 @@ class GUITooltip;
*
* No interfacial functions throws.
*/
class CGUI : public Singleton<CGUI>
class CGUI
{
friend class IGUIObject;
friend class IGUIScrollBarOwner;
@ -110,16 +107,16 @@ public:
CGUI();
~CGUI();
/**
* Initializes GUI script classes
*/
static void ScriptingInit();
/**
* Initializes the GUI, needs to be called before the GUI is used
*/
void Initialize();
/**
* @deprecated Will be removed
*/
void Process();
/**
* Performs processing that should happen every frame (including the "Tick" event)
*/
@ -180,8 +177,9 @@ public:
* everything else!
*
* @param Filename Name of file
* @param Paths Set of paths; all XML and JS files loaded will be added to this
*/
void LoadXmlFile(const VfsPath& Filename);
void LoadXmlFile(const VfsPath& Filename, std::set<VfsPath>& Paths);
/**
* Checks if object exists and return true or false accordingly
@ -297,14 +295,6 @@ private:
*/
void AddObject(IGUIObject* pObject);
/**
* Report XML Reading Error, should be called from within the
* Xerces_* functions.
*
* @param str Error message
*/
void ReportParseError(const wchar_t* str, ...) WPRINTF_ARGS(2);
/**
* You input the name of the object type, and let's
* say you input "button", then it will construct a
@ -381,7 +371,7 @@ private:
*
* @see LoadXmlFile()
*/
void Xeromyces_ReadRootObjects(XMBElement Element, CXeromyces* pFile);
void Xeromyces_ReadRootObjects(XMBElement Element, CXeromyces* pFile, std::set<VfsPath>& Paths);
/**
* Reads in the root element \<sprites\> (the DOMElement).
@ -438,7 +428,7 @@ private:
*
* @see LoadXmlFile()
*/
void Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObject *pParent);
void Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObject *pParent, std::set<VfsPath>& Paths);
/**
* Reads in the element <script> (the XMBElement) and executes
@ -450,7 +440,7 @@ private:
*
* @see LoadXmlFile()
*/
void Xeromyces_ReadScript(XMBElement Element, CXeromyces* pFile);
void Xeromyces_ReadScript(XMBElement Element, CXeromyces* pFile, std::set<VfsPath>& Paths);
/**
* Reads in the element <sprite> (the XMBElement) and stores the
@ -571,10 +561,6 @@ private:
*/
unsigned int m_MouseButtons;
/// Used when reading in XML files
// TODO Gee: Used?
int16_t m_Errors;
// Tooltip
GUITooltip m_Tooltip;
@ -646,7 +632,4 @@ private:
std::map<CStr, SGUIIcon> m_Icons;
};
#include "GUI.h"
#endif

View File

@ -21,6 +21,7 @@ IGUIScrollBar
#include "precompiled.h"
#include "GUI.h"
#include "CGUIScrollBarVertical.h"
#include "ps/CLogger.h"
#define LOG_CATEGORY L"gui"

View File

@ -40,6 +40,7 @@ A GUI ScrollBar
//--------------------------------------------------------
// Includes / Compiler directives
//--------------------------------------------------------
#include "IGUIScrollBar.h"
#include "GUI.h"
//--------------------------------------------------------

View File

@ -22,6 +22,7 @@ CInput
#include "precompiled.h"
#include "GUI.h"
#include "CInput.h"
#include "CGUIScrollBarVertical.h"
#include "ps/Font.h"
#include "lib/ogl.h"

View File

@ -22,6 +22,7 @@ CList
#include "precompiled.h"
#include "GUI.h"
#include "CList.h"
#include "CGUIScrollBarVertical.h"
#include "ps/CLogger.h"
#include "lib/external_libraries/sdl.h"

View File

@ -36,10 +36,8 @@ GUI Object - List [box]
//--------------------------------------------------------
// Includes / Compiler directives
//--------------------------------------------------------
//#include "GUI.h"
// TODO Gee: Remove
//class IGUIScrollBar;
#include "IGUIScrollBar.h"
//--------------------------------------------------------
// Macros

View File

@ -22,6 +22,7 @@ CText
#include "precompiled.h"
#include "GUI.h"
#include "CText.h"
#include "CGUIScrollBarVertical.h"
#include "lib/ogl.h"

View File

@ -40,9 +40,7 @@ GUI Inclusion file
#include <vector>
#include <stddef.h>
#include "ps/Pyrogenesis.h"
#include "ps/CStr.h"
#include "lib/ogl.h"
#include "GUIbase.h"
#include "GUIutil.h"
@ -53,7 +51,5 @@ GUI Inclusion file
#include "IGUIScrollBarOwner.h"
#include "IGUITextOwner.h"
#include "IGUIScrollBar.h"
#include "CGUIScrollBarVertical.h"
#include "CGUI.h"
#endif

206
source/gui/GUIManager.cpp Normal file
View File

@ -0,0 +1,206 @@
#include "precompiled.h"
#include "GUIManager.h"
#include "CGUI.h"
#include "lib/timer.h"
#include "ps/CLogger.h"
#include "ps/Profile.h"
#include "ps/XML/Xeromyces.h"
CGUIManager* g_GUI = NULL;
// General TODOs:
//
// A lot of the CGUI data could (and should) be shared between
// multiple pages, instead of treating them as completely independent, to save
// memory and loading time.
//
// Hotkeys are not unregistered when a page is unloaded.
// called from main loop when (input) events are received.
// event is passed to other handlers if false is returned.
// trampoline: we don't want to make the HandleEvent implementation static
InReaction gui_handler(const SDL_Event_* ev)
{
PROFILE("GUI event handler");
return g_GUI->HandleEvent(ev);
}
CGUIManager::SGUIPage::SGUIPage()
{
JS_AddNamedRoot(g_ScriptingHost.GetContext(), &initData, "SGUIPage initData");
}
CGUIManager::SGUIPage::SGUIPage(const SGUIPage& page)
{
*this = page;
JS_AddNamedRoot(g_ScriptingHost.GetContext(), &initData, "SGUIPage initData copy");
}
CGUIManager::SGUIPage::~SGUIPage()
{
JS_RemoveRoot(g_ScriptingHost.GetContext(), &initData);
}
CGUIManager::CGUIManager()
{
}
CGUIManager::~CGUIManager()
{
}
void CGUIManager::SwitchPage(const CStrW& pageName, jsval initData)
{
m_PageStack.clear();
PushPage(pageName, initData);
}
void CGUIManager::PushPage(const CStrW& pageName, jsval initData)
{
m_PageStack.push_back(SGUIPage());
m_PageStack.back().name = pageName;
m_PageStack.back().initData = initData;
LoadPage(m_PageStack.back());
}
void CGUIManager::PopPage()
{
if (m_PageStack.size() < 2)
{
debug_warn(L"Tried to pop GUI page when there's < 2 in the stack");
return;
}
m_PageStack.pop_back();
}
void CGUIManager::LoadPage(SGUIPage& page)
{
page.inputs.clear();
page.gui.reset(new CGUI());
page.gui->Initialize();
VfsPath path = VfsPath(L"gui")/page.name.c_str();
page.inputs.insert(path);
CXeromyces xero;
if (xero.Load(path) != PSRETURN_OK)
// Fail silently (Xeromyces reported the error)
return;
int elmt_page = xero.GetElementID("page");
int elmt_include = xero.GetElementID("include");
XMBElement root = xero.GetRoot();
if (root.GetNodeName() != elmt_page)
{
LOGERROR(L"GUI page '%ls' must have root element <page>", page.name.c_str());
return;
}
XERO_ITER_EL(root, node)
{
if (node.GetNodeName() != elmt_include)
{
LOGERROR(L"GUI page '%ls' must only have <include> elements inside <page>", page.name.c_str());
continue;
}
CStrW name (node.GetText());
TIMER(name.c_str());
VfsPath path (VfsPath(L"gui")/name.c_str());
page.gui->LoadXmlFile(path, page.inputs);
}
page.gui->SendEventToAll("load");
// Call the init() function
jsval rval;
if (! JS_CallFunctionName(g_ScriptingHost.GetContext(), page.gui->GetScriptObject(), "init", 1, &page.initData, &rval))
{
LOGERROR(L"GUI page '%ls': Failed to call init() function", page.name.c_str());
}
}
LibError CGUIManager::ReloadChangedFiles(const VfsPath& path)
{
for (PageStackType::iterator it = m_PageStack.begin(); it != m_PageStack.end(); ++it)
{
if (it->inputs.count(path))
{
LOGMESSAGE(L"GUI file '%ls' changed - reloading page '%ls'", path.string().c_str(), it->name.c_str());
LoadPage(*it);
}
}
return INFO::OK;
}
bool CGUIManager::GetPreDefinedColor(const CStr& name, CColor& output)
{
return top()->GetPreDefinedColor(name, output);
}
bool CGUIManager::IconExists(const CStr& str) const
{
return top()->IconExists(str);
}
SGUIIcon CGUIManager::GetIcon(const CStr& str) const
{
return top()->GetIcon(str);
}
IGUIObject* CGUIManager::FindObjectByName(const CStr& name) const
{
return top()->FindObjectByName(name);
}
void CGUIManager::SendEventToAll(const CStr& eventName)
{
top()->SendEventToAll(eventName);
}
void CGUIManager::TickObjects()
{
for (PageStackType::iterator it = m_PageStack.begin(); it != m_PageStack.end(); ++it)
it->gui->TickObjects();
}
void CGUIManager::Draw()
{
for (PageStackType::iterator it = m_PageStack.begin(); it != m_PageStack.end(); ++it)
it->gui->Draw();
}
void CGUIManager::UpdateResolution()
{
for (PageStackType::iterator it = m_PageStack.begin(); it != m_PageStack.end(); ++it)
it->gui->UpdateResolution();
}
JSObject* CGUIManager::GetScriptObject()
{
return top()->GetScriptObject();
}
InReaction CGUIManager::HandleEvent(const SDL_Event_* ev)
{
return top()->HandleEvent(ev);
}
// This returns a shared_ptr to make sure the CGUI doesn't get deallocated
// while we're in the middle of calling a function on it (e.g. if a GUI script
// calls SwitchPage)
shared_ptr<CGUI> CGUIManager::top() const
{
debug_assert(m_PageStack.size());
return m_PageStack.back().gui;
}

87
source/gui/GUIManager.h Normal file
View File

@ -0,0 +1,87 @@
#ifndef INCLUDED_GUIMANAGER
#define INCLUDED_GUIMANAGER
#include "lib/input.h"
#include "lib/file/vfs/vfs_path.h"
#include "ps/CStr.h"
#include "scripting/SpiderMonkey.h"
class CGUI;
class JSObject;
class IGUIObject;
struct CColor;
struct SGUIIcon;
/**
* External interface to the GUI system.
*
* The GUI consists of a set of pages. Each page is constructed from a
* series of XML files, and is independent from any other page.
* Only one page is active at a time. All events and render requests etc
* will go to the active page. This lets the GUI switch between pre-game menu
* and in-game UI.
*/
class CGUIManager
{
public:
CGUIManager();
~CGUIManager();
// Load a new GUI page and make it active, All current pages will be destroyed.
void SwitchPage(const CStrW& name, jsval initData);
// Load a new GUI page and make it active. All current pages will be retained,
// and will still be drawn and receive tick events, but will not receive
// user inputs.
void PushPage(const CStrW& name, jsval 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();
// Hotload pages when their .xml files have changed
LibError ReloadChangedFiles(const VfsPath& path);
// These functions are all equivalent to the CGUI functions of the same
// name, applied to the currently active GUI page:
bool GetPreDefinedColor(const CStr& name, CColor& output);
bool IconExists(const CStr& str) const;
SGUIIcon GetIcon(const CStr& str) const;
IGUIObject* FindObjectByName(const CStr& name) const;
void SendEventToAll(const CStr& eventName);
void TickObjects();
void Draw();
void UpdateResolution();
JSObject* GetScriptObject();
InReaction HandleEvent(const SDL_Event_* ev);
private:
struct SGUIPage
{
SGUIPage();
SGUIPage(const SGUIPage&);
~SGUIPage();
CStrW name;
std::set<VfsPath> inputs; // for hotloading
jsval initData;
shared_ptr<CGUI> gui;
};
void LoadPage(SGUIPage& page);
shared_ptr<CGUI> top() const;
typedef std::vector<SGUIPage> PageStackType;
PageStackType m_PageStack;
};
extern CGUIManager* g_GUI;
extern InReaction gui_handler(const SDL_Event_* ev);
#endif // INCLUDED_GUIMANAGER

View File

@ -371,7 +371,7 @@ void GUIRenderer::UpdateDrawCallCache(DrawCalls &Calls, const CStr& SpriteName,
{
SGUIImage Image;
Image.m_TextureName = VfsPath(L"art/textures/ui")/wstring_from_utf8(SpriteName.substr(10));
CClientArea ca("0 0 100% 100%");
CClientArea ca(CRect(0, 0, 0, 0), CRect(0, 0, 100, 100));
Image.m_Size = ca;
Image.m_TextureSize = ca;

View File

@ -21,6 +21,7 @@
#include "lib/timer.h"
#include "IGUIObject.h"
#include "CGUI.h"
#include "GUIutil.h"
#include "ps/CLogger.h"

View File

@ -25,8 +25,6 @@ GUI base
#include "GUI.h"
using std::string;
//--------------------------------------------------------
// Help Classes/Structs for the GUI implementation
//--------------------------------------------------------
@ -40,6 +38,11 @@ CClientArea::CClientArea(const CStr& Value)
SetClientArea(Value);
}
CClientArea::CClientArea(const CRect& pixel, const CRect& percent)
: pixel(pixel), percent(percent)
{
}
CRect CClientArea::GetClientArea(const CRect &parent) const
{
// If it's a 0 0 100% 100% we need no calculations
@ -59,9 +62,6 @@ CRect CClientArea::GetClientArea(const CRect &parent) const
bool CClientArea::SetClientArea(const CStr& Value)
{
// Get value in STL string format
string _Value = Value;
// This might lack incredible speed, but since all XML files
// are read at startup, reading 100 client areas will be
// negligible in the loading time.
@ -91,8 +91,8 @@ bool CClientArea::SetClientArea(const CStr& Value)
"_";
CParser& parser (CParserCache::Get(four_values));
CParserLine line;
line.ParseString(parser, _Value);
CParserLine line;
line.ParseString(parser, Value);
if (!line.m_ParseOK)
return false;
@ -103,7 +103,7 @@ bool CClientArea::SetClientArea(const CStr& Value)
// Divide into the four piles (delimiter is an argument named "delim")
for (int i=0, valuenr=0; i<(int)line.GetArgCount(); ++i)
{
string str;
std::string str;
line.GetArgString(i, str);
if (str == "delim")
{
@ -142,7 +142,7 @@ bool CClientArea::SetClientArea(const CStr& Value)
{
if (arg_count[v] == 1)
{
string str;
std::string str;
line.GetArgString(arg_start[v], str);
if (!line.GetArgFloat(arg_start[v], values[v][1]))

View File

@ -47,8 +47,6 @@ GUI Core, stuff that the whole GUI uses
#include "ps/Errors.h"
#include "ps/Pyrogenesis.h" // deprecated DECLARE_ERROR
//--------------------------------------------------------
// Forward declarations
//--------------------------------------------------------
@ -58,9 +56,6 @@ class IGUIObject;
// Macros
//--------------------------------------------------------
// Global CGUI
#define g_GUI CGUI::GetSingleton()
// Object settings setups
// Setup an object's ConstructObject function
@ -80,8 +75,6 @@ public: \
*/
enum EGUIMessageType
{
GUIM_PREPROCESS, // TODO questionable
GUIM_POSTPROCESS, // TODO questionable
GUIM_MOUSE_OVER,
GUIM_MOUSE_ENTER,
GUIM_MOUSE_LEAVE,
@ -110,10 +103,8 @@ enum EGUIMessageType
*/
struct SGUIMessage
{
SGUIMessage() {}
SGUIMessage(EGUIMessageType _type) : type(_type) {}
SGUIMessage(EGUIMessageType _type, const CStr& _value) : type(_type), value(_value) {}
~SGUIMessage() {}
/**
* Describes what the message regards
@ -140,19 +131,6 @@ enum
GUIRR_GHOST = 0x00000100
};
/**
* @enum EGUISettingsStruct
*
* Stored in SGUISetting, tells us in which struct
* the setting is located, that way we can query
* for the structs address.
*/
enum EGUISettingsStruct
{
GUISS_BASE,
GUISS_EXTENDED
};
// Text alignments
enum EAlign { EAlign_Left, EAlign_Right, EAlign_Center };
enum EVAlign { EVAlign_Top, EVAlign_Bottom, EVAlign_Center };
@ -188,6 +166,7 @@ class CClientArea
public:
CClientArea();
CClientArea(const CStr& Value);
CClientArea(const CRect& pixel, const CRect& percent);
/// Pixel modifiers
CRect pixel;

View File

@ -22,6 +22,7 @@ GUI text
#include "precompiled.h"
#include "GUI.h"
#include "GUIManager.h"
#include "ps/CLogger.h"
#include "ps/Parser.h"
#include <algorithm>
@ -104,7 +105,7 @@ void CGUIString::GenerateTextCall(SFeedback &Feedback,
if (itTextChunk->m_Tags[0].m_TagType == CGUIString::TextChunk::Tag::TAG_IMGLEFT)
{
// Only add the image if the icon exists.
if (g_GUI.IconExists(itTextChunk->m_Tags[0].m_TagValue))
if (g_GUI->IconExists(itTextChunk->m_Tags[0].m_TagValue))
{
Feedback.m_Images[SFeedback::Left].push_back(itTextChunk->m_Tags[0].m_TagValue);
}
@ -117,7 +118,7 @@ void CGUIString::GenerateTextCall(SFeedback &Feedback,
if (itTextChunk->m_Tags[0].m_TagType == CGUIString::TextChunk::Tag::TAG_IMGRIGHT)
{
// Only add the image if the icon exists.
if (g_GUI.IconExists(itTextChunk->m_Tags[0].m_TagValue))
if (g_GUI->IconExists(itTextChunk->m_Tags[0].m_TagValue))
{
Feedback.m_Images[SFeedback::Right].push_back(itTextChunk->m_Tags[0].m_TagValue);
}
@ -130,7 +131,7 @@ void CGUIString::GenerateTextCall(SFeedback &Feedback,
if (itTextChunk->m_Tags[0].m_TagType == CGUIString::TextChunk::Tag::TAG_ICON)
{
// Only add the image if the icon exists.
if (g_GUI.IconExists(itTextChunk->m_Tags[0].m_TagValue))
if (g_GUI->IconExists(itTextChunk->m_Tags[0].m_TagValue))
{
// We'll need to setup a text-call that will point
// to the icon, this is to be able to iterate
@ -142,7 +143,7 @@ void CGUIString::GenerateTextCall(SFeedback &Feedback,
SGUIText::SSpriteCall SpriteCall;
// Get Icon from icon database in g_GUI
SGUIIcon icon = g_GUI.GetIcon(itTextChunk->m_Tags[0].m_TagValue);
SGUIIcon icon = g_GUI->GetIcon(itTextChunk->m_Tags[0].m_TagValue);
CSize size = icon.m_Size;

View File

@ -21,6 +21,7 @@ GUI utilities
#include "precompiled.h"
#include "GUI.h"
#include "GUIManager.h"
#include "ps/Parser.h"
#include "ps/i18n.h"
@ -99,13 +100,10 @@ bool GUI<int>::ParseColor(const CStr& Value, CColor &Output, float DefaultAlpha)
{
// First, check our database in g_GUI for pre-defined colors
// If we find anything, we'll ignore DefaultAlpha
#ifdef g_GUI
// If it fails, it won't do anything with Output
if (g_GUI.GetPreDefinedColor(Value, Output))
if (g_GUI->GetPreDefinedColor(Value, Output))
return true;
#endif // g_GUI
return Output.ParseString(Value, DefaultAlpha);
}
@ -114,13 +112,10 @@ template <>
bool __ParseString<CColor>(const CStr& Value, CColor &Output)
{
// First, check our database in g_GUI for pre-defined colors
#ifdef g_GUI
// If it fails, it won't do anything with Output
if (g_GUI.GetPreDefinedColor(Value, Output))
if (g_GUI->GetPreDefinedColor(Value, Output))
return true;
#endif // g_GUI
return Output.ParseString(Value, 255.f);
}

View File

@ -137,19 +137,6 @@ public:
static PSRETURN SetSetting(IGUIObject *pObject, const CStr& Setting,
const T &Value, const bool &SkipMessage=false);
#ifdef g_GUI
/**
* Adapter that uses the singleton g_GUI
* Can safely be removed.
*/
static PSRETURN GetSetting(
const CStr& Object,
const CStr& Setting, T &Value)
{
return GetSetting(g_GUI, Object, Setting, Value);
}
#endif // g_GUI
/**
* Retrieves a setting by settings name and object name
*
@ -171,18 +158,6 @@ public:
return GetSetting(pObject, Setting, Value);
}
#ifdef g_GUI
/**
* Adapter that uses the singleton g_GUI
* Can safely be removed.
*/
static PSRETURN SetSetting(
const CStr& Object, const CStr& Setting, const T &Value, const bool& SkipMessage=false)
{
return SetSetting(g_GUI, Object, Setting, Value, SkipMessage);
}
#endif // g_GUI
/**
* Sets a value by setting and object name using a real
* datatype as input

View File

@ -27,7 +27,6 @@
extern JSPropertySpec JSI_props[]; \
extern JSFunctionSpec JSI_methods[]; \
JSBool construct( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ); \
JSBool getByName( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ); \
JSBool toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ); \
}

View File

@ -22,7 +22,9 @@
#include "gui/IGUIObject.h"
#include "gui/CGUI.h"
#include "gui/IGUIScrollBar.h"
#include "gui/CList.h"
#include "gui/GUIManager.h"
#include "ps/CLogger.h"
@ -45,7 +47,6 @@ JSPropertySpec JSI_IGUIObject::JSI_props[] =
JSFunctionSpec JSI_IGUIObject::JSI_methods[] =
{
{ "toString", JSI_IGUIObject::toString, 0, 0, 0 },
{ "getByName", JSI_IGUIObject::getByName, 1, 0, 0 },
{ 0 }
};
@ -60,8 +61,7 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
// access nonexistent properties.)
if (propName == "constructor" ||
propName == "prototype" ||
propName == "toString" ||
propName == "getByName"
propName == "toString"
)
return JS_TRUE;
@ -556,27 +556,6 @@ JSBool JSI_IGUIObject::construct(JSContext* cx, JSObject* obj, uintN argc, jsval
return JS_TRUE;
}
JSBool JSI_IGUIObject::getByName(JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* argv, jsval* rval)
{
debug_assert(argc == 1);
CStr objectName = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
IGUIObject* guiObject = g_GUI.FindObjectByName(objectName);
if (!guiObject)
{
// Not found - return null
*rval = JSVAL_NULL;
return JS_TRUE;
}
*rval = OBJECT_TO_JSVAL(guiObject->GetJSObject());
return JS_TRUE;
}
void JSI_IGUIObject::init()
{
g_ScriptingHost.DefineCustomObjectType(&JSI_class, construct, 1, JSI_props, JSI_methods, NULL, NULL);

View File

@ -30,7 +30,6 @@ namespace JSI_IGUIObject
JSBool getProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp);
JSBool setProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp);
JSBool construct(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
JSBool getByName(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
JSBool toString(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
void init();
}

View File

@ -30,9 +30,10 @@ that of Atlas depending on commandline parameters.
// included there.
#include "lib/precompiled.h"
#include "lib/input.h"
#include "lib/timer.h"
#include "lib/frequency_filter.h"
#include "lib/input.h"
#include "lib/ogl.h"
#include "lib/timer.h"
#include "lib/external_libraries/sdl.h"
#include "lib/res/sound/snd_mgr.h"
@ -49,6 +50,7 @@ that of Atlas depending on commandline parameters.
#include "ps/Hotkey.h"
#include "ps/Globals.h"
#include "ps/Interact.h"
#include "ps/XML/Xeromyces.h"
#include "network/NetClient.h"
#include "network/NetServer.h"
//#include "network/SessionManager.h"
@ -58,7 +60,7 @@ that of Atlas depending on commandline parameters.
#include "simulation/Scheduler.h"
#include "sound/CMusicPlayer.h"
#include "sound/SoundGroupMgr.h"
#include "gui/GUI.h"
#include "gui/GUIManager.h"
#define LOG_CATEGORY L"main"
@ -118,7 +120,7 @@ static void PumpEvents()
// used to prevent reloading during that time (see call site).
static bool ProgressiveBuildArchive()
{
ONCE(g_GUI.SendEventToAll("archivebuildercomplete"));
ONCE(g_GUI->SendEventToAll("archivebuildercomplete"));
return false;
#if 0
int ret = vfs_opt_auto_build("../logs/trace.txt", "mods/official/official%02d.zip", "mods/official/mini%02d.zip");
@ -260,7 +262,7 @@ static void Frame()
PROFILE_START("gui tick");
MICROLOG(L"gui tick");
g_GUI.TickObjects();
g_GUI->TickObjects();
PROFILE_END("gui tick");
ogl_WarnIfError();

View File

@ -18,6 +18,7 @@
#include "precompiled.h"
#include "Filesystem.h"
#include "gui/GUIManager.h"
#include "ps/CLogger.h"
#include "lib/posix/posix_time.h" // usleep
@ -67,6 +68,7 @@ LibError ReloadChangedFiles()
VfsPath pathname;
RETURN_ERR(g_VFS->GetVirtualPath(notifications[i].Pathname(), pathname));
RETURN_ERR(g_VFS->Invalidate(pathname));
RETURN_ERR(g_GUI->ReloadChangedFiles(pathname));
RETURN_ERR(h_reload(pathname));
}
}

View File

@ -40,7 +40,7 @@
#include "simulation/EntityManager.h"
#include "simulation/Simulation.h"
#include "gui/CGUI.h"
#include "gui/GUIManager.h"
class CNetServer;
extern CNetServer *g_NetServer;
@ -133,12 +133,11 @@ PSRETURN CGame::ReallyStartGame()
{
// Call the reallyStartGame GUI function, but only if it exists
jsval fval, rval;
JSBool ok = JS_GetProperty(g_ScriptingHost.getContext(), g_GUI.GetScriptObject(), "reallyStartGame", &fval);
JSBool ok = JS_GetProperty(g_ScriptingHost.getContext(), g_GUI->GetScriptObject(), "reallyStartGame", &fval);
debug_assert(ok);
if (ok && !JSVAL_IS_VOID(fval))
{
ok = JS_CallFunctionValue(g_ScriptingHost.getContext(), g_GUI.GetScriptObject(), fval, 0, NULL, &rval);
debug_assert(ok);
ok = JS_CallFunctionValue(g_ScriptingHost.getContext(), g_GUI->GetScriptObject(), fval, 0, NULL, &rval);
}
debug_printf(L"GAME STARTED, ALL INIT COMPLETE\n");
@ -151,7 +150,7 @@ PSRETURN CGame::ReallyStartGame()
g_GameRestarted = true;
g_GUI.SendEventToAll("sessionstart");
g_GUI->SendEventToAll("sessionstart");
return 0;
}

View File

@ -80,6 +80,7 @@
#include "gui/scripting/JSInterface_IGUIObject.h"
#include "gui/scripting/JSInterface_GUITypes.h"
#include "gui/GUI.h"
#include "gui/GUIManager.h"
#include "sound/JSI_Sound.h"
#include "network/NetLog.h"
@ -125,8 +126,6 @@ static int SetVideoMode(int w, int h, int bpp, bool fullscreen)
glViewport(0, 0, w, h);
g_GUI.UpdateResolution();
ogl_Init(); // required after each mode change
if(SDL_SetGamma(g_Gamma, g_Gamma, g_Gamma) < 0)
@ -199,58 +198,6 @@ retry:
// GUI integration
//----------------------------------------------------------------------------
void GUI_Init()
{
{TIMER(L"ps_gui_init");
g_GUI.Initialize();}
{TIMER(L"ps_gui_setup_xml");
g_GUI.LoadXmlFile(L"gui/test/setup.xml");}
{TIMER(L"ps_gui_styles_xml");
g_GUI.LoadXmlFile(L"gui/test/styles.xml");}
{TIMER(L"ps_gui_sprite1_xml");
g_GUI.LoadXmlFile(L"gui/test/sprite1.xml");}
// Atlas is running, we won't need these GUI pages (for now!
// what if Atlas switches to in-game mode?!)
// TODO: temporary hack until revised GUI structure is completed.
// if(ATLAS_IsRunning())
// return;
{TIMER(L"ps_gui_1");
g_GUI.LoadXmlFile(L"gui/test/1_init.xml");}
{TIMER(L"ps_gui_2");
g_GUI.LoadXmlFile(L"gui/test/2_mainmenu.xml");}
{TIMER(L"ps_gui_3");
g_GUI.LoadXmlFile(L"gui/test/3_loading.xml");}
{TIMER(L"ps_gui_4");
g_GUI.LoadXmlFile(L"gui/test/4_session.xml");}
{TIMER(L"ps_gui_6");
g_GUI.LoadXmlFile(L"gui/test/6_subwindows.xml");}
{TIMER(L"ps_gui_6_1");
g_GUI.LoadXmlFile(L"gui/test/6_1_manual.xml");}
{TIMER(L"ps_gui_6_2");
g_GUI.LoadXmlFile(L"gui/test/6_2_jukebox.xml");}
{TIMER(L"ps_gui_7");
g_GUI.LoadXmlFile(L"gui/test/7_atlas.xml");}
{TIMER(L"ps_gui_9");
g_GUI.LoadXmlFile(L"gui/test/9_global.xml");}
}
void GUI_Shutdown()
{
g_GUI.Destroy();
delete &g_GUI;
}
void GUI_ShowMainMenu()
{
}
// display progress / description in loading screen
void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task)
{
@ -258,7 +205,7 @@ void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task)
JSString* js_desc = StringConvert::wstring_to_jsstring(g_ScriptingHost.getContext(), i18n_description);
g_ScriptingHost.SetGlobal("g_Progress", INT_TO_JSVAL(percent));
g_ScriptingHost.SetGlobal("g_LoadDescription", STRING_TO_JSVAL(js_desc));
g_GUI.SendEventToAll("progress");
g_GUI->SendEventToAll("progress");
}
@ -386,7 +333,7 @@ void Render()
// Temp GUI message GeeTODO
MICROLOG(L"render GUI");
PROFILE_START( "render gui" );
if(g_DoRenderGui) g_GUI.Draw();
if(g_DoRenderGui) g_GUI->Draw();
PROFILE_END( "render gui" );
ogl_WarnIfError();
@ -499,8 +446,7 @@ static void RegisterJavascriptInterfaces()
SimulationScriptInit();
// GUI
JSI_IGUIObject::init();
JSI_GUITypes::init();
CGUI::ScriptingInit();
}
@ -611,7 +557,13 @@ static void InitPs(bool setup_gui)
}
// GUI uses VFS, so this must come after VFS init.
GUI_Init();
g_GUI->SwitchPage(L"page_pregame.xml", JSVAL_VOID);
}
else
{
// We do actually need *some* kind of GUI loaded, so use the
// (currently empty) Atlas one
g_GUI->SwitchPage(L"page_atlas.xml", JSVAL_VOID);
}
}
@ -643,7 +595,7 @@ static void InitInput()
static void ShutdownPs()
{
GUI_Shutdown();
SAFE_DELETE(g_GUI);
delete g_Console;
g_Console = 0;
@ -907,7 +859,7 @@ void Init(const CmdLineArgs& args, int flags)
const bool setup_gui = ((flags & INIT_NO_GUI) == 0 && g_AutostartMap.empty());
// GUI is notified in SetVideoMode, so this must come before that.
new CGUI;
g_GUI = new CGUIManager();
// default to windowed, so users don't get stuck if e.g. half the
// filesystem is missing and the config files aren't loaded
@ -1015,11 +967,6 @@ void Init(const CmdLineArgs& args, int flags)
ogl_WarnIfError();
{
TIMER(L"Init_guiload");
g_GUI.SendEventToAll("load");
}
if (g_FixedFrameTiming) {
CCamera &camera = *g_Game->GetView()->GetCamera();
#if 0 // TOPDOWN

View File

@ -98,8 +98,8 @@ CRect::CRect(const CPos &pos, const CSize &size) :
{
}
CRect::CRect(const float &_l, const float &_t, const float &_r, const float &_b) :
left(_l), top(_t), right(_r), bottom(_b)
CRect::CRect(const float l, const float t, const float r, const float b) :
left(l), top(t), right(r), bottom(b)
{
}

View File

@ -76,7 +76,7 @@ public:
CRect(const CSize &size);
CRect(const CPos &upperleft, const CPos &bottomright);
CRect(const CPos &pos, const CSize &size);
CRect(const float &_l, const float &_t, const float &_r, const float &_b);
CRect(const float l, const float t, const float r, const float b);
// Operators
void operator = (const CRect& a);

View File

@ -36,7 +36,7 @@
#include "graphics/UnitManager.h"
#include "graphics/scripting/JSInterface_Camera.h"
#include "graphics/scripting/JSInterface_LightEnv.h"
#include "gui/CGUI.h"
#include "gui/GUIManager.h"
#include "lib/timer.h"
#include "lib/svn_revision.h"
#include "lib/frequency_filter.h"
@ -890,29 +890,43 @@ JSBool ForceGarbageCollection(JSContext* cx, JSObject* UNUSED(obj), uintN argc,
// returns: global object
// notes:
// - Useful for accessing an object from another scope.
JSBool GetGuiGlobal(JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval)
JSBool GetActiveGui(JSContext* UNUSED(cx), JSObject*, uintN UNUSED(argc), jsval* UNUSED(argv), jsval* rval)
{
JSU_REQUIRE_NO_PARAMS();
*rval = OBJECT_TO_JSVAL(g_GUI.GetScriptObject());
*rval = OBJECT_TO_JSVAL(g_GUI->GetScriptObject());
return JS_TRUE;
}
// Resets the entire GUI state and reloads the XML files.
// params:
// returns:
JSBool ResetGui(JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval)
JSBool PushGuiPage(JSContext* cx, JSObject*, uintN UNUSED(argc), jsval* argv, jsval* UNUSED(rval))
{
JSU_REQUIRE_NO_PARAMS();
try
{
CStrW name = ToPrimitive<CStrW>(cx, argv[0]);
g_GUI->PushPage(name, argv[1]);
return JS_TRUE;
}
catch (PSERROR_Scripting&)
{
return JS_FALSE;
}
}
// Slightly unpleasant code, because CGUI is a Singleton but we don't really
// want it to be
g_GUI.Destroy();
delete &g_GUI;
new CGUI;
GUI_Init();
g_GUI.SendEventToAll("load");
JSBool SwitchGuiPage(JSContext* cx, JSObject*, uintN UNUSED(argc), jsval* argv, jsval* UNUSED(rval))
{
try
{
CStrW name = ToPrimitive<CStrW>(cx, argv[0]);
g_GUI->SwitchPage(name, argv[1]);
return JS_TRUE;
}
catch (PSERROR_Scripting&)
{
return JS_FALSE;
}
}
JSBool PopGuiPage(JSContext* UNUSED(cx), JSObject*, uintN UNUSED(argc), jsval* UNUSED(argv), jsval* UNUSED(rval))
{
g_GUI->PopPage();
return JS_TRUE;
}
@ -1480,9 +1494,10 @@ JSFunctionSpec ScriptFunctionTable[] =
JS_FUNC("toggleTerritoryRendering", ToggleTerritoryRendering, 0)
// GUI
JS_FUNC("getGUIObjectByName", JSI_IGUIObject::getByName, 1) // external
JS_FUNC("getGUIGlobal", GetGuiGlobal, 0)
JS_FUNC("resetGUI", ResetGui, 0)
JS_FUNC("getActiveGui", GetActiveGui, 0)
JS_FUNC("pushGuiPage", PushGuiPage, 2)
JS_FUNC("switchGuiPage", SwitchGuiPage, 2)
JS_FUNC("popGuiPage", PopGuiPage, 0)
// Events
JS_FUNC("addGlobalHandler", AddGlobalHandler, 2)

View File

@ -25,8 +25,7 @@
#include "graphics/GameView.h"
#include "graphics/ObjectManager.h"
#include "gui/CGUI.h"
#include "gui/GUIbase.h"
#include "gui/GUIManager.h"
#include "lib/external_libraries/sdl.h"
#include "maths/MathUtil.h"
#include "ps/CConsole.h"
@ -174,7 +173,7 @@ MESSAGEHANDLER(ResizeScreen)
g_Renderer.SetViewport(vp);
g_Renderer.Resize(g_xres, g_yres);
g_GUI.UpdateResolution();
g_GUI->UpdateResolution();
g_Console->UpdateScreenSize(g_xres, g_yres);
}