A bizarre C++ wart wants us to declare FromStack overloads
before the ThemeMetric templates that use them. That's broken and unreasonable, so change this around a bit and make FromStack (and Push) templates. Push() takes a bit of a trick. Some Push overloads push the actual value: scalars (int, float), RageColor (pushes a table). Others--most of them--push a reference to a C++ object. We want the scalars to have a reference parameter type, so we don't make extra copies of things like RageColor when we push them. We need to pass C++ objects by pointer (we need to push the actual object's pointer, not a pointer to a copy). Further, pushing a scalar is a const operation, but pushing a reference to an object is not. To do both with the same template, we handle objects with this slightly odd template: template<> void LuaHelpers::Push<T*>( lua_State *L, T *const &pObject ); The actual overload (T) is eg. "Actor*"; this fits within the general prototype, "Push(lua_State *L, const T &object)", giving us a const reference to a (non-const) pointer to Actor, and we're conceptually pushing the pointer. The net effect of this is that 1: what was before compile errors now becomes link time errors, but 2: these specializations don't have to be in the headers (except for new ones for Preference and BroadcastOnChange).
This commit is contained in:
@@ -127,9 +127,8 @@ const RString &EnumToString( int iVal, int iMax, const char **szNameArray, auto_
|
||||
return (X)(i+1); /*invalid*/ \
|
||||
}
|
||||
|
||||
#define LuaDeclareType(X) \
|
||||
namespace LuaHelpers { bool FromStack( lua_State *L, X &Object, int iOffset ); } \
|
||||
namespace LuaHelpers { void Push( lua_State *L, const X &Object ); }
|
||||
// currently unused
|
||||
#define LuaDeclareType(X)
|
||||
|
||||
#define LuaXType(X) \
|
||||
template struct EnumTraits<X>; \
|
||||
@@ -162,8 +161,8 @@ static void Lua##X(lua_State* L) \
|
||||
REGISTER_WITH_LUA_FUNCTION( Lua##X ); \
|
||||
template<> X EnumTraits<X>::Invalid = enum_add2( NUM_##X, 1 ); \
|
||||
template<> const char *EnumTraits<X>::szName = #X; \
|
||||
bool LuaHelpers::FromStack( lua_State *L, X &Object, int iOffset ) { Object = Enum::Check<X>( L, iOffset ); return true; } \
|
||||
void LuaHelpers::Push( lua_State *L, const X &Object ) { Enum::Push<X>( L, Object ); }
|
||||
namespace LuaHelpers { template<> bool FromStack<X>( lua_State *L, X &Object, int iOffset ) { Object = Enum::Check<X>( L, iOffset ); return true; } } \
|
||||
namespace LuaHelpers { template<> void Push<X>( lua_State *L, const X &Object ) { Enum::Push<X>( L, Object ); } }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ public:
|
||||
void T::PushSelf( lua_State *L ) { Luna<B>::PushObject( L, Luna<T>::m_sClassName, this ); } \
|
||||
static Luna##T registera##T; \
|
||||
/* Call PushSelf, so we always call the derived Luna<T>::Push. */ \
|
||||
namespace LuaHelpers { template<> void Push( lua_State *L, T *pObject ) { pObject->PushSelf( L ); } }
|
||||
namespace LuaHelpers { template<> void Push<T*>( lua_State *L, T *const &pObject ) { pObject->PushSelf( L ); } }
|
||||
|
||||
#define DEFINE_METHOD( method_name, expr ) \
|
||||
static int method_name( T* p, lua_State *L ) { LuaHelpers::Push( L, p->expr ); return 1; }
|
||||
|
||||
@@ -21,6 +21,19 @@ static LuaFunctionList *g_LuaFunctions = NULL;
|
||||
#pragma warning (disable : 4611)
|
||||
#endif
|
||||
|
||||
namespace LuaHelpers
|
||||
{
|
||||
template<> void Push<bool>( lua_State *L, const bool &Object );
|
||||
template<> void Push<float>( lua_State *L, const float &Object );
|
||||
template<> void Push<int>( lua_State *L, const int &Object );
|
||||
template<> void Push<RString>( lua_State *L, const RString &Object );
|
||||
|
||||
template<> bool FromStack<bool>( Lua *L, bool &Object, int iOffset );
|
||||
template<> bool FromStack<float>( Lua *L, float &Object, int iOffset );
|
||||
template<> bool FromStack<int>( Lua *L, int &Object, int iOffset );
|
||||
template<> bool FromStack<RString>( Lua *L, RString &Object, int iOffset );
|
||||
}
|
||||
|
||||
struct ChunkReaderString
|
||||
{
|
||||
ChunkReaderString( const RString &sBuf ): m_sBuf(sBuf) { m_bDone = false; }
|
||||
@@ -68,25 +81,27 @@ void LuaManager::UnsetGlobal( const RString &sName )
|
||||
LUA->Release( L );
|
||||
}
|
||||
|
||||
|
||||
void LuaHelpers::Push( lua_State *L, const bool &Object ) { lua_pushboolean( L, Object ); }
|
||||
void LuaHelpers::Push( lua_State *L, const float &Object ) { lua_pushnumber( L, Object ); }
|
||||
void LuaHelpers::Push( lua_State *L, const int &Object ) { lua_pushinteger( L, Object ); }
|
||||
void LuaHelpers::Push( lua_State *L, const RString &Object ) { lua_pushlstring( L, Object.data(), Object.size() ); }
|
||||
|
||||
bool LuaHelpers::FromStack( Lua *L, bool &Object, int iOffset ) { Object = !!lua_toboolean( L, iOffset ); return true; }
|
||||
bool LuaHelpers::FromStack( Lua *L, float &Object, int iOffset ) { Object = (float)lua_tonumber( L, iOffset ); return true; }
|
||||
bool LuaHelpers::FromStack( Lua *L, int &Object, int iOffset ) { Object = lua_tointeger( L, iOffset ); return true; }
|
||||
bool LuaHelpers::FromStack( Lua *L, RString &Object, int iOffset )
|
||||
namespace LuaHelpers
|
||||
{
|
||||
size_t iLen;
|
||||
const char *pStr = lua_tolstring( L, iOffset, &iLen );
|
||||
if( pStr != NULL )
|
||||
Object.assign( pStr, iLen );
|
||||
else
|
||||
Object.clear();
|
||||
template<> void Push<bool>( lua_State *L, const bool &Object ) { lua_pushboolean( L, Object ); }
|
||||
template<> void Push<float>( lua_State *L, const float &Object ) { lua_pushnumber( L, Object ); }
|
||||
template<> void Push<int>( lua_State *L, const int &Object ) { lua_pushinteger( L, Object ); }
|
||||
template<> void Push<RString>( lua_State *L, const RString &Object ) { lua_pushlstring( L, Object.data(), Object.size() ); }
|
||||
|
||||
return pStr != NULL;
|
||||
template<> bool FromStack<bool>( Lua *L, bool &Object, int iOffset ) { Object = !!lua_toboolean( L, iOffset ); return true; }
|
||||
template<> bool FromStack<float>( Lua *L, float &Object, int iOffset ) { Object = (float)lua_tonumber( L, iOffset ); return true; }
|
||||
template<> bool FromStack<int>( Lua *L, int &Object, int iOffset ) { Object = lua_tointeger( L, iOffset ); return true; }
|
||||
template<> bool FromStack<RString>( Lua *L, RString &Object, int iOffset )
|
||||
{
|
||||
size_t iLen;
|
||||
const char *pStr = lua_tolstring( L, iOffset, &iLen );
|
||||
if( pStr != NULL )
|
||||
Object.assign( pStr, iLen );
|
||||
else
|
||||
Object.clear();
|
||||
|
||||
return pStr != NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void LuaHelpers::CreateTableFromArrayB( Lua *L, const vector<bool> &aIn )
|
||||
|
||||
@@ -81,17 +81,10 @@ namespace LuaHelpers
|
||||
void PushValueFunc( lua_State *L, int iArgs );
|
||||
|
||||
template<class T>
|
||||
void Push( lua_State *L, T *pObject );
|
||||
void Push( lua_State *L, const T &Object );
|
||||
|
||||
void Push( lua_State *L, const bool &Object );
|
||||
void Push( lua_State *L, const float &Object );
|
||||
void Push( lua_State *L, const int &Object );
|
||||
void Push( lua_State *L, const RString &Object );
|
||||
|
||||
bool FromStack( Lua *L, bool &Object, int iOffset );
|
||||
bool FromStack( Lua *L, float &Object, int iOffset );
|
||||
bool FromStack( Lua *L, int &Object, int iOffset );
|
||||
bool FromStack( Lua *L, RString &Object, int iOffset );
|
||||
template<class T>
|
||||
bool FromStack( lua_State *L, T &Object, int iOffset );
|
||||
|
||||
template<class T>
|
||||
bool Pop( lua_State *L, T &val )
|
||||
|
||||
@@ -163,19 +163,22 @@ RString LuaReference::Serialize() const
|
||||
return sRet;
|
||||
}
|
||||
|
||||
bool LuaHelpers::FromStack( lua_State *L, LuaReference &Object, int iOffset )
|
||||
namespace LuaHelpers
|
||||
{
|
||||
lua_pushvalue( L, iOffset );
|
||||
Object.SetFromStack( L );
|
||||
return true;
|
||||
}
|
||||
template<> bool FromStack<LuaReference>( lua_State *L, LuaReference &Object, int iOffset )
|
||||
{
|
||||
lua_pushvalue( L, iOffset );
|
||||
Object.SetFromStack( L );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LuaHelpers::FromStack( lua_State *L, apActorCommands &Object, int iOffset )
|
||||
{
|
||||
LuaReference *pRef = new LuaReference;
|
||||
FromStack( L, *pRef, iOffset );
|
||||
Object = apActorCommands( pRef );
|
||||
return true;
|
||||
template<> bool FromStack<apActorCommands>( lua_State *L, apActorCommands &Object, int iOffset )
|
||||
{
|
||||
LuaReference *pRef = new LuaReference;
|
||||
FromStack( L, *pRef, iOffset );
|
||||
Object = apActorCommands( pRef );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
LuaTable::LuaTable()
|
||||
|
||||
@@ -51,12 +51,6 @@ private:
|
||||
|
||||
typedef AutoPtrCopyOnWrite<LuaReference> apActorCommands;
|
||||
|
||||
namespace LuaHelpers
|
||||
{
|
||||
bool FromStack( lua_State *L, LuaReference &Object, int iOffset );
|
||||
bool FromStack( lua_State *L, apActorCommands &Object, int iOffset );
|
||||
}
|
||||
|
||||
class LuaTable: public LuaReference
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#ifndef MessageManager_H
|
||||
#define MessageManager_H
|
||||
|
||||
#include "LuaManager.h"
|
||||
struct lua_State;
|
||||
|
||||
enum Message
|
||||
@@ -201,6 +202,8 @@ public:
|
||||
bool operator != ( const T &other ) const { return val != other; }
|
||||
};
|
||||
|
||||
namespace LuaHelpers { template<class T> void Push( lua_State *L, const BroadcastOnChange<T> &Object ) { LuaHelpers::Push<T>( L, Object.Get() ); } }
|
||||
|
||||
template<class T, int N>
|
||||
class BroadcastOnChange1D
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "EnumHelper.h"
|
||||
#include "RageUtil.h"
|
||||
#include "LuaManager.h"
|
||||
class XNode;
|
||||
|
||||
struct lua_State;
|
||||
@@ -115,6 +116,8 @@ private:
|
||||
void (*m_pfnValidate)(T& val);
|
||||
};
|
||||
|
||||
namespace LuaHelpers { template<typename T, typename U> void Push( lua_State *L, const Preference<T, U> &Object ) { LuaHelpers::Push<T>( L, Object.Get() ); } }
|
||||
|
||||
template <class T>
|
||||
class Preference1D
|
||||
{
|
||||
|
||||
@@ -36,10 +36,13 @@ void RageColor::FromStack( lua_State *L, int iPos )
|
||||
lua_pop( L, 5 );
|
||||
}
|
||||
|
||||
bool LuaHelpers::FromStack( lua_State *L, RageColor &Object, int iOffset )
|
||||
namespace LuaHelpers
|
||||
{
|
||||
Object.FromStack( L, iOffset );
|
||||
return true;
|
||||
template<> bool FromStack<RageColor>( lua_State *L, RageColor &Object, int iOffset )
|
||||
{
|
||||
Object.FromStack( L, iOffset );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *CullModeNames[] =
|
||||
|
||||
@@ -200,11 +200,6 @@ public:
|
||||
float r, g, b, a;
|
||||
} SM_ALIGN(16);
|
||||
|
||||
namespace LuaHelpers
|
||||
{
|
||||
bool FromStack( lua_State *L, RageColor &Object, int iOffset );
|
||||
}
|
||||
|
||||
/* Convert floating-point 0..1 value to integer 0..255 value. *
|
||||
*
|
||||
* As a test case,
|
||||
|
||||
@@ -72,10 +72,9 @@ public:
|
||||
{
|
||||
if( m_sName != "" && THEME && THEME->IsThemeLoaded() )
|
||||
{
|
||||
using namespace LuaHelpers;
|
||||
Lua *L = LUA->Get();
|
||||
THEME->PushMetric( L, m_sGroup, m_sName );
|
||||
if( !FromStack(L, m_currentValue, -1) )
|
||||
if( !LuaHelpers::FromStack(L, m_currentValue, -1) )
|
||||
m_currentValue = T();
|
||||
lua_pop( L, 1 );
|
||||
LUA->Release(L);
|
||||
|
||||
Reference in New Issue
Block a user