From 6aa8b779f06c178eba6d9e5022952578ef7b084c Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 19 Dec 2013 20:16:18 +0800 Subject: [PATCH 1/3] Updates submodule reference of Bindings-generator, it supports to bind std::vector ,std::vector, cocos2d::Map now. --- tools/bindings-generator | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bindings-generator b/tools/bindings-generator index a8e5123121..f0b6cc8dd3 160000 --- a/tools/bindings-generator +++ b/tools/bindings-generator @@ -1 +1 @@ -Subproject commit a8e5123121a4c537bfa9e79f7adb981c17b18e6e +Subproject commit f0b6cc8dd3d375f0999ec4e49dd90dbe1938c460 From f73e939b5794929e49e9cb49ae4888acbba095ef Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 19 Dec 2013 20:17:44 +0800 Subject: [PATCH 2/3] Supports to bind more container: std::vector, std::vector, cocos2d::Map. --- .../javascript/bindings/ScriptingCore.cpp | 54 ------- .../javascript/bindings/ScriptingCore.h | 51 ------- .../bindings/js_manual_conversions.cpp | 144 ++++++++++++++++++ .../bindings/js_manual_conversions.h | 121 ++++++++++++++- .../lua/bindings/LuaBasicConversions.cpp | 11 ++ .../lua/bindings/LuaBasicConversions.h | 17 +++ tools/tojs/cocos2dx_studio.ini | 2 +- tools/tolua/cocos2dx_studio.ini | 2 +- 8 files changed, 294 insertions(+), 108 deletions(-) diff --git a/cocos/scripting/javascript/bindings/ScriptingCore.cpp b/cocos/scripting/javascript/bindings/ScriptingCore.cpp index a859a1ed8e..076c2c2107 100644 --- a/cocos/scripting/javascript/bindings/ScriptingCore.cpp +++ b/cocos/scripting/javascript/bindings/ScriptingCore.cpp @@ -1504,58 +1504,4 @@ void jsb_remove_proxy(js_proxy_t* nativeProxy, js_proxy_t* jsProxy) JS_REMOVE_PROXY(nativeProxy, jsProxy); } -// JSStringWrapper -JSStringWrapper::JSStringWrapper() -: _buffer(nullptr) -{ -} - -JSStringWrapper::JSStringWrapper(JSString* str, JSContext* cx/* = NULL*/) -: _buffer(nullptr) -{ - set(str, cx); -} - -JSStringWrapper::JSStringWrapper(jsval val, JSContext* cx/* = NULL*/) -: _buffer(nullptr) -{ - set(val, cx); -} - -JSStringWrapper::~JSStringWrapper() -{ - CC_SAFE_DELETE_ARRAY(_buffer); -} - -void JSStringWrapper::set(jsval val, JSContext* cx) -{ - if (val.isString()) - { - this->set(val.toString(), cx); - } - else - { - CC_SAFE_DELETE_ARRAY(_buffer); - } -} - -void JSStringWrapper::set(JSString* str, JSContext* cx) -{ - CC_SAFE_DELETE_ARRAY(_buffer); - - if (!cx) - { - cx = ScriptingCore::getInstance()->getGlobalContext(); - } - // JS_EncodeString isn't supported in SpiderMonkey ff19.0. - //buffer = JS_EncodeString(cx, string); - unsigned short* pStrUTF16 = (unsigned short*)JS_GetStringCharsZ(cx, str); - - _buffer = cc_utf16_to_utf8(pStrUTF16, -1, NULL, NULL); -} - -const char* JSStringWrapper::get() -{ - return _buffer ? _buffer : ""; -} diff --git a/cocos/scripting/javascript/bindings/ScriptingCore.h b/cocos/scripting/javascript/bindings/ScriptingCore.h index b0c6c45acb..f393824a02 100644 --- a/cocos/scripting/javascript/bindings/ScriptingCore.h +++ b/cocos/scripting/javascript/bindings/ScriptingCore.h @@ -207,57 +207,6 @@ public: JSObject* NewGlobalObject(JSContext* cx, bool debug = false); -// just a simple utility to avoid mem leaking when using JSString -class JSStringWrapper -{ -public: - JSStringWrapper(); - JSStringWrapper(JSString* str, JSContext* cx = NULL); - JSStringWrapper(jsval val, JSContext* cx = NULL); - ~JSStringWrapper(); - - void set(jsval val, JSContext* cx); - void set(JSString* str, JSContext* cx); - const char* get(); - -private: - const char* _buffer; - - /* Copy and assignment are not supported. */ - JSStringWrapper(const JSStringWrapper &another); - JSStringWrapper &operator=(const JSStringWrapper &another); -}; - -// wraps a function and "this" object -class JSFunctionWrapper -{ - JSContext *_cx; - JSObject *_jsthis; - jsval _fval; -public: - JSFunctionWrapper(JSContext* cx, JSObject *jsthis, jsval fval) - : _cx(cx) - , _jsthis(jsthis) - , _fval(fval) - { - JS_AddNamedValueRoot(cx, &this->_fval, "JSFunctionWrapper"); - JS_AddNamedObjectRoot(cx, &this->_jsthis, "JSFunctionWrapper"); - } - ~JSFunctionWrapper() { - JS_RemoveValueRoot(this->_cx, &this->_fval); - JS_RemoveObjectRoot(this->_cx, &this->_jsthis); - } - JSBool invoke(unsigned int argc, jsval *argv, jsval &rval) { - JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET - - return JS_CallFunctionValue(this->_cx, this->_jsthis, this->_fval, argc, argv, &rval); - } -private: - /* Copy and assignment are not supported. */ - JSFunctionWrapper(const JSFunctionWrapper &another); - JSFunctionWrapper &operator=(const JSFunctionWrapper &another); -}; - JSBool jsb_set_reserved_slot(JSObject *obj, uint32_t idx, jsval value); JSBool jsb_get_reserved_slot(JSObject *obj, uint32_t idx, jsval& ret); diff --git a/cocos/scripting/javascript/bindings/js_manual_conversions.cpp b/cocos/scripting/javascript/bindings/js_manual_conversions.cpp index 382a89ae89..5ac6c5cf8d 100644 --- a/cocos/scripting/javascript/bindings/js_manual_conversions.cpp +++ b/cocos/scripting/javascript/bindings/js_manual_conversions.cpp @@ -12,6 +12,84 @@ USING_NS_CC; +// JSStringWrapper +JSStringWrapper::JSStringWrapper() +: _buffer(nullptr) +{ +} + +JSStringWrapper::JSStringWrapper(JSString* str, JSContext* cx/* = NULL*/) +: _buffer(nullptr) +{ + set(str, cx); +} + +JSStringWrapper::JSStringWrapper(jsval val, JSContext* cx/* = NULL*/) +: _buffer(nullptr) +{ + set(val, cx); +} + +JSStringWrapper::~JSStringWrapper() +{ + CC_SAFE_DELETE_ARRAY(_buffer); +} + +void JSStringWrapper::set(jsval val, JSContext* cx) +{ + if (val.isString()) + { + this->set(val.toString(), cx); + } + else + { + CC_SAFE_DELETE_ARRAY(_buffer); + } +} + +void JSStringWrapper::set(JSString* str, JSContext* cx) +{ + CC_SAFE_DELETE_ARRAY(_buffer); + + if (!cx) + { + cx = ScriptingCore::getInstance()->getGlobalContext(); + } + // JS_EncodeString isn't supported in SpiderMonkey ff19.0. + //buffer = JS_EncodeString(cx, string); + unsigned short* pStrUTF16 = (unsigned short*)JS_GetStringCharsZ(cx, str); + + _buffer = cc_utf16_to_utf8(pStrUTF16, -1, NULL, NULL); +} + +const char* JSStringWrapper::get() +{ + return _buffer ? _buffer : ""; +} + +// JSFunctionWrapper +JSFunctionWrapper::JSFunctionWrapper(JSContext* cx, JSObject *jsthis, jsval fval) +: _cx(cx) +, _jsthis(jsthis) +, _fval(fval) +{ + JS_AddNamedValueRoot(cx, &this->_fval, "JSFunctionWrapper"); + JS_AddNamedObjectRoot(cx, &this->_jsthis, "JSFunctionWrapper"); +} + +JSFunctionWrapper::~JSFunctionWrapper() +{ + JS_RemoveValueRoot(this->_cx, &this->_fval); + JS_RemoveObjectRoot(this->_cx, &this->_jsthis); +} + +JSBool JSFunctionWrapper::invoke(unsigned int argc, jsval *argv, jsval &rval) +{ + JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET + + return JS_CallFunctionValue(this->_cx, this->_jsthis, this->_fval, argc, argv, &rval); +} + static Color3B getColorFromJSObject(JSContext *cx, JSObject *colorObject) { JS::RootedValue jsr(cx); @@ -1124,6 +1202,72 @@ JSBool jsval_to_ssize( JSContext *cx, jsval vp, ssize_t* ret) return jsval_to_long(cx, vp, reinterpret_cast(ret)); } +JSBool jsval_to_std_vector_string( JSContext *cx, jsval vp, std::vector* ret) +{ + JSObject *jsobj; + JSBool ok = vp.isObject() && JS_ValueToObject( cx, vp, &jsobj ); + JSB_PRECONDITION3( ok, cx, JS_FALSE, "Error converting value to object"); + JSB_PRECONDITION3( jsobj && JS_IsArrayObject( cx, jsobj), cx, JS_FALSE, "Object must be an array"); + + uint32_t len = 0; + JS_GetArrayLength(cx, jsobj, &len); + + for (uint32_t i=0; i < len; i++) + { + jsval value; + if (JS_GetElement(cx, jsobj, i, &value)) + { + if (JSVAL_IS_STRING(value)) + { + JSStringWrapper valueWapper(JSVAL_TO_STRING(value), cx); + ret->push_back(valueWapper.get()); + } + else + { + JS_ReportError(cx, "not supported type in array"); + return JS_FALSE; + } + } + } + + return JS_TRUE; +} + +JSBool jsval_to_std_vector_int( JSContext *cx, jsval vp, std::vector* ret) +{ + JSObject *jsobj; + JSBool ok = vp.isObject() && JS_ValueToObject( cx, vp, &jsobj ); + JSB_PRECONDITION3( ok, cx, JS_FALSE, "Error converting value to object"); + JSB_PRECONDITION3( jsobj && JS_IsArrayObject( cx, jsobj), cx, JS_FALSE, "Object must be an array"); + + uint32_t len = 0; + JS_GetArrayLength(cx, jsobj, &len); + + for (uint32_t i=0; i < len; i++) + { + jsval value; + if (JS_GetElement(cx, jsobj, i, &value)) + { + if (JSVAL_IS_NUMBER(value)) + { + double number = 0.0; + JSBool ok = JS_ValueToNumber(cx, value, &number); + if (ok) + { + ret->push_back(static_cast(number)); + } + } + else + { + JS_ReportError(cx, "not supported type in array"); + return JS_FALSE; + } + } + } + + return JS_TRUE; +} + // native --> jsval jsval ccarray_to_jsval(JSContext* cx, Array *arr) diff --git a/cocos/scripting/javascript/bindings/js_manual_conversions.h b/cocos/scripting/javascript/bindings/js_manual_conversions.h index 8629121d4c..ec6da697a6 100644 --- a/cocos/scripting/javascript/bindings/js_manual_conversions.h +++ b/cocos/scripting/javascript/bindings/js_manual_conversions.h @@ -7,9 +7,46 @@ #include "jsapi.h" #include "js_bindings_core.h" +#include "js_bindings_config.h" #include "cocos2d.h" #include "spidermonkey_specifics.h" - + +// just a simple utility to avoid mem leaking when using JSString +class JSStringWrapper +{ +public: + JSStringWrapper(); + JSStringWrapper(JSString* str, JSContext* cx = NULL); + JSStringWrapper(jsval val, JSContext* cx = NULL); + ~JSStringWrapper(); + + void set(jsval val, JSContext* cx); + void set(JSString* str, JSContext* cx); + const char* get(); + +private: + const char* _buffer; + +private: + CC_DISALLOW_COPY_AND_ASSIGN(JSStringWrapper); +}; + +// wraps a function and "this" object +class JSFunctionWrapper +{ +public: + JSFunctionWrapper(JSContext* cx, JSObject *jsthis, jsval fval); + ~JSFunctionWrapper(); + + JSBool invoke(unsigned int argc, jsval *argv, jsval &rval); +private: + JSContext *_cx; + JSObject *_jsthis; + jsval _fval; +private: + CC_DISALLOW_COPY_AND_ASSIGN(JSFunctionWrapper); +}; + JSBool jsval_to_opaque( JSContext *cx, jsval vp, void **out ); JSBool jsval_to_int( JSContext *cx, jsval vp, int *out); JSBool jsval_to_uint( JSContext *cx, jsval vp, unsigned int *out); @@ -115,6 +152,62 @@ JSBool jsval_to_ccvaluemap(JSContext* cx, jsval v, cocos2d::ValueMap* ret); JSBool jsval_to_ccintvaluemap(JSContext* cx, jsval v, cocos2d::IntValueMap* ret); JSBool jsval_to_ccvaluevector(JSContext* cx, jsval v, cocos2d::ValueVector* ret); JSBool jsval_to_ssize( JSContext *cx, jsval vp, ssize_t* ret); +JSBool jsval_to_std_vector_string( JSContext *cx, jsval vp, std::vector* ret); +JSBool jsval_to_std_vector_int( JSContext *cx, jsval vp, std::vector* ret); + +template +JSBool jsval_to_ccmap_string_key(JSContext *cx, jsval v, cocos2d::Map* ret) +{ + if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) + { + return JS_TRUE; + } + + JSObject* tmp = JSVAL_TO_OBJECT(v); + if (!tmp) { + CCLOG("%s", "jsval_to_ccvaluemap: the jsval is not an object."); + return JS_FALSE; + } + + JSObject* it = JS_NewPropertyIterator(cx, tmp); + + while (true) + { + jsid idp; + jsval key; + if (! JS_NextProperty(cx, it, &idp) || ! JS_IdToValue(cx, idp, &key)) { + return JS_FALSE; // error + } + + if (key == JSVAL_VOID) { + break; // end of iteration + } + + if (!JSVAL_IS_STRING(key)) { + continue; // ignore integer properties + } + + JSStringWrapper keyWrapper(JSVAL_TO_STRING(key), cx); + + JS::RootedValue value(cx); + JS_GetPropertyById(cx, tmp, idp, &value); + if (value.isObject()) + { + js_proxy_t *proxy = nullptr; + JSObject* jsobj = JSVAL_TO_OBJECT(value); + proxy = jsb_get_js_proxy(jsobj); + CCASSERT(proxy, "Native object should be added!"); + T cobj = (T)(proxy ? proxy->ptr : nullptr); + ret->insert(keyWrapper.get(), cobj); + } + else + { + CCASSERT(false, "not supported type"); + } + } + + return JS_TRUE; +} // from native jsval int32_to_jsval( JSContext *cx, int32_t l); @@ -171,6 +264,32 @@ jsval ccvector_to_jsval(JSContext* cx, const cocos2d::Vector& v) return OBJECT_TO_JSVAL(jsretArr); } +template +jsval ccmap_string_key_to_jsval(JSContext* cx, const cocos2d::Map& v) +{ + JSObject* jsRet = JS_NewObject(cx, NULL, NULL, NULL); + + for (auto iter = v.begin(); iter != v.end(); ++iter) + { + JS::RootedValue element(cx); + + std::string key = iter->first; + T obj = iter->second; + + //First, check whether object is associated with js object. + js_proxy_t* jsproxy = js_get_or_create_proxy(cx, obj); + if (jsproxy) { + element = OBJECT_TO_JSVAL(jsproxy->obj); + } + + if (!key.empty()) + { + JS_SetProperty(cx, jsRet, key.c_str(), element); + } + } + return OBJECT_TO_JSVAL(jsRet); +} + jsval ccvalue_to_jsval(JSContext* cx, const cocos2d::Value& v); jsval ccvaluemap_to_jsval(JSContext* cx, const cocos2d::ValueMap& v); jsval ccintvaluemap_to_jsval(JSContext* cx, const cocos2d::IntValueMap& v); diff --git a/cocos/scripting/lua/bindings/LuaBasicConversions.cpp b/cocos/scripting/lua/bindings/LuaBasicConversions.cpp index 3d7dd6cae6..65295cf132 100644 --- a/cocos/scripting/lua/bindings/LuaBasicConversions.cpp +++ b/cocos/scripting/lua/bindings/LuaBasicConversions.cpp @@ -1423,6 +1423,17 @@ bool luaval_to_ccvaluevector(lua_State* L, int lo, cocos2d::ValueVector* ret) return ok; } +bool luaval_to_std_vector_string(lua_State* L, int lo, std::vector* ret) +{ + // TO BE DONE IN CPP FILE + return false; +} + +bool luaval_to_std_vector_int(lua_State* L, int lo, std::vector* ret) +{ + // TO BE DONE IN CPP FILE + return false; +} void point_to_luaval(lua_State* L,const Point& pt) { diff --git a/cocos/scripting/lua/bindings/LuaBasicConversions.h b/cocos/scripting/lua/bindings/LuaBasicConversions.h index 2ed5f9de9f..cfaf555ae7 100644 --- a/cocos/scripting/lua/bindings/LuaBasicConversions.h +++ b/cocos/scripting/lua/bindings/LuaBasicConversions.h @@ -114,6 +114,17 @@ bool luaval_to_ccvector(lua_State* L, int lo , cocos2d::Vector* ret) return ok; } +bool luaval_to_std_vector_string(lua_State* L, int lo, std::vector* ret); +bool luaval_to_std_vector_int(lua_State* L, int lo, std::vector* ret); + +template +bool luaval_to_ccmap_string_key(lua_State* L, int lo, cocos2d::Map* ret) +{ + // TO BE DONE: + return false; +} + + extern bool luaval_to_ccvalue(lua_State* L, int lo, cocos2d::Value* ret); extern bool luaval_to_ccvaluemap(lua_State* L, int lo, cocos2d::ValueMap* ret); extern bool luaval_to_ccintvaluemap(lua_State* L, int lo, cocos2d::IntValueMap* ret); @@ -165,6 +176,12 @@ void ccvector_to_luaval(lua_State* L,const cocos2d::Vector& inValue) } } +template +void ccmap_string_key_to_luaval(lua_State* L, const cocos2d::Map& v) +{ + // TO BE DONE: +} + void ccvalue_to_luaval(lua_State* L,const cocos2d::Value& inValue); void ccvaluemap_to_luaval(lua_State* L,const cocos2d::ValueMap& inValue); void ccintvaluemap_to_luaval(lua_State* L, const cocos2d::IntValueMap& inValue); diff --git a/tools/tojs/cocos2dx_studio.ini b/tools/tojs/cocos2dx_studio.ini index 48eb1c73c4..a8fd14ce20 100644 --- a/tools/tojs/cocos2dx_studio.ini +++ b/tools/tojs/cocos2dx_studio.ini @@ -43,7 +43,7 @@ skip = *::[^visit$ copyWith.* onEnter.* onExit.* ^description$ getObjectType .*H BatchNode::[init draw], Armature::[createBone updateBlendType getBody setBody getShapeList .*BlendFunc], Skin::[getSkinData setSkinData], - ArmatureAnimation::[updateHandler updateFrameData frameEvent (s|g)etAnimationData], + ArmatureAnimation::[updateHandler updateFrameData frameEvent (s|g)etAnimationData setMovementEventCallFunc setFrameEventCallFunc], ArmatureDataManager::[getTextureDatas], ActionManagerEx::[initWithDictionary], Bone::[getTweenData getBoneData], diff --git a/tools/tolua/cocos2dx_studio.ini b/tools/tolua/cocos2dx_studio.ini index ea46b68943..f112f2bbf9 100644 --- a/tools/tolua/cocos2dx_studio.ini +++ b/tools/tolua/cocos2dx_studio.ini @@ -40,7 +40,7 @@ skip = *::[^visit$ copyWith.* onEnter.* onExit.* ^description$ getObjectType .* ArmatureDataManager::[CCArmatureDataManager ~CCArmatureDataManager], Armature::[createBone updateBlendType setBody getShapeList ^getBody$], Skin::[(s|g)etSkinData], - ArmatureAnimation::[updateHandler updateFrameData frameEvent], + ArmatureAnimation::[updateHandler updateFrameData frameEvent setMovementEventCallFunc setFrameEventCallFunc], Bone::[(s|g)etIgnoreMovementBoneData], UILayer::[getInputManager], UILayoutParameter::[(s|g)etMargin], From 3dc052db4f436d4d8031104942c1f2c7127b3661 Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 19 Dec 2013 20:32:22 +0800 Subject: [PATCH 3/3] Fixes linux and windows building failure. --- cocos/2d/CCNode.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cocos/2d/CCNode.cpp b/cocos/2d/CCNode.cpp index 52be3d4155..18922971c1 100644 --- a/cocos/2d/CCNode.cpp +++ b/cocos/2d/CCNode.cpp @@ -1205,10 +1205,12 @@ const kmMat4& Node::getNodeToParentTransform() const // Build Transform Matrix // Adjusted transform calculation for rotational skew - _transform = { cy * _scaleX, sy * _scaleX, 0, 0, + kmScalar mat[] = { cy * _scaleX, sy * _scaleX, 0, 0, -sx * _scaleY, cx * _scaleY, 0, 0, 0, 0, 1, 0, x, y, 0, 1 }; + + kmMat4Fill(&_transform, mat); // XXX: Try to inline skew // If skew is needed, apply skew and then anchor point