Enable setting and getting property values from Lua scripts

This commit is contained in:
Alexander Bock
2014-08-31 17:52:02 +02:00
parent 5add1682d3
commit e7697a4ce0
13 changed files with 250 additions and 62 deletions

View File

@@ -38,6 +38,10 @@ public:
NumericalProperty(std::string identifier, std::string guiName, T value,
T minimumValue, T maximumValue);
bool getLua(lua_State* state) const override;
bool setLua(lua_State* state) override;
int typeLua() const override;
virtual std::string className() const override;
using TemplateProperty<T>::operator=;

View File

@@ -22,6 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <ghoul/lua/ghoul_lua.h>
namespace openspace {
namespace properties {
@@ -34,31 +36,49 @@ namespace properties {
template <> template <> \
TYPE PropertyDelegate<NumericalProperty<TYPE>>::defaultMinimumValue<TYPE>(); \
template <> template <> \
TYPE PropertyDelegate<NumericalProperty<TYPE>>::defaultMaximumValue<TYPE>();
TYPE PropertyDelegate<NumericalProperty<TYPE>>::defaultMaximumValue<TYPE>(); \
template <> template <> \
TYPE PropertyDelegate<NumericalProperty<TYPE>>::fromLuaValue( \
lua_State* state, bool& success); \
template <> template <> \
bool PropertyDelegate<NumericalProperty<TYPE>>::toLuaValue( \
lua_State* state, TYPE value);
#define REGISTER_NUMERICALPROPERTY_SOURCE(CLASS_NAME, TYPE, \
DEFAULT_VALUE, DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, DEFAULT_STEPPING) \
DEFAULT_VALUE, DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, DEFAULT_STEPPING, \
FROM_LUA_LAMBDA_EXPRESSION, TO_LUA_LAMBDA_EXPRESSION) \
template <> \
std::string PropertyDelegate<NumericalProperty<TYPE>>::className() { \
return #CLASS_NAME; \
} \
template <> \
std::string PropertyDelegate<TemplateProperty<TYPE>>::className() { \
return #CLASS_NAME; \
return #CLASS_NAME; \
} \
template <> template <> \
TYPE PropertyDelegate<NumericalProperty<TYPE>>::defaultValue<TYPE>() { \
return DEFAULT_VALUE; \
return DEFAULT_VALUE; \
} \
template <> template <> \
TYPE PropertyDelegate<NumericalProperty<TYPE>>::defaultMinimumValue<TYPE>() { \
return DEFAULT_MIN_VALUE; \
return DEFAULT_MIN_VALUE; \
} \
template <> template <> \
TYPE PropertyDelegate<NumericalProperty<TYPE>>::defaultMaximumValue<TYPE>() { \
return DEFAULT_MAX_VALUE; \
return DEFAULT_MAX_VALUE; \
} \
template <> template <> \
TYPE PropertyDelegate<NumericalProperty<TYPE>>::fromLuaValue<TYPE>( \
lua_State* state, bool& success) { \
return FROM_LUA_LAMBDA_EXPRESSION(state, success); \
} \
template <> template <> \
bool PropertyDelegate<NumericalProperty<TYPE>>::toLuaValue<TYPE>( \
lua_State* state, TYPE value) { \
return TO_LUA_LAMBDA_EXPRESSION(state, value); \
}
// Delegating constructors are necessary; automatic template deduction cannot
// deduce template argument for 'U' if 'default' methods are used as default values in
@@ -95,5 +115,28 @@ std::string NumericalProperty<T>::className() const {
return PropertyDelegate<NumericalProperty<T>>::className();
}
template <typename T>
bool NumericalProperty<T>::setLua(lua_State* state)
{
bool success;
T value = PropertyDelegate<NumericalProperty<T>>::fromLuaValue<T>(state, success);
if (success)
set(value);
return success;
}
template <typename T>
bool NumericalProperty<T>::getLua(lua_State* state) const
{
bool success = PropertyDelegate<NumericalProperty<T>>::toLuaValue<T>(state, TemplateProperty::_value);
return success;
}
template <typename T>
int openspace::properties::NumericalProperty<T>::typeLua() const {
return LUA_TNUMBER;
}
} // namespace properties
} // namespace openspace

