123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617 |
- /****************************************************************************
- Copyright (c) 2012 cocos2d-x.org
- Copyright (c) 2010 Sangwoo Im
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
- #include "CCScrollViewSmooth.h"
- #include "platform/CCDevice.h"
- #include "2d/CCActionInstant.h"
- #include "2d/CCActionInterval.h"
- #include "2d/CCActionTween.h"
- #include "base/CCDirector.h"
- #include "base/CCEventDispatcher.h"
- #include "renderer/CCRenderer.h"
- #include "base/ccUtils.h"
- #include "2d/CCTweenFunction.h"
- #include <algorithm>
- NS_CC_EXT_BEGIN
- #define SCROLL_DEACCEL_RATE 0.95f
- #define SCROLL_DEACCEL_DIST 1.0f
- #define BOUNCE_DURATION 0.15f
- #define INSET_RATIO 0.2f
- #define MOVE_INCH 7.0f/160.0f
- #define BOUNCE_BACK_FACTOR 0.35f
- //zg
- #define TURN_PAGE_SPEED 0.20f //designPixl/ms
- #define INVALID_PAGE 0xfff
- #define TURN_PAGE_MIN_OFFSET_RATIO 0.1f
- static float convertDistanceFromPointToInch(float pointDis)
- {
- auto glview = Director::getInstance()->getOpenGLView();
- float factor = ( glview->getScaleX() + glview->getScaleY() ) / 2;
- return pointDis * factor / Device::getDPI();
- }
- ScrollViewSmooth::ScrollViewSmooth()
- : _delegate(nullptr)
- , _direction(Direction::BOTH)
- , _dragging(false)
- , _container(nullptr)
- , _touchMoved(false)
- , _bounceable(false)
- , _clippingToBounds(false)
- , _touchLength(0.0f)
- , _minScale(0.0f)
- , _maxScale(0.0f)
- , _scissorRestored(false)
- , _touchListener(nullptr)
- , _animatedScrollAction(nullptr)
- ,_autoScrollCurrentlyOutOfBoundary(false)
- ,_autoScrollBraking(false)
- // zg
- , m_bPaged(false)
- , m_currPage(0)
- , m_targetPage(INVALID_PAGE)
- , m_touchBeganTime(0)
- , m_touchBeganOffset(0)
- , m_pageAdjustSize(Size::ZERO)
- , m_bIsScrollingPaused(false)
- // zml
- , _isInterceptTouch(false)
- , _bePressed(false)
- , _autoScrolling(false)
- , _autoScrollTotalTime(0)
- , _autoScrollAccumulatedTime(0)
- , _touchMovePreviousTimestamp(0)
- {
- }
- ScrollViewSmooth::~ScrollViewSmooth()
- {
- }
- ScrollViewSmooth* ScrollViewSmooth::create(Size size, Node* container/* = nullptr*/)
- {
- ScrollViewSmooth* pRet = new (std::nothrow) ScrollViewSmooth();
- if (pRet && pRet->initWithViewSize(size, container))
- {
- pRet->autorelease();
- }
- else
- {
- CC_SAFE_DELETE(pRet);
- }
- return pRet;
- }
- ScrollViewSmooth* ScrollViewSmooth::create()
- {
- ScrollViewSmooth* pRet = new (std::nothrow) ScrollViewSmooth();
- if (pRet && pRet->init())
- {
- pRet->autorelease();
- }
- else
- {
- CC_SAFE_DELETE(pRet);
- }
- return pRet;
- }
- bool ScrollViewSmooth::initWithViewSize(Size size, Node *container/* = nullptr*/)
- {
- if (Layer::init())
- {
- _container = container;
-
- if (!this->_container)
- {
- _container = Layer::create();
- _container->setIgnoreAnchorPointForPosition(false);
- _container->setAnchorPoint(Vec2(0.0f, 0.0f));
- }
- this->setViewSize(size);
- setTouchEnabled(true);
-
- _touches.reserve(EventTouch::MAX_TOUCHES);
-
- _delegate = nullptr;
- _bounceable = true;
- _clippingToBounds = true;
- //_container->setContentSize(Size::ZERO);
- _direction = Direction::BOTH;
- _container->setPosition(0.0f, 0.0f);
- _touchLength = 0.0f;
-
- this->addChild(_container);
- _minScale = _maxScale = 1.0f;
-
- return true;
- }
- return false;
- }
- bool ScrollViewSmooth::init()
- {
- return this->initWithViewSize(Size(200, 200), nullptr);
- }
- bool ScrollViewSmooth::isNodeVisible(Node* node)
- {
- const Vec2 offset = this->getContentOffset();
- const Size size = this->getViewSize();
- const float scale = this->getZoomScale();
-
- Rect viewRect;
-
- viewRect = Rect(-offset.x/scale, -offset.y/scale, size.width/scale, size.height/scale);
-
- return viewRect.intersectsRect(node->getBoundingBox());
- }
- void ScrollViewSmooth::pause(Ref* /*sender*/)
- {
- _container->pause();
- auto& children = _container->getChildren();
- for(const auto &child : children) {
- child->pause();
- }
- }
- void ScrollViewSmooth::resume(Ref* /*sender*/)
- {
- auto& children = _container->getChildren();
- for(const auto &child : children) {
- child->resume();
- }
- _container->resume();
- }
- bool ScrollViewSmooth::isTouchEnabled() const
- {
- return _touchListener != nullptr;
- }
- void ScrollViewSmooth::setTouchEnabled(bool enabled)
- {
- _eventDispatcher->removeEventListener(_touchListener);
- _touchListener = nullptr;
- if (enabled)
- {
- _touchListener = EventListenerTouchOneByOne::create();
- _touchListener->setSwallowTouches(true);
- _touchListener->onTouchBegan = CC_CALLBACK_2(ScrollViewSmooth::onTouchBegan, this);
- _touchListener->onTouchMoved = CC_CALLBACK_2(ScrollViewSmooth::onTouchMoved, this);
- _touchListener->onTouchEnded = CC_CALLBACK_2(ScrollViewSmooth::onTouchEnded, this);
- _touchListener->onTouchCancelled = CC_CALLBACK_2(ScrollViewSmooth::onTouchCancelled, this);
-
- _eventDispatcher->addEventListenerWithSceneGraphPriority(_touchListener, this);
- }
- else
- {
- _dragging = false;
- _touchMoved = false;
- _touches.clear();
- }
- }
- void ScrollViewSmooth::setContentOffset(Vec2 offset, bool animated/* = false*/)
- {
- if (animated)
- { //animate scrolling
- this->setContentOffsetInDuration(offset, BOUNCE_DURATION);
- }
- else
- { //set the container position directly
- if (!_bounceable)
- {
- const Vec2 minOffset = this->minContainerOffset();
- const Vec2 maxOffset = this->maxContainerOffset();
-
- offset.x = MAX(minOffset.x, MIN(maxOffset.x, offset.x));
- offset.y = MAX(minOffset.y, MIN(maxOffset.y, offset.y));
- }
- _container->setPosition(offset);
- if (_delegate != nullptr)
- {
- _delegate->scrollViewDidScroll(this);
- }
- }
- }
- void ScrollViewSmooth::setContentOffsetInDuration(Vec2 offset, float dt)
- {
- FiniteTimeAction *scroll, *expire;
-
- if (_animatedScrollAction) {
- stopAnimatedContentOffset();
- }
- scroll = MoveTo::create(dt, offset);
- expire = CallFuncN::create(CC_CALLBACK_1(ScrollViewSmooth::stoppedAnimatedScroll,this));
- _animatedScrollAction = _container->runAction(Sequence::create(scroll, expire, nullptr));
- _animatedScrollAction->retain();
- this->schedule(CC_SCHEDULE_SELECTOR(ScrollViewSmooth::performedAnimatedScroll));
- }
- void ScrollViewSmooth::stopAnimatedContentOffset() {
- stopAction(_animatedScrollAction);
- _animatedScrollAction->release();
- _animatedScrollAction = nullptr;
- stoppedAnimatedScroll(this);
- }
- Vec2 ScrollViewSmooth::getContentOffset()
- {
- return _container->getPosition();
- }
- void ScrollViewSmooth::setZoomScale(float s)
- {
- if (_container->getScale() != s)
- {
- Vec2 oldCenter, newCenter;
- Vec2 center;
-
- if (_touchLength == 0.0f)
- {
- center.set(_viewSize.width*0.5f, _viewSize.height*0.5f);
- center = this->convertToWorldSpace(center);
- }
- else
- {
- center = _touchPoint;
- }
-
- oldCenter = _container->convertToNodeSpace(center);
- _container->setScale(MAX(_minScale, MIN(_maxScale, s)));
- newCenter = _container->convertToWorldSpace(oldCenter);
-
- const Vec2 offset = center - newCenter;
- if (_delegate != nullptr)
- {
- _delegate->scrollViewDidZoom(this);
- }
- this->setContentOffset(_container->getPosition() + offset);
- }
- }
- float ScrollViewSmooth::getZoomScale()
- {
- return _container->getScale();
- }
- void ScrollViewSmooth::setZoomScale(float s, bool animated)
- {
- if (animated)
- {
- this->setZoomScaleInDuration(s, BOUNCE_DURATION);
- }
- else
- {
- this->setZoomScale(s);
- }
- }
- void ScrollViewSmooth::setZoomScaleInDuration(float s, float dt)
- {
- if (dt > 0)
- {
- if (_container->getScale() != s)
- {
- ActionTween *scaleAction;
- scaleAction = ActionTween::create(dt, "zoomScale", _container->getScale(), s);
- this->runAction(scaleAction);
- }
- }
- else
- {
- this->setZoomScale(s);
- }
- }
- void ScrollViewSmooth::updateTweenAction(float value, const std::string& /*key*/)
- {
- this->setZoomScale(value);
- }
- void ScrollViewSmooth::setViewSize(Size size)
- {
- _viewSize = size;
- Layer::setContentSize(size);
- }
- Node * ScrollViewSmooth::getContainer()
- {
- return this->_container;
- }
- void ScrollViewSmooth::setContainer(Node * pContainer)
- {
- // Make sure that '_container' has a non-nullptr value since there are
- // lots of logic that use '_container'.
- if (nullptr == pContainer)
- return;
- this->removeAllChildrenWithCleanup(true);
- this->_container = pContainer;
- this->_container->setIgnoreAnchorPointForPosition(false);
- this->_container->setAnchorPoint(Vec2(0.0f, 0.0f));
- this->addChild(this->_container);
- this->setViewSize(this->_viewSize);
- }
- bool ScrollViewSmooth::hasVisibleParents() const
- {
- auto parent = this->getParent();
- for( auto c = parent; c != nullptr; c = c->getParent() )
- {
- if( !c->isVisible() )
- {
- return false;
- }
- }
- return true;
- }
- void ScrollViewSmooth::relocateContainer(bool animated)
- {
- Vec2 oldPoint, min, max;
- float newX, newY;
-
- min = this->minContainerOffset();
- max = this->maxContainerOffset();
-
- oldPoint = _container->getPosition();
- newX = oldPoint.x;
- newY = oldPoint.y;
- if (_direction == Direction::BOTH || _direction == Direction::HORIZONTAL)
- {
- newX = MAX(newX, min.x);
- newX = MIN(newX, max.x);
- }
- if (_direction == Direction::BOTH || _direction == Direction::VERTICAL)
- {
- newY = MIN(newY, max.y);
- newY = MAX(newY, min.y);
- }
- if (newY != oldPoint.y || newX != oldPoint.x)
- {
- this->setContentOffset(Vec2(newX, newY), animated);
- }
- }
- Vec2 ScrollViewSmooth::maxContainerOffset()
- {
- Point anchorPoint = _container->isIgnoreAnchorPointForPosition()?Point::ZERO:_container->getAnchorPoint();
- float contW = _container->getContentSize().width * _container->getScaleX();
- float contH = _container->getContentSize().height * _container->getScaleY();
-
- return Vec2(anchorPoint.x * contW, anchorPoint.y * contH);
- }
- Vec2 ScrollViewSmooth::minContainerOffset()
- {
- Point anchorPoint = _container->isIgnoreAnchorPointForPosition()?Point::ZERO:_container->getAnchorPoint();
- float contW = _container->getContentSize().width * _container->getScaleX();
- float contH = _container->getContentSize().height * _container->getScaleY();
-
- return Vec2(_viewSize.width - (1 - anchorPoint.x) * contW, _viewSize.height - (1 - anchorPoint.y) * contH);
- }
- void ScrollViewSmooth::deaccelerateScrolling(float /*dt*/)
- {
- if (_dragging)
- {
- this->unschedule(CC_SCHEDULE_SELECTOR(ScrollViewSmooth::deaccelerateScrolling));
- return;
- }
-
- float newX, newY;
- Vec2 maxInset, minInset;
-
- _container->setPosition(_container->getPosition() + _scrollDistance);
-
- if (_bounceable)
- {
- maxInset = _maxInset;
- minInset = _minInset;
- }
- else
- {
- maxInset = this->maxContainerOffset();
- minInset = this->minContainerOffset();
- }
-
- newX = _container->getPosition().x;
- newY = _container->getPosition().y;
-
- _scrollDistance = _scrollDistance * SCROLL_DEACCEL_RATE;
- this->setContentOffset(Vec2(newX,newY));
-
- if ((fabsf(_scrollDistance.x) <= SCROLL_DEACCEL_DIST &&
- fabsf(_scrollDistance.y) <= SCROLL_DEACCEL_DIST) ||
- ((_direction == Direction::BOTH || _direction == Direction::VERTICAL) && (newY >= maxInset.y || newY <= minInset.y)) ||
- ((_direction == Direction::BOTH || _direction == Direction::HORIZONTAL) && (newX >= maxInset.x || newX <= minInset.x)))
- {
- this->unschedule(CC_SCHEDULE_SELECTOR(ScrollViewSmooth::deaccelerateScrolling));
- this->relocateContainer(true);
- }
- }
- void ScrollViewSmooth::stoppedAnimatedScroll(Node * /*node*/)
- {
- this->unschedule(CC_SCHEDULE_SELECTOR(ScrollViewSmooth::performedAnimatedScroll));
- // After the animation stopped, "scrollViewDidScroll" should be invoked, this could fix the bug of lack of tableview cells.
- if (_delegate != nullptr)
- {
- _delegate->scrollViewDidScroll(this);
- }
- }
- void ScrollViewSmooth::performedAnimatedScroll(float /*dt*/)
- {
- if (_dragging)
- {
- this->unschedule(CC_SCHEDULE_SELECTOR(ScrollViewSmooth::performedAnimatedScroll));
- return;
- }
- if (_delegate != nullptr)
- {
- _delegate->scrollViewDidScroll(this);
- }
- }
- const Size& ScrollViewSmooth::getContentSize() const
- {
- return _container->getContentSize();
- }
- void ScrollViewSmooth::setContentSize(const Size & size)
- {
- if (this->getContainer() != nullptr)
- {
- this->getContainer()->setContentSize(size);
- this->updateInset();
- }
- }
- void ScrollViewSmooth::updateInset()
- {
- if (this->getContainer() != nullptr)
- {
- _maxInset = this->maxContainerOffset();
- _maxInset.set(_maxInset.x + _viewSize.width * INSET_RATIO,
- _maxInset.y + _viewSize.height * INSET_RATIO);
- _minInset = this->minContainerOffset();
- _minInset.set(_minInset.x - _viewSize.width * INSET_RATIO,
- _minInset.y - _viewSize.height * INSET_RATIO);
- }
- }
- /**
- * make sure all children go to the container
- */
- void ScrollViewSmooth::addChild(Node * child, int zOrder, int tag)
- {
- if (_container != child) {
- _container->addChild(child, zOrder, tag);
- } else {
- Layer::addChild(child, zOrder, tag);
- }
- }
- void ScrollViewSmooth::removeChild(Node* node, bool cleanup)
- {
- if(_container != node)
- {
- _container->removeChild(node, cleanup);
- }
- else
- {
- Layer::removeChild(node, cleanup);
- }
- }
- void ScrollViewSmooth::removeAllChildrenWithCleanup(bool cleanup)
- {
- _container->removeAllChildrenWithCleanup(cleanup);
- Layer::removeAllChildrenWithCleanup(cleanup);
- }
- void ScrollViewSmooth::removeAllChildren()
- {
- removeAllChildrenWithCleanup(true);
- }
- void ScrollViewSmooth::addChild(Node * child, int zOrder, const std::string &name)
- {
- if (_container != child)
- {
- _container->addChild(child, zOrder, name);
- }
- else
- {
- Layer::addChild(child, zOrder, name);
- }
- }
- void ScrollViewSmooth::beforeDraw()
- {
- //ScrollView don't support drawing in 3D space
- _beforeDrawCommand.init(_globalZOrder);
- _beforeDrawCommand.func = CC_CALLBACK_0(ScrollViewSmooth::onBeforeDraw, this);
- Director::getInstance()->getRenderer()->addCommand(&_beforeDrawCommand);
- }
- /**
- * clip this view so that outside of the visible bounds can be hidden.
- */
- void ScrollViewSmooth::onBeforeDraw()
- {
- if (_clippingToBounds)
- {
- _scissorRestored = false;
- Rect frame = getViewRect();
- auto glview = Director::getInstance()->getOpenGLView();
- if (glview->getVR() == nullptr) {
- if (glview->isScissorEnabled()) {
- _scissorRestored = true;
- _parentScissorRect = glview->getScissorRect();
- //set the intersection of _parentScissorRect and frame as the new scissor rect
- if (frame.intersectsRect(_parentScissorRect)) {
- float x = MAX(frame.origin.x, _parentScissorRect.origin.x);
- float y = MAX(frame.origin.y, _parentScissorRect.origin.y);
- float xx = MIN(frame.origin.x + frame.size.width, _parentScissorRect.origin.x + _parentScissorRect.size.width);
- float yy = MIN(frame.origin.y + frame.size.height, _parentScissorRect.origin.y + _parentScissorRect.size.height);
- glview->setScissorInPoints(x, y, xx - x, yy - y);
- }
- }
- else {
- glEnable(GL_SCISSOR_TEST);
- glview->setScissorInPoints(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
- }
- }
- }
- }
- void ScrollViewSmooth::afterDraw()
- {
- _afterDrawCommand.init(_globalZOrder);
- _afterDrawCommand.func = CC_CALLBACK_0(ScrollViewSmooth::onAfterDraw, this);
- Director::getInstance()->getRenderer()->addCommand(&_afterDrawCommand);
- }
- /**
- * retract what's done in beforeDraw so that there's no side effect to
- * other nodes.
- */
- void ScrollViewSmooth::onAfterDraw()
- {
- if (_clippingToBounds)
- {
- auto glview = Director::getInstance()->getOpenGLView();
- if (glview->getVR() == nullptr) {
- if (_scissorRestored) {//restore the parent's scissor rect
- glview->setScissorInPoints(_parentScissorRect.origin.x, _parentScissorRect.origin.y, _parentScissorRect.size.width, _parentScissorRect.size.height);
- }
- else {
- glDisable(GL_SCISSOR_TEST);
- }
- }
- }
- }
- void ScrollViewSmooth::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags)
- {
- // quick return if not visible
- if (!isVisible())
- {
- return;
- }
- uint32_t flags = processParentFlags(parentTransform, parentFlags);
- // IMPORTANT:
- // To ease the migration to v3.0, we still support the Mat4 stack,
- // but it is deprecated and your code should not rely on it
- Director* director = Director::getInstance();
- CCASSERT(nullptr != director, "Director is null when setting matrix stack");
- director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
- director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
- this->beforeDraw();
- bool visibleByCamera = isVisitableByVisitingCamera();
- if (!_children.empty())
- {
- int i=0;
-
- // draw children zOrder < 0
- for( ; i < _children.size(); i++ )
- {
- Node *child = _children.at(i);
- if ( child->getLocalZOrder() < 0 )
- {
- child->visit(renderer, _modelViewTransform, flags);
- }
- else
- {
- break;
- }
- }
-
- // this draw
- if (visibleByCamera)
- this->draw(renderer, _modelViewTransform, flags);
-
- // draw children zOrder >= 0
- for( ; i < _children.size(); i++ )
- {
- Node *child = _children.at(i);
- child->visit(renderer, _modelViewTransform, flags);
- }
- }
- else if (visibleByCamera)
- {
- this->draw(renderer, _modelViewTransform, flags);
- }
- this->afterDraw();
- director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
- }
- bool ScrollViewSmooth::onTouchBegan(Touch* touch, Event* /*event*/)
- {
- /*
- if (!this->isVisible() || !this->hasVisibleParents())
- {
- return false;
- }
-
- Rect frame = getViewRect();
- //dispatcher does not know about clipping. reject touches outside visible bounds.
- if (_touches.size() > 2 ||
- _touchMoved ||
- !frame.containsPoint(touch->getLocation()))
- {
- return false;
- }
- if (std::find(_touches.begin(), _touches.end(), touch) == _touches.end())
- {
- _touches.push_back(touch);
- }
- if (_touches.size() == 1)
- { // scrolling
- _touchPoint = this->convertTouchToNodeSpace(touch);
- _touchMoved = false;
- _dragging = true; //dragging started
- _scrollDistance.setZero();
- _touchLength = 0.0f;
- //zg
- __pageTouchBegan();
- }
- else if (_touches.size() == 2)
- {
- _touchPoint = (this->convertTouchToNodeSpace(_touches[0]).getMidpoint(
- this->convertTouchToNodeSpace(_touches[1])));
-
- _touchLength = _container->convertTouchToNodeSpace(_touches[0]).getDistance(
- _container->convertTouchToNodeSpace(_touches[1]));
-
- _dragging = false;
- }
- return true;*/
- if (_isInterceptTouch){
- return false;
- }
- if (!this->isVisible() || !this->hasVisibleParents())
- {
- return false;
- }
-
- Rect frame = getViewRect();
-
- //dispatcher does not know about clipping. reject touches outside visible bounds.
- if (_touches.size() > 2 ||
- _touchMoved ||
- !frame.containsPoint(touch->getLocation()))
- {
- return false;
- }
-
- if (std::find(_touches.begin(), _touches.end(), touch) == _touches.end())
- {
- _touches.push_back(touch);
- }
-
- if (_touches.size() == 1)
- { // scrolling
- _touchPoint = this->convertTouchToNodeSpace(touch);
- _touchMoved = false;
- _dragging = true; //dragging started
- _scrollDistance.setZero();
- _touchLength = 0.0f;
- handlePressLogic(touch);
- //zg
- __pageTouchBegan();
- }
- else if (_touches.size() == 2)
- {
- _touchPoint = (this->convertTouchToNodeSpace(_touches[0]).getMidpoint(
- this->convertTouchToNodeSpace(_touches[1])));
-
- _touchLength = _container->convertTouchToNodeSpace(_touches[0]).getDistance(
- _container->convertTouchToNodeSpace(_touches[1]));
-
- _dragging = false;
- }
- return true;
- }
- void ScrollViewSmooth::onTouchMoved(Touch* touch, Event* /*event*/)
- {
- /*
- if (!this->isVisible())
- {
- return;
- }
- if (std::find(_touches.begin(), _touches.end(), touch) != _touches.end())
- {
- if (_touches.size() == 1 && _dragging)
- { // scrolling
- Vec2 moveDistance, newPoint;
- Rect frame;
- float newX, newY;
-
- frame = getViewRect();
- newPoint = this->convertTouchToNodeSpace(_touches[0]);
- moveDistance = newPoint - _touchPoint;
-
- float dis = 0.0f;
- if (_direction == Direction::VERTICAL)
- {
- dis = moveDistance.y;
- float pos = _container->getPosition().y;
- if (!(minContainerOffset().y <= pos && pos <= maxContainerOffset().y)) {
- moveDistance.y *= BOUNCE_BACK_FACTOR;
- }
- }
- else if (_direction == Direction::HORIZONTAL)
- {
- dis = moveDistance.x;
- float pos = _container->getPosition().x;
- if (!(minContainerOffset().x <= pos && pos <= maxContainerOffset().x)) {
- moveDistance.x *= BOUNCE_BACK_FACTOR;
- }
- }
- else
- {
- dis = sqrtf(moveDistance.x*moveDistance.x + moveDistance.y*moveDistance.y);
-
- float pos = _container->getPosition().y;
- if (!(minContainerOffset().y <= pos && pos <= maxContainerOffset().y)) {
- moveDistance.y *= BOUNCE_BACK_FACTOR;
- }
-
- pos = _container->getPosition().x;
- if (!(minContainerOffset().x <= pos && pos <= maxContainerOffset().x)) {
- moveDistance.x *= BOUNCE_BACK_FACTOR;
- }
- }
- if (!_touchMoved && fabs(convertDistanceFromPointToInch(dis)) < MOVE_INCH )
- {
- //CCLOG("Invalid movement, distance = [%f, %f], disInch = %f", moveDistance.x, moveDistance.y);
- return;
- }
-
- if (!_touchMoved)
- {
- moveDistance.setZero();
- }
-
- _touchPoint = newPoint;
- _touchMoved = true;
-
- if (_dragging)
- {
- switch (_direction)
- {
- case Direction::VERTICAL:
- moveDistance.set(0.0f, moveDistance.y);
- break;
- case Direction::HORIZONTAL:
- moveDistance.set(moveDistance.x, 0.0f);
- break;
- default:
- break;
- }
- newX = _container->getPosition().x + moveDistance.x;
- newY = _container->getPosition().y + moveDistance.y;
- _scrollDistance = moveDistance;
- this->setContentOffset(Vec2(newX, newY));
- }
- }
- else if (_touches.size() == 2 && !_dragging)
- {
- const float len = _container->convertTouchToNodeSpace(_touches[0]).getDistance(
- _container->convertTouchToNodeSpace(_touches[1]));
- this->setZoomScale(this->getZoomScale()*len/_touchLength);
- }
- }*/
- if (!this->isVisible())
- {
- return;
- }
-
- if (std::find(_touches.begin(), _touches.end(), touch) != _touches.end())
- {
- if (_touches.size() == 1 && _dragging)
- { // scrolling
- Vec2 moveDistance, newPoint;
- Rect frame;
- float newX, newY;
-
- frame = getViewRect();
-
- newPoint = this->convertTouchToNodeSpace(_touches[0]);
- moveDistance = newPoint - _touchPoint;
-
- float dis = 0.0f;
- if (_direction == Direction::VERTICAL)
- {
- dis = moveDistance.y;
- float pos = _container->getPosition().y;
- if (!(minContainerOffset().y <= pos && pos <= maxContainerOffset().y)) {
- moveDistance.y *= BOUNCE_BACK_FACTOR;
- }
- }
- else if (_direction == Direction::HORIZONTAL)
- {
- dis = moveDistance.x;
- float pos = _container->getPosition().x;
- if (!(minContainerOffset().x <= pos && pos <= maxContainerOffset().x)) {
- moveDistance.x *= BOUNCE_BACK_FACTOR;
- }
- }
- else
- {
- dis = sqrtf(moveDistance.x*moveDistance.x + moveDistance.y*moveDistance.y);
-
- float pos = _container->getPosition().y;
- if (!(minContainerOffset().y <= pos && pos <= maxContainerOffset().y)) {
- moveDistance.y *= BOUNCE_BACK_FACTOR;
- }
-
- pos = _container->getPosition().x;
- if (!(minContainerOffset().x <= pos && pos <= maxContainerOffset().x)) {
- moveDistance.x *= BOUNCE_BACK_FACTOR;
- }
- }
-
- if (!_touchMoved && fabs(convertDistanceFromPointToInch(dis)) < MOVE_INCH )
- {
- //CCLOG("Invalid movement, distance = [%f, %f], disInch = %f", moveDistance.x, moveDistance.y);
- return;
- }
-
- if (!_touchMoved)
- {
- moveDistance.setZero();
- }
-
- _touchPoint = newPoint;
- _touchMoved = true;
-
- if (_dragging)
- {
- switch (_direction)
- {
- case Direction::VERTICAL:
- moveDistance.set(0.0f, moveDistance.y);
- break;
- case Direction::HORIZONTAL:
- moveDistance.set(moveDistance.x, 0.0f);
- break;
- default:
- moveDistance.set(moveDistance.x, moveDistance.y);
- break;
- }
-
- newX = _container->getPosition().x + moveDistance.x;
- newY = _container->getPosition().y + moveDistance.y;
- _scrollDistance = moveDistance;
- handleMoveLogic(touch);
- // this->setContentOffset(Vec2(newX, newY));
- }
- }
- else if (_touches.size() == 2 && !_dragging)
- {
- const float len = _container->convertTouchToNodeSpace(_touches[0]).getDistance(
- _container->convertTouchToNodeSpace(_touches[1]));
- this->setZoomScale(this->getZoomScale()*len/_touchLength);
- }
- }
- }
- void ScrollViewSmooth::onTouchEnded(Touch* touch, Event* /*event*/)
- {
- /*
- if (!this->isVisible())
- {
- return;
- }
-
- auto touchIter = std::find(_touches.begin(), _touches.end(), touch);
-
- if (touchIter != _touches.end())
- {
- if (_touches.size() == 1 && _touchMoved)
- {
- // this->schedule(CC_SCHEDULE_SELECTOR(ScrollViewSmooth::deaccelerateScrolling));
- //zg
- if (__pageTouchEnd()) {
- __pageClearTouch();
- } else {
- // this->schedule(CC_SCHEDULE_SELECTOR(ScrollViewSmooth::deaccelerateScrolling));
- }
- }
- _touches.erase(touchIter);
- }
- if (_touches.size() == 0)
- {
- _dragging = false;
- _touchMoved = false;
- }*/
- if (!this->isVisible())
- {
- return;
- }
-
- auto touchIter = std::find(_touches.begin(), _touches.end(), touch);
- _touches.erase(touchIter);
-
- if (_touches.size() == 0)
- {
- _dragging = false;
- _touchMoved = false;
- }
-
- if (!_isInterceptTouch)
- {
- handleReleaseLogic(touch);
- }
- _isInterceptTouch = false;
- }
- void ScrollViewSmooth::onTouchCancelled(Touch* touch, Event* /*event*/)
- {/*
- if (!this->isVisible())
- {
- return;
- }
-
- auto touchIter = std::find(_touches.begin(), _touches.end(), touch);
- _touches.erase(touchIter);
-
- if (_touches.size() == 0)
- {
- _dragging = false;
- _touchMoved = false;
- }*/
-
- if (!this->isVisible())
- {
- return;
- }
-
- auto touchIter = std::find(_touches.begin(), _touches.end(), touch);
- _touches.erase(touchIter);
-
- if (_touches.size() == 0)
- {
- _dragging = false;
- _touchMoved = false;
- }
-
- if (!_isInterceptTouch)
- {
- handleReleaseLogic(touch);
- }
- _isInterceptTouch = false;
- }
- Rect ScrollViewSmooth::getViewRect()
- {
- Vec2 screenPos = this->convertToWorldSpace(Vec2::ZERO);
-
- float scaleX = this->getScaleX();
- float scaleY = this->getScaleY();
-
- for (Node *p = _parent; p != nullptr; p = p->getParent()) {
- scaleX *= p->getScaleX();
- scaleY *= p->getScaleY();
- }
- // Support negative scaling. Not doing so causes intersectsRect calls
- // (eg: to check if the touch was within the bounds) to return false.
- // Note, Node::getScale will assert if X and Y scales are different.
- if(scaleX<0.f) {
- screenPos.x += _viewSize.width*scaleX;
- scaleX = -scaleX;
- }
- if(scaleY<0.f) {
- screenPos.y += _viewSize.height*scaleY;
- scaleY = -scaleY;
- }
- return Rect(screenPos.x, screenPos.y, _viewSize.width*scaleX, _viewSize.height*scaleY);
- }
- // zg
- void ScrollViewSmooth::__pageTouchBegan()
- {
- //仅在设置了分页属性, 并且只有一个滑动方向的时候, 才支持分页.
- if( !m_bPaged || ( _direction != Direction::HORIZONTAL && _direction != Direction::VERTICAL )) return ;
-
- //记录初试时间和位置
- m_touchBeganTime = clock();
- m_touchBeganOffset = _direction == Direction::HORIZONTAL ? getContentOffset().x : getContentOffset().y;
-
- }
- bool ScrollViewSmooth::__pageTouchEnd()
- {
- if( !m_bPaged || ( _direction != Direction::HORIZONTAL && _direction != Direction::VERTICAL)) return false ;
-
- //constant
- const float PAGE_DISTENCE = _direction == Direction::HORIZONTAL ? getViewSize().width + m_pageAdjustSize.width: getViewSize().height + m_pageAdjustSize.height;
- if( PAGE_DISTENCE <= 0 ) return false;
-
- const float MAX_PAGE = ( _direction == Direction::HORIZONTAL ? getContentSize().width : getContentSize().height ) / PAGE_DISTENCE - 1;
- const float MIN_PAGE = 0;
-
- float currOffset = _direction == Direction::HORIZONTAL ? getContentOffset().x : getContentOffset().y;
- float deltaOffset = -(currOffset - m_touchBeganOffset);
- clock_t currTime = clock();
- float speed = currTime != m_touchBeganTime ? deltaOffset / ( currTime - m_touchBeganTime ) : 0;
-
-
- m_targetPage = m_currPage;
- if( std::abs(deltaOffset) >= TURN_PAGE_MIN_OFFSET_RATIO * PAGE_DISTENCE )
- {//滑动距离大于某一阈值.
-
- if( deltaOffset > 0 )
- {
- m_targetPage = m_currPage + 1;
- }
- else if( deltaOffset < 0 )
- {
- m_targetPage = m_currPage - 1;
- }
- }
- else if( std::abs(speed) >= TURN_PAGE_SPEED )
- {//速度大于某一阈值.
- if( speed > 0 )
- {
- m_targetPage = m_currPage + 1;
- }
- else if( speed < 0 )
- {
- m_targetPage = m_currPage - 1;
- }
- }
-
- if( m_targetPage > MAX_PAGE ) {
- m_targetPage = MAX_PAGE;
- }
- else if( m_targetPage < MIN_PAGE ) {
- m_targetPage = MIN_PAGE;
- }
-
- float targetOffset = -m_targetPage * ( _direction == Direction::HORIZONTAL ? getViewSize().width + m_pageAdjustSize.width: getViewSize().height + m_pageAdjustSize.height);
- if (m_targetPage == MAX_PAGE) {
- targetOffset -= (_direction == Direction::HORIZONTAL ? m_pageAdjustSize.width : m_pageAdjustSize.height);
- }
- float pageDurateion = 0.2;
- Point targetPointOffset = _direction == Direction::HORIZONTAL ? Point( targetOffset, getContentOffset().y ) : Point(getContentOffset().x, targetOffset );
- setContentOffsetInDuration(targetPointOffset, pageDurateion);
-
- if(_callFunc && (m_currPage != m_targetPage)){
- (this->*_callFunc)(m_targetPage);
- }
-
- m_currPage = m_targetPage;
-
- return true;
- }
- void ScrollViewSmooth::__pageTouchCancel()
- {
- if( !m_bPaged || ( _direction != Direction::HORIZONTAL && _direction != Direction::VERTICAL )) return ;
-
- __pageClearTouch();
-
- }
- void ScrollViewSmooth::__pageClearTouch()
- {
- //clear所有状态
- m_touchBeganOffset = 0;
- m_touchBeganTime = 0;
- m_targetPage = m_currPage;
- }
- void ScrollViewSmooth::zgMoveToPage(int page) {
- if (page != m_currPage) {
- float targetOffset = -page * (_direction == Direction::HORIZONTAL ? getViewSize().width : getViewSize().height);
- Point targetPointOffset = _direction == Direction::HORIZONTAL ? Point( targetOffset, getContentOffset().y ) : Point(getContentOffset().x, targetOffset );
- setContentOffset(targetPointOffset);
- m_currPage = page;
- if(_callFunc){
- (this->*_callFunc)(m_currPage);
- }
- }
- }
- void ScrollViewSmooth::zgMoveToPageWithAnimation(int page) {
- if (page != m_currPage) {
- float targetOffset = -page * (_direction == Direction::HORIZONTAL ? getViewSize().width : getViewSize().height);
- float pageDurateion = 0.2;
- Point targetPointOffset = _direction == Direction::HORIZONTAL ? Point( targetOffset, getContentOffset().y ) : Point(getContentOffset().x, targetOffset );
- setContentOffsetInDuration(targetPointOffset, pageDurateion);
- m_currPage = page;
- if(_callFunc){
- (this->*_callFunc)(m_currPage);
- }
- }
- }
- #pragma mask UItouch
- void ScrollViewSmooth::handlePressLogic(Touch *touch){
- _bePressed = true;
- _autoScrolling = false;
-
- // Clear gathered touch move information
- {
- _touchMovePreviousTimestamp = utils::getTimeInMilliseconds();
- _touchMoveDisplacements.clear();
- _touchMoveTimeDeltas.clear();
- }
- }
- void ScrollViewSmooth::handleMoveLogic(Touch *touch){
- Vec2 currPt, prevPt;
- // if(!calculateCurrAndPrevTouchPoints(touch, &currPt, &prevPt))
- // {
- // return;
- // }
- currPt = convertTouchToNodeSpace(touch);
- prevPt = convertToNodeSpace(touch->getPreviousLocation());
- Vec2 delta = currPt - prevPt;
- // Vec2 delta(delta3.x, delta3.y);
- scrollChildren(delta);
-
- // Gather touch move information for speed calculation
- // 收集触摸移动信息以进行速度计算
- gatherTouchMove(delta);
- }
- void ScrollViewSmooth::handleReleaseLogic(Touch *touch){
- // Gather the last touch information when released
- {
- Vec2 currPt, prevPt;
- currPt = convertTouchToNodeSpace(touch);
- prevPt = convertToNodeSpace(touch->getPreviousLocation());
- Vec2 delta = currPt - prevPt;
- gatherTouchMove(delta);
-
- }
-
- _bePressed = false;
-
- bool bounceBackStarted = startBounceBackIfNeeded();
- // bool bounceBackStarted = false;
- // if(!bounceBackStarted && _inertiaScrollEnabled)
- if(!bounceBackStarted)
- {
- Vec2 touchMoveVelocity = calculateTouchMoveVelocity();
- if(touchMoveVelocity != Vec2::ZERO)
- {
- startInertiaScroll(touchMoveVelocity);
- }
- }
- }
- void ScrollViewSmooth::scrollChildren(const Vec2& deltaMove)
- {
- Vec2 realMove = deltaMove;
- if(_bounceable)
- {
- // If the position of the inner container is out of the boundary, the offsets should be divided by two.
- Vec2 outOfBoundary = getHowMuchOutOfBoundary();
- // log("outOfBoundaryX %f, outOfBoundaryY %f",outOfBoundary.x,outOfBoundary.y);//手没离开的时候计算滑动用的log
- realMove.x *= (outOfBoundary.x == 0 ? 1 : 0.5f);
- realMove.y *= (outOfBoundary.y == 0 ? 1 : 0.5f);
- }
-
- if(!_bounceable)
- {
- Vec2 outOfBoundary = getHowMuchOutOfBoundary(realMove);
- realMove += outOfBoundary;
- }
-
- // bool scrolledToLeft = false;
- // bool scrolledToRight = false;
- // bool scrolledToTop = false;
- // bool scrolledToBottom = false;
- // if (realMove.y > 0.0f) // up
- // {
- // float icBottomPos = _container->getBottomBoundary();
- // if (icBottomPos + realMove.y >= 0)
- // {
- // scrolledToBottom = true;
- // }
- // }
- // else if (realMove.y < 0.0f) // down
- // {
- // float icTopPos = _innerContainer->getTopBoundary();
- // if (icTopPos + realMove.y <= _topBoundary)
- // {
- // scrolledToTop = true;
- // }
- // }
- //
- // if (realMove.x < 0.0f) // left
- // {
- // float icRightPos = _innerContainer->getRightBoundary();
- // if (icRightPos + realMove.x <= _rightBoundary)
- // {
- // scrolledToRight = true;
- // }
- // }
- // else if (realMove.x > 0.0f) // right
- // {
- // float icLeftPos = _innerContainer->getLeftBoundary();
- // if (icLeftPos + realMove.x >= _leftBoundary)
- // {
- // scrolledToLeft = true;
- // }
- // }
- moveInnerContainer(realMove, false);
- }
- Vec2 ScrollViewSmooth::getHowMuchOutOfBoundary(const Vec2& addition)
- {
- // if(addition == Vec2::ZERO && !_outOfBoundaryAmountDirty)
- // {
- // return _outOfBoundaryAmount;
- // }
-
- // Vec2 outOfBoundaryAmount(Vec2::ZERO);
- // if(_innerContainer->getLeftBoundary() + addition.x > _leftBoundary)
- // {
- // outOfBoundaryAmount.x = _leftBoundary - (_innerContainer->getLeftBoundary() + addition.x);
- // }
- // else if(_innerContainer->getRightBoundary() + addition.x < _rightBoundary)
- // {
- // outOfBoundaryAmount.x = _rightBoundary - (_innerContainer->getRightBoundary() + addition.x);
- // }
- //
- // if(_innerContainer->getTopBoundary() + addition.y < _topBoundary)
- // {
- // outOfBoundaryAmount.y = _topBoundary - (_innerContainer->getTopBoundary() + addition.y);
- // }
- // else if(_innerContainer->getBottomBoundary() + addition.y > _bottomBoundary)
- // {
- // outOfBoundaryAmount.y = _bottomBoundary - (_innerContainer->getBottomBoundary() + addition.y);
- // }
- //
- // if(addition == Vec2::ZERO)
- // {
- // _outOfBoundaryAmount = outOfBoundaryAmount;
- // _outOfBoundaryAmountDirty = false;
- // }
- // return outOfBoundaryAmount;
- Vec2 outOfBoundaryAmount(Vec2::ZERO);
- const Vec2 minOffset = this->minContainerOffset();
- const Vec2 maxOffset = this->maxContainerOffset();
- if (_container->getPosition().y + addition.y < minOffset.y) {
- outOfBoundaryAmount.y = minOffset.y - (_container->getPosition().y + addition.y);
- }
- return outOfBoundaryAmount;
- }
- void ScrollViewSmooth::moveInnerContainer(const Vec2& deltaMove, bool canStartBounceBack)
- {
- Vec2 adjustedMove = flattenVectorByDirection(deltaMove);
- // log("moveInnerContainerX %f,moveInnerContainerY %f ,canStartBounceBack is %d",deltaMove.x,deltaMove.y,canStartBounceBack);
- // setInnerContainerPosition(getInnerContainerPosition() + adjustedMove);
- setContentOffset(getContentOffset() + adjustedMove);
-
- if(_bounceable && canStartBounceBack)
- {
- startBounceBackIfNeeded();
- }
- }
- Vec2 ScrollViewSmooth::flattenVectorByDirection(const Vec2& vector)
- {
- Vec2 result = vector;
- // result.x = (_direction == Direction::VERTICAL || _direction == Direction::BOTH ? 0 : result.x);
- // result.y = (_direction == Direction::HORIZONTAL || _direction == Direction::BOTH ? 0 : result.y);
-
- result.x = (_direction == Direction::VERTICAL ? 0 : result.x);
- result.y = (_direction == Direction::HORIZONTAL ? 0 : result.y);
- return result;
- }
- void ScrollViewSmooth::gatherTouchMove(const Vec2& delta)
- {
- while(_touchMoveDisplacements.size() >= 5)
- {
- _touchMoveDisplacements.pop_front();
- _touchMoveTimeDeltas.pop_front();
- }
- _touchMoveDisplacements.push_back(delta);
-
- long long timestamp = utils::getTimeInMilliseconds();
- _touchMoveTimeDeltas.push_back((timestamp - _touchMovePreviousTimestamp) / 1000.0f);
- _touchMovePreviousTimestamp = timestamp;
- }
- Vec2 ScrollViewSmooth::calculateTouchMoveVelocity() const
- {
- float totalTime = 0;
- // log("------------------------------------------");
- for(auto &timeDelta : _touchMoveTimeDeltas)
- {
- // log("------- timeDelta %f", timeDelta);
- totalTime += timeDelta;
- }
- // log("------- totalTime %f", totalTime);
-
- if(totalTime == 0/* || totalTime >= 0.5*/)
- {
- // log("------- totalTime changed is not good");
- return Vec2::ZERO;
- }
-
- if (totalTime < 0.01) {
- // log("------- totalTime changed1 ---------- %f", totalTime);
- totalTime = 0.2;
- } else if (totalTime < 0.02 && totalTime >= 0.01) {
- // log("------- totalTime changed2 ---------- %f", totalTime);
- totalTime = 0.02;
- } else if (totalTime >= 0.5) {
- // log("------- totalTime changed3 ---------- %f", totalTime);
- totalTime = 0.5;
- }
- // log("------------------------------------------");
-
- Vec2 totalMovement;
- for(auto &displacement : _touchMoveDisplacements)
- {
- totalMovement += displacement;
- }
- return totalMovement / totalTime;
- }
- void ScrollViewSmooth::startInertiaScroll(const Vec2& touchMoveVelocity)
- {
- const float MOVEMENT_FACTOR = 0.7f;
- Vec2 inertiaTotalMovement = touchMoveVelocity * MOVEMENT_FACTOR;
- startAttenuatingAutoScroll(inertiaTotalMovement, touchMoveVelocity);
- }
- void ScrollViewSmooth::startAttenuatingAutoScroll(const Vec2& deltaMove, const Vec2& initialVelocity)
- {
- float time = calculateAutoScrollTimeByInitialSpeed(initialVelocity.length());
- startAutoScroll(deltaMove, time, true);
- }
- bool ScrollViewSmooth::isNecessaryAutoScrollBrake()
- {
- if(_autoScrollBraking)
- {
- return true;
- }
- Vec2 bounceBackAmount = getHowMuchOutOfBoundary();
- if(!fltEqualZero(bounceBackAmount))
- {
- // It just went out of boundary.
- if(!_autoScrollCurrentlyOutOfBoundary)
- {
- _autoScrollCurrentlyOutOfBoundary = true;
- _autoScrollBraking = true;
- _autoScrollBrakingStartPosition = _container->getPosition();
- return true;
- }
- }
- else
- {
- _autoScrollCurrentlyOutOfBoundary = false;
- }
- return false;
- }
- bool ScrollViewSmooth::startBounceBackIfNeeded()
- {
- if (!_bounceable)
- {
- return false;
- }
- Vec2 bounceBackAmount = getHowMuchOutOfBoundary();
- if(fltEqualZero(bounceBackAmount))
- {
- return false;
- }
-
- startAutoScroll(bounceBackAmount, 1.0f, true);
- return true;
- }
- float ScrollViewSmooth::calculateAutoScrollTimeByInitialSpeed(float initialSpeed)
- {
- // Calculate the time from the initial speed according to quintic polynomial.
- float time = sqrtf(sqrtf(initialSpeed / 5));
- return time;
- }
- void ScrollViewSmooth::startAutoScroll(const Vec2& deltaMove, float timeInSec, bool attenuated)
- {
- Vec2 adjustedDeltaMove = flattenVectorByDirection(deltaMove);// 单方向
-
- _autoScrolling = true;
- _autoScrollTargetDelta = adjustedDeltaMove;
-
- // _autoScrollAttenuate = attenuated;
- _autoScrollStartPosition = getContentOffset();
- _autoScrollTotalTime = timeInSec;
- _autoScrollAccumulatedTime = 0;
- _autoScrollBraking = false;
- _autoScrollBrakingStartPosition = Vec2::ZERO;
-
- // If the destination is also out of boundary of same side, start brake from beginning.
- Vec2 currentOutOfBoundary = getHowMuchOutOfBoundary();
- if (!fltEqualZero(currentOutOfBoundary))
- {
- _autoScrollCurrentlyOutOfBoundary = true;
- Vec2 afterOutOfBoundary = getHowMuchOutOfBoundary(adjustedDeltaMove);
- if(currentOutOfBoundary.x * afterOutOfBoundary.x > 0 || currentOutOfBoundary.y * afterOutOfBoundary.y > 0)
- {
- _autoScrollBraking = true;
- }
- }
- }
- #pragma mask update
- void ScrollViewSmooth::update(float dt)
- {
- if (_autoScrolling)
- {
- processAutoScrolling(dt);
- }
- }
- //手离开的时候计算滑动用的log
- void ScrollViewSmooth::processAutoScrolling(float deltaTime)
- {
- // Make auto scroll shorter if it needs to deaccelerate.
- //如果需要减速,请使自动滚动更短。
- // float brakingFactor = (/* DISABLES CODE */ (false) ? 0.05 : 1);
- float brakingFactor = (isNecessaryAutoScrollBrake() ? 0.05 : 1);
- // log("brakingFactor is %f",brakingFactor);
- // Elapsed time
- _autoScrollAccumulatedTime += deltaTime * (1 / brakingFactor);
-
- // Calculate the progress percentage
- float percentage = MIN(1, _autoScrollAccumulatedTime / _autoScrollTotalTime);
- bool _autoScrollAttenuate = true;
- if(_autoScrollAttenuate)
- {
- // Use quintic(5th degree) polynomial
- percentage = tweenfunc::quintEaseOut(percentage);
- }
- // Calculate the new position
- Vec2 newPosition = _autoScrollStartPosition + (_autoScrollTargetDelta * percentage);
- bool reachedEnd = std::abs(percentage - 1) <= FLT_EPSILON;
-
- if (reachedEnd)
- {
- newPosition = _autoScrollStartPosition + _autoScrollTargetDelta;
- }
-
- if(_bounceable)
- {
- // The new position is adjusted if out of boundary
- newPosition = _autoScrollBrakingStartPosition + (newPosition - _autoScrollBrakingStartPosition) * brakingFactor;
- }
- else
- {
- // Don't let go out of boundary
- // Vec2 moveDelta = newPosition - getContentOffset();
- // Vec2 outOfBoundary = getHowMuchOutOfBoundary(moveDelta);
- // if (!fltEqualZero(outOfBoundary))
- // {
- // newPosition += outOfBoundary;
- // reachedEnd = true;
- // }
- }
-
- // Finish auto scroll if it ended
- if(reachedEnd)
- {
- _autoScrolling = false;
- // dispatchEvent(SCROLLVIEW_EVENT_AUTOSCROLL_ENDED, EventType::AUTOSCROLL_ENDED);
- }
-
- moveInnerContainer(newPosition - getContentOffset(), reachedEnd);
- }
- bool ScrollViewSmooth::fltEqualZero(const Vec2& point) const
- {
- return (fabsf(point.x) <= 0.0001f && fabsf(point.y) <= 0.0001f);
- }
- void ScrollViewSmooth::onEnter(){
- Layer::onEnter();
- scheduleUpdate();
- }
- NS_CC_EXT_END
|