Currently, expression handling in XML is spotting and inconsistent.
Each actor type needs to evaluate attributes; only a few do. Strings are handled with the "@foo()" notation. Instead, after loading an XML file for loading as an actor, precompile all XML attributes as Lua expressions. The primary difference to code is: - previously, Attr="string" would act as a string if it was being read as one. Now, specify Attr='"string"'. Attr="@string" is a shorthand. (note that @strings will not be parsed as Lua strings, so can not use Lua escape characters) - previously, Attr="@func()" would evaluate func(), and the value of the attribute would be the return value of the function. This was only supported for a few attributes. Now, say Attr="func()", and this will work for all fields. - Attributes of other types are unchanged, except that all attributes may be Lua expressions, eg. Width="SCREEN_WIDTH". - Attributes names ending with "Command" are special, like metrics. Prefix "%" to disable this. This brings XML handling in line with metric handling. (This is an intermediary step; I have another idea that follows from this that should eliminate the annoying "'foo'"/"@foo".)
This commit is contained in:
+10
-9
@@ -258,6 +258,7 @@ void Actor::LoadFromNode( const RString& sDir, const XNode* pNode )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lua *L = LUA->Get();
|
||||||
FOREACH_CONST_Attr( pNode, pAttr )
|
FOREACH_CONST_Attr( pNode, pAttr )
|
||||||
{
|
{
|
||||||
// Load Name, if any.
|
// Load Name, if any.
|
||||||
@@ -272,10 +273,11 @@ void Actor::LoadFromNode( const RString& sDir, const XNode* pNode )
|
|||||||
else if( sKeyName == "BaseZoomZ" ) SetBaseZoomZ( pValue->GetValue<float>() );
|
else if( sKeyName == "BaseZoomZ" ) SetBaseZoomZ( pValue->GetValue<float>() );
|
||||||
else if( EndsWith(sKeyName,"Command") )
|
else if( EndsWith(sKeyName,"Command") )
|
||||||
{
|
{
|
||||||
apActorCommands apac = ActorUtil::ParseActorCommands( pValue->GetValue<RString>(), ssprintf("%s: %s", sDir.c_str(), sKeyName.c_str()) );
|
LuaReference *pRef = new LuaReference;
|
||||||
|
pValue->PushValue( L );
|
||||||
|
pRef->SetFromStack( L );
|
||||||
RString sCmdName = sKeyName.Left( sKeyName.size()-7 );
|
RString sCmdName = sKeyName.Left( sKeyName.size()-7 );
|
||||||
AddCommand( sCmdName, apac );
|
AddCommand( sCmdName, apActorCommands( pRef ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,14 +293,13 @@ void Actor::LoadFromNode( const RString& sDir, const XNode* pNode )
|
|||||||
|
|
||||||
RString sName;
|
RString sName;
|
||||||
c->GetAttrValue( "Name", sName );
|
c->GetAttrValue( "Name", sName );
|
||||||
RString sValue;
|
c->PushAttrValue( L, "Value" );
|
||||||
c->GetAttrValue( "Value", sValue );
|
|
||||||
|
|
||||||
LuaHelpers::RunAtExpressionS( sName );
|
LuaReference *pRef = new LuaReference;
|
||||||
apActorCommands apac = ActorUtil::ParseActorCommands( sValue, ssprintf("%s: %s", sDir.c_str(), sKeyName.c_str()) );
|
pRef->SetFromStack( L );
|
||||||
|
AddCommand( sName, apActorCommands( pRef ) );
|
||||||
AddCommand( sName, apac );
|
|
||||||
}
|
}
|
||||||
|
LUA->Release( L );
|
||||||
|
|
||||||
/* There's an InitCommand. Run it now. This can be used to eg. change Z to
|
/* There's an InitCommand. Run it now. This can be used to eg. change Z to
|
||||||
* modify draw order between BGAs in a Foreground. */
|
* modify draw order between BGAs in a Foreground. */
|
||||||
|
|||||||
@@ -200,14 +200,10 @@ Actor* ActorUtil::LoadFromNode( const RString& sDir, const XNode* pNode, Actor *
|
|||||||
if( !pChild->GetAttrValue( "Name", sName ) )
|
if( !pChild->GetAttrValue( "Name", sName ) )
|
||||||
Dialog::OK( ssprintf("Param node in '%s' is missing the attribute \"Name\"", sDir.c_str()), "MISSING_ATTRIBUTE" );
|
Dialog::OK( ssprintf("Param node in '%s' is missing the attribute \"Name\"", sDir.c_str()), "MISSING_ATTRIBUTE" );
|
||||||
|
|
||||||
LuaHelpers::RunAtExpressionS( sName );
|
Lua *L = LUA->Get();
|
||||||
|
if( !pChild->PushAttrValue( L, "Value" ) )
|
||||||
RString s;
|
|
||||||
if( !pChild->GetAttrValue( "Value", s ) )
|
|
||||||
Dialog::OK( ssprintf("Param node in '%s' is missing the attribute \"Value\"", sDir.c_str()), "MISSING_ATTRIBUTE" );
|
Dialog::OK( ssprintf("Param node in '%s' is missing the attribute \"Value\"", sDir.c_str()), "MISSING_ATTRIBUTE" );
|
||||||
|
|
||||||
Lua *L = LUA->Get();
|
|
||||||
LuaHelpers::RunExpression( L, s, sDir );
|
|
||||||
SetParamFromStack( L, sName, &setOldParams[sName] );
|
SetParamFromStack( L, sName, &setOldParams[sName] );
|
||||||
LUA->Release(L);
|
LUA->Release(L);
|
||||||
}
|
}
|
||||||
@@ -368,6 +364,7 @@ Actor* ActorUtil::MakeActor( const RString &sPath_, const XNode *pParent, Actor
|
|||||||
return new Actor;
|
return new Actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XmlFileUtil::CompileXNodeTree( &xml, sPath );
|
||||||
MergeActorXML( &xml, pParent );
|
MergeActorXML( &xml, pParent );
|
||||||
return ActorUtil::LoadFromNode( sDir, &xml );
|
return ActorUtil::LoadFromNode( sDir, &xml );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "RageUtil.h"
|
#include "RageUtil.h"
|
||||||
#include "DateTime.h"
|
#include "DateTime.h"
|
||||||
#include "Foreach.h"
|
#include "Foreach.h"
|
||||||
|
#include "LuaManager.h"
|
||||||
|
|
||||||
XNode::XNode()
|
XNode::XNode()
|
||||||
{
|
{
|
||||||
@@ -62,11 +63,19 @@ void XNodeStringValue::GetValue( int &out ) const { out = atoi(m_sValue); }
|
|||||||
void XNodeStringValue::GetValue( float &out ) const { out = StringToFloat(m_sValue); }
|
void XNodeStringValue::GetValue( float &out ) const { out = StringToFloat(m_sValue); }
|
||||||
void XNodeStringValue::GetValue( bool &out ) const { out = atoi(m_sValue) != 0; }
|
void XNodeStringValue::GetValue( bool &out ) const { out = atoi(m_sValue) != 0; }
|
||||||
void XNodeStringValue::GetValue( unsigned &out ) const { out = strtoul(m_sValue,NULL,0); }
|
void XNodeStringValue::GetValue( unsigned &out ) const { out = strtoul(m_sValue,NULL,0); }
|
||||||
|
void XNodeStringValue::PushValue( lua_State *L ) const
|
||||||
|
{
|
||||||
|
LuaHelpers::Push( L, m_sValue );
|
||||||
|
}
|
||||||
|
|
||||||
void XNodeStringValue::SetValue( const RString &v ) { m_sValue = v; }
|
void XNodeStringValue::SetValue( const RString &v ) { m_sValue = v; }
|
||||||
void XNodeStringValue::SetValue( int v ) { m_sValue = ssprintf("%d",v); }
|
void XNodeStringValue::SetValue( int v ) { m_sValue = ssprintf("%d",v); }
|
||||||
void XNodeStringValue::SetValue( float v ) { m_sValue = ssprintf("%f",v); }
|
void XNodeStringValue::SetValue( float v ) { m_sValue = ssprintf("%f",v); }
|
||||||
void XNodeStringValue::SetValue( unsigned v ) { m_sValue = ssprintf("%u",v); }
|
void XNodeStringValue::SetValue( unsigned v ) { m_sValue = ssprintf("%u",v); }
|
||||||
|
void XNodeStringValue::SetValueFromStack( lua_State *L )
|
||||||
|
{
|
||||||
|
LuaHelpers::Pop( L, m_sValue );
|
||||||
|
}
|
||||||
|
|
||||||
const XNodeValue *XNode::GetAttr( const RString &attrname ) const
|
const XNodeValue *XNode::GetAttr( const RString &attrname ) const
|
||||||
{
|
{
|
||||||
@@ -76,6 +85,18 @@ const XNodeValue *XNode::GetAttr( const RString &attrname ) const
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool XNode::PushAttrValue( lua_State *L, const RString &sName ) const
|
||||||
|
{
|
||||||
|
const XNodeValue *pAttr = GetAttr(sName);
|
||||||
|
if( pAttr == NULL )
|
||||||
|
{
|
||||||
|
lua_pushnil( L );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pAttr->PushValue( L );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
XNodeValue *XNode::GetAttr( const RString &attrname )
|
XNodeValue *XNode::GetAttr( const RString &attrname )
|
||||||
{
|
{
|
||||||
XAttrs::iterator it = m_attrs.find( attrname );
|
XAttrs::iterator it = m_attrs.find( attrname );
|
||||||
@@ -95,6 +116,18 @@ XNode *XNode::GetChild( const RString &sName )
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool XNode::PushChildValue( lua_State *L, const RString &sName ) const
|
||||||
|
{
|
||||||
|
const XNode *pChild = GetChild(sName);
|
||||||
|
if( pChild == NULL )
|
||||||
|
{
|
||||||
|
lua_pushnil( L );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pChild->m_pValue->PushValue( L );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const XNode *XNode::GetChild( const RString &sName ) const
|
const XNode *XNode::GetChild( const RString &sName ) const
|
||||||
{
|
{
|
||||||
multimap<RString, XNode*>::const_iterator it = m_childs.find( sName );
|
multimap<RString, XNode*>::const_iterator it = m_childs.find( sName );
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
struct DateTime;
|
struct DateTime;
|
||||||
class RageFileBasic;
|
class RageFileBasic;
|
||||||
|
struct lua_State;
|
||||||
|
|
||||||
class XNodeValue
|
class XNodeValue
|
||||||
{
|
{
|
||||||
@@ -18,6 +19,7 @@ public:
|
|||||||
virtual void GetValue( float &out ) const = 0;
|
virtual void GetValue( float &out ) const = 0;
|
||||||
virtual void GetValue( bool &out ) const = 0;
|
virtual void GetValue( bool &out ) const = 0;
|
||||||
virtual void GetValue( unsigned &out ) const = 0;
|
virtual void GetValue( unsigned &out ) const = 0;
|
||||||
|
virtual void PushValue( lua_State *L ) const = 0;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T GetValue() const { T val; GetValue(val); return val; }
|
T GetValue() const { T val; GetValue(val); return val; }
|
||||||
@@ -26,6 +28,7 @@ public:
|
|||||||
virtual void SetValue( int v ) = 0;
|
virtual void SetValue( int v ) = 0;
|
||||||
virtual void SetValue( float v ) = 0;
|
virtual void SetValue( float v ) = 0;
|
||||||
virtual void SetValue( unsigned v ) = 0;
|
virtual void SetValue( unsigned v ) = 0;
|
||||||
|
virtual void SetValueFromStack( lua_State *L ) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class XNodeStringValue: public XNodeValue
|
class XNodeStringValue: public XNodeValue
|
||||||
@@ -40,11 +43,13 @@ public:
|
|||||||
void GetValue( float &out ) const;
|
void GetValue( float &out ) const;
|
||||||
void GetValue( bool &out ) const;
|
void GetValue( bool &out ) const;
|
||||||
void GetValue( unsigned &out ) const;
|
void GetValue( unsigned &out ) const;
|
||||||
|
void PushValue( lua_State *L ) const;
|
||||||
|
|
||||||
void SetValue( const RString &v );
|
void SetValue( const RString &v );
|
||||||
void SetValue( int v );
|
void SetValue( int v );
|
||||||
void SetValue( float v );
|
void SetValue( float v );
|
||||||
void SetValue( unsigned v );
|
void SetValue( unsigned v );
|
||||||
|
void SetValueFromStack( lua_State *L );
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef map<RString,XNodeValue*> XAttrs;
|
typedef map<RString,XNodeValue*> XAttrs;
|
||||||
@@ -98,12 +103,14 @@ public:
|
|||||||
XNodeValue *GetAttr( const RString &sAttrName );
|
XNodeValue *GetAttr( const RString &sAttrName );
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool GetAttrValue( const RString &sName, T &out ) const { const XNodeValue *pAttr=GetAttr(sName); if(pAttr==NULL) return false; pAttr->GetValue(out); return true; }
|
bool GetAttrValue( const RString &sName, T &out ) const { const XNodeValue *pAttr=GetAttr(sName); if(pAttr==NULL) return false; pAttr->GetValue(out); return true; }
|
||||||
|
bool PushAttrValue( lua_State *L, const RString &sName ) const;
|
||||||
|
|
||||||
// in one level child nodes
|
// in one level child nodes
|
||||||
const XNode *GetChild( const RString &sName ) const;
|
const XNode *GetChild( const RString &sName ) const;
|
||||||
XNode *GetChild( const RString &sName );
|
XNode *GetChild( const RString &sName );
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool GetChildValue( const RString &sName, T &out ) const { const XNode *pChild=GetChild(sName); if(pChild==NULL) return false; pChild->GetValue(out); return true; }
|
bool GetChildValue( const RString &sName, T &out ) const { const XNode *pChild=GetChild(sName); if(pChild==NULL) return false; pChild->GetValue(out); return true; }
|
||||||
|
bool PushChildValue( lua_State *L, const RString &sName ) const;
|
||||||
|
|
||||||
// modify DOM
|
// modify DOM
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@@ -529,6 +529,117 @@ bool XmlFileUtil::SaveToFile( const XNode *pNode, const RString &sFile, const RS
|
|||||||
return SaveToFile( pNode, f, sStylesheet, bWriteTabs );
|
return SaveToFile( pNode, f, sStylesheet, bWriteTabs );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "LuaManager.h"
|
||||||
|
#include "LuaReference.h"
|
||||||
|
class XNodeLuaValue: public XNodeValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LuaReference m_Value;
|
||||||
|
XNodeValue *Copy() const { return new XNodeLuaValue( *this ); }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T GetValue() const { T val; GetValue(val); return val; }
|
||||||
|
|
||||||
|
void GetValue( RString &out ) const;
|
||||||
|
void GetValue( int &out ) const;
|
||||||
|
void GetValue( float &out ) const;
|
||||||
|
void GetValue( bool &out ) const;
|
||||||
|
void GetValue( unsigned &out ) const;
|
||||||
|
void PushValue( lua_State *L ) const;
|
||||||
|
|
||||||
|
void SetValue( const RString &v );
|
||||||
|
void SetValue( int v );
|
||||||
|
void SetValue( float v );
|
||||||
|
void SetValue( unsigned v );
|
||||||
|
void SetValueFromStack( lua_State *L );
|
||||||
|
};
|
||||||
|
|
||||||
|
void XNodeLuaValue::PushValue( lua_State *L ) const
|
||||||
|
{
|
||||||
|
m_Value.PushSelf( L );
|
||||||
|
}
|
||||||
|
|
||||||
|
void XNodeLuaValue::GetValue( RString &out ) const { Lua *L = LUA->Get(); PushValue( L ); LuaHelpers::Pop( L, out ); LUA->Release( L ); }
|
||||||
|
void XNodeLuaValue::GetValue( int &out ) const { Lua *L = LUA->Get(); PushValue( L ); LuaHelpers::Pop( L, out ); LUA->Release( L ); }
|
||||||
|
void XNodeLuaValue::GetValue( float &out ) const { Lua *L = LUA->Get(); PushValue( L ); LuaHelpers::Pop( L, out ); LUA->Release( L ); }
|
||||||
|
void XNodeLuaValue::GetValue( bool &out ) const { Lua *L = LUA->Get(); PushValue( L ); LuaHelpers::Pop( L, out ); LUA->Release( L ); }
|
||||||
|
void XNodeLuaValue::GetValue( unsigned &out ) const { Lua *L = LUA->Get(); PushValue( L ); float fVal; LuaHelpers::Pop( L, fVal ); out = fVal; LUA->Release( L ); }
|
||||||
|
|
||||||
|
void XNodeLuaValue::SetValueFromStack( lua_State *L )
|
||||||
|
{
|
||||||
|
m_Value.SetFromStack( L );
|
||||||
|
}
|
||||||
|
|
||||||
|
void XNodeLuaValue::SetValue( const RString &v ) { Lua *L = LUA->Get(); LuaHelpers::Push( L, v ); SetValueFromStack( L ); LUA->Release( L ); }
|
||||||
|
void XNodeLuaValue::SetValue( int v ) { Lua *L = LUA->Get(); LuaHelpers::Push( L, v ); SetValueFromStack( L ); LUA->Release( L ); }
|
||||||
|
void XNodeLuaValue::SetValue( float v ) { Lua *L = LUA->Get(); LuaHelpers::Push( L, v ); SetValueFromStack( L ); LUA->Release( L ); }
|
||||||
|
void XNodeLuaValue::SetValue( unsigned v ) { Lua *L = LUA->Get(); LuaHelpers::Push( L, (float) v ); SetValueFromStack( L ); LUA->Release( L ); }
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void CompileXMLNodeValue( Lua *L, const RString &sName, XNodeValue *&pValue, const RString &sFile )
|
||||||
|
{
|
||||||
|
RString sExpression;
|
||||||
|
pValue->GetValue( sExpression );
|
||||||
|
|
||||||
|
if( EndsWith(sName, "Command") && sExpression.size() > 0 && sExpression[0] == '%' )
|
||||||
|
{
|
||||||
|
sExpression.erase( 0, 1 );
|
||||||
|
if( !LuaHelpers::RunExpression(L, sExpression, sFile) )
|
||||||
|
{
|
||||||
|
/* Compiling or running failed. An error was already logged; just push a dummy
|
||||||
|
* return value. */
|
||||||
|
lua_pushnil( L );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( EndsWith(sName, "Command") && (sExpression.size() == 0 || sExpression[0] != '%') )
|
||||||
|
{
|
||||||
|
LuaHelpers::ParseCommandList( L, sExpression, sFile );
|
||||||
|
}
|
||||||
|
else if( sExpression.size() > 0 && sExpression[0] == '@' )
|
||||||
|
{
|
||||||
|
/* This is a raw string. */
|
||||||
|
sExpression.erase( 0, 1 );
|
||||||
|
LuaHelpers::Push( L, sExpression );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( !LuaHelpers::RunExpression(L, sExpression, sFile) )
|
||||||
|
{
|
||||||
|
/* Compiling or running failed. An error was already logged; just push a dummy
|
||||||
|
* return value. */
|
||||||
|
lua_pushnil( L );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete pValue;
|
||||||
|
pValue = new XNodeLuaValue;
|
||||||
|
pValue->SetValueFromStack( L );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XmlFileUtil::CompileXNodeTree( XNode *pNode, const RString &sFile )
|
||||||
|
{
|
||||||
|
vector<XNode *> aToCompile;
|
||||||
|
aToCompile.push_back( pNode );
|
||||||
|
|
||||||
|
Lua *L = LUA->Get();
|
||||||
|
while( aToCompile.size() )
|
||||||
|
{
|
||||||
|
pNode = aToCompile.back();
|
||||||
|
aToCompile.pop_back();
|
||||||
|
FOREACH_Child( pNode, pChild )
|
||||||
|
aToCompile.push_back( pChild );
|
||||||
|
|
||||||
|
CompileXMLNodeValue( L, pNode->GetName(), pNode->m_pValue, sFile );
|
||||||
|
|
||||||
|
FOREACH_Attr( pNode, pAttr )
|
||||||
|
CompileXMLNodeValue( L, pAttr->first, pAttr->second, sFile );
|
||||||
|
}
|
||||||
|
|
||||||
|
LUA->Release( L );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (c) 2001-2004 Chris Danford
|
* (c) 2001-2004 Chris Danford
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ namespace XmlFileUtil
|
|||||||
RString GetXML( const XNode *pNode );
|
RString GetXML( const XNode *pNode );
|
||||||
bool SaveToFile( const XNode *pNode, const RString &sFile, const RString &sStylesheet = "", bool bWriteTabs = true );
|
bool SaveToFile( const XNode *pNode, const RString &sFile, const RString &sStylesheet = "", bool bWriteTabs = true );
|
||||||
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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user