phaser
Version:
A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.
355 lines (309 loc) • 13.8 kB
JavaScript
var SubmitterTile = require('../../../../../src/renderer/webgl/renderNodes/submitter/SubmitterTile');
describe('SubmitterTile', function ()
{
var mockManager;
beforeEach(function ()
{
mockManager = {};
});
describe('constructor', function ()
{
it('should create an instance with default config', function ()
{
var node = new SubmitterTile(mockManager);
expect(node).toBeDefined();
});
it('should set the name to SubmitterTile by default', function ()
{
var node = new SubmitterTile(mockManager);
expect(node.name).toBe('SubmitterTile');
});
it('should set the batchHandler to BatchHandler by default', function ()
{
var node = new SubmitterTile(mockManager);
expect(node.batchHandler).toBe('BatchHandler');
});
it('should store the manager reference', function ()
{
var node = new SubmitterTile(mockManager);
expect(node.manager).toBe(mockManager);
});
it('should set clampFrame to true on _renderOptions', function ()
{
var node = new SubmitterTile(mockManager);
expect(node._renderOptions.clampFrame).toBe(true);
});
it('should accept a custom name via config', function ()
{
var node = new SubmitterTile(mockManager, { name: 'MyTileSubmitter' });
expect(node.name).toBe('MyTileSubmitter');
});
it('should accept a custom batchHandler via config', function ()
{
var node = new SubmitterTile(mockManager, { batchHandler: 'CustomBatchHandler' });
expect(node.batchHandler).toBe('CustomBatchHandler');
});
it('should initialise _renderOptions with multiTexturing true', function ()
{
var node = new SubmitterTile(mockManager);
expect(node._renderOptions.multiTexturing).toBe(true);
});
it('should initialise _renderOptions with lighting null', function ()
{
var node = new SubmitterTile(mockManager);
expect(node._renderOptions.lighting).toBeNull();
});
});
describe('defaultConfig', function ()
{
it('should have name SubmitterTile', function ()
{
expect(SubmitterTile.prototype.defaultConfig.name).toBe('SubmitterTile');
});
it('should have role Submitter', function ()
{
expect(SubmitterTile.prototype.defaultConfig.role).toBe('Submitter');
});
it('should have batchHandler BatchHandler', function ()
{
expect(SubmitterTile.prototype.defaultConfig.batchHandler).toBe('BatchHandler');
});
});
describe('run', function ()
{
var node;
var mockBatch;
var mockBatchHandler;
var drawingContext;
var gameObject;
var parentMatrix;
var texturerNode;
var transformerNode;
var glTexture;
var quad;
beforeEach(function ()
{
node = new SubmitterTile(mockManager);
mockBatch = vi.fn();
mockBatchHandler = { batch: mockBatch };
drawingContext = {};
parentMatrix = {};
glTexture = {};
quad = new Float32Array([
0, 1, // TL [0,1]
2, 3, // BL [2,3]
4, 5, // BR [4,5] (index 4,5)
6, 7 // TR [6,7]
]);
texturerNode = {
frame: { source: { glTexture: glTexture } },
uvSource: { u0: 0.1, v0: 0.2, u1: 0.9, v1: 0.8 }
};
transformerNode = {
quad: quad
};
gameObject = {
customRenderNodes: { BatchHandler: mockBatchHandler },
defaultRenderNodes: {},
tintMode: 0,
scene: {
sys: {
game: {
config: { smoothPixelArt: false }
}
}
}
};
});
it('should call batch on the game object batch handler', function ()
{
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
expect(mockBatch).toHaveBeenCalledTimes(1);
});
it('should fall back to defaultRenderNodes when customRenderNodes lacks the handler', function ()
{
gameObject.customRenderNodes = {};
gameObject.defaultRenderNodes = { BatchHandler: mockBatchHandler };
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
expect(mockBatch).toHaveBeenCalledTimes(1);
});
it('should pass drawingContext as the first batch argument', function ()
{
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
var args = mockBatch.mock.calls[0];
expect(args[0]).toBe(drawingContext);
});
it('should pass frame.source.glTexture as the second batch argument', function ()
{
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
var args = mockBatch.mock.calls[0];
expect(args[1]).toBe(glTexture);
});
it('should pass quad vertices in TL BL TR BR order', function ()
{
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
var args = mockBatch.mock.calls[0];
// quad order: TL=[0,1], BL=[2,3], TR=[6,7], BR=[4,5]
expect(args[2]).toBe(quad[0]);
expect(args[3]).toBe(quad[1]);
expect(args[4]).toBe(quad[2]);
expect(args[5]).toBe(quad[3]);
expect(args[6]).toBe(quad[6]);
expect(args[7]).toBe(quad[7]);
expect(args[8]).toBe(quad[4]);
expect(args[9]).toBe(quad[5]);
});
it('should pass UV coordinates as x, y, width, height', function ()
{
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
var args = mockBatch.mock.calls[0];
var u0 = 0.1;
var v0 = 0.2;
var u1 = 0.9;
var v1 = 0.8;
expect(args[10]).toBeCloseTo(u0);
expect(args[11]).toBeCloseTo(v0);
expect(args[12]).toBeCloseTo(u1 - u0);
expect(args[13]).toBeCloseTo(v1 - v0);
});
it('should use 0xffffffff tint colors when no tinterNode is provided', function ()
{
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
var args = mockBatch.mock.calls[0];
// tintEffect at index 14, then TL, BL, TR, BR tints at 15,16,17,18
expect(args[15]).toBe(0xffffffff);
expect(args[16]).toBe(0xffffffff);
expect(args[17]).toBe(0xffffffff);
expect(args[18]).toBe(0xffffffff);
});
it('should use gameObject.tintMode for tintEffect when no tinterNode is provided', function ()
{
gameObject.tintMode = 2;
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
var args = mockBatch.mock.calls[0];
expect(args[14]).toBe(2);
});
it('should use tinterNode tint values when tinterNode is provided', function ()
{
var tinterNode = {
tintEffect: 1,
tintTopLeft: 0xaabbccdd,
tintBottomLeft: 0x11223344,
tintTopRight: 0x55667788,
tintBottomRight: 0x99aabbcc
};
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode, tinterNode);
var args = mockBatch.mock.calls[0];
expect(args[14]).toBe(1);
expect(args[15]).toBe(0xaabbccdd);
expect(args[16]).toBe(0x11223344);
expect(args[17]).toBe(0x55667788);
expect(args[18]).toBe(0x99aabbcc);
});
it('should pass _renderOptions as the batch options argument', function ()
{
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
var args = mockBatch.mock.calls[0];
expect(args[19]).toBe(node._renderOptions);
});
it('should pass _renderOptions with clampFrame true', function ()
{
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
var args = mockBatch.mock.calls[0];
expect(args[19].clampFrame).toBe(true);
});
it('should pass frame UV coordinates in TL BL TR BR order as the final batch arguments', function ()
{
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
var args = mockBatch.mock.calls[0];
var u0 = 0.1;
var v0 = 0.2;
var u1 = 0.9;
var v1 = 0.8;
// frame coords: TL=(u0,v1), BL=(u0,v0), TR=(u1,v1), BR=(u1,v0)
expect(args[20]).toBeCloseTo(u0); // TL x
expect(args[21]).toBeCloseTo(v1); // TL y
expect(args[22]).toBeCloseTo(u0); // BL x
expect(args[23]).toBeCloseTo(v0); // BL y
expect(args[24]).toBeCloseTo(u1); // TR x
expect(args[25]).toBeCloseTo(v1); // TR y
expect(args[26]).toBeCloseTo(u1); // BR x
expect(args[27]).toBeCloseTo(v0); // BR y
});
it('should call texturerNode.run when it has a run method', function ()
{
texturerNode.run = vi.fn();
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
expect(texturerNode.run).toHaveBeenCalledTimes(1);
expect(texturerNode.run).toHaveBeenCalledWith(drawingContext, gameObject, null);
});
it('should not throw when texturerNode has no run method', function ()
{
expect(function ()
{
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
}).not.toThrow();
});
it('should call transformerNode.run when it has a run method', function ()
{
transformerNode.run = vi.fn();
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
expect(transformerNode.run).toHaveBeenCalledTimes(1);
expect(transformerNode.run).toHaveBeenCalledWith(drawingContext, gameObject, texturerNode, parentMatrix, null);
});
it('should not throw when transformerNode has no run method', function ()
{
expect(function ()
{
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
}).not.toThrow();
});
it('should call tinterNode.run when tinterNode is provided and has a run method', function ()
{
var element = { tileIndex: 5 };
var tinterNode = {
run: vi.fn(),
tintEffect: 0,
tintTopLeft: 0xffffffff,
tintBottomLeft: 0xffffffff,
tintTopRight: 0xffffffff,
tintBottomRight: 0xffffffff
};
node.run(drawingContext, gameObject, parentMatrix, element, texturerNode, transformerNode, tinterNode);
expect(tinterNode.run).toHaveBeenCalledTimes(1);
expect(tinterNode.run).toHaveBeenCalledWith(drawingContext, gameObject, element);
});
it('should pass element to texturerNode.run', function ()
{
var element = { tileIndex: 3 };
texturerNode.run = vi.fn();
node.run(drawingContext, gameObject, parentMatrix, element, texturerNode, transformerNode);
expect(texturerNode.run).toHaveBeenCalledWith(drawingContext, gameObject, element);
});
it('should pass element to transformerNode.run', function ()
{
var element = { tileIndex: 3 };
transformerNode.run = vi.fn();
node.run(drawingContext, gameObject, parentMatrix, element, texturerNode, transformerNode);
expect(transformerNode.run).toHaveBeenCalledWith(drawingContext, gameObject, texturerNode, parentMatrix, element);
});
it('should set _renderOptions.lighting to null when gameObject has no lighting', function ()
{
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
expect(node._renderOptions.lighting).toBeNull();
});
it('should set _renderOptions.smoothPixelArt from game config when texture has no override', function ()
{
gameObject.scene.sys.game.config.smoothPixelArt = true;
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
expect(node._renderOptions.smoothPixelArt).toBe(true);
});
it('should pass correct total number of arguments to batch', function ()
{
node.run(drawingContext, gameObject, parentMatrix, null, texturerNode, transformerNode);
var args = mockBatch.mock.calls[0];
// drawingContext + glTexture + 8 quad coords + 4 uv + tintEffect + 4 tints + renderOptions + 8 frame coords = 28
expect(args.length).toBe(28);
});
});
});