zoukankan      html  css  js  c++  java
  • 2dx关于js响应layer触摸消息的bug

    cocos2dx关于js响应layer触摸消息的bug

    cocos2d-x 3.7


    问题描述:

    目前这个版本中(3.7),c++层的layer触摸消息只能通过消息的方式发送给js,不能像lua一样直接回调js注册的触摸回调接口,为了方便,我们更改一下layer类的onTouchBegan/onTouchMove...等接口,使其支持在layer的触摸响应中直接回调js接口。
    具体实现见:http://www.cnblogs.com/songcf/p/4764444.html


    ok,在这之后就会发现ScriptingCore中有一个触摸响应判断的bug:
    只要c++对js的ontouchbegan函数调用成功,都会被视为当前layer捕捉到了该触摸(即return true)
    如果该layer开启了吞噬触摸,那么此次touch永远被该layer捕获,不再传递下去,即使你在js层中注册的onTouchBegan是return false,也无济于事。
    那么造成该bug的原因如下:

    //Layer判断是否捕获该touch,取决于executeScriptTouchHandler函数调用的返回值
    bool Layer::onTouchBegan(Touch *touch, Event *event)
    {
    #if CC_ENABLE_SCRIPT_BINDING
        if (kScriptTypeNone != _scriptType)
        {
            return executeScriptTouchHandler(EventTouch::EventCode::BEGAN, touch, event) == 0 ? false : true;
        }
    #endif
        CC_UNUSED_PARAM(event);
        CCASSERT(false, "Layer#ccTouchBegan override me");
        return true;
    }
    
    //再来看看executeScriptTouchHandler的返回值,取决于ScriptingCore::sendEvent
    int Layer::executeScriptTouchHandler(EventTouch::EventCode eventType, Touch* touch, Event* event)
    {
    #if CC_ENABLE_SCRIPT_BINDING
        if (kScriptTypeNone != _scriptType)
        {
            TouchScriptData data(eventType, this, touch, event);
            ScriptEvent scriptEvent(kTouchEvent, &data);
            return ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&scriptEvent);
        }
    #endif
        //can not reach it
        return 0;
    }
    
    //再看sendEvent中发送触摸消息的代码
    //这里可以看出layer是否捕获触摸取决于handleTouchEvent的返回值
    int ScriptingCore::sendEvent(ScriptEvent* evt)
    {
    	//......
            case kTouchEvent:
                {
                    TouchScriptData* data = (TouchScriptData*)evt->data;
                    return handleTouchEvent(data->nativeObject, data->actionType, data->touch, data->event);
                }
                break;
            case kTouchesEvent:
                {
                    TouchesScriptData* data = (TouchesScriptData*)evt->data;
                    return handleTouchesEvent(data->nativeObject, data->actionType, data->touches, data->event);
                }
                break;
    	//......
    }
    
    //你可以继续往下跟进去就会知道,最终返回的值到底是什么
    
    

    没错!如你所见,最后的返回值是JS_CallFunctionName是否调用成功,即这里c++调用js的onTouchBegan函数是否成功
    只要调用成功,touch就会被该layer捕获!跟onTouchBegan的返回值没半毛钱关系。那么正确的返回值应该是js端onTouchBegan的返回值。

    解决方案:

    修改ScriptingCorehandleTouchEvent/handleTouchesEvent两个接口,让它们的返回值为js端onTouchBegan的返回值:

    bool ScriptingCore::handleTouchEvent(void* nativeObj, cocos2d::EventTouch::EventCode eventCode, cocos2d::Touch* touch, cocos2d::Event* event)
    {
        JS::RootedValue ret(_cx);
        if (handleTouchEvent(nativeObj, eventCode, touch, event, &ret)){
    		return JS::ToBoolean(ret);
    	}
    	else {
    		return false;
    	}
    }
    
    bool ScriptingCore::handleTouchesEvent(void* nativeObj, cocos2d::EventTouch::EventCode eventCode, const std::vector<cocos2d::Touch*>& touches, cocos2d::Event* event)
    {
    	JS::RootedValue ret(_cx);
    	if (handleTouchesEvent(nativeObj, eventCode, touches, event, &ret)){
    		return JS::ToBoolean(ret);
    	}
    	else {
    		return false;
    	}
    }
    

    其实我不太明白官方为什么在layer的触摸响应中,只用c++回调lua接口,而js使用发消息的方式(不用c++回调js接口),性能?!

  • 相关阅读:
    POJ 1703 Find them, Catch them (数据结构-并查集)
    ProductHunt:创业公司产品猎场和秀场
    firedac数据集控件的公共祖先类——TFDAdaptedDataSet
    IDFTP连不上FTP服务器的解决方法
    SQLServer到底支持多少连接数的并发?
    日志
    权限
    DATASNAP中间件调用带OUTPUT参数的存储过程
    连接池中的连接超过数据库端的最大空闲时间
    firedac的TFDStoredProc动态创建并调用存储过程
  • 原文地址:https://www.cnblogs.com/songcf/p/4765452.html
Copyright © 2011-2022 走看看