2012-08-28 10:22:36 +08:00
|
|
|
#ifndef __JS_COCOS2D_X_SPECIFICS_H__
|
|
|
|
#define __JS_COCOS2D_X_SPECIFICS_H__
|
|
|
|
|
|
|
|
#include "jsapi.h"
|
|
|
|
#include "ScriptingCore.h"
|
|
|
|
|
2012-11-01 02:08:37 +08:00
|
|
|
class JSScheduleWrapper;
|
2012-10-23 02:07:23 +08:00
|
|
|
|
issue #1581: JSBinding bug fixes.
Some fixes of JSBinding codes:
[1] Check whether the proxy was already added in JS_NEW_PROXY
[2] In struct schedFunc_proxy_t, JSScheduleWrapper* --> CCArray*
Reason: One js function may correspond to many targets. To debug this, you could refer to JSScheduleWrapper::dump function. It will prove that i'm right. :)
[3] In ScriptingCore::cleanupSchedulesAndActions function, we must invoke unschedule for all targets and remove the proxy both in _schedFunc_target_ht and _schedTarget_native_ht, otherwise the hash tables will grow bigger and bigger, so I added a new function JSScheduleWrapper::removeAllTargetsForNatiaveNode to make this things easier.
[4] To easily find out the bugs of binding codes, I add JS_SetGCZeal in ScriptingCore::createGlobalContext, it only works in DEBUG mode.
[5] In js_cocos2dx_CCNode_getChildren, we should add the generated array to root to avoid gc happen when invoking JS_SetElement.
[6] The JSCallFuncWrapper isn't needed since an action will be run by a cc.Node and it will be released at the CCNode::cleanup.
[7] Some improvements of JSScheduleWrapper class.
[8] Added a new function JSScheduleWrapper::setTarget, it's for js_CCNode_unschedule to find out which target need to be unscheduled.
[9] Commented JS_SetReservedSlot in js_CCNode_scheduleOnce and js_CCNode_schedule.
Reason:
For js_CCNode_scheduleOnce: Don't add the callback function to the reserved slot of this js object.Since the class of js object may be inherited from cocos class(e.g. cc.Sprite). The subclass will not contain reserved slots. It will crash if invoking this.
For js_CCNode_schedule: Don't add js callback function to the reserved slot of scheduler js object. Since the scheduler is an object always rooted.
So the callback function might not be released when gc comes.I looked inside the implementation of cc.Node.schedule, and it doesn't use JS_SetReservedSlot there.
2012-11-28 22:04:55 +08:00
|
|
|
// JSScheduleWrapper* --> CCArray* since one js function may correspond to many targets.
|
|
|
|
// To debug this, you could refer to JSScheduleWrapper::dump function.
|
|
|
|
// It will prove that i'm right. :)
|
2012-10-23 02:07:23 +08:00
|
|
|
typedef struct jsScheduleFunc_proxy {
|
issue #1581: JSBinding bug fixes.
Some fixes of JSBinding codes:
[1] Check whether the proxy was already added in JS_NEW_PROXY
[2] In struct schedFunc_proxy_t, JSScheduleWrapper* --> CCArray*
Reason: One js function may correspond to many targets. To debug this, you could refer to JSScheduleWrapper::dump function. It will prove that i'm right. :)
[3] In ScriptingCore::cleanupSchedulesAndActions function, we must invoke unschedule for all targets and remove the proxy both in _schedFunc_target_ht and _schedTarget_native_ht, otherwise the hash tables will grow bigger and bigger, so I added a new function JSScheduleWrapper::removeAllTargetsForNatiaveNode to make this things easier.
[4] To easily find out the bugs of binding codes, I add JS_SetGCZeal in ScriptingCore::createGlobalContext, it only works in DEBUG mode.
[5] In js_cocos2dx_CCNode_getChildren, we should add the generated array to root to avoid gc happen when invoking JS_SetElement.
[6] The JSCallFuncWrapper isn't needed since an action will be run by a cc.Node and it will be released at the CCNode::cleanup.
[7] Some improvements of JSScheduleWrapper class.
[8] Added a new function JSScheduleWrapper::setTarget, it's for js_CCNode_unschedule to find out which target need to be unscheduled.
[9] Commented JS_SetReservedSlot in js_CCNode_scheduleOnce and js_CCNode_schedule.
Reason:
For js_CCNode_scheduleOnce: Don't add the callback function to the reserved slot of this js object.Since the class of js object may be inherited from cocos class(e.g. cc.Sprite). The subclass will not contain reserved slots. It will crash if invoking this.
For js_CCNode_schedule: Don't add js callback function to the reserved slot of scheduler js object. Since the scheduler is an object always rooted.
So the callback function might not be released when gc comes.I looked inside the implementation of cc.Node.schedule, and it doesn't use JS_SetReservedSlot there.
2012-11-28 22:04:55 +08:00
|
|
|
JSObject* jsfuncObj;
|
|
|
|
CCArray* targets;
|
2012-10-23 02:07:23 +08:00
|
|
|
UT_hash_handle hh;
|
|
|
|
} schedFunc_proxy_t;
|
|
|
|
|
|
|
|
typedef struct jsScheduleTarget_proxy {
|
2013-03-16 21:14:39 +08:00
|
|
|
JSObject* jsTargetObj;
|
issue #1581: JSBinding bug fixes.
Some fixes of JSBinding codes:
[1] Check whether the proxy was already added in JS_NEW_PROXY
[2] In struct schedFunc_proxy_t, JSScheduleWrapper* --> CCArray*
Reason: One js function may correspond to many targets. To debug this, you could refer to JSScheduleWrapper::dump function. It will prove that i'm right. :)
[3] In ScriptingCore::cleanupSchedulesAndActions function, we must invoke unschedule for all targets and remove the proxy both in _schedFunc_target_ht and _schedTarget_native_ht, otherwise the hash tables will grow bigger and bigger, so I added a new function JSScheduleWrapper::removeAllTargetsForNatiaveNode to make this things easier.
[4] To easily find out the bugs of binding codes, I add JS_SetGCZeal in ScriptingCore::createGlobalContext, it only works in DEBUG mode.
[5] In js_cocos2dx_CCNode_getChildren, we should add the generated array to root to avoid gc happen when invoking JS_SetElement.
[6] The JSCallFuncWrapper isn't needed since an action will be run by a cc.Node and it will be released at the CCNode::cleanup.
[7] Some improvements of JSScheduleWrapper class.
[8] Added a new function JSScheduleWrapper::setTarget, it's for js_CCNode_unschedule to find out which target need to be unscheduled.
[9] Commented JS_SetReservedSlot in js_CCNode_scheduleOnce and js_CCNode_schedule.
Reason:
For js_CCNode_scheduleOnce: Don't add the callback function to the reserved slot of this js object.Since the class of js object may be inherited from cocos class(e.g. cc.Sprite). The subclass will not contain reserved slots. It will crash if invoking this.
For js_CCNode_schedule: Don't add js callback function to the reserved slot of scheduler js object. Since the scheduler is an object always rooted.
So the callback function might not be released when gc comes.I looked inside the implementation of cc.Node.schedule, and it doesn't use JS_SetReservedSlot there.
2012-11-28 22:04:55 +08:00
|
|
|
CCArray* targets;
|
2012-10-23 02:07:23 +08:00
|
|
|
UT_hash_handle hh;
|
|
|
|
} schedTarget_proxy_t;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct jsCallFuncTarget_proxy {
|
|
|
|
void * ptr;
|
|
|
|
CCArray *obj;
|
|
|
|
UT_hash_handle hh;
|
|
|
|
} callfuncTarget_proxy_t;
|
|
|
|
|
|
|
|
extern schedFunc_proxy_t *_schedFunc_target_ht;
|
2013-03-16 21:14:39 +08:00
|
|
|
extern schedTarget_proxy_t *_schedObj_target_ht;
|
2012-10-23 02:07:23 +08:00
|
|
|
|
|
|
|
extern callfuncTarget_proxy_t *_callfuncTarget_native_ht;
|
2012-08-28 10:22:36 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* You don't need to manage the returned pointer. They live for the whole life of
|
|
|
|
* the app.
|
|
|
|
*/
|
|
|
|
template <class T>
|
|
|
|
inline js_type_class_t *js_get_type_from_native(T* native_obj) {
|
|
|
|
js_type_class_t *typeProxy;
|
2012-10-12 15:41:45 +08:00
|
|
|
long typeId = cocos2d::getHashCodeByString(typeid(*native_obj).name());
|
2012-08-28 10:22:36 +08:00
|
|
|
HASH_FIND_INT(_js_global_type_ht, &typeId, typeProxy);
|
|
|
|
if (!typeProxy) {
|
2012-10-12 15:41:45 +08:00
|
|
|
cocos2d::TypeInfo *typeInfo = dynamic_cast<cocos2d::TypeInfo *>(native_obj);
|
2012-08-28 10:22:36 +08:00
|
|
|
if (typeInfo) {
|
|
|
|
typeId = typeInfo->getClassTypeInfo();
|
|
|
|
} else {
|
2012-10-12 15:41:45 +08:00
|
|
|
typeId = cocos2d::getHashCodeByString(typeid(T).name());
|
2012-08-28 10:22:36 +08:00
|
|
|
}
|
|
|
|
HASH_FIND_INT(_js_global_type_ht, &typeId, typeProxy);
|
|
|
|
}
|
|
|
|
return typeProxy;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-06-04 12:53:42 +08:00
|
|
|
* The returned pointer should be deleted using jsb_remove_proxy. Most of the
|
2012-08-28 10:22:36 +08:00
|
|
|
* time you do that in the C++ destructor.
|
|
|
|
*/
|
|
|
|
template<class T>
|
|
|
|
inline js_proxy_t *js_get_or_create_proxy(JSContext *cx, T *native_obj) {
|
|
|
|
js_proxy_t *proxy;
|
|
|
|
HASH_FIND_PTR(_native_js_global_ht, &native_obj, proxy);
|
|
|
|
if (!proxy) {
|
|
|
|
js_type_class_t *typeProxy = js_get_type_from_native<T>(native_obj);
|
2013-03-13 18:10:54 +08:00
|
|
|
// Return NULL if can't find its type rather than making an assert.
|
|
|
|
// assert(typeProxy);
|
|
|
|
if (!typeProxy) {
|
2013-03-19 12:57:17 +08:00
|
|
|
CCLOGINFO("Could not find the type of native object.");
|
2013-03-13 18:10:54 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
JSObject* js_obj = JS_NewObject(cx, typeProxy->jsclass, typeProxy->proto, typeProxy->parentProto);
|
2013-06-04 12:53:42 +08:00
|
|
|
proxy = jsb_new_proxy(native_obj, js_obj);
|
2012-08-28 10:22:36 +08:00
|
|
|
#ifdef DEBUG
|
|
|
|
JS_AddNamedObjectRoot(cx, &proxy->obj, typeid(*native_obj).name());
|
|
|
|
#else
|
|
|
|
JS_AddObjectRoot(cx, &proxy->obj);
|
|
|
|
#endif
|
|
|
|
return proxy;
|
|
|
|
} else {
|
|
|
|
return proxy;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
jsval anonEvaluate(JSContext *cx, JSObject *thisObj, const char* string);
|
|
|
|
void register_cocos2dx_js_extensions(JSContext* cx, JSObject* obj);
|
|
|
|
|
2012-11-01 02:08:37 +08:00
|
|
|
|
|
|
|
class JSCallbackWrapper: public CCObject {
|
2012-08-28 10:22:36 +08:00
|
|
|
public:
|
fixed #1617: Some improvements for JS Bindings.
1) Changed cc.REPEAT_FOREVER = - 1 to cc.REPEAT_FOREVER = 0xffffffff
[Reason]: If cc.REPEAT_FOREVER = -1, it will be a very big double value after converting it to double by JS_ValueToNumber on android.
Then cast it to unsigned int, the value will be 0. The schedule will not be able to work.
I don't know why this occurs only on android.
[Solution]: Instead of passing -1 to it, I assign it with max value of unsigned int in c++.
2) Added two helper function, cc.ArrayGetIndexOfObject and cc.ArrayContainsObject.
3) Added JSScheduleWrapper::removeTargetForNativeNode to avoid memory leaks.
4) Improvments for JSTouchDelegate. Added four functions as follows:
// Set the touch delegate to map by using the key (pJSObj).
static void setDelegateForJSObject(JSObject* pJSObj, JSTouchDelegate* pDelegate);
// Get the touch delegate by the key (pJSObj).
static JSTouchDelegate* getDelegateForJSObject(JSObject* pJSObj);
// Remove the delegate by the key (pJSObj).
static void removeDelegateForJSObject(JSObject* pJSObj);
void unregisterTouchDelegate();
And exported cc.unregisterTouchDelegate(); to js.
Fix a memory leak for JSTouchDelegate by making it as an autorelease object.
5) Don't add js callback function to the reserved slot of object.
[Reason]: The target object may execute more than one schedule.
Therefore, previous js callback function will be replaced
by the current one. For example:
this.scheduleOnce(function() { temporary function 1 }, 0.5);
this.scheduleOnce(function() { temporary function 2 }, 0.5);
In this case, the temporary function 1 will be removed from reserved slot 0.
And temporary function 2 will be set to reserved slot 0 of this object.
If gc is triggered before the JSScheduleWrapper::scheduleFunc is invoked,
crash will happen. You could simply reproduce it by adding jsc.garbageCollect(); after scheduleOnce.
[Solution] Because one schedule corresponds to one JSScheduleWrapper, we root
the js callback function in JSScheduleWrapper::setJSCallbackFunc and unroot it
at the destructor of JSScheduleWrapper.
2012-12-18 11:56:44 +08:00
|
|
|
JSCallbackWrapper();
|
|
|
|
virtual ~JSCallbackWrapper();
|
2012-08-28 10:22:36 +08:00
|
|
|
void setJSCallbackFunc(jsval obj);
|
|
|
|
void setJSCallbackThis(jsval thisObj);
|
2012-11-01 02:08:37 +08:00
|
|
|
void setJSExtraData(jsval data);
|
|
|
|
|
2012-12-03 15:31:52 +08:00
|
|
|
const jsval& getJSCallbackFunc() const;
|
|
|
|
const jsval& getJSCallbackThis() const;
|
|
|
|
const jsval& getJSExtraData() const;
|
2012-11-01 02:08:37 +08:00
|
|
|
protected:
|
|
|
|
jsval jsCallback;
|
|
|
|
jsval jsThisObj;
|
|
|
|
jsval extraData;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class JSCCBAnimationWrapper: public JSCallbackWrapper {
|
|
|
|
public:
|
|
|
|
JSCCBAnimationWrapper() {}
|
|
|
|
virtual ~JSCCBAnimationWrapper() {}
|
|
|
|
|
|
|
|
void animationCompleteCallback() const {
|
|
|
|
|
|
|
|
JSContext *cx = ScriptingCore::getInstance()->getGlobalContext();
|
|
|
|
jsval retval = JSVAL_NULL;
|
|
|
|
|
|
|
|
if(!JSVAL_IS_VOID(jsCallback) && !JSVAL_IS_VOID(jsThisObj)) {
|
|
|
|
JS_CallFunctionValue(cx, JSVAL_TO_OBJECT(jsThisObj), jsCallback, 0, NULL, &retval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class JSCallFuncWrapper: public JSCallbackWrapper {
|
|
|
|
public:
|
|
|
|
JSCallFuncWrapper() {}
|
|
|
|
virtual ~JSCallFuncWrapper(void) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void setTargetForNativeNode(CCNode *pNode, JSCallFuncWrapper *target);
|
2012-10-23 02:07:23 +08:00
|
|
|
static CCArray * getTargetForNativeNode(CCNode *pNode);
|
|
|
|
|
2012-11-05 18:44:28 +08:00
|
|
|
void callbackFunc(CCNode *node) const;
|
2012-08-28 10:22:36 +08:00
|
|
|
};
|
|
|
|
|
2012-10-10 05:59:16 +08:00
|
|
|
|
2012-11-01 02:08:37 +08:00
|
|
|
class JSScheduleWrapper: public JSCallbackWrapper {
|
2012-10-10 05:59:16 +08:00
|
|
|
|
|
|
|
public:
|
2013-03-18 15:29:53 +08:00
|
|
|
JSScheduleWrapper() : _pTarget(NULL), _pPureJSTarget(NULL), _priority(0), _isUpdateSchedule(false) {}
|
2013-03-16 21:14:39 +08:00
|
|
|
virtual ~JSScheduleWrapper();
|
2012-10-10 05:59:16 +08:00
|
|
|
|
2012-11-01 02:08:37 +08:00
|
|
|
static void setTargetForSchedule(jsval sched, JSScheduleWrapper *target);
|
issue #1581: JSBinding bug fixes.
Some fixes of JSBinding codes:
[1] Check whether the proxy was already added in JS_NEW_PROXY
[2] In struct schedFunc_proxy_t, JSScheduleWrapper* --> CCArray*
Reason: One js function may correspond to many targets. To debug this, you could refer to JSScheduleWrapper::dump function. It will prove that i'm right. :)
[3] In ScriptingCore::cleanupSchedulesAndActions function, we must invoke unschedule for all targets and remove the proxy both in _schedFunc_target_ht and _schedTarget_native_ht, otherwise the hash tables will grow bigger and bigger, so I added a new function JSScheduleWrapper::removeAllTargetsForNatiaveNode to make this things easier.
[4] To easily find out the bugs of binding codes, I add JS_SetGCZeal in ScriptingCore::createGlobalContext, it only works in DEBUG mode.
[5] In js_cocos2dx_CCNode_getChildren, we should add the generated array to root to avoid gc happen when invoking JS_SetElement.
[6] The JSCallFuncWrapper isn't needed since an action will be run by a cc.Node and it will be released at the CCNode::cleanup.
[7] Some improvements of JSScheduleWrapper class.
[8] Added a new function JSScheduleWrapper::setTarget, it's for js_CCNode_unschedule to find out which target need to be unscheduled.
[9] Commented JS_SetReservedSlot in js_CCNode_scheduleOnce and js_CCNode_schedule.
Reason:
For js_CCNode_scheduleOnce: Don't add the callback function to the reserved slot of this js object.Since the class of js object may be inherited from cocos class(e.g. cc.Sprite). The subclass will not contain reserved slots. It will crash if invoking this.
For js_CCNode_schedule: Don't add js callback function to the reserved slot of scheduler js object. Since the scheduler is an object always rooted.
So the callback function might not be released when gc comes.I looked inside the implementation of cc.Node.schedule, and it doesn't use JS_SetReservedSlot there.
2012-11-28 22:04:55 +08:00
|
|
|
static CCArray * getTargetForSchedule(jsval sched);
|
2013-03-16 21:14:39 +08:00
|
|
|
static void setTargetForJSObject(JSObject* jsTargetObj, JSScheduleWrapper *target);
|
|
|
|
static CCArray * getTargetForJSObject(JSObject* jsTargetObj);
|
2013-03-18 15:29:53 +08:00
|
|
|
|
|
|
|
// Remove all targets.
|
|
|
|
static void removeAllTargets();
|
|
|
|
// Remove all targets for priority.
|
|
|
|
static void removeAllTargetsForMinPriority(int minPriority);
|
2013-03-16 21:14:39 +08:00
|
|
|
// Remove all targets by js object from hash table(_schedFunc_target_ht and _schedObj_target_ht).
|
|
|
|
static void removeAllTargetsForJSObject(JSObject* jsTargetObj);
|
|
|
|
// Remove the target by js object and the wrapper for native schedule.
|
|
|
|
static void removeTargetForJSObject(JSObject* jsTargetObj, JSScheduleWrapper* target);
|
issue #1581: JSBinding bug fixes.
Some fixes of JSBinding codes:
[1] Check whether the proxy was already added in JS_NEW_PROXY
[2] In struct schedFunc_proxy_t, JSScheduleWrapper* --> CCArray*
Reason: One js function may correspond to many targets. To debug this, you could refer to JSScheduleWrapper::dump function. It will prove that i'm right. :)
[3] In ScriptingCore::cleanupSchedulesAndActions function, we must invoke unschedule for all targets and remove the proxy both in _schedFunc_target_ht and _schedTarget_native_ht, otherwise the hash tables will grow bigger and bigger, so I added a new function JSScheduleWrapper::removeAllTargetsForNatiaveNode to make this things easier.
[4] To easily find out the bugs of binding codes, I add JS_SetGCZeal in ScriptingCore::createGlobalContext, it only works in DEBUG mode.
[5] In js_cocos2dx_CCNode_getChildren, we should add the generated array to root to avoid gc happen when invoking JS_SetElement.
[6] The JSCallFuncWrapper isn't needed since an action will be run by a cc.Node and it will be released at the CCNode::cleanup.
[7] Some improvements of JSScheduleWrapper class.
[8] Added a new function JSScheduleWrapper::setTarget, it's for js_CCNode_unschedule to find out which target need to be unscheduled.
[9] Commented JS_SetReservedSlot in js_CCNode_scheduleOnce and js_CCNode_schedule.
Reason:
For js_CCNode_scheduleOnce: Don't add the callback function to the reserved slot of this js object.Since the class of js object may be inherited from cocos class(e.g. cc.Sprite). The subclass will not contain reserved slots. It will crash if invoking this.
For js_CCNode_schedule: Don't add js callback function to the reserved slot of scheduler js object. Since the scheduler is an object always rooted.
So the callback function might not be released when gc comes.I looked inside the implementation of cc.Node.schedule, and it doesn't use JS_SetReservedSlot there.
2012-11-28 22:04:55 +08:00
|
|
|
static void dump();
|
2012-10-10 05:59:16 +08:00
|
|
|
|
|
|
|
void pause();
|
|
|
|
|
2012-11-22 12:05:38 +08:00
|
|
|
void scheduleFunc(float dt) const;
|
2013-03-18 15:29:53 +08:00
|
|
|
virtual void update(float dt);
|
|
|
|
|
issue #1581: JSBinding bug fixes.
Some fixes of JSBinding codes:
[1] Check whether the proxy was already added in JS_NEW_PROXY
[2] In struct schedFunc_proxy_t, JSScheduleWrapper* --> CCArray*
Reason: One js function may correspond to many targets. To debug this, you could refer to JSScheduleWrapper::dump function. It will prove that i'm right. :)
[3] In ScriptingCore::cleanupSchedulesAndActions function, we must invoke unschedule for all targets and remove the proxy both in _schedFunc_target_ht and _schedTarget_native_ht, otherwise the hash tables will grow bigger and bigger, so I added a new function JSScheduleWrapper::removeAllTargetsForNatiaveNode to make this things easier.
[4] To easily find out the bugs of binding codes, I add JS_SetGCZeal in ScriptingCore::createGlobalContext, it only works in DEBUG mode.
[5] In js_cocos2dx_CCNode_getChildren, we should add the generated array to root to avoid gc happen when invoking JS_SetElement.
[6] The JSCallFuncWrapper isn't needed since an action will be run by a cc.Node and it will be released at the CCNode::cleanup.
[7] Some improvements of JSScheduleWrapper class.
[8] Added a new function JSScheduleWrapper::setTarget, it's for js_CCNode_unschedule to find out which target need to be unscheduled.
[9] Commented JS_SetReservedSlot in js_CCNode_scheduleOnce and js_CCNode_schedule.
Reason:
For js_CCNode_scheduleOnce: Don't add the callback function to the reserved slot of this js object.Since the class of js object may be inherited from cocos class(e.g. cc.Sprite). The subclass will not contain reserved slots. It will crash if invoking this.
For js_CCNode_schedule: Don't add js callback function to the reserved slot of scheduler js object. Since the scheduler is an object always rooted.
So the callback function might not be released when gc comes.I looked inside the implementation of cc.Node.schedule, and it doesn't use JS_SetReservedSlot there.
2012-11-28 22:04:55 +08:00
|
|
|
CCObject* getTarget();
|
|
|
|
void setTarget(CCObject* pTarget);
|
2013-03-16 21:14:39 +08:00
|
|
|
|
|
|
|
void setPureJSTarget(JSObject* jstarget);
|
|
|
|
JSObject* getPureJSTarget();
|
2013-03-18 15:29:53 +08:00
|
|
|
|
|
|
|
void setPriority(int priority);
|
|
|
|
int getPriority();
|
|
|
|
|
|
|
|
void setUpdateSchedule(bool isUpdateSchedule);
|
|
|
|
bool isUpdateSchedule();
|
|
|
|
|
issue #1581: JSBinding bug fixes.
Some fixes of JSBinding codes:
[1] Check whether the proxy was already added in JS_NEW_PROXY
[2] In struct schedFunc_proxy_t, JSScheduleWrapper* --> CCArray*
Reason: One js function may correspond to many targets. To debug this, you could refer to JSScheduleWrapper::dump function. It will prove that i'm right. :)
[3] In ScriptingCore::cleanupSchedulesAndActions function, we must invoke unschedule for all targets and remove the proxy both in _schedFunc_target_ht and _schedTarget_native_ht, otherwise the hash tables will grow bigger and bigger, so I added a new function JSScheduleWrapper::removeAllTargetsForNatiaveNode to make this things easier.
[4] To easily find out the bugs of binding codes, I add JS_SetGCZeal in ScriptingCore::createGlobalContext, it only works in DEBUG mode.
[5] In js_cocos2dx_CCNode_getChildren, we should add the generated array to root to avoid gc happen when invoking JS_SetElement.
[6] The JSCallFuncWrapper isn't needed since an action will be run by a cc.Node and it will be released at the CCNode::cleanup.
[7] Some improvements of JSScheduleWrapper class.
[8] Added a new function JSScheduleWrapper::setTarget, it's for js_CCNode_unschedule to find out which target need to be unscheduled.
[9] Commented JS_SetReservedSlot in js_CCNode_scheduleOnce and js_CCNode_schedule.
Reason:
For js_CCNode_scheduleOnce: Don't add the callback function to the reserved slot of this js object.Since the class of js object may be inherited from cocos class(e.g. cc.Sprite). The subclass will not contain reserved slots. It will crash if invoking this.
For js_CCNode_schedule: Don't add js callback function to the reserved slot of scheduler js object. Since the scheduler is an object always rooted.
So the callback function might not be released when gc comes.I looked inside the implementation of cc.Node.schedule, and it doesn't use JS_SetReservedSlot there.
2012-11-28 22:04:55 +08:00
|
|
|
protected:
|
2013-03-16 21:14:39 +08:00
|
|
|
CCObject* _pTarget;
|
|
|
|
JSObject* _pPureJSTarget;
|
2013-03-18 15:29:53 +08:00
|
|
|
int _priority;
|
|
|
|
bool _isUpdateSchedule;
|
2012-10-10 05:59:16 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
fixed #1617: Some improvements for JS Bindings.
1) Changed cc.REPEAT_FOREVER = - 1 to cc.REPEAT_FOREVER = 0xffffffff
[Reason]: If cc.REPEAT_FOREVER = -1, it will be a very big double value after converting it to double by JS_ValueToNumber on android.
Then cast it to unsigned int, the value will be 0. The schedule will not be able to work.
I don't know why this occurs only on android.
[Solution]: Instead of passing -1 to it, I assign it with max value of unsigned int in c++.
2) Added two helper function, cc.ArrayGetIndexOfObject and cc.ArrayContainsObject.
3) Added JSScheduleWrapper::removeTargetForNativeNode to avoid memory leaks.
4) Improvments for JSTouchDelegate. Added four functions as follows:
// Set the touch delegate to map by using the key (pJSObj).
static void setDelegateForJSObject(JSObject* pJSObj, JSTouchDelegate* pDelegate);
// Get the touch delegate by the key (pJSObj).
static JSTouchDelegate* getDelegateForJSObject(JSObject* pJSObj);
// Remove the delegate by the key (pJSObj).
static void removeDelegateForJSObject(JSObject* pJSObj);
void unregisterTouchDelegate();
And exported cc.unregisterTouchDelegate(); to js.
Fix a memory leak for JSTouchDelegate by making it as an autorelease object.
5) Don't add js callback function to the reserved slot of object.
[Reason]: The target object may execute more than one schedule.
Therefore, previous js callback function will be replaced
by the current one. For example:
this.scheduleOnce(function() { temporary function 1 }, 0.5);
this.scheduleOnce(function() { temporary function 2 }, 0.5);
In this case, the temporary function 1 will be removed from reserved slot 0.
And temporary function 2 will be set to reserved slot 0 of this object.
If gc is triggered before the JSScheduleWrapper::scheduleFunc is invoked,
crash will happen. You could simply reproduce it by adding jsc.garbageCollect(); after scheduleOnce.
[Solution] Because one schedule corresponds to one JSScheduleWrapper, we root
the js callback function in JSScheduleWrapper::setJSCallbackFunc and unroot it
at the destructor of JSScheduleWrapper.
2012-12-18 11:56:44 +08:00
|
|
|
class JSTouchDelegate: public CCObject, public CCTouchDelegate
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// Set the touch delegate to map by using the key (pJSObj).
|
|
|
|
static void setDelegateForJSObject(JSObject* pJSObj, JSTouchDelegate* pDelegate);
|
|
|
|
// Get the touch delegate by the key (pJSObj).
|
|
|
|
static JSTouchDelegate* getDelegateForJSObject(JSObject* pJSObj);
|
|
|
|
// Remove the delegate by the key (pJSObj).
|
|
|
|
static void removeDelegateForJSObject(JSObject* pJSObj);
|
|
|
|
|
|
|
|
void setJSObject(JSObject *obj);
|
|
|
|
void registerStandardDelegate();
|
|
|
|
void registerTargettedDelegate(int priority, bool swallowsTouches);
|
|
|
|
// unregister touch delegate.
|
|
|
|
// Normally, developer should invoke cc.unregisterTouchDelegate() in when the scene exits.
|
|
|
|
// So this function need to be binded.
|
|
|
|
void unregisterTouchDelegate();
|
|
|
|
|
|
|
|
bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
|
|
|
|
void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
|
|
|
|
void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
|
|
|
|
void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
|
2012-08-28 10:22:36 +08:00
|
|
|
|
|
|
|
// optional
|
fixed #1617: Some improvements for JS Bindings.
1) Changed cc.REPEAT_FOREVER = - 1 to cc.REPEAT_FOREVER = 0xffffffff
[Reason]: If cc.REPEAT_FOREVER = -1, it will be a very big double value after converting it to double by JS_ValueToNumber on android.
Then cast it to unsigned int, the value will be 0. The schedule will not be able to work.
I don't know why this occurs only on android.
[Solution]: Instead of passing -1 to it, I assign it with max value of unsigned int in c++.
2) Added two helper function, cc.ArrayGetIndexOfObject and cc.ArrayContainsObject.
3) Added JSScheduleWrapper::removeTargetForNativeNode to avoid memory leaks.
4) Improvments for JSTouchDelegate. Added four functions as follows:
// Set the touch delegate to map by using the key (pJSObj).
static void setDelegateForJSObject(JSObject* pJSObj, JSTouchDelegate* pDelegate);
// Get the touch delegate by the key (pJSObj).
static JSTouchDelegate* getDelegateForJSObject(JSObject* pJSObj);
// Remove the delegate by the key (pJSObj).
static void removeDelegateForJSObject(JSObject* pJSObj);
void unregisterTouchDelegate();
And exported cc.unregisterTouchDelegate(); to js.
Fix a memory leak for JSTouchDelegate by making it as an autorelease object.
5) Don't add js callback function to the reserved slot of object.
[Reason]: The target object may execute more than one schedule.
Therefore, previous js callback function will be replaced
by the current one. For example:
this.scheduleOnce(function() { temporary function 1 }, 0.5);
this.scheduleOnce(function() { temporary function 2 }, 0.5);
In this case, the temporary function 1 will be removed from reserved slot 0.
And temporary function 2 will be set to reserved slot 0 of this object.
If gc is triggered before the JSScheduleWrapper::scheduleFunc is invoked,
crash will happen. You could simply reproduce it by adding jsc.garbageCollect(); after scheduleOnce.
[Solution] Because one schedule corresponds to one JSScheduleWrapper, we root
the js callback function in JSScheduleWrapper::setJSCallbackFunc and unroot it
at the destructor of JSScheduleWrapper.
2012-12-18 11:56:44 +08:00
|
|
|
void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);
|
|
|
|
void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);
|
|
|
|
void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent);
|
|
|
|
void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent);
|
|
|
|
|
|
|
|
private:
|
|
|
|
JSObject *_mObj;
|
|
|
|
typedef std::map<JSObject*, JSTouchDelegate*> TouchDelegateMap;
|
|
|
|
typedef std::pair<JSObject*, JSTouchDelegate*> TouchDelegatePair;
|
|
|
|
static TouchDelegateMap sTouchDelegateMap;
|
2012-08-28 10:22:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|