Merge pull request #4559 from dumganhar/more_container_bind

[Scripting] Supports to bind more container: std::vector<std::string>, std::vector<int>, cocos2d::Map<std::string, T>.
This commit is contained in:
James Chen 2013-12-19 04:46:23 -08:00
commit c00bf38ab3
10 changed files with 298 additions and 110 deletions

View File

@ -1205,10 +1205,12 @@ const kmMat4& Node::getNodeToParentTransform() const
// Build Transform Matrix // Build Transform Matrix
// Adjusted transform calculation for rotational skew // 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, -sx * _scaleY, cx * _scaleY, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
x, y, 0, 1 }; x, y, 0, 1 };
kmMat4Fill(&_transform, mat);
// XXX: Try to inline skew // XXX: Try to inline skew
// If skew is needed, apply skew and then anchor point // If skew is needed, apply skew and then anchor point

View File

@ -1504,58 +1504,4 @@ void jsb_remove_proxy(js_proxy_t* nativeProxy, js_proxy_t* jsProxy)
JS_REMOVE_PROXY(nativeProxy, 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 : "";
}

View File

@ -207,57 +207,6 @@ public:
JSObject* NewGlobalObject(JSContext* cx, bool debug = false); 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_set_reserved_slot(JSObject *obj, uint32_t idx, jsval value);
JSBool jsb_get_reserved_slot(JSObject *obj, uint32_t idx, jsval& ret); JSBool jsb_get_reserved_slot(JSObject *obj, uint32_t idx, jsval& ret);

View File

@ -12,6 +12,84 @@
USING_NS_CC; 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) static Color3B getColorFromJSObject(JSContext *cx, JSObject *colorObject)
{ {
JS::RootedValue jsr(cx); 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<long*>(ret)); return jsval_to_long(cx, vp, reinterpret_cast<long*>(ret));
} }
JSBool jsval_to_std_vector_string( JSContext *cx, jsval vp, std::vector<std::string>* 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<int>* 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<int>(number));
}
}
else
{
JS_ReportError(cx, "not supported type in array");
return JS_FALSE;
}
}
}
return JS_TRUE;
}
// native --> jsval // native --> jsval
jsval ccarray_to_jsval(JSContext* cx, Array *arr) jsval ccarray_to_jsval(JSContext* cx, Array *arr)

View File

