Line data Source code
1 : /**
2 : Copyright (c) 2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #include "XLGestureRecognizer.h"
25 : #include "XLInputListener.h"
26 : #include "XLNode.h"
27 : #include "XLDirector.h"
28 : #include "XLInputDispatcher.h"
29 :
30 : namespace STAPPLER_VERSIONIZED stappler::xenolith {
31 :
32 21 : const Vec2 &GestureScroll::location() const {
33 21 : return pos;
34 : }
35 :
36 21 : void GestureScroll::cleanup() {
37 21 : pos = Vec2::ZERO;
38 21 : amount = Vec2::ZERO;
39 21 : }
40 :
41 :
42 3023 : void GestureTap::cleanup() {
43 3023 : id = maxOf<uint32_t>();
44 3023 : time.clear();
45 3023 : count = 0;
46 3023 : }
47 :
48 289 : void GesturePress::cleanup() {
49 289 : id = maxOf<uint32_t>();
50 289 : limit.clear();
51 289 : time.clear();
52 289 : tickCount = 0;
53 289 : }
54 :
55 176 : void GestureSwipe::cleanup() {
56 176 : firstTouch = Vec2::ZERO;
57 176 : secondTouch = Vec2::ZERO;
58 176 : midpoint = Vec2::ZERO;
59 176 : delta = Vec2::ZERO;
60 176 : velocity = Vec2::ZERO;
61 176 : }
62 :
63 84 : void GesturePinch::cleanup() {
64 84 : first = Vec2::ZERO;
65 84 : second = Vec2::ZERO;
66 84 : center = Vec2::ZERO;
67 84 : startDistance = 0.0f;
68 84 : prevDistance = 0.0f;
69 84 : distance = 0.0f;
70 84 : scale = 0.0f;
71 84 : velocity = 0.0f;
72 84 : }
73 :
74 2461 : bool GestureRecognizer::init() {
75 2461 : return true;
76 : }
77 :
78 14455 : bool GestureRecognizer::canHandleEvent(const InputEvent &event) const {
79 14455 : if (_eventMask.test(toInt(event.data.event))) {
80 4849 : if (!_buttonMask.any() || _buttonMask.test(toInt(event.data.button))) {
81 4849 : return true;
82 : }
83 : }
84 9606 : return false;
85 : }
86 :
87 18903 : InputEventState GestureRecognizer::handleInputEvent(const InputEvent &event, float density) {
88 18903 : if (!_eventMask.test(toInt(event.data.event))) {
89 10632 : return InputEventState::Declined;
90 : }
91 :
92 8271 : if (_buttonMask.any() && !_buttonMask.test(toInt(event.data.button))) {
93 3262 : return InputEventState::Declined;
94 : }
95 :
96 5009 : _density = density;
97 :
98 5009 : switch (event.data.event) {
99 1960 : case InputEventName::Begin:
100 : case InputEventName::KeyPressed:
101 1960 : return addEvent(event, density);
102 : break;
103 1044 : case InputEventName::Move:
104 : case InputEventName::KeyRepeated:
105 1044 : return renewEvent(event, density);
106 : break;
107 1788 : case InputEventName::End:
108 : case InputEventName::KeyReleased:
109 1788 : return removeEvent(event, true, density);
110 : break;
111 217 : case InputEventName::Cancel:
112 : case InputEventName::KeyCanceled:
113 217 : return removeEvent(event, false, density);
114 : break;
115 0 : default: break;
116 : }
117 0 : return InputEventState::Processed;
118 : }
119 :
120 2125 : void GestureRecognizer::onEnter(InputListener *) {
121 :
122 2125 : }
123 :
124 2125 : void GestureRecognizer::onExit() {
125 :
126 2125 : }
127 :
128 21 : uint32_t GestureRecognizer::getEventCount() const {
129 21 : return (uint32_t)_events.size();
130 : }
131 :
132 42 : bool GestureRecognizer::hasEvent(const InputEvent &event) const {
133 42 : if (_events.size() == 0) {
134 21 : return false;
135 : }
136 :
137 21 : for (auto & pEvent : _events) {
138 21 : if (pEvent.data.id == event.data.id) {
139 21 : return true;
140 : }
141 : }
142 :
143 0 : return false;
144 : }
145 :
146 2272 : GestureRecognizer::EventMask GestureRecognizer::getEventMask() const {
147 2272 : return _eventMask;
148 : }
149 :
150 303030 : void GestureRecognizer::update(uint64_t dt) {
151 :
152 303030 : }
153 :
154 21 : Vec2 GestureRecognizer::getLocation() const {
155 21 : if (_events.size() > 0) {
156 21 : return Vec2(_events.back().currentLocation);
157 : } else {
158 0 : return Vec2::ZERO;
159 : }
160 : }
161 :
162 126 : void GestureRecognizer::cancel() {
163 126 : auto eventsToRemove = _events;
164 126 : for (auto &event : eventsToRemove) {
165 0 : removeEvent(event, false, _density);
166 : }
167 126 : }
168 :
169 136 : bool GestureRecognizer::canAddEvent(const InputEvent &event) const {
170 136 : if (_events.size() < _maxEvents) {
171 136 : for (auto &it : _events) {
172 0 : if (event.data.id == it.data.id) {
173 0 : return false;
174 : }
175 : }
176 136 : return true;
177 : } else {
178 0 : return false;
179 : }
180 : }
181 :
182 1872 : InputEventState GestureRecognizer::addEvent(const InputEvent &event, float density) {
183 1872 : if (_events.size() < _maxEvents) {
184 1914 : for (auto &it : _events) {
185 42 : if (event.data.id == it.data.id) {
186 0 : return InputEventState::Declined;
187 : }
188 : }
189 1872 : _events.emplace_back(event);
190 1872 : return InputEventState::Processed;
191 : } else {
192 0 : return InputEventState::Declined;
193 : }
194 : }
195 :
196 2009 : InputEventState GestureRecognizer::removeEvent(const InputEvent &event, bool success, float density) {
197 2009 : if (_events.size() == 0) {
198 179 : return InputEventState::Declined;
199 : }
200 :
201 1830 : uint32_t index = maxOf<uint32_t>();
202 1830 : auto pEvent = getTouchById(event.data.id, &index);
203 1830 : if (pEvent && index < _events.size()) {
204 1830 : _events.erase(_events.begin() + index);
205 1830 : return InputEventState::Processed;
206 : } else {
207 0 : return InputEventState::Declined;
208 : }
209 : }
210 :
211 1023 : InputEventState GestureRecognizer::renewEvent(const InputEvent &event, float density) {
212 1023 : if (_events.size() == 0) {
213 496 : return InputEventState::Declined;
214 : }
215 :
216 527 : uint32_t index = maxOf<uint32_t>();
217 527 : auto pEvent = getTouchById(event.data.id, &index);
218 527 : if (pEvent && index < _events.size()) {
219 527 : _events[index] = event;
220 527 : return InputEventState::Processed;
221 : } else {
222 0 : return InputEventState::Declined;
223 : }
224 : }
225 :
226 2357 : InputEvent *GestureRecognizer::getTouchById(uint32_t id, uint32_t *index) {
227 2357 : InputEvent *pTouch = nullptr; uint32_t i = 0;
228 2399 : for (i = 0; i < _events.size(); i ++) {
229 2399 : pTouch = &_events.at(i);
230 2399 : if (pTouch->data.id == id) {
231 2357 : if (index) {
232 2357 : *index = i;
233 : }
234 2357 : return pTouch;
235 : }
236 : }
237 0 : return nullptr;
238 : }
239 :
240 193 : bool GestureTouchRecognizer::init(InputCallback &&cb, ButtonMask &&mask) {
241 193 : if (!GestureRecognizer::init()) {
242 0 : return false;
243 : }
244 :
245 193 : if (cb) {
246 193 : _maxEvents = 10;
247 193 : _buttonMask = move(mask);
248 193 : _callback = move(cb);
249 193 : _eventMask.set(toInt(InputEventName::Begin));
250 193 : _eventMask.set(toInt(InputEventName::Move));
251 193 : _eventMask.set(toInt(InputEventName::End));
252 193 : _eventMask.set(toInt(InputEventName::Cancel));
253 193 : return true;
254 : }
255 0 : return false;
256 : }
257 :
258 1258 : bool GestureTouchRecognizer::canHandleEvent(const InputEvent &event) const {
259 1258 : if (GestureRecognizer::canHandleEvent(event)) {
260 0 : if (_buttonMask.test(toInt(event.data.button))) {
261 0 : return true;
262 : }
263 : }
264 1258 : return false;
265 : }
266 :
267 42 : void GestureTouchRecognizer::removeRecognizedEvent(uint32_t id) {
268 42 : for (auto it = _events.begin(); it != _events.end(); it ++) {
269 42 : if ((*it).data.id == id) {
270 42 : _events.erase(it);
271 42 : break;
272 : }
273 : }
274 42 : }
275 :
276 63 : InputEventState GestureTouchRecognizer::addEvent(const InputEvent &event, float density) {
277 63 : if (!_buttonMask.test(toInt(event.data.button))) {
278 0 : return InputEventState::Declined;
279 : }
280 :
281 63 : if (GestureRecognizer::addEvent(event, density) != InputEventState::Declined) {
282 63 : _event.event = GestureEvent::Began;
283 63 : _event.input = &event;
284 63 : if (!_callback(_event)) {
285 21 : removeRecognizedEvent(event.data.id);
286 21 : _event.event = GestureEvent::Cancelled;
287 21 : _event.input = nullptr;
288 21 : return InputEventState::Declined;
289 : }
290 42 : return InputEventState::Captured;
291 : }
292 0 : return InputEventState::Declined;
293 : }
294 :
295 63 : InputEventState GestureTouchRecognizer::removeEvent(const InputEvent &event, bool successful, float density) {
296 63 : if (GestureRecognizer::removeEvent(event, successful, density) != InputEventState::Declined) {
297 21 : _event.event = successful ? GestureEvent::Ended : GestureEvent::Cancelled;
298 21 : _event.input = &event;
299 21 : _callback(_event);
300 21 : _event.event = GestureEvent::Cancelled;
301 21 : _event.input = nullptr;
302 21 : return InputEventState::Processed;
303 : }
304 42 : return InputEventState::Declined;
305 : }
306 :
307 63 : InputEventState GestureTouchRecognizer::renewEvent(const InputEvent &event, float density) {
308 63 : if (GestureRecognizer::renewEvent(event, density) != InputEventState::Declined) {
309 42 : _event.event = GestureEvent::Activated;
310 42 : _event.input = &event;
311 42 : if (!_callback(_event)) {
312 21 : removeRecognizedEvent(event.data.id);
313 21 : _event.event = GestureEvent::Cancelled;
314 21 : _event.input = nullptr;
315 21 : return InputEventState::Declined;
316 : }
317 21 : return InputEventState::Processed;
318 : }
319 21 : return InputEventState::Declined;
320 : }
321 :
322 :
323 726 : bool GestureTapRecognizer::init(InputCallback &&cb, ButtonMask &&mask, uint32_t maxTapCount) {
324 726 : if (!GestureRecognizer::init()) {
325 0 : return false;
326 : }
327 :
328 726 : if (cb) {
329 726 : _maxEvents = 1;
330 726 : _maxTapCount = maxTapCount;
331 726 : _callback = move(cb);
332 726 : _buttonMask = move(mask);
333 726 : _eventMask.set(toInt(InputEventName::Begin));
334 726 : _eventMask.set(toInt(InputEventName::Move));
335 726 : _eventMask.set(toInt(InputEventName::End));
336 726 : _eventMask.set(toInt(InputEventName::Cancel));
337 726 : return true;
338 : }
339 0 : return false;
340 : }
341 :
342 109153 : void GestureTapRecognizer::update(uint64_t dt) {
343 109153 : GestureRecognizer::update(dt);
344 :
345 109153 : auto now = Time::now();
346 109153 : if (_gesture.count > 0 && _gesture.time - now > TapIntervalAllowed) {
347 6 : _gesture.event = GestureEvent::Activated;
348 6 : _gesture.input = _events.empty() ? &_tmpEvent : &_events.front();
349 6 : _callback(_gesture);
350 6 : _gesture.event = GestureEvent::Cancelled;
351 6 : _gesture.input = nullptr;
352 6 : _gesture.cleanup();
353 : }
354 109153 : }
355 :
356 21 : void GestureTapRecognizer::cancel() {
357 21 : GestureRecognizer::cancel();
358 21 : _gesture.cleanup();
359 21 : }
360 :
361 1568 : InputEventState GestureTapRecognizer::addEvent(const InputEvent &ev, float density) {
362 1568 : if (_gesture.count > 0 && _gesture.pos.distance(ev.currentLocation) > TapDistanceAllowedMulti * density) {
363 0 : return InputEventState::Declined;
364 : }
365 1568 : if (GestureRecognizer::addEvent(ev, density) != InputEventState::Declined) {
366 1568 : auto count = _gesture.count;
367 1568 : auto time = _gesture.time;
368 1568 : _gesture.cleanup();
369 1568 : if (time - Time::now() < TapIntervalAllowed) {
370 0 : _gesture.count = count;
371 0 : _gesture.time = time;
372 : }
373 1568 : _gesture.id = ev.data.id;
374 1568 : _gesture.pos = ev.currentLocation;
375 1568 : return InputEventState::Processed;
376 : }
377 0 : return InputEventState::Declined;
378 : }
379 :
380 1626 : InputEventState GestureTapRecognizer::removeEvent(const InputEvent &ev, bool successful, float density) {
381 1626 : InputEventState ret = InputEventState::Declined;
382 1626 : if (GestureRecognizer::removeEvent(ev, successful, density) != InputEventState::Declined) {
383 1568 : _tmpEvent = ev;
384 1568 : if (successful && _gesture.pos.distance(ev.currentLocation) <= TapDistanceAllowed * density) {
385 1476 : registerTap();
386 1476 : ret = InputEventState::Processed;
387 : } else {
388 92 : ret = InputEventState::Processed;
389 : }
390 : }
391 1626 : return ret;
392 : }
393 :
394 292 : InputEventState GestureTapRecognizer::renewEvent(const InputEvent &ev, float density) {
395 292 : auto ret = GestureRecognizer::renewEvent(ev, density);
396 292 : if (ret != InputEventState::Declined) {
397 67 : if (_gesture.pos.distance(ev.currentLocation) > TapDistanceAllowed * density) {
398 25 : return removeEvent(ev, false, density);
399 : }
400 : }
401 267 : return ret;
402 : }
403 :
404 1476 : void GestureTapRecognizer::registerTap() {
405 1476 : auto currentTime = Time::now();
406 :
407 1476 : if (currentTime < _gesture.time + TapIntervalAllowed) {
408 0 : _gesture.count ++;
409 : } else {
410 1476 : _gesture.count = 1;
411 : }
412 :
413 1476 : _gesture.time = currentTime;
414 1476 : if (_gesture.count == _maxTapCount) {
415 1407 : _gesture.event = GestureEvent::Activated;
416 1407 : _gesture.input = _events.empty() ? &_tmpEvent : &_events.front();
417 1407 : _callback(_gesture);
418 1407 : _gesture.event = GestureEvent::Cancelled;
419 1407 : _gesture.input = nullptr;
420 1407 : _gesture.cleanup();
421 : }
422 1476 : }
423 :
424 558 : bool GesturePressRecognizer::init(InputCallback &&cb, TimeInterval interval, bool continuous, ButtonMask &&btn) {
425 558 : if (!GestureRecognizer::init()) {
426 0 : return false;
427 : }
428 :
429 558 : if (cb) {
430 558 : _maxEvents = 1;
431 558 : _callback = move(cb);
432 558 : _interval = interval;
433 558 : _continuous = continuous;
434 558 : _buttonMask = move(btn);
435 :
436 : // enable all touch events
437 558 : _eventMask.set(toInt(InputEventName::Begin));
438 558 : _eventMask.set(toInt(InputEventName::Move));
439 558 : _eventMask.set(toInt(InputEventName::End));
440 558 : _eventMask.set(toInt(InputEventName::Cancel));
441 558 : return true;
442 : }
443 0 : return false;
444 : }
445 :
446 42 : void GesturePressRecognizer::cancel() {
447 42 : GestureRecognizer::cancel();
448 42 : _gesture.cleanup();
449 42 : _lastTime.clear();
450 42 : }
451 :
452 79983 : void GesturePressRecognizer::update(uint64_t dt) {
453 79983 : if ((!_notified || _continuous) && _lastTime && _events.size() > 0) {
454 84 : auto time = Time::now() - _lastTime;
455 84 : if (_gesture.time.mksec() / _interval.mksec() != time.mksec() / _interval.mksec()) {
456 84 : _gesture.time = time;
457 84 : ++ _gesture.tickCount;
458 84 : _gesture.event = GestureEvent::Activated;
459 84 : _gesture.input = &_events.front();
460 84 : if (!_callback(_gesture)) {
461 0 : cancel();
462 : }
463 84 : _notified = true;
464 : }
465 : }
466 79983 : }
467 :
468 136 : InputEventState GesturePressRecognizer::addEvent(const InputEvent &event, float density) {
469 136 : if (GestureRecognizer::canAddEvent(event)) {
470 136 : _gesture.cleanup();
471 136 : _gesture.pos = event.currentLocation;
472 136 : _gesture.time.clear();
473 136 : _gesture.limit = _interval;
474 136 : _gesture.event = GestureEvent::Began;
475 136 : _gesture.input = &event;
476 136 : if (_callback(_gesture)) {
477 90 : GestureRecognizer::addEvent(event, density);
478 90 : _lastTime = Time::now();
479 90 : _notified = false;
480 90 : return InputEventState::Captured;
481 : }
482 : }
483 46 : return InputEventState::Declined;
484 : }
485 :
486 163 : InputEventState GesturePressRecognizer::removeEvent(const InputEvent &event, bool successful, float density) {
487 163 : if (GestureRecognizer::removeEvent(event, successful, density) != InputEventState::Declined) {
488 90 : float distance = event.originalLocation.distance(event.currentLocation);
489 90 : _gesture.time = Time::now() - _lastTime;
490 90 : _gesture.event = (successful && distance <= TapDistanceAllowed * density) ? GestureEvent::Ended : GestureEvent::Cancelled;
491 90 : _gesture.input = &event;
492 90 : _callback(_gesture);
493 90 : _gesture.event = GestureEvent::Cancelled;
494 90 : _gesture.input = nullptr;
495 90 : _lastTime.clear();
496 90 : _gesture.cleanup();
497 90 : _notified = true;
498 90 : return InputEventState::Processed;
499 : }
500 73 : return InputEventState::Declined;
501 : }
502 :
503 292 : InputEventState GesturePressRecognizer::renewEvent(const InputEvent &event, float density) {
504 292 : if (GestureRecognizer::renewEvent(event, density) != InputEventState::Declined) {
505 42 : if (event.originalLocation.distance(event.currentLocation) > TapDistanceAllowed * density) {
506 21 : return removeEvent(event, false, density);
507 : }
508 21 : return InputEventState::Processed;
509 : }
510 250 : return InputEventState::Declined;
511 : }
512 :
513 174 : bool GestureSwipeRecognizer::init(InputCallback &&cb, float threshold, bool includeThreshold, ButtonMask &&btn) {
514 174 : if (!GestureRecognizer::init()) {
515 0 : return false;
516 : }
517 :
518 174 : if (cb) {
519 174 : _maxEvents = 2;
520 174 : _callback = move(cb);
521 174 : _threshold = threshold;
522 174 : _includeThreshold = includeThreshold;
523 174 : _buttonMask = move(btn);
524 :
525 : // enable all touch events
526 174 : _eventMask.set(toInt(InputEventName::Begin));
527 174 : _eventMask.set(toInt(InputEventName::Move));
528 174 : _eventMask.set(toInt(InputEventName::End));
529 174 : _eventMask.set(toInt(InputEventName::Cancel));
530 174 : return true;
531 : }
532 0 : return false;
533 : }
534 :
535 21 : void GestureSwipeRecognizer::cancel() {
536 21 : GestureRecognizer::cancel();
537 21 : _gesture.cleanup();
538 21 : _swipeBegin = false;
539 21 : _lastTime.clear();
540 21 : _currentTouch = maxOf<uint32_t>();
541 21 : }
542 :
543 109 : InputEventState GestureSwipeRecognizer::addEvent(const InputEvent &event, float density) {
544 109 : if (GestureRecognizer::addEvent(event, density) != InputEventState::Declined) {
545 109 : Vec2 accum;
546 239 : for (auto &it : _events) {
547 130 : accum = accum + it.currentLocation;
548 : }
549 109 : accum /= float(_events.size());
550 :
551 109 : _gesture.midpoint = accum;
552 109 : _currentTouch = event.data.id;
553 109 : _lastTime = Time::now();
554 109 : return InputEventState::Processed;
555 : } else {
556 0 : return InputEventState::Declined;
557 : }
558 : }
559 :
560 115 : InputEventState GestureSwipeRecognizer::removeEvent(const InputEvent &event, bool successful, float density) {
561 115 : if (GestureRecognizer::removeEvent(event, successful, density) != InputEventState::Declined) {
562 109 : if (_events.size() > 0) {
563 21 : _currentTouch = _events.back().data.id;
564 21 : _lastTime = Time::now();
565 : } else {
566 88 : if (_swipeBegin) {
567 46 : _gesture.event = successful ? GestureEvent::Ended : GestureEvent::Cancelled;
568 46 : _gesture.input = &event;
569 46 : _callback(_gesture);
570 : }
571 :
572 88 : _gesture.event = GestureEvent::Cancelled;
573 88 : _gesture.input = nullptr;
574 88 : _gesture.cleanup();
575 88 : _swipeBegin = false;
576 :
577 88 : _currentTouch = maxOf<uint32_t>();
578 :
579 88 : _velocityX.dropValues();
580 88 : _velocityY.dropValues();
581 :
582 88 : _lastTime.clear();
583 : }
584 109 : return InputEventState::Processed;
585 : }
586 6 : return InputEventState::Declined;
587 : }
588 :
589 334 : InputEventState GestureSwipeRecognizer::renewEvent(const InputEvent &event, float density) {
590 334 : if (GestureRecognizer::renewEvent(event, density) != InputEventState::Declined) {
591 334 : if (_events.size() == 1) {
592 292 : Vec2 current = event.currentLocation;
593 292 : Vec2 prev = (_swipeBegin)?event.previousLocation:event.originalLocation;
594 :
595 292 : _gesture.secondTouch = _gesture.firstTouch = current;
596 292 : _gesture.midpoint = current;
597 :
598 292 : _gesture.delta = current - prev;
599 292 : _gesture.density = density;
600 :
601 292 : if (!_swipeBegin && _gesture.delta.length() > _threshold * density) {
602 25 : _gesture.cleanup();
603 25 : if (_includeThreshold) {
604 25 : _gesture.delta = current - prev;
605 : } else {
606 0 : _gesture.delta = current - event.previousLocation;
607 : }
608 25 : _gesture.secondTouch = _gesture.firstTouch = current;
609 25 : _gesture.midpoint = current;
610 :
611 25 : _swipeBegin = true;
612 25 : _gesture.event = GestureEvent::Began;
613 25 : _gesture.input = &event;
614 25 : if (!_callback(_gesture)) {
615 0 : _swipeBegin = false;
616 0 : cancel();
617 0 : return InputEventState::Declined;
618 : }
619 :
620 25 : if (_includeThreshold) {
621 25 : _gesture.delta = current - event.previousLocation;
622 : }
623 : }
624 :
625 292 : if (_swipeBegin /* && _gesture.delta.length() > 0.01f */) {
626 271 : auto t = Time::now();
627 271 : float tm = (float)1000000LL / (float)((t - _lastTime).toMicroseconds());
628 271 : if (tm > 80) {
629 24 : tm = 80;
630 : }
631 :
632 271 : float velX = _velocityX.step(_gesture.delta.x * tm);
633 271 : float velY = _velocityY.step(_gesture.delta.y * tm);
634 :
635 271 : _gesture.velocity = Vec2(velX, velY);
636 271 : _gesture.event = GestureEvent::Activated;
637 271 : _gesture.input = &event;
638 271 : if (!_callback(_gesture)) {
639 0 : cancel();
640 0 : return InputEventState::Declined;
641 : }
642 :
643 271 : _lastTime = t;
644 : }
645 42 : } else if (_events.size() == 2) {
646 42 : Vec2 current = event.currentLocation;
647 42 : Vec2 second = _gesture.secondTouch;
648 42 : Vec2 prev = _gesture.midpoint;
649 :
650 42 : _gesture.density = density;
651 :
652 42 : if (event.data.id != _currentTouch) {
653 21 : second = _gesture.secondTouch = current;
654 21 : } else if (event.data.id == _currentTouch) {
655 21 : _gesture.firstTouch = current;
656 21 : _gesture.midpoint = _gesture.secondTouch.getMidpoint(_gesture.firstTouch);
657 21 : _gesture.delta = _gesture.midpoint - prev;
658 :
659 21 : if (!_swipeBegin && _gesture.delta.length() > _threshold * density) {
660 21 : _gesture.cleanup();
661 21 : _gesture.firstTouch = current;
662 21 : _gesture.secondTouch = current;
663 21 : _gesture.midpoint = _gesture.secondTouch.getMidpoint(_gesture.firstTouch);
664 21 : _gesture.delta = _gesture.midpoint - prev;
665 :
666 21 : _swipeBegin = true;
667 21 : _gesture.event = GestureEvent::Began;
668 21 : _gesture.input = &event;
669 21 : if (!_callback(_gesture)) {
670 0 : cancel();
671 0 : return InputEventState::Declined;
672 : }
673 : }
674 :
675 21 : if (_swipeBegin /* && _gesture.delta.length() > 0.01f */ ) {
676 21 : auto t = Time::now();
677 21 : float tm = (float)1000000LL / (float)((t - _lastTime).toMicroseconds());
678 21 : if (tm > 80) {
679 21 : tm = 80;
680 : }
681 :
682 21 : float velX = _velocityX.step(_gesture.delta.x * tm);
683 21 : float velY = _velocityY.step(_gesture.delta.y * tm);
684 :
685 21 : _gesture.velocity = Vec2(velX, velY);
686 21 : _gesture.event = GestureEvent::Activated;
687 21 : _gesture.input = &event;
688 21 : if (!_callback(_gesture)) {
689 0 : cancel();
690 0 : return InputEventState::Declined;
691 : }
692 :
693 21 : _lastTime = t;
694 : }
695 : }
696 : }
697 334 : return _swipeBegin ? InputEventState::Captured : InputEventState::Processed;
698 : } else {
699 0 : return InputEventState::Declined;
700 : }
701 : }
702 :
703 42 : bool GesturePinchRecognizer::init(InputCallback &&cb, ButtonMask &&btn) {
704 42 : if (!GestureRecognizer::init()) {
705 0 : return false;
706 : }
707 :
708 42 : if (cb) {
709 42 : _maxEvents = 2;
710 42 : _callback = move(cb);
711 42 : _buttonMask = move(btn);
712 :
713 : // enable all touch events
714 42 : _eventMask.set(toInt(InputEventName::Begin));
715 42 : _eventMask.set(toInt(InputEventName::Move));
716 42 : _eventMask.set(toInt(InputEventName::End));
717 42 : _eventMask.set(toInt(InputEventName::Cancel));
718 42 : return true;
719 : }
720 0 : return false;
721 : }
722 :
723 21 : void GesturePinchRecognizer::cancel() {
724 21 : GestureRecognizer::cancel();
725 21 : _gesture.cleanup();
726 21 : _velocity.dropValues();
727 21 : _lastTime.clear();
728 21 : }
729 :
730 42 : InputEventState GesturePinchRecognizer::addEvent(const InputEvent &event, float density) {
731 42 : if (GestureRecognizer::addEvent(event, density) != InputEventState::Declined) {
732 42 : if (_events.size() == 2) {
733 21 : _gesture.cleanup();
734 21 : _gesture.first = _events.at(0).currentLocation;
735 21 : _gesture.second = _events.at(1).currentLocation;
736 21 : _gesture.center = _gesture.first.getMidpoint(_gesture.second);
737 21 : _gesture.distance = _gesture.prevDistance = _gesture.startDistance = _gesture.first.distance(_gesture.second);
738 21 : _gesture.scale = _gesture.distance / _gesture.startDistance;
739 21 : _gesture.event = GestureEvent::Began;
740 21 : _gesture.input = &_events.at(0);
741 21 : _gesture.density = density;
742 21 : _lastTime = Time::now();
743 21 : if (_callback) {
744 21 : _callback(_gesture);
745 : }
746 21 : return InputEventState::Captured;
747 : }
748 21 : return InputEventState::Processed;
749 : } else {
750 0 : return InputEventState::Declined;
751 : }
752 : }
753 :
754 42 : InputEventState GesturePinchRecognizer::removeEvent(const InputEvent &event, bool successful, float density) {
755 42 : if (GestureRecognizer::removeEvent(event, successful, density) != InputEventState::Declined) {
756 42 : if (_events.size() == 1) {
757 21 : _gesture.event = successful ? GestureEvent::Ended : GestureEvent::Cancelled;
758 21 : if (_callback) {
759 21 : _callback(_gesture);
760 : }
761 21 : _gesture.cleanup();
762 21 : _lastTime.clear();
763 21 : _velocity.dropValues();
764 : }
765 42 : return InputEventState::Processed;
766 : }
767 0 : return InputEventState::Declined;
768 : }
769 :
770 42 : InputEventState GesturePinchRecognizer::renewEvent(const InputEvent &event, float density) {
771 42 : if (GestureRecognizer::renewEvent(event, density) != InputEventState::Declined) {
772 42 : if (_events.size() == 2) {
773 42 : auto &first = _events.at(0);
774 42 : auto &second = _events.at(1);
775 42 : if (event.data.id == first.data.id || event.data.id == second.data.id) {
776 42 : auto scale = _gesture.scale;
777 :
778 42 : _gesture.first = _events.at(0).currentLocation;
779 42 : _gesture.second = _events.at(1).currentLocation;
780 42 : _gesture.center = _gesture.first.getMidpoint(_gesture.second);
781 42 : _gesture.prevDistance = _events.at(0).previousLocation.distance(_events.at(1).previousLocation);
782 42 : _gesture.distance = _gesture.first.distance(_gesture.second);
783 42 : _gesture.scale = _gesture.distance / _gesture.startDistance;
784 42 : _gesture.density = density;
785 :
786 42 : auto t = Time::now();
787 42 : float tm = (float)1000000LL / (float)((t - _lastTime).toMicroseconds());
788 42 : if (tm > 80) {
789 42 : tm = 80;
790 : }
791 42 : _velocity.addValue((scale - _gesture.scale) * tm);
792 42 : _gesture.velocity = _velocity.getAverage();
793 :
794 42 : _gesture.event = GestureEvent::Activated;
795 42 : if (_callback) {
796 42 : _callback(_gesture);
797 : }
798 :
799 42 : _lastTime = t;
800 : }
801 42 : return InputEventState::Captured;
802 : }
803 0 : return InputEventState::Processed;
804 : }
805 0 : return InputEventState::Declined;
806 : }
807 :
808 132 : bool GestureScrollRecognizer::init(InputCallback &&cb) {
809 132 : if (!GestureRecognizer::init()) {
810 0 : return false;
811 : }
812 :
813 132 : if (cb) {
814 132 : _callback = move(cb);
815 132 : _eventMask.set(toInt(InputEventName::Scroll));
816 132 : return true;
817 : }
818 :
819 0 : return false;
820 : }
821 :
822 369 : InputEventState GestureScrollRecognizer::handleInputEvent(const InputEvent &event, float density) {
823 369 : if (!_eventMask.test(toInt(event.data.event))) {
824 348 : return InputEventState::Declined;
825 : }
826 :
827 21 : _gesture.event = GestureEvent::Activated;
828 21 : _gesture.input = &event;
829 21 : _gesture.pos = event.currentLocation;
830 21 : _gesture.amount = Vec2(event.data.point.valueX, event.data.point.valueY);
831 21 : if (_callback) {
832 21 : _callback(_gesture);
833 : }
834 21 : _gesture.event = GestureEvent::Cancelled;
835 21 : return InputEventState::Captured;
836 : }
837 :
838 :
839 42 : bool GestureMoveRecognizer::init(InputCallback &&cb, bool withinNode) {
840 42 : if (!GestureRecognizer::init()) {
841 0 : return false;
842 : }
843 :
844 42 : if (cb) {
845 42 : _callback = move(cb);
846 42 : _eventMask.set(toInt(InputEventName::MouseMove));
847 42 : _onlyWithinNode = withinNode;
848 42 : return true;
849 : }
850 :
851 0 : return false;
852 : }
853 :
854 4152 : bool GestureMoveRecognizer::canHandleEvent(const InputEvent &event) const {
855 4152 : if (GestureRecognizer::canHandleEvent(event)) {
856 4958 : if (!_onlyWithinNode || (_listener && _listener->getOwner()
857 2458 : && _listener->getOwner()->isTouched(event.currentLocation, _listener->getTouchPadding()))) {
858 2484 : return true;
859 : }
860 : }
861 1668 : return false;
862 : }
863 :
864 2873 : InputEventState GestureMoveRecognizer::handleInputEvent(const InputEvent &event, float density) {
865 2873 : if (!canHandleEvent(event)) {
866 1631 : return InputEventState::Declined;
867 : }
868 :
869 1242 : if (!_eventMask.test(toInt(event.data.event))) {
870 0 : return InputEventState::Declined;
871 : }
872 :
873 1242 : _event.event = GestureEvent::Activated;
874 1242 : _event.input = &event;
875 1242 : if (_callback) {
876 1242 : _callback(_event);
877 : }
878 1242 : _event.input = nullptr;
879 1242 : _event.event = GestureEvent::Cancelled;
880 1242 : return InputEventState::Processed;
881 : }
882 :
883 21 : void GestureMoveRecognizer::onEnter(InputListener *l) {
884 21 : GestureRecognizer::onEnter(l);
885 21 : _listener = l;
886 21 : }
887 :
888 21 : void GestureMoveRecognizer::onExit() {
889 21 : _listener = nullptr;
890 21 : GestureRecognizer::onExit();
891 21 : }
892 :
893 126 : bool GestureKeyRecognizer::init(InputCallback &&cb, KeyMask &&mask) {
894 126 : if (!GestureRecognizer::init()) {
895 0 : return false;
896 : }
897 :
898 126 : if (cb && mask.any()) {
899 126 : _callback = move(cb);
900 126 : _keyMask = mask;
901 126 : _eventMask.set(toInt(InputEventName::KeyPressed));
902 126 : _eventMask.set(toInt(InputEventName::KeyRepeated));
903 126 : _eventMask.set(toInt(InputEventName::KeyReleased));
904 126 : _eventMask.set(toInt(InputEventName::KeyCanceled));
905 126 : return true;
906 : }
907 :
908 0 : log::error("GestureKeyRecognizer", "Callback or key mask is not defined");
909 0 : return false;
910 : }
911 :
912 4258 : bool GestureKeyRecognizer::canHandleEvent(const InputEvent &ev) const {
913 4258 : if (GestureRecognizer::canHandleEvent(ev)) {
914 126 : if (_keyMask.test(toInt(ev.data.key.keycode))) {
915 84 : return true;
916 : }
917 : }
918 4174 : return false;
919 : }
920 :
921 42 : bool GestureKeyRecognizer::isKeyPressed(InputKeyCode code) const {
922 42 : if (_pressedKeys.test(toInt(code))) {
923 21 : return true;
924 : }
925 21 : return false;
926 : }
927 :
928 42 : InputEventState GestureKeyRecognizer::addEvent(const InputEvent &event, float density) {
929 42 : if (_keyMask.test(toInt(event.data.key.keycode))) {
930 42 : _pressedKeys.set(toInt(event.data.key.keycode));
931 42 : return _callback(GestureData{GestureEvent::Began, &event}) ? InputEventState::Captured : InputEventState::Declined;
932 : }
933 0 : return InputEventState::Declined;
934 : }
935 :
936 42 : InputEventState GestureKeyRecognizer::removeEvent(const InputEvent &event, bool success, float density) {
937 42 : if (_pressedKeys.test(toInt(event.data.key.keycode))) {
938 42 : _callback(GestureData{success ? GestureEvent::Ended : GestureEvent::Cancelled, &event});
939 42 : _pressedKeys.reset(toInt(event.data.key.keycode));
940 42 : return InputEventState::Processed;
941 : }
942 0 : return InputEventState::Declined;
943 : }
944 :
945 21 : InputEventState GestureKeyRecognizer::renewEvent(const InputEvent &event, float density) {
946 21 : if (_pressedKeys.test(toInt(event.data.key.keycode))) {
947 21 : _callback(GestureData{GestureEvent::Activated, &event});
948 21 : return InputEventState::Processed;
949 : }
950 0 : return InputEventState::Declined;
951 : }
952 :
953 447 : bool GestureMouseOverRecognizer::init(InputCallback &&cb, float padding) {
954 447 : if (!GestureRecognizer::init()) {
955 0 : return false;
956 : }
957 :
958 447 : if (cb) {
959 447 : _callback = move(cb);
960 447 : _eventMask.set(toInt(InputEventName::MouseMove));
961 447 : _eventMask.set(toInt(InputEventName::FocusGain));
962 447 : _eventMask.set(toInt(InputEventName::PointerEnter));
963 447 : return true;
964 : }
965 :
966 0 : log::error("GestureKeyRecognizer", "Callback or key mask is not defined");
967 0 : return false;
968 : }
969 :
970 760 : InputEventState GestureMouseOverRecognizer::handleInputEvent(const InputEvent &event, float density) {
971 760 : switch (event.data.event) {
972 43 : case InputEventName::FocusGain:
973 43 : if (_viewHasFocus != event.data.getValue()) {
974 41 : _viewHasFocus = event.data.getValue();
975 41 : updateState(event);
976 : }
977 43 : break;
978 49 : case InputEventName::PointerEnter:
979 49 : if (_viewHasPointer != event.data.getValue()) {
980 45 : _viewHasPointer = event.data.getValue();
981 45 : updateState(event);
982 : }
983 49 : break;
984 572 : case InputEventName::MouseMove:
985 572 : if (auto tar = _listener->getOwner()) {
986 572 : auto v = tar->isTouched(event.currentLocation, _padding);
987 572 : if (_hasMouseOver != v) {
988 21 : _hasMouseOver = v;
989 21 : updateState(event);
990 : }
991 : } else {
992 0 : if (_hasMouseOver) {
993 0 : _hasMouseOver = false;
994 0 : updateState(event);
995 : }
996 : }
997 572 : break;
998 96 : default:
999 96 : break;
1000 : }
1001 760 : return InputEventState::Processed;
1002 : }
1003 :
1004 426 : void GestureMouseOverRecognizer::onEnter(InputListener *l) {
1005 426 : GestureRecognizer::onEnter(l);
1006 426 : _listener = l;
1007 :
1008 426 : auto dispatcher = l->getOwner()->getDirector()->getInputDispatcher();
1009 :
1010 426 : _viewHasPointer = dispatcher->isPointerWithinWindow();
1011 426 : _viewHasFocus = dispatcher->hasFocus();
1012 426 : }
1013 :
1014 426 : void GestureMouseOverRecognizer::onExit() {
1015 426 : _listener = nullptr;
1016 426 : GestureRecognizer::onExit();
1017 426 : }
1018 :
1019 107 : void GestureMouseOverRecognizer::updateState(const InputEvent &event) {
1020 107 : auto value = _viewHasFocus && _viewHasPointer && _hasMouseOver;
1021 107 : if (value != _value) {
1022 4 : _value = value;
1023 4 : _event.input = &event;
1024 4 : _event.event = _value ? GestureEvent::Began : GestureEvent::Ended;
1025 4 : _callback(_event);
1026 : }
1027 107 : }
1028 :
1029 84 : std::ostream &operator<<(std::ostream &stream, GestureEvent ev) {
1030 84 : switch (ev) {
1031 21 : case GestureEvent::Began: stream << "GestureEvent::Began"; break;
1032 21 : case GestureEvent::Activated: stream << "GestureEvent::Activated"; break;
1033 21 : case GestureEvent::Ended: stream << "GestureEvent::Ended"; break;
1034 21 : case GestureEvent::Cancelled: stream << "GestureEvent::Cancelled"; break;
1035 : }
1036 84 : return stream;
1037 : }
1038 :
1039 : }
|