UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

386 lines (309 loc) 13.9 kB
var StrokePath = require('../../../../src/renderer/webgl/renderNodes/StrokePath'); describe('StrokePath', function () { var drawLineNode; var manager; var instance; function makeManager () { drawLineNode = { run: vi.fn(function (drawingContext, currentMatrix, x0, y0, x1, y1, hw0, hw1, vertices) { // Push 8 floats (4 vertices * 2 components) per call vertices.push(x0, y0, x1, y1, x0, y0, x1, y1); }) }; return { getNode: function (name) { if (name === 'DrawLine') { return drawLineNode; } return null; } }; } function makeMatrix () { return { tx: 0, ty: 0, getX: function (dx, dy) { return dx; }, getY: function (dx, dy) { return dy; } }; } function makeDrawingContext () { return {}; } function makeSubmitter () { return { batch: vi.fn() }; } function makePoint (x, y, width) { return { x: x, y: y, width: width !== undefined ? width : 2 }; } beforeEach(function () { manager = makeManager(); instance = new StrokePath(manager); }); describe('constructor', function () { it('should set name to StrokePath', function () { expect(instance.name).toBe('StrokePath'); }); it('should store the manager reference', function () { expect(instance.manager).toBe(manager); }); it('should retrieve the DrawLine node from the manager', function () { expect(instance.drawLineNode).toBe(drawLineNode); }); it('should have null _run by default', function () { expect(instance._run).toBeNull(); }); }); describe('run', function () { it('should call submitterNode.batch once per run', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); var path = [ makePoint(0, 0), makePoint(10, 0), makePoint(20, 0) ]; instance.run(ctx, submitter, path, 4, true, matrix, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0, false); expect(submitter.batch).toHaveBeenCalledTimes(1); }); it('should call drawLineNode.run once per path segment', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); var path = [ makePoint(0, 0), makePoint(10, 0), makePoint(20, 0) ]; instance.run(ctx, submitter, path, 4, true, matrix, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0, false); // 3 points = 2 segments expect(drawLineNode.run).toHaveBeenCalledTimes(2); }); it('should call drawLineNode.run once for a two-point path', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); var path = [ makePoint(0, 0), makePoint(10, 0) ]; instance.run(ctx, submitter, path, 4, true, matrix, 0, 0, 0, 0, 0, false); expect(drawLineNode.run).toHaveBeenCalledTimes(1); }); it('should produce 6 indices per segment for a thin line (lineWidth <= 2)', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); // 3 points = 2 segments, lineWidth = 1 var path = [ makePoint(0, 0), makePoint(10, 0), makePoint(20, 0) ]; instance.run(ctx, submitter, path, 1, true, matrix, 0, 0, 0, 0, 0, false); var callArgs = submitter.batch.mock.calls[0]; var indices = callArgs[1]; // 2 segments × 6 indices each = 12, no connecting quads expect(indices.length).toBe(12); }); it('should produce extra connecting indices for thick open path', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); // 3 points = 2 segments, lineWidth = 4 → connect=true var path = [ makePoint(0, 0), makePoint(10, 0), makePoint(20, 0) ]; instance.run(ctx, submitter, path, 4, true, matrix, 0, 0, 0, 0, 0, false); var callArgs = submitter.batch.mock.calls[0]; var indices = callArgs[1]; // 2 segments × 6 + 1 connecting quad × 6 = 18 expect(indices.length).toBe(18); }); it('should produce loop-closing indices for a thick closed path', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); // 3 points = 2 segments, closed (open=false), lineWidth = 4 var path = [ makePoint(0, 0), makePoint(10, 0), makePoint(20, 0) ]; instance.run(ctx, submitter, path, 4, false, matrix, 0, 0, 0, 0, 0, false); var callArgs = submitter.batch.mock.calls[0]; var indices = callArgs[1]; // 2 segments × 6 + 1 connecting quad × 6 + 1 closing quad × 6 = 24 expect(indices.length).toBe(24); }); it('should not add connecting quads when lineWidth equals 2', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); var path = [ makePoint(0, 0), makePoint(10, 0), makePoint(20, 0) ]; instance.run(ctx, submitter, path, 2, false, matrix, 0, 0, 0, 0, 0, false); var callArgs = submitter.batch.mock.calls[0]; var indices = callArgs[1]; // lineWidth <= 2 → no connecting quads, 2 × 6 = 12 expect(indices.length).toBe(12); }); it('should not add loop-closing quad when path has only two points', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); // 2 points = 1 segment only; connectLoop requires pathLength > 1 AND !first on last var path = [ makePoint(0, 0), makePoint(10, 0) ]; instance.run(ctx, submitter, path, 4, false, matrix, 0, 0, 0, 0, 0, false); var callArgs = submitter.batch.mock.calls[0]; var indices = callArgs[1]; // Only 1 segment, no second segment means no connecting quad; 6 indices expect(indices.length).toBe(6); }); it('should assign tint colors to the colors array in correct order', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); var path = [ makePoint(0, 0), makePoint(10, 0) ]; instance.run(ctx, submitter, path, 1, true, matrix, 0xAA, 0xBB, 0xCC, 0xDD, 0, false); var callArgs = submitter.batch.mock.calls[0]; var colors = callArgs[3]; // Order: tintTL, tintBL, tintBR, tintTR expect(colors[0]).toBe(0xAA); expect(colors[1]).toBe(0xCC); expect(colors[2]).toBe(0xDD); expect(colors[3]).toBe(0xBB); }); it('should produce 4 color entries per segment', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); var path = [ makePoint(0, 0), makePoint(10, 0), makePoint(20, 0), makePoint(30, 0) ]; instance.run(ctx, submitter, path, 1, true, matrix, 0, 0, 0, 0, 0, false); var callArgs = submitter.batch.mock.calls[0]; var colors = callArgs[3]; // 3 segments × 4 colors = 12 expect(colors.length).toBe(12); }); it('should pass lighting argument to submitterNode.batch', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); var path = [ makePoint(0, 0), makePoint(10, 0) ]; instance.run(ctx, submitter, path, 1, true, matrix, 0, 0, 0, 0, 0, true); var callArgs = submitter.batch.mock.calls[0]; expect(callArgs[4]).toBe(true); }); it('should skip intermediate points when detail causes close points to be culled', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); // Matrix with identity-like transform but non-zero tx/ty offsets do not affect delta var matrix = makeMatrix(); // Large detail value so intermediate points get skipped var detail = 100; // 4 points = 3 potential segments; the first intermediate is very close to // the start and gets skipped, reducing to 2 actual drawLineNode calls. // Note: the while-loop guard prevents skipping to the very last point, // so a minimum of 4 points is needed to demonstrate LOD culling. var path = [ makePoint(0, 0), makePoint(1, 0), // very close to first → skipped by LOD makePoint(2, 0), // becomes the end of the merged first segment makePoint(200, 0) // final point ]; instance.run(ctx, submitter, path, 1, true, matrix, 0, 0, 0, 0, detail, false); // LOD skipping merges the first two segments into one, // reducing 3 potential segments to 2 drawLineNode calls expect(drawLineNode.run).toHaveBeenCalledTimes(2); }); it('should not skip points when detail is 0', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); var path = [ makePoint(0, 0), makePoint(1, 0), makePoint(2, 0) ]; instance.run(ctx, submitter, path, 1, true, matrix, 0, 0, 0, 0, 0, false); // detail = 0 disables LOD, all points rendered: 2 segments expect(drawLineNode.run).toHaveBeenCalledTimes(2); }); it('should call drawLineNode.run with correct point coordinates', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); var path = [ makePoint(5, 10, 4), makePoint(15, 20, 6) ]; instance.run(ctx, submitter, path, 1, true, matrix, 0, 0, 0, 0, 0, false); var callArgs = drawLineNode.run.mock.calls[0]; // args: drawingContext, currentMatrix, x0, y0, x1, y1, hw0, hw1, vertices expect(callArgs[2]).toBe(5); expect(callArgs[3]).toBe(10); expect(callArgs[4]).toBe(15); expect(callArgs[5]).toBe(20); expect(callArgs[6]).toBe(2); // point.width / 2 expect(callArgs[7]).toBe(3); // nextPoint.width / 2 }); it('should produce vertices array with 8 entries per segment (from drawLineNode mock)', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); var path = [ makePoint(0, 0), makePoint(10, 0), makePoint(20, 0) ]; instance.run(ctx, submitter, path, 1, true, matrix, 0, 0, 0, 0, 0, false); var callArgs = submitter.batch.mock.calls[0]; var vertices = callArgs[2]; // 2 segments × 8 floats = 16 expect(vertices.length).toBe(16); }); it('should pass drawingContext to submitterNode.batch as first argument', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); var path = [ makePoint(0, 0), makePoint(10, 0) ]; instance.run(ctx, submitter, path, 1, true, matrix, 0, 0, 0, 0, 0, false); var callArgs = submitter.batch.mock.calls[0]; expect(callArgs[0]).toBe(ctx); }); it('should use first triangle winding: TL, BL, BR', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); var path = [ makePoint(0, 0), makePoint(10, 0) ]; instance.run(ctx, submitter, path, 1, true, matrix, 0, 0, 0, 0, 0, false); var callArgs = submitter.batch.mock.calls[0]; var indices = callArgs[1]; // vertexCount = 4 after first segment // TL=0, BL=1, BR=2, TR=3 expect(indices[0]).toBe(0); // TL expect(indices[1]).toBe(1); // BL expect(indices[2]).toBe(2); // BR }); it('should use second triangle winding: BR, TR, TL', function () { var ctx = makeDrawingContext(); var submitter = makeSubmitter(); var matrix = makeMatrix(); var path = [ makePoint(0, 0), makePoint(10, 0) ]; instance.run(ctx, submitter, path, 1, true, matrix, 0, 0, 0, 0, 0, false); var callArgs = submitter.batch.mock.calls[0]; var indices = callArgs[1]; expect(indices[3]).toBe(2); // BR expect(indices[4]).toBe(3); // TR expect(indices[5]).toBe(0); // TL }); }); });