first-pass: actor descriptions in Lua
This commit is contained in:
@@ -314,6 +314,33 @@ static void MergeActorXML( XNode *pChild, const XNode *pParent )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
XNode *LoadXNodeFromLuaShowErrors( const RString &sFile )
|
||||||
|
{
|
||||||
|
RString sScript;
|
||||||
|
if( !GetFileContents(sFile, sScript) )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
Lua *L = LUA->Get();
|
||||||
|
|
||||||
|
RString sError;
|
||||||
|
if( !LuaHelpers::RunScript(L, sScript, sFile, sError, 1) )
|
||||||
|
{
|
||||||
|
lua_pop( L, 1 );
|
||||||
|
LUA->Release( L );
|
||||||
|
sError = ssprintf( "Lua runtime error: %s", sError.c_str() );
|
||||||
|
Dialog::OK( sError, "LUA_ERROR" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
XNode *pRet = XmlFileUtil::XNodeFromTable( L );
|
||||||
|
|
||||||
|
LUA->Release( L );
|
||||||
|
return pRet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If pParent is non-NULL, it's the parent node when nesting XML, which is
|
* If pParent is non-NULL, it's the parent node when nesting XML, which is
|
||||||
* used only by ActorUtil::LoadFromNode.
|
* used only by ActorUtil::LoadFromNode.
|
||||||
@@ -344,6 +371,16 @@ Actor* ActorUtil::MakeActor( const RString &sPath_, const XNode *pParent, Actor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( ft == FT_Directory )
|
||||||
|
{
|
||||||
|
RString sLuaPath = sPath + "default.lua";
|
||||||
|
if( DoesFileExist(sLuaPath) )
|
||||||
|
{
|
||||||
|
sPath = sLuaPath;
|
||||||
|
ft = FT_Lua;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RString sDir = Dirname( sPath );
|
RString sDir = Dirname( sPath );
|
||||||
switch( ft )
|
switch( ft )
|
||||||
{
|
{
|
||||||
@@ -367,6 +404,19 @@ Actor* ActorUtil::MakeActor( const RString &sPath_, const XNode *pParent, Actor
|
|||||||
MergeActorXML( &xml, pParent );
|
MergeActorXML( &xml, pParent );
|
||||||
return ActorUtil::LoadFromNode( sDir, &xml );
|
return ActorUtil::LoadFromNode( sDir, &xml );
|
||||||
}
|
}
|
||||||
|
case FT_Lua:
|
||||||
|
{
|
||||||
|
auto_ptr<XNode> pNode( LoadXNodeFromLuaShowErrors(sPath) );
|
||||||
|
if( pNode.get() == NULL )
|
||||||
|
{
|
||||||
|
// XNode will warn about the error
|
||||||
|
return new Actor;
|
||||||
|
}
|
||||||
|
|
||||||
|
MergeActorXML( pNode.get(), pParent );
|
||||||
|
Actor *pRet = ActorUtil::LoadFromNode( sDir, pNode.get() );
|
||||||
|
return pRet;
|
||||||
|
}
|
||||||
case FT_Bitmap:
|
case FT_Bitmap:
|
||||||
case FT_Movie:
|
case FT_Movie:
|
||||||
{
|
{
|
||||||
@@ -503,6 +553,7 @@ static const char *FileTypeNames[] = {
|
|||||||
"Movie",
|
"Movie",
|
||||||
"Directory",
|
"Directory",
|
||||||
"Xml",
|
"Xml",
|
||||||
|
"Lua",
|
||||||
"Model",
|
"Model",
|
||||||
};
|
};
|
||||||
XToString( FileType, NUM_FileType );
|
XToString( FileType, NUM_FileType );
|
||||||
@@ -513,6 +564,7 @@ FileType ActorUtil::GetFileType( const RString &sPath )
|
|||||||
sExt.MakeLower();
|
sExt.MakeLower();
|
||||||
|
|
||||||
if( sExt=="xml" ) return FT_Xml;
|
if( sExt=="xml" ) return FT_Xml;
|
||||||
|
else if( sExt=="lua" ) return FT_Lua;
|
||||||
else if(
|
else if(
|
||||||
sExt=="png" ||
|
sExt=="png" ||
|
||||||
sExt=="jpg" ||
|
sExt=="jpg" ||
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ enum FileType
|
|||||||
FT_Movie,
|
FT_Movie,
|
||||||
FT_Directory,
|
FT_Directory,
|
||||||
FT_Xml,
|
FT_Xml,
|
||||||
|
FT_Lua,
|
||||||
FT_Model,
|
FT_Model,
|
||||||
NUM_FileType,
|
NUM_FileType,
|
||||||
FT_Invalid
|
FT_Invalid
|
||||||
|
|||||||
@@ -640,8 +640,113 @@ void XmlFileUtil::CompileXNodeTree( XNode *pNode, const RString &sFile )
|
|||||||
LUA->Release( L );
|
LUA->Release( L );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
XNode *XNodeFromTableRecursive( lua_State *L, const RString &sName, LuaReference &ProcessedTables )
|
||||||
|
{
|
||||||
|
XNode *pNode = new XNode( sName );
|
||||||
|
|
||||||
|
/* Set the value of the node to the table. */
|
||||||
|
{
|
||||||
|
XNodeLuaValue *pValue = new XNodeLuaValue;
|
||||||
|
lua_pushvalue( L, -1 );
|
||||||
|
pValue->SetValueFromStack( L );
|
||||||
|
pNode->SetValueFrom( pValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterate over the table, pulling out attributes and tables to process. */
|
||||||
|
map<RString, LuaReference> NodesToAdd;
|
||||||
|
lua_pushnil( L );
|
||||||
|
while( lua_next(L, -2) )
|
||||||
|
{
|
||||||
|
lua_pushvalue( L, -2 );
|
||||||
|
RString sName;
|
||||||
|
LuaHelpers::Pop( L, sName );
|
||||||
|
|
||||||
|
/* If this entry is a table, add it recursively. */
|
||||||
|
if( lua_istable(L, -1) )
|
||||||
|
{
|
||||||
|
NodesToAdd[sName].SetFromStack( L );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( lua_isstring(L, -1) && EndsWith(sName, "Command") )
|
||||||
|
{
|
||||||
|
RString sExpression;
|
||||||
|
LuaHelpers::Pop( L, sExpression );
|
||||||
|
LuaHelpers::ParseCommandList( L, sExpression, "" /* XXX */ );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, add an attribute. */
|
||||||
|
XNodeLuaValue *pValue = new XNodeLuaValue;
|
||||||
|
pValue->SetValueFromStack( L );
|
||||||
|
pNode->AppendAttrFrom( sName, pValue );
|
||||||
|
}
|
||||||
|
lua_pop( L, 1 ); // pop nil
|
||||||
|
|
||||||
|
/* Recursively process tables. */
|
||||||
|
FOREACHM( RString, LuaReference, NodesToAdd, t )
|
||||||
|
{
|
||||||
|
const RString &sNodeName = t->first;
|
||||||
|
LuaReference &NodeToAdd = t->second;
|
||||||
|
|
||||||
|
/* Check if the table is on the stack. */
|
||||||
|
ProcessedTables.PushSelf( L );
|
||||||
|
NodeToAdd.PushSelf( L ); // push table
|
||||||
|
lua_gettable( L, -2 );
|
||||||
|
|
||||||
|
bool bSawThisTableAlready = !lua_isnil(L, -1);
|
||||||
|
lua_pop( L, 2 ); // pop lua_gettable result, ProcessedTables
|
||||||
|
if( bSawThisTableAlready )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Add the table to the stack. */
|
||||||
|
ProcessedTables.PushSelf( L );
|
||||||
|
NodeToAdd.PushSelf( L );
|
||||||
|
lua_pushboolean( L, true );
|
||||||
|
lua_settable( L, -3 );
|
||||||
|
lua_pop( L, 1 ); // pop ProcessedTables
|
||||||
|
|
||||||
|
NodeToAdd.PushSelf( L );
|
||||||
|
XNode *pNewNode = XNodeFromTableRecursive( L, sNodeName, ProcessedTables );
|
||||||
|
if( pNewNode )
|
||||||
|
pNode->AppendChild( pNewNode );
|
||||||
|
|
||||||
|
/* Remove the table from the stack. */
|
||||||
|
ProcessedTables.PushSelf( L );
|
||||||
|
NodeToAdd.PushSelf( L );
|
||||||
|
lua_pushnil( L );
|
||||||
|
lua_settable( L, -3 );
|
||||||
|
lua_pop( L, 1 ); // pop ProcessedTables
|
||||||
|
}
|
||||||
|
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (c) 2001-2004 Chris Danford
|
* Pop a table off of the stack, and return an XNode tree referring recursively
|
||||||
|
* to entries in the table.
|
||||||
|
*
|
||||||
|
* The table may not contain table cycles; if a cycle is detected, only the first
|
||||||
|
* table seen will have a corresponding XNode.
|
||||||
|
*
|
||||||
|
* Users of the resulting XNode may access the original table via PushValue.
|
||||||
|
*/
|
||||||
|
XNode *XmlFileUtil::XNodeFromTable( lua_State *L )
|
||||||
|
{
|
||||||
|
/* Maintain a set of references that we've created. Tables may loop; XNode trees may
|
||||||
|
* not. If we encounter a cycle, skip creating an XNode for that node. */
|
||||||
|
LuaReference ProcessedTables;
|
||||||
|
lua_newtable( L );
|
||||||
|
ProcessedTables.SetFromStack( L );
|
||||||
|
|
||||||
|
return XNodeFromTableRecursive( L, "Layer", ProcessedTables );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (c) 2001-2006 Chris Danford, Glenn Maynard
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
class RageFileBasic;
|
class RageFileBasic;
|
||||||
class XNode;
|
class XNode;
|
||||||
|
struct lua_State;
|
||||||
|
|
||||||
namespace XmlFileUtil
|
namespace XmlFileUtil
|
||||||
{
|
{
|
||||||
@@ -19,6 +20,7 @@ namespace XmlFileUtil
|
|||||||
bool SaveToFile( const XNode *pNode, RageFileBasic &f, const RString &sStylesheet = "", bool bWriteTabs = true );
|
bool SaveToFile( const XNode *pNode, RageFileBasic &f, const RString &sStylesheet = "", bool bWriteTabs = true );
|
||||||
|
|
||||||
void CompileXNodeTree( XNode *pNode, const RString &sFile );
|
void CompileXNodeTree( XNode *pNode, const RString &sFile );
|
||||||
|
XNode *XNodeFromTable( lua_State *L );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user