phaser
Version:
A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.
340 lines (268 loc) • 11.4 kB
JavaScript
var ContainerCanvasRenderer = require('../../../src/gameobjects/container/ContainerCanvasRenderer');
describe('ContainerCanvasRenderer', function ()
{
var renderer;
var container;
var camera;
var transformMatrix;
function makeChild (opts)
{
opts = opts || {};
var child = {
alpha: opts.alpha !== undefined ? opts.alpha : 1,
scrollFactorX: opts.scrollFactorX !== undefined ? opts.scrollFactorX : 1,
scrollFactorY: opts.scrollFactorY !== undefined ? opts.scrollFactorY : 1,
blendMode: opts.blendMode !== undefined ? opts.blendMode : 0,
willRender: vi.fn().mockReturnValue(opts.willRender !== undefined ? opts.willRender : true),
setAlpha: vi.fn(function (v) { this.alpha = v; }),
setScrollFactor: vi.fn(function (x, y) { this.scrollFactorX = x; this.scrollFactorY = y; }),
renderCanvas: vi.fn()
};
return child;
}
beforeEach(function ()
{
transformMatrix = {
loadIdentity: vi.fn(),
multiply: vi.fn(),
translate: vi.fn(),
rotate: vi.fn(),
scale: vi.fn(),
applyITRS: vi.fn()
};
renderer = {
currentBlendMode: 0,
setBlendMode: vi.fn()
};
container = {
list: [],
localTransform: transformMatrix,
x: 0,
y: 0,
rotation: 0,
scaleX: 1,
scaleY: 1,
blendMode: 0,
_alpha: 1,
scrollFactorX: 1,
scrollFactorY: 1,
mask: null
};
camera = {
addToRenderList: vi.fn()
};
});
it('should always call camera.addToRenderList with the container', function ()
{
ContainerCanvasRenderer(renderer, container, camera, null);
expect(camera.addToRenderList).toHaveBeenCalledWith(container);
});
it('should call camera.addToRenderList even when the container has no children', function ()
{
container.list = [];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(camera.addToRenderList).toHaveBeenCalledOnce();
});
it('should return early and not process the transform matrix when children list is empty', function ()
{
container.list = [];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(transformMatrix.applyITRS).not.toHaveBeenCalled();
expect(transformMatrix.loadIdentity).not.toHaveBeenCalled();
});
it('should call applyITRS when no parentMatrix is provided', function ()
{
container.list = [ makeChild() ];
container.x = 10;
container.y = 20;
container.rotation = 0.5;
container.scaleX = 2;
container.scaleY = 3;
ContainerCanvasRenderer(renderer, container, camera, null);
expect(transformMatrix.applyITRS).toHaveBeenCalledWith(10, 20, 0.5, 2, 3);
});
it('should call loadIdentity, multiply, translate, rotate, scale when parentMatrix is provided', function ()
{
var parentMatrix = { type: 'parentMatrix' };
container.list = [ makeChild() ];
container.x = 5;
container.y = 15;
container.rotation = 1.0;
container.scaleX = 1.5;
container.scaleY = 2.5;
ContainerCanvasRenderer(renderer, container, camera, parentMatrix);
expect(transformMatrix.loadIdentity).toHaveBeenCalled();
expect(transformMatrix.multiply).toHaveBeenCalledWith(parentMatrix);
expect(transformMatrix.translate).toHaveBeenCalledWith(5, 15);
expect(transformMatrix.rotate).toHaveBeenCalledWith(1.0);
expect(transformMatrix.scale).toHaveBeenCalledWith(1.5, 2.5);
expect(transformMatrix.applyITRS).not.toHaveBeenCalled();
});
it('should not call renderer.setBlendMode when container has a valid blend mode', function ()
{
container.blendMode = 1;
container.list = [ makeChild() ];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(renderer.setBlendMode).not.toHaveBeenCalled();
});
it('should call renderer.setBlendMode(0) when container blendMode is -1', function ()
{
container.blendMode = -1;
container.list = [ makeChild() ];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(renderer.setBlendMode).toHaveBeenCalledWith(0);
});
it('should call child.renderCanvas with correct arguments', function ()
{
var child = makeChild();
container.list = [ child ];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(child.renderCanvas).toHaveBeenCalledWith(renderer, child, camera, transformMatrix);
});
it('should skip children where willRender returns false', function ()
{
var child = makeChild({ willRender: false });
container.list = [ child ];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(child.renderCanvas).not.toHaveBeenCalled();
});
it('should multiply child alpha by container alpha before rendering', function ()
{
container._alpha = 0.5;
var child = makeChild({ alpha: 0.8 });
container.list = [ child ];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(child.setAlpha).toHaveBeenCalledWith(0.8 * 0.5);
});
it('should restore child alpha to original value after rendering', function ()
{
container._alpha = 0.5;
var originalAlpha = 0.8;
var child = makeChild({ alpha: originalAlpha });
container.list = [ child ];
ContainerCanvasRenderer(renderer, container, camera, null);
var calls = child.setAlpha.mock.calls;
expect(calls[calls.length - 1][0]).toBe(originalAlpha);
});
it('should multiply child scrollFactors by container scrollFactors before rendering', function ()
{
container.scrollFactorX = 2;
container.scrollFactorY = 3;
var child = makeChild({ scrollFactorX: 0.5, scrollFactorY: 0.25 });
container.list = [ child ];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(child.setScrollFactor).toHaveBeenCalledWith(0.5 * 2, 0.25 * 3);
});
it('should restore child scrollFactors to original values after rendering', function ()
{
container.scrollFactorX = 2;
container.scrollFactorY = 3;
var origX = 0.5;
var origY = 0.25;
var child = makeChild({ scrollFactorX: origX, scrollFactorY: origY });
container.list = [ child ];
ContainerCanvasRenderer(renderer, container, camera, null);
var calls = child.setScrollFactor.mock.calls;
var lastCall = calls[calls.length - 1];
expect(lastCall[0]).toBe(origX);
expect(lastCall[1]).toBe(origY);
});
it('should set child blend mode when container blendMode is -1 and child blend mode differs from renderer', function ()
{
container.blendMode = -1;
renderer.currentBlendMode = 0;
var child = makeChild({ blendMode: 2 });
container.list = [ child ];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(renderer.setBlendMode).toHaveBeenCalledWith(2);
});
it('should not set child blend mode when container has a valid blend mode', function ()
{
container.blendMode = 1;
renderer.currentBlendMode = 0;
var child = makeChild({ blendMode: 2 });
container.list = [ child ];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(renderer.setBlendMode).not.toHaveBeenCalled();
});
it('should not set child blend mode when child blend mode matches renderer currentBlendMode', function ()
{
container.blendMode = -1;
renderer.currentBlendMode = 2;
var child = makeChild({ blendMode: 2 });
container.list = [ child ];
// renderer.setBlendMode(0) gets called for container, then child blend mode matches current
ContainerCanvasRenderer(renderer, container, camera, null);
var calls = renderer.setBlendMode.mock.calls;
// Only the initial container call with 0 should have happened
expect(calls.length).toBe(1);
expect(calls[0][0]).toBe(0);
});
it('should call mask.preRenderCanvas before children and mask.postRenderCanvas after', function ()
{
var mask = {
preRenderCanvas: vi.fn(),
postRenderCanvas: vi.fn()
};
container.mask = mask;
var child = makeChild();
container.list = [ child ];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(mask.preRenderCanvas).toHaveBeenCalledWith(renderer, null, camera);
expect(mask.postRenderCanvas).toHaveBeenCalledWith(renderer);
});
it('should call mask.preRenderCanvas before child.renderCanvas', function ()
{
var callOrder = [];
var mask = {
preRenderCanvas: vi.fn(function () { callOrder.push('pre'); }),
postRenderCanvas: vi.fn(function () { callOrder.push('post'); })
};
container.mask = mask;
var child = makeChild();
child.renderCanvas = vi.fn(function () { callOrder.push('render'); });
container.list = [ child ];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(callOrder).toEqual([ 'pre', 'render', 'post' ]);
});
it('should not call mask methods when container has no mask', function ()
{
container.mask = null;
container.list = [ makeChild() ];
// Should not throw
expect(function ()
{
ContainerCanvasRenderer(renderer, container, camera, null);
}).not.toThrow();
});
it('should render all children that pass willRender check', function ()
{
var child1 = makeChild({ willRender: true });
var child2 = makeChild({ willRender: false });
var child3 = makeChild({ willRender: true });
container.list = [ child1, child2, child3 ];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(child1.renderCanvas).toHaveBeenCalled();
expect(child2.renderCanvas).not.toHaveBeenCalled();
expect(child3.renderCanvas).toHaveBeenCalled();
});
it('should pass camera to each child willRender call', function ()
{
var child = makeChild();
container.list = [ child ];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(child.willRender).toHaveBeenCalledWith(camera);
});
it('should handle a container with multiple children correctly', function ()
{
container._alpha = 0.5;
container.scrollFactorX = 2;
container.scrollFactorY = 2;
var child1 = makeChild({ alpha: 1, scrollFactorX: 1, scrollFactorY: 1 });
var child2 = makeChild({ alpha: 0.5, scrollFactorX: 0.5, scrollFactorY: 0.5 });
container.list = [ child1, child2 ];
ContainerCanvasRenderer(renderer, container, camera, null);
expect(child1.renderCanvas).toHaveBeenCalled();
expect(child2.renderCanvas).toHaveBeenCalled();
});
});