View File

@@ -32,6 +32,8 @@
#include <functional>
#include <string>
struct lua_State;
namespace openspace {
namespace properties {
@@ -49,6 +51,10 @@ public:
virtual void set(boost::any value);
virtual const std::type_info& type() const;
virtual bool getLua(lua_State* state) const;
virtual bool setLua(lua_State* state);
virtual int typeLua() const;
virtual void onChange(std::function<void()> callback);
const std::string& identifier() const;

View File

@@ -27,6 +27,8 @@
#include <string>
struct lua_State;
namespace openspace {
namespace properties {
@@ -43,6 +45,12 @@ public:
template <typename U>
static U defaultMaximumValue();
template <typename U>
static U fromLuaValue(lua_State* state, bool& success);
template <typename U>
static bool toLuaValue(lua_State* state, U value);
};
} // namespace properties

View File

@@ -57,5 +57,19 @@ U PropertyDelegate<T>::defaultMaximumValue() {
"Unimplemented PropertyDelegate::defaultMaximumValue specialization");
}
template <typename T>
template <typename U>
U PropertyDelegate<T>::fromLuaValue(lua_State* state, bool& success) {
static_assert(sizeof(T) == 0,
"Unimplemented PropertyDelegate::fromLuaValue specialization");
}
template <typename T>
template <typename U>
bool PropertyDelegate<T>::toLuaValue(lua_State* state, U value) {
static_assert(sizeof(T) == 0,
"Unimplemented PropertyDelegate::toLuaValue specialization");
}
} // namespace properties
} // namespace openspace

View File

@@ -104,7 +104,8 @@ void TemplateProperty<T>::set(boost::any value) {
notifyListeners();
}
catch (boost::bad_any_cast&) {
LERRORC("TemplateProperty", "Illegal cast to '" << typeid(T).name() << "'");
LERRORC("TemplateProperty", "Illegal cast from '" << value.type().name()
<< "' to '" << typeid(T).name() << "'");
}
}

View File

@@ -40,7 +40,7 @@ int printFatal(lua_State* L);
// Properties
int property_setValue(lua_State* L);
//static int property_getValue(lua_State* L);
int property_getValue(lua_State* L);
} // namespace scripting
} // namespace openspace

View File

