phaser
Version:
A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.
183 lines (160 loc) • 7.36 kB
JavaScript
/**
* @author Benjamin D. Richards <benjamindrichards@gmail.com>
* @copyright 2013-2026 Phaser Studio Inc.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var TransformMatrix = require('../../../../gameobjects/components/TransformMatrix.js');
var Class = require('../../../../utils/Class');
var Merge = require('../../../../utils/object/Merge');
var RenderNode = require('../RenderNode');
/**
* @classdesc
* A RenderNode that computes and stores the screen-space position
* of a single vertex each time it is run.
*
* During its `run` call, this node applies the camera view matrix (adjusted
* for the game object's scroll factors), any parent container matrix, and the
* game object's own position, rotation, and scale into a single final transform
* matrix. It then projects the vertex position through that matrix
* and writes the result back to the vertex position,
* ready for consumption by the subsequent submitter node.
*
* @class TransformerVertex
* @memberof Phaser.Renderer.WebGL.RenderNodes
* @constructor
* @since 4.0.0
* @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode
* @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode.
* @param {object} [config] - The configuration object for this RenderNode.
*/
var TransformerVertex = new Class({
Extends: RenderNode,
initialize: function TransformerVertex (manager, config)
{
config = Merge(config || {}, this.defaultConfig);
RenderNode.call(this, config.name, manager);
/**
* The matrix used internally to compute sprite transforms.
*
* @name Phaser.Renderer.WebGL.RenderNodes.TransformerVertex#_spriteMatrix
* @type {Phaser.GameObjects.Components.TransformMatrix}
* @since 4.0.0
* @private
*/
this._spriteMatrix = new TransformMatrix();
/**
* The matrix used internally to compute the final transform.
*
* @name Phaser.Renderer.WebGL.RenderNodes.TransformerVertex#_calcMatrix
* @type {Phaser.GameObjects.Components.TransformMatrix}
* @since 4.0.0
* @private
*/
this._calcMatrix = new TransformMatrix();
/**
* Whether vertices transformed with the current matrix should be
* rounded to the nearest integer. This is computed by `setupMatrix`
* and consumed by `transformVertex`.
*
* @name Phaser.Renderer.WebGL.RenderNodes.TransformerVertex#_roundVertices
* @type {boolean}
* @since 4.2.0
* @private
*/
this._roundVertices = false;
},
defaultConfig: {
name: 'TransformerVertex',
role: 'Transformer'
},
/**
* Computes the final screen-space position of the given vertex
* for the given GameObject and stores it in the vertex.
*
* The method builds the complete transform by combining the camera view
* matrix (modified by the game object's scroll factors), an optional parent
* container matrix, and the game object's own position, rotation, and scale.
* If vertex rounding is required, the resulting values are snapped to the nearest integer.
*
* @method Phaser.Renderer.WebGL.RenderNodes.TransformerVertex#run
* @since 4.0.0
* @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context.
* @param {Phaser.GameObjects.GameObject} gameObject - The GameObject being rendered.
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested.
* @param {Phaser.Math.Vector2} vertex - The vertex to transform.
*/
run: function (drawingContext, gameObject, parentMatrix, vertex)
{
this.onRunBegin(drawingContext);
this.setupMatrix(drawingContext, gameObject, parentMatrix);
this.transformVertex(vertex);
this.onRunEnd(drawingContext);
},
/**
* Builds the final transform matrix for the given GameObject and caches it,
* along with whether transformed vertices should be rounded. This combines
* the camera view matrix (modified by the game object's scroll factors), an
* optional parent container matrix, and the game object's own position,
* rotation, and scale.
*
* Call this once before transforming a batch of vertices with
* `transformVertex`, since the matrix is constant for all vertices of a
* single GameObject. This avoids rebuilding the matrix for every vertex.
*
* @method Phaser.Renderer.WebGL.RenderNodes.TransformerVertex#setupMatrix
* @since 4.2.0
* @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context.
* @param {Phaser.GameObjects.GameObject} gameObject - The GameObject being rendered.
* @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - This transform matrix is defined if the game object is nested.
* @return {Phaser.GameObjects.Components.TransformMatrix} The cached transform matrix.
*/
setupMatrix: function (drawingContext, gameObject, parentMatrix)
{
var camera = drawingContext.camera;
var spriteMatrix = this._spriteMatrix;
var calcMatrix = this._calcMatrix.copyWithScrollFactorFrom(
camera.getViewMatrix(!drawingContext.useCanvas),
camera.scrollX, camera.scrollY,
gameObject.scrollFactorX, gameObject.scrollFactorY
);
if (parentMatrix)
{
calcMatrix.multiply(parentMatrix);
}
spriteMatrix.applyITRS(
gameObject.x, gameObject.y,
gameObject.rotation,
gameObject.scaleX, gameObject.scaleY
);
calcMatrix.multiply(spriteMatrix);
// Determine whether the matrix does not rotate, scale, or skew.
// Keyword: #OnlyTranslate
var cmm = calcMatrix.matrix;
var onlyTranslate = cmm[0] === 1 && cmm[1] === 0 && cmm[2] === 0 && cmm[3] === 1;
// Cache whether vertices should be rounded, as this is constant
// for the whole GameObject.
this._roundVertices = gameObject.willRoundVertices(camera, onlyTranslate);
return calcMatrix;
},
/**
* Projects a single vertex through the matrix built by the most recent
* `setupMatrix` call, writing the result back to the vertex. If vertex
* rounding is required, the values are snapped to the nearest integer.
*
* @method Phaser.Renderer.WebGL.RenderNodes.TransformerVertex#transformVertex
* @since 4.2.0
* @param {Phaser.Math.Vector2} vertex - The vertex to transform.
* @return {Phaser.Math.Vector2} The transformed vertex.
*/
transformVertex: function (vertex)
{
this._calcMatrix.transformPoint(vertex.x, vertex.y, vertex);
if (this._roundVertices)
{
vertex.x = Math.round(vertex.x);
vertex.y = Math.round(vertex.y);
}
return vertex;
}
});
module.exports = TransformerVertex;