#include "CCEGLViewProtocol.h" #include "touch_dispatcher/CCTouchDispatcher.h" #include "touch_dispatcher/CCTouch.h" #include "CCDirector.h" #include "cocoa/CCSet.h" #include "cocoa/CCDictionary.h" #include "cocoa/CCInteger.h" NS_CC_BEGIN static CCTouch* s_pTouches[CC_MAX_TOUCHES] = { NULL }; static unsigned int s_indexBitsUsed = 0; static CCDictionary s_TouchesIntergerDict; static int getUnUsedIndex() { int i; int temp = s_indexBitsUsed; for (i = 0; i < CC_MAX_TOUCHES; i++) { if (! (temp & 0x00000001)) { s_indexBitsUsed |= (1 << i); return i; } temp >>= 1; } // all bits are used return -1; } static void removeUsedIndexBit(int index) { if (index < 0 || index >= CC_MAX_TOUCHES) { return; } unsigned int temp = 1 << index; temp = ~temp; s_indexBitsUsed &= temp; } CCEGLViewProtocol::CCEGLViewProtocol() : _delegate(NULL) , _scaleX(1.0f) , _scaleY(1.0f) , _resolutionPolicy(kResolutionUnKnown) { } CCEGLViewProtocol::~CCEGLViewProtocol() { } void CCEGLViewProtocol::setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy) { CCAssert(resolutionPolicy != kResolutionUnKnown, "should set resolutionPolicy"); if (width == 0.0f || height == 0.0f) { return; } _designResolutionSize.setSize(width, height); _scaleX = (float)_screenSize.width / _designResolutionSize.width; _scaleY = (float)_screenSize.height / _designResolutionSize.height; if (resolutionPolicy == kResolutionNoBorder) { _scaleX = _scaleY = MAX(_scaleX, _scaleY); } if (resolutionPolicy == kResolutionShowAll) { _scaleX = _scaleY = MIN(_scaleX, _scaleY); } if ( resolutionPolicy == kResolutionFixedHeight) { _scaleX = _scaleY; _designResolutionSize.width = ceilf(_screenSize.width/_scaleX); } if ( resolutionPolicy == kResolutionFixedWidth) { _scaleY = _scaleX; _designResolutionSize.height = ceilf(_screenSize.height/_scaleY); } // calculate the rect of viewport float viewPortW = _designResolutionSize.width * _scaleX; float viewPortH = _designResolutionSize.height * _scaleY; _viewPortRect.setRect((_screenSize.width - viewPortW) / 2, (_screenSize.height - viewPortH) / 2, viewPortW, viewPortH); _resolutionPolicy = resolutionPolicy; // reset director's member variables to fit visible rect CCDirector::sharedDirector()->_winSizeInPoints = getDesignResolutionSize(); CCDirector::sharedDirector()->createStatsLabel(); CCDirector::sharedDirector()->setGLDefaultValues(); } const CCSize& CCEGLViewProtocol::getDesignResolutionSize() const { return _designResolutionSize; } const CCSize& CCEGLViewProtocol::getFrameSize() const { return _screenSize; } void CCEGLViewProtocol::setFrameSize(float width, float height) { _designResolutionSize = _screenSize = CCSizeMake(width, height); } CCSize CCEGLViewProtocol::getVisibleSize() const { if (_resolutionPolicy == kResolutionNoBorder) { return CCSizeMake(_screenSize.width/_scaleX, _screenSize.height/_scaleY); } else { return _designResolutionSize; } } CCPoint CCEGLViewProtocol::getVisibleOrigin() const { if (_resolutionPolicy == kResolutionNoBorder) { return CCPointMake((_designResolutionSize.width - _screenSize.width/_scaleX)/2, (_designResolutionSize.height - _screenSize.height/_scaleY)/2); } else { return CCPointZero; } } void CCEGLViewProtocol::setTouchDelegate(EGLTouchDelegate * pDelegate) { _delegate = pDelegate; } void CCEGLViewProtocol::setViewPortInPoints(float x , float y , float w , float h) { glViewport((GLint)(x * _scaleX + _viewPortRect.origin.x), (GLint)(y * _scaleY + _viewPortRect.origin.y), (GLsizei)(w * _scaleX), (GLsizei)(h * _scaleY)); } void CCEGLViewProtocol::setScissorInPoints(float x , float y , float w , float h) { glScissor((GLint)(x * _scaleX + _viewPortRect.origin.x), (GLint)(y * _scaleY + _viewPortRect.origin.y), (GLsizei)(w * _scaleX), (GLsizei)(h * _scaleY)); } bool CCEGLViewProtocol::isScissorEnabled() { return (GL_FALSE == glIsEnabled(GL_SCISSOR_TEST)) ? false : true; } CCRect CCEGLViewProtocol::getScissorRect() { GLfloat params[4]; glGetFloatv(GL_SCISSOR_BOX, params); float x = (params[0] - _viewPortRect.origin.x) / _scaleX; float y = (params[1] - _viewPortRect.origin.y) / _scaleY; float w = params[2] / _scaleX; float h = params[3] / _scaleY; return CCRectMake(x, y, w, h); } void CCEGLViewProtocol::setViewName(const char* pszViewName) { if (pszViewName != NULL && strlen(pszViewName) > 0) { strncpy(_viewName, pszViewName, sizeof(_viewName)); } } const char* CCEGLViewProtocol::getViewName() { return _viewName; } void CCEGLViewProtocol::handleTouchesBegin(int num, int ids[], float xs[], float ys[]) { CCSet set; for (int i = 0; i < num; ++i) { int id = ids[i]; float x = xs[i]; float y = ys[i]; CCInteger* pIndex = (CCInteger*)s_TouchesIntergerDict.objectForKey(id); int nUnusedIndex = 0; // it is a new touch if (pIndex == NULL) { nUnusedIndex = getUnUsedIndex(); // The touches is more than MAX_TOUCHES ? if (nUnusedIndex == -1) { CCLOG("The touches is more than MAX_TOUCHES, nUnusedIndex = %d", nUnusedIndex); continue; } CCTouch* pTouch = s_pTouches[nUnusedIndex] = new CCTouch(); pTouch->setTouchInfo(nUnusedIndex, (x - _viewPortRect.origin.x) / _scaleX, (y - _viewPortRect.origin.y) / _scaleY); //CCLOG("x = %f y = %f", pTouch->getLocationInView().x, pTouch->getLocationInView().y); CCInteger* pInterObj = new CCInteger(nUnusedIndex); s_TouchesIntergerDict.setObject(pInterObj, id); set.addObject(pTouch); pInterObj->release(); } } if (set.count() == 0) { CCLOG("touchesBegan: count = 0"); return; } _delegate->touchesBegan(&set, NULL); } void CCEGLViewProtocol::handleTouchesMove(int num, int ids[], float xs[], float ys[]) { CCSet set; for (int i = 0; i < num; ++i) { int id = ids[i]; float x = xs[i]; float y = ys[i]; CCInteger* pIndex = (CCInteger*)s_TouchesIntergerDict.objectForKey(id); if (pIndex == NULL) { CCLOG("if the index doesn't exist, it is an error"); continue; } CCLOGINFO("Moving touches with id: %d, x=%f, y=%f", id, x, y); CCTouch* pTouch = s_pTouches[pIndex->getValue()]; if (pTouch) { pTouch->setTouchInfo(pIndex->getValue(), (x - _viewPortRect.origin.x) / _scaleX, (y - _viewPortRect.origin.y) / _scaleY); set.addObject(pTouch); } else { // It is error, should return. CCLOG("Moving touches with id: %d error", id); return; } } if (set.count() == 0) { CCLOG("touchesMoved: count = 0"); return; } _delegate->touchesMoved(&set, NULL); } void CCEGLViewProtocol::getSetOfTouchesEndOrCancel(CCSet& set, int num, int ids[], float xs[], float ys[]) { for (int i = 0; i < num; ++i) { int id = ids[i]; float x = xs[i]; float y = ys[i]; CCInteger* pIndex = (CCInteger*)s_TouchesIntergerDict.objectForKey(id); if (pIndex == NULL) { CCLOG("if the index doesn't exist, it is an error"); continue; } /* Add to the set to send to the director */ CCTouch* pTouch = s_pTouches[pIndex->getValue()]; if (pTouch) { CCLOGINFO("Ending touches with id: %d, x=%f, y=%f", id, x, y); pTouch->setTouchInfo(pIndex->getValue(), (x - _viewPortRect.origin.x) / _scaleX, (y - _viewPortRect.origin.y) / _scaleY); set.addObject(pTouch); // release the object pTouch->release(); s_pTouches[pIndex->getValue()] = NULL; removeUsedIndexBit(pIndex->getValue()); s_TouchesIntergerDict.removeObjectForKey(id); } else { CCLOG("Ending touches with id: %d error", id); return; } } if (set.count() == 0) { CCLOG("touchesEnded or touchesCancel: count = 0"); return; } } void CCEGLViewProtocol::handleTouchesEnd(int num, int ids[], float xs[], float ys[]) { CCSet set; getSetOfTouchesEndOrCancel(set, num, ids, xs, ys); _delegate->touchesEnded(&set, NULL); } void CCEGLViewProtocol::handleTouchesCancel(int num, int ids[], float xs[], float ys[]) { CCSet set; getSetOfTouchesEndOrCancel(set, num, ids, xs, ys); _delegate->touchesCancelled(&set, NULL); } const CCRect& CCEGLViewProtocol::getViewPortRect() const { return _viewPortRect; } float CCEGLViewProtocol::getScaleX() const { return _scaleX; } float CCEGLViewProtocol::getScaleY() const { return _scaleY; } NS_CC_END