mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Improvements to EffectLine in sprites
This commit is contained in:
parent
93ebc9e417
commit
a66a5c4bff
@ -42,19 +42,20 @@ class TestApp extends App {
|
|||||||
List<String> _labelTexts = [
|
List<String> _labelTexts = [
|
||||||
"Colored",
|
"Colored",
|
||||||
"Smoke",
|
"Smoke",
|
||||||
"Electric"
|
"Electric",
|
||||||
|
"Rocket Trail"
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget build() {
|
Widget build() {
|
||||||
ThemeData theme = new ThemeData(
|
ThemeData theme = new ThemeData(
|
||||||
brightness: ThemeBrightness.light,
|
brightness: ThemeBrightness.light,
|
||||||
primarySwatch: Colors.purple
|
primarySwatch: Colors.blue
|
||||||
);
|
);
|
||||||
|
|
||||||
return new Theme(
|
return new Theme(
|
||||||
data: theme,
|
data: theme,
|
||||||
child: new Title(
|
child: new Title(
|
||||||
title: 'Test drawAtlas',
|
title: 'EffectLine Demo',
|
||||||
child: _buildColumn()
|
child: _buildColumn()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -114,11 +115,10 @@ class TestBed extends NodeWithSize {
|
|||||||
// Create a line with no texture and a color sequence
|
// Create a line with no texture and a color sequence
|
||||||
_line = new EffectLine(
|
_line = new EffectLine(
|
||||||
texture: null,
|
texture: null,
|
||||||
colorSequence: new ColorSequence.fromStartAndEndColor(new Color(0xffff0000), new Color(0xff0000ff)),
|
colorSequence: new ColorSequence.fromStartAndEndColor(new Color(0xaaffff00), new Color(0xaaff9900)),
|
||||||
widthMode: EffectLineWidthMode.barrel,
|
widthMode: EffectLineWidthMode.barrel,
|
||||||
minWidth: 20.0,
|
minWidth: 10.0,
|
||||||
maxWidth: 50.0,
|
maxWidth: 15.0,
|
||||||
animationMode: EffectLineAnimationMode.scroll,
|
|
||||||
fadeAfterDelay: 1.0,
|
fadeAfterDelay: 1.0,
|
||||||
fadeDuration: 1.0
|
fadeDuration: 1.0
|
||||||
);
|
);
|
||||||
@ -147,6 +147,20 @@ class TestBed extends NodeWithSize {
|
|||||||
maxWidth: 100.0,
|
maxWidth: 100.0,
|
||||||
animationMode: EffectLineAnimationMode.random
|
animationMode: EffectLineAnimationMode.random
|
||||||
);
|
);
|
||||||
|
} else if (lineType == "Rocket Trail") {
|
||||||
|
Texture baseTexture = new Texture(_images['assets/line_effects.png']);
|
||||||
|
Texture trailLineTexture = baseTexture.textureFromRect(new Rect.fromLTRB(0.0, 896.0, 1024.0, 1024.0));
|
||||||
|
|
||||||
|
_line = new EffectLine(
|
||||||
|
texture: trailLineTexture,
|
||||||
|
textureLoopLength: 300.0,
|
||||||
|
widthMode: EffectLineWidthMode.barrel,
|
||||||
|
minWidth: 20.0,
|
||||||
|
maxWidth: 40.0,
|
||||||
|
widthGrowthSpeed: 40.0,
|
||||||
|
fadeAfterDelay: 0.5,
|
||||||
|
fadeDuration: 1.5
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addChild(_line);
|
addChild(_line);
|
@ -15,12 +15,15 @@ class EffectLine extends Node {
|
|||||||
|
|
||||||
EffectLine({
|
EffectLine({
|
||||||
this.texture: null,
|
this.texture: null,
|
||||||
|
this.transferMode: sky.TransferMode.dstOver,
|
||||||
List<Point> points,
|
List<Point> points,
|
||||||
this.widthMode : EffectLineWidthMode.linear,
|
this.widthMode : EffectLineWidthMode.linear,
|
||||||
this.minWidth: 10.0,
|
this.minWidth: 10.0,
|
||||||
this.maxWidth: 10.0,
|
this.maxWidth: 10.0,
|
||||||
|
this.widthGrowthSpeed: 0.0,
|
||||||
this.animationMode: EffectLineAnimationMode.none,
|
this.animationMode: EffectLineAnimationMode.none,
|
||||||
this.scrollSpeed: 0.1,
|
this.scrollSpeed: 0.1,
|
||||||
|
double scrollStart: 0.0,
|
||||||
this.fadeDuration: null,
|
this.fadeDuration: null,
|
||||||
this.fadeAfterDelay: null,
|
this.fadeAfterDelay: null,
|
||||||
this.textureLoopLength: null,
|
this.textureLoopLength: null,
|
||||||
@ -36,15 +39,20 @@ class EffectLine extends Node {
|
|||||||
new Color(0xffffffff),
|
new Color(0xffffffff),
|
||||||
new Color(0xffffffff));
|
new Color(0xffffffff));
|
||||||
|
|
||||||
|
_offset = scrollStart;
|
||||||
|
|
||||||
_painter = new TexturedLinePainter(points, _colors, _widths, texture);
|
_painter = new TexturedLinePainter(points, _colors, _widths, texture);
|
||||||
_painter.textureLoopLength = textureLoopLength;
|
_painter.textureLoopLength = textureLoopLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Texture texture;
|
final Texture texture;
|
||||||
|
|
||||||
|
final sky.TransferMode transferMode;
|
||||||
|
|
||||||
final EffectLineWidthMode widthMode;
|
final EffectLineWidthMode widthMode;
|
||||||
final double minWidth;
|
final double minWidth;
|
||||||
final double maxWidth;
|
final double maxWidth;
|
||||||
|
final double widthGrowthSpeed;
|
||||||
|
|
||||||
final EffectLineAnimationMode animationMode;
|
final EffectLineAnimationMode animationMode;
|
||||||
final double scrollSpeed;
|
final double scrollSpeed;
|
||||||
@ -86,14 +94,25 @@ class EffectLine extends Node {
|
|||||||
_offset = randomDouble();
|
_offset = randomDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update age of line points, and remove if neccessary
|
// Update age of line points and remove if neccesasry
|
||||||
if (fadeDuration != null && fadeAfterDelay != null) {
|
if (fadeDuration != null && fadeAfterDelay != null) {
|
||||||
|
// Increase age of points
|
||||||
for (int i = _points.length - 1; i >= 0; i--) {
|
for (int i = _points.length - 1; i >= 0; i--) {
|
||||||
_pointAges[i] += dt;
|
_pointAges[i] += dt;
|
||||||
if (_pointAges[i] > (fadeDuration + fadeAfterDelay)) {
|
}
|
||||||
_pointAges.removeAt(i);
|
|
||||||
_points.removeAt(i);
|
// Check if the first/oldest point should be removed
|
||||||
|
while(_points.length > 0 && _pointAges[0] > (fadeDuration + fadeAfterDelay)) {
|
||||||
|
// Update scroll if it isn't the last and only point that is about to removed
|
||||||
|
if (_points.length > 1 && textureLoopLength != null) {
|
||||||
|
double dist = GameMath.pointQuickDist(_points[0], _points[1]);
|
||||||
|
_offset = (_offset - (dist / textureLoopLength)) % 1.0;
|
||||||
|
if (_offset < 0.0) _offset += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove the point
|
||||||
|
_pointAges.removeAt(0);
|
||||||
|
_points.removeAt(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,8 +120,6 @@ class EffectLine extends Node {
|
|||||||
void paint(PaintingCanvas canvas) {
|
void paint(PaintingCanvas canvas) {
|
||||||
if (points.length < 2) return;
|
if (points.length < 2) return;
|
||||||
|
|
||||||
//_painter.textureLoopLength = textureLoopLength;
|
|
||||||
|
|
||||||
_painter.points = points;
|
_painter.points = points;
|
||||||
|
|
||||||
// Calculate colors
|
// Calculate colors
|
||||||
@ -127,12 +144,14 @@ class EffectLine extends Node {
|
|||||||
|
|
||||||
// Calculate widths
|
// Calculate widths
|
||||||
List<double> widths = [];
|
List<double> widths = [];
|
||||||
for (double stop in stops) {
|
for (int i = 0; i < stops.length; i++) {
|
||||||
|
double stop = stops[i];
|
||||||
|
double growth = math.max(widthGrowthSpeed * _pointAges[i], 0.0);
|
||||||
if (widthMode == EffectLineWidthMode.linear) {
|
if (widthMode == EffectLineWidthMode.linear) {
|
||||||
double width = minWidth + (maxWidth - minWidth) * stop;
|
double width = minWidth + (maxWidth - minWidth) * stop + growth;
|
||||||
widths.add(width);
|
widths.add(width);
|
||||||
} else if (widthMode == EffectLineWidthMode.barrel) {
|
} else if (widthMode == EffectLineWidthMode.barrel) {
|
||||||
double width = minWidth + math.sin(stop * math.PI) * (maxWidth - minWidth);
|
double width = minWidth + math.sin(stop * math.PI) * (maxWidth - minWidth) + growth;
|
||||||
widths.add(width);
|
widths.add(width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,12 +167,38 @@ class EffectLine extends Node {
|
|||||||
if (points.length > 0 && point.x == points[points.length - 1].x && point.y == points[points.length - 1].y)
|
if (points.length > 0 && point.x == points[points.length - 1].x && point.y == points[points.length - 1].y)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (simplify) {
|
if (simplify && points.length >= 2 && GameMath.pointQuickDist(point, points[points.length - 2]) < 10.0) {
|
||||||
|
// Check if we should remove last point before adding the new one
|
||||||
|
|
||||||
|
// Calculate the square distance from the middle point to the line of the
|
||||||
|
// new point and the second to last point
|
||||||
|
double dist2 = _distToSeqment2(
|
||||||
|
points[points.length - 1],
|
||||||
|
point,
|
||||||
|
points[points.length - 2]
|
||||||
|
);
|
||||||
|
|
||||||
|
// If the point is on the line, remove it
|
||||||
|
if (dist2 < 1.0) {
|
||||||
|
_points.removeAt(_points.length - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add point and point's age
|
// Add point and point's age
|
||||||
_points.add(point);
|
_points.add(point);
|
||||||
_pointAges.add(0.0);
|
_pointAges.add(0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double _sqr(double x) => x * x;
|
||||||
|
|
||||||
|
double _dist2(Point v, Point w) => _sqr(v.x - w.x) + _sqr(v.y - w.y);
|
||||||
|
|
||||||
|
double _distToSeqment2(Point p, Point v, Point w) {
|
||||||
|
double l2 = _dist2(v, w);
|
||||||
|
if (l2 == 0.0) return _dist2(p, v);
|
||||||
|
double t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
|
||||||
|
if (t < 0) return _dist2(p, v);
|
||||||
|
if (t > 1) return _dist2(p, w);
|
||||||
|
return _dist2(p, new Point(v.x + t * (w.x - v.x), v.y + t * (w.y - v.y)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,8 @@ class TexturedLinePainter {
|
|||||||
_calculatedTextureStops = null;
|
_calculatedTextureStops = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sky.TransferMode transferMode = sky.TransferMode.srcOver;
|
||||||
|
|
||||||
Paint _cachedPaint = new Paint();
|
Paint _cachedPaint = new Paint();
|
||||||
|
|
||||||
void paint(PaintingCanvas canvas) {
|
void paint(PaintingCanvas canvas) {
|
||||||
@ -85,6 +87,8 @@ class TexturedLinePainter {
|
|||||||
assert(_points.length == colors.length);
|
assert(_points.length == colors.length);
|
||||||
assert(_points.length == widths.length);
|
assert(_points.length == widths.length);
|
||||||
|
|
||||||
|
_cachedPaint.transferMode = transferMode;
|
||||||
|
|
||||||
// Calculate normals
|
// Calculate normals
|
||||||
List<Vector2> vectors = [];
|
List<Vector2> vectors = [];
|
||||||
for (Point pt in _points) {
|
for (Point pt in _points) {
|
||||||
@ -216,7 +220,13 @@ Vector2 _computeMiter(Vector2 lineA, Vector2 lineB) {
|
|||||||
Vector2 miter = new Vector2(- (lineA[1] + lineB[1]), lineA[0] + lineB[0]);
|
Vector2 miter = new Vector2(- (lineA[1] + lineB[1]), lineA[0] + lineB[0]);
|
||||||
miter.normalize();
|
miter.normalize();
|
||||||
|
|
||||||
double miterLength = 1.0 / dot2(miter, new Vector2(-lineA[1], lineA[0]));
|
double dot = dot2(miter, new Vector2(-lineA[1], lineA[0]));
|
||||||
|
if (dot.abs() < 0.1) {
|
||||||
|
miter = _vectorNormal(lineA).normalize();
|
||||||
|
return miter;
|
||||||
|
}
|
||||||
|
|
||||||
|
double miterLength = 1.0 / dot;
|
||||||
miter = miter.scale(miterLength);
|
miter = miter.scale(miterLength);
|
||||||
|
|
||||||
return miter;
|
return miter;
|
||||||
|
Loading…
Reference in New Issue
Block a user