Line data Source code
1 : import 'dart:math'; 2 : import 'dart:ui'; 3 : 4 : import 'package:vector_math/vector_math_64.dart'; 5 : 6 : export 'package:vector_math/vector_math_64.dart' hide Colors; 7 : 8 : extension Vector2Extension on Vector2 { 9 : /// Creates an [Offset] from the [Vector2] 10 0 : Offset toOffset() => Offset(x, y); 11 : 12 : /// Creates a [Size] from the [Vector2] 13 0 : Size toSize() => Size(x, y); 14 : 15 : /// Creates a [Point] from the [Vector2] 16 0 : Point toPoint() => Point(x, y); 17 : 18 : /// A rectangle constructor operator. 19 : /// 20 : /// Combines two [Vector2]s to form a Rect whose top-left coordinate is the 21 : /// point given by adding this vector, the left-hand-side operand, 22 : /// to the origin, and whose size is the right-hand-side operand. 23 8 : Rect operator &(Vector2 size) => toPositionedRect(size); 24 : 25 : /// Creates a [Rect] starting from [x, y] and having the size of the 26 : /// argument [Vector2] 27 78 : Rect toPositionedRect(Vector2 size) => Rect.fromLTWH(x, y, size.x, size.y); 28 : 29 : /// Creates a [Rect] starting in origin and going the [Vector2] 30 8 : Rect toRect() => Rect.fromLTWH(0, 0, x, y); 31 : 32 : /// Linearly interpolate towards another Vector2 33 0 : void lerp(Vector2 to, double t) { 34 0 : setFrom(this + (to - this) * t); 35 : } 36 : 37 : /// Whether the [Vector2] is the zero vector or not 38 125 : bool isZero() => x == 0 && y == 0; 39 : 40 : /// Rotates the [Vector2] with [angle] in radians 41 : /// rotates around [center] if it is defined 42 : /// In a screen coordinate system (where the y-axis is flipped) it rotates in 43 : /// a clockwise fashion 44 : /// In a normal coordinate system it rotates in a counter-clockwise fashion 45 8 : void rotate(double angle, {Vector2? center}) { 46 16 : if (isZero() || angle == 0) { 47 : // No point in rotating the zero vector or to rotate with 0 as angle 48 : return; 49 : } 50 : if (center == null) { 51 1 : setValues( 52 7 : x * cos(angle) - y * sin(angle), 53 7 : x * sin(angle) + y * cos(angle), 54 : ); 55 : } else { 56 2 : setValues( 57 26 : cos(angle) * (x - center.x) - sin(angle) * (y - center.y) + center.x, 58 26 : sin(angle) * (x - center.x) + cos(angle) * (y - center.y) + center.y, 59 : ); 60 : } 61 : } 62 : 63 : /// Changes the [length] of the vector to the length provided, without 64 : /// changing direction. 65 : /// 66 : /// If you try to scale the zero (empty) vector, it will remain unchanged, and 67 : /// no error will be thrown. 68 2 : void scaleTo(double newLength) { 69 2 : final l = length; 70 2 : if (l != 0) { 71 6 : scale(newLength.abs() / l); 72 : } 73 : } 74 : 75 : /// Smoothly moves this [Vector2] in the direction [target] by a displacement 76 : /// given by a distance [ds] in that direction. 77 : /// 78 : /// It does not goes beyond target, regardless of [ds], so the final value 79 : /// is always [target]. 80 : /// 81 : /// Note: [ds] is the displacement vector in units of the vector space. It is 82 : /// **not** a percentage (relative value). 83 23 : void moveToTarget( 84 : Vector2 target, 85 : double ds, 86 : ) { 87 23 : if (this != target) { 88 2 : final diff = target - this; 89 4 : if (diff.length < ds) { 90 2 : setFrom(target); 91 : } else { 92 2 : diff.scaleTo(ds); 93 4 : setFrom(this + diff); 94 : } 95 : } 96 : } 97 : 98 : /// Signed angle in a coordinate system where the Y-axis is flipped. 99 : /// 100 : /// Since on a canvas/screen y is smaller the further up you go, instead of 101 : /// larger like on a normal coordinate system, to get an angle that is in that 102 : /// coordinate system we have to flip the Y-axis of the [Vector]. 103 : /// 104 : /// Example: 105 : /// Up: Vector(0.0, -1.0).screenAngle == 0 106 : /// Down: Vector(0.0, 1.0).screenAngle == +-pi 107 : /// Left: Vector(-1.0, 0.0).screenAngle == -pi/2 108 : /// Right: Vector(-1.0, 0.0).screenAngle == pi/2 109 14 : double screenAngle() => (clone()..y *= -1).angleToSigned(Vector2(0.0, 1.0)); 110 : 111 : /// Modulo/Remainder 112 0 : Vector2 operator %(Vector2 mod) => Vector2(x % mod.x, y % mod.y); 113 : 114 : /// Create a Vector2 with ints as input 115 20 : static Vector2 fromInts(int x, int y) => Vector2(x.toDouble(), y.toDouble()); 116 : 117 : /// Creates a heading [Vector2] with the given angle in radians. 118 0 : static Vector2 fromRadians(double r) => Vector2.zero()..rotate(r); 119 : 120 : /// Creates a heading [Vector2] with the given angle in degrees. 121 0 : static Vector2 fromDegrees(double d) => fromRadians(d * degrees2Radians); 122 : }