2015-05-05 10:50:19 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2012 Zynga Inc.
|
2018-01-29 16:25:32 +08:00
|
|
|
* Copyright (c) 2013-2016 Chukong Technologies Inc.
|
|
|
|
* Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
2015-05-05 10:50:19 +08:00
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __JS_COCOS2D_X_SPECIFICS_H__
|
|
|
|
#define __JS_COCOS2D_X_SPECIFICS_H__
|
|
|
|
|
2016-03-20 21:53:44 +08:00
|
|
|
#include "scripting/js-bindings/manual/ScriptingCore.h"
|
2016-04-18 15:09:21 +08:00
|
|
|
|
|
|
|
#include "2d/CCScene.h"
|
|
|
|
#include "2d/CCSprite.h"
|
|
|
|
#include "base/CCEventListenerTouch.h"
|
|
|
|
#include "base/CCRef.h"
|
|
|
|
#include "base/uthash.h"
|
2015-05-05 10:50:19 +08:00
|
|
|
#include "platform/CCSAXParser.h"
|
|
|
|
|
|
|
|
class JSScheduleWrapper;
|
|
|
|
|
2016-08-19 16:28:47 +08:00
|
|
|
namespace JSBinding
|
|
|
|
{
|
|
|
|
typedef cocos2d::Vector<cocos2d::Ref*> Array;
|
|
|
|
typedef cocos2d::Map<std::string, cocos2d::Ref*> Dictionary;
|
|
|
|
|
|
|
|
class DictionaryRef : public cocos2d::Ref
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Dictionary data;
|
|
|
|
};
|
|
|
|
|
|
|
|
class ArrayRef : public cocos2d::Ref
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Array data;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
// JSScheduleWrapper* --> Array* 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. :)
|
|
|
|
typedef struct jsScheduleFunc_proxy {
|
2015-11-25 14:32:19 +08:00
|
|
|
JSObject* jsfuncObj;
|
2016-08-19 16:28:47 +08:00
|
|
|
JSBinding::Array* targets;
|
2015-05-05 10:50:19 +08:00
|
|
|
UT_hash_handle hh;
|
|
|
|
} schedFunc_proxy_t;
|
|
|
|
|
|
|
|
typedef struct jsScheduleTarget_proxy {
|
2015-11-25 14:32:19 +08:00
|
|
|
JSObject* jsTargetObj;
|
2016-08-19 16:28:47 +08:00
|
|
|
JSBinding::Array* targets;
|
2015-05-05 10:50:19 +08:00
|
|
|
UT_hash_handle hh;
|
|
|
|
} schedTarget_proxy_t;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct jsCallFuncTarget_proxy {
|
|
|
|
void * ptr;
|
2016-08-19 16:28:47 +08:00
|
|
|
JSBinding::Array* obj;
|
2015-05-05 10:50:19 +08:00
|
|
|
UT_hash_handle hh;
|
|
|
|
} callfuncTarget_proxy_t;
|
|
|
|
|
|
|
|
extern schedFunc_proxy_t *_schedFunc_target_ht;
|
|
|
|
extern schedTarget_proxy_t *_schedObj_target_ht;
|
|
|
|
extern callfuncTarget_proxy_t *_callfuncTarget_native_ht;
|
|
|
|
|
2016-12-21 13:39:34 +08:00
|
|
|
extern JSClass *jsb_RefFinalizeHook_class;
|
|
|
|
extern JSObject *jsb_RefFinalizeHook_prototype;
|
|
|
|
extern JSClass *jsb_ObjFinalizeHook_class;
|
|
|
|
extern JSObject *jsb_ObjFinalizeHook_prototype;
|
2015-12-17 21:53:40 +08:00
|
|
|
|
2015-05-05 10:50:19 +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) {
|
|
|
|
bool found = false;
|
|
|
|
std::string typeName = typeid(*native_obj).name();
|
|
|
|
auto typeProxyIter = _js_global_type_map.find(typeName);
|
|
|
|
if (typeProxyIter == _js_global_type_map.end())
|
|
|
|
{
|
|
|
|
typeName = typeid(T).name();
|
|
|
|
typeProxyIter = _js_global_type_map.find(typeName);
|
|
|
|
if (typeProxyIter != _js_global_type_map.end())
|
|
|
|
{
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
return found ? typeProxyIter->second : nullptr;
|
|
|
|
}
|
|
|
|
|
2016-02-25 09:47:19 +08:00
|
|
|
/**
|
|
|
|
* get type from a cocos2d::Node, call function(js_get_type_from_native) above.
|
|
|
|
*/
|
|
|
|
CC_JS_DLL js_type_class_t *js_get_type_from_node(cocos2d::Node* native_obj);
|
|
|
|
|
2015-12-08 11:05:23 +08:00
|
|
|
/**
|
|
|
|
* Gets or creates a JSObject based on native_obj.
|
2015-12-17 21:53:40 +08:00
|
|
|
* If native_obj is subclass of Ref, it will use the jsb_ref functions.
|
|
|
|
* Otherwise it will Root the newly created JSObject
|
2015-12-08 11:05:23 +08:00
|
|
|
*/
|
|
|
|
template<class T>
|
|
|
|
JSObject* js_get_or_create_jsobject(JSContext *cx, typename std::enable_if<!std::is_base_of<cocos2d::Ref,T>::value,T>::type *native_obj)
|
|
|
|
{
|
2015-12-17 21:53:40 +08:00
|
|
|
js_type_class_t* typeClass = js_get_type_from_native<T>(native_obj);
|
|
|
|
return jsb_get_or_create_weak_jsobject(cx, native_obj, typeClass, typeid(*native_obj).name());
|
2015-12-08 11:05:23 +08:00
|
|
|
}
|
|
|
|
|
2015-12-08 11:14:10 +08:00
|
|
|
/**
|
|
|
|
* Gets or creates a JSObject based on native_obj.
|
2015-12-17 21:53:40 +08:00
|
|
|
* If native_obj is subclass of Ref, it will use the jsb_ref functions.
|
|
|
|
* Otherwise it will Root the newly created JSObject
|
2015-12-08 11:14:10 +08:00
|
|
|
*/
|
2015-12-08 11:05:23 +08:00
|
|
|
template<class T>
|
|
|
|
JSObject* js_get_or_create_jsobject(JSContext *cx, typename std::enable_if<std::is_base_of<cocos2d::Ref,T>::value,T>::type *native_obj)
|
|
|
|
{
|
|
|
|
js_type_class_t* typeClass = js_get_type_from_native<T>(native_obj);
|
2015-12-11 14:15:44 +08:00
|
|
|
return jsb_ref_get_or_create_jsobject(cx, native_obj, typeClass, typeid(*native_obj).name());
|
2015-12-08 11:05:23 +08:00
|
|
|
}
|
|
|
|
|
2015-12-17 21:53:40 +08:00
|
|
|
/**
|
|
|
|
* Add a FinalizeHook object to the target object.
|
|
|
|
* When the target object get garbage collected, its FinalizeHook's finalize function will be invoked.
|
|
|
|
* In the finalize function, it mainly remove native/js proxys, release/delete the native object.
|
|
|
|
* IMPORTANT: For Ref objects, please remember to retain the native object to correctly manage its reference count.
|
|
|
|
*/
|
2016-12-21 13:39:34 +08:00
|
|
|
void js_add_FinalizeHook(JSContext *cx, JS::HandleObject target, bool isRef=true);
|
2015-12-17 21:53:40 +08:00
|
|
|
|
2016-01-24 19:40:44 +08:00
|
|
|
void js_add_object_reference(JS::HandleValue owner, JS::HandleValue target);
|
|
|
|
void js_remove_object_reference(JS::HandleValue owner, JS::HandleValue target);
|
|
|
|
void js_add_object_root(JS::HandleValue target);
|
|
|
|
void js_remove_object_root(JS::HandleValue target);
|
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
JS::Value anonEvaluate(JSContext *cx, JS::HandleObject thisObj, const char* string);
|
|
|
|
void register_cocos2dx_js_core(JSContext* cx, JS::HandleObject obj);
|
|
|
|
|
|
|
|
|
|
|
|
class JSCallbackWrapper: public cocos2d::Ref {
|
|
|
|
public:
|
|
|
|
JSCallbackWrapper();
|
|
|
|
virtual ~JSCallbackWrapper();
|
2018-01-10 14:39:45 +08:00
|
|
|
|
2015-10-22 17:00:57 +08:00
|
|
|
void setJSCallbackFunc(JS::HandleValue callback);
|
|
|
|
void setJSCallbackThis(JS::HandleValue thisObj);
|
|
|
|
void setJSExtraData(JS::HandleValue data);
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-10-22 17:00:57 +08:00
|
|
|
const jsval getJSCallbackFunc() const;
|
|
|
|
const jsval getJSCallbackThis() const;
|
|
|
|
const jsval getJSExtraData() const;
|
2015-05-05 10:50:19 +08:00
|
|
|
protected:
|
2018-01-10 14:39:45 +08:00
|
|
|
JS::PersistentRootedValue* _jsCallback;
|
|
|
|
JS::PersistentRootedValue* _jsThisObj;
|
|
|
|
JS::PersistentRootedValue* _extraData;
|
2015-05-05 10:50:19 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-01-10 14:39:45 +08:00
|
|
|
class JSScheduleWrapper: public JSCallbackWrapper
|
|
|
|
{
|
2015-05-05 10:50:19 +08:00
|
|
|
public:
|
2015-10-22 17:00:57 +08:00
|
|
|
JSScheduleWrapper();
|
2018-01-10 14:39:45 +08:00
|
|
|
virtual ~JSScheduleWrapper();
|
2015-05-05 10:50:19 +08:00
|
|
|
|
|
|
|
static void setTargetForSchedule(JS::HandleValue sched, JSScheduleWrapper *target);
|
2016-08-19 16:28:47 +08:00
|
|
|
static JSBinding::Array* getTargetForSchedule(JS::HandleValue sched);
|
2015-05-05 10:50:19 +08:00
|
|
|
static void setTargetForJSObject(JS::HandleObject jsTargetObj, JSScheduleWrapper *target);
|
2016-08-19 16:28:47 +08:00
|
|
|
static JSBinding::Array* getTargetForJSObject(JS::HandleObject jsTargetObj);
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
// Remove all targets.
|
|
|
|
static void removeAllTargets();
|
|
|
|
// Remove all targets for priority.
|
|
|
|
static void removeAllTargetsForMinPriority(int minPriority);
|
2016-04-18 15:09:21 +08:00
|
|
|
// Remove all targets by js object from hash table(_schedFunc_target_ht and _schedObj_target_ht).
|
2015-05-05 10:50:19 +08:00
|
|
|
static void removeAllTargetsForJSObject(JS::HandleObject jsTargetObj);
|
|
|
|
// Remove the target by js object and the wrapper for native schedule.
|
|
|
|
static void removeTargetForJSObject(JS::HandleObject jsTargetObj, JSScheduleWrapper* target);
|
|
|
|
static void dump();
|
|
|
|
|
|
|
|
void pause();
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
void scheduleFunc(float dt);
|
|
|
|
void update(float dt);
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
Ref* getTarget();
|
|
|
|
void setTarget(Ref* pTarget);
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
void setPureJSTarget(JS::HandleObject jstarget);
|
|
|
|
JSObject* getPureJSTarget();
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
void setPriority(int priority);
|
|
|
|
int getPriority();
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
void setUpdateSchedule(bool isUpdateSchedule);
|
|
|
|
bool isUpdateSchedule();
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
protected:
|
|
|
|
Ref* _pTarget;
|
2018-01-10 14:39:45 +08:00
|
|
|
JS::PersistentRootedObject* _pPureJSTarget;
|
2015-05-05 10:50:19 +08:00
|
|
|
int _priority;
|
|
|
|
bool _isUpdateSchedule;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class JSTouchDelegate: public cocos2d::Ref
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
JSTouchDelegate();
|
|
|
|
~JSTouchDelegate();
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
// 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);
|
|
|
|
|
2015-10-28 11:55:28 +08:00
|
|
|
void setJSObject(JS::HandleObject obj);
|
2015-05-05 10:50:19 +08:00
|
|
|
void registerStandardDelegate(int priority);
|
|
|
|
void registerTargetedDelegate(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 onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *event);
|
|
|
|
void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *event);
|
|
|
|
void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *event);
|
|
|
|
void onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *event);
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
// optional
|
|
|
|
void onTouchesBegan(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event);
|
|
|
|
void onTouchesMoved(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event);
|
|
|
|
void onTouchesEnded(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event);
|
|
|
|
void onTouchesCancelled(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event);
|
|
|
|
|
|
|
|
private:
|
2016-01-28 01:03:13 +08:00
|
|
|
JS::Heap<JSObject*> _obj;
|
2015-05-05 10:50:19 +08:00
|
|
|
typedef std::unordered_map<JSObject*, JSTouchDelegate*> TouchDelegateMap;
|
|
|
|
typedef std::pair<JSObject*, JSTouchDelegate*> TouchDelegatePair;
|
|
|
|
static TouchDelegateMap sTouchDelegateMap;
|
|
|
|
cocos2d::EventListenerTouchOneByOne* _touchListenerOneByOne;
|
|
|
|
cocos2d::EventListenerTouchAllAtOnce* _touchListenerAllAtOnce;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class __JSPlistDelegator: public cocos2d::SAXDelegator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static __JSPlistDelegator* getInstance() {
|
|
|
|
static __JSPlistDelegator* pInstance = NULL;
|
|
|
|
if (pInstance == NULL) {
|
2015-12-16 17:06:56 +08:00
|
|
|
pInstance = new (std::nothrow) __JSPlistDelegator();
|
2015-05-05 10:50:19 +08:00
|
|
|
}
|
|
|
|
return pInstance;
|
|
|
|
};
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
~__JSPlistDelegator();
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
cocos2d::SAXParser* getParser();
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
std::string parse(const std::string& path);
|
|
|
|
std::string parseText(const std::string& text);
|
2016-04-18 15:09:21 +08:00
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
// implement pure virtual methods of SAXDelegator
|
2016-09-26 14:49:47 +08:00
|
|
|
void startElement(void *ctx, const char *name, const char **atts) override;
|
|
|
|
void endElement(void *ctx, const char *name) override;
|
|
|
|
void textHandler(void *ctx, const char *ch, size_t len) override;
|
2015-05-05 10:50:19 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
cocos2d::SAXParser _parser;
|
|
|
|
std::string _result;
|
|
|
|
bool _isStoringCharacters;
|
|
|
|
std::string _currentValue;
|
|
|
|
};
|
|
|
|
|
|
|
|
bool js_cocos2dx_Node_onEnter(JSContext *cx, uint32_t argc, jsval *vp);
|
|
|
|
bool js_cocos2dx_Node_onExit(JSContext *cx, uint32_t argc, jsval *vp);
|
|
|
|
bool js_cocos2dx_Node_onEnterTransitionDidFinish(JSContext *cx, uint32_t argc, jsval *vp);
|
|
|
|
bool js_cocos2dx_Node_onExitTransitionDidStart(JSContext *cx, uint32_t argc, jsval *vp);
|
2015-07-16 14:09:26 +08:00
|
|
|
bool js_cocos2dx_Node_cleanup(JSContext *cx, uint32_t argc, jsval *vp);
|
2015-05-05 10:50:19 +08:00
|
|
|
bool js_cocos2dx_Component_onEnter(JSContext *cx, uint32_t argc, jsval *vp);
|
|
|
|
bool js_cocos2dx_Component_onExit(JSContext *cx, uint32_t argc, jsval *vp);
|
|
|
|
|
2015-07-03 12:55:55 +08:00
|
|
|
bool js_cocos2dx_retain(JSContext *cx, uint32_t argc, jsval *vp);
|
|
|
|
bool js_cocos2dx_release(JSContext *cx, uint32_t argc, jsval *vp);
|
|
|
|
|
2015-05-05 10:50:19 +08:00
|
|
|
void get_or_create_js_obj(JSContext* cx, JS::HandleObject obj, const std::string &name, JS::MutableHandleObject jsObj);
|
2016-01-24 19:40:44 +08:00
|
|
|
void get_or_create_js_obj(const std::string &name, JS::MutableHandleObject jsObj);
|
2015-05-05 10:50:19 +08:00
|
|
|
|
|
|
|
#endif
|