@ -7,9 +7,46 @@
#include "jsapi.h" #include "jsapi.h"
#include "js_bindings_core.h" #include "js_bindings_core.h"
#include "js_bindings_config.h"
#include "cocos2d.h" #include "cocos2d.h"
#include "spidermonkey_specifics.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_opaque( JSContext *cx, jsval vp, void **out );
JSBool jsval_to_int( JSContext *cx, jsval vp, int *out); JSBool jsval_to_int( JSContext *cx, jsval vp, int *out);
JSBool jsval_to_uint( JSContext *cx, jsval vp, unsigned 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_ccintvaluemap(JSContext* cx, jsval v, cocos2d::IntValueMap* ret);
JSBool jsval_to_ccvaluevector(JSContext* cx, jsval v, cocos2d::ValueVector* 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_ssize( JSContext *cx, jsval vp, ssize_t* ret);
JSBool jsval_to_std_vector_string( JSContext *cx, jsval vp, std::vector<std::string>* ret);
JSBool jsval_to_std_vector_int( JSContext *cx, jsval vp, std::vector<int>* ret);
template <class T>
JSBool jsval_to_ccmap_string_key(JSContext *cx, jsval v, cocos2d::Map<std::string, T>* 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 // from native
jsval int32_to_jsval( JSContext *cx, int32_t l); jsval int32_to_jsval( JSContext *cx, int32_t l);
@ -171,6 +264,32 @@ jsval ccvector_to_jsval(JSContext* cx, const cocos2d::Vector<T>& v)
return OBJECT_TO_JSVAL(jsretArr); return OBJECT_TO_JSVAL(jsretArr);
} }
template <class T>
jsval ccmap_string_key_to_jsval(JSContext* cx, const cocos2d::Map<std::string, T>& 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<cocos2d::Object>(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 ccvalue_to_jsval(JSContext* cx, const cocos2d::Value& v);
jsval ccvaluemap_to_jsval(JSContext* cx, const cocos2d::ValueMap& v); jsval ccvaluemap_to_jsval(JSContext* cx, const cocos2d::ValueMap& v);
jsval ccintvaluemap_to_jsval(JSContext* cx, const cocos2d::IntValueMap& v); jsval ccintvaluemap_to_jsval(JSContext* cx, const cocos2d::IntValueMap& v);

View File

@ -1423,6 +1423,17 @@ bool luaval_to_ccvaluevector(lua_State* L, int lo, cocos2d::ValueVector* ret)
return ok; return ok;
} }
bool luaval_to_std_vector_string(lua_State* L, int lo, std::vector<std::string>* ret)
{
// TO BE DONE IN CPP FILE
return false;
}
bool luaval_to_std_vector_int(lua_State* L, int lo, std::vector<int>* ret)
{
// TO BE DONE IN CPP FILE
return false;
}
void point_to_luaval(lua_State* L,const Point& pt) void point_to_luaval(lua_State* L,const Point& pt)
{ {

View File

@ -114,6 +114,17 @@ bool luaval_to_ccvector(lua_State* L, int lo , cocos2d::Vector<T>* ret)
return ok; return ok;
} }
bool luaval_to_std_vector_string(lua_State* L, int lo, std::vector<std::string>* ret);
bool luaval_to_std_vector_int(lua_State* L, int lo, std::vector<int>* ret);
template <class T>
bool luaval_to_ccmap_string_key(lua_State* L, int lo, cocos2d::Map<std::string, T>* ret)
{
// TO BE DONE:
return false;
}
extern bool luaval_to_ccvalue(lua_State* L, int lo, cocos2d::Value* ret); 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_ccvaluemap(lua_State* L, int lo, cocos2d::ValueMap* ret);
extern bool luaval_to_ccintvaluemap(lua_State* L, int lo, cocos2d::IntValueMap* 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<T>& inValue)
} }
} }
template <class T>
void ccmap_string_key_to_luaval(lua_State* L, const cocos2d::Map<std::string, T>& v)
{
// TO BE DONE:
}
void ccvalue_to_luaval(lua_State* L,const cocos2d::Value& inValue); void ccvalue_to_luaval(lua_State* L,const cocos2d::Value& inValue);
void ccvaluemap_to_luaval(lua_State* L,const cocos2d::ValueMap& inValue); void ccvaluemap_to_luaval(lua_State* L,const cocos2d::ValueMap& inValue);
void ccintvaluemap_to_luaval(lua_State* L, const cocos2d::IntValueMap& inValue); void ccintvaluemap_to_luaval(lua_State* L, const cocos2d::IntValueMap& inValue);

@ -1 +1 @@
Subproject commit a8e5123121a4c537bfa9e79f7adb981c17b18e6e Subproject commit f0b6cc8dd3d375f0999ec4e49dd90dbe1938c460

View File

@ -43,7 +43,7 @@ skip = *::[^visit$ copyWith.* onEnter.* onExit.* ^description$ getObjectType .*H
BatchNode::[init draw], BatchNode::[init draw],
Armature::[createBone updateBlendType getBody setBody getShapeList .*BlendFunc], Armature::[createBone updateBlendType getBody setBody getShapeList .*BlendFunc],
Skin::[getSkinData setSkinData], Skin::[getSkinData setSkinData],
ArmatureAnimation::[updateHandler updateFrameData frameEvent (s|g)etAnimationData], ArmatureAnimation::[updateHandler updateFrameData frameEvent (s|g)etAnimationData setMovementEventCallFunc setFrameEventCallFunc],
ArmatureDataManager::[getTextureDatas], ArmatureDataManager::[getTextureDatas],
ActionManagerEx::[initWithDictionary], ActionManagerEx::[initWithDictionary],
Bone::[getTweenData getBoneData], Bone::[getTweenData getBoneData],

View File

@ -40,7 +40,7 @@ skip = *::[^visit$ copyWith.* onEnter.* onExit.* ^description$ getObjectType .*
ArmatureDataManager::[CCArmatureDataManager ~CCArmatureDataManager], ArmatureDataManager::[CCArmatureDataManager ~CCArmatureDataManager],
Armature::[createBone updateBlendType setBody getShapeList ^getBody$], Armature::[createBone updateBlendType setBody getShapeList ^getBody$],
Skin::[(s|g)etSkinData], Skin::[(s|g)etSkinData],
ArmatureAnimation::[updateHandler updateFrameData frameEvent], ArmatureAnimation::[updateHandler updateFrameData frameEvent setMovementEventCallFunc setFrameEventCallFunc],
Bone::[(s|g)etIgnoreMovementBoneData], Bone::[(s|g)etIgnoreMovementBoneData],
UILayer::[getInputManager], UILayer::[getInputManager],
UILayoutParameter::[(s|g)etMargin], UILayoutParameter::[(s|g)etMargin],