mobile gesture handler

This commit is contained in:
Nick Fisher
2024-10-11 15:37:03 +08:00
parent f267aa6dc6
commit f180c1018f
3 changed files with 58 additions and 31 deletions

View File

@@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:math';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:thermion_dart/thermion_dart.dart'; import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart';
@@ -26,6 +27,8 @@ class DelegateInputHandler implements InputHandler {
Map<InputType, InputAction> _actions = { Map<InputType, InputAction> _actions = {
InputType.LMB_HOLD_AND_MOVE: InputAction.TRANSLATE, InputType.LMB_HOLD_AND_MOVE: InputAction.TRANSLATE,
InputType.SCALE1: InputAction.TRANSLATE,
InputType.SCALE2: InputAction.ZOOM,
InputType.MMB_HOLD_AND_MOVE: InputAction.ROTATE, InputType.MMB_HOLD_AND_MOVE: InputAction.ROTATE,
InputType.SCROLLWHEEL: InputAction.TRANSLATE, InputType.SCROLLWHEEL: InputAction.TRANSLATE,
InputType.POINTER_MOVE: InputAction.NONE, InputType.POINTER_MOVE: InputAction.NONE,
@@ -99,6 +102,8 @@ class DelegateInputHandler implements InputHandler {
InputType.KEYDOWN_W: InputAction.TRANSLATE, InputType.KEYDOWN_W: InputAction.TRANSLATE,
InputType.KEYDOWN_S: InputAction.TRANSLATE, InputType.KEYDOWN_S: InputAction.TRANSLATE,
InputType.KEYDOWN_D: InputAction.TRANSLATE, InputType.KEYDOWN_D: InputAction.TRANSLATE,
InputType.SCALE1: InputAction.TRANSLATE,
InputType.SCALE2: InputAction.ZOOM,
if (freeLook) InputType.POINTER_MOVE: InputAction.ROTATE, if (freeLook) InputType.POINTER_MOVE: InputAction.ROTATE,
}); });
@@ -235,15 +240,6 @@ class DelegateInputHandler implements InputHandler {
@override @override
Future<bool> get initialized => viewer.initialized; Future<bool> get initialized => viewer.initialized;
@override
Future<void> onScaleEnd() async {}
@override
Future<void> onScaleStart() async {}
@override
Future<void> onScaleUpdate() async {}
@override @override
void setActionForType(InputType gestureType, InputAction gestureAction) { void setActionForType(InputType gestureType, InputAction gestureAction) {
_actions[gestureType] = gestureAction; _actions[gestureType] = gestureAction;
@@ -261,4 +257,26 @@ class DelegateInputHandler implements InputHandler {
void keyUp(PhysicalKey key) { void keyUp(PhysicalKey key) {
_pressedKeys.remove(key); _pressedKeys.remove(key);
} }
@override
Future<void> onScaleEnd(int pointerCount) async {}
@override
Future<void> onScaleStart(Vector2 localPosition, int pointerCount) async {
// noop
}
@override
Future<void> onScaleUpdate(Vector2 focalPoint, Vector2 focalPointDelta,
double horizontalScale, double verticalScale, double scale, int pointerCount) async {
if (pointerCount == 1) {
_inputDeltas[InputType.SCALE1] =
Vector3(focalPointDelta.x, focalPointDelta.y, 0);
} else if (pointerCount == 2) {
_inputDeltas[InputType.SCALE2] =
Vector3(0, 0, max(horizontalScale, verticalScale));
} else {
throw UnimplementedError("Only pointerCount <= 2 supported");
}
}
} }

View File

@@ -35,9 +35,9 @@ abstract class InputHandler {
Future<void> onPointerMove( Future<void> onPointerMove(
Vector2 localPosition, Vector2 delta, bool isMiddle); Vector2 localPosition, Vector2 delta, bool isMiddle);
Future<void> onPointerUp(bool isMiddle); Future<void> onPointerUp(bool isMiddle);
Future<void> onScaleStart(); Future<void> onScaleStart(Vector2 focalPoint, int pointerCount);
Future<void> onScaleUpdate(); Future<void> onScaleUpdate(Vector2 focalPoint, Vector2 focalPointDelta, double horizontalScale, double verticalScale, double scale, int pointerCount);
Future<void> onScaleEnd(); Future<void> onScaleEnd(int pointerCount);
Future<bool> get initialized; Future<bool> get initialized;
Future dispose(); Future dispose();

View File

@@ -110,7 +110,7 @@ class _ThermionListenerWidgetState extends State<ThermionListenerWidget> {
Widget _mobile(double pixelRatio) { Widget _mobile(double pixelRatio) {
return _MobileListenerWidget( return _MobileListenerWidget(
gestureHandler: widget.gestureHandler, pixelRatio: pixelRatio); gestureHandler: widget.gestureHandler, pixelRatio: pixelRatio, child:widget.child);
} }
@override @override
@@ -135,8 +135,10 @@ class _ThermionListenerWidgetState extends State<ThermionListenerWidget> {
class _MobileListenerWidget extends StatefulWidget { class _MobileListenerWidget extends StatefulWidget {
final InputHandler gestureHandler; final InputHandler gestureHandler;
final double pixelRatio; final double pixelRatio;
final Widget? child;
const _MobileListenerWidget({Key? key, required this.gestureHandler, required this.pixelRatio}) const _MobileListenerWidget(
{Key? key, required this.gestureHandler, required this.pixelRatio, this.child})
: super(key: key); : super(key: key);
@override @override
@@ -154,22 +156,29 @@ class _MobileListenerWidgetState extends State<_MobileListenerWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
onTapDown: (details) => widget.gestureHandler onTapDown: (details) => widget.gestureHandler.onPointerDown(
.onPointerDown(details.localPosition.toVector2() * widget.pixelRatio, false), details.localPosition.toVector2() * widget.pixelRatio, false),
onDoubleTap: () { onDoubleTap: () {
widget.gestureHandler.setActionForType(InputType.SCALE1, widget.gestureHandler.setActionForType(InputType.SCALE1,
isPan ? InputAction.TRANSLATE : InputAction.ROTATE); isPan ? InputAction.TRANSLATE : InputAction.ROTATE);
}, },
onScaleStart: (details) async { onScaleStart: (details) async {
await widget.gestureHandler.onScaleStart(); await widget.gestureHandler.onScaleStart(
}, details.localFocalPoint.toVector2(), details.pointerCount);
onScaleUpdate: (details) async { },
await widget.gestureHandler.onScaleUpdate(); onScaleUpdate: (ScaleUpdateDetails details) async {
}, await widget.gestureHandler.onScaleUpdate(
onScaleEnd: (details) async { details.localFocalPoint.toVector2(),
await widget.gestureHandler.onScaleUpdate(); details.focalPointDelta.toVector2(),
}, details.horizontalScale,
); details.verticalScale,
details.scale,
details.pointerCount);
},
onScaleEnd: (details) async {
await widget.gestureHandler.onScaleEnd(details.pointerCount);
},
child: widget.child);
} }
} }