mirror of
https://github.com/flutter/flutter
synced 2024-10-14 04:02:56 +00:00
Merge pull request #315 from vlidholt/master
Optimizations for sprite code
This commit is contained in:
commit
0d7156fc03
|
@ -37,6 +37,7 @@ class Node {
|
||||||
int _addedOrder;
|
int _addedOrder;
|
||||||
int _childrenLastAddedOrder = 0;
|
int _childrenLastAddedOrder = 0;
|
||||||
bool _childrenNeedSorting = false;
|
bool _childrenNeedSorting = false;
|
||||||
|
Matrix4 _savedTotalMatrix;
|
||||||
|
|
||||||
/// Decides if the node and its children is currently paused.
|
/// Decides if the node and its children is currently paused.
|
||||||
///
|
///
|
||||||
|
@ -64,6 +65,7 @@ class Node {
|
||||||
ActionController get actions {
|
ActionController get actions {
|
||||||
if (_actions == null) {
|
if (_actions == null) {
|
||||||
_actions = new ActionController();
|
_actions = new ActionController();
|
||||||
|
if (_spriteBox != null) _spriteBox._actionControllers = null;
|
||||||
}
|
}
|
||||||
return _actions;
|
return _actions;
|
||||||
}
|
}
|
||||||
|
@ -96,7 +98,7 @@ class Node {
|
||||||
///
|
///
|
||||||
/// myNode.rotation = 45.0;
|
/// myNode.rotation = 45.0;
|
||||||
double get rotation => _rotation;
|
double get rotation => _rotation;
|
||||||
|
|
||||||
void set rotation(double rotation) {
|
void set rotation(double rotation) {
|
||||||
assert(rotation != null);
|
assert(rotation != null);
|
||||||
_rotation = rotation;
|
_rotation = rotation;
|
||||||
|
@ -107,7 +109,7 @@ class Node {
|
||||||
///
|
///
|
||||||
/// myNode.position = new Point(42.0, 42.0);
|
/// myNode.position = new Point(42.0, 42.0);
|
||||||
Point get position => _position;
|
Point get position => _position;
|
||||||
|
|
||||||
void set position(Point position) {
|
void set position(Point position) {
|
||||||
assert(position != null);
|
assert(position != null);
|
||||||
_position = position;
|
_position = position;
|
||||||
|
@ -200,7 +202,7 @@ class Node {
|
||||||
child._spriteBox = this._spriteBox;
|
child._spriteBox = this._spriteBox;
|
||||||
_childrenLastAddedOrder += 1;
|
_childrenLastAddedOrder += 1;
|
||||||
child._addedOrder = _childrenLastAddedOrder;
|
child._addedOrder = _childrenLastAddedOrder;
|
||||||
if (_spriteBox != null) _spriteBox._eventTargets = null;
|
if (_spriteBox != null) _spriteBox._registerNode(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes a child from this node.
|
/// Removes a child from this node.
|
||||||
|
@ -211,7 +213,7 @@ class Node {
|
||||||
if (_children.remove(child)) {
|
if (_children.remove(child)) {
|
||||||
child._parent = null;
|
child._parent = null;
|
||||||
child._spriteBox = null;
|
child._spriteBox = null;
|
||||||
if (_spriteBox != null) _spriteBox._eventTargets = null;
|
if (_spriteBox != null) _spriteBox._deregisterNode(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +235,7 @@ class Node {
|
||||||
}
|
}
|
||||||
_children = [];
|
_children = [];
|
||||||
_childrenNeedSorting = false;
|
_childrenNeedSorting = false;
|
||||||
if (_spriteBox != null) _spriteBox._eventTargets = null;
|
if (_spriteBox != null) _spriteBox._deregisterNode(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _sortChildren() {
|
void _sortChildren() {
|
||||||
|
@ -265,9 +267,9 @@ class Node {
|
||||||
if (_transformMatrix != null) {
|
if (_transformMatrix != null) {
|
||||||
return _transformMatrix;
|
return _transformMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
double cx, sx, cy, sy;
|
double cx, sx, cy, sy;
|
||||||
|
|
||||||
if (_rotation == 0.0) {
|
if (_rotation == 0.0) {
|
||||||
cx = 1.0;
|
cx = 1.0;
|
||||||
sx = 0.0;
|
sx = 0.0;
|
||||||
|
@ -277,7 +279,7 @@ class Node {
|
||||||
else {
|
else {
|
||||||
double radiansX = convertDegrees2Radians(_rotation);
|
double radiansX = convertDegrees2Radians(_rotation);
|
||||||
double radiansY = convertDegrees2Radians(_rotation);
|
double radiansY = convertDegrees2Radians(_rotation);
|
||||||
|
|
||||||
cx = math.cos(radiansX);
|
cx = math.cos(radiansX);
|
||||||
sx = math.sin(radiansX);
|
sx = math.sin(radiansX);
|
||||||
cy = math.cos(radiansY);
|
cy = math.cos(radiansY);
|
||||||
|
@ -289,7 +291,7 @@ class Node {
|
||||||
-sx * _scaleY, cx * _scaleY, 0.0, 0.0,
|
-sx * _scaleY, cx * _scaleY, 0.0, 0.0,
|
||||||
0.0, 0.0, 1.0, 0.0,
|
0.0, 0.0, 1.0, 0.0,
|
||||||
_position.x, _position.y, 0.0, 1.0);
|
_position.x, _position.y, 0.0, 1.0);
|
||||||
|
|
||||||
return _transformMatrix;
|
return _transformMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +405,7 @@ class Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
|
|
||||||
void _visit(PaintingCanvas canvas) {
|
void _visit(PaintingCanvas canvas) {
|
||||||
assert(canvas != null);
|
assert(canvas != null);
|
||||||
if (!visible) return;
|
if (!visible) return;
|
||||||
|
@ -412,9 +414,9 @@ class Node {
|
||||||
_visitChildren(canvas);
|
_visitChildren(canvas);
|
||||||
_postPaint(canvas);
|
_postPaint(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _prePaint(PaintingCanvas canvas) {
|
void _prePaint(PaintingCanvas canvas) {
|
||||||
canvas.save();
|
_savedTotalMatrix = canvas.getTotalMatrix();
|
||||||
|
|
||||||
// Get the transformation matrix and apply transform
|
// Get the transformation matrix and apply transform
|
||||||
canvas.concat(transformMatrix.storage);
|
canvas.concat(transformMatrix.storage);
|
||||||
|
@ -438,7 +440,7 @@ class Node {
|
||||||
/// }
|
/// }
|
||||||
void paint(PaintingCanvas canvas) {
|
void paint(PaintingCanvas canvas) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _visitChildren(PaintingCanvas canvas) {
|
void _visitChildren(PaintingCanvas canvas) {
|
||||||
// Sort children if needed
|
// Sort children if needed
|
||||||
_sortChildren();
|
_sortChildren();
|
||||||
|
@ -463,9 +465,9 @@ class Node {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _postPaint(PaintingCanvas canvas) {
|
void _postPaint(PaintingCanvas canvas) {
|
||||||
canvas.restore();
|
canvas.setMatrix(_savedTotalMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receiving update calls
|
// Receiving update calls
|
||||||
|
@ -536,4 +538,4 @@ class Node {
|
||||||
bool handleEvent(SpriteBoxEvent event) {
|
bool handleEvent(SpriteBoxEvent event) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ class Sprite extends NodeWithSize {
|
||||||
/// mySprite.transferMode = TransferMode.plusMode;
|
/// mySprite.transferMode = TransferMode.plusMode;
|
||||||
TransferMode transferMode;
|
TransferMode transferMode;
|
||||||
|
|
||||||
|
Paint _cachedPaint = new Paint();
|
||||||
|
|
||||||
/// Creates a new sprite from the provided [texture].
|
/// Creates a new sprite from the provided [texture].
|
||||||
///
|
///
|
||||||
/// var mySprite = new Sprite(myTexture)
|
/// var mySprite = new Sprite(myTexture)
|
||||||
|
@ -65,7 +67,8 @@ class Sprite extends NodeWithSize {
|
||||||
}
|
}
|
||||||
|
|
||||||
void paint(PaintingCanvas canvas) {
|
void paint(PaintingCanvas canvas) {
|
||||||
canvas.save();
|
// Store old matrix
|
||||||
|
Matrix4 savedMatrix = canvas.getTotalMatrix();
|
||||||
|
|
||||||
// Account for pivot point
|
// Account for pivot point
|
||||||
applyTransformForPivot(canvas);
|
applyTransformForPivot(canvas);
|
||||||
|
@ -75,10 +78,10 @@ class Sprite extends NodeWithSize {
|
||||||
double h = texture.size.height;
|
double h = texture.size.height;
|
||||||
|
|
||||||
if (w <= 0 || h <= 0) return;
|
if (w <= 0 || h <= 0) return;
|
||||||
|
|
||||||
double scaleX = size.width / w;
|
double scaleX = size.width / w;
|
||||||
double scaleY = size.height / h;
|
double scaleY = size.height / h;
|
||||||
|
|
||||||
if (constrainProportions) {
|
if (constrainProportions) {
|
||||||
// Constrain proportions, using the smallest scale and by centering the image
|
// Constrain proportions, using the smallest scale and by centering the image
|
||||||
if (scaleX < scaleY) {
|
if (scaleX < scaleY) {
|
||||||
|
@ -89,26 +92,27 @@ class Sprite extends NodeWithSize {
|
||||||
scaleX = scaleY;
|
scaleX = scaleY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.scale(scaleX, scaleY);
|
canvas.scale(scaleX, scaleY);
|
||||||
|
|
||||||
// Setup paint object for opacity and transfer mode
|
// Setup paint object for opacity and transfer mode
|
||||||
Paint paint = new Paint();
|
_cachedPaint.color = new Color.fromARGB((255.0*_opacity).toInt(), 255, 255, 255);
|
||||||
paint.color = new Color.fromARGB((255.0*_opacity).toInt(), 255, 255, 255);
|
|
||||||
if (colorOverlay != null) {
|
if (colorOverlay != null) {
|
||||||
paint.setColorFilter(new ColorFilter.mode(colorOverlay, TransferMode.srcATop));
|
_cachedPaint.setColorFilter(new ColorFilter.mode(colorOverlay, TransferMode.srcATop));
|
||||||
}
|
}
|
||||||
if (transferMode != null) {
|
if (transferMode != null) {
|
||||||
paint.setTransferMode(transferMode);
|
_cachedPaint.setTransferMode(transferMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do actual drawing of the sprite
|
// Do actual drawing of the sprite
|
||||||
texture.drawTexture(canvas, Point.origin, paint);
|
texture.drawTexture(canvas, Point.origin, _cachedPaint);
|
||||||
} else {
|
} else {
|
||||||
// Paint a red square for missing texture
|
// Paint a red square for missing texture
|
||||||
canvas.drawRect(new Rect.fromLTRB(0.0, 0.0, size.width, size.height),
|
canvas.drawRect(new Rect.fromLTRB(0.0, 0.0, size.width, size.height),
|
||||||
new Paint()..color = const Color.fromARGB(255, 255, 0, 0));
|
new Paint()..color = new Color.fromARGB(255, 255, 0, 0));
|
||||||
}
|
}
|
||||||
canvas.restore();
|
|
||||||
|
// Restore matrix
|
||||||
|
canvas.setMatrix(savedMatrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,8 @@ class SpriteBox extends RenderBox {
|
||||||
|
|
||||||
List<Node> _eventTargets;
|
List<Node> _eventTargets;
|
||||||
|
|
||||||
|
List<ActionController> _actionControllers;
|
||||||
|
|
||||||
Rect _visibleArea;
|
Rect _visibleArea;
|
||||||
|
|
||||||
Rect get visibleArea {
|
Rect get visibleArea {
|
||||||
|
@ -131,6 +133,18 @@ class SpriteBox extends RenderBox {
|
||||||
_callSpriteBoxPerformedLayout(_rootNode);
|
_callSpriteBoxPerformedLayout(_rootNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adding and removing nodes
|
||||||
|
|
||||||
|
_registerNode(Node node) {
|
||||||
|
_actionControllers = null;
|
||||||
|
_eventTargets = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_deregisterNode(Node node) {
|
||||||
|
_actionControllers = null;
|
||||||
|
_eventTargets = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Event handling
|
// Event handling
|
||||||
|
|
||||||
void _addEventTargets(Node node, List<Node> eventTargets) {
|
void _addEventTargets(Node node, List<Node> eventTargets) {
|
||||||
|
@ -342,19 +356,32 @@ class SpriteBox extends RenderBox {
|
||||||
// if (_numFrames % 60 == 0)
|
// if (_numFrames % 60 == 0)
|
||||||
// print("delta: $delta fps: $_frameRate");
|
// print("delta: $delta fps: $_frameRate");
|
||||||
|
|
||||||
_runActions(_rootNode, delta);
|
_runActions(delta);
|
||||||
_callUpdate(_rootNode, delta);
|
_callUpdate(_rootNode, delta);
|
||||||
|
|
||||||
|
// Schedule next update
|
||||||
_scheduleTick();
|
_scheduleTick();
|
||||||
|
|
||||||
|
// Make sure the node graph is redrawn
|
||||||
markNeedsPaint();
|
markNeedsPaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _runActions(Node node, double dt) {
|
void _runActions(double dt) {
|
||||||
if (node._actions != null) {
|
if (_actionControllers == null) {
|
||||||
node._actions.step(dt);
|
_actionControllers = [];
|
||||||
|
_addActionControllers(_rootNode, _actionControllers);
|
||||||
}
|
}
|
||||||
|
for (ActionController actions in _actionControllers) {
|
||||||
|
actions.step(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _addActionControllers(Node node, List<ActionController> controllers) {
|
||||||
|
if (node._actions != null) controllers.add(node._actions);
|
||||||
|
|
||||||
for (int i = node.children.length - 1; i >= 0; i--) {
|
for (int i = node.children.length - 1; i >= 0; i--) {
|
||||||
Node child = node.children[i];
|
Node child = node.children[i];
|
||||||
_runActions(child, dt);
|
_addActionControllers(child, controllers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue