Files

151 lines
5.5 KiB
JavaScript
Raw Permalink Normal View History

2025-01-04 00:34:03 +01:00
/**
* Draws a path.
* @param {number[]|PIXI.IPointData[]|PIXI.Polygon|...number|...PIXI.IPointData} path The polygon or points.
* @returns {this} This Graphics instance.
*/
PIXI.Graphics.prototype.drawPath = function(...path) {
let closeStroke = false;
let polygon = path[0];
let points;
if ( polygon.points ) {
closeStroke = polygon.closeStroke;
points = polygon.points;
} else if ( Array.isArray(path[0]) ) {
points = path[0];
} else {
points = path;
}
polygon = new PIXI.Polygon(points);
polygon.closeStroke = closeStroke;
return this.drawShape(polygon);
};
PIXI.LegacyGraphics.prototype.drawPath = PIXI.Graphics.prototype.drawPath;
PIXI.smooth.SmoothGraphics.prototype.drawPath = PIXI.Graphics.prototype.drawPath;
/* -------------------------------------------- */
/**
* Draws a smoothed polygon.
* @param {number[]|PIXI.IPointData[]|PIXI.Polygon|...number|...PIXI.IPointData} path The polygon or points.
* @param {number} [smoothing=0] The smoothness in the range [0, 1]. 0: no smoothing; 1: maximum smoothing.
* @returns {this} This Graphics instance.
*/
PIXI.Graphics.prototype.drawSmoothedPolygon = function(...path) {
let closeStroke = true;
let polygon = path[0];
let points;
let factor;
if ( polygon.points ) {
closeStroke = polygon.closeStroke;
points = polygon.points;
factor = path[1];
} else if ( Array.isArray(path[0]) ) {
points = path[0];
factor = path[1];
} else if ( typeof path[0] === "number" ) {
points = path;
factor = path.length % 2 ? path.at(-1) : 0;
} else {
const n = path.length - (typeof path.at(-1) !== "object" ? 1 : 0);
points = [];
for ( let i = 0; i < n; i++ ) points.push(path[i].x, path[i].y);
factor = path.at(n);
}
factor ??= 0;
if ( (points.length < 6) || (factor <= 0) ) {
polygon = new PIXI.Polygon(points.slice(0, points.length - (points.length % 2)));
polygon.closeStroke = closeStroke;
return this.drawShape(polygon);
}
const dedupedPoints = [points[0], points[1]];
for ( let i = 2; i < points.length - 1; i += 2 ) {
const x = points[i];
const y = points[i + 1];
if ( (x === points[i - 2]) && (y === points[i - 1]) ) continue;
dedupedPoints.push(x, y);
}
points = dedupedPoints;
if ( closeStroke && (points[0] === points.at(-2)) && (points[1] === points.at(-1)) ) points.length -= 2;
if ( points.length < 6 ) {
polygon = new PIXI.Polygon(points);
polygon.closeStroke = closeStroke;
return this.drawShape(polygon);
}
const getBezierControlPoints = (fromX, fromY, toX, toY, nextX, nextY) => {
const vectorX = nextX - fromX;
const vectorY = nextY - fromY;
const preDistance = Math.hypot(toX - fromX, toY - fromY);
const postDistance = Math.hypot(nextX - toX, nextY - toY);
const totalDistance = preDistance + postDistance;
const cp0d = 0.5 * factor * (preDistance / totalDistance);
const cp1d = 0.5 * factor * (postDistance / totalDistance);
return [
toX - (vectorX * cp0d),
toY - (vectorY * cp0d),
toX + (vectorX * cp1d),
toY + (vectorY * cp1d)
];
};
let [fromX, fromY, toX, toY] = points;
let [cpX, cpY, cpXNext, cpYNext] = getBezierControlPoints(points.at(-2), points.at(-1), fromX, fromY, toX, toY);
this.moveTo(fromX, fromY);
for ( let i = 2, n = points.length + (closeStroke ? 2 : 0); i < n; i += 2 ) {
const nextX = points[(i + 2) % points.length];
const nextY = points[(i + 3) % points.length];
cpX = cpXNext;
cpY = cpYNext;
let cpX2;
let cpY2;
[cpX2, cpY2, cpXNext, cpYNext] = getBezierControlPoints(fromX, fromY, toX, toY, nextX, nextY);
if ( !closeStroke && (i === 2) ) this.quadraticCurveTo(cpX2, cpY2, toX, toY);
else if ( !closeStroke && (i === points.length - 2) ) this.quadraticCurveTo(cpX, cpY, toX, toY);
else this.bezierCurveTo(cpX, cpY, cpX2, cpY2, toX, toY);
fromX = toX;
fromY = toY;
toX = nextX;
toY = nextY;
}
if ( closeStroke ) this.closePath();
this.finishPoly();
return this;
};
PIXI.LegacyGraphics.prototype.drawSmoothedPolygon = PIXI.Graphics.prototype.drawSmoothedPolygon;
PIXI.smooth.SmoothGraphics.prototype.drawSmoothedPolygon = PIXI.Graphics.prototype.drawSmoothedPolygon;
/* -------------------------------------------- */
/**
* Draws a smoothed path.
* @param {number[]|PIXI.IPointData[]|PIXI.Polygon|...number|...PIXI.IPointData} path The polygon or points.
* @param {number} [smoothing=0] The smoothness in the range [0, 1]. 0: no smoothing; 1: maximum smoothing.
* @returns {this} This Graphics instance.
*/
PIXI.Graphics.prototype.drawSmoothedPath = function(...path) {
let closeStroke = false;
let polygon = path[0];
let points;
let factor;
if ( polygon.points ) {
closeStroke = polygon.closeStroke;
points = polygon.points;
factor = path[1];
} else if ( Array.isArray(path[0]) ) {
points = path[0];
factor = path[1];
} else if ( typeof path[0] === "number" ) {
points = path;
factor = path.length % 2 ? path.at(-1) : 0;
} else {
const n = path.length - (typeof path.at(-1) !== "object" ? 1 : 0);
points = [];
for ( let i = 0; i < n; i++ ) points.push(path[i].x, path[i].y);
factor = path.at(n);
}
polygon = new PIXI.Polygon(points);
polygon.closeStroke = closeStroke;
return this.drawSmoothedPolygon(polygon, factor);
};
PIXI.LegacyGraphics.prototype.drawSmoothedPath = PIXI.Graphics.prototype.drawSmoothedPath;
PIXI.smooth.SmoothGraphics.prototype.drawSmoothedPath = PIXI.Graphics.prototype.drawSmoothedPath;