2009-04-18 10:00:33 -07:00
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A . D .
*
* 0 A . D . is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 2 of the License , or
* ( at your option ) any later version .
*
* 0 A . D . is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with 0 A . D . If not , see < http : //www.gnu.org/licenses/>.
*/
2003-11-03 08:22:45 -08:00
/*
CGUI
*/
2004-06-03 11:38:14 -07:00
# include "precompiled.h"
2004-06-15 14:08:05 -07:00
2004-09-19 04:38:54 -07:00
# include <string>
2005-06-27 21:06:25 -07:00
2004-09-19 04:38:54 -07:00
# include <stdarg.h>
2005-08-12 10:06:53 -07:00
# include "lib/res/graphics/unifont.h"
2004-09-19 04:38:54 -07:00
2003-11-03 08:22:45 -08:00
# include "GUI.h"
2004-05-28 21:06:50 -07:00
// Types - when including them into the engine.
# include "CButton.h"
2004-09-01 20:02:32 -07:00
# include "CImage.h"
2004-05-28 21:06:50 -07:00
# include "CText.h"
# include "CCheckBox.h"
# include "CRadioButton.h"
2004-10-14 03:09:26 -07:00
# include "CInput.h"
2005-04-07 02:13:10 -07:00
# include "CList.h"
2005-04-23 16:20:50 -07:00
# include "CDropDown.h"
2004-10-13 19:32:26 -07:00
# include "CProgressBar.h"
2004-12-21 05:37:24 -08:00
# include "CTooltip.h"
2004-10-07 18:10:14 -07:00
# include "MiniMap.h"
2009-12-03 12:17:22 -08:00
# include "scripting/JSInterface_GUITypes.h"
2004-05-28 21:06:50 -07:00
2005-08-14 16:50:37 -07:00
# include "ps/XML/Xeromyces.h"
2004-08-27 15:08:30 -07:00
# include "ps/Font.h"
2003-11-23 18:18:41 -08:00
2006-06-01 19:10:27 -07:00
# include "ps/Pyrogenesis.h"
# include "lib/input.h"
2007-05-09 14:01:11 -07:00
# include "lib/bits.h"
2007-12-20 12:21:45 -08:00
# include "lib/timer.h"
2010-03-01 06:55:34 -08:00
# include "lib/utf8.h"
2007-12-20 12:21:45 -08:00
# include "lib/sysdep/sysdep.h"
2004-05-28 21:06:50 -07:00
// TODO Gee: Whatever include CRect/CPos/CSize
2006-06-01 19:10:27 -07:00
# include "ps/Overlay.h"
2007-06-15 10:03:26 -07:00
# include "ps/Profile.h"
2003-11-03 08:22:45 -08:00
2004-07-08 08:23:47 -07:00
# include "scripting/ScriptingHost.h"
2010-05-05 15:36:35 -07:00
# include "scripting/JSConversions.h"
2006-06-01 19:10:27 -07:00
# include "ps/Hotkey.h"
2005-10-16 16:16:08 -07:00
# include "ps/Globals.h"
2007-12-20 12:21:45 -08:00
# include "ps/Filesystem.h"
2004-07-08 08:23:47 -07:00
2006-01-21 03:07:25 -08:00
const double SELECT_DBLCLICK_RATE = 0.5 ;
2004-07-08 08:23:47 -07:00
# include "ps/CLogger.h"
2009-11-03 13:46:35 -08:00
# define LOG_CATEGORY L"gui"
2004-08-15 13:57:31 -07:00
2004-07-08 08:23:47 -07:00
// Class for global JavaScript object
JSClass GUIClass = {
2009-12-03 12:17:22 -08:00
" GUIClass " , JSCLASS_HAS_PRIVATE ,
2004-07-08 08:23:47 -07:00
JS_PropertyStub , JS_PropertyStub , JS_PropertyStub , JS_PropertyStub ,
JS_EnumerateStub , JS_ResolveStub , JS_ConvertStub , JS_FinalizeStub ,
} ;
2009-12-03 12:17:22 -08:00
static JSBool GetGUIObjectByName ( JSContext * cx , JSObject * obj , uintN UNUSED ( argc ) , jsval * argv , jsval * rval )
2003-11-04 15:41:42 -08:00
{
2009-12-03 12:17:22 -08:00
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 ;
}
2003-11-04 15:41:42 -08:00
}
2009-12-03 12:17:22 -08:00
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 ) ;
}
2005-10-24 14:10:45 -07:00
2006-08-26 14:52:18 -07:00
InReaction CGUI : : HandleEvent ( const SDL_Event_ * ev )
2003-11-03 08:22:45 -08:00
{
2005-10-20 08:27:39 -07:00
InReaction ret = IN_PASS ;
2004-10-14 03:09:26 -07:00
2006-08-26 14:52:18 -07:00
if ( ev - > ev . type = = SDL_GUIHOTKEYPRESS )
2004-07-22 09:18:12 -07:00
{
2006-08-26 14:52:18 -07:00
const CStr & objectName = * ( CStr * ) ev - > ev . user . data1 ;
2004-10-31 12:29:09 -08:00
IGUIObject * object = FindObjectByName ( objectName ) ;
if ( ! object )
{
2009-11-03 13:46:35 -08:00
LOG ( CLogger : : Error , LOG_CATEGORY , L " Cannot find hotkeyed object '%hs' " , objectName . c_str ( ) ) ;
2004-10-31 12:29:09 -08:00
}
else
{
object - > HandleMessage ( SGUIMessage ( GUIM_PRESSED ) ) ;
object - > ScriptEvent ( " press " ) ;
}
2004-07-22 09:18:12 -07:00
}
2006-08-26 14:52:18 -07:00
else if ( ev - > ev . type = = SDL_MOUSEMOTION )
2003-12-26 22:26:03 -08:00
{
2004-09-02 22:48:47 -07:00
// Yes the mouse position is stored as float to avoid
2005-10-20 10:44:56 -07:00
// constant conversions when operating in a
2004-09-02 22:48:47 -07:00
// float-based environment.
2006-08-26 14:52:18 -07:00
m_MousePos = CPos ( ( float ) ev - > ev . motion . x , ( float ) ev - > ev . motion . y ) ;
2003-11-03 08:22:45 -08:00
2003-12-26 22:26:03 -08:00
GUI < SGUIMessage > : : RecurseObject ( GUIRR_HIDDEN | GUIRR_GHOST , m_BaseObject ,
& IGUIObject : : HandleMessage ,
SGUIMessage ( GUIM_MOUSE_MOTION ) ) ;
}
2004-07-08 08:23:47 -07:00
// Update m_MouseButtons. (BUTTONUP is handled later.)
2006-08-26 14:52:18 -07:00
else if ( ev - > ev . type = = SDL_MOUSEBUTTONDOWN )
2003-12-26 22:26:03 -08:00
{
2006-08-26 14:52:18 -07:00
switch ( ev - > ev . button . button )
2005-10-24 14:10:45 -07:00
{
case SDL_BUTTON_LEFT :
case SDL_BUTTON_RIGHT :
case SDL_BUTTON_MIDDLE :
2008-09-06 14:15:53 -07:00
m_MouseButtons | = Bit < unsigned int > ( ev - > ev . button . button ) ;
2005-10-24 14:10:45 -07:00
break ;
default :
break ;
}
2003-12-26 22:26:03 -08:00
}
2003-11-03 08:22:45 -08:00
// Only one object can be hovered
2003-11-23 18:18:41 -08:00
IGUIObject * pNearest = NULL ;
2003-11-03 08:22:45 -08:00
2004-10-14 03:09:26 -07:00
// TODO Gee: (2004-09-08) Big TODO, don't do the below if the SDL_Event is something like a keypress!
2003-11-24 18:47:12 -08:00
try
2003-11-03 08:22:45 -08:00
{
2007-06-15 10:03:26 -07:00
PROFILE ( " mouse events " ) ;
2004-05-28 21:06:50 -07:00
// TODO Gee: Optimizations needed!
// these two recursive function are quite overhead heavy.
2003-11-24 18:47:12 -08:00
// pNearest will after this point at the hovered object, possibly NULL
2003-12-26 22:26:03 -08:00
GUI < IGUIObject * > : : RecurseObject ( GUIRR_HIDDEN | GUIRR_GHOST , m_BaseObject ,
2003-11-24 18:47:12 -08:00
& IGUIObject : : ChooseMouseOverAndClosest ,
pNearest ) ;
2004-07-11 09:22:35 -07:00
2005-07-23 15:27:55 -07:00
// Is placed in the UpdateMouseOver function
2006-08-26 14:52:18 -07:00
//if (ev->ev.type == SDL_MOUSEMOTION && pNearest)
2005-07-23 15:27:55 -07:00
// pNearest->ScriptEvent("mousemove");
2004-07-11 09:22:35 -07:00
2003-11-24 18:47:12 -08:00
// 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
2004-07-22 09:18:12 -07:00
2003-12-26 22:26:03 -08:00
GUI < IGUIObject * > : : RecurseObject ( GUIRR_HIDDEN | GUIRR_GHOST , m_BaseObject ,
2003-11-24 18:47:12 -08:00
& IGUIObject : : UpdateMouseOver ,
pNearest ) ;
2006-08-26 14:52:18 -07:00
if ( ev - > ev . type = = SDL_MOUSEBUTTONDOWN )
2003-11-24 18:47:12 -08:00
{
2006-08-26 14:52:18 -07:00
switch ( ev - > ev . button . button )
2003-11-24 18:47:12 -08:00
{
2004-05-28 21:06:50 -07:00
case SDL_BUTTON_LEFT :
if ( pNearest )
2003-12-26 22:26:03 -08:00
{
2004-10-14 03:09:26 -07:00
if ( pNearest ! = m_FocusedObject )
{
// Update focused object
if ( m_FocusedObject )
m_FocusedObject - > HandleMessage ( SGUIMessage ( GUIM_LOST_FOCUS ) ) ;
m_FocusedObject = pNearest ;
m_FocusedObject - > HandleMessage ( SGUIMessage ( GUIM_GOT_FOCUS ) ) ;
}
2004-05-28 21:06:50 -07:00
pNearest - > HandleMessage ( SGUIMessage ( GUIM_MOUSE_PRESS_LEFT ) ) ;
2004-07-11 09:22:35 -07:00
pNearest - > ScriptEvent ( " mouseleftpress " ) ;
2004-10-14 03:09:26 -07:00
// Block event, so things on the map (behind the GUI) won't be pressed
2005-10-20 10:44:56 -07:00
ret = IN_HANDLED ;
2004-05-28 21:06:50 -07:00
}
2005-04-23 16:20:50 -07:00
else if ( m_FocusedObject )
{
m_FocusedObject - > HandleMessage ( SGUIMessage ( GUIM_LOST_FOCUS ) ) ;
//if (m_FocusedObject-> TODO SelfishFocus?
m_FocusedObject = 0 ;
}
2004-07-11 09:22:35 -07:00
break ;
2004-05-28 21:06:50 -07:00
2004-06-02 08:22:19 -07:00
case SDL_BUTTON_WHEELDOWN : // wheel down
2004-05-28 21:06:50 -07:00
if ( pNearest )
{
pNearest - > HandleMessage ( SGUIMessage ( GUIM_MOUSE_WHEEL_DOWN ) ) ;
2004-07-11 09:22:35 -07:00
pNearest - > ScriptEvent ( " mousewheeldown " ) ;
2004-10-17 03:55:57 -07:00
2005-10-20 10:44:56 -07:00
ret = IN_HANDLED ;
2003-12-26 22:26:03 -08:00
}
2004-05-28 21:06:50 -07:00
break ;
2004-06-02 08:22:19 -07:00
case SDL_BUTTON_WHEELUP : // wheel up
2004-05-28 21:06:50 -07:00
if ( pNearest )
2003-12-26 22:26:03 -08:00
{
2004-05-28 21:06:50 -07:00
pNearest - > HandleMessage ( SGUIMessage ( GUIM_MOUSE_WHEEL_UP ) ) ;
2005-07-23 15:27:55 -07:00
pNearest - > ScriptEvent ( " mousewheelup " ) ;
2004-10-17 03:55:57 -07:00
2005-10-20 10:44:56 -07:00
ret = IN_HANDLED ;
2003-12-26 22:26:03 -08:00
}
2004-05-28 21:06:50 -07:00
break ;
default :
break ;
}
}
else
2006-08-26 14:52:18 -07:00
if ( ev - > ev . type = = SDL_MOUSEBUTTONUP )
2004-05-28 21:06:50 -07:00
{
2006-08-26 14:52:18 -07:00
switch ( ev - > ev . button . button )
2004-05-28 21:06:50 -07:00
{
2004-12-21 05:37:24 -08:00
case SDL_BUTTON_LEFT :
2003-12-26 22:26:03 -08:00
if ( pNearest )
2004-07-11 09:22:35 -07:00
{
2008-01-07 12:03:19 -08:00
double timeElapsed = timer_Time ( ) - pNearest - > m_LastClickTime [ SDL_BUTTON_LEFT ] ;
pNearest - > m_LastClickTime [ SDL_BUTTON_LEFT ] = timer_Time ( ) ;
2006-01-21 03:07:25 -08:00
//Double click?
if ( timeElapsed < SELECT_DBLCLICK_RATE )
{
pNearest - > HandleMessage ( SGUIMessage ( GUIM_MOUSE_DBLCLICK_LEFT ) ) ;
pNearest - > ScriptEvent ( " mouseleftdoubleclick " ) ;
}
else
{
pNearest - > HandleMessage ( SGUIMessage ( GUIM_MOUSE_RELEASE_LEFT ) ) ;
pNearest - > ScriptEvent ( " mouseleftrelease " ) ;
}
ret = IN_HANDLED ;
}
break ;
case SDL_BUTTON_RIGHT :
if ( pNearest )
{
2008-01-07 12:03:19 -08:00
double timeElapsed = timer_Time ( ) - pNearest - > m_LastClickTime [ SDL_BUTTON_RIGHT ] ;
pNearest - > m_LastClickTime [ SDL_BUTTON_RIGHT ] = timer_Time ( ) ;
2006-01-21 03:07:25 -08:00
//Double click?
if ( timeElapsed < SELECT_DBLCLICK_RATE )
{
pNearest - > HandleMessage ( SGUIMessage ( GUIM_MOUSE_DBLCLICK_RIGHT ) ) ;
//pNearest->ScriptEvent("mouserightdoubleclick");
}
else
{
pNearest - > HandleMessage ( SGUIMessage ( GUIM_MOUSE_RELEASE_RIGHT ) ) ;
//pNearest->ScriptEvent("mouserightrelease");
}
2004-10-14 03:09:26 -07:00
2005-10-20 10:44:56 -07:00
ret = IN_HANDLED ;
2004-07-11 09:22:35 -07:00
}
2004-12-21 05:37:24 -08:00
break ;
2003-12-26 22:26:03 -08:00
}
2004-05-28 21:06:50 -07:00
// Reset all states on all visible objects
GUI < > : : RecurseObject ( GUIRR_HIDDEN , m_BaseObject ,
& IGUIObject : : ResetStates ) ;
// It will have reset the mouse over of the current hovered, so we'll
// have to restore that
if ( pNearest )
pNearest - > m_MouseHovering = true ;
2003-11-24 18:47:12 -08:00
}
}
2009-09-27 08:04:46 -07:00
catch ( PSERROR_GUI & e )
2003-11-24 18:47:12 -08:00
{
2005-08-09 09:02:15 -07:00
UNUSED2 ( e ) ;
2009-11-03 13:46:35 -08:00
debug_warn ( L " CGUI::HandleEvent error " ) ;
2003-12-26 22:26:03 -08:00
// TODO Gee: Handle
2003-11-24 18:47:12 -08:00
}
2003-11-03 08:22:45 -08:00
// JW: what's the difference between mPress and mDown? what's the code below responsible for?
2004-06-10 19:14:18 -07:00
/*
// Generally if just mouse is clicked
2003-11-03 08:22:45 -08:00
if ( m_pInput - > mDown ( NEMM_BUTTON1 ) & & pNearest )
{
pNearest - > HandleMessage ( GUIM_MOUSE_DOWN_LEFT ) ;
}
*/
2004-07-08 08:23:47 -07:00
// BUTTONUP's effect on m_MouseButtons is handled after
// everything else, so that e.g. 'press' handlers (activated
// on button up) see which mouse button had been pressed.
2006-08-26 14:52:18 -07:00
if ( ev - > ev . type = = SDL_MOUSEBUTTONUP )
2004-07-08 08:23:47 -07:00
{
2006-08-26 14:52:18 -07:00
switch ( ev - > ev . button . button )
2005-10-24 14:10:45 -07:00
{
case SDL_BUTTON_LEFT :
case SDL_BUTTON_RIGHT :
case SDL_BUTTON_MIDDLE :
2008-09-06 14:15:53 -07:00
m_MouseButtons & = ~ Bit < unsigned int > ( ev - > ev . button . button ) ;
2005-10-24 14:10:45 -07:00
break ;
default :
break ;
}
2004-07-08 08:23:47 -07:00
}
2004-10-14 03:09:26 -07:00
// Handle keys for input boxes
2005-01-22 10:46:03 -08:00
if ( GetFocusedObject ( ) )
2004-10-14 03:09:26 -07:00
{
2005-01-22 10:46:03 -08:00
if (
2006-08-26 14:52:18 -07:00
( ev - > ev . type = = SDL_KEYDOWN & &
ev - > ev . key . keysym . sym ! = SDLK_ESCAPE & &
2005-10-31 10:36:36 -08:00
! g_keys [ SDLK_LCTRL ] & & ! g_keys [ SDLK_RCTRL ] & &
! g_keys [ SDLK_LALT ] & & ! g_keys [ SDLK_RALT ] )
2006-08-26 14:52:18 -07:00
| | ev - > ev . type = = SDL_HOTKEYDOWN
2005-01-22 10:46:03 -08:00
)
2004-10-14 03:09:26 -07:00
{
ret = GetFocusedObject ( ) - > ManuallyHandleEvent ( ev ) ;
}
2005-10-20 10:44:56 -07:00
// else will return IN_PASS because we never used the button.
2004-10-14 03:09:26 -07:00
}
return ret ;
2003-11-03 08:22:45 -08:00
}
2004-07-24 12:09:12 -07:00
void CGUI : : TickObjects ( )
{
CStr action = " tick " ;
GUI < CStr > : : RecurseObject ( 0 , m_BaseObject ,
& IGUIObject : : ScriptEvent , action ) ;
2004-12-21 05:37:24 -08:00
// Also update tooltips:
// TODO: Efficiency
IGUIObject * pNearest = NULL ;
GUI < IGUIObject * > : : RecurseObject ( GUIRR_HIDDEN | GUIRR_GHOST , m_BaseObject ,
& IGUIObject : : ChooseMouseOverAndClosest ,
pNearest ) ;
m_Tooltip . Update ( pNearest , m_MousePos , this ) ;
2004-07-24 12:09:12 -07:00
}
2006-07-20 07:37:58 -07:00
void CGUI : : SendEventToAll ( const CStr & EventName )
2005-01-01 09:30:55 -08:00
{
2006-03-02 22:03:16 -08:00
// janwas 2006-03-03: spoke with Ykkrosh about EventName case.
// when registering, case is converted to lower - this avoids surprise
// if someone were to get the case wrong and then not notice their
// handler is never called. however, until now, the other end
// (sending events here) wasn't converting to lower case,
// leading to a similar problem.
// now fixed; case is irrelevant since all are converted to lower.
2005-01-01 09:30:55 -08:00
GUI < CStr > : : RecurseObject ( 0 , m_BaseObject ,
2006-03-02 22:03:16 -08:00
& IGUIObject : : ScriptEvent , EventName . LowerCase ( ) ) ;
2005-01-01 09:30:55 -08:00
}
2003-11-03 08:22:45 -08:00
//-------------------------------------------------------------------
// Constructor / Destructor
//-------------------------------------------------------------------
2006-01-29 10:23:47 -08:00
CGUI : : CGUI ( ) : m_MouseButtons ( 0 ) , m_FocusedObject ( NULL ) , m_InternalNameNumber ( 0 )
2003-11-03 08:22:45 -08:00
{
2003-11-06 03:54:46 -08:00
m_BaseObject = new CGUIDummyObject ;
2003-11-03 08:22:45 -08:00
m_BaseObject - > SetGUI ( this ) ;
2004-07-08 08:23:47 -07:00
// Construct the parent object for all GUI JavaScript things
2004-09-04 07:40:06 -07:00
m_ScriptObject = JS_NewObject ( g_ScriptingHost . getContext ( ) , & GUIClass , NULL , NULL ) ;
2005-06-27 21:06:25 -07:00
debug_assert ( m_ScriptObject ! = NULL ) ; // How should it handle errors?
2004-07-08 08:23:47 -07:00
JS_AddRoot ( g_ScriptingHost . getContext ( ) , & m_ScriptObject ) ;
2009-12-03 12:17:22 -08:00
JS_SetPrivate ( g_ScriptingHost . getContext ( ) , m_ScriptObject , this ) ;
2003-11-03 08:22:45 -08:00
}
CGUI : : ~ CGUI ( )
{
2009-12-03 12:17:22 -08:00
Destroy ( ) ;
2003-11-03 08:22:45 -08:00
if ( m_BaseObject )
delete m_BaseObject ;
2004-07-08 08:23:47 -07:00
if ( m_ScriptObject )
2009-12-03 12:17:22 -08:00
{
// Make sure it doesn't have dangling references to this CGUI
JS_SetPrivate ( g_ScriptingHost . getContext ( ) , m_ScriptObject , NULL ) ;
2004-07-08 08:23:47 -07:00
// Let it be garbage-collected
JS_RemoveRoot ( g_ScriptingHost . getContext ( ) , & m_ScriptObject ) ;
2009-12-03 12:17:22 -08:00
}
2003-11-03 08:22:45 -08:00
}
2003-11-22 07:07:22 -08:00
//-------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------
2004-06-18 07:07:06 -07:00
IGUIObject * CGUI : : ConstructObject ( const CStr & str )
2003-11-03 08:22:45 -08:00
{
if ( m_ObjectTypes . count ( str ) > 0 )
return ( * m_ObjectTypes [ str ] ) ( ) ;
else
2003-11-23 18:18:41 -08:00
{
2004-09-01 20:02:32 -07:00
// Error reporting will be handled with the NULL return.
2003-11-03 08:22:45 -08:00
return NULL ;
2003-11-23 18:18:41 -08:00
}
2003-11-03 08:22:45 -08:00
}
2003-11-23 18:18:41 -08:00
void CGUI : : Initialize ( )
2003-11-03 08:22:45 -08:00
{
// Add base types!
2003-11-23 18:18:41 -08:00
// You can also add types outside the GUI to extend the flexibility of the GUI.
2004-12-05 13:56:09 -08:00
// Pyrogenesis though will have all the object types inserted from here.
2004-05-28 21:06:50 -07:00
AddObjectType ( " empty " , & CGUIDummyObject : : ConstructObject ) ;
AddObjectType ( " button " , & CButton : : ConstructObject ) ;
2004-09-01 20:02:32 -07:00
AddObjectType ( " image " , & CImage : : ConstructObject ) ;
2004-05-28 21:06:50 -07:00
AddObjectType ( " text " , & CText : : ConstructObject ) ;
AddObjectType ( " checkbox " , & CCheckBox : : ConstructObject ) ;
AddObjectType ( " radiobutton " , & CRadioButton : : ConstructObject ) ;
2004-10-13 19:32:26 -07:00
AddObjectType ( " progressbar " , & CProgressBar : : ConstructObject ) ;
2009-12-03 12:17:22 -08:00
AddObjectType ( " minimap " , & CMiniMap : : ConstructObject ) ;
2004-10-14 03:09:26 -07:00
AddObjectType ( " input " , & CInput : : ConstructObject ) ;
2005-07-19 22:27:32 -07:00
AddObjectType ( " list " , & CList : : ConstructObject ) ;
2005-04-23 16:20:50 -07:00
AddObjectType ( " dropdown " , & CDropDown : : ConstructObject ) ;
2003-11-03 08:22:45 -08:00
}
void CGUI : : Draw ( )
{
2004-07-08 08:23:47 -07:00
// Clear the depth buffer, so the GUI is
// drawn on top of everything else
glClear ( GL_DEPTH_BUFFER_BIT ) ;
2003-11-23 18:18:41 -08:00
glPushMatrix ( ) ;
2005-02-04 23:25:16 -08:00
guiLoadIdentity ( ) ;
2003-11-23 18:18:41 -08:00
2003-11-03 08:22:45 -08:00
try
{
2003-11-23 18:18:41 -08:00
// Recurse IGUIObject::Draw() with restriction: hidden
// meaning all hidden objects won't call Draw (nor will it recurse its children)
GUI < > : : RecurseObject ( GUIRR_HIDDEN , m_BaseObject , & IGUIObject : : Draw ) ;
2003-11-03 08:22:45 -08:00
}
2009-09-27 08:04:46 -07:00
catch ( PSERROR_GUI & e )
2003-11-03 08:22:45 -08:00
{
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI draw error: %hs " , e . what ( ) ) ;
2003-11-03 08:22:45 -08:00
}
2003-11-23 18:18:41 -08:00
glPopMatrix ( ) ;
2003-11-03 08:22:45 -08:00
}
2009-07-28 09:59:19 -07:00
void CGUI : : DrawSprite ( const CGUISpriteInstance & Sprite ,
2004-12-18 05:32:00 -08:00
int CellID ,
2005-08-09 09:02:15 -07:00
const float & Z ,
const CRect & Rect ,
const CRect & UNUSED ( Clipping ) )
2003-11-30 23:06:55 -08:00
{
2004-12-15 13:24:46 -08:00
// If the sprite doesn't exist (name == ""), don't bother drawing anything
if ( Sprite . IsEmpty ( ) )
2003-11-30 23:06:55 -08:00
return ;
2004-07-24 07:04:40 -07:00
// TODO: Clipping?
2003-11-30 23:06:55 -08:00
glPushMatrix ( ) ;
2004-07-13 15:48:53 -07:00
glTranslatef ( 0.0f , 0.0f , Z ) ;
2003-11-30 23:06:55 -08:00
2004-12-18 05:32:00 -08:00
Sprite . Draw ( Rect , CellID , m_Sprites ) ;
2004-09-01 20:02:32 -07:00
2003-11-30 23:06:55 -08:00
glPopMatrix ( ) ;
2004-12-15 13:24:46 -08:00
2003-11-30 23:06:55 -08:00
}
2003-11-03 08:22:45 -08:00
void CGUI : : Destroy ( )
{
// We can use the map to delete all
2003-11-22 07:07:22 -08:00
// now we don't want to cancel all if one Destroy fails
2003-11-03 08:22:45 -08:00
map_pObjects : : iterator it ;
for ( it = m_pAllObjects . begin ( ) ; it ! = m_pAllObjects . end ( ) ; + + it )
{
try
{
it - > second - > Destroy ( ) ;
}
2009-09-27 08:04:46 -07:00
catch ( PSERROR_GUI & e )
2003-11-03 08:22:45 -08:00
{
2005-08-09 09:02:15 -07:00
UNUSED2 ( e ) ;
2009-11-03 13:46:35 -08:00
debug_warn ( L " CGUI::Destroy error " ) ;
2003-12-26 22:26:03 -08:00
// TODO Gee: Handle
2003-11-03 08:22:45 -08:00
}
delete it - > second ;
}
2004-12-18 05:32:00 -08:00
for ( std : : map < CStr , CGUISprite > : : iterator it2 = m_Sprites . begin ( ) ; it2 ! = m_Sprites . end ( ) ; + + it2 )
for ( std : : vector < SGUIImage > : : iterator it3 = it2 - > second . m_Images . begin ( ) ; it3 ! = it2 - > second . m_Images . e nd ( ) ; + + it3 )
delete it3 - > m_Effects ;
2003-11-03 08:22:45 -08:00
// Clear all
m_pAllObjects . clear ( ) ;
m_Sprites . clear ( ) ;
2004-08-30 19:09:58 -07:00
m_Icons . clear ( ) ;
2003-11-03 08:22:45 -08:00
}
2003-11-24 09:13:37 -08:00
void CGUI : : UpdateResolution ( )
{
2003-11-24 18:47:12 -08:00
// Update ALL cached
2003-11-24 09:13:37 -08:00
GUI < > : : RecurseObject ( 0 , m_BaseObject , & IGUIObject : : UpdateCachedSize ) ;
}
2003-11-23 18:18:41 -08:00
void CGUI : : AddObject ( IGUIObject * pObject )
2003-11-03 08:22:45 -08:00
{
2003-11-30 23:06:55 -08:00
try
{
2003-11-03 08:22:45 -08:00
// Add CGUI pointer
2003-11-23 18:18:41 -08:00
GUI < CGUI * > : : RecurseObject ( 0 , pObject , & IGUIObject : : SetGUI , this ) ;
2003-11-03 08:22:45 -08:00
// Add child to base object
2004-12-13 04:07:12 -08:00
m_BaseObject - > AddChild ( pObject ) ; // can throw
2003-11-24 18:47:12 -08:00
// Cache tree
GUI < > : : RecurseObject ( 0 , pObject , & IGUIObject : : UpdateCachedSize ) ;
2004-05-28 21:06:50 -07:00
// Loaded
GUI < SGUIMessage > : : RecurseObject ( 0 , pObject , & IGUIObject : : HandleMessage , SGUIMessage ( GUIM_LOAD ) ) ;
2003-11-30 23:06:55 -08:00
}
2009-09-27 08:04:46 -07:00
catch ( PSERROR_GUI & )
2003-11-03 08:22:45 -08:00
{
2009-09-27 08:04:46 -07:00
throw ;
2003-11-30 23:06:55 -08:00
}
2003-11-03 08:22:45 -08:00
}
void CGUI : : UpdateObjects ( )
{
// We'll fill a temporary map until we know everything
// succeeded
map_pObjects AllObjects ;
try
{
// Fill freshly
2003-11-23 18:18:41 -08:00
GUI < map_pObjects > : : RecurseObject ( 0 , m_BaseObject , & IGUIObject : : AddToPointersMap , AllObjects ) ;
2003-11-03 08:22:45 -08:00
}
2009-09-27 08:04:46 -07:00
catch ( PSERROR_GUI & )
2003-11-03 08:22:45 -08:00
{
// Throw the same error
2009-09-27 08:04:46 -07:00
throw ;
2003-11-03 08:22:45 -08:00
}
// Else actually update the real one
2005-01-12 16:17:31 -08:00
m_pAllObjects . swap ( AllObjects ) ;
2003-11-03 08:22:45 -08:00
}
2004-06-18 07:07:06 -07:00
bool CGUI : : ObjectExists ( const CStr & Name ) const
2003-11-03 08:22:45 -08:00
{
2004-05-29 04:59:59 -07:00
return m_pAllObjects . count ( Name ) ! = 0 ;
2004-05-28 21:06:50 -07:00
}
2004-07-08 08:23:47 -07:00
IGUIObject * CGUI : : FindObjectByName ( const CStr & Name ) const
{
map_pObjects : : const_iterator it = m_pAllObjects . find ( Name ) ;
if ( it = = m_pAllObjects . end ( ) )
return NULL ;
else
return it - > second ;
}
2004-05-28 21:06:50 -07:00
// private struct used only in GenerateText(...)
2004-05-29 04:59:59 -07:00
struct SGenerateTextImage
2004-05-28 21:06:50 -07:00
{
2004-12-18 05:32:00 -08:00
float m_YFrom , // The image's starting location in Y
m_YTo , // The image's end location in Y
2004-09-02 22:48:47 -07:00
m_Indentation ; // The image width in other words
2004-05-28 21:06:50 -07:00
// Some help functions
// TODO Gee: CRect => CPoint ?
2004-12-18 05:32:00 -08:00
void SetupSpriteCall ( const bool Left , SGUIText : : SSpriteCall & SpriteCall ,
const float width , const float y ,
2006-07-20 07:37:58 -07:00
const CSize & Size , const CStr & TextureName ,
2004-12-18 05:32:00 -08:00
const float BufferZone , const int CellID )
2004-05-28 21:06:50 -07:00
{
// TODO Gee: Temp hardcoded values
SpriteCall . m_Area . top = y + BufferZone ;
SpriteCall . m_Area . bottom = y + BufferZone + Size . cy ;
if ( Left )
{
SpriteCall . m_Area . left = BufferZone ;
SpriteCall . m_Area . right = Size . cx + BufferZone ;
}
else
{
SpriteCall . m_Area . left = width - BufferZone - Size . cx ;
SpriteCall . m_Area . right = width - BufferZone ;
}
2004-12-18 05:32:00 -08:00
SpriteCall . m_CellID = CellID ;
2004-12-15 13:24:46 -08:00
SpriteCall . m_Sprite = TextureName ;
2004-05-28 21:06:50 -07:00
m_YFrom = SpriteCall . m_Area . top - BufferZone ;
m_YTo = SpriteCall . m_Area . bottom + BufferZone ;
m_Indentation = Size . cx + BufferZone * 2 ;
}
} ;
2004-08-30 19:09:58 -07:00
SGUIText CGUI : : GenerateText ( const CGUIString & string ,
2004-09-02 22:48:47 -07:00
const CStr & Font , const float & Width , const float & BufferZone ,
2004-08-30 19:09:58 -07:00
const IGUIObject * pObject )
2004-05-28 21:06:50 -07:00
{
SGUIText Text ; // object we're generating
if ( string . m_Words . size ( ) = = 0 )
return Text ;
2004-09-02 22:48:47 -07:00
float x = BufferZone , y = BufferZone ; // drawing pointer
2004-05-28 21:06:50 -07:00
int from = 0 ;
bool done = false ;
2004-09-04 13:35:12 -07:00
bool FirstLine = true ; // Necessary because text in the first line is shorter
// (it doesn't count the line spacing)
2004-05-28 21:06:50 -07:00
// Images on the left or the right side.
2008-07-13 14:22:03 -07:00
std : : vector < SGenerateTextImage > Images [ 2 ] ;
2004-05-28 21:06:50 -07:00
int pos_last_img = - 1 ; // Position in the string where last img (either left or right) were encountered.
// in order to avoid duplicate processing.
// Easier to read.
bool WordWrapping = ( Width ! = 0 ) ;
// Go through string word by word
2004-05-29 04:59:59 -07:00
for ( int i = 0 ; i < ( int ) string . m_Words . size ( ) - 1 & & ! done ; + + i )
2004-05-28 21:06:50 -07:00
{
// Pre-process each line one time, so we know which floating images
// will be added for that line.
// Generated stuff is stored in Feedback.
CGUIString : : SFeedback Feedback ;
// Preliminary line_height, used for word-wrapping with floating images.
2004-09-02 22:48:47 -07:00
float prelim_line_height = 0.f ;
2004-05-28 21:06:50 -07:00
// Width and height of all text calls generated.
2004-08-30 19:09:58 -07:00
string . GenerateTextCall ( Feedback , Font ,
2004-09-04 13:35:12 -07:00
string . m_Words [ i ] , string . m_Words [ i + 1 ] ,
FirstLine ) ;
2004-05-28 21:06:50 -07:00
// Loop through our images queues, to see if images has been added.
// Check if this has already been processed.
// Also, floating images are only applicable if Word-Wrapping is on
if ( WordWrapping & & i > pos_last_img )
{
// Loop left/right
for ( int j = 0 ; j < 2 ; + + j )
{
2008-07-13 14:22:03 -07:00
for ( std : : vector < CStr > : : const_iterator it = Feedback . m_Images [ j ] . begin ( ) ;
2004-08-30 19:09:58 -07:00
it ! = Feedback . m_Images [ j ] . end ( ) ;
2004-05-28 21:06:50 -07:00
+ + it )
{
SGUIText : : SSpriteCall SpriteCall ;
SGenerateTextImage Image ;
// Y is if no other floating images is above, y. Else it is placed
// after the last image, like a stack downwards.
2004-09-02 22:48:47 -07:00
float _y ;
2004-05-28 21:06:50 -07:00
if ( Images [ j ] . size ( ) > 0 )
2007-05-09 14:01:11 -07:00
_y = std : : max ( y , Images [ j ] . back ( ) . m_YTo ) ;
2004-05-28 21:06:50 -07:00
else
_y = y ;
2004-08-30 19:09:58 -07:00
// Get Size from Icon database
SGUIIcon icon = GetIcon ( * it ) ;
CSize size = icon . m_Size ;
2005-07-24 17:52:03 -07:00
Image . SetupSpriteCall ( ( j = = CGUIString : : SFeedback : : Left ) , SpriteCall , Width , _y , size , icon . m_SpriteName , BufferZone , icon . m_CellID ) ;
2004-05-28 21:06:50 -07:00
// Check if image is the lowest thing.
2007-05-09 14:01:11 -07:00
Text . m_Size . cy = std : : max ( Text . m_Size . cy , Image . m_YTo ) ;
2004-05-28 21:06:50 -07:00
Images [ j ] . push_back ( Image ) ;
Text . m_SpriteCalls . push_back ( SpriteCall ) ;
}
}
}
2007-05-09 14:01:11 -07:00
pos_last_img = std : : max ( pos_last_img , i ) ;
2004-05-28 21:06:50 -07:00
x + = Feedback . m_Size . cx ;
2007-05-09 14:01:11 -07:00
prelim_line_height = std : : max ( prelim_line_height , Feedback . m_Size . cy ) ;
2004-05-28 21:06:50 -07:00
// If Width is 0, then there's no word-wrapping, disable NewLine.
2004-07-24 07:04:40 -07:00
if ( ( WordWrapping & & ( x > Width - BufferZone | | Feedback . m_NewLine ) ) | | i = = ( int ) string . m_Words . size ( ) - 2 )
2004-05-28 21:06:50 -07:00
{
2004-08-30 19:09:58 -07:00
// Change 'from' to 'i', but first keep a copy of its value.
2004-05-28 21:06:50 -07:00
int temp_from = from ;
from = i ;
static const int From = 0 , To = 1 ;
//int width_from=0, width_to=width;
2004-09-02 22:48:47 -07:00
float width_range [ 2 ] ;
2004-05-28 21:06:50 -07:00
width_range [ From ] = BufferZone ;
width_range [ To ] = Width - BufferZone ;
2004-08-30 19:09:58 -07:00
// Floating images are only applicable if word-wrapping is enabled.
2004-05-28 21:06:50 -07:00
if ( WordWrapping )
{
// Decide width of the line. We need to iterate our floating images.
// this won't be exact because we're assuming the line_height
// will be as our preliminary calculation said. But that may change,
// although we'd have to add a couple of more loops to try straightening
2004-12-21 05:37:24 -08:00
// this problem out, and it is very unlikely to happen noticeably if one
// structures his text in a stylistically pure fashion. Even if not, it
2004-05-28 21:06:50 -07:00
// is still quite unlikely it will happen.
// Loop through left and right side, from and to.
for ( int j = 0 ; j < 2 ; + + j )
{
2008-07-13 14:22:03 -07:00
for ( std : : vector < SGenerateTextImage > : : const_iterator it = Images [ j ] . begin ( ) ;
2004-05-28 21:06:50 -07:00
it ! = Images [ j ] . end ( ) ;
+ + it )
{
// We're working with two intervals here, the image's and the line height's.
// let's find the union of these two.
2004-09-02 22:48:47 -07:00
float union_from , union_to ;
2004-05-28 21:06:50 -07:00
2007-05-09 14:01:11 -07:00
union_from = std : : max ( y , it - > m_YFrom ) ;
union_to = std : : min ( y + prelim_line_height , it - > m_YTo ) ;
2004-05-28 21:06:50 -07:00
2004-07-31 06:37:35 -07:00
// The union is not empty
2004-05-28 21:06:50 -07:00
if ( union_to > union_from )
{
if ( j = = From )
2007-05-09 14:01:11 -07:00
width_range [ From ] = std : : max ( width_range [ From ] , it - > m_Indentation ) ;
2004-05-28 21:06:50 -07:00
else
2007-05-09 14:01:11 -07:00
width_range [ To ] = std : : min ( width_range [ To ] , Width - it - > m_Indentation ) ;
2004-05-28 21:06:50 -07:00
}
}
}
}
// Reset X for the next loop
x = width_range [ From ] ;
// Now we'll do another loop to figure out the height of
// the line (the height of the largest character). This
// couldn't be determined in the first loop (main loop)
// because it didn't regard images, so we don't know
// if all characters processed, will actually be involved
// in that line.
2004-09-02 22:48:47 -07:00
float line_height = 0.f ;
2004-05-28 21:06:50 -07:00
for ( int j = temp_from ; j < = i ; + + j )
{
// We don't want to use Feedback now, so we'll have to use
// another.
CGUIString : : SFeedback Feedback2 ;
2004-08-30 19:09:58 -07:00
// Don't attach object, it'll suppress the errors
// we want them to be reported in the final GenerateTextCall()
// so that we don't get duplicates.
string . GenerateTextCall ( Feedback2 , Font ,
2004-09-04 13:35:12 -07:00
string . m_Words [ j ] , string . m_Words [ j + 1 ] ,
FirstLine ) ;
2004-05-28 21:06:50 -07:00
// Append X value.
x + = Feedback2 . m_Size . cx ;
if ( WordWrapping & & x > width_range [ To ] & & j ! = temp_from & & ! Feedback2 . m_NewLine )
break ;
// Let line_height be the maximum m_Height we encounter.
2007-05-09 14:01:11 -07:00
line_height = std : : max ( line_height , Feedback2 . m_Size . cy ) ;
2004-05-28 21:06:50 -07:00
if ( WordWrapping & & Feedback2 . m_NewLine )
break ;
}
// Reset x once more
x = width_range [ From ] ;
2004-07-13 15:48:53 -07:00
// Move down, because font drawing starts from the baseline
y + = line_height ;
2004-05-28 21:06:50 -07:00
// Do the real processing now
for ( int j = temp_from ; j < = i ; + + j )
{
// We don't want to use Feedback now, so we'll have to use
2004-08-30 19:09:58 -07:00
// another one.
2004-05-28 21:06:50 -07:00
CGUIString : : SFeedback Feedback2 ;
// Defaults
2004-08-30 19:09:58 -07:00
string . GenerateTextCall ( Feedback2 , Font ,
string . m_Words [ j ] , string . m_Words [ j + 1 ] ,
2004-09-04 13:35:12 -07:00
FirstLine , pObject ) ;
2004-05-28 21:06:50 -07:00
// Iterate all and set X/Y values
// Since X values are not set, we need to make an internal
// iteration with an increment that will append the internal
// x, that is what x_pointer is for.
2004-09-02 22:48:47 -07:00
float x_pointer = 0.f ;
2004-05-28 21:06:50 -07:00
2008-07-13 14:22:03 -07:00
std : : vector < SGUIText : : STextCall > : : iterator it ;
2004-05-28 21:06:50 -07:00
for ( it = Feedback2 . m_TextCalls . begin ( ) ; it ! = Feedback2 . m_TextCalls . end ( ) ; + + it )
{
2004-07-31 06:37:35 -07:00
it - > m_Pos = CPos ( x + x_pointer , y ) ;
2004-05-28 21:06:50 -07:00
x_pointer + = it - > m_Size . cx ;
if ( it - > m_pSpriteCall )
{
2004-08-30 19:09:58 -07:00
it - > m_pSpriteCall - > m_Area + = it - > m_Pos - CSize ( 0 , it - > m_pSpriteCall - > m_Area . GetHeight ( ) ) ;
2004-05-28 21:06:50 -07:00
}
}
// Append X value.
x + = Feedback2 . m_Size . cx ;
2007-05-09 14:01:11 -07:00
Text . m_Size . cx = std : : max ( Text . m_Size . cx , x + BufferZone ) ;
2004-05-28 21:06:50 -07:00
2004-08-30 19:09:58 -07:00
// The first word overrides the width limit, what we
// do, in those cases, are just drawing that word even
2004-05-28 21:06:50 -07:00
// though it'll extend the object.
if ( WordWrapping ) // only if word-wrapping is applicable
{
if ( Feedback2 . m_NewLine )
{
from = j + 1 ;
2004-08-30 19:09:58 -07:00
// Sprite call can exist within only a newline segment,
// therefore we need this.
Text . m_SpriteCalls . insert ( Text . m_SpriteCalls . end ( ) , Feedback2 . m_SpriteCalls . begin ( ) , Feedback2 . m_SpriteCalls . end ( ) ) ;
2004-05-28 21:06:50 -07:00
break ;
}
else
if ( x > width_range [ To ] & & j = = temp_from )
{
from = j + 1 ;
// do not break, since we want it to be added to m_TextCalls
}
else
if ( x > width_range [ To ] )
{
from = j ;
break ;
}
}
// Add the whole Feedback2.m_TextCalls to our m_TextCalls.
Text . m_TextCalls . insert ( Text . m_TextCalls . end ( ) , Feedback2 . m_TextCalls . begin ( ) , Feedback2 . m_TextCalls . end ( ) ) ;
Text . m_SpriteCalls . insert ( Text . m_SpriteCalls . end ( ) , Feedback2 . m_SpriteCalls . begin ( ) , Feedback2 . m_SpriteCalls . end ( ) ) ;
2004-07-24 07:04:40 -07:00
if ( j = = ( int ) string . m_Words . size ( ) - 2 )
2004-05-28 21:06:50 -07:00
done = true ;
}
2004-08-30 19:09:58 -07:00
2004-07-13 15:48:53 -07:00
// Reset X
2004-09-02 22:48:47 -07:00
x = 0.f ;
2004-05-28 21:06:50 -07:00
// Update height of all
2007-05-09 14:01:11 -07:00
Text . m_Size . cy = std : : max ( Text . m_Size . cy , y + BufferZone ) ;
2004-05-28 21:06:50 -07:00
2004-09-04 13:35:12 -07:00
FirstLine = false ;
2004-05-28 21:06:50 -07:00
// Now if we entered as from = i, then we want
// i being one minus that, so that it will become
// the same i in the next loop. The difference is that
// we're on a new line now.
i = from - 1 ;
}
}
return Text ;
}
2004-12-15 13:24:46 -08:00
void CGUI : : DrawText ( SGUIText & Text , const CColor & DefaultColor ,
2005-07-23 17:01:41 -07:00
const CPos & pos , const float & z , const CRect & clipping )
2004-05-28 21:06:50 -07:00
{
2004-09-02 22:48:47 -07:00
// TODO Gee: All these really necessary? Some
2004-12-21 05:37:24 -08:00
// are defaults and if you changed them
2004-09-02 22:48:47 -07:00
// the opposite value at the end of the functions,
// some things won't be drawn correctly.
2004-07-13 15:48:53 -07:00
glEnable ( GL_TEXTURE_2D ) ;
glDisable ( GL_CULL_FACE ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
glEnable ( GL_BLEND ) ;
glDisable ( GL_ALPHA_TEST ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
2005-07-23 17:01:41 -07:00
if ( clipping ! = CRect ( ) )
{
double eq [ 4 ] [ 4 ] =
{
{ 0.0 , 1.0 , 0.0 , - clipping . top } ,
{ 1.0 , 0.0 , 0.0 , - clipping . left } ,
{ 0.0 , - 1.0 , 0.0 , clipping . bottom } ,
{ - 1.0 , 0.0 , 0.0 , clipping . right }
} ;
for ( int i = 0 ; i < 4 ; + + i )
{
glClipPlane ( GL_CLIP_PLANE0 + i , eq [ i ] ) ;
glEnable ( GL_CLIP_PLANE0 + i ) ;
}
}
2004-08-27 15:08:30 -07:00
CFont * font = NULL ;
2009-11-03 13:46:35 -08:00
CStrW LastFontName ;
2004-07-13 15:48:53 -07:00
2008-07-13 14:22:03 -07:00
for ( std : : vector < SGUIText : : STextCall > : : const_iterator it = Text . m_TextCalls . begin ( ) ;
2004-07-13 15:48:53 -07:00
it ! = Text . m_TextCalls . end ( ) ;
2004-05-28 21:06:50 -07:00
+ + it )
{
2004-08-30 19:09:58 -07:00
// If this is just a placeholder for a sprite call, continue
2004-05-28 21:06:50 -07:00
if ( it - > m_pSpriteCall )
continue ;
2004-07-13 15:48:53 -07:00
// Switch fonts when necessary, but remember the last one used
if ( it - > m_Font ! = LastFontName )
{
2004-08-27 15:08:30 -07:00
delete font ;
font = new CFont ( it - > m_Font ) ;
font - > Bind ( ) ;
2004-07-13 15:48:53 -07:00
LastFontName = it - > m_Font ;
}
CColor color = it - > m_UseCustomColor ? it - > m_Color : DefaultColor ;
glPushMatrix ( ) ;
2004-09-05 19:21:21 -07:00
// TODO Gee: (2004-09-04) Why are font corrupted if inputted float value?
2004-09-05 20:05:36 -07:00
glTranslatef ( ( GLfloat ) int ( pos . x + it - > m_Pos . x ) , ( GLfloat ) int ( pos . y + it - > m_Pos . y ) , z ) ;
2004-12-31 04:20:22 -08:00
glColor4fv ( color . FloatArray ( ) ) ;
2004-09-06 05:54:35 -07:00
glwprintf ( L " %ls " , it - > m_String . c_str ( ) ) ; // "%ls" is necessary in case m_String contains % symbols
2004-07-13 15:48:53 -07:00
glPopMatrix ( ) ;
2004-05-28 21:06:50 -07:00
}
2005-02-04 23:25:16 -08:00
if ( font )
delete font ;
2004-07-13 15:48:53 -07:00
2008-07-13 14:22:03 -07:00
for ( std : : list < SGUIText : : SSpriteCall > : : iterator it = Text . m_SpriteCalls . begin ( ) ;
2004-05-28 21:06:50 -07:00
it ! = Text . m_SpriteCalls . end ( ) ;
+ + it )
{
2004-12-18 05:32:00 -08:00
DrawSprite ( it - > m_Sprite , it - > m_CellID , z , it - > m_Area + pos ) ;
2004-05-28 21:06:50 -07:00
}
2004-09-02 22:48:47 -07:00
// TODO To whom it may concern: Thing were not reset, so
// I added this line, modify if incorrect --
2005-07-24 01:29:02 -07:00
if ( clipping ! = CRect ( ) )
{
for ( int i = 0 ; i < 4 ; + + i )
glDisable ( GL_CLIP_PLANE0 + i ) ;
}
2004-09-02 22:48:47 -07:00
glDisable ( GL_TEXTURE_2D ) ;
// -- GL
2003-11-03 08:22:45 -08:00
}
2006-07-20 07:37:58 -07:00
bool CGUI : : GetPreDefinedColor ( const CStr & name , CColor & Output )
2005-07-25 12:06:18 -07:00
{
if ( m_PreDefinedColors . count ( name ) = = 0 )
{
return false ;
}
else
{
Output = m_PreDefinedColors [ name ] ;
return true ;
}
}
2003-11-23 18:18:41 -08:00
/**
* @ callgraph
*/
2009-12-03 12:17:22 -08:00
void CGUI : : LoadXmlFile ( const VfsPath & Filename , std : : set < VfsPath > & Paths )
2003-11-03 08:22:45 -08:00
{
2009-12-03 12:17:22 -08:00
Paths . insert ( Filename ) ;
2003-11-03 08:22:45 -08:00
2004-07-08 08:23:47 -07:00
CXeromyces XeroFile ;
2010-07-04 03:15:53 -07:00
if ( XeroFile . Load ( g_VFS , Filename ) ! = PSRETURN_OK )
2004-07-15 12:10:33 -07:00
// Fail silently
2004-07-11 09:22:35 -07:00
return ;
2003-11-03 08:22:45 -08:00
2007-05-02 05:07:08 -07:00
XMBElement node = XeroFile . GetRoot ( ) ;
2003-11-24 18:47:12 -08:00
2004-07-08 08:23:47 -07:00
// Check root element's (node) name so we know what kind of
// data we'll be expecting
2007-05-02 05:07:08 -07:00
CStr root_name ( XeroFile . GetElementString ( node . GetNodeName ( ) ) ) ;
2004-06-13 16:36:16 -07:00
2004-07-17 10:09:33 -07:00
try
2004-07-08 08:23:47 -07:00
{
2004-10-14 03:09:26 -07:00
2004-07-17 10:09:33 -07:00
if ( root_name = = " objects " )
{
2009-12-03 12:17:22 -08:00
Xeromyces_ReadRootObjects ( node , & XeroFile , Paths ) ;
2004-07-17 10:09:33 -07:00
// Re-cache all values so these gets cached too.
//UpdateResolution();
}
else
if ( root_name = = " sprites " )
{
Xeromyces_ReadRootSprites ( node , & XeroFile ) ;
}
else
if ( root_name = = " styles " )
{
Xeromyces_ReadRootStyles ( node , & XeroFile ) ;
}
else
if ( root_name = = " setup " )
{
Xeromyces_ReadRootSetup ( node , & XeroFile ) ;
}
else
{
2009-11-03 13:46:35 -08:00
debug_warn ( L " CGUI::LoadXmlFile error " ) ;
2004-07-17 10:09:33 -07:00
// TODO Gee: Output in log
}
2004-07-08 08:23:47 -07:00
}
2005-05-23 17:00:40 -07:00
catch ( PSERROR_GUI & e )
2004-07-08 08:23:47 -07:00
{
2009-11-03 13:46:35 -08:00
LOG ( CLogger : : Error , LOG_CATEGORY , L " Errors loading GUI file %ls (%d) " , Filename . string ( ) . c_str ( ) , e . getCode ( ) ) ;
2004-07-17 10:09:33 -07:00
return ;
2004-07-08 08:23:47 -07:00
}
2003-11-03 08:22:45 -08:00
}
//===================================================================
2004-07-08 08:23:47 -07:00
// XML Reading Xeromyces Specific Sub-Routines
2003-11-03 08:22:45 -08:00
//===================================================================
2009-12-03 12:17:22 -08:00
void CGUI : : Xeromyces_ReadRootObjects ( XMBElement Element , CXeromyces * pFile , std : : set < VfsPath > & Paths )
2003-11-03 08:22:45 -08:00
{
2007-05-02 05:07:08 -07:00
int el_script = pFile - > GetElementID ( " script " ) ;
2004-07-11 09:22:35 -07:00
2010-02-28 13:36:25 -08:00
std : : vector < std : : pair < CStr , CStr > > subst ;
2003-11-03 08:22:45 -08:00
// Iterate main children
2004-07-11 09:22:35 -07:00
// they should all be <object> or <script> elements
2007-05-02 05:07:08 -07:00
XMBElementList children = Element . GetChildNodes ( ) ;
2004-07-08 08:23:47 -07:00
for ( int i = 0 ; i < children . Count ; + + i )
2003-11-03 08:22:45 -08:00
{
2009-11-03 13:46:35 -08:00
//debug_printf(L"Object %d\n", i);
2007-05-02 05:07:08 -07:00
XMBElement child = children . Item ( i ) ;
2003-11-03 08:22:45 -08:00
2007-05-02 05:07:08 -07:00
if ( child . GetNodeName ( ) = = el_script )
2004-07-11 09:22:35 -07:00
// Execute the inline script
2009-12-03 12:17:22 -08:00
Xeromyces_ReadScript ( child , pFile , Paths ) ;
2004-07-11 09:22:35 -07:00
else
// Read in this whole object into the GUI
2010-02-28 13:36:25 -08:00
Xeromyces_ReadObject ( child , pFile , m_BaseObject , subst , Paths ) ;
2003-11-03 08:22:45 -08:00
}
}
2004-07-08 08:23:47 -07:00
void CGUI : : Xeromyces_ReadRootSprites ( XMBElement Element , CXeromyces * pFile )
2003-11-03 08:22:45 -08:00
{
// Iterate main children
// they should all be <sprite> elements
2007-05-02 05:07:08 -07:00
XMBElementList children = Element . GetChildNodes ( ) ;
2004-07-08 08:23:47 -07:00
for ( int i = 0 ; i < children . Count ; + + i )
2003-11-03 08:22:45 -08:00
{
2007-05-02 05:07:08 -07:00
XMBElement child = children . Item ( i ) ;
2003-11-03 08:22:45 -08:00
2004-07-08 08:23:47 -07:00
// Read in this whole object into the GUI
Xeromyces_ReadSprite ( child , pFile ) ;
2003-11-03 08:22:45 -08:00
}
}
2004-07-08 08:23:47 -07:00
void CGUI : : Xeromyces_ReadRootStyles ( XMBElement Element , CXeromyces * pFile )
2003-11-30 23:06:55 -08:00
{
// Iterate main children
// they should all be <styles> elements
2007-05-02 05:07:08 -07:00
XMBElementList children = Element . GetChildNodes ( ) ;
2004-07-08 08:23:47 -07:00
for ( int i = 0 ; i < children . Count ; + + i )
2003-11-30 23:06:55 -08:00
{
2007-05-02 05:07:08 -07:00
XMBElement child = children . Item ( i ) ;
2003-11-30 23:06:55 -08:00
2004-07-08 08:23:47 -07:00
// Read in this whole object into the GUI
Xeromyces_ReadStyle ( child , pFile ) ;
2003-11-30 23:06:55 -08:00
}
}
2004-07-08 08:23:47 -07:00
void CGUI : : Xeromyces_ReadRootSetup ( XMBElement Element , CXeromyces * pFile )
2003-12-26 22:26:03 -08:00
{
// Iterate main children
// they should all be <icon>, <scrollbar> or <tooltip>.
2007-05-02 05:07:08 -07:00
XMBElementList children = Element . GetChildNodes ( ) ;
2004-07-08 08:23:47 -07:00
for ( int i = 0 ; i < children . Count ; + + i )
2003-12-26 22:26:03 -08:00
{
2007-05-02 05:07:08 -07:00
XMBElement child = children . Item ( i ) ;
2003-12-26 22:26:03 -08:00
2004-07-08 08:23:47 -07:00
// Read in this whole object into the GUI
2003-12-26 22:26:03 -08:00
2007-05-02 05:07:08 -07:00
CStr name ( pFile - > GetElementString ( child . GetNodeName ( ) ) ) ;
2003-12-26 22:26:03 -08:00
2004-07-10 13:33:42 -07:00
if ( name = = " scrollbar " )
2004-07-08 08:23:47 -07:00
{
Xeromyces_ReadScrollBarStyle ( child , pFile ) ;
2003-12-26 22:26:03 -08:00
}
2004-08-30 19:09:58 -07:00
else
if ( name = = " icon " )
{
Xeromyces_ReadIcon ( child , pFile ) ;
}
2004-12-21 05:37:24 -08:00
else
if ( name = = " tooltip " )
{
Xeromyces_ReadTooltip ( child , pFile ) ;
}
else
2005-07-25 12:06:18 -07:00
if ( name = = " color " )
{
Xeromyces_ReadColor ( child , pFile ) ;
}
else
2004-12-21 05:37:24 -08:00
{
2009-11-03 13:46:35 -08:00
debug_warn ( L " Invalid data - DTD shouldn't allow this " ) ;
2004-12-21 05:37:24 -08:00
}
2003-12-26 22:26:03 -08:00
}
}
2010-02-28 13:36:25 -08:00
void CGUI : : Xeromyces_ReadObject ( XMBElement Element , CXeromyces * pFile , IGUIObject * pParent , const std : : vector < std : : pair < CStr , CStr > > & NameSubst , std : : set < VfsPath > & Paths )
2003-11-03 08:22:45 -08:00
{
2005-06-27 21:06:25 -07:00
debug_assert ( pParent ) ;
2004-07-08 08:23:47 -07:00
int i ;
2003-11-03 08:22:45 -08:00
// Our object we are going to create
2003-11-23 18:18:41 -08:00
IGUIObject * object = NULL ;
2003-11-03 08:22:45 -08:00
2007-05-02 05:07:08 -07:00
XMBAttributeList attributes = Element . GetAttributes ( ) ;
2004-07-08 08:23:47 -07:00
2003-11-03 08:22:45 -08:00
// Well first of all we need to determine the type
2007-05-02 05:07:08 -07:00
CStr type ( attributes . GetNamedItem ( pFile - > GetAttributeID ( " type " ) ) ) ;
2009-03-23 14:35:26 -07:00
if ( type . empty ( ) )
type = " empty " ;
2003-11-03 08:22:45 -08:00
// Construct object from specified type
// henceforth, we need to do a rollback before aborting.
// i.e. releasing this object
2004-10-31 14:00:01 -08:00
object = ConstructObject ( type ) ;
2003-11-03 08:22:45 -08:00
if ( ! object )
{
// Report error that object was unsuccessfully loaded
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Unrecognized object type \" %hs \" " , type . c_str ( ) ) ;
2003-11-03 08:22:45 -08:00
return ;
}
2004-07-08 08:23:47 -07:00
// Cache some IDs for element attribute names, to avoid string comparisons
2007-05-02 05:07:08 -07:00
# define ELMT(x) int elmt_##x = pFile->GetElementID(#x)
# define ATTR(x) int attr_##x = pFile->GetAttributeID(#x)
2004-07-08 08:23:47 -07:00
ELMT ( object ) ;
ELMT ( action ) ;
2010-02-28 13:36:25 -08:00
ELMT ( repeat ) ;
2004-07-08 08:23:47 -07:00
ATTR ( style ) ;
ATTR ( type ) ;
ATTR ( name ) ;
2004-07-22 09:18:12 -07:00
ATTR ( hotkey ) ;
2004-07-08 08:23:47 -07:00
ATTR ( z ) ;
ATTR ( on ) ;
2004-07-11 09:22:35 -07:00
ATTR ( file ) ;
2004-07-08 08:23:47 -07:00
2003-11-30 23:06:55 -08:00
//
// Read Style and set defaults
//
2003-12-26 22:26:03 -08:00
// If the setting "style" is set, try loading that setting.
//
// Always load default (if it's available) first!
//
2007-05-02 05:07:08 -07:00
CStr argStyle ( attributes . GetNamedItem ( attr_style ) ) ;
2003-11-30 23:06:55 -08:00
2004-12-21 05:37:24 -08:00
if ( m_Styles . count ( " default " ) = = 1 )
object - > LoadStyle ( * this , " default " ) ;
2003-12-26 22:26:03 -08:00
2007-02-01 06:46:14 -08:00
if ( ! argStyle . empty ( ) )
2003-11-30 23:06:55 -08:00
{
2003-12-26 22:26:03 -08:00
// additional check
2003-11-30 23:06:55 -08:00
if ( m_Styles . count ( argStyle ) = = 0 )
{
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Trying to use style '%hs' that doesn't exist. " , argStyle . c_str ( ) ) ;
2003-11-30 23:06:55 -08:00
}
2003-12-26 22:26:03 -08:00
else object - > LoadStyle ( * this , argStyle ) ;
2003-11-30 23:06:55 -08:00
}
2003-12-26 22:26:03 -08:00
2003-11-03 08:22:45 -08:00
//
// Read Attributes
//
bool NameSet = false ;
2003-12-26 22:26:03 -08:00
bool ManuallySetZ = false ; // if z has been manually set, this turn true
2003-11-03 08:22:45 -08:00
2004-10-31 14:00:01 -08:00
CStr hotkeyTag ;
2004-07-22 09:18:12 -07:00
2003-11-03 08:22:45 -08:00
// Now we can iterate all attributes and store
2004-07-08 08:23:47 -07:00
for ( i = 0 ; i < attributes . Count ; + + i )
2003-11-03 08:22:45 -08:00
{
2007-05-02 05:07:08 -07:00
XMBAttribute attr = attributes . Item ( i ) ;
2003-11-03 08:22:45 -08:00
2004-05-28 21:06:50 -07:00
// If value is "null", then it is equivalent as never being entered
2009-11-03 13:46:35 -08:00
if ( CStr ( attr . Value ) = = " null " )
2004-05-28 21:06:50 -07:00
continue ;
2003-11-30 23:06:55 -08:00
// Ignore "type" and "style", we've already checked it
2004-07-17 10:09:33 -07:00
if ( attr . Name = = attr_type | | attr . Name = = attr_style )
2003-11-03 08:22:45 -08:00
continue ;
// Also the name needs some special attention
2004-07-08 08:23:47 -07:00
if ( attr . Name = = attr_name )
2003-11-03 08:22:45 -08:00
{
2010-02-28 13:36:25 -08:00
CStr name ( attr . Value ) ;
// Apply the requested substitutions
for ( size_t j = 0 ; j < NameSubst . size ( ) ; + + j )
name . Replace ( NameSubst [ j ] . first , NameSubst [ j ] . second ) ;
object - > SetName ( name ) ;
2003-11-03 08:22:45 -08:00
NameSet = true ;
continue ;
}
2004-07-22 09:18:12 -07:00
// Wire up the hotkey tag, if it has one
2004-10-31 14:00:01 -08:00
if ( attr . Name = = attr_hotkey )
2004-07-22 09:18:12 -07:00
hotkeyTag = attr . Value ;
2004-07-08 08:23:47 -07:00
if ( attr . Name = = attr_z )
2003-12-26 22:26:03 -08:00
ManuallySetZ = true ;
2003-11-03 08:22:45 -08:00
// Try setting the value
2010-05-30 06:11:32 -07:00
if ( object - > SetSetting ( pFile - > GetAttributeString ( attr . Name ) , CStrW ( attr . Value ) , true ) ! = PSRETURN_OK )
2003-11-03 08:22:45 -08:00
{
2009-12-03 12:17:22 -08:00
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 ( ) ) ;
2003-11-03 08:22:45 -08:00
// This is not a fatal error
}
}
2004-05-28 21:06:50 -07:00
// Check if name isn't set, generate an internal name in that case.
2003-11-03 08:22:45 -08:00
if ( ! NameSet )
{
2004-05-28 21:06:50 -07:00
object - > SetName ( CStr ( " __internal( " ) + CStr ( m_InternalNameNumber ) + CStr ( " ) " ) ) ;
+ + m_InternalNameNumber ;
2003-11-03 08:22:45 -08:00
}
2004-07-22 09:18:12 -07:00
// Attempt to register the hotkey tag, if one was provided
2007-02-01 06:46:14 -08:00
if ( ! hotkeyTag . empty ( ) )
2007-05-02 05:07:08 -07:00
HotkeyRegisterGuiObject ( object - > GetName ( ) , hotkeyTag ) ;
2004-07-08 08:23:47 -07:00
2007-05-02 05:07:08 -07:00
CStrW caption ( Element . GetText ( ) ) ;
2007-02-01 06:46:14 -08:00
if ( ! caption . empty ( ) )
2004-07-08 08:23:47 -07:00
{
2004-12-13 04:07:12 -08:00
// Set the setting caption to this
2005-02-04 23:25:16 -08:00
object - > SetSetting ( " caption " , caption , true ) ;
2004-12-13 04:07:12 -08:00
// There is no harm if the object didn't have a "caption"
2004-07-08 08:23:47 -07:00
}
2003-11-03 08:22:45 -08:00
//
// Read Children
//
// Iterate children
2007-05-02 05:07:08 -07:00
XMBElementList children = Element . GetChildNodes ( ) ;
2003-11-03 08:22:45 -08:00
2004-07-08 08:23:47 -07:00
for ( i = 0 ; i < children . Count ; + + i )
2003-11-03 08:22:45 -08:00
{
// Get node
2007-05-02 05:07:08 -07:00
XMBElement child = children . Item ( i ) ;
2003-11-03 08:22:45 -08:00
2004-07-08 08:23:47 -07:00
// Check what name the elements got
2007-05-02 05:07:08 -07:00
int element_name = child . GetNodeName ( ) ;
2003-11-03 08:22:45 -08:00
2004-07-08 08:23:47 -07:00
if ( element_name = = elmt_object )
{
// Call this function on the child
2010-02-28 13:36:25 -08:00
Xeromyces_ReadObject ( child , pFile , object , NameSubst , Paths ) ;
2003-11-03 08:22:45 -08:00
}
2004-07-08 08:23:47 -07:00
else if ( element_name = = elmt_action )
2003-11-03 08:22:45 -08:00
{
2004-07-11 09:22:35 -07:00
// Scripted <action> element
// Check for a 'file' parameter
2009-11-03 13:46:35 -08:00
CStrW filename ( child . GetAttributes ( ) . GetNamedItem ( attr_file ) ) ;
2004-07-11 09:22:35 -07:00
CStr code ;
// If there is a file, open it and use it as the code
2009-11-03 13:46:35 -08:00
if ( ! filename . empty ( ) )
2004-07-11 09:22:35 -07:00
{
2009-12-03 12:17:22 -08:00
Paths . insert ( filename ) ;
2004-07-29 09:17:21 -07:00
CVFSFile scriptfile ;
2010-07-04 03:15:53 -07:00
if ( scriptfile . Load ( g_VFS , filename ) ! = PSRETURN_OK )
2004-07-11 09:22:35 -07:00
{
2009-12-03 12:17:22 -08:00
LOGERROR ( L " Error opening GUI script action file '%ls' " , filename . c_str ( ) ) ;
2004-07-17 10:09:33 -07:00
throw PSERROR_GUI_JSOpenFailed ( ) ;
}
2004-07-11 09:22:35 -07:00
2004-07-29 09:17:21 -07:00
code = scriptfile . GetAsString ( ) ;
2004-07-11 09:22:35 -07:00
}
// Read the inline code (concatenating to the file code, if both are specified)
2009-11-03 13:46:35 -08:00
code + = CStr ( child . GetText ( ) ) ;
2004-07-11 09:22:35 -07:00
2009-11-03 13:46:35 -08:00
CStr action = CStr ( child . GetAttributes ( ) . GetNamedItem ( attr_on ) ) ;
2004-07-11 09:22:35 -07:00
object - > RegisterScriptHandler ( action . LowerCase ( ) , code , this ) ;
2003-11-03 08:22:45 -08:00
}
2010-02-28 13:36:25 -08:00
else if ( element_name = = elmt_repeat )
{
Xeromyces_ReadRepeat ( child , pFile , object , Paths ) ;
}
2005-04-07 02:13:10 -07:00
else
{
// Try making the object read the tag.
if ( ! object - > HandleAdditionalChildren ( child , pFile ) )
{
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: (object: %hs) Reading unknown children for its type " , object - > GetPresentableName ( ) . c_str ( ) ) ;
2005-04-07 02:13:10 -07:00
}
}
2003-11-30 23:06:55 -08:00
}
2003-11-03 08:22:45 -08:00
2003-12-26 22:26:03 -08:00
//
// Check if Z wasn't manually set
//
if ( ! ManuallySetZ )
{
// Set it automatically to 10 plus its parents
2009-12-03 12:17:22 -08:00
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 )
2003-12-26 22:26:03 -08:00
{
2009-12-03 12:17:22 -08:00
GUI < float > : : SetSetting ( object , " z " , pParent - > GetBufferedZ ( ) + 10.f , true ) ;
2003-12-26 22:26:03 -08:00
}
else
2009-12-03 12:17:22 -08:00
// If the object is relative, then we'll just store Z as "10"
2003-12-26 22:26:03 -08:00
{
2009-12-03 12:17:22 -08:00
GUI < float > : : SetSetting ( object , " z " , 10.f , true ) ;
2003-12-26 22:26:03 -08:00
}
}
2003-11-03 08:22:45 -08:00
//
// Input Child
//
try
{
if ( pParent = = m_BaseObject )
AddObject ( object ) ;
else
pParent - > AddChild ( object ) ;
}
2009-09-27 08:04:46 -07:00
catch ( PSERROR_GUI & e )
2009-11-03 13:46:35 -08:00
{
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI error: %hs " , e . what ( ) ) ;
2003-11-03 08:22:45 -08:00
}
}
2010-02-28 13:36:25 -08:00
void CGUI : : Xeromyces_ReadRepeat ( XMBElement Element , CXeromyces * pFile , IGUIObject * pParent , std : : set < VfsPath > & Paths )
{
# define ELMT(x) int elmt_##x = pFile->GetElementID(#x)
# define ATTR(x) int attr_##x = pFile->GetAttributeID(#x)
ELMT ( object ) ;
ATTR ( count ) ;
XMBAttributeList attributes = Element . GetAttributes ( ) ;
int count = CStr ( attributes . GetNamedItem ( attr_count ) ) . ToInt ( ) ;
for ( int n = 0 ; n < count ; + + n )
{
std : : vector < std : : pair < CStr , CStr > > subst ;
subst . push_back ( std : : make_pair ( CStr ( " [n] " ) , " [ " + CStr ( n ) + " ] " ) ) ;
XERO_ITER_EL ( Element , child )
{
if ( child . GetNodeName ( ) = = elmt_object )
{
Xeromyces_ReadObject ( child , pFile , pParent , subst , Paths ) ;
}
}
}
}
2009-12-03 12:17:22 -08:00
void CGUI : : Xeromyces_ReadScript ( XMBElement Element , CXeromyces * pFile , std : : set < VfsPath > & Paths )
2004-07-11 09:22:35 -07:00
{
// Check for a 'file' parameter
2009-12-03 12:17:22 -08:00
CStrW file ( Element . GetAttributes ( ) . GetNamedItem ( pFile - > GetAttributeID ( " file " ) ) ) ;
2004-07-11 09:22:35 -07:00
2004-07-11 11:18:54 -07:00
// If there is a file specified, open and execute it
2007-02-01 06:46:14 -08:00
if ( ! file . empty ( ) )
2009-12-03 12:17:22 -08:00
{
Paths . insert ( file ) ;
2010-01-24 09:24:35 -08:00
try
{
g_ScriptingHost . RunScript ( file , m_ScriptObject ) ;
}
catch ( PSERROR_Scripting & e )
{
LOGERROR ( L " GUI: Error executing script %ls: %hs " , file . c_str ( ) , e . what ( ) ) ;
}
2009-12-03 12:17:22 -08:00
}
2004-07-11 09:22:35 -07:00
// Execute inline scripts
2010-01-24 09:24:35 -08:00
try
{
CStr code ( Element . GetText ( ) ) ;
if ( ! code . empty ( ) )
g_ScriptingHost . RunMemScript ( code . c_str ( ) , code . length ( ) , " Some XML file " , Element . GetLineNumber ( ) , m_ScriptObject ) ;
}
catch ( PSERROR_Scripting & e )
{
LOGERROR ( L " GUI: Error executing inline script: %hs " , e . what ( ) ) ;
}
2004-07-11 09:22:35 -07:00
}
2004-07-08 08:23:47 -07:00
void CGUI : : Xeromyces_ReadSprite ( XMBElement Element , CXeromyces * pFile )
2003-11-03 08:22:45 -08:00
{
// Sprite object we're adding
CGUISprite sprite ;
// and what will be its reference name
CStr name ;
//
// Read Attributes
//
// Get name, we know it exists because of DTD requirements
2007-05-02 05:07:08 -07:00
name = Element . GetAttributes ( ) . GetNamedItem ( pFile - > GetAttributeID ( " name " ) ) ;
2003-11-03 08:22:45 -08:00
2004-12-21 05:37:24 -08:00
if ( m_Sprites . find ( name ) ! = m_Sprites . end ( ) )
2009-12-03 12:17:22 -08:00
LOGWARNING ( L " GUI sprite name '%hs' used more than once; first definition will be discarded " , name . c_str ( ) ) ;
2004-12-21 05:37:24 -08:00
2003-11-03 08:22:45 -08:00
//
// Read Children (the images)
//
2004-12-18 05:32:00 -08:00
SGUIImageEffects * effects = NULL ;
2003-11-03 08:22:45 -08:00
// Iterate children
2007-05-02 05:07:08 -07:00
XMBElementList children = Element . GetChildNodes ( ) ;
2003-11-03 08:22:45 -08:00
2004-07-08 08:23:47 -07:00
for ( int i = 0 ; i < children . Count ; + + i )
2003-11-03 08:22:45 -08:00
{
// Get node
2007-05-02 05:07:08 -07:00
XMBElement child = children . Item ( i ) ;
2003-11-03 08:22:45 -08:00
2007-05-02 05:07:08 -07:00
CStr ElementName ( pFile - > GetElementString ( child . GetNodeName ( ) ) ) ;
2003-11-03 08:22:45 -08:00
2004-12-18 05:32:00 -08:00
if ( ElementName = = " image " )
{
Xeromyces_ReadImage ( child , pFile , sprite ) ;
}
else if ( ElementName = = " effect " )
{
2009-12-03 12:17:22 -08:00
if ( effects )
{
LOGERROR ( L " GUI <sprite> must not have more than one <effect> " ) ;
}
else
{
effects = new SGUIImageEffects ;
Xeromyces_ReadEffects ( child , pFile , * effects ) ;
}
2004-12-18 05:32:00 -08:00
}
else
{
2009-11-03 13:46:35 -08:00
debug_warn ( L " Invalid data - DTD shouldn't allow this " ) ;
2004-12-18 05:32:00 -08:00
}
2003-11-03 08:22:45 -08:00
}
2004-12-18 05:32:00 -08:00
// Apply the effects to every image (unless the image overrides it with
// different effects)
if ( effects )
for ( std : : vector < SGUIImage > : : iterator it = sprite . m_Images . begin ( ) ; it ! = sprite . m_Images . end ( ) ; + + it )
if ( ! it - > m_Effects )
it - > m_Effects = new SGUIImageEffects ( * effects ) ; // do a copy just so it can be deleted correctly later
delete effects ;
2003-11-03 08:22:45 -08:00
//
// Add Sprite
//
m_Sprites [ name ] = sprite ;
}
2004-07-08 08:23:47 -07:00
void CGUI : : Xeromyces_ReadImage ( XMBElement Element , CXeromyces * pFile , CGUISprite & parent )
2003-11-03 08:22:45 -08:00
{
// Image object we're adding
SGUIImage image ;
2009-12-03 12:17:22 -08:00
// 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 ) ) ;
2004-07-13 15:48:53 -07:00
2003-12-26 22:26:03 -08:00
// TODO Gee: Setup defaults here (or maybe they are in the SGUIImage ctor)
2003-11-03 08:22:45 -08:00
//
// Read Attributes
//
// Now we can iterate all attributes and store
2007-05-02 05:07:08 -07:00
XMBAttributeList attributes = Element . GetAttributes ( ) ;
2004-07-08 08:23:47 -07:00
for ( int i = 0 ; i < attributes . Count ; + + i )
2003-11-03 08:22:45 -08:00
{
2007-05-02 05:07:08 -07:00
XMBAttribute attr = attributes . Item ( i ) ;
CStr attr_name ( pFile - > GetAttributeString ( attr . Name ) ) ;
2004-07-10 13:56:15 -07:00
CStr attr_value ( attr . Value ) ;
2003-11-03 08:22:45 -08:00
2004-07-10 13:33:42 -07:00
if ( attr_name = = " texture " )
2003-11-03 08:22:45 -08:00
{
2009-11-09 12:53:48 -08:00
image . m_TextureName = VfsPath ( L " art/textures/ui " ) / wstring_from_utf8 ( attr_value ) ;
2003-11-03 08:22:45 -08:00
}
else
2004-07-10 13:33:42 -07:00
if ( attr_name = = " size " )
2003-11-03 08:22:45 -08:00
{
2003-11-30 23:06:55 -08:00
CClientArea ca ;
if ( ! GUI < CClientArea > : : ParseString ( attr_value , ca ) )
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Error parsing '%hs' ( \" %hs \" ) " , attr_name . c_str ( ) , attr_value . c_str ( ) ) ;
2003-11-30 23:06:55 -08:00
else image . m_Size = ca ;
}
else
2005-01-01 04:06:17 -08:00
if ( attr_name = = " texture_size " )
2004-07-13 15:48:53 -07:00
{
CClientArea ca ;
if ( ! GUI < CClientArea > : : ParseString ( attr_value , ca ) )
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Error parsing '%hs' ( \" %hs \" ) " , attr_name . c_str ( ) , attr_value . c_str ( ) ) ;
2004-07-13 15:48:53 -07:00
else image . m_TextureSize = ca ;
}
else
2005-01-01 04:06:17 -08:00
if ( attr_name = = " real_texture_placement " )
2004-09-01 20:02:32 -07:00
{
CRect rect ;
if ( ! GUI < CRect > : : ParseString ( attr_value , rect ) )
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Error parsing '%hs' ( \" %hs \" ) " , attr_name . c_str ( ) , attr_value . c_str ( ) ) ;
2004-09-01 20:02:32 -07:00
else image . m_TexturePlacementInFile = rect ;
}
else
2005-01-01 04:06:17 -08:00
if ( attr_name = = " cell_size " )
2004-12-17 08:20:08 -08:00
{
CSize size ;
if ( ! GUI < CSize > : : ParseString ( attr_value , size ) )
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Error parsing '%hs' ( \" %hs \" ) " , attr_name . c_str ( ) , attr_value . c_str ( ) ) ;
2004-12-18 05:32:00 -08:00
else image . m_CellSize = size ;
2004-12-17 08:20:08 -08:00
}
else
2005-01-01 04:06:17 -08:00
if ( attr_name = = " z_level " )
2004-05-28 21:06:50 -07:00
{
2004-09-02 22:48:47 -07:00
float z_level ;
if ( ! GUI < float > : : ParseString ( attr_value , z_level ) )
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Error parsing '%hs' ( \" %hs \" ) " , attr_name . c_str ( ) , attr_value . c_str ( ) ) ;
2004-09-02 22:48:47 -07:00
else image . m_DeltaZ = z_level / 100.f ;
2004-05-28 21:06:50 -07:00
}
else
2004-07-10 13:33:42 -07:00
if ( attr_name = = " backcolor " )
2003-11-30 23:06:55 -08:00
{
CColor color ;
if ( ! GUI < CColor > : : ParseString ( attr_value , color ) )
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Error parsing '%hs' ( \" %hs \" ) " , attr_name . c_str ( ) , attr_value . c_str ( ) ) ;
2003-11-30 23:06:55 -08:00
else image . m_BackColor = color ;
}
2004-09-05 19:21:21 -07:00
else
if ( attr_name = = " bordercolor " )
{
CColor color ;
if ( ! GUI < CColor > : : ParseString ( attr_value , color ) )
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Error parsing '%hs' ( \" %hs \" ) " , attr_name . c_str ( ) , attr_value . c_str ( ) ) ;
2004-09-05 19:21:21 -07:00
else image . m_BorderColor = color ;
}
else
if ( attr_name = = " border " )
{
bool b ;
if ( ! GUI < bool > : : ParseString ( attr_value , b ) )
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Error parsing '%hs' ( \" %hs \" ) " , attr_name . c_str ( ) , attr_value . c_str ( ) ) ;
2004-09-05 19:21:21 -07:00
else image . m_Border = b ;
}
2004-12-18 05:32:00 -08:00
else
{
2009-11-03 13:46:35 -08:00
debug_warn ( L " Invalid data - DTD shouldn't allow this " ) ;
2004-12-18 05:32:00 -08:00
}
}
// Look for effects
2007-05-02 05:07:08 -07:00
XMBElementList children = Element . GetChildNodes ( ) ;
2004-12-18 05:32:00 -08:00
for ( int i = 0 ; i < children . Count ; + + i )
{
2007-05-02 05:07:08 -07:00
XMBElement child = children . Item ( i ) ;
CStr ElementName ( pFile - > GetElementString ( child . GetNodeName ( ) ) ) ;
2004-12-18 05:32:00 -08:00
if ( ElementName = = " effect " )
{
2009-12-03 12:17:22 -08:00
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 ) ;
}
2004-12-18 05:32:00 -08:00
}
else
{
2009-11-03 13:46:35 -08:00
debug_warn ( L " Invalid data - DTD shouldn't allow this " ) ;
2004-12-18 05:32:00 -08:00
}
2003-11-03 08:22:45 -08:00
}
2003-11-30 23:06:55 -08:00
2003-11-03 08:22:45 -08:00
//
// Input
//
parent . AddImage ( image ) ;
}
2003-11-30 23:06:55 -08:00
2004-12-18 05:32:00 -08:00
void CGUI : : Xeromyces_ReadEffects ( XMBElement Element , CXeromyces * pFile , SGUIImageEffects & effects )
{
2007-05-02 05:07:08 -07:00
XMBAttributeList attributes = Element . GetAttributes ( ) ;
2004-12-18 05:32:00 -08:00
for ( int i = 0 ; i < attributes . Count ; + + i )
{
2007-05-02 05:07:08 -07:00
XMBAttribute attr = attributes . Item ( i ) ;
CStr attr_name ( pFile - > GetAttributeString ( attr . Name ) ) ;
2004-12-18 05:32:00 -08:00
CStr attr_value ( attr . Value ) ;
2005-01-03 14:23:27 -08:00
# define COLOR(xml, mem, alpha) \
2004-12-18 05:32:00 -08:00
if ( attr_name = = xml ) \
{ \
CColor color ; \
2005-01-03 14:23:27 -08:00
if ( ! GUI < int > : : ParseColor ( attr_value , color , alpha ) ) \
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Error parsing '%hs' ( \" %hs \" ) " , attr_name . c_str ( ) , attr_value . c_str ( ) ) ; \
2004-12-18 05:32:00 -08:00
else effects . m_ # # mem = color ; \
} \
else
2005-01-03 14:23:27 -08:00
2004-12-19 04:20:04 -08:00
# define BOOL(xml, mem) \
if ( attr_name = = xml ) \
{ \
effects . m_ # # mem = true ; \
} \
else
2005-01-03 14:23:27 -08:00
COLOR ( " add_color " , AddColor , 0.f )
COLOR ( " multiply_color " , MultiplyColor , 255.f )
2004-12-19 04:20:04 -08:00
BOOL ( " grayscale " , Greyscale )
2004-12-18 05:32:00 -08:00
{
2009-11-03 13:46:35 -08:00
debug_warn ( L " Invalid data - DTD shouldn't allow this " ) ;
2004-12-18 05:32:00 -08:00
}
}
}
2004-07-08 08:23:47 -07:00
void CGUI : : Xeromyces_ReadStyle ( XMBElement Element , CXeromyces * pFile )
2003-11-30 23:06:55 -08:00
{
// style object we're adding
SGUIStyle style ;
CStr name ;
//
// Read Attributes
//
// Now we can iterate all attributes and store
2007-05-02 05:07:08 -07:00
XMBAttributeList attributes = Element . GetAttributes ( ) ;
2004-07-08 08:23:47 -07:00
for ( int i = 0 ; i < attributes . Count ; + + i )
2003-11-30 23:06:55 -08:00
{
2007-05-02 05:07:08 -07:00
XMBAttribute attr = attributes . Item ( i ) ;
CStr attr_name ( pFile - > GetAttributeString ( attr . Name ) ) ;
2004-07-10 13:56:15 -07:00
CStr attr_value ( attr . Value ) ;
2003-11-30 23:06:55 -08:00
// The "name" setting is actually the name of the style
// and not a new default
2004-07-10 13:33:42 -07:00
if ( attr_name = = " name " )
2003-11-30 23:06:55 -08:00
name = attr_value ;
else
2004-07-10 13:33:42 -07:00
style . m_SettingsDefaults [ attr_name ] = attr_value ;
2003-11-30 23:06:55 -08:00
}
//
// Add to CGUI
//
m_Styles [ name ] = style ;
}
2003-12-26 22:26:03 -08:00
2004-07-08 08:23:47 -07:00
void CGUI : : Xeromyces_ReadScrollBarStyle ( XMBElement Element , CXeromyces * pFile )
2003-12-26 22:26:03 -08:00
{
// style object we're adding
SGUIScrollBarStyle scrollbar ;
CStr name ;
//
// Read Attributes
//
// Now we can iterate all attributes and store
2007-05-02 05:07:08 -07:00
XMBAttributeList attributes = Element . GetAttributes ( ) ;
2004-07-08 08:23:47 -07:00
for ( int i = 0 ; i < attributes . Count ; + + i )
2003-12-26 22:26:03 -08:00
{
2007-05-02 05:07:08 -07:00
XMBAttribute attr = attributes . Item ( i ) ;
CStr attr_name = pFile - > GetAttributeString ( attr . Name ) ;
2004-07-10 13:56:15 -07:00
CStr attr_value ( attr . Value ) ;
2003-12-26 22:26:03 -08:00
2004-10-31 14:00:01 -08:00
if ( attr_value = = " null " )
2004-05-28 21:06:50 -07:00
continue ;
2004-07-10 13:33:42 -07:00
if ( attr_name = = " name " )
2003-12-26 22:26:03 -08:00
name = attr_value ;
else
2004-07-10 13:33:42 -07:00
if ( attr_name = = " width " )
2003-12-26 22:26:03 -08:00
{
2004-09-02 22:48:47 -07:00
float f ;
if ( ! GUI < float > : : ParseString ( attr_value , f ) )
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Error parsing '%hs' ( \" %hs \" ) " , attr_name . c_str ( ) , attr_value . c_str ( ) ) ;
else
scrollbar . m_Width = f ;
2003-12-26 22:26:03 -08:00
}
2004-05-28 21:06:50 -07:00
else
2005-01-01 04:06:17 -08:00
if ( attr_name = = " minimum_bar_size " )
2004-05-28 21:06:50 -07:00
{
2004-09-02 22:48:47 -07:00
float f ;
if ( ! GUI < float > : : ParseString ( attr_value , f ) )
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Error parsing '%hs' ( \" %hs \" ) " , attr_name . c_str ( ) , attr_value . c_str ( ) ) ;
else
scrollbar . m_MinimumBarSize = f ;
2004-05-28 21:06:50 -07:00
}
else
2005-01-01 04:06:17 -08:00
if ( attr_name = = " sprite_button_top " )
2004-05-28 21:06:50 -07:00
scrollbar . m_SpriteButtonTop = attr_value ;
else
2005-04-07 02:13:10 -07:00
if ( attr_name = = " sprite_button_top_pressed " )
2004-05-28 21:06:50 -07:00
scrollbar . m_SpriteButtonTopPressed = attr_value ;
else
2005-04-07 02:13:10 -07:00
if ( attr_name = = " sprite_button_top_disabled " )
2004-05-28 21:06:50 -07:00
scrollbar . m_SpriteButtonTopDisabled = attr_value ;
else
2005-04-07 02:13:10 -07:00
if ( attr_name = = " sprite_button_top_over " )
2004-05-28 21:06:50 -07:00
scrollbar . m_SpriteButtonTopOver = attr_value ;
else
2005-01-01 04:06:17 -08:00
if ( attr_name = = " sprite_button_bottom " )
2004-05-28 21:06:50 -07:00
scrollbar . m_SpriteButtonBottom = attr_value ;
else
2005-04-07 02:13:10 -07:00
if ( attr_name = = " sprite_button_bottom_pressed " )
2004-05-28 21:06:50 -07:00
scrollbar . m_SpriteButtonBottomPressed = attr_value ;
else
2005-04-07 02:13:10 -07:00
if ( attr_name = = " sprite_button_bottom_disabled " )
2004-05-28 21:06:50 -07:00
scrollbar . m_SpriteButtonBottomDisabled = attr_value ;
else
2005-04-07 02:13:10 -07:00
if ( attr_name = = " sprite_button_bottom_over " )
2004-05-28 21:06:50 -07:00
scrollbar . m_SpriteButtonBottomOver = attr_value ;
else
2005-01-01 04:06:17 -08:00
if ( attr_name = = " sprite_back_vertical " )
2004-05-28 21:06:50 -07:00
scrollbar . m_SpriteBackVertical = attr_value ;
else
2005-04-07 02:13:10 -07:00
if ( attr_name = = " sprite_bar_vertical " )
2004-05-28 21:06:50 -07:00
scrollbar . m_SpriteBarVertical = attr_value ;
else
2005-04-07 02:13:10 -07:00
if ( attr_name = = " sprite_bar_vertical_over " )
2004-05-28 21:06:50 -07:00
scrollbar . m_SpriteBarVerticalOver = attr_value ;
else
2005-04-07 02:13:10 -07:00
if ( attr_name = = " sprite_bar_vertical_pressed " )
2004-05-28 21:06:50 -07:00
scrollbar . m_SpriteBarVerticalPressed = attr_value ;
2004-08-30 19:09:58 -07:00
}
2004-05-28 21:06:50 -07:00
2004-08-30 19:09:58 -07:00
//
2005-04-07 02:13:10 -07:00
// Add to CGUI
2004-08-30 19:09:58 -07:00
//
2004-05-28 21:06:50 -07:00
2004-08-30 19:09:58 -07:00
m_ScrollBarStyles [ name ] = scrollbar ;
}
2004-05-28 21:06:50 -07:00
2004-08-30 19:09:58 -07:00
void CGUI : : Xeromyces_ReadIcon ( XMBElement Element , CXeromyces * pFile )
{
// Icon we're adding
SGUIIcon icon ;
CStr name ;
2004-05-28 21:06:50 -07:00
2007-05-02 05:07:08 -07:00
XMBAttributeList attributes = Element . GetAttributes ( ) ;
2004-08-30 19:09:58 -07:00
for ( int i = 0 ; i < attributes . Count ; + + i )
{
2007-05-02 05:07:08 -07:00
XMBAttribute attr = attributes . Item ( i ) ;
CStr attr_name ( pFile - > GetAttributeString ( attr . Name ) ) ;
2004-08-30 19:09:58 -07:00
CStr attr_value ( attr . Value ) ;
2004-05-28 21:06:50 -07:00
2004-10-31 14:00:01 -08:00
if ( attr_value = = " null " )
2004-08-30 19:09:58 -07:00
continue ;
2004-05-28 21:06:50 -07:00
2004-08-30 19:09:58 -07:00
if ( attr_name = = " name " )
name = attr_value ;
else
2005-07-24 17:52:03 -07:00
if ( attr_name = = " sprite " )
icon . m_SpriteName = attr_value ;
2004-08-30 19:09:58 -07:00
else
if ( attr_name = = " size " )
{
CSize size ;
if ( ! GUI < CSize > : : ParseString ( attr_value , size ) )
2009-12-03 12:17:22 -08:00
LOGERROR ( L " Error parsing '%hs' ( \" %hs \" ) inside <icon>. " , attr_name . c_str ( ) , attr_value . c_str ( ) ) ;
else
icon . m_Size = size ;
2004-08-30 19:09:58 -07:00
}
2004-12-18 05:32:00 -08:00
else
2005-01-01 04:06:17 -08:00
if ( attr_name = = " cell_id " )
2004-12-18 05:32:00 -08:00
{
int cell_id ;
if ( ! GUI < int > : : ParseString ( attr_value , cell_id ) )
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Error parsing '%hs' ( \" %hs \" ) inside <icon>. " , attr_name . c_str ( ) , attr_value . c_str ( ) ) ;
else
icon . m_CellID = cell_id ;
2004-12-18 05:32:00 -08:00
}
else
{
2009-11-03 13:46:35 -08:00
debug_warn ( L " Invalid data - DTD shouldn't allow this " ) ;
2004-12-18 05:32:00 -08:00
}
2003-12-26 22:26:03 -08:00
}
2004-08-30 19:09:58 -07:00
m_Icons [ name ] = icon ;
2003-12-26 22:26:03 -08:00
}
2004-12-21 05:37:24 -08:00
void CGUI : : Xeromyces_ReadTooltip ( XMBElement Element , CXeromyces * pFile )
{
2004-12-23 05:56:34 -08:00
// Read the tooltip, and store it as a specially-named object
2004-12-21 05:37:24 -08:00
2004-12-23 05:56:34 -08:00
IGUIObject * object = new CTooltip ;
2004-12-21 05:37:24 -08:00
2007-05-02 05:07:08 -07:00
XMBAttributeList attributes = Element . GetAttributes ( ) ;
2004-12-21 05:37:24 -08:00
for ( int i = 0 ; i < attributes . Count ; + + i )
{
2007-05-02 05:07:08 -07:00
XMBAttribute attr = attributes . Item ( i ) ;
CStr attr_name ( pFile - > GetAttributeString ( attr . Name ) ) ;
2004-12-21 05:37:24 -08:00
CStr attr_value ( attr . Value ) ;
if ( attr_name = = " name " )
{
2004-12-23 05:56:34 -08:00
object - > SetName ( " __tooltip_ " + attr_value ) ;
2004-12-21 05:37:24 -08:00
}
else
{
object - > SetSetting ( attr_name , attr_value ) ;
}
}
AddObject ( object ) ;
}
2005-07-25 12:06:18 -07:00
// Reads Custom Color
void CGUI : : Xeromyces_ReadColor ( XMBElement Element , CXeromyces * pFile )
{
// Read the color and stor in m_PreDefinedColors
2007-05-02 05:07:08 -07:00
XMBAttributeList attributes = Element . GetAttributes ( ) ;
2005-07-25 12:06:18 -07:00
//IGUIObject* object = new CTooltip;
CColor color ;
2007-05-02 05:07:08 -07:00
CStr name = attributes . GetNamedItem ( pFile - > GetAttributeID ( " name " ) ) ;
2005-07-25 12:06:18 -07:00
// Try parsing value
2007-05-02 05:07:08 -07:00
CStr value ( Element . GetText ( ) ) ;
2007-02-01 06:46:14 -08:00
if ( ! value . empty ( ) )
2005-07-25 12:06:18 -07:00
{
// Try setting color to value
if ( ! color . ParseString ( value , 255.f ) )
{
2009-12-03 12:17:22 -08:00
LOGERROR ( L " GUI: Unable to create custom color '%hs'. Invalid color syntax. " , name . c_str ( ) ) ;
2005-07-25 12:06:18 -07:00
}
else
{
// input color
m_PreDefinedColors [ name ] = color ;
}
}
}