LCOV - code coverage report
Current view: top level - lib/src/components/input - joystick_component.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 25 48 52.1 %
Date: 2021-08-10 15:50:53 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:math';
       2             : 
       3             : import 'package:flutter/rendering.dart' show EdgeInsets;
       4             : 
       5             : import '../../../components.dart';
       6             : import '../../../extensions.dart';
       7             : import '../../gestures/events.dart';
       8             : import 'hud_margin_component.dart';
       9             : 
      10          41 : enum JoystickDirection {
      11             :   up,
      12             :   upLeft,
      13             :   upRight,
      14             :   right,
      15             :   down,
      16             :   downRight,
      17             :   downLeft,
      18             :   left,
      19             :   idle,
      20             : }
      21             : 
      22             : class JoystickComponent extends HudMarginComponent with Draggable {
      23             :   late final PositionComponent knob;
      24             :   late final PositionComponent? background;
      25             : 
      26             :   /// The percentage [0.0, 1.0] the knob is dragged from the center to the edge.
      27             :   double intensity = 0.0;
      28             : 
      29             :   /// The amount the knob is dragged from the center.
      30             :   Vector2 delta = Vector2.zero();
      31             : 
      32             :   /// The percentage, presented as a [Vector2], and direction that the knob is
      33             :   /// currently pulled from its base position to a edge of the joystick.
      34           0 :   Vector2 get relativeDelta => delta / knobRadius;
      35             : 
      36             :   /// The radius from the center of the knob to the edge of as far as the knob
      37             :   /// can be dragged.
      38             :   late double knobRadius;
      39             : 
      40             :   /// The position where the knob rests.
      41             :   late Vector2 _baseKnobPosition;
      42             : 
      43           1 :   JoystickComponent({
      44             :     required this.knob,
      45             :     this.background,
      46             :     EdgeInsets? margin,
      47             :     Vector2? position,
      48             :     double? size,
      49             :     double? knobRadius,
      50             :     Anchor anchor = Anchor.center,
      51             :   })  : assert(
      52           0 :           size != null || background != null,
      53             :           'Either size or background must be defined',
      54             :         ),
      55             :         assert(
      56           2 :           knob.position.isZero() && (background?.position.isZero() ?? true),
      57             :           'Positions should not be set for the knob or the background',
      58             :         ),
      59           1 :         super(
      60             :           margin: margin,
      61             :           position: position,
      62           1 :           size: background?.size ?? Vector2.all(size ?? 0),
      63             :           anchor: anchor,
      64             :         ) {
      65           4 :     this.knobRadius = knobRadius ?? this.size.x / 2;
      66             :   }
      67             : 
      68             :   @override
      69           1 :   Future<void> onLoad() async {
      70           2 :     await super.onLoad();
      71           2 :     knob.anchor = Anchor.center;
      72           5 :     knob.position.add(size / 2);
      73           4 :     _baseKnobPosition = knob.position.clone();
      74           1 :     if (background != null) {
      75           0 :       addChild(background!);
      76             :     }
      77           2 :     addChild(knob);
      78             :   }
      79             : 
      80           0 :   @override
      81             :   void update(double dt) {
      82           0 :     super.update(dt);
      83           0 :     final knobRadius2 = knobRadius * knobRadius;
      84           0 :     if (delta.isZero() && _baseKnobPosition != knob.position) {
      85           0 :       knob.position = _baseKnobPosition;
      86           0 :     } else if (delta.length2 > knobRadius2) {
      87           0 :       delta.scaleTo(knobRadius);
      88             :     }
      89           0 :     if (!delta.isZero()) {
      90           0 :       knob.position
      91           0 :         ..setFrom(_baseKnobPosition)
      92           0 :         ..add(delta);
      93             :     }
      94           0 :     intensity = delta.length2 / knobRadius2;
      95             :   }
      96             : 
      97           0 :   @override
      98             :   bool onDragStart(int pointerId, DragStartInfo info) {
      99             :     return false;
     100             :   }
     101             : 
     102           0 :   @override
     103             :   bool onDragUpdate(_, DragUpdateInfo info) {
     104           0 :     delta.add(info.delta.global);
     105             :     return false;
     106             :   }
     107             : 
     108           0 :   @override
     109             :   bool onDragEnd(int id, __) {
     110           0 :     onDragCancel(id);
     111             :     return false;
     112             :   }
     113             : 
     114           0 :   @override
     115             :   bool onDragCancel(_) {
     116           0 :     delta.setZero();
     117             :     return false;
     118             :   }
     119             : 
     120             :   static const double _eighthOfPi = pi / 8;
     121             : 
     122           1 :   JoystickDirection get direction {
     123           2 :     if (delta.isZero()) {
     124             :       return JoystickDirection.idle;
     125             :     }
     126             : 
     127           2 :     var knobAngle = delta.screenAngle();
     128             :     // Since screenAngle and angleTo doesn't care about "direction" of the angle
     129             :     // we have to use angleToSigned and create an only increasing angle by
     130             :     // removing negative angles from 2*pi.
     131           3 :     knobAngle = knobAngle < 0 ? 2 * pi + knobAngle : knobAngle;
     132           2 :     if (knobAngle >= 0 && knobAngle <= _eighthOfPi) {
     133             :       return JoystickDirection.up;
     134           4 :     } else if (knobAngle > 1 * _eighthOfPi && knobAngle <= 3 * _eighthOfPi) {
     135             :       return JoystickDirection.upRight;
     136           4 :     } else if (knobAngle > 3 * _eighthOfPi && knobAngle <= 5 * _eighthOfPi) {
     137             :       return JoystickDirection.right;
     138           4 :     } else if (knobAngle > 5 * _eighthOfPi && knobAngle <= 7 * _eighthOfPi) {
     139             :       return JoystickDirection.downRight;
     140           4 :     } else if (knobAngle > 7 * _eighthOfPi && knobAngle <= 9 * _eighthOfPi) {
     141             :       return JoystickDirection.down;
     142           4 :     } else if (knobAngle > 9 * _eighthOfPi && knobAngle <= 11 * _eighthOfPi) {
     143             :       return JoystickDirection.downLeft;
     144           4 :     } else if (knobAngle > 11 * _eighthOfPi && knobAngle <= 13 * _eighthOfPi) {
     145             :       return JoystickDirection.left;
     146           4 :     } else if (knobAngle > 13 * _eighthOfPi && knobAngle <= 15 * _eighthOfPi) {
     147             :       return JoystickDirection.upLeft;
     148           0 :     } else if (knobAngle > 15 * _eighthOfPi) {
     149             :       return JoystickDirection.up;
     150             :     } else {
     151             :       return JoystickDirection.idle;
     152             :     }
     153             :   }
     154             : }

Generated by: LCOV version 1.15