SlidingActor.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. #include "SlidingActor.h"
  2. #include "ClipRectActor.h"
  3. #include "PointerState.h"
  4. #include "UpdateState.h"
  5. //#include "Draggable.h"
  6. #include "initActor.h"
  7. #include "Serialize.h"
  8. namespace oxygine
  9. {
  10. float _defaultTouchThreshold = 15;
  11. void SlidingActor::setDefaultTouchThreshold(float val)
  12. {
  13. _defaultTouchThreshold = val;
  14. }
  15. SlidingActor::SlidingActor():
  16. _sliding(false),
  17. _rad(_defaultTouchThreshold),
  18. _maxSpeed(250),
  19. _downTime(0),
  20. _lastTime(0), _current(0), _lastIterTime(0)
  21. {
  22. _clip = new ClipRectActor;
  23. _clip->addEventListener(TouchEvent::TOUCH_DOWN, CLOSURE(this, &SlidingActor::_newEvent));
  24. _clip->addEventListener(TouchEvent::TOUCH_UP, CLOSURE(this, &SlidingActor::_newEvent));
  25. _clip->addEventListener(TouchEvent::MOVE, CLOSURE(this, &SlidingActor::_newEvent));
  26. addChild(_clip);
  27. }
  28. void SlidingActor::destroy()
  29. {
  30. _clip->removeChildren();
  31. _drag.destroy();
  32. _content = 0;
  33. }
  34. SlidingActor::~SlidingActor()
  35. {
  36. destroy();
  37. }
  38. void SlidingActor::setTouchThreshold(float rad)
  39. {
  40. _rad = rad;
  41. }
  42. void SlidingActor::sizeChanged(const Vector2& size)
  43. {
  44. if (_clip)
  45. _clip->setSize(size);
  46. updateDragBounds();
  47. }
  48. void SlidingActor::snap()
  49. {
  50. if (!_content)
  51. return;
  52. updateDragBounds();
  53. _drag.snapClient2Bounds();
  54. _sliding = false;
  55. }
  56. void SlidingActor::stop()
  57. {
  58. _speed = Vector2(0, 0);
  59. }
  60. void SlidingActor::setContent(spActor content)
  61. {
  62. if (_content)
  63. {
  64. _drag.destroy();
  65. _content->detach();
  66. }
  67. _downTime = 0;
  68. _current = 0;
  69. _lastIterTime = 0;
  70. _sliding = false;
  71. //_prev[0].pos = _content->getPosition();
  72. //_prev[0].tm = tm;
  73. for (int i = 0; i < NUM; ++i)
  74. _prev[i].tm = 0;
  75. _holded = 0; //event->target;
  76. //_downPos = te->localPosition;
  77. //_downTime = tm;
  78. _speed = Vector2(0, 0);
  79. _content = content;
  80. _drag.init(content.get());
  81. _clip->addChild(_content);
  82. updateDragBounds();
  83. }
  84. void SlidingActor::setLocked(bool locked)
  85. {
  86. _drag.setDragEnabled(!locked);
  87. }
  88. void SlidingActor::updateDragBounds()
  89. {
  90. if (!_content)
  91. return;
  92. float w = std::max(0.0f, _content->getWidth() * _content->getScaleX() - _clip->getWidth());
  93. float h = std::max(0.0f, _content->getHeight() * _content->getScaleY() - _clip->getHeight());
  94. RectF bounds(-w, -h, w, h);
  95. _drag.setDragBounds(bounds);
  96. }
  97. const timeMS fdt = 1000 / 60;
  98. //const float fdt = 20;
  99. void SlidingActor::doUpdate(const UpdateState& us)
  100. {
  101. if (!_content)
  102. return;
  103. //static float ml = 0;
  104. //ml = max(_speed.length(), ml);
  105. //log::messageln("sp: %.2f", ml);
  106. int ct = getTimeMS();
  107. if (_lastIterTime + NUM * fdt < ct)
  108. _lastIterTime = ct;
  109. if (_drag.isDragging())
  110. {
  111. Vector2 pos = _content->getPosition();
  112. //log::messageln("%d) pos %.2f %.2f", _current, pos.x, pos.y);
  113. _prev[_current].pos = pos;
  114. _prev[_current].tm = ct;
  115. _current = (_current + 1) % NUM;
  116. return;
  117. }
  118. if (_sliding)
  119. {
  120. const RectF& bounds = _drag.getDragBounds();
  121. while (_lastIterTime + fdt <= ct)
  122. {
  123. Vector2 pos = _content->getPosition();
  124. Vector2 newpos = pos + _speed * (fdt / 1000.0f);
  125. if (newpos.x < bounds.getLeft())
  126. {
  127. newpos.x = bounds.getLeft();
  128. _speed.x = 0;
  129. }
  130. else if (newpos.x > bounds.getRight())
  131. {
  132. newpos.x = bounds.getRight();
  133. _speed.x = 0;
  134. }
  135. if (newpos.y < bounds.getTop())
  136. {
  137. newpos.y = bounds.getTop();
  138. _speed.y = 0;
  139. }
  140. else if (newpos.y > bounds.getBottom())
  141. {
  142. newpos.y = bounds.getBottom();
  143. _speed.y = 0;
  144. }
  145. _speed *= 0.97f;
  146. _content->setPosition(newpos);
  147. _lastIterTime += fdt;
  148. }
  149. SlidingEvent sl(SlidingEvent::SLIDING);
  150. sl.speed = _speed;
  151. dispatchEvent(&sl);
  152. _speed = sl.speed;
  153. if (_speed.sqlength() < 8)
  154. {
  155. _sliding = false;
  156. SlidingEvent ev(SlidingEvent::END);
  157. dispatchEvent(&ev);
  158. }
  159. }
  160. }
  161. void SlidingActor::handleEvent(Event* event)
  162. {
  163. _Actor::handleEvent(event);
  164. }
  165. void SlidingActor::_newEvent(Event* event)
  166. {
  167. if (!_content)
  168. return;
  169. TouchEvent* te = safeCast<TouchEvent*>(event);
  170. timeMS tm = getTimeMS();
  171. switch (te->type)
  172. {
  173. case TouchEvent::TOUCH_DOWN:
  174. {
  175. _current = 0;
  176. _lastIterTime = tm;
  177. _prev[0].pos = _content->getPosition();
  178. _prev[0].tm = tm;
  179. for (int i = 1; i < NUM; ++i)
  180. _prev[i].tm = 0;
  181. _holded = event->target;
  182. _downPos = te->localPosition;
  183. _downTime = tm;
  184. }
  185. break;
  186. case TouchEvent::TOUCH_UP:
  187. {
  188. if (_drag.getDragEnabled())
  189. {
  190. _downTime = 0;
  191. Vector2 pos = _content->getPosition();
  192. _holded = 0;
  193. const iter* old = 0;
  194. const iter* mid = 0;
  195. const iter* last = _prev + _current;
  196. for (int i = 1; i < NUM; ++i)
  197. {
  198. int n = (_current + NUM - i) % NUM;
  199. if (_prev[n].tm)
  200. last = _prev + n;
  201. else
  202. break;
  203. if (!mid && (last->tm + 50 <= tm))
  204. mid = last;
  205. if (last->tm + 150 <= tm)
  206. {
  207. old = last;
  208. break;
  209. }
  210. }
  211. if (!old)
  212. old = last;
  213. if (!mid)
  214. mid = last;
  215. Vector2 midpos = mid->pos;
  216. Vector2 dir = pos - midpos;
  217. if (dir.sqlength() < 10 * 10)
  218. _speed = Vector2(0, 0);
  219. else
  220. {
  221. timeMS v = tm - old->tm;
  222. if (!v)
  223. return;
  224. Vector2 dr = pos - old->pos;
  225. Vector2 ns = (dr * 1000.0f) / v;
  226. if (_speed.dot(ns) < 0)
  227. _speed = ns;
  228. else
  229. _speed += ns;
  230. }
  231. if (!_sliding)
  232. {
  233. _sliding = true;
  234. }
  235. SlidingEvent sd(SlidingEvent::BEGIN);
  236. sd.speed = _speed;
  237. dispatchEvent(&sd);
  238. _speed = sd.speed;
  239. _lastIterTime = tm;
  240. }
  241. }
  242. break;
  243. case TouchEvent::MOVE:
  244. {
  245. Vector2 offset = _downPos - te->localPosition;
  246. float d = offset.dot(offset);
  247. if (_holded && (d >= _rad * _rad))
  248. {
  249. spActor act = safeSpCast<Actor>(_holded);
  250. while (act && act.get() != _content.get())
  251. {
  252. act->setNotPressed();
  253. act = act->getParent();
  254. }
  255. _holded = 0;
  256. }
  257. }
  258. break;
  259. }
  260. }
  261. void SlidingActor::serialize(serializedata* data)
  262. {
  263. _Actor::serialize(data);
  264. data->node.set_name("SlidingActor");
  265. }
  266. void SlidingActor::deserialize(const deserializedata* data)
  267. {
  268. _Actor::deserialize(data);
  269. }
  270. }