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-10-23 02:07:23 +08:00
|
|
|
class JSSchedule;
|
|
|
|
|
|
|
|
typedef struct jsScheduleFunc_proxy {
|
|
|
|
void * ptr;
|
|
|
|
JSSchedule *obj;
|
|
|
|
UT_hash_handle hh;
|
|
|
|
} schedFunc_proxy_t;
|
|
|
|
|
|
|
|
typedef struct jsScheduleTarget_proxy {
|
|
|
|
void * ptr;
|
|
|
|
CCArray *obj;
|
|
|
|
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;
|
|
|
|
extern schedTarget_proxy_t *_schedTarget_native_ht;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The returned pointer should be deleted using JS_REMOVE_PROXY. Most of the
|
|
|
|
* 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);
|
|
|
|
assert(typeProxy);
|
|
|
|
JSObject* js_obj = JS_NewObject(cx, typeProxy->jsclass, typeProxy->proto, typeProxy->parentProto);
|
|
|
|
JS_NEW_PROXY(proxy, native_obj, js_obj);
|
|
|
|
#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);
|
|
|
|
|
|
|
|
class JSCallFunc: public CCObject {
|
|
|
|
public:
|
|
|
|
JSCallFunc(jsval func): jsCallback(func) {}
|
2012-10-27 06:31:52 +08:00
|
|
|
JSCallFunc() {extraData = JSVAL_VOID;}
|
2012-10-23 02:07:23 +08:00
|
|
|
virtual ~JSCallFunc() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
void setJSCallbackFunc(jsval obj);
|
|
|
|
void setJSCallbackThis(jsval thisObj);
|
|
|
|
void setExtraDataField(jsval data);
|
|
|
|
static void dumpNamedRoot(const char *name, void *addr, JSGCRootType type, void *data);
|
2012-10-23 02:07:23 +08:00
|
|
|
static void setTargetForNativeNode(CCNode *pNode, JSCallFunc *target);
|
|
|
|
static CCArray * getTargetForNativeNode(CCNode *pNode);
|
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
void callbackFunc(CCNode *node) const {
|
|
|
|
|
2012-10-12 09:43:40 +08:00
|
|
|
jsval valArr[2];
|
|
|
|
|
|
|
|
JSContext *cx = ScriptingCore::getInstance()->getGlobalContext();
|
|
|
|
js_proxy_t *proxy = js_get_or_create_proxy<cocos2d::CCNode>(cx, node);
|
2012-10-27 06:31:52 +08:00
|
|
|
|
|
|
|
JS_AddValueRoot(cx, valArr);
|
|
|
|
|
2012-10-12 09:43:40 +08:00
|
|
|
valArr[0] = OBJECT_TO_JSVAL(proxy->obj);
|
2012-10-27 06:31:52 +08:00
|
|
|
if(!JSVAL_IS_VOID(extraData)) {
|
2012-10-25 05:05:29 +08:00
|
|
|
valArr[1] = extraData;
|
2012-08-28 10:22:36 +08:00
|
|
|
} else {
|
2012-10-12 09:43:40 +08:00
|
|
|
valArr[1] = JSVAL_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
jsval retval;
|
2012-10-27 06:31:52 +08:00
|
|
|
if(jsCallback != JSVAL_VOID && jsThisObj != JSVAL_VOID) {
|
2012-10-25 05:05:29 +08:00
|
|
|
JS_CallFunctionValue(cx, JSVAL_TO_OBJECT(jsThisObj), jsCallback, 2, valArr, &retval);
|
2012-10-12 09:43:40 +08:00
|
|
|
}
|
2012-10-27 06:31:52 +08:00
|
|
|
|
2012-10-29 15:10:13 +08:00
|
|
|
JSCallFunc::setTargetForNativeNode(node, (JSCallFunc *)this);
|
2012-10-27 06:31:52 +08:00
|
|
|
|
|
|
|
JS_RemoveValueRoot(cx, valArr);
|
2012-10-12 09:43:40 +08:00
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
}
|
|
|
|
private:
|
|
|
|
jsval jsCallback;
|
|
|
|
jsval jsThisObj;
|
2012-10-25 05:05:29 +08:00
|
|
|
jsval extraData;
|
2012-08-28 10:22:36 +08:00
|
|
|
};
|
|
|
|
|
2012-10-10 05:59:16 +08:00
|
|
|
|
|
|
|
class JSSchedule: public CCObject {
|
|
|
|
|
|
|
|
public:
|
|
|
|
JSSchedule(jsval func): jsSchedule(func) {}
|
2012-10-27 06:31:52 +08:00
|
|
|
JSSchedule() {jsSchedule = JSVAL_VOID; jsThisObj = JSVAL_VOID;}
|
2012-10-23 02:07:23 +08:00
|
|
|
virtual ~JSSchedule() {
|
|
|
|
return;
|
|
|
|
}
|
2012-10-10 05:59:16 +08:00
|
|
|
|
|
|
|
static void setTargetForSchedule(jsval sched, JSSchedule *target);
|
|
|
|
static JSSchedule * getTargetForSchedule(jsval sched);
|
|
|
|
static void setTargetForNativeNode(CCNode *pNode, JSSchedule *target);
|
|
|
|
static CCArray * getTargetForNativeNode(CCNode *pNode);
|
|
|
|
|
|
|
|
void setJSScheduleFunc(jsval obj);
|
|
|
|
void setJSScheduleThis(jsval thisObj);
|
|
|
|
|
|
|
|
void pause();
|
|
|
|
|
2012-10-12 09:43:40 +08:00
|
|
|
void scheduleFunc(float dt) const {
|
|
|
|
|
|
|
|
jsval retval = JSVAL_NULL, data = DOUBLE_TO_JSVAL(dt);
|
|
|
|
JSContext *cx = ScriptingCore::getInstance()->getGlobalContext();
|
|
|
|
|
2012-10-27 06:31:52 +08:00
|
|
|
JSBool ok = JS_AddValueRoot(cx, &data);
|
|
|
|
if(!ok) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!JSVAL_IS_VOID(jsSchedule) && !JSVAL_IS_VOID(jsThisObj)) {
|
|
|
|
ScriptingCore::dumpRoot(cx, 0, NULL);
|
2012-10-12 09:43:40 +08:00
|
|
|
JS_CallFunctionValue(cx, JSVAL_TO_OBJECT(jsThisObj), jsSchedule, 1, &data, &retval);
|
|
|
|
}
|
|
|
|
|
2012-10-27 06:31:52 +08:00
|
|
|
JS_RemoveValueRoot(cx, &data);
|
|
|
|
|
2012-10-10 05:59:16 +08:00
|
|
|
}
|
2012-10-12 09:43:40 +08:00
|
|
|
|
2012-10-10 05:59:16 +08:00
|
|
|
private:
|
|
|
|
|
|
|
|
jsval jsSchedule;
|
|
|
|
jsval jsThisObj;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-08-28 10:22:36 +08:00
|
|
|
class JSTouchDelegate: public CCTouchDelegate, public CCNode {
|
|
|
|
public:
|
|
|
|
void setJSObject(JSObject *obj);
|
|
|
|
void registerStandardDelegate();
|
|
|
|
void registerTargettedDelegate(int priority, bool swallowsTouches);
|
|
|
|
|
|
|
|
bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) {
|
|
|
|
CC_UNUSED_PARAM(pTouch);
|
|
|
|
CC_UNUSED_PARAM(pEvent);
|
|
|
|
jsval retval;
|
|
|
|
ScriptingCore::getInstance()->executeCustomTouchEvent(CCTOUCHBEGAN,
|
|
|
|
pTouch, _mObj, retval);
|
|
|
|
if(JSVAL_IS_BOOLEAN(retval)) {
|
|
|
|
return JSVAL_TO_BOOLEAN(retval);
|
|
|
|
} return false;
|
|
|
|
};
|
|
|
|
// optional
|
|
|
|
|
|
|
|
void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) {
|
|
|
|
CC_UNUSED_PARAM(pTouch);
|
|
|
|
CC_UNUSED_PARAM(pEvent);
|
2012-09-24 13:57:45 +08:00
|
|
|
//jsval retval;
|
2012-08-28 10:22:36 +08:00
|
|
|
ScriptingCore::getInstance()->executeCustomTouchEvent(CCTOUCHMOVED,
|
|
|
|
pTouch, _mObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {
|
|
|
|
CC_UNUSED_PARAM(pTouch);
|
|
|
|
CC_UNUSED_PARAM(pEvent);
|
|
|
|
ScriptingCore::getInstance()->executeCustomTouchEvent(CCTOUCHENDED,
|
|
|
|
pTouch, _mObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent) {
|
|
|
|
CC_UNUSED_PARAM(pTouch);
|
|
|
|
CC_UNUSED_PARAM(pEvent);
|
|
|
|
ScriptingCore::getInstance()->executeCustomTouchEvent(CCTOUCHCANCELLED,
|
|
|
|
pTouch, _mObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
// optional
|
|
|
|
void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent) {
|
|
|
|
CC_UNUSED_PARAM(pTouches);
|
|
|
|
CC_UNUSED_PARAM(pEvent);
|
|
|
|
ScriptingCore::getInstance()->executeCustomTouchesEvent(CCTOUCHBEGAN,
|
|
|
|
pTouches, _mObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent) {
|
|
|
|
CC_UNUSED_PARAM(pTouches);
|
|
|
|
CC_UNUSED_PARAM(pEvent);
|
|
|
|
ScriptingCore::getInstance()->executeCustomTouchesEvent(CCTOUCHMOVED,
|
|
|
|
pTouches, _mObj);
|
|
|
|
}
|
|
|
|
void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent) {
|
|
|
|
CC_UNUSED_PARAM(pTouches);
|
|
|
|
CC_UNUSED_PARAM(pEvent);
|
|
|
|
ScriptingCore::getInstance()->executeCustomTouchesEvent(CCTOUCHENDED,
|
|
|
|
pTouches, _mObj);
|
|
|
|
}
|
|
|
|
void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent) {
|
|
|
|
CC_UNUSED_PARAM(pTouches);
|
|
|
|
CC_UNUSED_PARAM(pEvent);
|
|
|
|
ScriptingCore::getInstance()->executeCustomTouchesEvent(CCTOUCHCANCELLED,
|
|
|
|
pTouches, _mObj);
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
JSObject *_mObj;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|