@@ -24,6 +24,8 @@
#include "openspace/properties/property.h"
#include <ghoul/lua/ghoul_lua.h>
namespace openspace {
namespace properties {
@@ -56,12 +58,24 @@ boost::any Property::get() const {
return boost::any();
}
bool Property::getLua(lua_State* state) const {
return true;
}
void Property::set(boost::any value) {}
bool Property::setLua(lua_State* state) {
return true;
}
const std::type_info& Property::type() const {
return typeid(void);
}
int Property::typeLua() const {
return LUA_TNONE;
}
const std::string& Property::guiName() const {
return _guiName;
}

View File

@@ -24,6 +24,8 @@
#include "openspace/properties/scalarproperty.h"
#include <ghoul/lua/ghoul_lua.h>
#include <limits>
using std::numeric_limits;
@@ -31,52 +33,101 @@ using std::numeric_limits;
namespace openspace {
namespace properties {
#define DEFAULT_FROM_LUA_LAMBDA(TYPE, DEFAULT_VALUE) \
[](lua_State* state, bool& success) -> TYPE { \
success = (lua_isnumber(state, -1) == 1); \
if (success) \
return static_cast<TYPE>(lua_tonumber(state, -1)); \
else \
return DEFAULT_VALUE; \
}
#define DEFAULT_TO_LUA_LAMBDA(TYPE) \
[](lua_State* state, TYPE value) -> bool { \
lua_pushnumber(state, static_cast<lua_Number>(value)); \
return true; \
}
// char16_t and char32_t are not supported on Visual Studio 2013 and are defined to
// be equal to unsigned short and unsigned int which causes a compile error
REGISTER_TEMPLATEPROPERTY_SOURCE(BoolProperty, bool, false);
REGISTER_NUMERICALPROPERTY_SOURCE(CharProperty, char, char(0),
numeric_limits<char>::lowest(), numeric_limits<char>::max(), char(1));
numeric_limits<char>::lowest(), numeric_limits<char>::max(), char(1),
DEFAULT_FROM_LUA_LAMBDA(char, char(0)), DEFAULT_TO_LUA_LAMBDA(char));
//REGISTER_NUMERICALPROPERTY_SOURCE(Char16Property, char16_t, char16_t(0),
// numeric_limits<char16_t>::lowest(), numeric_limits<char16_t>::max(), char16_t(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(Char32Property, char32_t, char32_t(0),
// numeric_limits<char32_t>::lowest(), numeric_limits<char32_t>::max(), char32_t(1));
REGISTER_NUMERICALPROPERTY_SOURCE(WCharProperty, wchar_t, wchar_t(0),
numeric_limits<wchar_t>::lowest(), numeric_limits<wchar_t>::max(), wchar_t(1));
numeric_limits<wchar_t>::lowest(), numeric_limits<wchar_t>::max(), wchar_t(1),
DEFAULT_FROM_LUA_LAMBDA(wchar_t, wchar_t(0)), DEFAULT_TO_LUA_LAMBDA(wchar_t));
REGISTER_NUMERICALPROPERTY_SOURCE(SignedCharProperty, signed char, (signed char)(0),
numeric_limits<signed char>::lowest(), numeric_limits<signed char>::max(),
(signed char)0);
(signed char)0, DEFAULT_FROM_LUA_LAMBDA(signed char, (signed char)(0)),
DEFAULT_TO_LUA_LAMBDA(signed char));
REGISTER_NUMERICALPROPERTY_SOURCE(UCharProperty, unsigned char, (unsigned char)0,
numeric_limits<unsigned char>::lowest(), numeric_limits<unsigned char>::max(),
(unsigned char)1);
(unsigned char)1, DEFAULT_FROM_LUA_LAMBDA(unsigned char, (unsigned char)(0)),
DEFAULT_TO_LUA_LAMBDA(unsigned char));
REGISTER_NUMERICALPROPERTY_SOURCE(ShortProperty, short, short(0),
numeric_limits<short>::lowest(), numeric_limits<short>::max(), short(1));
numeric_limits<short>::lowest(), numeric_limits<short>::max(), short(1),
DEFAULT_FROM_LUA_LAMBDA(short, short(0)), DEFAULT_TO_LUA_LAMBDA(short));
REGISTER_NUMERICALPROPERTY_SOURCE(UShortProperty, unsigned short, (unsigned short)(0),
numeric_limits<unsigned short>::lowest(), numeric_limits<unsigned short>::max(),
(unsigned short)1);
(unsigned short)1, DEFAULT_FROM_LUA_LAMBDA(unsigned short, (unsigned short)(0)),
DEFAULT_TO_LUA_LAMBDA(unsigned short));
REGISTER_NUMERICALPROPERTY_SOURCE(IntProperty, int, int(0),
numeric_limits<int>::lowest(), numeric_limits<int>::max(), int(1));
numeric_limits<int>::lowest(), numeric_limits<int>::max(), int(1),
DEFAULT_FROM_LUA_LAMBDA(int, int(0)), DEFAULT_TO_LUA_LAMBDA(int));
REGISTER_NUMERICALPROPERTY_SOURCE(UIntProperty, unsigned int, (unsigned int)0,
numeric_limits<unsigned int>::lowest(), numeric_limits<unsigned int>::max(),
(unsigned int)1);
(unsigned int)1, DEFAULT_FROM_LUA_LAMBDA(unsigned int, (unsigned int)(0)),
DEFAULT_TO_LUA_LAMBDA(unsigned int));
REGISTER_NUMERICALPROPERTY_SOURCE(LongProperty, long, long(0),
numeric_limits<long>::lowest(), numeric_limits<long>::max(), long(1));
numeric_limits<long>::lowest(), numeric_limits<long>::max(), long(1),
DEFAULT_FROM_LUA_LAMBDA(long, long(0)), DEFAULT_TO_LUA_LAMBDA(long));
REGISTER_NUMERICALPROPERTY_SOURCE(ULongProperty, unsigned long, (unsigned long)0,
numeric_limits<unsigned long>::lowest(), numeric_limits<unsigned long>::max(),
(unsigned long)1);
(unsigned long)1, DEFAULT_FROM_LUA_LAMBDA(unsigned long, (unsigned long)(0)),
DEFAULT_TO_LUA_LAMBDA(unsigned long));
REGISTER_NUMERICALPROPERTY_SOURCE(LongLongProperty, long long, (long long)0,
numeric_limits<long long>::lowest(), numeric_limits<long long>::max(), (long long)1);
numeric_limits<long long>::lowest(), numeric_limits<long long>::max(), (long long)1,
DEFAULT_FROM_LUA_LAMBDA(long long, (long long)(0)),
DEFAULT_TO_LUA_LAMBDA(long long));
REGISTER_NUMERICALPROPERTY_SOURCE(ULongLongProperty, unsigned long long,
(unsigned long long)1, numeric_limits<unsigned long long>::lowest(),
numeric_limits<unsigned long long>::max(), (unsigned long long)1);
numeric_limits<unsigned long long>::max(), (unsigned long long)1,
DEFAULT_FROM_LUA_LAMBDA(unsigned long long, (unsigned long long)(0)),
DEFAULT_TO_LUA_LAMBDA(unsigned long long));
REGISTER_NUMERICALPROPERTY_SOURCE(FloatProperty, float, 0.f,
numeric_limits<float>::lowest(), numeric_limits<float>::max(), 0.01f);
numeric_limits<float>::lowest(), numeric_limits<float>::max(), 0.01f,
DEFAULT_FROM_LUA_LAMBDA(float, float(0)), DEFAULT_TO_LUA_LAMBDA(float));
REGISTER_NUMERICALPROPERTY_SOURCE(DoubleProperty, double, 0.0,
numeric_limits<double>::lowest(), numeric_limits<double>::max(), 0.01);
numeric_limits<double>::lowest(), numeric_limits<double>::max(), 0.01,
DEFAULT_FROM_LUA_LAMBDA(double, double(0)), DEFAULT_TO_LUA_LAMBDA(double));
REGISTER_NUMERICALPROPERTY_SOURCE(LongDoubleProperty, long double, (long double)0,
numeric_limits<long double>::lowest(), numeric_limits<long double>::max(),
(long double)0.01f);
(long double)0.01f,
DEFAULT_FROM_LUA_LAMBDA(long double, (long double)(0)),
DEFAULT_TO_LUA_LAMBDA(long double));
} // namespace properties
} // namespace openspace

