etqw-sdk/source/game/decls/DeclGUI.cpp
2008-05-29 00:00:00 +00:00

937 lines
21 KiB
C++

// Copyright (C) 2007 Id Software, Inc.
//
#include "precompiled.h"
#pragma hdrstop
#include "DeclGUI.h"
#include "../../framework/DeclParseHelper.h"
#include "../guis/UserInterfaceManager.h"
#include "../../framework/Licensee.h"
const char sdDeclGUIProperty_Identifier[] = "sdDeclGUIProperty";
const char sdDeclGUITimeEvent_Identifier[] = "sdDeclGUITimeEvent";
const char sdDeclGUITimeline_Identifier[] = "sdDeclGUITimeline";
const char sdDeclGUIEvent_Identifier[] = "sdDeclGUIEvent";
const char sdDeclGUIWindow_Identifier[] = "sdDeclGUIWindow";
/*
===============================================================================
sdDeclGUIWindow
===============================================================================
*/
idStrPool sdDeclGUIWindow::s_strPool;
/*
================
sdDeclGUIWindow::sdDeclGUIWindow
================
*/
sdDeclGUIWindow::sdDeclGUIWindow( void ) : properties(1), events(1), children(1)
#ifdef _DEBUG
,breakOnDraw( false ), breakOnLayout( false )
#endif
{
type = s_strPool.AllocString( "window" );
}
/*
================
sdDeclGUIWindow::~sdDeclGUIWindow
================
*/
sdDeclGUIWindow::~sdDeclGUIWindow( void ) {
properties.DeleteContents( true );
events.DeleteContents( true );
}
/*
================
sdDeclGUIWindow::ParseEvents
================
*/
bool sdDeclGUIWindow::ParseEvents( idList< sdDeclGUIEvent* >& events, idLexer& src ) {
if ( !src.ExpectTokenString( "{" ) ) {
return false;
}
idToken token;
while ( true ) {
if( !src.ReadToken( &token ) ) {
src.Error( "Unexpected End of File" );
return false;
}
if ( !token.Cmp( "}" ) ) {
break;
}
sdDeclGUIEvent* event = new sdDeclGUIEvent();
if ( !event->Parse( src, token ) ) {
delete event;
return false;
}
events.Alloc() = event;
}
return true;
}
/*
================
sdDeclGUIWindow::ParseProperties
================
*/
bool sdDeclGUIWindow::ParseProperties( idList< sdDeclGUIProperty* >& properties, idLexer& src ) {
if ( !src.ExpectTokenString( "{" ) ) {
return false;
}
idToken token;
while ( true ) {
if( !src.ReadToken( &token ) ) {
src.Error( "Unexpected End of File" );
return false;
}
if ( !token.Cmp( "}" ) ) {
break;
}
sdDeclGUIProperty* property = new sdDeclGUIProperty();
if ( !property->Parse( src, token ) ) {
delete property;
return false;
}
properties.Alloc() = property;
}
return true;
}
/*
================
sdDeclGUITimelineHolder::ParseTimeline
================
*/
bool sdDeclGUITimelineHolder::ParseTimeline( idLexer& src ) {
idToken token;
if( !src.ReadToken( &token ) ) {
src.Error( "Unexpected End of File" );
return false;
}
sdDeclGUITimeline* timeline = NULL;
const char* name = GUI_DEFAULT_TIMELINE_NAME;
if( token == "{" ) {
src.UnreadToken( &token );
} else {
name = token.c_str();
}
declTimelineHash_t::Iterator iter = timelines.Find( name );
if( iter == timelines.End() ) {
timeline = new sdDeclGUITimeline;
timelines.Set( name, timeline );
} else {
timeline = iter->second;
}
if ( !src.ExpectTokenString( "{" ) ) {
return false;
}
while ( true ) {
if( !src.ReadToken( &token ) ) {
src.Error( "Unexpected End of File" );
return false;
}
if ( !token.Cmp( "}" ) ) {
break;
}
if ( !token.Icmp( "properties" ) ) {
if ( !sdDeclGUIWindow::ParseProperties( timeline->GetProperties(), src ) ) {
src.Error( "Error Parsing Properties" );
return false;
}
continue;
}
sdDeclGUITimeEvent* timeEvent = new sdDeclGUITimeEvent();
if ( !timeEvent->Parse( src, token ) ) {
delete timeEvent;
return false;
}
timeline->GetEvents().Alloc() = timeEvent;
}
return true;
}
/*
================
sdDeclGUIWindow::Parse
================
*/
bool sdDeclGUIWindow::Parse( idLexer& src, sdDeclGUI* declGui ) {
idToken token;
if ( !src.ReadToken( &token ) ) {
src.Error( "Unexpected End of File" );
return false;
}
if ( token.type != TT_NAME ) {
src.Error( "Invalid Window Name '%s'", name.c_str() );
return false;
}
name = token;
if ( !src.ExpectTokenString( "{" ) ) {
return false;
}
while ( true ) {
if( !src.ReadToken( &token ) ) {
src.Error( "%s Unexpected End of File", name.c_str() );
return false;
}
if ( !token.Cmp( "}" ) ) {
break;
}
#ifdef _DEBUG
if ( !token.Icmp( "breakOnParse" ) ) {
assert( 0 );
continue;
}
#endif
if ( !token.Icmp( "windowDef" ) ) {
sdDeclGUIWindow* window = declGui->ParseWindow( src );
if( window == NULL ) {
return false;
}
children.Append( window->GetName() );
continue;
}
if ( !token.Icmp( "breakOnDraw" ) ) {
#ifdef _DEBUG
breakOnDraw = true;
#endif
continue;
}
if ( !token.Icmp( "breakOnLayout" ) ) {
#ifdef _DEBUG
breakOnLayout = true;
#endif
continue;
}
if ( !token.Icmp( "type" ) ) {
if ( !src.ReadToken( &token ) ) {
src.Error( "%s Unexpected End of File", name.c_str() );
return false;
}
type = s_strPool.AllocString( token.c_str() );
src.ExpectTokenString( ";" );
} else if ( !token.Icmp( "properties" ) ) {
if ( !ParseProperties( properties, src ) ) {
src.Error( "%s Error Parsing Properties", name.c_str() );
return false;
}
} else if ( !token.Icmp( "events" ) ) {
if ( !ParseEvents( events, src ) ) {
src.Error( "%s Error Parsing Events", name.c_str() );
return false;
}
} else if ( !token.Icmp( "timeline" ) ) {
if ( !timelines.ParseTimeline( src ) ) {
src.Error( "%s Error Parsing Timeline", name.c_str() );
return false;
}
} else {
src.Error( "%s unexpected token '%s'", name.c_str(), token.c_str() );
return false;
}
}
return true;
}
/*
============
sdDeclGUITimelineHolder::GetTimeline
============
*/
const sdDeclGUITimeline* sdDeclGUITimelineHolder::GetTimeline( int index ) const {
return timelines.FindIndex( index )->second;
}
/*
============
sdDeclGUITimelineHolder::GetTimelineName
============
*/
const char* sdDeclGUITimelineHolder::GetTimelineName( int index ) const {
return timelines.FindIndex( index )->first;
}
/*
===============================================================================
sdDeclGUITimeEvent
===============================================================================
*/
/*
================
sdDeclGUITimeEvent::sdDeclGUITimeEvent
================
*/
sdDeclGUITimeEvent::sdDeclGUITimeEvent( void ) {
startTime = -1;
}
/*
================
sdDeclGUITimeEvent::~sdDeclGUITimeEvent
================
*/
sdDeclGUITimeEvent::~sdDeclGUITimeEvent( void ) {
}
/*
================
sdDeclGUITimeEvent::Parse
================
*/
bool sdDeclGUITimeEvent::Parse( idLexer& src, const idToken& nameToken ) {
tokens.Clear();
int line = src.GetLineNum();
if ( nameToken.Icmp( "onTime" ) ) {
src.Error( "%s Events in the Timeline Must be Called onTime", nameToken.c_str() );
return false;
}
idToken token;
if ( !src.ReadToken( &token ) ) {
src.Error( "%s Unexpected End of File", nameToken.c_str() );
return false;
}
if ( token.type != TT_NUMBER || !( token.subtype & TT_INTEGER ) ) {
src.Error( "%s Start Time Must be an Integer", nameToken.c_str() );
return false;
}
startTime = token.GetIntValue();
if( !sdDeclGUI::ParseBracedSection( src, tokens ) ) {
src.Error( "%s Error Parsing Text", nameToken.c_str() );
return false;
}
return true;
}
/*
===============================================================================
sdDeclGUIEvent
===============================================================================
*/
/*
================
sdDeclGUIEvent::sdDeclGUIEvent
================
*/
sdDeclGUIEvent::sdDeclGUIEvent( void ) : flags( 1 ) {
name = -1;
}
/*
================
sdDeclGUIEvent::~sdDeclGUIEvent
================
*/
sdDeclGUIEvent::~sdDeclGUIEvent( void ) {
}
/*
================
sdDeclGUIEvent::Parse
================
*/
bool sdDeclGUIEvent::Parse( idLexer& src, const idToken& nameToken ) {
int line = src.GetLineNum();
if ( nameToken.type != TT_NAME ) {
src.Error( "'%s' Invalid Name For Event", nameToken.c_str() );
return false;
}
name = nameToken.GetBinaryIndex();
idToken token;
while ( true ) {
if ( !src.ReadToken( &token ) ) {
src.Error( "%s Unexpected End of File", nameToken.c_str() );
return false;
}
if ( !token.Cmp( "{" ) ) {
src.UnreadToken( &token );
break;
}
flags.Alloc() = token.GetBinaryIndex();
}
if ( !sdDeclGUI::ParseBracedSection( src, tokens ) ) {
src.Error( "%s Error Parsing Event Text", nameToken.c_str() );
return false;
}
return true;
}
/*
===============================================================================
sdDeclGUIProperty
===============================================================================
*/
/*
================
sdDeclGUIProperty::sdDeclGUIProperty
================
*/
sdDeclGUIProperty::sdDeclGUIProperty( void ) {
type = -1;
name = -1;
}
/*
================
sdDeclGUIProperty::~sdDeclGUIProperty
================
*/
sdDeclGUIProperty::~sdDeclGUIProperty( void ) {
}
/*
================
sdDeclGUIProperty::Parse
================
*/
bool sdDeclGUIProperty::Parse( idLexer& src, const idToken& typeName ) {
type = typeName.GetBinaryIndex();
idToken token;
if ( !src.ReadToken( &token ) ) {
src.Error( "Unexpected End of File" );
return false;
}
if ( token.type != TT_NAME ) {
src.Error( "'%s' Invalid Name for Property", token.c_str() );
return false;
}
idStr nameStr = token;
name = token.GetBinaryIndex();
if ( !src.ReadToken( &token ) ) {
src.Error( "Unexpected End of File" );
return false;
}
if ( !token.Icmp( ";" ) ) {
return true;
} else if ( !token.Icmp( "=" ) ) {
while ( true ) {
if ( !src.ReadToken( &token ) ) {
src.Error( "%s Unexpected End of File", nameStr.c_str() );
return false;
}
if ( !token.Cmp( "}" ) ) {
src.Error( "%s Unexpected '}'", nameStr.c_str() );
return false;
}
if ( !token.Icmp( ";" ) ) {
if ( value.Empty() ) {
src.Error( "%s Unexpected ';'", nameStr.c_str() );
return false;
}
value.Append( token.GetBinaryIndex() );
break;
} else {
value.Append( token.GetBinaryIndex() );
}
}
return true;
}
src.Error( "Unexpected Token '%s'", token.c_str() );
return false;
}
/*
===============================================================================
sdDeclGUI
===============================================================================
*/
idStrList sdDeclGUI::defines( 32 );
/*
================
sdDeclGUI::sdDeclGUI
================
*/
sdDeclGUI::sdDeclGUI( void ) :
windows( 8 ),
properties( 1 ),
events( 1 )
#ifdef _DEBUG
,breakOnDraw( false )
#endif
{
}
/*
================
sdDeclGUI::~sdDeclGUI
================
*/
sdDeclGUI::~sdDeclGUI( void ) {
FreeData();
}
/*
================
sdDeclGUI::DefaultDefinition
================
*/
const char* sdDeclGUI::DefaultDefinition( void ) const {
return \
"{\n" \
"\twindowDef desktop {\n" \
"\t}\n" \
"}\n";
}
/*
============
sdDeclGUI::ParseWindow
============
*/
sdDeclGUIWindow* sdDeclGUI::ParseWindow( idLexer& src ) {
sdDeclGUIWindow* window = new sdDeclGUIWindow();
if ( !window->Parse( src, this ) ) {
delete window;
src.Error( "Error Parsing Window" );
return NULL;
} else {
windows.Alloc() = window;
}
return window;
}
/*
================
sdDeclGUI::Parse
================
*/
bool sdDeclGUI::Parse( const char *text, const int textLength ) {
idToken token;
idParser src;
src.SetFlags( LEXER_FLAGS );
bool binary = HasBinaryBuffer();
if( !binary ) {
// init code-generated #defines
for( int i = 0; i < defines.Num(); i++ ) {
src.AddDefine( defines[ i ] );
}
src.AddDefine( "true 1" );
src.AddDefine( "false 0" );
}
sdDeclParseHelper declHelper( this, text, textLength, src );
const byte* parseOutput;
int parseOutputLength;
declHelper.GetBinaryBuffer( parseOutput, parseOutputLength );
idLexer binarySrc;
if( !binarySrc.LoadMemoryBinary( parseOutput, parseOutputLength, GetFileName(), &declManager->GetGlobalTokenCache() ) ) {
binarySrc.Error( "Couldn't load binary data." );
return false;
}
binarySrc.SkipUntilString( "{", &token );
idDict tempDict;
while( true ) {
if ( !binarySrc.ReadToken( &token ) ) {
binarySrc.Error( "Unexpected End of File" );
return false;
}
if ( !token.Cmp( "}" ) ) {
break;
}
if ( !token.Icmp( "breakOnDraw" ) ) {
#ifdef _DEBUG
breakOnDraw = true;
#endif
continue;
}
if ( !token.Icmp( "windowDef" ) ) {
sdDeclGUIWindow* window = ParseWindow( binarySrc );
if( window == NULL ) {
return false;
}
} else if ( !token.Icmp( "properties" ) ) {
if ( !sdDeclGUIWindow::ParseProperties( properties, binarySrc ) ) {
binarySrc.Error( "Error Parsing Properties" );
return false;
}
} else if ( !token.Icmp( "events" ) ) {
if ( !sdDeclGUIWindow::ParseEvents( events, binarySrc ) ) {
binarySrc.Error( "Error Parsing Events" );
return false;
}
} else if ( !token.Icmp( "timeline" ) ) {
if ( !timelines.ParseTimeline( binarySrc ) ) {
binarySrc.Error( "Error Parsing Timeline" );
return false;
}
} else if ( !token.Icmp( "sounds" ) ) {
tempDict.Clear();
if ( !tempDict.Parse( binarySrc ) ) {
binarySrc.Error( "Error Parsing sound table" );
return false;
}
sounds.SetDefaults( &tempDict );
} else if ( !token.Icmp( "materials" ) ) {
tempDict.Clear();
if ( !tempDict.Parse( binarySrc ) ) {
binarySrc.Error( "Error Parsing material table" );
return false;
}
materials.SetDefaults( &tempDict );
} else if ( !token.Icmp( "colors" ) ) {
tempDict.Clear();
if ( !tempDict.Parse( binarySrc ) ) {
binarySrc.Error( "Error Parsing color table" );
return false;
}
colors.SetDefaults( &tempDict );
} else if ( !token.Icmp( "atmospheres" ) ) {
tempDict.Clear();
if ( !tempDict.Parse( binarySrc ) ) {
binarySrc.Error( "Error Parsing atmosphere pre-cache table" );
return false;
}
for( int i = 0 ; i < tempDict.GetNumKeyVals(); i++ ) {
const idKeyValue* kv = tempDict.GetKeyVal( i );
if( !kv->GetKey().IsEmpty() ) {
gameLocal.declAtmosphereType[ kv->GetKey().c_str() ];
}
}
} else if ( !token.Icmp( "models" ) ) {
tempDict.Clear();
if ( !tempDict.Parse( binarySrc ) ) {
binarySrc.Error( "Error Parsing models pre-cache table" );
return false;
}
for( int i = 0 ; i < tempDict.GetNumKeyVals(); i++ ) {
const idKeyValue* kv = tempDict.GetKeyVal( i );
if( !kv->GetKey().IsEmpty() ) {
renderModelManager->FindModel( kv->GetKey().c_str() );
}
}
} else if ( !token.Icmp( "touchFiles" ) ) {
tempDict.Clear();
if ( !tempDict.Parse( binarySrc ) ) {
binarySrc.Error( "Error Parsing file touch pre-cache table" );
return false;
}
for( int i = 0 ; i < tempDict.GetNumKeyVals(); i++ ) {
const idKeyValue* kv = tempDict.GetKeyVal( i );
if( !kv->GetKey().IsEmpty() ) {
sdFilePtr f( fileSystem->OpenFileRead( kv->GetKey().c_str(), true ) );
if( !f.IsValid() ) {
binarySrc.Warning( "Could not touch '%s'", kv->GetKey().c_str() );
}
}
}
}
else if ( !token.Icmp( "touchFolders" ) ) {
tempDict.Clear();
if ( !tempDict.Parse( binarySrc ) ) {
binarySrc.Error( "Error Parsing folder touch pre-cache table" );
return false;
}
for( int i = 0 ; i < tempDict.GetNumKeyVals(); i++ ) {
const idKeyValue* kv = tempDict.GetKeyVal( i );
if( !kv->GetKey().IsEmpty() ) {
idFileList* fl = fileSystem->ListFiles( kv->GetKey().c_str(), kv->GetValue().c_str() );
sdStringBuilder_Heap base;
for( int i = 0; i < fl->GetNumFiles(); i++ ) {
base = fl->GetBasePath();
base += "/";
base += fl->GetFile( i );
sdFilePtr f( fileSystem->OpenFileRead( base.c_str(), true ) );
assert( f.IsValid() );
}
fileSystem->FreeFileList( fl );
}
}
} else if ( !token.Icmp( "partialLoadModels" ) ) {
// these aren't touched here and must be explicitly loaded by code
// make sure any models referenced here are precached properly!
tempDict.Clear();
if ( !tempDict.Parse( binarySrc ) ) {
binarySrc.Error( "Error Parsing partial load models pre-cache table" );
return false;
}
for( int i = 0 ; i < tempDict.GetNumKeyVals(); i++ ) {
const idKeyValue* kv = tempDict.GetKeyVal( i );
if( !kv->GetKey().IsEmpty() ) {
partialLoadModels.Append( kv->GetKey() );
}
}
} else {
binarySrc.Error( "Unknown token '%s'", token.c_str() );
return false;
}
}
// jrad - precaching
const idKeyValue* kv;
CacheMaterialDictionary( GetName(), materials );
for( int i = 0 ; i < sounds.GetNumKeyVals(); i++ ) {
kv = sounds.GetKeyVal( i );
if( kv->GetValue().Length() ) {
gameLocal.declSoundShaderType[ kv->GetValue() ];
}
}
return true;
}
/*
============
sdDeclGUI::CacheMaterialDictionary
============
*/
void sdDeclGUI::CacheMaterialDictionary( const char* name, const idDict& materials ) {
const idKeyValue* kv;
idToken token;
for( int i = 0 ; i < materials.GetNumKeyVals(); i++ ) {
kv = materials.GetKeyVal( i );
if( kv->GetValue().Length() ) {
idLexer src( kv->GetValue(), kv->GetValue().Length(), "LookupMaterial", LEXFL_ALLOWPATHNAMES );
// jrad - gross copy and paste from sdUIWindow::ParseMaterial
while( !src.HadError() ) {
if( !src.ReadToken( &token )) {
break;
}
if( token.Icmp( "literal:" ) == 0 ) {
continue;
}
if( token.Icmp( "_frame" ) == 0 ) {
continue;
}
if( token.Icmp( "_st" ) == 0 ) {
continue;
}
if( token.Icmp( "_3v" ) == 0 ) {
continue;
}
if( token.Icmp( "_3h" ) == 0 ) {
continue;
}
if( token.Icmp( "_5h" ) == 0 ) {
continue;
}
if( token.Icmp( "_size" ) == 0 ) {
src.ParseInt();
src.ExpectTokenString( "," );
src.ParseInt();
continue;
}
if( token == "::" ) {
continue;
}
break;
}
if( gameLocal.declMaterialType[ token ] == NULL ) {
gameLocal.Warning( "%s: Couldn't precache material '%s'", name, token.c_str() );
}
}
}
}
/*
================
sdDeclGUI::FreeData
================
*/
void sdDeclGUI::FreeData( void ) {
windows.DeleteContents( true );
properties.DeleteContents( true );
events.DeleteContents( true );
timelines.Clear();
colors.Clear();
materials.Clear();
sounds.Clear();
partialLoadModels.Clear();
}
/*
================
sdDeclGUI::CacheFromDict
================
*/
void sdDeclGUI::CacheFromDict( const idDict& dict ) {
const idKeyValue* kv = NULL;
while( kv = dict.MatchPrefix( "gui", kv ) ) {
if ( kv->GetValue().Length() ) {
gameLocal.declGUIType[ kv->GetValue() ];
}
}
}
/*
============
sdDeclGUI::ParseBracedSection
============
*/
bool sdDeclGUI::ParseBracedSection( idLexer& src, idList< unsigned short >& tokens, const char* open, const char* close ) {
idToken token;
if( !src.ReadToken( &token ) ) {
return false;
}
if( token != open ) {
return false;
}
tokens.Append( token.GetBinaryIndex() );
int numBraces = 1;
while( numBraces > 0 ) {
if( !src.ReadToken( &token ) ) {
return false;
}
tokens.Append( token.GetBinaryIndex() );
if( token.Cmp( open ) == 0 ) {
numBraces++;
continue;
}
if( token.Cmp( close ) == 0 ) {
numBraces--;
continue;
}
}
tokens.Condense();
return true;
}
/*
============
sdDeclGUI::CreateConstructor
============
*/
bool sdDeclGUI::CreateConstructor( const idList<sdDeclGUIProperty*>& properties, idList<unsigned short>& tokens, idTokenCache& tokenCache ) {
tokens.Clear();
idToken temp;
temp = "{";
unsigned short openBrace = tokenCache.FindToken( temp );
temp = "}";
unsigned short closeBrace = tokenCache.FindToken( temp );
temp = "=";
unsigned short equals = tokenCache.FindToken( temp );
idList< unsigned short > constructorTokens;
tokens.Append( openBrace );
bool hasValues = false;
for( int i = 0; i < properties.Num(); i++ ) {
sdDeclGUIProperty* prop = properties[ i ];
if( prop->GetValue().Empty() ) {
continue;
}
tokens.Append( prop->GetName() );
tokens.Append( equals );
tokens.Append( prop->GetValue() );
hasValues = true;
}
tokens.Append( closeBrace );
return hasValues;
}