UNPKG

phaser3-rex-plugins

Version:
1,454 lines (1,187 loc) 42.3 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.rexquadshapeplugin = factory()); })(this, (function () { 'use strict'; /* src: { fillColor, fillAlpha, pathData, pathIndexes // Earcut(pathData) } */ var Utils$1 = Phaser.Renderer.WebGL.Utils; var FillPathWebGL = function (pipeline, calcMatrix, src, alpha, dx, dy) { var fillTintColor = Utils$1.getTintAppendFloatAlpha(src.fillColor, src.fillAlpha * alpha); var path = src.pathData; var pathIndexes = src.pathIndexes; for (var i = 0; i < pathIndexes.length; i += 3) { var p0 = pathIndexes[i] * 2; var p1 = pathIndexes[i + 1] * 2; var p2 = pathIndexes[i + 2] * 2; var x0 = path[p0 + 0] - dx; var y0 = path[p0 + 1] - dy; var x1 = path[p1 + 0] - dx; var y1 = path[p1 + 1] - dy; var x2 = path[p2 + 0] - dx; var y2 = path[p2 + 1] - dy; var tx0 = calcMatrix.getX(x0, y0); var ty0 = calcMatrix.getY(x0, y0); var tx1 = calcMatrix.getX(x1, y1); var ty1 = calcMatrix.getY(x1, y1); var tx2 = calcMatrix.getX(x2, y2); var ty2 = calcMatrix.getY(x2, y2); pipeline.batchTri(src, tx0, ty0, tx1, ty1, tx2, ty2, 0, 0, 1, 1, fillTintColor, fillTintColor, fillTintColor, 2); } }; /* src: { strokeColor, strokeAlpha, pathData, lineWidth, closePath, isDashed, strokePathData, strokePathMask } */ var Utils = Phaser.Renderer.WebGL.Utils; var StrokePathWebGL = function (pipeline, src, alpha, dx, dy) { var strokeTint = pipeline.strokeTint; var strokeTintColor = Utils.getTintAppendFloatAlpha(src.strokeColor, src.strokeAlpha * alpha); strokeTint.TL = strokeTintColor; strokeTint.TR = strokeTintColor; strokeTint.BL = strokeTintColor; strokeTint.BR = strokeTintColor; var isDashed = src.isDashed && !!src.strokePathData; var path = (!isDashed) ? src.pathData : src.strokePathData; var pathLength = path.length - 1; var lineWidth = src.lineWidth; var halfLineWidth = lineWidth / 2; var px1 = path[0] - dx; var py1 = path[1] - dy; var px2, py2; if (!src.closePath) { pathLength -= 2; } if (!isDashed) { // Default behavior for (var i = 2; i < pathLength; i += 2) { px2 = path[i] - dx; py2 = path[i + 1] - dy; pipeline.batchLine( px1, py1, px2, py2, halfLineWidth, halfLineWidth, lineWidth, i - 2, (src.closePath) ? (i === pathLength - 1) : false ); px1 = px2; py1 = py2; } } else { // Draw dashed line var strokePathMask = src.strokePathMask; var drawMaskIdx = 0; var segLineIdx = 0; for (var i = 2; i < pathLength; i += 2) { px2 = path[i] - dx; py2 = path[i + 1] - dy; if (strokePathMask[drawMaskIdx]) { pipeline.batchLine( px1, py1, px2, py2, halfLineWidth, halfLineWidth, lineWidth, segLineIdx, false ); segLineIdx++; } else { segLineIdx = 0; } px1 = px2; py1 = py2; drawMaskIdx++; } } }; const GetCalcMatrix = Phaser.GameObjects.GetCalcMatrix; var PolygonWebGLRenderer = function (renderer, src, camera, parentMatrix) { if (src.dirty) { src.updateData(); src.dirty = false; } camera.addToRenderList(src); var pipeline = renderer.pipelines.set(src.pipeline); var result = GetCalcMatrix(src, camera, parentMatrix); var calcMatrix = pipeline.calcMatrix.copyFrom(result.calc); var dx = src._displayOriginX; var dy = src._displayOriginY; var alpha = camera.alpha * src.alpha; renderer.pipelines.preBatch(src); if (src.isFilled) { FillPathWebGL(pipeline, calcMatrix, src, alpha, dx, dy); } if (src.isStroked) { StrokePathWebGL(pipeline, src, alpha, dx, dy); } renderer.pipelines.postBatch(src); }; var FillStyleCanvas = function (ctx, src, altColor, altAlpha) { var fillColor = (altColor) ? altColor : src.fillColor; var fillAlpha = (altAlpha) ? altAlpha : src.fillAlpha; var red = ((fillColor & 0xFF0000) >>> 16); var green = ((fillColor & 0xFF00) >>> 8); var blue = (fillColor & 0xFF); ctx.fillStyle = 'rgba(' + red + ',' + green + ',' + blue + ',' + fillAlpha + ')'; }; /* src: { fillColor, fillAlpha, pathData, closePath } */ var FillPathCanvas = function (ctx, src, dx, dy) { var path = src.pathData; if (!path || (path.length < 4)) { return; } var pathLength = path.length - 1; var px1 = path[0] - dx; var py1 = path[1] - dy; ctx.beginPath(); ctx.moveTo(px1, py1); if (!src.closePath) { pathLength -= 2; } for (var i = 2; i < pathLength; i += 2) { var px2 = path[i] - dx; var py2 = path[i + 1] - dy; ctx.lineTo(px2, py2); } if (src.closePath) { ctx.closePath(); } FillStyleCanvas(ctx, src); ctx.fill(); }; var LineStyleCanvas = function (ctx, src, altColor, altAlpha) { var strokeColor = (altColor) ? altColor : src.strokeColor; var strokeAlpha = (altAlpha) ? altAlpha : src.strokeAlpha; var red = ((strokeColor & 0xFF0000) >>> 16); var green = ((strokeColor & 0xFF00) >>> 8); var blue = (strokeColor & 0xFF); ctx.strokeStyle = 'rgba(' + red + ',' + green + ',' + blue + ',' + strokeAlpha + ')'; ctx.lineWidth = src.lineWidth; }; /* src: { strokeColor, strokeAlpha, pathData, lineWidth, closePath, isDashed, strokePathData, strokePathMask } */ var StrokePathCanvas = function (ctx, src, dx, dy) { var isDashed = src.isDashed && !!src.strokePathData; var path = (!isDashed) ? src.pathData : src.strokePathData; if (!path || (path.length < 4)) { return; } var pathLength = path.length - 1; var px1 = path[0] - dx; var py1 = path[1] - dy; LineStyleCanvas(ctx, src); ctx.beginPath(); if (!src.closePath) { pathLength -= 2; } if (!isDashed) { // Default behavior ctx.moveTo(px1, py1); for (var i = 2; i < pathLength; i += 2) { var px2 = path[i] - dx; var py2 = path[i + 1] - dy; ctx.lineTo(px2, py2); } if (src.closePath) { ctx.closePath(); } } else { // Draw dashed line var strokePathMask = src.strokePathMask; var drawMaskIdx = 0; for (var i = 2; i < pathLength; i += 2) { var px2 = path[i] - dx; var py2 = path[i + 1] - dy; if (strokePathMask[drawMaskIdx]) { ctx.moveTo(px1, py1); ctx.lineTo(px2, py2); } px1 = px2; py1 = py2; drawMaskIdx++; } } ctx.stroke(); }; const SetTransform = Phaser.Renderer.Canvas.SetTransform; var PolygonCanvasRenderer = function (renderer, src, camera, parentMatrix) { if (src.dirty) { src.updateData(); src.dirty = false; } camera.addToRenderList(src); var ctx = renderer.currentContext; if (SetTransform(renderer, ctx, src, camera, parentMatrix)) { var dx = src._displayOriginX; var dy = src._displayOriginY; if (src.isFilled) { FillPathCanvas(ctx, src, dx, dy); } if (src.isStroked) { StrokePathCanvas(ctx, src, dx, dy); } // Restore the context saved in SetTransform ctx.restore(); } }; var Render = { renderWebGL: PolygonWebGLRenderer, renderCanvas: PolygonCanvasRenderer }; const EPSILON = 1e-6; const DEFAULT_SEGMENT_COUNT = 10; const DEFAULT_DRAW_RATIO = 0.5; var NormalizeDashArray = function (dashPattern) { if (!Array.isArray(dashPattern)) { return null; } var normalized = []; for (var i = 0, cnt = dashPattern.length; i < cnt; i++) { var d = Number(dashPattern[i]); if (isFinite(d) && (d > 0)) { normalized.push(d); } } return (normalized.length > 0) ? normalized : null; }; var BuildAutoDashPattern = function (dashPattern, totalPathLength) { var { segments = DEFAULT_SEGMENT_COUNT, drawRatio = DEFAULT_DRAW_RATIO } = dashPattern; segments = Math.round(segments); if (!isFinite(segments) || (segments <= 0)) { return null; } if (!(totalPathLength > EPSILON)) { return null; } var segmentLength = totalPathLength / segments; if (!(segmentLength > EPSILON)) { return null; } drawRatio = Math.max(0, Math.min(1, drawRatio)); if (drawRatio >= (1 - EPSILON)) { // 100% draw ratio becomes a solid stroke. return null; } var drawLength = segmentLength * drawRatio; if (drawLength <= EPSILON) { drawLength = EPSILON; } var gapLength = segmentLength - drawLength; if (gapLength <= EPSILON) { return null; } return [drawLength, gapLength]; }; var NormalizeDashPattern = function (dashPattern, totalPathLength) { return NormalizeDashArray(dashPattern) || BuildAutoDashPattern(dashPattern, totalPathLength); }; var WrapOffset = function (offset, totalLength) { if (!isFinite(offset)) { offset = 0; } offset = offset % totalLength; if (offset < 0) { offset += totalLength; } return offset; }; var ForEachStrokeSegment = function (pathData, closePath, callback) { if ((!pathData) || (pathData.length < 4)) { return; } var pathLength = pathData.length - 1; if (!closePath) { pathLength -= 2; } if (pathLength < 2) { return; } var px1 = pathData[0]; var py1 = pathData[1]; for (var i = 2; i < pathLength; i += 2) { var px2 = pathData[i]; var py2 = pathData[i + 1]; callback(px1, py1, px2, py2); px1 = px2; py1 = py2; } }; var GetTotalPathLength = function (pathData, closePath) { var totalLength = 0; ForEachStrokeSegment(pathData, closePath, function (x0, y0, x1, y1) { var dx = x1 - x0; var dy = y1 - y0; totalLength += Math.sqrt((dx * dx) + (dy * dy)); }); return totalLength; }; var BuildDashStroke = function (pathData, config, out) { if (config === undefined) { config = {}; } if (out === undefined) { out = {}; } var { closePath = false, dashPattern, dashOffset = 0, } = config; var totalPathLength = GetTotalPathLength(pathData, closePath); dashPattern = NormalizeDashPattern(dashPattern, totalPathLength); // No valid dash pattern -> keep original stroke path, disable mask. if (dashPattern === null) { return null; } var strokePathData = []; var strokePathMask = []; var totalPatternLength = 0; for (var i = 0, cnt = dashPattern.length; i < cnt; i++) { totalPatternLength += dashPattern[i]; } if (totalPatternLength <= EPSILON) { out.strokePathData = (pathData) ? pathData.slice() : []; out.strokePathMask = undefined; return out; } var patternIndex = 0; var draw = true; // Pattern starts from a draw segment. var patternRemain = dashPattern[patternIndex]; var AdvancePattern = function () { patternIndex = (patternIndex + 1) % dashPattern.length; draw = !draw; patternRemain = dashPattern[patternIndex]; }; var offset = WrapOffset(dashOffset, totalPatternLength); while (offset > EPSILON) { if (offset < (patternRemain - EPSILON)) { patternRemain -= offset; offset = 0; } else { offset -= patternRemain; AdvancePattern(); } } var PushSegment = function (x0, y0, x1, y1, drawState) { if (strokePathData.length === 0) { strokePathData.push(x0, y0); } else { var lastX = strokePathData[strokePathData.length - 2]; var lastY = strokePathData[strokePathData.length - 1]; if ((lastX !== x0) || (lastY !== y0)) { strokePathData.push(x0, y0); } } strokePathData.push(x1, y1); strokePathMask.push(drawState ? 1 : 0); }; ForEachStrokeSegment(pathData, closePath, function (x0, y0, x1, y1) { var dx = x1 - x0; var dy = y1 - y0; var segLength = Math.sqrt((dx * dx) + (dy * dy)); if (segLength <= EPSILON) { return; } var traveled = 0; while (traveled < (segLength - EPSILON)) { var step = Math.min(patternRemain, segLength - traveled); if (step <= EPSILON) { AdvancePattern(); continue; } var t0 = traveled / segLength; var t1 = (traveled + step) / segLength; var sx = x0 + (dx * t0); var sy = y0 + (dy * t0); var ex = x0 + (dx * t1); var ey = y0 + (dy * t1); PushSegment(sx, sy, ex, ey, draw); traveled += step; patternRemain -= step; if (patternRemain <= EPSILON) { AdvancePattern(); } } }); // Keep the existing open-path convention in StrokePathWebGL: // an extra tail point is ignored by the renderer when closePath=false. if (!closePath && (strokePathData.length >= 2)) { strokePathData.push( strokePathData[strokePathData.length - 2], strokePathData[strokePathData.length - 1] ); } out.strokePathData = strokePathData; out.strokePathMask = strokePathMask; return out; }; var SetDashPattern = function (dashPattern, dashOffset) { // dashPattern: [draw, gap] , or {segments, drawRatio} this.dashPattern = dashPattern; this.dashOffset = dashOffset || 0; this.isDashed = !!dashPattern; return this; }; var ClearDashPattern = function () { this.setDashPattern(); return this; }; var SetDashed = function (enable) { if (enable === undefined) { enable = true; } this.isDashed = enable; return this; }; var BuildStrokePath = function () { if (this.isDashed) { var result = BuildDashStroke(this.pathData, { closePath: this.closePath, dashPattern: this.dashPattern, dashOffset: this.dashOffset }, this); if (result) { this.strokePathData = result.strokePathData; this.strokePathMask = result.strokePathMask; } else { this.isDashed = false; } } return this; }; var StrokePathConfigMethods = { setDashPattern: SetDashPattern, clearDashPattern: ClearDashPattern, setDashed: SetDashed }; var Methods = { buildStrokePath: BuildStrokePath }; Object.assign( Methods, StrokePathConfigMethods, ); const Shape = Phaser.GameObjects.Shape; class PolygnBase extends Shape { init() { this.isDashed = false; this.strokePathData = undefined; this.strokePathMask = undefined; this.dashPattern = undefined; this.dashOffset = 0; } get fillColor() { return this._fillColor; } set fillColor(value) { this._fillColor = value; this.isFilled = (value != null) && (this._fillAlpha > 0); } get fillAlpha() { return this._fillAlpha; } set fillAlpha(value) { this._fillAlpha = value; this.isFilled = (value > 0) && (this._fillColor != null); } // Fully override setFillStyle method setFillStyle(color, alpha) { if (alpha === undefined) { alpha = 1; } this.fillColor = color; this.fillAlpha = alpha; return this; } get strokeColor() { return this._strokeColor; } set strokeColor(value) { this._strokeColor = value; this.isStroked = (value != null) && (this._strokeAlpha > 0) && (this._lineWidth > 0); } get strokeAlpha() { return this._strokeAlpha; } set strokeAlpha(value) { this._strokeAlpha = value; this.isStroked = (value > 0) && (this._strokeColor != null) && (this._lineWidth > 0); } get lineWidth() { return this._lineWidth; } set lineWidth(value) { this._lineWidth = value; this.isStroked = (value > 0) && (this._strokeColor != null); } // Fully override setStrokeStyle method setStrokeStyle(lineWidth, color, alpha) { if (alpha === undefined) { alpha = 1; } this.lineWidth = lineWidth; this.strokeColor = color; this.strokeAlpha = alpha; return this; } updateData() { // Update this.pathData this.buildStrokePath(); return this; } get width() { return this.geom.width; } set width(value) { this.resize(value, this.height); } get height() { return this.geom.height; } set height(value) { this.resize(this.width, value); } setSize(width, height) { var input = this.input; if (input && !input.customHitArea) { input.hitArea.width = width; input.hitArea.height = height; } return this; } resize(width, height) { this.setSize(width, height); return this; } } Object.assign( PolygnBase.prototype, Methods, Render ); var HasProperty = function (obj, prop) { if (!obj) { return false; } if (obj.hasOwnProperty(prop)) { return true; } while (obj) { if (Object.getOwnPropertyDescriptor(obj, prop)) { return true; } obj = obj.__proto__; } return false; }; var InjectPointAccessProperties = function (gameObject, key, point) { if (!key || HasProperty(gameObject, `${key}X`)) { return; } Object.defineProperty(gameObject, `${key}X`, { get: function () { return point.x; }, set: function (value) { point.x = value; gameObject.dirty = true; }, }); Object.defineProperty(gameObject, `${key}Y`, { get: function () { return point.y; }, set: function (value) { point.y = value; gameObject.dirty = true; }, }); Object.defineProperty(gameObject, `${key}T`, { get: function () { return point.t; }, set: function (value) { point.t = value; gameObject.dirty = true; }, }); }; var PointMethods = { setTLPosition(x, y) { this.geom.setTLPosition(x, y); this.dirty = true; return this; }, setTRPosition(x, y) { this.geom.setTRPosition(x, y); this.dirty = true; return this; }, setBLPosition(x, y) { this.geom.setBLPosition(x, y); this.dirty = true; return this; }, setBRPosition(x, y) { this.geom.setBRPosition(x, y); this.dirty = true; return this; }, resetCornerPosition() { this.geom.resetCornerPosition(); this.dirty = true; return this; }, insertTopSidePoint(t, x, y, key) { var points = this.geom.topSidePoints; if (Array.isArray(t)) { var points = t, point; for (var i = 0, cnt = points.length; i < cnt; i++) { point = points[i]; this.geom.insertTopSidePoint(point.t, point.x, point.y); InjectPointAccessProperties(this, point.key, points[points.length - 1]); } } else { this.geom.insertTopSidePoint(t, x, y); InjectPointAccessProperties(this, key, points[points.length - 1]); } this.dirty = true; return this; }, insertRightSidePoint(t, x, y, key) { var points = this.geom.rightSidePoints; if (Array.isArray(t)) { var points = t, point; for (var i = 0, cnt = points.length; i < cnt; i++) { point = points[i]; this.geom.insertRightSidePoint(point.t, point.x, point.y); InjectPointAccessProperties(this, point.key, points[points.length - 1]); } } else { this.geom.insertRightSidePoint(t, x, y); InjectPointAccessProperties(this, key, points[points.length - 1]); } this.dirty = true; return this; }, insertBottomSidePoint(t, x, y, key) { var points = this.geom.bottomSidePoints; if (Array.isArray(t)) { var points = t, point; for (var i = 0, cnt = points.length; i < cnt; i++) { point = points[i]; this.geom.insertBottomSidePoint(point.t, point.x, point.y); InjectPointAccessProperties(this, point.key, points[points.length - 1]); } } else { this.geom.insertBottomSidePoint(t, x, y); InjectPointAccessProperties(this, key, points[points.length - 1]); } this.dirty = true; return this; }, insertLeftSidePoint(t, x, y, key) { var points = this.geom.leftSidePoints; if (Array.isArray(t)) { var points = t, point; for (var i = 0, cnt = points.length; i < cnt; i++) { point = points[i]; this.geom.insertLeftSidePoint(point.t, point.x, point.y); InjectPointAccessProperties(this, point.key, points[points.length - 1]); } } else { this.geom.insertLeftSidePoint(t, x, y); InjectPointAccessProperties(this, key, points[points.length - 1]); } this.dirty = true; return this; }, clearTopSidePoints() { this.geom.clearTopSidePoints(); this.dirty = true; return this; }, clearRightSidePoints() { this.geom.clearRightSidePoints(); this.dirty = true; return this; }, clearBottomSidePoints() { this.geom.clearBottomSidePoints(); this.dirty = true; return this; }, clearLeftSidePoints() { this.geom.clearLeftSidePoints(); this.dirty = true; return this; }, clearAllSidesPoints() { this.geom.clearAllSidesPoints(); this.dirty = true; return this; }, }; class QuadGeom { constructor(x, y, width, height) { if (x === undefined) { x = 0; } if (y === undefined) { y = x; } if (width === undefined) { width = 0; } if (height === undefined) { height = 0; } this.setTo(x, y, width, height); this.tlx = 0; this.tly = 0; this.trx = 0; this.try = 0; this.blx = 0; this.bly = 0; this.brx = 0; this.bry = 0; this.topSidePoints = []; this.rightSidePoints = []; this.bottomSidePoints = []; this.leftSidePoints = []; } setTo(x, y, width, height) { this.setPosition(x, y); this.setSize(width, height); return this; } setPosition(x, y) { this.x = x; this.y = y; return this; } setSize(width, height) { this.width = width; this.height = height; return this; } setTLPosition(x, y) { this.tlx = x; this.tly = y; return this; } setTRPosition(x, y) { this.trx = x; this.try = y; return this; } setBLPosition(x, y) { this.blx = x; this.bly = y; return this; } setBRPosition(x, y) { this.brx = x; this.bry = y; return this; } resetCornerPosition() { this .setTLPosition(0, 0) .setTRPosition(0, 0) .setBLPosition(0, 0) .setBRPosition(0, 0); return this; } insertTopSidePoint(t, x, y) { AddPoint(this.topSidePoints, t, x, y); return this; } insertRightSidePoint(t, x, y) { AddPoint(this.rightSidePoints, t, x, y); return this; } insertBottomSidePoint(t, x, y) { AddPoint(this.bottomSidePoints, t, x, y); return this; } insertLeftSidePoint(t, x, y) { AddPoint(this.leftSidePoints, t, x, y); return this; } clearTopSidePoints() { this.topSidePoints.length = 0; return this; } clearRightSidePoints() { this.rightSidePoints.length = 0; return this; } clearBottomSidePoints() { this.bottomSidePoints.length = 0; return this; } clearLeftSidePoints() { this.leftSidePoints.length = 0; return this; } clearAllSidesPoints() { this .clearTopSidePoints() .clearRightSidePoints() .clearBottomSidePoints() .clearLeftSidePoints(); return this; } } var AddPoint = function (points, t, x, y) { if (typeof (t) !== 'number') { var config = t; t = config.t; x = config.x; y = config.y; } points.push({ t: t, x: x, y: y }); }; var LineTo = function (x, y, pathData) { var cnt = pathData.length; if (cnt >= 2) { var lastX = pathData[cnt - 2]; var lastY = pathData[cnt - 1]; if ((x === lastX) && (y === lastY)) { return pathData; } } pathData.push(x, y); return pathData; }; const IsPlainObject = Phaser.Utils.Objects.IsPlainObject; const GetValue = Phaser.Utils.Objects.GetValue; const Linear = Phaser.Math.Linear; const Earcut = Phaser.Geom.Polygon.Earcut; class Quad extends PolygnBase { constructor(scene, x, y, width, height, fillColor, fillAlpha) { var strokeColor, strokeAlpha, strokeWidth; if (IsPlainObject(x)) { var config = x; x = config.x; y = config.y; width = config.width; height = config.height; fillColor = config.color; fillAlpha = config.alpha; strokeColor = config.strokeColor; strokeAlpha = config.strokeAlpha; strokeWidth = config.strokeWidth; } if (x === undefined) { x = 0; } if (y === undefined) { y = 0; } if (width === undefined) { width = 1; } if (height === undefined) { height = width; } var geom = new QuadGeom(); // Configurate it later super(scene, 'rexQuadShape', geom); this.init(); geom.setTo(0, 0, width, height); this.setPosition(x, y); this.setFillStyle(fillColor, fillAlpha); if ((strokeColor !== undefined) && (strokeWidth === undefined)) { strokeWidth = 2; } this.setStrokeStyle(strokeWidth, strokeColor, strokeAlpha); this .setTLPosition(GetValue(config, 'tlx', 0), GetValue(config, 'tly', 0)) .setTRPosition(GetValue(config, 'trx', 0), GetValue(config, 'try', 0)) .setBLPosition(GetValue(config, 'blx', 0), GetValue(config, 'bly', 0)) .setBRPosition(GetValue(config, 'brx', 0), GetValue(config, 'bry', 0)); var leftSidePoints = GetValue(config, 'leftSidePoints'); if (leftSidePoints) { this.insertLeftSidePoint(leftSidePoints); } var topSidePoints = GetValue(config, 'topSidePoints'); if (topSidePoints) { this.insertTopSidePoint(topSidePoints); } var rightSidePoints = GetValue(config, 'rightSidePoints'); if (rightSidePoints) { this.insertRightSidePoint(rightSidePoints); } var bottomSidePoints = GetValue(config, 'bottomSidePoints'); if (bottomSidePoints) { this.insertBottomSidePoint(bottomSidePoints); } this.updateDisplayOrigin(); this.dirty = true; } updateData() { var geom = this.geom; var pathData = this.pathData; pathData.length = 0; var width = geom.width; var height = geom.height; var tlx = 0 + geom.tlx; var tly = 0 + geom.tly; var trx = width + geom.trx; var try_ = 0 + geom.try; var brx = width + geom.brx; var bry = height + geom.bry; var blx = 0 + geom.blx; var bly = height + geom.bly; var topSidePoints = geom.topSidePoints; var rightSidePoints = geom.rightSidePoints; var bottomSidePoints = geom.bottomSidePoints; var leftSidePoints = geom.leftSidePoints; // Top side LineTo(tlx, tly, pathData); SortPoints(topSidePoints); for (var i = 0, cnt = topSidePoints.length; i < cnt; i++) { var point = topSidePoints[i]; var px = Linear(tlx, trx, point.t) + point.x; var py = Linear(tly, try_, point.t) + point.y; LineTo(px, py, pathData); } // Right side LineTo(trx, try_, pathData); SortPoints(rightSidePoints); for (var i = 0, cnt = rightSidePoints.length; i < cnt; i++) { var point = rightSidePoints[i]; var px = Linear(trx, brx, point.t) + point.x; var py = Linear(try_, bry, point.t) + point.y; LineTo(px, py, pathData); } // Bottom side LineTo(brx, bry, pathData); SortPoints(bottomSidePoints); for (var i = bottomSidePoints.length - 1; i >= 0; i--) { var point = bottomSidePoints[i]; var px = Linear(blx, brx, point.t) + point.x; var py = Linear(bly, bry, point.t) + point.y; LineTo(px, py, pathData); } // Left side LineTo(blx, bly, pathData); SortPoints(leftSidePoints); for (var i = leftSidePoints.length - 1; i >= 0; i--) { var point = leftSidePoints[i]; var px = Linear(tlx, blx, point.t) + point.x; var py = Linear(tly, bly, point.t) + point.y; LineTo(px, py, pathData); } pathData.push(pathData[0], pathData[1]); // Repeat first point to close curve this.pathIndexes = Earcut(pathData); super.updateData(); return this; } get tlx() { return this.geom.tlx; } set tlx(value) { this.geom.tlx = value; this.dirty = true; } get tly() { return this.geom.tly; } set tly(value) { this.geom.tly = value; this.dirty = true; } get trx() { return this.geom.trx; } set trx(value) { this.geom.trx = value; this.dirty = true; } get try() { return this.geom.try; } set try(value) { this.geom.try = value; this.dirty = true; } get blx() { return this.geom.blx; } set blx(value) { this.geom.blx = value; this.dirty = true; } get bly() { return this.geom.bly; } set bly(value) { this.geom.bly = value; this.dirty = true; } get brx() { return this.geom.brx; } set brx(value) { this.geom.brx = value; this.dirty = true; } get bry() { return this.geom.bry; } set bry(value) { this.geom.bry = value; this.dirty = true; } get leftSidePoints() { return this.geom.leftSidePoints; } get topSidePoints() { return this.geom.topSidePoints; } get bottomSidePoints() { return this.geom.bottomSidePoints; } get rightSidePoints() { return this.geom.rightSidePoints; } } var SortPoints = function (points) { if (points.length <= 1) { return; } points.sort(function (pointA, pointB) { return pointA.t - pointB.t; }); }; Object.assign( Quad.prototype, PointMethods, ); function Factory (x, y, width, height, fillColor, fillAlpha) { var gameObject = new Quad(this.scene, x, y, width, height, fillColor, fillAlpha); this.scene.add.existing(gameObject); return gameObject; } const GetAdvancedValue = Phaser.Utils.Objects.GetAdvancedValue; const BuildGameObject = Phaser.GameObjects.BuildGameObject; function Creator (config, addToScene) { if (config === undefined) { config = {}; } if (addToScene !== undefined) { config.add = addToScene; } var width = GetAdvancedValue(config, 'width', undefined); var height = GetAdvancedValue(config, 'height', width); var fillColor = GetAdvancedValue(config, 'fillColor', undefined); var fillAlpha = GetAdvancedValue(config, 'fillAlpha', undefined); var gameObject = new Quad(this.scene, 0, 0, width, height, fillColor, fillAlpha); BuildGameObject(this.scene, gameObject, config); return gameObject; } var IsNil = function (value) { return value === null || value === undefined; }; var IsObjectLike = function (value) { return value !== null && typeof value === 'object'; }; var NormalizePath = function (path, delimiter) { if (Array.isArray(path)) ; else if (typeof path !== 'string') { path = []; } else if (path.trim() === '') { path = []; } else { path = path.split(delimiter).filter(Boolean); } return path; }; /** * Set a nested value into target by path (mutates target). * * - If keys is a string and does NOT contain delimiter, write directly. * - Intermediate non-plain-object values are always overwritten with {}. * * @param {object} target * @param {string|string[]} keys * @param {*} value * @param {string} [delimiter='.'] * @returns {object} the same target reference */ var SetValue = function (target, keys, value, delimiter = '.') { if (!IsObjectLike(target)) { return target; } // Invalid key: no-op; don't replace root if (IsNil(keys) || keys === '' || (Array.isArray(keys) && keys.length === 0)) { return target; } // Fast path: single key if ( (typeof keys === 'string' && keys.indexOf(delimiter) === -1) || (typeof keys === 'number') ) { target[keys] = value; return target; } var pathSegments = NormalizePath(keys, delimiter); if (pathSegments.length === 0) { return target; } var cursor = target; var pathSegmentsCount = pathSegments.length; for (var index = 0; index < pathSegmentsCount - 1; index++) { var segment = pathSegments[index]; var next = cursor[segment]; if (!IsObjectLike(next)) { // Force overwrite intermediates cursor[segment] = {}; } cursor = cursor[segment]; } cursor[pathSegments[pathSegmentsCount - 1]] = value; return target; }; class QuadPlugin extends Phaser.Plugins.BasePlugin { constructor(pluginManager) { super(pluginManager); // Register our new Game Object type pluginManager.registerGameObject('rexQuadShape', Factory, Creator); } start() { var eventEmitter = this.game.events; eventEmitter.on('destroy', this.destroy, this); } } SetValue(window, 'RexPlugins.GameObjects.QuadShape', Quad); return QuadPlugin; }));