View File

@@ -352,8 +352,8 @@ bool SceneGraph::registerScriptFunctions()
ScriptEngine::LuaLibrary sceneGraphLibrary = {
"",
{
{ "setPropertyValue", &property_setValue}
// { "getPropertyValue", &property_getValue},
{ "setPropertyValue", &property_setValue},
{ "getPropertyValue", &property_getValue}
}
};

View File

@@ -222,14 +222,6 @@ void ScriptEngine::addLibraryFunctions(const LuaLibrary& library, bool replace)
}
void ScriptEngine::addBaseLibrary() {
ScriptEngine::LuaLibrary sceneGraphLibrary = {
"",
{
{ "setPropertyValue", &property_setValue}
// { "getPropertyValue", &property_getValue},
}
};
LuaLibrary lib = {
"",
{

View File

@@ -29,6 +29,7 @@
#include <ghoul/logging/logmanager.h>
#include <ghoul/lua/ghoul_lua.h>
#include <ghoul/lua/lua_helper.h>
namespace openspace {
namespace scripting {
@@ -97,29 +98,34 @@ int property_setValue(lua_State* L)
// TODO Check for argument number (ab)
std::string uri = luaL_checkstring(L, -2);
const int type = lua_type(L, -1);
boost::any propertyValue;
switch (type) {
case LUA_TNONE:
case LUA_TLIGHTUSERDATA:
case LUA_TTABLE:
case LUA_TFUNCTION:
case LUA_TUSERDATA:
case LUA_TTHREAD:
LERROR("Function parameter was of type '" << luaTypeToString(type) << "'");
return 0;
case LUA_TNIL:
propertyValue = 0;
break;
case LUA_TBOOLEAN:
propertyValue = lua_toboolean(L, -1);
break;
case LUA_TNUMBER:
propertyValue = lua_tonumber(L, -1);
break;
case LUA_TSTRING:
propertyValue = std::string(lua_tostring(L, -1));
break;
}
// boost::any propertyValue;
// switch (type) {
// case LUA_TNONE:
// case LUA_TLIGHTUSERDATA:
// case LUA_TFUNCTION:
// case LUA_TUSERDATA:
// case LUA_TTHREAD:
// LERROR("Function parameter was of type '" << luaTypeToString(type) << "'");
// return 0;
// case LUA_TNIL:
// propertyValue = 0;
// break;
// case LUA_TBOOLEAN:
// propertyValue = lua_toboolean(L, -1);
// break;
// case LUA_TNUMBER:
// propertyValue = lua_tonumber(L, -1);
// break;
// case LUA_TSTRING:
// propertyValue = std::string(lua_tostring(L, -1));
// break;
//case LUA_TTABLE: {
// ghoul::Dictionary d;
// ghoul::lua::populateDictionary(L, d);
// propertyValue = d;
// break;
//}
// }
Property* prop = property(uri);
if (!prop) {
@@ -127,15 +133,64 @@ int property_setValue(lua_State* L)
return 0;
}
prop->set(propertyValue);
//if (propertyValue.type() != prop->type()) {
if (type != prop->typeLua())
LERROR("Property '" << uri << "' does not accept input of type '"
<< luaTypeToString(type) << "'. Requested type: '"
<< luaTypeToString(prop->typeLua() << "'");
}
else
prop->setLua(L);
//prop->set(propertyValue);
return 0;
}
//int property_getValue(lua_State* L)
//{
//
//}
int property_getValue(lua_State* L) {
const std::string _loggerCat = "property_getValue";
// TODO Check for argument number (ab)
std::string uri = luaL_checkstring(L, -1);
Property* prop = property(uri);
if (!prop) {
LERROR("Property with uri '" << uri << "' could not be found");
lua_pushnil(L);
}
else {
prop->getLua(L);
//switch (type) {
// case LUA_TNONE:
// case LUA_TLIGHTUSERDATA:
// case LUA_TFUNCTION:
// case LUA_TUSERDATA:
// case LUA_TTHREAD:
// LERROR("Function parameter was of type '" << luaTypeToString(type)
// << "'");
// return 0;
// case LUA_TNIL:
// propertyValue = 0;
// break;
// case LUA_TBOOLEAN:
// propertyValue = lua_toboolean(L, -1);
// break;
// case LUA_TNUMBER:
// propertyValue = lua_tonumber(L, -1);
// break;
// case LUA_TSTRING:
// propertyValue = std::string(lua_tostring(L, -1));
// break;
// case LUA_TTABLE: {
// ghoul::Dictionary d;
// ghoul::lua::populateDictionary(L, d);
// propertyValue = d;
// break;
// }
//}
}
return 1;
}
} // namespace scripting
} // namespace openspace