diff --git a/Client/App/App.vcproj b/Client/App/App.vcproj index 69a3788c..1524efbb 100644 --- a/Client/App/App.vcproj +++ b/Client/App/App.vcproj @@ -1,1321 +1,1813 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Client/App/include/lua/LuaBridge.h b/Client/App/include/lua/LuaBridge.h new file mode 100644 index 00000000..b6f3db71 --- /dev/null +++ b/Client/App/include/lua/LuaBridge.h @@ -0,0 +1,211 @@ +#pragma once +#include "lua.h" +#include "lauxlib.h" +#include "boost/shared_ptr.hpp" +#include "util/Utilities.h" +#include "G3D/format.h" +#include + +namespace RBX +{ + namespace Lua + { + template + class Bridge + { + protected: + static const char* className; + + public: + static T* pushNewObject(lua_State* L) + { + T* ptr = static_cast(lua_newuserdata(L, sizeof(T))); + new(ptr) T(); + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return ptr; + } + static T& getObject(lua_State* L, size_t index) + { + return *static_cast(luaL_checkudata(L, static_cast(index), className)); + } + static void registerClass(lua_State* L) + { + luaL_newmetatable(L, className); + + lua_pushstring(L, "__index"); + lua_pushcfunction(L, on_index); + lua_settable(L, -3); + + lua_pushstring(L, "__newindex"); + lua_pushcfunction(L, on_newindex); + lua_settable(L, -3); + + lua_pushstring(L, "__gc"); + lua_pushcfunction(L, on_gc); + lua_settable(L, -3); + + if (isComparable) + { + lua_pushstring(L, "__eq"); + lua_pushcfunction(L, on_eq); + lua_settable(L, -3); + } + + lua_pushstring(L, "__tostring"); + lua_pushcfunction(L, on_tostring); + lua_settable(L, -3); + + lua_pop(L, 1); + } + + public: + template + static T* pushNewObject(lua_State* L, Param1Type param1) + { + T* ptr = static_cast(lua_newuserdata(L, sizeof(T))); + new(ptr) T(param1); + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return ptr; + } + + template + static bool getValue(lua_State* L, size_t index, Object& value) + { + const Object* object = static_cast(lua_touserdata(L,static_cast(index))); + if (object) + { + if (lua_getmetatable(L, static_cast(index))) + { + luaL_getmetatable(L, className); + if (lua_rawequal(L, -1, -2)) + { + lua_pop(L, 2); + value = *object; + return true; + } + } + else + { + lua_pop(L, 1); + } + } + + return false; + } + + protected: + static int on_index(lua_State* L) + { + const char* name = luaL_checkstring(L, 2); + T& object = getObject(L, 1); + return on_index(object, name, L); + } + static int on_index(const T& object, const char* name, lua_State* L); + static int on_newindex(lua_State* L) + { + // TODO: function return not matching + const char* name = luaL_checkstring(L, 2); + T& object = getObject(L, 1); + on_newindex(object, name, L); + return 0; + } + static void on_newindex(T& object, const char* name, lua_State* L) + { + throw std::runtime_error(G3D::format("%s cannot be assigned to", name)); + } + static int on_tostring(lua_State* L) + { + T& object = getObject(L, 1); + return on_tostring(object, L); + } + static int on_tostring(const T& object, lua_State* L) + { + std::string name = StringConverter::convertToString(object); + lua_pushstring(L, name.c_str()); + return 1; + } + static int on_gc(lua_State* L) + { + T& object = getObject(L, 1); + object.~T(); + return 0; + } + static int on_eq(lua_State* L) + { + lua_pushboolean(L, getObject(L, 1) == getObject(L, 2)); + return 1; + } + }; + + template + class SharedPtrBridge : protected Bridge, false> + { + public: + static void registerClass(lua_State* L) + { + Bridge, false>::registerClass(L); + } + static void registerClassLibrary(lua_State* L) + { + lua_pushlightuserdata(L, push); + newweaktable(L, "v"); + lua_rawset(L, LUA_REGISTRYINDEX); + } + static void push(lua_State* L, boost::shared_ptr instance) + { + if (!instance) + { + lua_pushnil(L); + } + else + { + lua_gettop(L); + lua_pushlightuserdata(L, push); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_pushlightuserdata(L, instance.get()); + lua_rawget(L, -2); + + if (lua_type(L, -1) == LUA_TNIL) + { + lua_pop(L, 1); + pushNewObject(L, instance); + lua_pushlightuserdata(L, instance.get()); + lua_pushvalue(L, -2); + lua_rawset(L, -4); + } + + lua_remove(L, -2); + } + } + static boost::shared_ptr getPtr(lua_State* L, size_t index) + { + // TODO: check match for T=boost::shared_ptr + // when security is implemented + + if (lua_type(L, static_cast(index)) == LUA_TNIL) + { + return boost::shared_ptr(); + } + else + { + return getObject(L, index); + } + } + + public: + template + static bool getPtr(lua_State* L, size_t index, ValueType& value) + { + if (lua_type(L, static_cast(index)) == LUA_TNIL) + { + value = boost::shared_ptr(); + return 1; + } + + return getValue(L, index, value); + } + }; + } +} diff --git a/Client/App/include/lua/lua.hpp b/Client/App/include/lua/lua.hpp new file mode 100644 index 00000000..dc270422 --- /dev/null +++ b/Client/App/include/lua/lua.hpp @@ -0,0 +1,28 @@ +#pragma once +#include "lua.h" + +namespace RBX +{ + namespace Lua + { + class ScopedPopper + { + private: + int popCount; + lua_State* thread; + + public: + ScopedPopper(lua_State* thread, int popCount) + : popCount(popCount), + thread(thread) + { + } + ScopedPopper& operator+=(int); + ScopedPopper& operator-=(int); + ~ScopedPopper() + { + lua_pop(thread, popCount); + } + }; + } +} diff --git a/Client/App/include/reflection/function.h b/Client/App/include/reflection/function.h index 2dfbf995..0a5d3b6a 100644 --- a/Client/App/include/reflection/function.h +++ b/Client/App/include/reflection/function.h @@ -16,6 +16,7 @@ namespace RBX NeedTrustedCaller = 0, AnyCaller = 1 }; + public: class Arguments { @@ -25,32 +26,23 @@ namespace RBX public: virtual size_t size() const = 0; virtual void get(int, Value&) const = 0; - public: - //Arguments(const Arguments&); - Arguments(); - ~Arguments(); - public: - //Arguments& operator=(const Arguments&); }; + public: typedef Function Describing; public: const Security security; + protected: SignatureDescriptor signature; - public: - //FunctionDescriptor(const FunctionDescriptor&); protected: FunctionDescriptor(ClassDescriptor& classDescriptor, const char* name, Security security); + public: const SignatureDescriptor& getSignature() const; virtual void execute(DescribedBase*, Arguments&) const = 0; - public: - virtual ~FunctionDescriptor(); - public: - //FunctionDescriptor& operator=(const FunctionDescriptor&); }; class Function @@ -60,29 +52,25 @@ namespace RBX const DescribedBase* instance; public: - //Function(const Function&); + Function(const Function&); Function(const FunctionDescriptor&, const DescribedBase*); - public: Function& operator=(const Function&); const Name& getName() const; - const FunctionDescriptor* getDescriptor() const; + const FunctionDescriptor* getDescriptor() const + { + return descriptor; + } void execute(FunctionDescriptor::Arguments&) const; }; template class FuncDesc : public FunctionDescriptor { - public: - //FuncDesc(const FuncDesc&); protected: FuncDesc(const char* name, Security security) : FunctionDescriptor(Class::classDescriptor(), name, security) { } - public: - virtual ~FuncDesc(); - public: - //FuncDesc& operator=(const FuncDesc&); }; } } diff --git a/Client/App/include/reflection/member.h b/Client/App/include/reflection/member.h index ba33aeb6..1bb6be82 100644 --- a/Client/App/include/reflection/member.h +++ b/Client/App/include/reflection/member.h @@ -16,8 +16,6 @@ namespace RBX const Name& category; const ClassDescriptor& owner; - public: - //MemberDescriptor(const MemberDescriptor&); protected: MemberDescriptor(const ClassDescriptor& owner, const char* name, const char* category) : Descriptor(name), @@ -26,47 +24,72 @@ namespace RBX { } virtual ~MemberDescriptor(); + public: bool isMemberOf(const DescribedBase*) const; bool isMemberOf(const ClassDescriptor&) const; - //MemberDescriptor& operator=(const MemberDescriptor&); }; template class MemberDescriptorContainer { public: - typedef std::vector Collection; + typedef std::vector CollectionType; + class Collection : public CollectionType + { + }; public: class Iterator : public std::iterator { private: DescribedBase* instance; - typename Collection::const_iterator iter; + typename CollectionType::const_iterator iter; public: - Iterator(const typename Collection::const_iterator&, DescribedBase*); + Iterator(const typename CollectionType::const_iterator& iter, DescribedBase* instance) + : instance(instance), + iter(iter) + { + } + public: typename TheDescriptor::Describing operator*() const; - bool operator==(const Iterator&) const; - bool operator!=(const Iterator&) const; + bool operator==(const Iterator& other) const + { + return iter == other.iter; + } + bool operator!=(const Iterator& other) const + { + return iter != other.iter; + } Iterator operator++(int); Iterator& operator++(); }; + public: class ConstIterator : public std::iterator { private: const DescribedBase* instance; - typename Collection::const_iterator iter; + typename CollectionType::const_iterator iter; public: - ConstIterator(const typename Collection::const_iterator&, const DescribedBase*); + ConstIterator(const typename CollectionType::const_iterator& iter, const DescribedBase* instance) + : instance(instance), + iter(iter) + { + } public: typename TheDescriptor::Describing operator*() const; - bool operator==(const ConstIterator&) const; - bool operator!=(const ConstIterator&) const; + bool operator==(const ConstIterator& other) const + { + return iter == other.iter; + } + bool operator!=(const ConstIterator& other) const + { + return iter != other.iter; + } ConstIterator operator++(int); ConstIterator& operator++(); const TheDescriptor& getDescriptor() const; @@ -77,8 +100,6 @@ namespace RBX std::vector derivedContainers; MemberDescriptorContainer* base; - public: - //MemberDescriptorContainer(const MemberDescriptorContainer&); protected: // TODO: check if matches MemberDescriptorContainer(MemberDescriptorContainer* base) @@ -93,20 +114,93 @@ namespace RBX base->derivedContainers.push_back(this); } } + public: void declare(TheDescriptor*); - typename Collection::const_iterator descriptors_begin() const; - typename Collection::const_iterator descriptors_end() const; - typename Collection::const_iterator findDescriptor(const Name&) const; - Iterator findMember(const Name&, DescribedBase*) const; - ConstIterator findConstMember(const Name&, const DescribedBase*) const; - Iterator members_begin(DescribedBase*) const; - ConstIterator members_begin(const DescribedBase*) const; - Iterator members_end(DescribedBase*) const; - ConstIterator members_end(const DescribedBase*) const; + + typename CollectionType::const_iterator descriptors_begin() const + { + return descriptors.begin(); + } + typename CollectionType::const_iterator descriptors_end() const + { + return descriptors.end(); + } + typename CollectionType::const_iterator findDescriptor(const Name& name) const + { + size_t posStart = 0; + size_t posEnd = descriptors.size(); + + if (posEnd) + { + size_t i; + bool found = false; + + do + { + i = (posStart+posEnd)/2; + + const Name& descName = descriptors[i]->name; + + if (name == descName) + { + found = true; + break; + } + + int compare = name.compare(descName); + + if (compare < 0) + { + posEnd = i; + } + else + { + if (compare <= 0) + { + found = true; + break; + } + + posStart = i+1; + } + } while (posStart < posEnd); + + if (found) + return descriptors.begin()+i; + } + + return descriptors.end(); + } + + Iterator findMember(const Name& name, DescribedBase* instance) const + { + return Iterator::Iterator(findDescriptor(name), instance); + } + ConstIterator findConstMember(const Name& name, const DescribedBase* instance) const + { + return ConstIterator::ConstIterator(findDescriptor(name), instance); + } + + Iterator members_begin(DescribedBase* instance) const + { + return Iterator::Iterator(descriptors_begin(), instance); + } + ConstIterator members_begin(const DescribedBase* instance) const + { + return ConstIterator::ConstIterator(descriptors_begin(), instance); + } + + Iterator members_end(DescribedBase* instance) const + { + return Iterator::Iterator(descriptors_end(), instance); + } + ConstIterator members_end(const DescribedBase* instance) const + { + return ConstIterator::ConstIterator(descriptors_end(), instance); + } + void mergeMembers(const MemberDescriptorContainer*); - public: - ~MemberDescriptorContainer() {} // TODO: does not match public: static bool compare(const TheDescriptor*, const TheDescriptor*); diff --git a/Client/App/include/reflection/object.h b/Client/App/include/reflection/object.h index 68936e5d..43df43fd 100644 --- a/Client/App/include/reflection/object.h +++ b/Client/App/include/reflection/object.h @@ -13,24 +13,35 @@ namespace RBX { namespace Reflection { - class ClassDescriptor : public Descriptor, public MemberDescriptorContainer, public MemberDescriptorContainer, public MemberDescriptorContainer - { - public: - typedef MemberDescriptorContainer PropertyContainer; - typedef MemberDescriptorContainer SignalContainer; - typedef MemberDescriptorContainer FunctionContainer; + typedef MemberDescriptorContainer PropertyContainer; + typedef MemberDescriptorContainer::Iterator PropertyIterator; + typedef MemberDescriptorContainer::ConstIterator ConstPropertyIterator; + + typedef MemberDescriptorContainer FunctionContainer; + typedef MemberDescriptorContainer::ConstIterator FunctionIterator; + typedef MemberDescriptorContainer SignalContainer; + typedef MemberDescriptorContainer::Iterator SignalIterator; + typedef MemberDescriptorContainer::ConstIterator ConstSignalIterator; + + class ClassDescriptor : public Descriptor, + public MemberDescriptorContainer, + public MemberDescriptorContainer, + public MemberDescriptorContainer + { private: std::vector derivedClasses; ClassDescriptor* base; + public: static bool lockedDown; public: - //ClassDescriptor(const ClassDescriptor&); ClassDescriptor(ClassDescriptor& base, const char* name); + private: ClassDescriptor(); + public: const ClassDescriptor* getBase() const { @@ -44,10 +55,6 @@ namespace RBX std::vector::const_iterator derivedClasses_end() const; bool operator==(const ClassDescriptor& other) const; bool operator!=(const ClassDescriptor& other) const; - public: - virtual ~ClassDescriptor(); - public: - //ClassDescriptor& operator=(const ClassDescriptor&); public: static ClassDescriptor& rootDescriptor() // TODO: check @@ -59,11 +66,6 @@ namespace RBX class __declspec(novtable) DescribedBase : public SignalSource { - public: - typedef MemberDescriptorContainer MDCProperty; - typedef MemberDescriptorContainer MDCFunction; - typedef MemberDescriptorContainer MDCSignal; - protected: const ClassDescriptor* descriptor; @@ -73,26 +75,76 @@ namespace RBX ClassDescriptor::lockedDown = true; descriptor = &ClassDescriptor::rootDescriptor(); } + public: const ClassDescriptor& getDescriptor() const { return *descriptor; } - MDCProperty::ConstIterator findProperty(const Name&) const; - MDCProperty::Iterator findProperty(const Name&); - MDCProperty::Iterator properties_begin(); - MDCProperty::ConstIterator properties_begin() const; - MDCProperty::Iterator properties_end(); - MDCProperty::ConstIterator properties_end() const; - MDCFunction::ConstIterator findFunction(const Name&) const; - MDCFunction::ConstIterator functions_begin() const; - MDCFunction::ConstIterator functions_end() const; - MDCSignal::ConstIterator findSignal(const Name&) const; - MDCSignal::Iterator findSignal(const Name&); - MDCSignal::Iterator signals_begin(); - MDCSignal::ConstIterator signals_begin() const; - MDCSignal::Iterator signals_end(); - MDCSignal::ConstIterator signals_end() const; + + // TODO: find iterators don't fully match when inlined (see LuaInstanceBridge.cpp) + ConstPropertyIterator findProperty(const Name& name) const + { + return getDescriptor().PropertyContainer::findConstMember(name, this); + } + PropertyIterator findProperty(const Name& name) + { + return getDescriptor().PropertyContainer::findMember(name, this); + } + PropertyIterator properties_begin() + { + return getDescriptor().PropertyContainer::members_begin(this); + } + ConstPropertyIterator properties_begin() const + { + return getDescriptor().PropertyContainer::members_begin(this); + } + PropertyIterator properties_end() + { + return getDescriptor().PropertyContainer::members_end(this); + } + ConstPropertyIterator properties_end() const + { + return getDescriptor().PropertyContainer::members_end(this); + } + + FunctionIterator findFunction(const Name& name) const + { + return getDescriptor().FunctionContainer::findConstMember(name, this); + } + FunctionIterator functions_begin() const + { + return getDescriptor().FunctionContainer::members_begin(this); + } + FunctionIterator functions_end() const + { + return getDescriptor().FunctionContainer::members_end(this); + } + + ConstSignalIterator findSignal(const Name& name) const + { + return getDescriptor().SignalContainer::findConstMember(name, this); + } + SignalIterator findSignal(const Name& name) + { + return getDescriptor().SignalContainer::findMember(name, this); + } + SignalIterator signals_begin() + { + return getDescriptor().SignalContainer::members_begin(this); + } + ConstSignalIterator signals_begin() const + { + return getDescriptor().SignalContainer::members_begin(this); + } + SignalIterator signals_end() + { + return getDescriptor().SignalContainer::members_end(this); + } + ConstSignalIterator signals_end() const + { + return getDescriptor().SignalContainer::members_end(this); + } public: static ClassDescriptor& classDescriptor() diff --git a/Client/App/include/reflection/property.h b/Client/App/include/reflection/property.h index 2660483f..49a42d21 100644 --- a/Client/App/include/reflection/property.h +++ b/Client/App/include/reflection/property.h @@ -22,37 +22,38 @@ namespace RBX STREAMING = 4, LEGACY = 0 }; + public: typedef Property Describing; private: size_t bIsPublic : 1; size_t bCanStreamWrite : 1; + public: const Type& type; - public: - //PropertyDescriptor(const PropertyDescriptor&); protected: PropertyDescriptor(ClassDescriptor& classDescriptor, const Type& type, const char* name, const char* category, Functionality flags); + public: bool isPublic() const; virtual bool isReadOnly() const = 0; bool canStreamWrite() const; - bool operator==(const PropertyDescriptor&) const; + bool operator==(const PropertyDescriptor& other) const + { + return this == &other; + } virtual bool equalValues(const DescribedBase*, const DescribedBase*) const = 0; virtual bool hasStringValue() const = 0; virtual std::string getStringValue(const DescribedBase*) const = 0; virtual bool setStringValue(DescribedBase*, const std::string&) const = 0; XmlElement* write(const DescribedBase*, bool) const; virtual void read(DescribedBase*, const XmlElement*, IReferenceBinder&) const; + private: virtual void writeValue(const DescribedBase*, XmlElement*) const = 0; virtual void readValue(DescribedBase*, const XmlElement*, IReferenceBinder&) const = 0; - public: - virtual ~PropertyDescriptor(); - public: - //PropertyDescriptor& operator=(const PropertyDescriptor&); }; class ConstProperty @@ -62,7 +63,11 @@ namespace RBX const DescribedBase* instance; public: - //ConstProperty(const ConstProperty&); + ConstProperty(const ConstProperty& other) + : descriptor(other.descriptor), + instance(other.instance) + { + } ConstProperty(const PropertyDescriptor& descriptor, const DescribedBase* instance) : descriptor(&descriptor), instance(instance) @@ -78,23 +83,28 @@ namespace RBX { return *descriptor; // might be wrong? } - //ConstProperty& operator=(const ConstProperty&); // maybe? + ConstProperty& operator=(const ConstProperty&); const Name& getName() const; bool hasStringValue() const; std::string getStringValue() const; XmlElement* write() const; + + public: + template + T getValue() const; }; class Property : public ConstProperty { public: - //Property(const Property&); + Property(const Property&); Property(const PropertyDescriptor& descriptor, DescribedBase* instance) : ConstProperty(descriptor, instance) { } + public: - //Property& operator=(const Property&); // maybe? + Property& operator=(const Property&); bool operator==(const Property&) const; bool operator!=(const Property&) const; DescribedBase* getInstance() const @@ -103,6 +113,10 @@ namespace RBX } bool setStringValue(const std::string&); void read(const XmlElement*, IReferenceBinder&); + + public: + template + void setValue(const T& value); }; template @@ -115,20 +129,11 @@ namespace RBX virtual bool isReadOnly() const = 0; virtual PropType getValue(const DescribedBase*) const = 0; virtual void setValue(DescribedBase*, const PropType&) const = 0; - public: - //GetSet(const GetSet&); - GetSet() - { - } - public: - //GetSet& operator=(const GetSet&); }; protected: std::auto_ptr getset; - public: - //TypedPropertyDescriptor(TypedPropertyDescriptor&); protected: TypedPropertyDescriptor(ClassDescriptor& classDescriptor, const char* name, const char* category, std::auto_ptr getset, Functionality flags) : PropertyDescriptor(classDescriptor, Type::singleton(), name, category, flags), @@ -136,6 +141,7 @@ namespace RBX { } TypedPropertyDescriptor(ClassDescriptor&, const Type&, const char*, const char*, std::auto_ptr, Functionality); + public: virtual bool isReadOnly() const; PropType getValue(const DescribedBase*) const; @@ -144,13 +150,10 @@ namespace RBX virtual bool hasStringValue() const; virtual std::string getStringValue(const DescribedBase*) const; virtual bool setStringValue(DescribedBase*, const std::string&) const; + private: virtual void readValue(DescribedBase*, const XmlElement*, IReferenceBinder&) const; virtual void writeValue(const DescribedBase*, XmlElement*) const; - public: - virtual ~TypedPropertyDescriptor(); - public: - //TypedPropertyDescriptor& operator=(TypedPropertyDescriptor&); }; class RefPropertyDescriptor : public PropertyDescriptor @@ -158,21 +161,15 @@ namespace RBX public: virtual DescribedBase* getRefValue(const DescribedBase*) const = 0; virtual void setRefValue(DescribedBase*, DescribedBase*) const = 0; - public: - //RefPropertyDescriptor(const RefPropertyDescriptor&); + protected: RefPropertyDescriptor(ClassDescriptor& classDescriptor, const Type& type, const char* name, const char* category, Functionality flags) : PropertyDescriptor(classDescriptor, type, name, category, flags) { } - protected: virtual bool hasStringValue() const; virtual std::string getStringValue(const DescribedBase*) const; virtual bool setStringValue(DescribedBase*, const std::string&) const; - public: - virtual ~RefPropertyDescriptor(); - public: - //RefPropertyDescriptor& operator=(const RefPropertyDescriptor&); }; class EnumPropertyDescriptor : public PropertyDescriptor @@ -185,14 +182,9 @@ namespace RBX virtual bool setIndexValue(DescribedBase*, unsigned) const = 0; virtual int getEnumValue(const DescribedBase*) const = 0; virtual bool setEnumValue(DescribedBase*, int) const = 0; - public: - //EnumPropertyDescriptor(const EnumPropertyDescriptor&); + protected: EnumPropertyDescriptor(ClassDescriptor&, const EnumDescriptor&, const char*, const char*, Functionality); - public: - virtual ~EnumPropertyDescriptor(); - public: - //EnumPropertyDescriptor& operator=(const EnumPropertyDescriptor&); }; } } diff --git a/Client/App/include/reflection/reflection.h b/Client/App/include/reflection/reflection.h index ed61eebf..e13c13ff 100644 --- a/Client/App/include/reflection/reflection.h +++ b/Client/App/include/reflection/reflection.h @@ -65,23 +65,16 @@ namespace RBX // helps with constructors typedef DescribedCreatable Base; - public: - //DescribedCreatable(const DescribedCreatable&); protected: DescribedCreatable(); + template DescribedCreatable(Arg0Type arg0); - public: - virtual ~DescribedCreatable(); - public: - //DescribedCreatable& operator=(const DescribedCreatable&); }; template class DescribedNonCreatable : public Reflection::Described> { - public: - //DescribedNonCreatable(const DescribedNonCreatable&); protected: DescribedNonCreatable() : Described() @@ -93,10 +86,6 @@ namespace RBX : Described(arg0) { } - public: - virtual ~DescribedNonCreatable(); - public: - //DescribedNonCreatable& operator=(const DescribedNonCreatable&); }; namespace Reflection @@ -116,7 +105,6 @@ namespace RBX void (Class::*changed)(const PropertyDescriptor&); public: - //BoundPropGetSet(const BoundPropGetSet&); BoundPropGetSet(BoundProp& desc, PropType (Class::*member), void (Class::*changed)(const PropertyDescriptor&)) : desc(desc), member(member), @@ -147,16 +135,19 @@ namespace RBX }; public: - //BoundProp(BoundProp&); template BoundProp(const char* name, const char* category, PropType (Class::*member), Functionality flags) : TypedPropertyDescriptor(Class::classDescriptor(), name, category, std::auto_ptr(), flags) { getset.reset(new BoundPropGetSet(*this, member, NULL)); } - virtual ~BoundProp(); - public: - //BoundProp& operator=(BoundProp&); + + template + BoundProp(const char* name, const char* category, PropType (Class::*member), void (Class::*changed)(const PropertyDescriptor&), Functionality flags) + : TypedPropertyDescriptor(Class::classDescriptor(), name, category, std::auto_ptr(), flags) + { + getset.reset(new BoundPropGetSet(*this, member, changed)); + } }; // PropDescriptor @@ -299,8 +290,6 @@ namespace RBX private: std::auto_ptr::GetSet> getset; - public: - //RefPropDescriptor(RefPropDescriptor&); public: virtual bool isReadOnly() const; ReturnType* getValue(const DescribedBase*) const; @@ -311,6 +300,7 @@ namespace RBX virtual void readValue(DescribedBase*, const XmlElement*, IReferenceBinder&) const; virtual void writeValue(const DescribedBase*, XmlElement*) const; virtual void assignIDREF(DescribedBase*, const InstanceHandle&) const; + public: template RefPropDescriptor(char const* name, char const* category, typename GetFunction get, typename SetFunction set, Functionality flags) @@ -319,9 +309,6 @@ namespace RBX getset(PropDescriptor::getset(get, set)) { } - virtual ~RefPropDescriptor(); - public: - //RefPropDescriptor& operator=(RefPropDescriptor&); }; // EnumPropDescriptor diff --git a/Client/App/include/reflection/signal.h b/Client/App/include/reflection/signal.h index 96ea802d..029a81b8 100644 --- a/Client/App/include/reflection/signal.h +++ b/Client/App/include/reflection/signal.h @@ -13,17 +13,30 @@ namespace RBX { namespace Reflection { + typedef std::vector Arguments; + class GenericSlotWrapper { public: virtual ~GenericSlotWrapper(); - public: virtual void execute(const std::vector&) = 0; + public: - //GenericSlotWrapper(const GenericSlotWrapper&); - GenericSlotWrapper(); + template + static GenericSlotWrapper* create(T); + }; + + template + class TGenericSlotWrapper : public GenericSlotWrapper + { + private: + T slot; + + private: + TGenericSlotWrapper(const T&); + public: - //GenericSlotWrapper& operator=(const GenericSlotWrapper&); + virtual void execute(const Arguments&); }; class SignalSource; @@ -35,22 +48,25 @@ namespace RBX public: const SignalDescriptor& descriptor; - public: - //SignalInstance(const SignalInstance&); protected: SignalInstance(SignalSource* source, const SignalDescriptor& descriptor) : source(source), descriptor(descriptor) { } + public: virtual ~SignalInstance(); + public: SignalSource* getSource() { return source; } - //SignalInstance& operator=(const SignalInstance&); + + public: + template + boost::signals::connection connectGeneric(T slot, boost::signals::connect_position pos); }; class __declspec(novtable) SignalSource @@ -74,25 +90,23 @@ namespace RBX public: void (*signalCreatedHook)(SignalSource*); + protected: SignatureDescriptor signature; - public: - //SignalDescriptor(const SignalDescriptor&); protected: SignalDescriptor(ClassDescriptor& classDescriptor, const char* name); + protected: SignalInstance* findSignalInstance(const SignalSource* source) const; + private: virtual boost::signals::connection connectGeneric(SignalInstance*, GenericSlotWrapper*, boost::signals::connect_position) const = 0; virtual SignalInstance* newSignalInstance(SignalSource&) const = 0; + public: boost::shared_ptr getSignalInstance(SignalSource& source) const; const SignatureDescriptor& getSignature() const; - public: - virtual ~SignalDescriptor() {} - public: - //SignalDescriptor& operator=(const SignalDescriptor&); }; class Signal @@ -102,10 +116,11 @@ namespace RBX DescribedBase* instance; public: - //Signal(const Signal&); + Signal(const Signal&); Signal(const SignalDescriptor&, DescribedBase*); + public: - //Signal& operator=(const Signal&); // maybe? + Signal& operator=(const Signal&); const Name& getName() const; const SignalDescriptor* getDescriptor() const; boost::shared_ptr getSignalInstance() const; @@ -118,29 +133,25 @@ namespace RBX class TSignalInstance : public SignalInstance, public boost::signal { public: - //TSignalInstance(const TSignalInstance&); TSignalInstance(SignalSource* source, const SignalDescriptor& descriptor) : SignalInstance(source, descriptor), boost::signal() { } - virtual ~TSignalInstance() {} - public: - //TSignalInstance& operator=(const TSignalInstance&); }; - public: - //TSignalDesc(const TSignalDesc&); protected: TSignalDesc(ClassDescriptor& classDescriptor, const char* name) : SignalDescriptor(classDescriptor, name) { } + private: virtual SignalInstance* newSignalInstance(SignalSource& source) const { return new TSignalInstance(&source, *this); } + protected: TSignalInstance* findSig(const SignalSource* source) const { @@ -150,6 +161,7 @@ namespace RBX { return *(TSignalInstance*)(getSignalInstance(source).get()); } + public: boost::signals::connection connect(SignalSource* source, const boost::slot>& slot) { @@ -163,8 +175,6 @@ namespace RBX TSignalInstance* instance = findSig(source); return !instance || instance->empty(); } - virtual ~TSignalDesc() {} - //TSignalDesc& operator=(const TSignalDesc&); }; @@ -184,18 +194,12 @@ namespace RBX boost::shared_ptr wrapper; public: - //GenericSlotAdapter(const GenericSlotAdapter&); GenericSlotAdapter(GenericSlotWrapper*); + public: void operator()(); - public: - ~GenericSlotAdapter(); - public: - //GenericSlotAdapter& operator=(const GenericSlotAdapter&); }; - public: - //SignalDescImpl(const SignalDescImpl&); protected: SignalDescImpl(ClassDescriptor& classDescriptor, const char* name) : TSignalDesc(classDescriptor, name) @@ -212,11 +216,6 @@ namespace RBX protected: virtual boost::signals::connection connectGeneric(SignalInstance*, GenericSlotWrapper*, boost::signals::connect_position) const; - - public: - virtual ~SignalDescImpl() {} - public: - //SignalDescImpl& operator=(const SignalDescImpl&); }; template @@ -229,8 +228,8 @@ namespace RBX boost::shared_ptr wrapper; public: - //GenericSlotAdapter(const GenericSlotAdapter&); GenericSlotAdapter(GenericSlotWrapper*); + public: void operator()(typename FunctionTraits::Arg1Type arg1) { @@ -239,14 +238,8 @@ namespace RBX wrapper->execute(args); } - public: - ~GenericSlotAdapter(); - public: - //GenericSlotAdapter& operator=(const GenericSlotAdapter&); }; - public: - //SignalDescImpl(const SignalDescImpl&); protected: SignalDescImpl(ClassDescriptor& classDescriptor, const char* name) : TSignalDesc(classDescriptor, name) @@ -263,35 +256,24 @@ namespace RBX protected: virtual boost::signals::connection connectGeneric(SignalInstance*, GenericSlotWrapper*, boost::signals::connect_position) const; - - public: - virtual ~SignalDescImpl() {} - public: - //SignalDescImpl& operator=(const SignalDescImpl&); }; template class SignalDescImpl<2, CallbackSignature> : public TSignalDesc { - protected: + public: class GenericSlotAdapter { private: boost::shared_ptr wrapper; public: - //GenericSlotAdapter(const GenericSlotAdapter&); GenericSlotAdapter(GenericSlotWrapper*); + public: void operator()(typename FunctionTraits::Arg1Type arg1, typename FunctionTraits::Arg2Type arg2); - public: - ~GenericSlotAdapter(); - public: - //GenericSlotAdapter& operator=(const GenericSlotAdapter&); }; - public: - //SignalDescImpl(const SignalDescImpl&); protected: SignalDescImpl(ClassDescriptor& classDescriptor, const char* name) : TSignalDesc(classDescriptor, name) @@ -308,18 +290,12 @@ namespace RBX protected: virtual boost::signals::connection connectGeneric(SignalInstance*, GenericSlotWrapper*, boost::signals::connect_position) const; - - public: - virtual ~SignalDescImpl() {} - public: - //SignalDescImpl& operator=(const SignalDescImpl&); }; template class SignalDesc : public SignalDescImpl::ArgCount, CallbackSignature> { public: - //SignalDesc(const SignalDesc&); SignalDesc(const char* name, const char* arg1name, const char* arg2name) : SignalDescImpl(Class::classDescriptor(), name) { @@ -339,9 +315,6 @@ namespace RBX : SignalDescImpl(Class::classDescriptor(), name) { } - virtual ~SignalDesc() {} - public: - //SignalDesc& operator=(const SignalDesc&); }; } } diff --git a/Client/App/include/reflection/type.h b/Client/App/include/reflection/type.h index 18a4b09e..2f7c72da 100644 --- a/Client/App/include/reflection/type.h +++ b/Client/App/include/reflection/type.h @@ -2,12 +2,15 @@ #include #include #include +#include #include "reflection/descriptor.h" namespace RBX { namespace Reflection { + typedef std::vector ValueCollection; + class Type : public Descriptor { public: @@ -15,11 +18,15 @@ namespace RBX const Name& tag; public: - bool operator==(const Type&) const; - bool operator!=(const Type&) const; + bool operator==(const Type& other) const + { + return this == &other; + } + bool operator!=(const Type& other) const + { + return this != &other; + } - public: - //Type(const Type&); protected: Type(const char* name, const type_info& type, const char* tag) // TODO: check if matches (will only match in a /GS project) : Descriptor(name), @@ -33,8 +40,6 @@ namespace RBX tag(Name::lookup(name)) { } - public: - virtual ~Type() {} public: template @@ -43,17 +48,11 @@ namespace RBX class RefType : public Type { - public: - //RefType(const RefType&); private: RefType(const char* name, const type_info& type) : Type(name, type, "Ref") { } - public: - virtual ~RefType() {} - public: - //RefType& operator=(const RefType&); public: template @@ -71,38 +70,72 @@ namespace RBX boost::any value; public: - //Value(const Value&); // TODO: check ctor Value(); + // TODO: this is autogenerated template Value(typename ValueType& value) : _type(&Type::singleton()), value(value) { } + public: - Value& operator=(const Value& other) + const Type& type() const { - this->_type = other._type; - this->value = other.value; + return *_type; } - const Type& type() const; - bool isVoid() const; - public: - ~Value() {} + bool isVoid() const + { + // this is a guess + return isType(); + } + public: + template + T cast() const + { + return boost::any_cast(value); + } + + // not in resym but it might exist + template + T cast() + { + return boost::any_cast(value); + } + template T& convert(); + template + T& genericConvert(); + + template + T get() const; + + template + bool isType() const + { + return typeid(T) == type().type; + } + + template + Value& operator=(const T& rhs) + { + this->_type = &Type::singleton(); + this->value = rhs; + return *this; + } + + // TODO: replace all mentions with operator=? template void set(const T& value) { this->_type = &Type::singleton(); this->value = value; } - - // TODO: definitions for all the template functions }; class SignatureDescriptor @@ -115,6 +148,7 @@ namespace RBX const Type* type; const Value defaultValue; + // TODO: these are all autogenerated public: //template //Item(const char* name) @@ -134,7 +168,6 @@ namespace RBX { } ~Item() {} - //Item(const Item&); }; public: @@ -143,12 +176,10 @@ namespace RBX public: void addArgument(const Name& name, const Type& type, const Value& defaultValue); + public: - //SignatureDescriptor(const SignatureDescriptor&); SignatureDescriptor(); - ~SignatureDescriptor(); - public: - //SignatureDescriptor& operator=(const SignatureDescriptor&); + ~SignatureDescriptor(); // TODO: this is autogenerated }; } } diff --git a/Client/App/include/script/LuaArguments.h b/Client/App/include/script/LuaArguments.h new file mode 100644 index 00000000..6e6da5a4 --- /dev/null +++ b/Client/App/include/script/LuaArguments.h @@ -0,0 +1,239 @@ +#pragma once +#include "reflection/reflection.h" +#include "script/ThreadRef.h" +#include "script/LuaAtomicClasses.h" +#include "script/LuaInstanceBridge.h" +#include "lua.h" + +namespace RBX +{ + namespace Lua + { + class LuaArguments : public Reflection::FunctionDescriptor::Arguments + { + private: + const int offset; + lua_State* L; + + public: + LuaArguments(lua_State*, int); + virtual size_t size() const + { + // TODO: check match + return lua_gettop(L)-1; + } + virtual void get(int index, Reflection::Value& value) const + { + // TODO: check match + int pos = index + offset; + RBXASSERT(pos > 0); + get(L, pos, value); + } + int push(const Reflection::Value&) const; + int pushReturnValue() const; + + public: + // TODO: 97.00% + static void get(lua_State* L, int luaIndex, Reflection::Value& value) + { + // (018310) S_BPREL32: [FFFFFF80], Type: 0x11DC, n ; const int + // (018320) S_BPREL32: [FFFFFF84], Type: 0x928D, values ; *std::vector / *ValueCollection + + if (luaIndex <= lua_gettop(L)) + { + switch (lua_type(L, luaIndex)) + { + case LUA_TNUMBER: + { + float rhs = lua_tonumber(L, luaIndex); + value = rhs; + return; + } + + case LUA_TBOOLEAN: + { + bool rhs = lua_toboolean(L, luaIndex) != 0; + value = rhs; + return; + } + + case LUA_TSTRING: + { + const char* str = lua_tostring(L, luaIndex); + value = std::string(str); + return; + } + + case LUA_TTABLE: + { + const int n = static_cast(lua_objlen(L, luaIndex)); + value = Reflection::ValueCollection(n); + Reflection::ValueCollection& values = value.cast(); + + if (n >= 1) + { + int i = 1; + do + { + Reflection::Value& ival = values[i-1]; + lua_rawgeti(L, luaIndex, i); + LuaArguments::get(L, -1, ival); + lua_pop(L, 1); + i++; + } while (i <= n); + } + + return; + } + + case LUA_TNIL: + value = Reflection::Value(); + break; + + case LUA_TFUNCTION: + value = lua_tofunction(L, luaIndex); + return; + + case LUA_TUSERDATA: + if (CoordinateFrameBridge::getValue(L, luaIndex, value) + || Vector3Bridge::getValue(L, luaIndex, value) + || Color3Bridge::getValue(L, luaIndex, value) + || BrickColorBridge::getValue(L, luaIndex, value) + || ObjectBridge::getPtr(L, luaIndex, value)) + return; + + value = Reflection::Value(); + break; + + default: + value = Reflection::Value(); + break; + } + } + } + + static int push(const Reflection::Value& value, lua_State* const L) + { + if (value.isType()) + return 0; + + if (value.isType()) + { + lua_pushinteger(L, value.cast()); + return 1; + } + + if (value.isType()) + { + lua_pushboolean(L, value.cast()); + return 1; + } + + if (value.isType()) + { + lua_pushnumber(L, value.cast()); + return 1; + } + + if (value.isType()) + { + lua_pushnumber(L, value.cast()); + return 1; + } + + if (value.isType()) + { + lua_pushfunction(L, value.cast()); + return 1; + } + + if (value.isType()) + { + lua_pushstring(L, value.cast().c_str()); + return 1; + } + + if (value.isType()) + { + Vector3Bridge::pushVector3(L, value.cast()); + return 1; + } + + if (value.isType()) + { + CoordinateFrameBridge::pushCoordinateFrame(L, value.cast()); + return 1; + } + + if (value.isType()) + { + Color3Bridge::pushColor3(L, value.cast()); + return 1; + } + + if (value.isType()) + { + BrickColorBridge::pushNewObject(L, value.cast()); + return 1; + } + + if (value.isType()) + { + lua_pushstring(L, value.cast().c_str()); + return 1; + } + + if (value.isType>()) + { + ObjectBridge::push(L, value.cast&>()); + return 1; + } + + if (value.isType>()) + { + ObjectBridge::push(L, value.cast&>()); + return 1; + } + + if (value.isType()) + { + const Reflection::ValueCollection& collection = value.cast(); + return pushTable(collection.begin(), collection.end(), L); + } + + if (value.isType>()) + { + boost::shared_ptr values = value.cast>(); + + if (values) + { + return pushTable(values->begin(), values->end(), L); + } + else + { + lua_newtable(L); + return 1; + } + } + + return 0; + } + + public: + template + static int pushTable(T _First, T _Last, lua_State* const L) + { + lua_createtable(L, _Last-_First, 0); + + int i = 0; + for (; _First != _Last; _First++) + { + push(*_First, L); + lua_rawseti(L, -2, ++i); + } + + return 1; + } + }; + } +} diff --git a/Client/App/include/script/LuaAtomicClasses.h b/Client/App/include/script/LuaAtomicClasses.h new file mode 100644 index 00000000..d455e610 --- /dev/null +++ b/Client/App/include/script/LuaAtomicClasses.h @@ -0,0 +1,205 @@ +#pragma once +#include "v8datamodel/BrickColor.h" +#include "lua/LuaBridge.h" +#include "G3D/CoordinateFrame.h" +#include "G3D/Vector3.h" +#include "G3D/Color3.h" +#include "lauxlib.h" + +namespace RBX +{ + namespace Lua + { + class CoordinateFrameBridge : public Bridge + { + friend class Bridge; + + private: + static const luaL_Reg classLibrary[4]; + + public: + static void registerClassLibrary(lua_State* L) + { + luaL_register(L, className, classLibrary); + lua_pop(L, 1); + } + static void pushCoordinateFrame(lua_State* L, G3D::CoordinateFrame CF) + { + pushNewObject(L, CF); + } + + private: + static int newCoordinateFrame(lua_State* L); + static int fromEulerAnglesXYZ(lua_State* L); + static int fromAxisAngle(lua_State* L); + static int on_add(lua_State* L); + static int on_sub(lua_State* L); + static int on_mul(lua_State* L); + static int on_inverse(lua_State* L); + static int on_toWorldSpace(lua_State* L); + static int on_toObjectSpace(lua_State* L); + static int on_pointToWorldSpace(lua_State* L); + static int on_pointToObjectSpace(lua_State* L); + static int on_vectorToWorldSpace(lua_State* L); + static int on_vectorToObjectSpace(lua_State* L); + static int on_toEulerAnglesXYZ(lua_State* L); + static int on_components(lua_State* L); + }; + + class Vector3Bridge : public Bridge + { + friend class Bridge; + + private: + static const luaL_Reg classLibrary[2]; + + public: + static void registerClassLibrary(lua_State* L) + { + luaL_register(L, className, classLibrary); + lua_pop(L, 1); + } + static void pushVector3(lua_State* L, G3D::Vector3 color) + { + pushNewObject(L, color); + } + + private: + static int newVector3(lua_State* L); + static int on_add(lua_State* L); + static int on_sub(lua_State* L); + static int on_mul(lua_State* L); + static int on_div(lua_State* L); + static int on_unm(lua_State* L); + }; + + class Color3Bridge : public Bridge + { + private: + static const luaL_Reg classLibrary[2]; + + public: + static void registerClassLibrary(lua_State* L) + { + luaL_register(L, className, classLibrary); + lua_pop(L, 1); + } + static void pushColor3(lua_State* L, G3D::Color3 color) + { + pushNewObject(L, color); + } + + private: + static int newColor3(lua_State* L); + }; + + class BrickColorBridge : public Bridge + { + private: + static const luaL_Reg classLibrary[13]; + + public: + static void registerClassLibrary(lua_State* L) + { + luaL_register(L, className, classLibrary); + lua_pop(L, 1); + } + + private: + static int newBrickColor(lua_State* L); + static int randomBrickColor(lua_State* L); + }; + + template<> + void Vector3Bridge::registerClass(lua_State *L) + { + luaL_newmetatable(L, className); + + lua_pushstring(L, "__index"); + lua_pushcfunction(L, on_index); + lua_settable(L, -3); + + lua_pushstring(L, "__newindex"); + lua_pushcfunction(L, on_newindex); + lua_settable(L, -3); + + lua_pushstring(L, "__gc"); + lua_pushcfunction(L, on_gc); + lua_settable(L, -3); + + lua_pushstring(L, "__eq"); + lua_pushcfunction(L, on_eq); + lua_settable(L, -3); + + lua_pushstring(L, "__tostring"); + lua_pushcfunction(L, on_tostring); + lua_settable(L, -3); + + lua_pushstring(L, "__add"); + lua_pushcfunction(L, Vector3Bridge::on_add); + lua_settable(L, -3); + + lua_pushstring(L, "__sub"); + lua_pushcfunction(L, Vector3Bridge::on_sub); + lua_settable(L, -3); + + lua_pushstring(L, "__mul"); + lua_pushcfunction(L, Vector3Bridge::on_mul); + lua_settable(L, -3); + + lua_pushstring(L, "__div"); + lua_pushcfunction(L, Vector3Bridge::on_div); + lua_settable(L, -3); + + lua_pushstring(L, "__unm"); + lua_pushcfunction(L, Vector3Bridge::on_unm); + lua_settable(L, -3); + + lua_pop(L, 1); + } + + template<> + void CoordinateFrameBridge::registerClass(lua_State *L) + { + luaL_newmetatable(L, className); + + lua_pushstring(L, "__index"); + lua_pushcfunction(L, on_index); + lua_settable(L, -3); + + lua_pushstring(L, "__newindex"); + lua_pushcfunction(L, on_newindex); + lua_settable(L, -3); + + lua_pushstring(L, "__gc"); + lua_pushcfunction(L, on_gc); + lua_settable(L, -3); + + lua_pushstring(L, "__eq"); + lua_pushcfunction(L, on_eq); + lua_settable(L, -3); + + lua_pushstring(L, "__tostring"); + lua_pushcfunction(L, on_tostring); + lua_settable(L, -3); + + lua_pushstring(L, "__add"); + lua_pushcfunction(L, CoordinateFrameBridge::on_add); + lua_settable(L, -3); + + lua_pushstring(L, "__sub"); + lua_pushcfunction(L, CoordinateFrameBridge::on_sub); + lua_settable(L, -3); + + lua_pushstring(L, "__mul"); + lua_pushcfunction(L, CoordinateFrameBridge::on_mul); + lua_settable(L, -3); + + lua_pushstring(L, "inverse"); + lua_pushcfunction(L, CoordinateFrameBridge::on_inverse); + lua_settable(L, -3); + + lua_pop(L, 1); + } + } +} diff --git a/Client/App/include/script/LuaInstanceBridge.h b/Client/App/include/script/LuaInstanceBridge.h new file mode 100644 index 00000000..8b0be79d --- /dev/null +++ b/Client/App/include/script/LuaInstanceBridge.h @@ -0,0 +1,54 @@ +#pragma once +#include "lua/LuaBridge.h" +#include "reflection/reflection.h" +#include "v8tree/Instance.h" +#include "lua.h" +#include "lauxlib.h" +#include "G3D/format.h" + +namespace RBX +{ + namespace Lua + { + void newweaktable(lua_State* L, const char* mode); + + template <> + int SharedPtrBridge::on_tostring(const boost::shared_ptr& object, lua_State* L) + { + Instance* instance = dynamic_cast(object.get()); + + if (instance) + lua_pushstring(L, instance->getName().c_str()); + else + lua_pushstring(L, object->classDescriptor().name.c_str()); + + return 1; + } + + class ObjectBridge : public SharedPtrBridge + { + private: + static const luaL_Reg classLibrary[2]; + + public: + static int callMemberFunction(lua_State* L); + static void registerInstanceClassLibrary(lua_State* L) + { + luaL_register(L, "Instance", classLibrary); + lua_pop(L, 1); + } + static int newInstance(lua_State* thread); + // TODO: 98.30% (functional match) + static boost::shared_ptr getInstance(lua_State* L, size_t index) + { + boost::shared_ptr object = getPtr(L, index); + Reflection::DescribedBase* object2 = object.get(); + + if (object2 && !dynamic_cast(object2)) + throw std::runtime_error(G3D::format("Object %s is not an Instance", object->classDescriptor().name.c_str())); + + return shared_from(static_cast(object2)); + } + }; + } +} diff --git a/Client/App/include/script/LuaMemory.h b/Client/App/include/script/LuaMemory.h new file mode 100644 index 00000000..b9bbc742 --- /dev/null +++ b/Client/App/include/script/LuaMemory.h @@ -0,0 +1,20 @@ +#pragma once + +class LuaAllocator +{ +private: + size_t heapSize; + size_t heapCount; + size_t maxHeapSize; + size_t maxHeapCount; + +public: + LuaAllocator(); + void clearHeapMax(); + void getHeapStats(size_t&, size_t&) const; + void getHeapStats(size_t& heapSize, size_t& heapCount, size_t& maxHeapSize, size_t& maxHeapCount) const; + void* alloc(void* ptr, size_t osize, size_t nsize); + +public: + static void* alloc(void* ud, void* ptr, size_t osize, size_t nsize); +}; diff --git a/Client/App/include/script/LuaSignalBridge.h b/Client/App/include/script/LuaSignalBridge.h new file mode 100644 index 00000000..94e7c8a4 --- /dev/null +++ b/Client/App/include/script/LuaSignalBridge.h @@ -0,0 +1,67 @@ +#pragma once +#include "lua/LuaBridge.h" +#include "script/Script.h" +#include "script/ScriptContext.h" +#include "script/ThreadRef.h" +#include "reflection/reflection.h" +#include "boost/signals.hpp" + +namespace RBX +{ + namespace Lua + { + template<> + int SharedPtrBridge::on_tostring(const boost::shared_ptr& object, lua_State* L) + { + std::string name = "Signal "; + name += object->descriptor.name.name; + lua_pushstring(L, name.c_str()); + return 1; + } + + class SignalBridge : public SharedPtrBridge + { + public: + static int connect(lua_State* L); + static int wait(lua_State* L); + }; + + class SignalConnectionBridge : public Bridge + { + // hmm + friend class Bridge; + + private: + static int disconnect(lua_State* L); + }; + + template<> + int SignalConnectionBridge::on_tostring(const boost::signals::connection& object, lua_State* L) + { + lua_pushstring(L, "Connection"); + return 1; + } + } +} + +class FunctionScriptSlot : public RBX::Script::Slot +{ +private: + RBX::ScriptContext& context; + RBX::Lua::FunctionRef function; + RBX::Lua::ThreadRef cachedSlotThread; + +public: + FunctionScriptSlot(lua_State* thread, int functionIndex); + void operator()(const RBX::Reflection::Arguments&); +}; + +class WaitScriptSlot : public RBX::Script::Slot +{ +private: + RBX::Lua::ThreadRef waitThread; + +public: + WaitScriptSlot(lua_State* thread); + void operator()(const RBX::Reflection::Arguments&); +}; diff --git a/Client/App/include/script/Script.h b/Client/App/include/script/Script.h index 298f1e49..0f7c4a39 100644 --- a/Client/App/include/script/Script.h +++ b/Client/App/include/script/Script.h @@ -1,29 +1,90 @@ #pragma once +#include "script/ScriptContext.h" +#include "v8tree/Instance.h" #include "util/Debug.h" +#include "boost/shared_ptr.hpp" +#include "boost/signals.hpp" namespace RBX { - class Script; class ScriptContext; - class IScriptOwner + extern const char* sScript; + class Script : public DescribedCreatable { - protected: - virtual IScriptOwner* scriptShouldRun(Script* script) = 0; - virtual void runScript(Script* script, ScriptContext* context) + public: + class Slot { - RBXASSERT(0); + public: + boost::shared_ptr cnction; + + protected: + Slot() + : cnction(new boost::signals::connection()) + { + } + }; + + private: + boost::shared_ptr embeddedSource; + ContentId scriptId; + bool disabled; + class IScriptOwner* owner; + + public: + static Reflection::BoundProp prop_Disabled; + static const Reflection::PropDescriptor prop_EmbeddedSourceCode; + static const Reflection::PropDescriptor prop_SourceCodeId; + + public: + Script(const Script&); + Script(); + virtual ~Script(); + + bool isDisabled() const + { + return disabled; } - virtual void releaseScript(Script* script) + + virtual bool askSetParent(const Instance*) const; + bool isCodeEmbedded() const; + boost::shared_ptr requestCode(); + + void setEmbeddedCode(const std::string& value); + const std::string& getEmbeddedCode() const { - RBXASSERT(0); + return *embeddedSource.get(); } - public: - //IScriptOwner(const IScriptOwner&); - IScriptOwner() + + const ContentId& getScriptId() const { + return scriptId; } + void setScriptId(const ContentId& value); + + protected: + virtual void onServiceProvider(const ServiceProvider* oldProvider, const ServiceProvider* newProvider); + virtual void onAncestorChanged(const AncestorChanged& event); + }; + + extern const char* sLocalScript; + class LocalScript : public DescribedCreatable + { + public: + LocalScript(); + virtual ~LocalScript(); + }; + + class IScriptOwner + { + friend class Script; + + protected: + virtual IScriptOwner* scriptShouldRun(Script* script); + virtual void runScript(Script* script, ScriptContext* context); + virtual void releaseScript(Script* script); + public: - //IScriptOwner& operator=(const IScriptOwner&); + IScriptOwner(); }; } diff --git a/Client/App/include/script/ScriptContext.h b/Client/App/include/script/ScriptContext.h new file mode 100644 index 00000000..ef37fc60 --- /dev/null +++ b/Client/App/include/script/ScriptContext.h @@ -0,0 +1,149 @@ +#pragma once +#include "script/Script.h" +#include "script/ScriptEvent.h" +#include "script/LuaMemory.h" +#include "script/LuaArguments.h" +#include "script/ThreadRef.h" +#include "v8tree/Instance.h" +#include "v8tree/Service.h" +#include "v8datamodel/Stats.h" +#include "util/Events.h" +#include "util/RunStateOwner.h" +#include "boost/shared_ptr.hpp" +#include "boost/date_time.hpp" +#include "lua.h" + +// TODO: where do these numbers actually come from? i don't think +// they were actually defined like this +#define RBX_LUA_GLOBAL_SCRIPTCONTEXT (void*)0x43 // 'C' +#define RBX_LUA_GLOBAL_THREADREFNODE (void*)0x4E // 'N' +#define RBX_LUA_GLOBAL_IDENTITY (void*)0x54 // 'T' + +namespace RBX +{ + class Script; + + namespace Lua + { + class YieldingThreads; + } + + // TODO: remove when appropriate + namespace Security + { + enum Identities + { + Anonymous, + LocalGUI, + GameScript, + CmdLine, + TrustedCOM, + TrustedWebService, + Replicator + }; + } + + extern const char *sScriptContext; + class ScriptContext : public DescribedCreatable, + public Service, + public Listener, + public Listener + { + public: + typedef boost::function1 PushArgumentsClosure; + typedef boost::function2 ReadResultsClosure; + + public: + enum Result + { + Success, + Yield, + Error + }; + + // TODO: come back to this when luasoft gets his stuff done + public: + class ScriptImpersonator// : public Security::Impersonator + { + public: + ScriptImpersonator(lua_State*); + ~ScriptImpersonator(); + }; + + private: + lua_State* globalState; + Lua::ThreadRef commandLineSandbox; + std::set scripts; + boost::posix_time::ptime nextPendingScripts; + std::vector> pendingScripts; + boost::shared_ptr runService; + boost::scoped_ptr yieldEvent; + bool scriptsDisabled; + boost::shared_ptr statsItem; + + public: + boost::scoped_ptr allocator; + static Reflection::BoundProp propScriptsDisabled; + + public: + ScriptContext(); + virtual ~ScriptContext(); + + std::auto_ptr call(const Lua::FunctionRef&, const Reflection::ValueCollection&); + void call(const Lua::FunctionRef&); + void call(const Lua::FunctionRef&, PushArgumentsClosure, ReadResultsClosure); + std::auto_ptr executeInNewThread(Security::Identities, const char*, const char*, const Reflection::ValueCollection&); + void executeInNewThread(Security::Identities, const char*, const char*); + void executeInNewThread(Security::Identities, const char*, const char*, PushArgumentsClosure pushArguments, ReadResultsClosure readResults); + Result resume(lua_State* thread, int narg); + void resume(lua_State* thread, PushArgumentsClosure pushArguments, ReadResultsClosure readResults); + void gc() + { + if (globalState) + lua_gc(globalState, LUA_GCCOLLECT, 0); + } + size_t getThreadCount() const; + bool hasState() const; + lua_State* state(); + virtual XmlElement* write(); + + protected: + virtual void onServiceProvider(const ServiceProvider* oldProvider, const ServiceProvider* newProvider); + virtual void onEvent(const RunService* source, Heartbeat event); + virtual void onEvent(const RunService* source, RunTransition event); + + private: + void onChangedScriptEnabled(const Reflection::PropertyDescriptor& __formal); + + public: + void closeState(); + void addScript(Script* script); + void removeScript(Script* script); + + private: + void disassociateState(Script* script); + void openState(); + void startScript(boost::shared_ptr