cocos2d-x/ScrollViewの慣性の動きが気持ちよくないので自分で制御する。

Cocos StudioでScrollViewを配置してみたが、慣性の動きが気持ちよくないので、自分で動かす。
ただ、バウンドはできなくなる。
ソースが美しくないのは悪しからず。。。

```cpp:ScrollViewController.cpp

#include "ScrollViewController.h"

using namespace cocos2d;

const uint32_t ScrollViewController::HISTORY_FRAME = 10;

ScrollViewController::ScrollViewController():_target(nullptr),_touchNow(false),_deceleration(defaultDeceleration)
{
  
}
ScrollViewController::~ScrollViewController()
{
  
}
void ScrollViewController::setTarget(cocos2d::ui::ScrollView* scrollview)
{
  _target = scrollview;
  // もともとの慣性は無効に
  _target->setInertiaScrollEnabled(false);
  
  _target->addTouchEventListener([this](Ref* ref, ui::Widget::TouchEventType type){
    switch(type)
    {
        // タッチ開始時
      case ui::Widget::TouchEventType::BEGAN:
        _touchNow = true;
        _history.clear();
        _vec = Vec2::ZERO;
        _posPre = _target->getInnerContainer()->getPosition();
        break;
        // タッチ終了時
      case ui::Widget::TouchEventType::CANCELED:
      case ui::Widget::TouchEventType::ENDED:
        if( _history.size() > 0 ){
          for( auto& h : _history ){
            _vec += h;
          }
          _vec.x /= _history.size();
          _vec.y /= _history.size();
        }
        _touchNow = false;
        break;
      default:
        break;
    }
  });
  
  
  scheduleUpdate();
}

void ScrollViewController::update(float delta)
{
  if( _target == nullptr ){
    return;
  }
  auto innner = _target->getInnerContainer();
  // タッチ中は動きの履歴を貯める
  if( _touchNow ){
    auto now = innner->getPosition();
    auto vec = now - _posPre;
    _history.push_back(vec);
    while(_history.size()>HISTORY_FRAME){
      _history.pop_front();
    }
    _posPre = now;
  }
  // タッチ中じゃなかったら動かす
  else{
    auto now = innner->getPosition();
    auto pos = now + _vec;
    auto szLimit = _target->getInnerContainerSize();
    auto szTarget = _target->getContentSize();
    szLimit.width -= szTarget.width;
    szLimit.height -= szTarget.height;
    
    if( pos.y > 0 ){
      pos.y = 0;
    }
    if( pos.y < -szLimit.height ){
      pos.y = -szLimit.height;
    }
    if( pos.x > 0 ){
      pos.x = 0;
    }
    if( pos.x < -szLimit.width ){
      pos.x = -szLimit.width;
    }
    _vec = pos - now;
    innner->setPosition(pos);
    _deceleration(_vec);
  }
}

void ScrollViewController::defaultDeceleration(cocos2d::Vec2& vec)
{
  vec *= 0.95f;
  if( fabs(vec.x) < 0.1f && fabs(vec.y) < 0.1f ){
    vec = Vec2::ZERO;
  }
}

```

```cpp:ScrollViewController.h

#ifndef __ScrollViewController_H__
#define __ScrollViewController_H__
#include "cocos2d.h"
#include <ui/UIScrollView.h>
#include <deque>

class ScrollViewController : public cocos2d::Node
{
  ScrollViewController();
  ~ScrollViewController();
public:

  CREATE_FUNC(ScrollViewController);
  void setTarget(cocos2d::ui::ScrollView* scrollview);
  virtual void update(float delta);
  void setDeceleration(std::function<void(cocos2d::Vec2& vec)> dec){
    _deceleration = dec;
  }

private:
  cocos2d::ui::ScrollView* _target;
  bool _touchNow;
  cocos2d::Vec2 _vec;
  cocos2d::Vec2 _posPre;
  std::deque<cocos2d::Vec2> _history;
  static const uint32_t HISTORY_FRAME;
  std::function<void(cocos2d::Vec2& vec)> _deceleration;
  static void defaultDeceleration(cocos2d::Vec2& vec);
  
};
#endif


```

使い方は

```cpp:FooScene.cpp

  auto scrollview = (ui::ScrollView*)_node->getChildByName("scrollview");

  auto ctrl = ScrollViewController::create();
  ctrl->setTarget(scrollview);
  _node->addChild(ctrl);

```

SceneにaddChild()して参照カウンタの管理できるから、cocos2d::Nodeから継承しているが、特に意味はないです。