2003-11-03 17:22:45 +01:00
/*
CGUI
by Gustav Larsson
gee @ pyro . nu
*/
2004-06-03 20:38:14 +02:00
# include "precompiled.h"
2004-06-15 23:08:05 +02:00
2003-11-03 17:22:45 +01:00
# include "GUI.h"
2004-05-29 06:06:50 +02:00
// Types - when including them into the engine.
# include "CButton.h"
# include "CText.h"
# include "CCheckBox.h"
# include "CRadioButton.h"
2004-07-08 17:23:47 +02:00
# include "ps/Xeromyces.h"
2003-11-24 03:18:41 +01:00
2003-12-01 08:06:55 +01:00
# include "Prometheus.h"
2003-11-24 03:18:41 +01:00
# include "input.h"
2004-05-29 06:06:50 +02:00
# include "OverlayText.h"
// TODO Gee: Whatever include CRect/CPos/CSize
# include "Overlay.h"
2003-11-03 17:22:45 +01:00
2004-07-08 17:23:47 +02:00
# include "scripting/ScriptingHost.h"
2004-07-22 18:18:12 +02:00
# include "Hotkey.h"
2004-07-08 17:23:47 +02:00
2003-12-27 07:26:03 +01:00
# include <string>
# include <assert.h>
# include <stdarg.h>
2003-11-03 17:22:45 +01:00
// namespaces used
using namespace std ;
2004-07-08 17:23:47 +02:00
# include "ps/CLogger.h"
# define XERO_TIME
2004-08-15 22:57:31 +02:00
# define LOG_CATEGORY "gui"
2004-07-08 17:23:47 +02:00
// Class for global JavaScript object
JSClass GUIClass = {
" GUIClass " , 0 ,
JS_PropertyStub , JS_PropertyStub , JS_PropertyStub , JS_PropertyStub ,
JS_EnumerateStub , JS_ResolveStub , JS_ConvertStub , JS_FinalizeStub ,
} ;
2003-11-03 17:22:45 +01:00
2004-06-03 03:43:33 +02:00
extern int g_xres , g_yres ;
2003-11-03 17:22:45 +01:00
2003-11-22 16:07:22 +01:00
//-------------------------------------------------------------------
// 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
//-------------------------------------------------------------------
2004-06-24 16:06:24 +02:00
int gui_handler ( const SDL_Event * ev )
2003-11-05 00:41:42 +01:00
{
2003-11-05 23:34:38 +01:00
return g_GUI . HandleEvent ( ev ) ;
2003-11-05 00:41:42 +01:00
}
2004-06-24 16:06:24 +02:00
int CGUI : : HandleEvent ( const SDL_Event * ev )
2003-11-03 17:22:45 +01:00
{
2004-07-22 18:18:12 +02:00
// MT: If something's gone wrong, check this block... (added for hotkey support)
if ( ev - > type = = SDL_GUIHOTKEYPRESS )
{
const CStr & objectName = * ( ( CStr * ) ev - > user . code ) ;
IGUIObject * object = FindObjectByName ( objectName ) ;
object - > HandleMessage ( SGUIMessage ( GUIM_PRESSED ) ) ;
object - > ScriptEvent ( " press " ) ;
}
// -- MT
2004-06-24 16:06:24 +02:00
if ( ev - > type = = SDL_MOUSEMOTION )
2003-12-27 07:26:03 +01:00
{
2004-06-24 16:06:24 +02:00
m_MousePos = CPos ( ev - > motion . x , ev - > motion . y ) ;
2003-11-03 17:22:45 +01:00
2003-12-27 07:26:03 +01:00
GUI < SGUIMessage > : : RecurseObject ( GUIRR_HIDDEN | GUIRR_GHOST , m_BaseObject ,
& IGUIObject : : HandleMessage ,
SGUIMessage ( GUIM_MOUSE_MOTION ) ) ;
}
2004-05-29 06:06:50 +02:00
// TODO Gee: temp-stuff
// char buf[30];
2004-06-24 16:06:24 +02:00
// sprintf(buf, "type = %d", ev->type);
2004-05-29 06:06:50 +02:00
//TEMPmessage = buf;
2003-12-27 07:26:03 +01:00
2004-07-08 17:23:47 +02:00
// Update m_MouseButtons. (BUTTONUP is handled later.)
2004-06-24 16:06:24 +02:00
if ( ev - > type = = SDL_MOUSEBUTTONDOWN )
2003-12-27 07:26:03 +01:00
{
2004-07-08 17:23:47 +02:00
// (0,1,2) = (LMB,RMB,MMB)
if ( ev - > button . button < 3 )
m_MouseButtons | = ( 1 < < ev - > button . button ) ;
2003-12-27 07:26:03 +01:00
}
2003-11-03 17:22:45 +01:00
// JW: (pre|post)process omitted; what're they for? why would we need any special button_released handling?
// Only one object can be hovered
2003-11-24 03:18:41 +01:00
IGUIObject * pNearest = NULL ;
2003-11-03 17:22:45 +01:00
2003-11-25 03:47:12 +01:00
try
2003-11-03 17:22:45 +01:00
{
2004-05-29 06:06:50 +02:00
// TODO Gee: Optimizations needed!
// these two recursive function are quite overhead heavy.
2003-11-25 03:47:12 +01:00
// pNearest will after this point at the hovered object, possibly NULL
2003-12-27 07:26:03 +01:00
GUI < IGUIObject * > : : RecurseObject ( GUIRR_HIDDEN | GUIRR_GHOST , m_BaseObject ,
2003-11-25 03:47:12 +01:00
& IGUIObject : : ChooseMouseOverAndClosest ,
pNearest ) ;
2004-07-11 18:22:35 +02:00
if ( ev - > type = = SDL_MOUSEMOTION & & pNearest )
pNearest - > ScriptEvent ( " mousemove " ) ;
2003-11-25 03:47:12 +01: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 18:18:12 +02:00
2003-12-27 07:26:03 +01:00
GUI < IGUIObject * > : : RecurseObject ( GUIRR_HIDDEN | GUIRR_GHOST , m_BaseObject ,
2003-11-25 03:47:12 +01:00
& IGUIObject : : UpdateMouseOver ,
pNearest ) ;
2004-06-24 16:06:24 +02:00
if ( ev - > type = = SDL_MOUSEBUTTONDOWN )
2003-11-25 03:47:12 +01:00
{
2004-06-24 16:06:24 +02:00
switch ( ev - > button . button )
2003-11-25 03:47:12 +01:00
{
2004-05-29 06:06:50 +02:00
case SDL_BUTTON_LEFT :
if ( pNearest )
2003-12-27 07:26:03 +01:00
{
2004-05-29 06:06:50 +02:00
pNearest - > HandleMessage ( SGUIMessage ( GUIM_MOUSE_PRESS_LEFT ) ) ;
2004-07-11 18:22:35 +02:00
pNearest - > ScriptEvent ( " mouseleftpress " ) ;
2004-05-29 06:06:50 +02:00
}
2004-07-11 18:22:35 +02:00
break ;
2004-05-29 06:06:50 +02:00
2004-06-02 17:22:19 +02:00
case SDL_BUTTON_WHEELDOWN : // wheel down
2004-05-29 06:06:50 +02:00
if ( pNearest )
{
pNearest - > HandleMessage ( SGUIMessage ( GUIM_MOUSE_WHEEL_DOWN ) ) ;
2004-07-11 18:22:35 +02:00
pNearest - > ScriptEvent ( " mousewheeldown " ) ;
2003-12-27 07:26:03 +01:00
}
2004-05-29 06:06:50 +02:00
break ;
2004-06-02 17:22:19 +02:00
case SDL_BUTTON_WHEELUP : // wheel up
2004-05-29 06:06:50 +02:00
if ( pNearest )
2003-12-27 07:26:03 +01:00
{
2004-05-29 06:06:50 +02:00
pNearest - > HandleMessage ( SGUIMessage ( GUIM_MOUSE_WHEEL_UP ) ) ;
2004-07-11 18:22:35 +02:00
pNearest - > ScriptEvent ( " mousewheelup " ) ;
2003-12-27 07:26:03 +01:00
}
2004-05-29 06:06:50 +02:00
break ;
default :
break ;
}
}
else
2004-06-24 16:06:24 +02:00
if ( ev - > type = = SDL_MOUSEBUTTONUP )
2004-05-29 06:06:50 +02:00
{
2004-06-24 16:06:24 +02:00
if ( ev - > button . button = = SDL_BUTTON_LEFT )
2004-05-29 06:06:50 +02:00
{
2003-12-27 07:26:03 +01:00
if ( pNearest )
2004-07-11 18:22:35 +02:00
{
2004-05-29 06:06:50 +02:00
pNearest - > HandleMessage ( SGUIMessage ( GUIM_MOUSE_RELEASE_LEFT ) ) ;
2004-07-11 18:22:35 +02:00
pNearest - > ScriptEvent ( " mouseleftrelease " ) ;
}
2003-12-27 07:26:03 +01:00
}
2004-05-29 06:06:50 +02: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-25 03:47:12 +01:00
}
}
catch ( PS_RESULT e )
{
2004-05-29 13:59:59 +02:00
UNUSED ( e ) ;
2004-08-10 18:04:21 +02:00
debug_warn ( " CGUI::HandleEvent error " ) ;
2003-12-27 07:26:03 +01:00
// TODO Gee: Handle
2003-11-25 03:47:12 +01:00
}
2003-11-03 17:22:45 +01:00
// JW: what's the difference between mPress and mDown? what's the code below responsible for?
2004-06-11 04:14:18 +02:00
/*
// Generally if just mouse is clicked
2003-11-03 17:22:45 +01:00
if ( m_pInput - > mDown ( NEMM_BUTTON1 ) & & pNearest )
{
pNearest - > HandleMessage ( GUIM_MOUSE_DOWN_LEFT ) ;
}
*/
2004-07-08 17:23:47 +02: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.
if ( ev - > type = = SDL_MOUSEBUTTONUP )
{
// (0,1,2) = (LMB,RMB,MMB)
if ( ev - > button . button < 3 )
m_MouseButtons & = ~ ( 1 < < ev - > button . button ) ;
}
2004-06-24 16:06:24 +02:00
return EV_PASS ;
2003-11-03 17:22:45 +01:00
}
2004-07-24 21:09:12 +02:00
void CGUI : : TickObjects ( )
{
CStr action = " tick " ;
GUI < CStr > : : RecurseObject ( 0 , m_BaseObject ,
& IGUIObject : : ScriptEvent , action ) ;
}
2003-11-03 17:22:45 +01:00
//-------------------------------------------------------------------
// Constructor / Destructor
//-------------------------------------------------------------------
2004-07-08 17:23:47 +02:00
CGUI : : CGUI ( ) : m_InternalNameNumber ( 0 ) , m_MouseButtons ( 0 )
2003-11-03 17:22:45 +01:00
{
2003-11-06 12:54:46 +01:00
m_BaseObject = new CGUIDummyObject ;
2003-11-03 17:22:45 +01:00
m_BaseObject - > SetGUI ( this ) ;
2004-07-08 17:23:47 +02:00
// Construct the parent object for all GUI JavaScript things
m_ScriptObject = ( void * ) JS_NewObject ( g_ScriptingHost . getContext ( ) , & GUIClass , NULL , NULL ) ;
assert ( m_ScriptObject ! = NULL ) ; // How should it handle errors?
JS_AddRoot ( g_ScriptingHost . getContext ( ) , & m_ScriptObject ) ;
2003-11-03 17:22:45 +01:00
// This will make this invisible, not add
//m_BaseObject->SetName(BASE_OBJECT_NAME);
}
CGUI : : ~ CGUI ( )
{
if ( m_BaseObject )
delete m_BaseObject ;
2004-07-08 17:23:47 +02:00
if ( m_ScriptObject )
// Let it be garbage-collected
JS_RemoveRoot ( g_ScriptingHost . getContext ( ) , & m_ScriptObject ) ;
2003-11-03 17:22:45 +01:00
}
2003-11-22 16:07:22 +01:00
//-------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------
2004-06-18 16:07:06 +02:00
IGUIObject * CGUI : : ConstructObject ( const CStr & str )
2003-11-03 17:22:45 +01:00
{
if ( m_ObjectTypes . count ( str ) > 0 )
return ( * m_ObjectTypes [ str ] ) ( ) ;
else
2003-11-24 03:18:41 +01:00
{
2004-08-10 18:04:21 +02:00
debug_warn ( " CGUI::ConstructObject error " ) ;
2003-12-27 07:26:03 +01:00
// TODO Gee: Report in log
2003-11-03 17:22:45 +01:00
return NULL ;
2003-11-24 03:18:41 +01:00
}
2003-11-03 17:22:45 +01:00
}
2003-11-24 03:18:41 +01:00
void CGUI : : Initialize ( )
2003-11-03 17:22:45 +01:00
{
// Add base types!
2003-11-24 03:18:41 +01:00
// You can also add types outside the GUI to extend the flexibility of the GUI.
// Prometheus though will have all the object types inserted from here.
2004-05-29 06:06:50 +02:00
AddObjectType ( " empty " , & CGUIDummyObject : : ConstructObject ) ;
AddObjectType ( " button " , & CButton : : ConstructObject ) ;
AddObjectType ( " text " , & CText : : ConstructObject ) ;
AddObjectType ( " checkbox " , & CCheckBox : : ConstructObject ) ;
AddObjectType ( " radiobutton " , & CRadioButton : : ConstructObject ) ;
2003-11-03 17:22:45 +01:00
}
void CGUI : : Process ( )
{
2004-06-11 04:14:18 +02:00
/*
2003-11-03 17:22:45 +01:00
2003-12-27 07:26:03 +01:00
// TODO Gee: check if m_pInput is valid, otherwise return
2003-11-03 17:22:45 +01:00
/// assert(m_pInput);
// Pre-process all objects
try
{
2003-11-24 03:18:41 +01:00
GUI < EGUIMessage > : : RecurseObject ( 0 , m_BaseObject , & IGUIObject : : HandleMessage , GUIM_PREPROCESS ) ;
2003-11-03 17:22:45 +01:00
}
catch ( PS_RESULT e )
{
return ;
}
// Check mouse over
try
{
// Only one object can be hovered
// check which one it is, if any !
2003-11-24 03:18:41 +01:00
IGUIObject * pNearest = NULL ;
2003-11-03 17:22:45 +01:00
2003-11-24 03:18:41 +01:00
GUI < IGUIObject * > : : RecurseObject ( GUIRR_HIDDEN , m_BaseObject , & IGUIObject : : ChooseMouseOverAndClosest , pNearest ) ;
2003-11-03 17:22:45 +01: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
2003-11-24 03:18:41 +01:00
GUI < IGUIObject * > : : RecurseObject ( GUIRR_HIDDEN , m_BaseObject , & IGUIObject : : UpdateMouseOver , pNearest ) ;
2003-11-03 17:22:45 +01:00
// 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 ( PS_RESULT e )
{
return ;
}
// Post-process all objects
try
{
2003-11-24 03:18:41 +01:00
GUI < EGUIMessage > : : RecurseObject ( 0 , m_BaseObject , & IGUIObject : : HandleMessage , GUIM_POSTPROCESS ) ;
2003-11-03 17:22:45 +01:00
}
catch ( PS_RESULT e )
{
return ;
}
*/
}
void CGUI : : Draw ( )
{
2004-07-08 17:23:47 +02:00
// Clear the depth buffer, so the GUI is
// drawn on top of everything else
glClear ( GL_DEPTH_BUFFER_BIT ) ;
2003-11-24 03:18:41 +01:00
glPushMatrix ( ) ;
glLoadIdentity ( ) ;
// Adapt (origio) to being in top left corner and down
// just like the mouse position
2004-05-29 13:59:59 +02:00
glTranslatef ( 0.0f , ( GLfloat ) g_yres , - 1000.0f ) ;
2003-11-24 03:18:41 +01:00
glScalef ( 1.0f , - 1.f , 1.0f ) ;
2003-11-03 17:22:45 +01:00
try
{
2003-11-24 03:18:41 +01: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 17:22:45 +01:00
}
catch ( PS_RESULT e )
{
2004-05-29 13:59:59 +02:00
UNUSED ( e ) ;
2003-11-24 03:18:41 +01:00
glPopMatrix ( ) ;
2003-12-27 07:26:03 +01:00
// TODO Gee: Report error.
2004-08-10 18:04:21 +02:00
debug_warn ( " CGUI::Draw error " ) ;
2003-11-03 17:22:45 +01:00
return ;
}
2003-11-24 03:18:41 +01:00
glPopMatrix ( ) ;
2003-11-03 17:22:45 +01:00
}
2004-06-18 16:07:06 +02:00
void CGUI : : DrawSprite ( const CStr & SpriteName ,
2003-12-01 08:06:55 +01:00
const float & Z ,
const CRect & Rect ,
const CRect & Clipping )
{
2003-12-27 07:26:03 +01:00
// This is not an error, it's just a choice not to draw any sprite.
2004-05-29 06:06:50 +02:00
if ( SpriteName = = CStr ( ) )
2003-12-01 08:06:55 +01:00
return ;
2004-07-24 16:04:40 +02:00
// TODO: Clipping?
2004-05-29 06:06:50 +02:00
bool DoClipping = ( Clipping ! = CRect ( ) ) ;
2004-07-24 16:04:40 +02:00
2003-12-01 08:06:55 +01:00
CGUISprite Sprite ;
// Fetch real sprite from name
if ( m_Sprites . count ( SpriteName ) = = 0 )
{
2004-08-10 18:04:21 +02:00
debug_warn ( " CGUI::DrawSprite error " ) ;
2003-12-27 07:26:03 +01:00
// TODO Gee: Report error
2003-12-01 08:06:55 +01:00
return ;
}
else Sprite = m_Sprites [ SpriteName ] ;
glPushMatrix ( ) ;
2004-07-14 00:48:53 +02:00
glTranslatef ( 0.0f , 0.0f , Z ) ;
2003-12-01 08:06:55 +01:00
2004-07-14 00:48:53 +02:00
// Iterate all images and request them being drawn be the
// CRenderer
std : : vector < SGUIImage > : : const_iterator cit ;
for ( cit = Sprite . m_Images . begin ( ) ; cit ! = Sprite . m_Images . end ( ) ; + + cit )
{
if ( cit - > m_Texture )
2003-12-01 08:06:55 +01:00
{
2004-07-15 21:10:33 +02:00
// TODO: Handle the GL state in a nicer way
2004-07-14 00:48:53 +02:00
glEnable ( GL_TEXTURE_2D ) ;
2004-08-06 17:01:23 +02:00
glColor3f ( 1.0f , 1.0f , 1.0f ) ;
2004-07-14 00:48:53 +02:00
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_REPLACE ) ;
2004-07-15 21:10:33 +02:00
int fmt ;
tex_info ( cit - > m_Texture , NULL , NULL , & fmt , NULL , NULL ) ;
if ( fmt = = GL_RGBA | | fmt = = GL_BGRA )
{
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
glEnable ( GL_BLEND ) ;
}
else
{
glDisable ( GL_BLEND ) ;
}
2004-07-14 00:48:53 +02:00
tex_bind ( cit - > m_Texture ) ;
2004-07-10 22:33:42 +02:00
2003-12-01 08:06:55 +01:00
CRect real = cit - > m_Size . GetClientArea ( Rect ) ;
2004-07-14 12:40:36 +02:00
// Get the screen position/size of a single tiling of the texture
2004-07-14 00:48:53 +02:00
CRect TexSize = cit - > m_TextureSize . GetClientArea ( real ) ;
2004-05-29 06:06:50 +02:00
2004-07-14 12:40:36 +02:00
float TexLeft = ( float ) ( TexSize . left - real . left ) / ( float ) TexSize . GetWidth ( ) ;
2004-07-14 00:48:53 +02:00
float TexRight = TexLeft + ( float ) real . GetWidth ( ) / ( float ) TexSize . GetWidth ( ) ;
2004-07-14 12:40:36 +02:00
// 'Bottom' is actually the top in screen-space (I think),
// because the GUI puts (0,0) at the top-left
float TexBottom = ( float ) ( TexSize . bottom - real . bottom ) / ( float ) TexSize . GetHeight ( ) ;
float TexTop = TexBottom + ( float ) real . GetHeight ( ) / ( float ) TexSize . GetHeight ( ) ;
2003-12-01 08:06:55 +01:00
glBegin ( GL_QUADS ) ;
2004-07-14 12:40:36 +02:00
glTexCoord2f ( TexRight , TexBottom ) ; glVertex3f ( ( float ) real . right , ( float ) real . bottom , cit - > m_DeltaZ ) ;
glTexCoord2f ( TexLeft , TexBottom ) ; glVertex3f ( ( float ) real . left , ( float ) real . bottom , cit - > m_DeltaZ ) ;
glTexCoord2f ( TexLeft , TexTop ) ; glVertex3f ( ( float ) real . left , ( float ) real . top , cit - > m_DeltaZ ) ;
glTexCoord2f ( TexRight , TexTop ) ; glVertex3f ( ( float ) real . right , ( float ) real . top , cit - > m_DeltaZ ) ;
2003-12-01 08:06:55 +01:00
glEnd ( ) ;
2004-05-29 06:06:50 +02:00
2004-07-14 00:48:53 +02:00
glDisable ( GL_TEXTURE_2D ) ;
2004-08-06 17:01:23 +02:00
2004-07-14 00:48:53 +02:00
}
else
{
glColor3f ( cit - > m_BackColor . r , cit - > m_BackColor . g , cit - > m_BackColor . b ) ;
2004-07-10 22:33:42 +02:00
2004-07-14 00:48:53 +02:00
CRect real = cit - > m_Size . GetClientArea ( Rect ) ;
glBegin ( GL_QUADS ) ;
glVertex3f ( ( float ) real . right , ( float ) real . bottom , cit - > m_DeltaZ ) ;
glVertex3f ( ( float ) real . left , ( float ) real . bottom , cit - > m_DeltaZ ) ;
glVertex3f ( ( float ) real . left , ( float ) real . top , cit - > m_DeltaZ ) ;
glVertex3f ( ( float ) real . right , ( float ) real . top , cit - > m_DeltaZ ) ;
glEnd ( ) ;
2003-12-01 08:06:55 +01:00
}
2004-07-14 00:48:53 +02:00
}
2003-12-01 08:06:55 +01:00
glPopMatrix ( ) ;
}
2003-11-03 17:22:45 +01:00
void CGUI : : Destroy ( )
{
// We can use the map to delete all
2003-11-22 16:07:22 +01:00
// now we don't want to cancel all if one Destroy fails
2003-11-03 17:22:45 +01:00
map_pObjects : : iterator it ;
for ( it = m_pAllObjects . begin ( ) ; it ! = m_pAllObjects . end ( ) ; + + it )
{
try
{
it - > second - > Destroy ( ) ;
}
catch ( PS_RESULT e )
{
2004-05-29 13:59:59 +02:00
UNUSED ( e ) ;
2004-08-10 18:04:21 +02:00
debug_warn ( " CGUI::Destroy error " ) ;
2003-12-27 07:26:03 +01:00
// TODO Gee: Handle
2003-11-03 17:22:45 +01:00
}
delete it - > second ;
}
// Clear all
m_pAllObjects . clear ( ) ;
m_Sprites . clear ( ) ;
}
2003-11-24 18:13:37 +01:00
void CGUI : : UpdateResolution ( )
{
2003-11-25 03:47:12 +01:00
// Update ALL cached
2003-11-24 18:13:37 +01:00
GUI < > : : RecurseObject ( 0 , m_BaseObject , & IGUIObject : : UpdateCachedSize ) ;
}
2003-11-24 03:18:41 +01:00
void CGUI : : AddObject ( IGUIObject * pObject )
2003-11-03 17:22:45 +01:00
{
2003-12-01 08:06:55 +01:00
try
{
2003-11-03 17:22:45 +01:00
// Add CGUI pointer
2003-11-24 03:18:41 +01:00
GUI < CGUI * > : : RecurseObject ( 0 , pObject , & IGUIObject : : SetGUI , this ) ;
2003-11-03 17:22:45 +01:00
// Add child to base object
m_BaseObject - > AddChild ( pObject ) ;
2003-11-25 03:47:12 +01:00
// Cache tree
GUI < > : : RecurseObject ( 0 , pObject , & IGUIObject : : UpdateCachedSize ) ;
2004-05-29 06:06:50 +02:00
// Loaded
GUI < SGUIMessage > : : RecurseObject ( 0 , pObject , & IGUIObject : : HandleMessage , SGUIMessage ( GUIM_LOAD ) ) ;
2004-07-11 18:22:35 +02:00
GUI < CStr > : : RecurseObject ( 0 , pObject , & IGUIObject : : ScriptEvent , " load " ) ;
2003-12-01 08:06:55 +01:00
}
2003-11-03 17:22:45 +01:00
catch ( PS_RESULT e )
{
throw e ;
2003-12-01 08:06:55 +01:00
}
2003-11-03 17:22:45 +01:00
}
void CGUI : : UpdateObjects ( )
{
// We'll fill a temporary map until we know everything
// succeeded
map_pObjects AllObjects ;
try
{
// Fill freshly
2003-11-24 03:18:41 +01:00
GUI < map_pObjects > : : RecurseObject ( 0 , m_BaseObject , & IGUIObject : : AddToPointersMap , AllObjects ) ;
2003-11-03 17:22:45 +01:00
}
catch ( PS_RESULT e )
{
// Throw the same error
throw e ;
}
// Else actually update the real one
m_pAllObjects = AllObjects ;
}
2004-06-18 16:07:06 +02:00
bool CGUI : : ObjectExists ( const CStr & Name ) const
2003-11-03 17:22:45 +01:00
{
2004-05-29 13:59:59 +02:00
return m_pAllObjects . count ( Name ) ! = 0 ;
2004-05-29 06:06:50 +02:00
}
2004-07-08 17:23:47 +02: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-29 06:06:50 +02:00
// private struct used only in GenerateText(...)
2004-05-29 13:59:59 +02:00
struct SGenerateTextImage
2004-05-29 06:06:50 +02:00
{
int m_YFrom , // The images starting location in Y
m_YTo , // The images end location in Y
m_Indentation ; // The image width in other words
// Some help functions
// TODO Gee: CRect => CPoint ?
void SetupSpriteCall ( const bool & Left , SGUIText : : SSpriteCall & SpriteCall ,
const int & width , const int & y ,
2004-06-18 16:07:06 +02:00
const CSize & Size , const CStr & TextureName ,
2004-05-29 06:06:50 +02:00
const int & BufferZone )
{
// 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 ;
}
SpriteCall . m_TextureName = TextureName ;
m_YFrom = SpriteCall . m_Area . top - BufferZone ;
m_YTo = SpriteCall . m_Area . bottom + BufferZone ;
m_Indentation = Size . cx + BufferZone * 2 ;
}
} ;
SGUIText CGUI : : GenerateText ( const CGUIString & string , /*const CColor &Color, */
2004-06-18 16:07:06 +02:00
const CStr & Font , const int & Width , const int & BufferZone )
2004-05-29 06:06:50 +02:00
{
SGUIText Text ; // object we're generating
if ( string . m_Words . size ( ) = = 0 )
return Text ;
int x = BufferZone , y = BufferZone ; // drawing pointer
int from = 0 ;
bool done = false ;
// Images on the left or the right side.
vector < SGenerateTextImage > Images [ 2 ] ;
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 13:59:59 +02:00
for ( int i = 0 ; i < ( int ) string . m_Words . size ( ) - 1 & & ! done ; + + i )
2004-05-29 06:06:50 +02: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.
int prelim_line_height = 0 ;
// Width and height of all text calls generated.
string . GenerateTextCall ( Feedback , Font , /*CColor(),*/
string . m_Words [ i ] , string . m_Words [ i + 1 ] ) ;
// 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 )
{
for ( vector < CStr > : : const_iterator it = Feedback . m_Images [ j ] . begin ( ) ;
it ! = Feedback . m_Images [ j ] . end ( ) ;
+ + 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.
int _y ;
if ( Images [ j ] . size ( ) > 0 )
_y = max ( y , Images [ j ] . back ( ) . m_YTo ) ;
else
_y = y ;
// TODO Gee: CSize temp
CSize size ; size . cx = 100 ; size . cy = 100 ;
Image . SetupSpriteCall ( ( j = = CGUIString : : SFeedback : : Left ) , SpriteCall , Width , _y , size , CStr ( " white-border " ) , BufferZone ) ;
// Check if image is the lowest thing.
Text . m_Size . cy = max ( Text . m_Size . cy , Image . m_YTo ) ;
Images [ j ] . push_back ( Image ) ;
Text . m_SpriteCalls . push_back ( SpriteCall ) ;
}
}
}
pos_last_img = max ( pos_last_img , i ) ;
x + = Feedback . m_Size . cx ;
prelim_line_height = max ( prelim_line_height , Feedback . m_Size . cy ) ;
// If Width is 0, then there's no word-wrapping, disable NewLine.
2004-07-24 16:04:40 +02:00
if ( ( WordWrapping & & ( x > Width - BufferZone | | Feedback . m_NewLine ) ) | | i = = ( int ) string . m_Words . size ( ) - 2 )
2004-05-29 06:06:50 +02:00
{
// Change from to i, but first keep a copy of its value.
int temp_from = from ;
from = i ;
static const int From = 0 , To = 1 ;
//int width_from=0, width_to=width;
int width_range [ 2 ] ;
width_range [ From ] = BufferZone ;
width_range [ To ] = Width - BufferZone ;
// Floating images are only appicable if word-wrapping is enabled.
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
// this problem out, and it is very unlikely to happen noticably if one
// stuctures his text in a stylistically pure fashion. Even if not, it
// is still quite unlikely it will happen.
// Loop through left and right side, from and to.
for ( int j = 0 ; j < 2 ; + + j )
{
for ( vector < SGenerateTextImage > : : const_iterator it = Images [ j ] . begin ( ) ;
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.
int union_from , union_to ;
union_from = max ( y , it - > m_YFrom ) ;
union_to = min ( y + prelim_line_height , it - > m_YTo ) ;
2004-07-31 15:37:35 +02:00
// The union is not empty
2004-05-29 06:06:50 +02:00
if ( union_to > union_from )
{
if ( j = = From )
width_range [ From ] = max ( width_range [ From ] , it - > m_Indentation ) ;
else
width_range [ To ] = min ( width_range [ To ] , Width - it - > m_Indentation ) ;
}
}
}
}
// 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.
int line_height = 0 ;
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 ;
string . GenerateTextCall ( Feedback2 , Font , /*CColor(),*/
string . m_Words [ j ] , string . m_Words [ j + 1 ] ) ;
// 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.
line_height = max ( line_height , Feedback2 . m_Size . cy ) ;
if ( WordWrapping & & Feedback2 . m_NewLine )
break ;
}
// Reset x once more
x = width_range [ From ] ;
2004-07-14 00:48:53 +02:00
// Move down, because font drawing starts from the baseline
y + = line_height ;
2004-05-29 06:06:50 +02: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
// another.
CGUIString : : SFeedback Feedback2 ;
// Defaults
string . GenerateTextCall ( Feedback2 , Font , /*Color, */
string . m_Words [ j ] , string . m_Words [ j + 1 ] ) ;
// 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.
int x_pointer = 0 ;
vector < SGUIText : : STextCall > : : iterator it ;
for ( it = Feedback2 . m_TextCalls . begin ( ) ; it ! = Feedback2 . m_TextCalls . end ( ) ; + + it )
{
2004-07-31 15:37:35 +02:00
it - > m_Pos = CPos ( x + x_pointer , y ) ;
2004-05-29 06:06:50 +02:00
x_pointer + = it - > m_Size . cx ;
if ( it - > m_pSpriteCall )
{
it - > m_pSpriteCall - > m_Area =
it - > m_pSpriteCall - > m_Area + it - > m_Pos ;
}
}
// Append X value.
x + = Feedback2 . m_Size . cx ;
Text . m_Size . cx = max ( Text . m_Size . cx , x + BufferZone ) ;
// The first word overrides the width limit, that we
// do in those cases, are just draw that word even
// though it'll extend the object.
if ( WordWrapping ) // only if word-wrapping is applicable
{
if ( Feedback2 . m_NewLine )
{
from = j + 1 ;
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 16:04:40 +02:00
if ( j = = ( int ) string . m_Words . size ( ) - 2 )
2004-05-29 06:06:50 +02:00
done = true ;
}
2004-07-14 00:48:53 +02:00
// Reset X
2004-05-29 06:06:50 +02:00
x = 0 ;
// Update height of all
Text . m_Size . cy = max ( Text . m_Size . cy , y + BufferZone ) ;
// 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 ;
}
void CGUI : : DrawText ( const SGUIText & Text , const CColor & DefaultColor ,
const CPos & pos , const float & z )
{
2004-07-14 00:48:53 +02: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 ) ;
Handle font = 0 ;
CStr LastFontName ;
for ( vector < SGUIText : : STextCall > : : const_iterator it = Text . m_TextCalls . begin ( ) ;
it ! = Text . m_TextCalls . end ( ) ;
2004-05-29 06:06:50 +02:00
+ + it )
{
if ( it - > m_pSpriteCall )
continue ;
2004-07-14 00:48:53 +02:00
// Switch fonts when necessary, but remember the last one used
if ( it - > m_Font ! = LastFontName )
{
if ( font )
unifont_unload ( font ) ;
font = unifont_load ( it - > m_Font ) ;
unifont_bind ( font ) ;
LastFontName = it - > m_Font ;
}
CColor color = it - > m_UseCustomColor ? it - > m_Color : DefaultColor ;
glPushMatrix ( ) ;
glTranslatef ( ( float ) pos . x + it - > m_Pos . x , ( float ) pos . y + it - > m_Pos . y , ( float ) z ) ;
glColor4f ( color . r , color . g , color . b , color . a ) ;
glwprintf ( L " %hs " , it - > m_String . c_str ( ) ) ;
glPopMatrix ( ) ;
2004-05-29 06:06:50 +02:00
}
2004-07-14 00:48:53 +02:00
if ( font )
unifont_unload ( font ) ;
2004-05-29 06:06:50 +02:00
for ( vector < SGUIText : : SSpriteCall > : : const_iterator it = Text . m_SpriteCalls . begin ( ) ;
it ! = Text . m_SpriteCalls . end ( ) ;
+ + it )
{
DrawSprite ( it - > m_TextureName , z , it - > m_Area + pos ) ;
}
2003-11-03 17:22:45 +01:00
}
2004-08-09 18:29:21 +02:00
void CGUI : : ReportParseError ( const CStr & str )
2003-11-03 17:22:45 +01:00
{
// Print header
if ( m_Errors = = 0 )
{
2004-08-15 22:57:31 +02:00
LOG ( ERROR , LOG_CATEGORY , " *** GUI Tree Creation Errors: " ) ;
2003-11-03 17:22:45 +01:00
}
// Important, set ParseError to true
+ + m_Errors ;
2004-08-15 22:57:31 +02:00
LOG ( ERROR , LOG_CATEGORY , str ) ;
2003-11-03 17:22:45 +01:00
}
2003-11-24 03:18:41 +01:00
/**
* @ callgraph
*/
2003-11-07 02:55:29 +01:00
void CGUI : : LoadXMLFile ( const string & Filename )
2003-11-03 17:22:45 +01:00
{
// Reset parse error
// we can later check if this has increased
m_Errors = 0 ;
2004-07-08 17:23:47 +02:00
CXeromyces XeroFile ;
2004-07-29 18:17:21 +02:00
if ( XeroFile . Load ( Filename . c_str ( ) ) ! = PSRETURN_OK )
2004-07-15 21:10:33 +02:00
// Fail silently
2004-07-11 18:22:35 +02:00
return ;
2003-11-03 17:22:45 +01:00
2004-07-08 17:23:47 +02:00
XMBElement node = XeroFile . getRoot ( ) ;
2003-11-25 03:47:12 +01:00
2004-07-08 17:23:47 +02:00
// Check root element's (node) name so we know what kind of
// data we'll be expecting
2004-07-10 22:33:42 +02:00
std : : string root_name = XeroFile . getElementString ( node . getNodeName ( ) ) ;
2004-06-14 01:36:16 +02:00
2004-07-17 19:09:33 +02:00
try
2004-07-08 17:23:47 +02:00
{
2003-11-03 17:22:45 +01:00
2004-07-17 19:09:33 +02:00
if ( root_name = = " objects " )
{
Xeromyces_ReadRootObjects ( node , & XeroFile ) ;
// 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
{
2004-08-10 18:04:21 +02:00
debug_warn ( " CGUI::LoadXMLFile error " ) ;
2004-07-17 19:09:33 +02:00
// TODO Gee: Output in log
}
2004-07-08 17:23:47 +02:00
}
2004-07-17 19:09:33 +02:00
catch ( PSERROR_GUI )
2004-07-08 17:23:47 +02:00
{
2004-08-15 22:57:31 +02:00
LOG ( ERROR , LOG_CATEGORY , " Errors loading GUI file %s " , Filename . c_str ( ) ) ;
2004-07-17 19:09:33 +02:00
return ;
2004-07-08 17:23:47 +02:00
}
2003-12-27 07:26:03 +01:00
2004-07-08 17:23:47 +02:00
// Now report if any other errors occured
if ( m_Errors > 0 )
{
/// g_console.submit("echo GUI Tree Creation Reports %d errors", m_Errors);
2003-11-03 17:22:45 +01:00
}
2004-07-08 17:23:47 +02:00
2003-11-03 17:22:45 +01:00
}
//===================================================================
2004-07-08 17:23:47 +02:00
// XML Reading Xeromyces Specific Sub-Routines
2003-11-03 17:22:45 +01:00
//===================================================================
2004-07-08 17:23:47 +02:00
void CGUI : : Xeromyces_ReadRootObjects ( XMBElement Element , CXeromyces * pFile )
2003-11-03 17:22:45 +01:00
{
2004-07-11 18:22:35 +02:00
int el_script = pFile - > getElementID ( " script " ) ;
2003-11-03 17:22:45 +01:00
// Iterate main children
2004-07-11 18:22:35 +02:00
// they should all be <object> or <script> elements
2004-07-08 17:23:47 +02:00
XMBElementList children = Element . getChildNodes ( ) ;
for ( int i = 0 ; i < children . Count ; + + i )
2003-11-03 17:22:45 +01:00
{
2004-07-08 17:23:47 +02:00
//debug_out("Object %d\n", i);
XMBElement child = children . item ( i ) ;
2003-11-03 17:22:45 +01:00
2004-07-11 18:22:35 +02:00
if ( child . getNodeName ( ) = = el_script )
// Execute the inline script
Xeromyces_ReadScript ( child , pFile ) ;
else
// Read in this whole object into the GUI
Xeromyces_ReadObject ( child , pFile , m_BaseObject ) ;
2003-11-03 17:22:45 +01:00
}
}
2004-07-08 17:23:47 +02:00
void CGUI : : Xeromyces_ReadRootSprites ( XMBElement Element , CXeromyces * pFile )
2003-11-03 17:22:45 +01:00
{
// Iterate main children
// they should all be <sprite> elements
2004-07-08 17:23:47 +02:00
XMBElementList children = Element . getChildNodes ( ) ;
for ( int i = 0 ; i < children . Count ; + + i )
2003-11-03 17:22:45 +01:00
{
2004-07-08 17:23:47 +02:00
XMBElement child = children . item ( i ) ;
2003-11-03 17:22:45 +01:00
2004-07-08 17:23:47 +02:00
// Read in this whole object into the GUI
Xeromyces_ReadSprite ( child , pFile ) ;
2003-11-03 17:22:45 +01:00
}
}
2004-07-08 17:23:47 +02:00
void CGUI : : Xeromyces_ReadRootStyles ( XMBElement Element , CXeromyces * pFile )
2003-12-01 08:06:55 +01:00
{
// Iterate main children
// they should all be <styles> elements
2004-07-08 17:23:47 +02:00
XMBElementList children = Element . getChildNodes ( ) ;
for ( int i = 0 ; i < children . Count ; + + i )
2003-12-01 08:06:55 +01:00
{
2004-07-08 17:23:47 +02:00
XMBElement child = children . item ( i ) ;
2003-12-01 08:06:55 +01:00
2004-07-08 17:23:47 +02:00
// Read in this whole object into the GUI
Xeromyces_ReadStyle ( child , pFile ) ;
2003-12-01 08:06:55 +01:00
}
}
2004-07-08 17:23:47 +02:00
void CGUI : : Xeromyces_ReadRootSetup ( XMBElement Element , CXeromyces * pFile )
2003-12-27 07:26:03 +01:00
{
// Iterate main children
// they should all be <icon>, <scrollbar> or <tooltip>.
2004-07-08 17:23:47 +02:00
XMBElementList children = Element . getChildNodes ( ) ;
for ( int i = 0 ; i < children . Count ; + + i )
2003-12-27 07:26:03 +01:00
{
2004-07-08 17:23:47 +02:00
XMBElement child = children . item ( i ) ;
2003-12-27 07:26:03 +01:00
2004-07-08 17:23:47 +02:00
// Read in this whole object into the GUI
2003-12-27 07:26:03 +01:00
2004-07-10 22:33:42 +02:00
std : : string name = pFile - > getElementString ( child . getNodeName ( ) ) ;
2003-12-27 07:26:03 +01:00
2004-07-10 22:33:42 +02:00
if ( name = = " scrollbar " )
2004-07-08 17:23:47 +02:00
{
Xeromyces_ReadScrollBarStyle ( child , pFile ) ;
2003-12-27 07:26:03 +01:00
}
2004-07-08 17:23:47 +02:00
// No need for else, we're using DTD.
2003-12-27 07:26:03 +01:00
}
}
2004-07-08 17:23:47 +02:00
void CGUI : : Xeromyces_ReadObject ( XMBElement Element , CXeromyces * pFile , IGUIObject * pParent )
2003-11-03 17:22:45 +01:00
{
2004-07-08 17:23:47 +02:00
assert ( pParent ) ;
int i ;
2003-11-03 17:22:45 +01:00
// Our object we are going to create
2003-11-24 03:18:41 +01:00
IGUIObject * object = NULL ;
2003-11-03 17:22:45 +01:00
2004-07-08 17:23:47 +02:00
XMBAttributeList attributes = Element . getAttributes ( ) ;
2003-11-03 17:22:45 +01:00
// Well first of all we need to determine the type
2004-07-11 13:51:27 +02:00
utf16string type = attributes . getNamedItem ( pFile - > getAttributeID ( " type " ) ) ;
2003-11-03 17:22:45 +01:00
// Construct object from specified type
// henceforth, we need to do a rollback before aborting.
// i.e. releasing this object
2004-07-10 22:56:15 +02:00
object = ConstructObject ( ( CStr ) type ) ;
2003-11-03 17:22:45 +01:00
if ( ! object )
{
// Report error that object was unsuccessfully loaded
2004-07-10 22:56:15 +02:00
ReportParseError ( CStr ( " Unrecognized type: " ) + CStr ( type ) ) ;
2003-11-03 17:22:45 +01:00
delete object ;
return ;
}
2004-07-08 17:23:47 +02:00
// Cache some IDs for element attribute names, to avoid string comparisons
2004-07-10 22:33:42 +02:00
# define ELMT(x) int elmt_##x = pFile->getElementID(#x)
# define ATTR(x) int attr_##x = pFile->getAttributeID(#x)
2004-07-08 17:23:47 +02:00
ELMT ( object ) ;
ELMT ( action ) ;
ATTR ( style ) ;
ATTR ( type ) ;
ATTR ( name ) ;
2004-07-22 18:18:12 +02:00
// MT - temp tag
ATTR ( hotkey ) ;
// -- MT
2004-07-08 17:23:47 +02:00
ATTR ( z ) ;
ATTR ( on ) ;
2004-07-11 18:22:35 +02:00
ATTR ( file ) ;
2004-07-08 17:23:47 +02:00
2003-12-01 08:06:55 +01:00
//
// Read Style and set defaults
//
2003-12-27 07:26:03 +01:00
// If the setting "style" is set, try loading that setting.
//
// Always load default (if it's available) first!
//
2004-07-10 22:56:15 +02:00
CStr argStyle = ( CStr ) attributes . getNamedItem ( attr_style ) ;
2003-12-01 08:06:55 +01:00
2003-12-27 07:26:03 +01:00
if ( m_Styles . count ( CStr ( " default " ) ) = = 1 )
object - > LoadStyle ( * this , CStr ( " default " ) ) ;
if ( argStyle ! = CStr ( ) )
2003-12-01 08:06:55 +01:00
{
2003-12-27 07:26:03 +01:00
// additional check
2003-12-01 08:06:55 +01:00
if ( m_Styles . count ( argStyle ) = = 0 )
{
2004-08-10 18:04:21 +02:00
debug_warn ( " CGUI::Xeromyces_ReadObject error " ) ;
2003-12-27 07:26:03 +01:00
// TODO Gee: Error
2003-12-01 08:06:55 +01:00
}
2003-12-27 07:26:03 +01:00
else object - > LoadStyle ( * this , argStyle ) ;
2003-12-01 08:06:55 +01:00
}
2003-12-27 07:26:03 +01:00
2003-11-03 17:22:45 +01:00
//
// Read Attributes
//
bool NameSet = false ;
2003-12-27 07:26:03 +01:00
bool ManuallySetZ = false ; // if z has been manually set, this turn true
2003-11-03 17:22:45 +01:00
2004-07-22 18:18:12 +02:00
// MT - temp tag
CStr hotkeyTag ( " " ) ;
// -- MT
2003-11-03 17:22:45 +01:00
// Now we can iterate all attributes and store
2004-07-08 17:23:47 +02:00
for ( i = 0 ; i < attributes . Count ; + + i )
2003-11-03 17:22:45 +01:00
{
2004-07-08 17:23:47 +02:00
XMBAttribute attr = attributes . item ( i ) ;
2003-11-03 17:22:45 +01:00
2004-05-29 06:06:50 +02:00
// If value is "null", then it is equivalent as never being entered
2004-07-11 20:18:54 +02:00
if ( ( CStr ) attr . Value = = ( CStr ) " null " )
2004-05-29 06:06:50 +02:00
continue ;
2003-12-01 08:06:55 +01:00
// Ignore "type" and "style", we've already checked it
2004-07-17 19:09:33 +02:00
if ( attr . Name = = attr_type | | attr . Name = = attr_style )
2003-11-03 17:22:45 +01:00
continue ;
// Also the name needs some special attention
2004-07-08 17:23:47 +02:00
if ( attr . Name = = attr_name )
2003-11-03 17:22:45 +01:00
{
2004-07-10 22:56:15 +02:00
object - > SetName ( ( CStr ) attr . Value ) ;
2003-11-03 17:22:45 +01:00
NameSet = true ;
continue ;
}
2004-07-22 18:18:12 +02:00
// MT - temp tag
// Wire up the hotkey tag, if it has one
if ( attr . Name = = attr_hotkey )
hotkeyTag = attr . Value ;
// -- MT
2004-07-08 17:23:47 +02:00
if ( attr . Name = = attr_z )
2003-12-27 07:26:03 +01:00
ManuallySetZ = true ;
2004-07-17 19:09:33 +02:00
// Generate "stretched:filename" sprites.
//
// Check whether it's actually one of the many sprite... parameters.
if ( pFile - > getAttributeString ( attr . Name ) . substr ( 0 , 6 ) = = " sprite " )
{
// Check whether it's a special stretched one
2004-07-27 02:26:51 +02:00
std : : string SpriteName = CStr8 ( attr . Value ) . c_str ( ) ;
2004-07-17 19:09:33 +02:00
if ( SpriteName . substr ( 0 , 10 ) = = " stretched: " & &
m_Sprites . find ( SpriteName ) = = m_Sprites . end ( ) )
{
std : : string TexFilename = " art/textures/ui/ " ;
TexFilename + = SpriteName . substr ( 10 ) ;
Handle tex = tex_load ( TexFilename . c_str ( ) ) ;
if ( tex < = 0 )
{
2004-08-15 22:57:31 +02:00
LOG ( ERROR , LOG_CATEGORY , " Error opening texture '%s': %lld " , TexFilename . c_str ( ) , tex ) ;
2004-07-17 19:09:33 +02:00
}
2004-08-26 12:31:34 +02:00
else
{
CGUISprite sprite ;
SGUIImage image ;
CStr DefaultSize ( " 0 0 100% 100% " ) ;
image . m_TextureSize = CClientArea ( DefaultSize ) ;
image . m_Size = CClientArea ( DefaultSize ) ;
image . m_TextureName = TexFilename ;
image . m_Texture = tex ;
tex_upload ( tex ) ;
2004-07-17 19:09:33 +02:00
2004-08-26 12:31:34 +02:00
sprite . AddImage ( image ) ;
m_Sprites [ SpriteName ] = sprite ;
}
2004-07-17 19:09:33 +02:00
}
}
2003-11-03 17:22:45 +01:00
// Try setting the value
try
{
2004-07-10 22:56:15 +02:00
object - > SetSetting ( pFile - > getAttributeString ( attr . Name ) , ( CStr ) attr . Value ) ;
2003-11-03 17:22:45 +01:00
}
catch ( PS_RESULT e )
{
2004-05-29 13:59:59 +02:00
UNUSED ( e ) ;
2004-07-10 22:56:15 +02:00
ReportParseError ( CStr ( " Can't set \" " ) + pFile - > getAttributeString ( attr . Name ) + CStr ( " \" to \" " ) + ( CStr ) attr . Value + CStr ( " \" " ) ) ;
2003-11-03 17:22:45 +01:00
// This is not a fatal error
}
}
2004-05-29 06:06:50 +02:00
// Check if name isn't set, generate an internal name in that case.
2003-11-03 17:22:45 +01:00
if ( ! NameSet )
{
2004-05-29 06:06:50 +02:00
object - > SetName ( CStr ( " __internal( " ) + CStr ( m_InternalNameNumber ) + CStr ( " ) " ) ) ;
+ + m_InternalNameNumber ;
2003-11-03 17:22:45 +01:00
}
2004-07-22 18:18:12 +02:00
// MT - temp tag
// Attempt to register the hotkey tag, if one was provided
if ( hotkeyTag . Length ( ) )
hotkeyRegisterGUIObject ( object - > GetName ( ) , hotkeyTag ) ;
// -- MT
2004-07-08 17:23:47 +02:00
2004-07-10 22:56:15 +02:00
CStr caption = ( CStr ) Element . getText ( ) ;
2004-07-08 17:23:47 +02:00
caption . Trim ( PS_TRIM_BOTH ) ;
if ( caption . Length ( ) )
{
try
{
// Set the setting caption to this
object - > SetSetting ( " caption " , caption ) ;
}
2004-07-14 00:48:53 +02:00
catch ( PS_RESULT )
2004-07-08 17:23:47 +02:00
{
// There is no harm if the object didn't have a "caption"
}
}
2003-11-03 17:22:45 +01:00
//
// Read Children
//
// Iterate children
2004-07-08 17:23:47 +02:00
XMBElementList children = Element . getChildNodes ( ) ;
2003-11-03 17:22:45 +01:00
2004-07-08 17:23:47 +02:00
for ( i = 0 ; i < children . Count ; + + i )
2003-11-03 17:22:45 +01:00
{
// Get node
2004-07-08 17:23:47 +02:00
XMBElement child = children . item ( i ) ;
2003-11-03 17:22:45 +01:00
2004-07-08 17:23:47 +02:00
// Check what name the elements got
int element_name = child . getNodeName ( ) ;
2003-11-03 17:22:45 +01:00
2004-07-08 17:23:47 +02:00
if ( element_name = = elmt_object )
{
2004-08-10 18:04:21 +02:00
//debug_warn("CGUI::Xeromyces_ReadObject error");
// janwas: this happens but looks to be handled
2004-07-08 17:23:47 +02:00
// TODO Gee: REPORT ERROR
2003-11-03 17:22:45 +01:00
2004-07-08 17:23:47 +02:00
// Call this function on the child
Xeromyces_ReadObject ( child , pFile , object ) ;
2003-11-03 17:22:45 +01:00
}
2004-07-08 17:23:47 +02:00
else if ( element_name = = elmt_action )
2003-11-03 17:22:45 +01:00
{
2004-07-11 18:22:35 +02:00
// Scripted <action> element
// Check for a 'file' parameter
2004-07-11 20:18:54 +02:00
CStr file ( child . getAttributes ( ) . getNamedItem ( attr_file ) ) ;
2004-07-11 18:22:35 +02:00
CStr code ;
// If there is a file, open it and use it as the code
if ( file . Length ( ) )
{
2004-07-29 18:17:21 +02:00
CVFSFile scriptfile ;
if ( scriptfile . Load ( file ) ! = PSRETURN_OK )
2004-07-11 18:22:35 +02:00
{
2004-08-15 22:57:31 +02:00
LOG ( ERROR , LOG_CATEGORY , " Error opening action file '%s' " , file . c_str ( ) ) ;
2004-07-17 19:09:33 +02:00
throw PSERROR_GUI_JSOpenFailed ( ) ;
}
2004-07-11 18:22:35 +02:00
2004-07-29 18:17:21 +02:00
code = scriptfile . GetAsString ( ) ;
2004-07-11 18:22:35 +02:00
}
// Read the inline code (concatenating to the file code, if both are specified)
2004-07-11 20:18:54 +02:00
code + = ( CStr ) child . getText ( ) ;
2004-07-11 18:22:35 +02:00
2004-07-10 22:56:15 +02:00
CStr action = ( CStr ) child . getAttributes ( ) . getNamedItem ( attr_on ) ;
2004-07-11 18:22:35 +02:00
object - > RegisterScriptHandler ( action . LowerCase ( ) , code , this ) ;
2003-11-03 17:22:45 +01:00
}
2003-12-01 08:06:55 +01:00
}
2003-11-03 17:22:45 +01:00
2003-12-27 07:26:03 +01:00
//
// Check if Z wasn't manually set
//
if ( ! ManuallySetZ )
{
// Set it automatically to 10 plus its parents
if ( pParent = = NULL )
{
2004-08-10 18:04:21 +02:00
debug_warn ( " CGUI::Xeromyces_ReadObject error " ) ;
2003-12-27 07:26:03 +01:00
// TODO Gee: Report error
}
else
{
2004-05-29 06:06:50 +02:00
bool absolute ;
GUI < bool > : : GetSetting ( object , " absolute " , absolute ) ;
2003-12-27 07:26:03 +01:00
// If the object is absolute, we'll have to get the parent's Z buffered,
// and add to that!
2004-05-29 06:06:50 +02:00
if ( absolute )
2003-12-27 07:26:03 +01:00
{
GUI < float > : : SetSetting ( object , " z " , pParent - > GetBufferedZ ( ) + 10.f ) ;
}
else
// If the object is relative, then we'll just store Z as "10"
{
GUI < float > : : SetSetting ( object , " z " , 10.f ) ;
}
}
}
2003-11-03 17:22:45 +01:00
//
// Input Child
//
try
{
if ( pParent = = m_BaseObject )
AddObject ( object ) ;
else
pParent - > AddChild ( object ) ;
}
catch ( PS_RESULT e )
2003-12-01 08:06:55 +01:00
{
2003-11-03 17:22:45 +01:00
ReportParseError ( e ) ;
}
}
2004-07-11 18:22:35 +02:00
void CGUI : : Xeromyces_ReadScript ( XMBElement Element , CXeromyces * pFile )
{
// Check for a 'file' parameter
CStr file ( Element . getAttributes ( ) . getNamedItem ( pFile - > getAttributeID ( " file " ) ) ) ;
2004-07-11 20:18:54 +02:00
// If there is a file specified, open and execute it
2004-07-11 18:22:35 +02:00
if ( file . Length ( ) )
{
2004-07-29 18:17:21 +02:00
CVFSFile scriptfile ;
if ( scriptfile . Load ( file ) ! = PSRETURN_OK )
2004-07-11 18:22:35 +02:00
{
2004-08-15 22:57:31 +02:00
LOG ( ERROR , LOG_CATEGORY , " Error opening script file '%s' " , file . c_str ( ) ) ;
2004-07-17 19:09:33 +02:00
throw PSERROR_GUI_JSOpenFailed ( ) ;
2004-07-11 18:22:35 +02:00
}
2004-07-17 19:09:33 +02:00
jsval result ;
2004-07-29 18:17:21 +02:00
JS_EvaluateScript ( g_ScriptingHost . getContext ( ) , ( JSObject * ) m_ScriptObject , ( const char * ) scriptfile . GetBuffer ( ) , ( int ) scriptfile . GetBufferSize ( ) , file , 1 , & result ) ;
2004-07-11 18:22:35 +02:00
}
// Execute inline scripts
CStr code ( Element . getText ( ) ) ;
2004-07-12 17:50:12 +02:00
if ( code . Length ( ) )
{
jsval result ;
// TODO: Report the filename
JS_EvaluateScript ( g_ScriptingHost . getContext ( ) , ( JSObject * ) m_ScriptObject , code . c_str ( ) , ( int ) code . Length ( ) , " Some XML file " , Element . getLineNumber ( ) , & result ) ;
}
2004-07-11 18:22:35 +02:00
}
2004-07-08 17:23:47 +02:00
void CGUI : : Xeromyces_ReadSprite ( XMBElement Element , CXeromyces * pFile )
2003-11-03 17:22:45 +01: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
2004-07-10 22:56:15 +02:00
name = ( CStr ) Element . getAttributes ( ) . getNamedItem ( pFile - > getAttributeID ( " name " ) ) ;
2003-11-03 17:22:45 +01:00
//
// Read Children (the images)
//
// Iterate children
2004-07-08 17:23:47 +02:00
XMBElementList children = Element . getChildNodes ( ) ;
2003-11-03 17:22:45 +01:00
2004-07-08 17:23:47 +02:00
for ( int i = 0 ; i < children . Count ; + + i )
2003-11-03 17:22:45 +01:00
{
// Get node
2004-07-08 17:23:47 +02:00
XMBElement child = children . item ( i ) ;
2003-11-03 17:22:45 +01:00
2004-07-08 17:23:47 +02:00
// All Elements will be of type "image" by DTD law
2003-11-03 17:22:45 +01:00
2004-07-08 17:23:47 +02:00
// Call this function on the child
Xeromyces_ReadImage ( child , pFile , sprite ) ;
2003-11-03 17:22:45 +01:00
}
//
// Add Sprite
//
m_Sprites [ name ] = sprite ;
}
2004-07-08 17:23:47 +02:00
void CGUI : : Xeromyces_ReadImage ( XMBElement Element , CXeromyces * pFile , CGUISprite & parent )
2003-11-03 17:22:45 +01:00
{
// Image object we're adding
SGUIImage image ;
2004-07-14 00:48:53 +02:00
CStr DefaultTextureSize = " 0 0 100% 100% " ;
image . m_TextureSize = CClientArea ( DefaultTextureSize ) ;
2003-12-27 07:26:03 +01:00
// TODO Gee: Setup defaults here (or maybe they are in the SGUIImage ctor)
2003-11-03 17:22:45 +01:00
//
// Read Attributes
//
// Now we can iterate all attributes and store
2004-07-08 17:23:47 +02:00
XMBAttributeList attributes = Element . getAttributes ( ) ;
for ( int i = 0 ; i < attributes . Count ; + + i )
2003-11-03 17:22:45 +01:00
{
2004-07-08 17:23:47 +02:00
XMBAttribute attr = attributes . item ( i ) ;
2004-07-10 22:33:42 +02:00
std : : string attr_name = pFile - > getAttributeString ( attr . Name ) ;
2004-07-10 22:56:15 +02:00
CStr attr_value ( attr . Value ) ;
2003-11-03 17:22:45 +01:00
// This is the only attribute we want
2004-07-10 22:33:42 +02:00
if ( attr_name = = " texture " )
2003-11-03 17:22:45 +01:00
{
2004-07-14 00:48:53 +02:00
// Load the texture from disk now, because now's as good a time as any
std : : string TexFilename = " art/textures/ui/ " ;
TexFilename + = attr_value ;
Handle tex = tex_load ( TexFilename . c_str ( ) ) ;
if ( tex < = 0 )
{
2004-08-15 22:57:31 +02:00
LOG ( ERROR , LOG_CATEGORY , " Error opening texture '%s': %lld " , TexFilename . c_str ( ) , tex ) ;
2004-07-14 00:48:53 +02:00
}
2004-08-26 12:31:34 +02:00
else
{
image . m_TextureName = TexFilename ;
image . m_Texture = tex ;
tex_upload ( tex ) ;
}
2003-11-03 17:22:45 +01:00
}
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " size " )
2003-11-03 17:22:45 +01:00
{
2003-12-01 08:06:55 +01:00
CClientArea ca ;
if ( ! GUI < CClientArea > : : ParseString ( attr_value , ca ) )
{
2004-08-10 18:04:21 +02:00
debug_warn ( " CGUI::Xeromyces_ReadImage error " ) ;
2003-12-27 07:26:03 +01:00
// TODO Gee: Error
2003-12-01 08:06:55 +01:00
}
else image . m_Size = ca ;
}
else
2004-07-14 00:48:53 +02:00
if ( attr_name = = " texture-size " )
{
CClientArea ca ;
if ( ! GUI < CClientArea > : : ParseString ( attr_value , ca ) )
{
2004-08-10 18:04:21 +02:00
debug_warn ( " CGUI::Xeromyces_ReadImage error " ) ;
2004-07-14 00:48:53 +02:00
// TODO Gee: Error
}
else image . m_TextureSize = ca ;
}
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " z-level " )
2004-05-29 06:06:50 +02:00
{
int z_level ;
if ( ! GUI < int > : : ParseString ( attr_value , z_level ) )
{
2004-08-10 18:04:21 +02:00
debug_warn ( " CGUI::Xeromyces_ReadImage error " ) ;
2004-05-29 06:06:50 +02:00
// TODO Gee: Error
}
else image . m_DeltaZ = ( float ) z_level / 100.f ;
}
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " backcolor " )
2003-12-01 08:06:55 +01:00
{
CColor color ;
if ( ! GUI < CColor > : : ParseString ( attr_value , color ) )
{
2004-08-10 18:04:21 +02:00
debug_warn ( " CGUI::Xeromyces_ReadImage error " ) ;
2003-12-27 07:26:03 +01:00
// TODO Gee: Error
2003-12-01 08:06:55 +01:00
}
else image . m_BackColor = color ;
}
else
{
2004-08-10 18:04:21 +02:00
debug_warn ( " CGUI::Xeromyces_ReadImage error " ) ;
2003-12-27 07:26:03 +01:00
// TODO Gee: Log
2003-12-01 08:06:55 +01:00
//g_console.submit("echo Error attribute " + attr_name + " is not expected in <image>");
2003-11-03 17:22:45 +01:00
return ;
}
}
2003-12-01 08:06:55 +01:00
2003-11-03 17:22:45 +01:00
//
// Input
//
parent . AddImage ( image ) ;
}
2003-12-01 08:06:55 +01:00
2004-07-08 17:23:47 +02:00
void CGUI : : Xeromyces_ReadStyle ( XMBElement Element , CXeromyces * pFile )
2003-12-01 08:06:55 +01:00
{
// style object we're adding
SGUIStyle style ;
CStr name ;
//
// Read Attributes
//
// Now we can iterate all attributes and store
2004-07-08 17:23:47 +02:00
XMBAttributeList attributes = Element . getAttributes ( ) ;
for ( int i = 0 ; i < attributes . Count ; + + i )
2003-12-01 08:06:55 +01:00
{
2004-07-08 17:23:47 +02:00
XMBAttribute attr = attributes . item ( i ) ;
2004-07-10 22:33:42 +02:00
std : : string attr_name = pFile - > getAttributeString ( attr . Name ) ;
2004-07-10 22:56:15 +02:00
CStr attr_value ( attr . Value ) ;
2003-12-01 08:06:55 +01:00
// The "name" setting is actually the name of the style
// and not a new default
2004-07-10 22:33:42 +02:00
if ( attr_name = = " name " )
2003-12-01 08:06:55 +01:00
name = attr_value ;
else
2004-07-10 22:33:42 +02:00
style . m_SettingsDefaults [ attr_name ] = attr_value ;
2003-12-01 08:06:55 +01:00
}
//
// Add to CGUI
//
m_Styles [ name ] = style ;
}
2003-12-27 07:26:03 +01:00
2004-07-08 17:23:47 +02:00
void CGUI : : Xeromyces_ReadScrollBarStyle ( XMBElement Element , CXeromyces * pFile )
2003-12-27 07:26:03 +01:00
{
// style object we're adding
SGUIScrollBarStyle scrollbar ;
CStr name ;
//
// Read Attributes
//
// Now we can iterate all attributes and store
2004-07-08 17:23:47 +02:00
XMBAttributeList attributes = Element . getAttributes ( ) ;
for ( int i = 0 ; i < attributes . Count ; + + i )
2003-12-27 07:26:03 +01:00
{
2004-07-08 17:23:47 +02:00
XMBAttribute attr = attributes . item ( i ) ;
2004-07-10 22:33:42 +02:00
std : : string attr_name = pFile - > getAttributeString ( attr . Name ) ;
2004-07-10 22:56:15 +02:00
CStr attr_value ( attr . Value ) ;
2003-12-27 07:26:03 +01:00
2004-05-29 06:06:50 +02:00
if ( attr_value = = CStr ( " null " ) )
continue ;
2004-07-10 22:33:42 +02:00
if ( attr_name = = " name " )
2003-12-27 07:26:03 +01:00
name = attr_value ;
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " width " )
2003-12-27 07:26:03 +01:00
{
int i ;
if ( ! GUI < int > : : ParseString ( attr_value , i ) )
{
// TODO Gee: Report in log file
}
scrollbar . m_Width = i ;
}
2004-05-29 06:06:50 +02:00
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " minimum-bar-size " )
2004-05-29 06:06:50 +02:00
{
int i ;
if ( ! GUI < int > : : ParseString ( attr_value , i ) )
{
// TODO Gee: Report in log file
}
scrollbar . m_MinimumBarSize = i ;
}
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " sprite-button-top " )
2004-05-29 06:06:50 +02:00
scrollbar . m_SpriteButtonTop = attr_value ;
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " sprite-button-top-pressed " )
2004-05-29 06:06:50 +02:00
scrollbar . m_SpriteButtonTopPressed = attr_value ;
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " sprite-button-top-disabled " )
2004-05-29 06:06:50 +02:00
scrollbar . m_SpriteButtonTopDisabled = attr_value ;
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " sprite-button-top-over " )
2004-05-29 06:06:50 +02:00
scrollbar . m_SpriteButtonTopOver = attr_value ;
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " sprite-button-bottom " )
2004-05-29 06:06:50 +02:00
scrollbar . m_SpriteButtonBottom = attr_value ;
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " sprite-button-bottom-pressed " )
2004-05-29 06:06:50 +02:00
scrollbar . m_SpriteButtonBottomPressed = attr_value ;
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " sprite-button-bottom-disabled " )
2004-05-29 06:06:50 +02:00
scrollbar . m_SpriteButtonBottomDisabled = attr_value ;
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " sprite-button-bottom-over " )
2004-05-29 06:06:50 +02:00
scrollbar . m_SpriteButtonBottomOver = attr_value ;
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " sprite-back-vertical " )
2004-05-29 06:06:50 +02:00
scrollbar . m_SpriteBackVertical = attr_value ;
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " sprite-bar-vertical " )
2004-05-29 06:06:50 +02:00
scrollbar . m_SpriteBarVertical = attr_value ;
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " sprite-bar-vertical-over " )
2004-05-29 06:06:50 +02:00
scrollbar . m_SpriteBarVerticalOver = attr_value ;
else
2004-07-10 22:33:42 +02:00
if ( attr_name = = " sprite-bar-vertical-pressed " )
2004-05-29 06:06:50 +02:00
scrollbar . m_SpriteBarVerticalPressed = attr_value ;
/*
CStr m_SpriteButtonTop ;
CStr m_SpriteButtonTopPressed ;
CStr m_SpriteButtonTopDisabled ;
CStr m_SpriteButtonBottom ;
CStr m_SpriteButtonBottomPressed ;
CStr m_SpriteButtonBottomDisabled ;
CStr m_SpriteScrollBackHorizontal ;
CStr m_SpriteScrollBarHorizontal ;
CStr m_SpriteButtonLeft ;
CStr m_SpriteButtonLeftPressed ;
CStr m_SpriteButtonLeftDisabled ;
CStr m_SpriteButtonRight ;
CStr m_SpriteButtonRightPressed ;
CStr m_SpriteButtonRightDisabled ;
CStr m_SpriteScrollBackVertical ;
CStr m_SpriteScrollBarVertical ;
*/
2003-12-27 07:26:03 +01:00
}
//
// Add to CGUI
//
m_ScrollBarStyles [ name ] = scrollbar ;
}