Otclient  14/8/2020
luaobject.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2020 OTClient <https://github.com/edubart/otclient>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 #ifndef LUAOBJECT_H
24 #define LUAOBJECT_H
25 
26 #include "declarations.h"
27 
29 // @bindclass
31 {
32 public:
33  LuaObject();
34  virtual ~LuaObject();
35 
36  template<typename T>
37  void connectLuaField(const std::string& field, const std::function<T>& f, bool pushFront = false);
38 
42  template<typename... T>
43  int luaCallLuaField(const std::string& field, const T&... args);
44 
45  template<typename R, typename... T>
46  R callLuaField(const std::string& field, const T&... args);
47  template<typename... T>
48  void callLuaField(const std::string& field, const T&... args);
49 
51  bool hasLuaField(const std::string& field);
52 
54  template<typename T>
55  void setLuaField(const std::string& key, const T& value);
56 
58  template<typename T>
59  T getLuaField(const std::string& key);
60 
62  void releaseLuaFieldsTable();
63 
65  void luaSetField(const std::string& key);
66 
68  void luaGetField(const std::string& key);
69 
71  void luaGetMetatable();
72 
74  void luaGetFieldsTable();
75 
78  int getUseCount();
79 
81  std::string getClassName();
82 
83  LuaObjectPtr asLuaObject() { return static_self_cast<LuaObject>(); }
84 
85  void operator=(const LuaObject&) { }
86 
87 private:
88  int m_fieldsTableRef;
89 };
90 
91 template<typename F>
92 void connect(const LuaObjectPtr& obj, const std::string& field, const std::function<F>& f, bool pushFront = false);
93 
94 template<typename Lambda>
95 typename std::enable_if<std::is_constructible<decltype(&Lambda::operator())>::value, void>::type
96 connect(const LuaObjectPtr& obj, const std::string& field, const Lambda& f, bool pushFront = false);
97 
98 #include "luainterface.h"
99 
100 template<typename T>
101 void LuaObject::connectLuaField(const std::string& field, const std::function<T>& f, bool pushFront)
102 {
103  luaGetField(field);
104  if(g_lua.isTable()) {
105  if(pushFront)
106  g_lua.pushInteger(1);
107  push_luavalue(f);
108  g_lua.callGlobalField("table","insert");
109  } else {
110  if(g_lua.isNil()) {
111  push_luavalue(f);
112  luaSetField(field);
113  g_lua.pop();
114  } else if(g_lua.isFunction()) {
115  g_lua.newTable();
116  g_lua.insert(-2);
117  g_lua.rawSeti(1);
118  push_luavalue(f);
119  g_lua.rawSeti(2);
120  luaSetField(field);
121  }
122  }
123 }
124 
125 // connect for std::function
126 template<typename F>
127 void connect(const LuaObjectPtr& obj, const std::string& field, const std::function<F>& f, bool pushFront) {
128  obj->connectLuaField<F>(field, f, pushFront);
129 }
130 
131 namespace luabinder {
132  template<typename F>
134 
135  template<typename Lambda, typename Ret, typename... Args>
136  struct connect_lambda<Ret(Lambda::*)(Args...) const> {
137  static void call(const LuaObjectPtr& obj, const std::string& field, const Lambda& f, bool pushFront) {
138  connect(obj, field, std::function<Ret(Args...)>(f), pushFront);
139  }
140  };
141 };
142 
143 // connect for lambdas
144 template<typename Lambda>
145 typename std::enable_if<std::is_constructible<decltype(&Lambda::operator())>::value, void>::type
146 connect(const LuaObjectPtr& obj, const std::string& field, const Lambda& f, bool pushFront) {
147  typedef decltype(&Lambda::operator()) F;
148  luabinder::connect_lambda<F>::call(obj, field, f, pushFront);
149 }
150 
151 template<typename... T>
152 int LuaObject::luaCallLuaField(const std::string& field, const T&... args) {
153  // note that the field must be retrieved from this object lua value
154  // to force using the __index metamethod of it's metatable
155  // so cannot use LuaObject::getField here
156  // push field
158  g_lua.getField(field);
159 
160  if(!g_lua.isNil()) {
161  // the first argument is always this object (self)
162  g_lua.insert(-2);
163  int numArgs = g_lua.polymorphicPush(args...);
164  return g_lua.signalCall(1 + numArgs);
165  } else {
166  g_lua.pop(2);
167  }
168  return 0;
169 }
170 
171 template<typename R, typename... T>
172 R LuaObject::callLuaField(const std::string& field, const T&... args) {
173  R result;
174  int rets = luaCallLuaField(field, args...);
175  if(rets > 0) {
176  assert(rets == 1);
177  result = g_lua.polymorphicPop<R>();
178  } else
179  result = R();
180  return result;
181 }
182 
183 template<typename... T>
184 void LuaObject::callLuaField(const std::string& field, const T&... args) {
185  int rets = luaCallLuaField(field, args...);
186  if(rets > 0)
187  g_lua.pop(rets);
188 }
189 
190 template<typename T>
191 void LuaObject::setLuaField(const std::string& key, const T& value) {
192  g_lua.polymorphicPush(value);
193  luaSetField(key);
194 }
195 
196 template<typename T>
197 T LuaObject::getLuaField(const std::string& key) {
198  luaGetField(key);
199  return g_lua.polymorphicPop<T>();
200 }
201 
202 #endif
push_luavalue
int push_luavalue(const Outfit &outfit)
Definition: luavaluecasts.cpp:26
LuaInterface::insert
void insert(int index)
Definition: luainterface.cpp:819
LuaInterface::rawSeti
void rawSeti(int n, int index=-2)
Definition: luainterface.cpp:978
LuaObject::connectLuaField
void connectLuaField(const std::string &field, const std::function< T > &f, bool pushFront=false)
Definition: luaobject.h:101
LuaObject::luaGetMetatable
void luaGetMetatable()
Get object's metatable.
Definition: luaobject.cpp:87
luabinder::connect_lambda< Ret(Lambda::*)(Args...) const >::call
static void call(const LuaObjectPtr &obj, const std::string &field, const Lambda &f, bool pushFront)
Definition: luaobject.h:137
LuaInterface::callGlobalField
void callGlobalField(const std::string &global, const std::string &field, const T &... args)
Definition: luainterface.h:445
LuaObject::luaGetFieldsTable
void luaGetFieldsTable()
Gets the table containing all stored fields of this lua object, the result is pushed onto the stack.
Definition: luaobject.cpp:104
luainterface.h
LuaInterface::isFunction
bool isFunction(int index=-1)
Definition: luainterface.cpp:1180
LuaObject::getClassName
std::string getClassName()
Returns the derived class name, its the same name used in Lua.
Definition: luaobject.cpp:117
connect
std::enable_if< std::is_constructible< decltype(&Lambda::operator())>::value, void >::type connect(const LuaObjectPtr &obj, const std::string &field, const Lambda &f, bool pushFront=false)
Definition: luaobject.h:96
LuaObject::~LuaObject
virtual ~LuaObject()
Definition: luaobject.cpp:34
LuaInterface::getField
void getField(const char *key, int index=-1)
Definition: luainterface.cpp:880
LuaInterface::polymorphicPush
int polymorphicPush(const T &v, const Args &... args)
Pushes any type onto the stack.
Definition: luainterface.h:358
LuaObject::releaseLuaFieldsTable
void releaseLuaFieldsTable()
Release fields table reference.
Definition: luaobject.cpp:54
declarations.h
LuaObject::callLuaField
R callLuaField(const std::string &field, const T &... args)
Definition: luaobject.h:172
LuaInterface::isNil
bool isNil(int index=-1)
Definition: luainterface.cpp:1150
g_lua
LuaInterface g_lua
Definition: luainterface.cpp:31
LuaObject::luaSetField
void luaSetField(const std::string &key)
Sets a field from this lua object, the value must be on the stack.
Definition: luaobject.cpp:62
LuaObject::luaGetField
void luaGetField(const std::string &key)
Gets a field from this lua object, the result is pushed onto the stack.
Definition: luaobject.cpp:76
LuaObject::getUseCount
int getUseCount()
Definition: luaobject.cpp:112
LuaInterface::polymorphicPop
T polymorphicPop()
Same as castValue but also pops.
Definition: luainterface.h:339
LuaInterface::pushObject
void pushObject(const LuaObjectPtr &obj)
Definition: luainterface.cpp:1109
LuaObject::asLuaObject
LuaObjectPtr asLuaObject()
Definition: luaobject.h:83
LuaObject::setLuaField
void setLuaField(const std::string &key, const T &value)
Sets a field in this lua object.
Definition: luaobject.h:191
luabinder
Definition: luabinder.h:40
LuaInterface::signalCall
int signalCall(int numArgs=0, int numRets=-1)
Definition: luainterface.cpp:468
LuaInterface::isTable
bool isTable(int index=-1)
Definition: luainterface.cpp:1174
LuaObject::getLuaField
T getLuaField(const std::string &key)
Gets a field from this lua object.
Definition: luaobject.h:197
LuaInterface::pop
void pop(int n=1)
Definition: luainterface.cpp:999
stdext::shared_object_ptr
Definition: shared_object.h:39
LuaObject::hasLuaField
bool hasLuaField(const std::string &field)
Returns true if the lua field exists.
Definition: luaobject.cpp:42
LuaObject::luaCallLuaField
int luaCallLuaField(const std::string &field, const T &... args)
Definition: luaobject.h:152
luabinder::connect_lambda
Definition: luaobject.h:133
LuaInterface::pushInteger
void pushInteger(long v)
Definition: luainterface.cpp:1066
LuaObject
LuaObject, all script-able classes have it as base.
Definition: luaobject.h:30
LuaObject::LuaObject
LuaObject()
Definition: luaobject.cpp:29
stdext::shared_object
Definition: shared_object.h:41
LuaObject::operator=
void operator=(const LuaObject &)
Definition: luaobject.h:85
LuaInterface::newTable
void newTable()
Definition: luainterface.cpp:984