This commit is contained in:
Akko
2025-08-04 18:57:35 +02:00
parent 8cf6e78a79
commit 9495868c2e
5030 changed files with 518594 additions and 17609 deletions

View File

@@ -0,0 +1,25 @@
declare global
{
namespace PixiMixins
{
interface RendererSystems
{
graphicsContext: import('./shared/GraphicsContextSystem').GraphicsContextSystem;
}
interface RendererPipes
{
graphics: import('./shared/GraphicsPipe').GraphicsPipe;
}
interface RendererOptions
{
/**
* A value from 0 to 1 that controls the smoothness of bezier curves (the higher the smoother)
* @default 0.5
*/
bezierSmoothness: number
}
}
}
export {};

View File

@@ -0,0 +1,20 @@
import { ExtensionType } from '../../../extensions/Extensions';
import { Shader } from '../../../rendering/renderers/shared/shader/Shader';
import type { Graphics } from '../shared/Graphics';
import type { GraphicsAdaptor, GraphicsPipe } from '../shared/GraphicsPipe';
/**
* A GraphicsAdaptor that uses WebGL to render graphics.
* @memberof rendering
* @ignore
*/
export declare class GlGraphicsAdaptor implements GraphicsAdaptor {
/** @ignore */
static extension: {
readonly type: readonly [ExtensionType.WebGLPipesAdaptor];
readonly name: "graphics";
};
shader: Shader;
init(): void;
execute(graphicsPipe: GraphicsPipe, renderable: Graphics): void;
destroy(): void;
}

View File

@@ -0,0 +1,79 @@
'use strict';
var Extensions = require('../../../extensions/Extensions.js');
var Matrix = require('../../../maths/matrix/Matrix.js');
var maxRecommendedTextures = require('../../../rendering/batcher/gl/utils/maxRecommendedTextures.js');
var compileHighShaderToProgram = require('../../../rendering/high-shader/compileHighShaderToProgram.js');
var colorBit = require('../../../rendering/high-shader/shader-bits/colorBit.js');
var generateTextureBatchBit = require('../../../rendering/high-shader/shader-bits/generateTextureBatchBit.js');
var localUniformBit = require('../../../rendering/high-shader/shader-bits/localUniformBit.js');
var roundPixelsBit = require('../../../rendering/high-shader/shader-bits/roundPixelsBit.js');
var getBatchSamplersUniformGroup = require('../../../rendering/renderers/gl/shader/getBatchSamplersUniformGroup.js');
var Shader = require('../../../rendering/renderers/shared/shader/Shader.js');
var UniformGroup = require('../../../rendering/renderers/shared/shader/UniformGroup.js');
"use strict";
class GlGraphicsAdaptor {
init() {
const uniforms = new UniformGroup.UniformGroup({
uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
uTransformMatrix: { value: new Matrix.Matrix(), type: "mat3x3<f32>" },
uRound: { value: 0, type: "f32" }
});
const maxTextures = maxRecommendedTextures.getMaxTexturesPerBatch();
const glProgram = compileHighShaderToProgram.compileHighShaderGlProgram({
name: "graphics",
bits: [
colorBit.colorBitGl,
generateTextureBatchBit.generateTextureBatchBitGl(maxTextures),
localUniformBit.localUniformBitGl,
roundPixelsBit.roundPixelsBitGl
]
});
this.shader = new Shader.Shader({
glProgram,
resources: {
localUniforms: uniforms,
batchSamplers: getBatchSamplersUniformGroup.getBatchSamplersUniformGroup(maxTextures)
}
});
}
execute(graphicsPipe, renderable) {
const context = renderable.context;
const shader = context.customShader || this.shader;
const renderer = graphicsPipe.renderer;
const contextSystem = renderer.graphicsContext;
const {
batcher,
instructions
} = contextSystem.getContextRenderData(context);
shader.groups[0] = renderer.globalUniforms.bindGroup;
renderer.state.set(graphicsPipe.state);
renderer.shader.bind(shader);
renderer.geometry.bind(batcher.geometry, shader.glProgram);
const batches = instructions.instructions;
for (let i = 0; i < instructions.instructionSize; i++) {
const batch = batches[i];
if (batch.size) {
for (let j = 0; j < batch.textures.count; j++) {
renderer.texture.bind(batch.textures.textures[j], j);
}
renderer.geometry.draw("triangle-list", batch.size, batch.start);
}
}
}
destroy() {
this.shader.destroy(true);
this.shader = null;
}
}
/** @ignore */
GlGraphicsAdaptor.extension = {
type: [
Extensions.ExtensionType.WebGLPipesAdaptor
],
name: "graphics"
};
exports.GlGraphicsAdaptor = GlGraphicsAdaptor;
//# sourceMappingURL=GlGraphicsAdaptor.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,77 @@
import { ExtensionType } from '../../../extensions/Extensions.mjs';
import { Matrix } from '../../../maths/matrix/Matrix.mjs';
import { getMaxTexturesPerBatch } from '../../../rendering/batcher/gl/utils/maxRecommendedTextures.mjs';
import { compileHighShaderGlProgram } from '../../../rendering/high-shader/compileHighShaderToProgram.mjs';
import { colorBitGl } from '../../../rendering/high-shader/shader-bits/colorBit.mjs';
import { generateTextureBatchBitGl } from '../../../rendering/high-shader/shader-bits/generateTextureBatchBit.mjs';
import { localUniformBitGl } from '../../../rendering/high-shader/shader-bits/localUniformBit.mjs';
import { roundPixelsBitGl } from '../../../rendering/high-shader/shader-bits/roundPixelsBit.mjs';
import { getBatchSamplersUniformGroup } from '../../../rendering/renderers/gl/shader/getBatchSamplersUniformGroup.mjs';
import { Shader } from '../../../rendering/renderers/shared/shader/Shader.mjs';
import { UniformGroup } from '../../../rendering/renderers/shared/shader/UniformGroup.mjs';
"use strict";
class GlGraphicsAdaptor {
init() {
const uniforms = new UniformGroup({
uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
uTransformMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
uRound: { value: 0, type: "f32" }
});
const maxTextures = getMaxTexturesPerBatch();
const glProgram = compileHighShaderGlProgram({
name: "graphics",
bits: [
colorBitGl,
generateTextureBatchBitGl(maxTextures),
localUniformBitGl,
roundPixelsBitGl
]
});
this.shader = new Shader({
glProgram,
resources: {
localUniforms: uniforms,
batchSamplers: getBatchSamplersUniformGroup(maxTextures)
}
});
}
execute(graphicsPipe, renderable) {
const context = renderable.context;
const shader = context.customShader || this.shader;
const renderer = graphicsPipe.renderer;
const contextSystem = renderer.graphicsContext;
const {
batcher,
instructions
} = contextSystem.getContextRenderData(context);
shader.groups[0] = renderer.globalUniforms.bindGroup;
renderer.state.set(graphicsPipe.state);
renderer.shader.bind(shader);
renderer.geometry.bind(batcher.geometry, shader.glProgram);
const batches = instructions.instructions;
for (let i = 0; i < instructions.instructionSize; i++) {
const batch = batches[i];
if (batch.size) {
for (let j = 0; j < batch.textures.count; j++) {
renderer.texture.bind(batch.textures.textures[j], j);
}
renderer.geometry.draw("triangle-list", batch.size, batch.start);
}
}
}
destroy() {
this.shader.destroy(true);
this.shader = null;
}
}
/** @ignore */
GlGraphicsAdaptor.extension = {
type: [
ExtensionType.WebGLPipesAdaptor
],
name: "graphics"
};
export { GlGraphicsAdaptor };
//# sourceMappingURL=GlGraphicsAdaptor.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,20 @@
import { ExtensionType } from '../../../extensions/Extensions';
import { Shader } from '../../../rendering/renderers/shared/shader/Shader';
import type { Graphics } from '../shared/Graphics';
import type { GraphicsAdaptor, GraphicsPipe } from '../shared/GraphicsPipe';
/**
* A GraphicsAdaptor that uses the GPU to render graphics.
* @memberof rendering
* @ignore
*/
export declare class GpuGraphicsAdaptor implements GraphicsAdaptor {
/** @ignore */
static extension: {
readonly type: readonly [ExtensionType.WebGPUPipesAdaptor];
readonly name: "graphics";
};
shader: Shader;
init(): void;
execute(graphicsPipe: GraphicsPipe, renderable: Graphics): void;
destroy(): void;
}

View File

@@ -0,0 +1,91 @@
'use strict';
var Extensions = require('../../../extensions/Extensions.js');
var Matrix = require('../../../maths/matrix/Matrix.js');
var maxRecommendedTextures = require('../../../rendering/batcher/gl/utils/maxRecommendedTextures.js');
var getTextureBatchBindGroup = require('../../../rendering/batcher/gpu/getTextureBatchBindGroup.js');
var compileHighShaderToProgram = require('../../../rendering/high-shader/compileHighShaderToProgram.js');
var colorBit = require('../../../rendering/high-shader/shader-bits/colorBit.js');
var generateTextureBatchBit = require('../../../rendering/high-shader/shader-bits/generateTextureBatchBit.js');
var localUniformBit = require('../../../rendering/high-shader/shader-bits/localUniformBit.js');
var roundPixelsBit = require('../../../rendering/high-shader/shader-bits/roundPixelsBit.js');
var Shader = require('../../../rendering/renderers/shared/shader/Shader.js');
var UniformGroup = require('../../../rendering/renderers/shared/shader/UniformGroup.js');
"use strict";
class GpuGraphicsAdaptor {
init() {
const localUniforms = new UniformGroup.UniformGroup({
uTransformMatrix: { value: new Matrix.Matrix(), type: "mat3x3<f32>" },
uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
uRound: { value: 0, type: "f32" }
});
const gpuProgram = compileHighShaderToProgram.compileHighShaderGpuProgram({
name: "graphics",
bits: [
colorBit.colorBit,
generateTextureBatchBit.generateTextureBatchBit(maxRecommendedTextures.getMaxTexturesPerBatch()),
localUniformBit.localUniformBitGroup2,
roundPixelsBit.roundPixelsBit
]
});
this.shader = new Shader.Shader({
gpuProgram,
resources: {
// added on the fly!
localUniforms
}
});
}
execute(graphicsPipe, renderable) {
const context = renderable.context;
const shader = context.customShader || this.shader;
const renderer = graphicsPipe.renderer;
const contextSystem = renderer.graphicsContext;
const {
batcher,
instructions
} = contextSystem.getContextRenderData(context);
const encoder = renderer.encoder;
encoder.setPipelineFromGeometryProgramAndState(
batcher.geometry,
shader.gpuProgram,
graphicsPipe.state
);
encoder.setGeometry(batcher.geometry, shader.gpuProgram);
const globalUniformsBindGroup = renderer.globalUniforms.bindGroup;
encoder.setBindGroup(0, globalUniformsBindGroup, shader.gpuProgram);
const localBindGroup = renderer.renderPipes.uniformBatch.getUniformBindGroup(shader.resources.localUniforms, true);
encoder.setBindGroup(2, localBindGroup, shader.gpuProgram);
const batches = instructions.instructions;
for (let i = 0; i < instructions.instructionSize; i++) {
const batch = batches[i];
shader.groups[1] = batch.bindGroup;
if (!batch.gpuBindGroup) {
const textureBatch = batch.textures;
batch.bindGroup = getTextureBatchBindGroup.getTextureBatchBindGroup(textureBatch.textures, textureBatch.count);
batch.gpuBindGroup = renderer.bindGroup.getBindGroup(
batch.bindGroup,
shader.gpuProgram,
1
);
}
encoder.setBindGroup(1, batch.bindGroup, shader.gpuProgram);
encoder.renderPassEncoder.drawIndexed(batch.size, 1, batch.start);
}
}
destroy() {
this.shader.destroy(true);
this.shader = null;
}
}
/** @ignore */
GpuGraphicsAdaptor.extension = {
type: [
Extensions.ExtensionType.WebGPUPipesAdaptor
],
name: "graphics"
};
exports.GpuGraphicsAdaptor = GpuGraphicsAdaptor;
//# sourceMappingURL=GpuGraphicsAdaptor.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,89 @@
import { ExtensionType } from '../../../extensions/Extensions.mjs';
import { Matrix } from '../../../maths/matrix/Matrix.mjs';
import { getMaxTexturesPerBatch } from '../../../rendering/batcher/gl/utils/maxRecommendedTextures.mjs';
import { getTextureBatchBindGroup } from '../../../rendering/batcher/gpu/getTextureBatchBindGroup.mjs';
import { compileHighShaderGpuProgram } from '../../../rendering/high-shader/compileHighShaderToProgram.mjs';
import { colorBit } from '../../../rendering/high-shader/shader-bits/colorBit.mjs';
import { generateTextureBatchBit } from '../../../rendering/high-shader/shader-bits/generateTextureBatchBit.mjs';
import { localUniformBitGroup2 } from '../../../rendering/high-shader/shader-bits/localUniformBit.mjs';
import { roundPixelsBit } from '../../../rendering/high-shader/shader-bits/roundPixelsBit.mjs';
import { Shader } from '../../../rendering/renderers/shared/shader/Shader.mjs';
import { UniformGroup } from '../../../rendering/renderers/shared/shader/UniformGroup.mjs';
"use strict";
class GpuGraphicsAdaptor {
init() {
const localUniforms = new UniformGroup({
uTransformMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
uRound: { value: 0, type: "f32" }
});
const gpuProgram = compileHighShaderGpuProgram({
name: "graphics",
bits: [
colorBit,
generateTextureBatchBit(getMaxTexturesPerBatch()),
localUniformBitGroup2,
roundPixelsBit
]
});
this.shader = new Shader({
gpuProgram,
resources: {
// added on the fly!
localUniforms
}
});
}
execute(graphicsPipe, renderable) {
const context = renderable.context;
const shader = context.customShader || this.shader;
const renderer = graphicsPipe.renderer;
const contextSystem = renderer.graphicsContext;
const {
batcher,
instructions
} = contextSystem.getContextRenderData(context);
const encoder = renderer.encoder;
encoder.setPipelineFromGeometryProgramAndState(
batcher.geometry,
shader.gpuProgram,
graphicsPipe.state
);
encoder.setGeometry(batcher.geometry, shader.gpuProgram);
const globalUniformsBindGroup = renderer.globalUniforms.bindGroup;
encoder.setBindGroup(0, globalUniformsBindGroup, shader.gpuProgram);
const localBindGroup = renderer.renderPipes.uniformBatch.getUniformBindGroup(shader.resources.localUniforms, true);
encoder.setBindGroup(2, localBindGroup, shader.gpuProgram);
const batches = instructions.instructions;
for (let i = 0; i < instructions.instructionSize; i++) {
const batch = batches[i];
shader.groups[1] = batch.bindGroup;
if (!batch.gpuBindGroup) {
const textureBatch = batch.textures;
batch.bindGroup = getTextureBatchBindGroup(textureBatch.textures, textureBatch.count);
batch.gpuBindGroup = renderer.bindGroup.getBindGroup(
batch.bindGroup,
shader.gpuProgram,
1
);
}
encoder.setBindGroup(1, batch.bindGroup, shader.gpuProgram);
encoder.renderPassEncoder.drawIndexed(batch.size, 1, batch.start);
}
}
destroy() {
this.shader.destroy(true);
this.shader = null;
}
}
/** @ignore */
GpuGraphicsAdaptor.extension = {
type: [
ExtensionType.WebGPUPipesAdaptor
],
name: "graphics"
};
export { GpuGraphicsAdaptor };
//# sourceMappingURL=GpuGraphicsAdaptor.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
export declare function colorToUniform(rgb: number, alpha: number, out: Float32Array, offset: number): void;
export declare function color32BitToUniform(abgr: number, out: Float32Array, offset: number): void;

View File

@@ -0,0 +1,20 @@
'use strict';
"use strict";
function colorToUniform(rgb, alpha, out, offset) {
out[offset++] = (rgb >> 16 & 255) / 255;
out[offset++] = (rgb >> 8 & 255) / 255;
out[offset++] = (rgb & 255) / 255;
out[offset++] = alpha;
}
function color32BitToUniform(abgr, out, offset) {
const alpha = (abgr >> 24 & 255) / 255;
out[offset++] = (abgr & 255) / 255 * alpha;
out[offset++] = (abgr >> 8 & 255) / 255 * alpha;
out[offset++] = (abgr >> 16 & 255) / 255 * alpha;
out[offset++] = alpha;
}
exports.color32BitToUniform = color32BitToUniform;
exports.colorToUniform = colorToUniform;
//# sourceMappingURL=colorToUniform.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"colorToUniform.js","sources":["../../../../src/scene/graphics/gpu/colorToUniform.ts"],"sourcesContent":["export function colorToUniform(rgb: number, alpha: number, out: Float32Array, offset: number)\n{\n // TODO replace with Color..\n out[offset++] = ((rgb >> 16) & 0xFF) / 255;\n out[offset++] = ((rgb >> 8) & 0xFF) / 255;\n out[offset++] = (rgb & 0xFF) / 255;\n out[offset++] = alpha;\n}\n\nexport function color32BitToUniform(abgr: number, out: Float32Array, offset: number)\n{\n const alpha = ((abgr >> 24) & 0xFF) / 255;\n\n out[offset++] = ((abgr & 0xFF) / 255) * alpha;\n out[offset++] = (((abgr >> 8) & 0xFF) / 255) * alpha;\n out[offset++] = (((abgr >> 16) & 0xFF) / 255) * alpha;\n out[offset++] = alpha;\n}\n"],"names":[],"mappings":";;;AAAO,SAAS,cAAe,CAAA,GAAA,EAAa,KAAe,EAAA,GAAA,EAAmB,MAC9E,EAAA;AAEI,EAAA,GAAA,CAAI,MAAQ,EAAA,CAAA,GAAA,CAAM,GAAO,IAAA,EAAA,GAAM,GAAQ,IAAA,GAAA,CAAA;AACvC,EAAA,GAAA,CAAI,MAAQ,EAAA,CAAA,GAAA,CAAM,GAAO,IAAA,CAAA,GAAK,GAAQ,IAAA,GAAA,CAAA;AACtC,EAAI,GAAA,CAAA,MAAA,EAAQ,CAAK,GAAA,CAAA,GAAA,GAAM,GAAQ,IAAA,GAAA,CAAA;AAC/B,EAAA,GAAA,CAAI,QAAQ,CAAI,GAAA,KAAA,CAAA;AACpB,CAAA;AAEgB,SAAA,mBAAA,CAAoB,IAAc,EAAA,GAAA,EAAmB,MACrE,EAAA;AACI,EAAM,MAAA,KAAA,GAAA,CAAU,IAAQ,IAAA,EAAA,GAAM,GAAQ,IAAA,GAAA,CAAA;AAEtC,EAAA,GAAA,CAAI,MAAQ,EAAA,CAAA,GAAA,CAAM,IAAO,GAAA,GAAA,IAAQ,GAAO,GAAA,KAAA,CAAA;AACxC,EAAA,GAAA,CAAI,MAAQ,EAAA,CAAA,GAAA,CAAO,IAAQ,IAAA,CAAA,GAAK,OAAQ,GAAO,GAAA,KAAA,CAAA;AAC/C,EAAA,GAAA,CAAI,MAAQ,EAAA,CAAA,GAAA,CAAO,IAAQ,IAAA,EAAA,GAAM,OAAQ,GAAO,GAAA,KAAA,CAAA;AAChD,EAAA,GAAA,CAAI,QAAQ,CAAI,GAAA,KAAA,CAAA;AACpB;;;;;"}

View File

@@ -0,0 +1,17 @@
"use strict";
function colorToUniform(rgb, alpha, out, offset) {
out[offset++] = (rgb >> 16 & 255) / 255;
out[offset++] = (rgb >> 8 & 255) / 255;
out[offset++] = (rgb & 255) / 255;
out[offset++] = alpha;
}
function color32BitToUniform(abgr, out, offset) {
const alpha = (abgr >> 24 & 255) / 255;
out[offset++] = (abgr & 255) / 255 * alpha;
out[offset++] = (abgr >> 8 & 255) / 255 * alpha;
out[offset++] = (abgr >> 16 & 255) / 255 * alpha;
out[offset++] = alpha;
}
export { color32BitToUniform, colorToUniform };
//# sourceMappingURL=colorToUniform.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"colorToUniform.mjs","sources":["../../../../src/scene/graphics/gpu/colorToUniform.ts"],"sourcesContent":["export function colorToUniform(rgb: number, alpha: number, out: Float32Array, offset: number)\n{\n // TODO replace with Color..\n out[offset++] = ((rgb >> 16) & 0xFF) / 255;\n out[offset++] = ((rgb >> 8) & 0xFF) / 255;\n out[offset++] = (rgb & 0xFF) / 255;\n out[offset++] = alpha;\n}\n\nexport function color32BitToUniform(abgr: number, out: Float32Array, offset: number)\n{\n const alpha = ((abgr >> 24) & 0xFF) / 255;\n\n out[offset++] = ((abgr & 0xFF) / 255) * alpha;\n out[offset++] = (((abgr >> 8) & 0xFF) / 255) * alpha;\n out[offset++] = (((abgr >> 16) & 0xFF) / 255) * alpha;\n out[offset++] = alpha;\n}\n"],"names":[],"mappings":";AAAO,SAAS,cAAe,CAAA,GAAA,EAAa,KAAe,EAAA,GAAA,EAAmB,MAC9E,EAAA;AAEI,EAAA,GAAA,CAAI,MAAQ,EAAA,CAAA,GAAA,CAAM,GAAO,IAAA,EAAA,GAAM,GAAQ,IAAA,GAAA,CAAA;AACvC,EAAA,GAAA,CAAI,MAAQ,EAAA,CAAA,GAAA,CAAM,GAAO,IAAA,CAAA,GAAK,GAAQ,IAAA,GAAA,CAAA;AACtC,EAAI,GAAA,CAAA,MAAA,EAAQ,CAAK,GAAA,CAAA,GAAA,GAAM,GAAQ,IAAA,GAAA,CAAA;AAC/B,EAAA,GAAA,CAAI,QAAQ,CAAI,GAAA,KAAA,CAAA;AACpB,CAAA;AAEgB,SAAA,mBAAA,CAAoB,IAAc,EAAA,GAAA,EAAmB,MACrE,EAAA;AACI,EAAM,MAAA,KAAA,GAAA,CAAU,IAAQ,IAAA,EAAA,GAAM,GAAQ,IAAA,GAAA,CAAA;AAEtC,EAAA,GAAA,CAAI,MAAQ,EAAA,CAAA,GAAA,CAAM,IAAO,GAAA,GAAA,IAAQ,GAAO,GAAA,KAAA,CAAA;AACxC,EAAA,GAAA,CAAI,MAAQ,EAAA,CAAA,GAAA,CAAO,IAAQ,IAAA,CAAA,GAAK,OAAQ,GAAO,GAAA,KAAA,CAAA;AAC/C,EAAA,GAAA,CAAI,MAAQ,EAAA,CAAA,GAAA,CAAO,IAAQ,IAAA,EAAA,GAAM,OAAQ,GAAO,GAAA,KAAA,CAAA;AAChD,EAAA,GAAA,CAAI,QAAQ,CAAI,GAAA,KAAA,CAAA;AACpB;;;;"}

1
node_modules/pixi.js/lib/scene/graphics/init.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export {};

10
node_modules/pixi.js/lib/scene/graphics/init.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
'use strict';
var Extensions = require('../../extensions/Extensions.js');
var GraphicsContextSystem = require('./shared/GraphicsContextSystem.js');
var GraphicsPipe = require('./shared/GraphicsPipe.js');
"use strict";
Extensions.extensions.add(GraphicsPipe.GraphicsPipe);
Extensions.extensions.add(GraphicsContextSystem.GraphicsContextSystem);
//# sourceMappingURL=init.js.map

1
node_modules/pixi.js/lib/scene/graphics/init.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"init.js","sources":["../../../src/scene/graphics/init.ts"],"sourcesContent":["import { extensions } from '../../extensions/Extensions';\nimport { GraphicsContextSystem } from './shared/GraphicsContextSystem';\nimport { GraphicsPipe } from './shared/GraphicsPipe';\n\nextensions.add(GraphicsPipe);\nextensions.add(GraphicsContextSystem);\n"],"names":["extensions","GraphicsPipe","GraphicsContextSystem"],"mappings":";;;;;;;AAIAA,qBAAA,CAAW,IAAIC,yBAAY,CAAA,CAAA;AAC3BD,qBAAA,CAAW,IAAIE,2CAAqB,CAAA;;"}

8
node_modules/pixi.js/lib/scene/graphics/init.mjs generated vendored Normal file
View File

@@ -0,0 +1,8 @@
import { extensions } from '../../extensions/Extensions.mjs';
import { GraphicsContextSystem } from './shared/GraphicsContextSystem.mjs';
import { GraphicsPipe } from './shared/GraphicsPipe.mjs';
"use strict";
extensions.add(GraphicsPipe);
extensions.add(GraphicsContextSystem);
//# sourceMappingURL=init.mjs.map

1
node_modules/pixi.js/lib/scene/graphics/init.mjs.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"init.mjs","sources":["../../../src/scene/graphics/init.ts"],"sourcesContent":["import { extensions } from '../../extensions/Extensions';\nimport { GraphicsContextSystem } from './shared/GraphicsContextSystem';\nimport { GraphicsPipe } from './shared/GraphicsPipe';\n\nextensions.add(GraphicsPipe);\nextensions.add(GraphicsContextSystem);\n"],"names":[],"mappings":";;;;;AAIA,UAAA,CAAW,IAAI,YAAY,CAAA,CAAA;AAC3B,UAAA,CAAW,IAAI,qBAAqB,CAAA"}

View File

@@ -0,0 +1,41 @@
import { Matrix } from '../../../maths/matrix/Matrix';
import type { Batch, Batcher } from '../../../rendering/batcher/shared/Batcher';
import type { DefaultBatchableMeshElement } from '../../../rendering/batcher/shared/DefaultBatcher';
import type { Texture } from '../../../rendering/renderers/shared/texture/Texture';
import type { Graphics } from './Graphics';
/**
* A batchable graphics object.
* @ignore
*/
export declare class BatchableGraphics implements DefaultBatchableMeshElement {
readonly packAsQuad = false;
batcherName: string;
texture: Texture;
renderable: Graphics;
indexOffset: number;
indexSize: number;
attributeOffset: number;
attributeSize: number;
baseColor: number;
alpha: number;
applyTransform: boolean;
roundPixels: 0 | 1;
_indexStart: number;
_textureId: number;
_attributeStart: number;
_batcher: Batcher;
_batch: Batch;
geometryData: {
vertices: number[];
uvs: number[];
indices: number[];
};
get uvs(): number[];
get positions(): number[];
get indices(): number[];
get blendMode(): import("../../..").BLEND_MODES;
get color(): number;
get transform(): Matrix;
copyTo(gpuBuffer: BatchableGraphics): void;
reset(): void;
}

View File

@@ -0,0 +1,61 @@
'use strict';
var Matrix = require('../../../maths/matrix/Matrix.js');
var multiplyHexColors = require('../../container/utils/multiplyHexColors.js');
"use strict";
const identityMatrix = new Matrix.Matrix();
class BatchableGraphics {
constructor() {
this.packAsQuad = false;
this.batcherName = "default";
this.applyTransform = true;
this.roundPixels = 0;
this._batcher = null;
this._batch = null;
}
get uvs() {
return this.geometryData.uvs;
}
get positions() {
return this.geometryData.vertices;
}
get indices() {
return this.geometryData.indices;
}
get blendMode() {
if (this.applyTransform) {
return this.renderable.groupBlendMode;
}
return "normal";
}
get color() {
const rgb = this.baseColor;
const bgr = rgb >> 16 | rgb & 65280 | (rgb & 255) << 16;
const renderable = this.renderable;
if (renderable) {
return multiplyHexColors.multiplyHexColors(bgr, renderable.groupColor) + (this.alpha * renderable.groupAlpha * 255 << 24);
}
return bgr + (this.alpha * 255 << 24);
}
get transform() {
return this.renderable?.groupTransform || identityMatrix;
}
copyTo(gpuBuffer) {
gpuBuffer.indexOffset = this.indexOffset;
gpuBuffer.indexSize = this.indexSize;
gpuBuffer.attributeOffset = this.attributeOffset;
gpuBuffer.attributeSize = this.attributeSize;
gpuBuffer.baseColor = this.baseColor;
gpuBuffer.alpha = this.alpha;
gpuBuffer.texture = this.texture;
gpuBuffer.geometryData = this.geometryData;
}
reset() {
this.applyTransform = true;
this.renderable = null;
}
}
exports.BatchableGraphics = BatchableGraphics;
//# sourceMappingURL=BatchableGraphics.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BatchableGraphics.js","sources":["../../../../src/scene/graphics/shared/BatchableGraphics.ts"],"sourcesContent":["import { Matrix } from '../../../maths/matrix/Matrix';\nimport { multiplyHexColors } from '../../container/utils/multiplyHexColors';\n\nimport type { Batch, Batcher } from '../../../rendering/batcher/shared/Batcher';\nimport type { DefaultBatchableMeshElement } from '../../../rendering/batcher/shared/DefaultBatcher';\nimport type { Texture } from '../../../rendering/renderers/shared/texture/Texture';\nimport type { Graphics } from './Graphics';\n\nconst identityMatrix = new Matrix();\n/**\n * A batchable graphics object.\n * @ignore\n */\n\nexport class BatchableGraphics implements DefaultBatchableMeshElement\n{\n public readonly packAsQuad = false;\n public batcherName = 'default';\n\n public texture: Texture;\n\n public renderable: Graphics;\n public indexOffset: number;\n public indexSize: number;\n public attributeOffset: number;\n public attributeSize: number;\n public baseColor: number;\n public alpha: number;\n public applyTransform = true;\n public roundPixels: 0 | 1 = 0;\n\n public _indexStart: number;\n public _textureId: number;\n public _attributeStart: number;\n public _batcher: Batcher = null;\n public _batch: Batch = null;\n\n public geometryData: { vertices: number[]; uvs: number[]; indices: number[]; };\n\n get uvs()\n {\n return this.geometryData.uvs;\n }\n\n get positions()\n {\n return this.geometryData.vertices;\n }\n\n get indices()\n {\n return this.geometryData.indices;\n }\n\n get blendMode()\n {\n if (this.applyTransform)\n {\n return this.renderable.groupBlendMode;\n }\n\n return 'normal';\n }\n get color()\n {\n const rgb = this.baseColor;\n const bgr = (rgb >> 16) | (rgb & 0xff00) | ((rgb & 0xff) << 16);\n const renderable = this.renderable;\n\n if (renderable)\n {\n return multiplyHexColors(bgr, renderable.groupColor)\n + ((this.alpha * renderable.groupAlpha * 255) << 24);\n }\n\n return bgr + ((this.alpha * 255) << 24);\n }\n\n get transform()\n {\n return this.renderable?.groupTransform || identityMatrix;\n }\n\n public copyTo(gpuBuffer: BatchableGraphics)\n {\n gpuBuffer.indexOffset = this.indexOffset;\n gpuBuffer.indexSize = this.indexSize;\n\n gpuBuffer.attributeOffset = this.attributeOffset;\n gpuBuffer.attributeSize = this.attributeSize;\n\n gpuBuffer.baseColor = this.baseColor;\n gpuBuffer.alpha = this.alpha;\n\n gpuBuffer.texture = this.texture;\n gpuBuffer.geometryData = this.geometryData;\n }\n\n public reset()\n {\n this.applyTransform = true;\n this.renderable = null;\n }\n}\n"],"names":["Matrix","multiplyHexColors"],"mappings":";;;;;;AAQA,MAAM,cAAA,GAAiB,IAAIA,aAAO,EAAA,CAAA;AAM3B,MAAM,iBACb,CAAA;AAAA,EADO,WAAA,GAAA;AAEH,IAAA,IAAA,CAAgB,UAAa,GAAA,KAAA,CAAA;AAC7B,IAAA,IAAA,CAAO,WAAc,GAAA,SAAA,CAAA;AAWrB,IAAA,IAAA,CAAO,cAAiB,GAAA,IAAA,CAAA;AACxB,IAAA,IAAA,CAAO,WAAqB,GAAA,CAAA,CAAA;AAK5B,IAAA,IAAA,CAAO,QAAoB,GAAA,IAAA,CAAA;AAC3B,IAAA,IAAA,CAAO,MAAgB,GAAA,IAAA,CAAA;AAAA,GAAA;AAAA,EAIvB,IAAI,GACJ,GAAA;AACI,IAAA,OAAO,KAAK,YAAa,CAAA,GAAA,CAAA;AAAA,GAC7B;AAAA,EAEA,IAAI,SACJ,GAAA;AACI,IAAA,OAAO,KAAK,YAAa,CAAA,QAAA,CAAA;AAAA,GAC7B;AAAA,EAEA,IAAI,OACJ,GAAA;AACI,IAAA,OAAO,KAAK,YAAa,CAAA,OAAA,CAAA;AAAA,GAC7B;AAAA,EAEA,IAAI,SACJ,GAAA;AACI,IAAA,IAAI,KAAK,cACT,EAAA;AACI,MAAA,OAAO,KAAK,UAAW,CAAA,cAAA,CAAA;AAAA,KAC3B;AAEA,IAAO,OAAA,QAAA,CAAA;AAAA,GACX;AAAA,EACA,IAAI,KACJ,GAAA;AACI,IAAA,MAAM,MAAM,IAAK,CAAA,SAAA,CAAA;AACjB,IAAA,MAAM,MAAO,GAAO,IAAA,EAAA,GAAO,GAAM,GAAA,KAAA,GAAA,CAAY,MAAM,GAAS,KAAA,EAAA,CAAA;AAC5D,IAAA,MAAM,aAAa,IAAK,CAAA,UAAA,CAAA;AAExB,IAAA,IAAI,UACJ,EAAA;AACI,MAAO,OAAAC,mCAAA,CAAkB,KAAK,UAAW,CAAA,UAAU,KAC/C,IAAK,CAAA,KAAA,GAAQ,UAAW,CAAA,UAAA,GAAa,GAAQ,IAAA,EAAA,CAAA,CAAA;AAAA,KACrD;AAEA,IAAO,OAAA,GAAA,IAAQ,IAAK,CAAA,KAAA,GAAQ,GAAQ,IAAA,EAAA,CAAA,CAAA;AAAA,GACxC;AAAA,EAEA,IAAI,SACJ,GAAA;AACI,IAAO,OAAA,IAAA,CAAK,YAAY,cAAkB,IAAA,cAAA,CAAA;AAAA,GAC9C;AAAA,EAEO,OAAO,SACd,EAAA;AACI,IAAA,SAAA,CAAU,cAAc,IAAK,CAAA,WAAA,CAAA;AAC7B,IAAA,SAAA,CAAU,YAAY,IAAK,CAAA,SAAA,CAAA;AAE3B,IAAA,SAAA,CAAU,kBAAkB,IAAK,CAAA,eAAA,CAAA;AACjC,IAAA,SAAA,CAAU,gBAAgB,IAAK,CAAA,aAAA,CAAA;AAE/B,IAAA,SAAA,CAAU,YAAY,IAAK,CAAA,SAAA,CAAA;AAC3B,IAAA,SAAA,CAAU,QAAQ,IAAK,CAAA,KAAA,CAAA;AAEvB,IAAA,SAAA,CAAU,UAAU,IAAK,CAAA,OAAA,CAAA;AACzB,IAAA,SAAA,CAAU,eAAe,IAAK,CAAA,YAAA,CAAA;AAAA,GAClC;AAAA,EAEO,KACP,GAAA;AACI,IAAA,IAAA,CAAK,cAAiB,GAAA,IAAA,CAAA;AACtB,IAAA,IAAA,CAAK,UAAa,GAAA,IAAA,CAAA;AAAA,GACtB;AACJ;;;;"}

View File

@@ -0,0 +1,59 @@
import { Matrix } from '../../../maths/matrix/Matrix.mjs';
import { multiplyHexColors } from '../../container/utils/multiplyHexColors.mjs';
"use strict";
const identityMatrix = new Matrix();
class BatchableGraphics {
constructor() {
this.packAsQuad = false;
this.batcherName = "default";
this.applyTransform = true;
this.roundPixels = 0;
this._batcher = null;
this._batch = null;
}
get uvs() {
return this.geometryData.uvs;
}
get positions() {
return this.geometryData.vertices;
}
get indices() {
return this.geometryData.indices;
}
get blendMode() {
if (this.applyTransform) {
return this.renderable.groupBlendMode;
}
return "normal";
}
get color() {
const rgb = this.baseColor;
const bgr = rgb >> 16 | rgb & 65280 | (rgb & 255) << 16;
const renderable = this.renderable;
if (renderable) {
return multiplyHexColors(bgr, renderable.groupColor) + (this.alpha * renderable.groupAlpha * 255 << 24);
}
return bgr + (this.alpha * 255 << 24);
}
get transform() {
return this.renderable?.groupTransform || identityMatrix;
}
copyTo(gpuBuffer) {
gpuBuffer.indexOffset = this.indexOffset;
gpuBuffer.indexSize = this.indexSize;
gpuBuffer.attributeOffset = this.attributeOffset;
gpuBuffer.attributeSize = this.attributeSize;
gpuBuffer.baseColor = this.baseColor;
gpuBuffer.alpha = this.alpha;
gpuBuffer.texture = this.texture;
gpuBuffer.geometryData = this.geometryData;
}
reset() {
this.applyTransform = true;
this.renderable = null;
}
}
export { BatchableGraphics };
//# sourceMappingURL=BatchableGraphics.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BatchableGraphics.mjs","sources":["../../../../src/scene/graphics/shared/BatchableGraphics.ts"],"sourcesContent":["import { Matrix } from '../../../maths/matrix/Matrix';\nimport { multiplyHexColors } from '../../container/utils/multiplyHexColors';\n\nimport type { Batch, Batcher } from '../../../rendering/batcher/shared/Batcher';\nimport type { DefaultBatchableMeshElement } from '../../../rendering/batcher/shared/DefaultBatcher';\nimport type { Texture } from '../../../rendering/renderers/shared/texture/Texture';\nimport type { Graphics } from './Graphics';\n\nconst identityMatrix = new Matrix();\n/**\n * A batchable graphics object.\n * @ignore\n */\n\nexport class BatchableGraphics implements DefaultBatchableMeshElement\n{\n public readonly packAsQuad = false;\n public batcherName = 'default';\n\n public texture: Texture;\n\n public renderable: Graphics;\n public indexOffset: number;\n public indexSize: number;\n public attributeOffset: number;\n public attributeSize: number;\n public baseColor: number;\n public alpha: number;\n public applyTransform = true;\n public roundPixels: 0 | 1 = 0;\n\n public _indexStart: number;\n public _textureId: number;\n public _attributeStart: number;\n public _batcher: Batcher = null;\n public _batch: Batch = null;\n\n public geometryData: { vertices: number[]; uvs: number[]; indices: number[]; };\n\n get uvs()\n {\n return this.geometryData.uvs;\n }\n\n get positions()\n {\n return this.geometryData.vertices;\n }\n\n get indices()\n {\n return this.geometryData.indices;\n }\n\n get blendMode()\n {\n if (this.applyTransform)\n {\n return this.renderable.groupBlendMode;\n }\n\n return 'normal';\n }\n get color()\n {\n const rgb = this.baseColor;\n const bgr = (rgb >> 16) | (rgb & 0xff00) | ((rgb & 0xff) << 16);\n const renderable = this.renderable;\n\n if (renderable)\n {\n return multiplyHexColors(bgr, renderable.groupColor)\n + ((this.alpha * renderable.groupAlpha * 255) << 24);\n }\n\n return bgr + ((this.alpha * 255) << 24);\n }\n\n get transform()\n {\n return this.renderable?.groupTransform || identityMatrix;\n }\n\n public copyTo(gpuBuffer: BatchableGraphics)\n {\n gpuBuffer.indexOffset = this.indexOffset;\n gpuBuffer.indexSize = this.indexSize;\n\n gpuBuffer.attributeOffset = this.attributeOffset;\n gpuBuffer.attributeSize = this.attributeSize;\n\n gpuBuffer.baseColor = this.baseColor;\n gpuBuffer.alpha = this.alpha;\n\n gpuBuffer.texture = this.texture;\n gpuBuffer.geometryData = this.geometryData;\n }\n\n public reset()\n {\n this.applyTransform = true;\n this.renderable = null;\n }\n}\n"],"names":[],"mappings":";;;;AAQA,MAAM,cAAA,GAAiB,IAAI,MAAO,EAAA,CAAA;AAM3B,MAAM,iBACb,CAAA;AAAA,EADO,WAAA,GAAA;AAEH,IAAA,IAAA,CAAgB,UAAa,GAAA,KAAA,CAAA;AAC7B,IAAA,IAAA,CAAO,WAAc,GAAA,SAAA,CAAA;AAWrB,IAAA,IAAA,CAAO,cAAiB,GAAA,IAAA,CAAA;AACxB,IAAA,IAAA,CAAO,WAAqB,GAAA,CAAA,CAAA;AAK5B,IAAA,IAAA,CAAO,QAAoB,GAAA,IAAA,CAAA;AAC3B,IAAA,IAAA,CAAO,MAAgB,GAAA,IAAA,CAAA;AAAA,GAAA;AAAA,EAIvB,IAAI,GACJ,GAAA;AACI,IAAA,OAAO,KAAK,YAAa,CAAA,GAAA,CAAA;AAAA,GAC7B;AAAA,EAEA,IAAI,SACJ,GAAA;AACI,IAAA,OAAO,KAAK,YAAa,CAAA,QAAA,CAAA;AAAA,GAC7B;AAAA,EAEA,IAAI,OACJ,GAAA;AACI,IAAA,OAAO,KAAK,YAAa,CAAA,OAAA,CAAA;AAAA,GAC7B;AAAA,EAEA,IAAI,SACJ,GAAA;AACI,IAAA,IAAI,KAAK,cACT,EAAA;AACI,MAAA,OAAO,KAAK,UAAW,CAAA,cAAA,CAAA;AAAA,KAC3B;AAEA,IAAO,OAAA,QAAA,CAAA;AAAA,GACX;AAAA,EACA,IAAI,KACJ,GAAA;AACI,IAAA,MAAM,MAAM,IAAK,CAAA,SAAA,CAAA;AACjB,IAAA,MAAM,MAAO,GAAO,IAAA,EAAA,GAAO,GAAM,GAAA,KAAA,GAAA,CAAY,MAAM,GAAS,KAAA,EAAA,CAAA;AAC5D,IAAA,MAAM,aAAa,IAAK,CAAA,UAAA,CAAA;AAExB,IAAA,IAAI,UACJ,EAAA;AACI,MAAO,OAAA,iBAAA,CAAkB,KAAK,UAAW,CAAA,UAAU,KAC/C,IAAK,CAAA,KAAA,GAAQ,UAAW,CAAA,UAAA,GAAa,GAAQ,IAAA,EAAA,CAAA,CAAA;AAAA,KACrD;AAEA,IAAO,OAAA,GAAA,IAAQ,IAAK,CAAA,KAAA,GAAQ,GAAQ,IAAA,EAAA,CAAA,CAAA;AAAA,GACxC;AAAA,EAEA,IAAI,SACJ,GAAA;AACI,IAAO,OAAA,IAAA,CAAK,YAAY,cAAkB,IAAA,cAAA,CAAA;AAAA,GAC9C;AAAA,EAEO,OAAO,SACd,EAAA;AACI,IAAA,SAAA,CAAU,cAAc,IAAK,CAAA,WAAA,CAAA;AAC7B,IAAA,SAAA,CAAU,YAAY,IAAK,CAAA,SAAA,CAAA;AAE3B,IAAA,SAAA,CAAU,kBAAkB,IAAK,CAAA,eAAA,CAAA;AACjC,IAAA,SAAA,CAAU,gBAAgB,IAAK,CAAA,aAAA,CAAA;AAE/B,IAAA,SAAA,CAAU,YAAY,IAAK,CAAA,SAAA,CAAA;AAC3B,IAAA,SAAA,CAAU,QAAQ,IAAK,CAAA,KAAA,CAAA;AAEvB,IAAA,SAAA,CAAU,UAAU,IAAK,CAAA,OAAA,CAAA;AACzB,IAAA,SAAA,CAAU,eAAe,IAAK,CAAA,YAAA,CAAA;AAAA,GAClC;AAAA,EAEO,KACP,GAAA;AACI,IAAA,IAAA,CAAK,cAAiB,GAAA,IAAA,CAAA;AACtB,IAAA,IAAA,CAAK,UAAa,GAAA,IAAA,CAAA;AAAA,GACtB;AACJ;;;;"}

View File

@@ -0,0 +1,100 @@
import type { ColorSource } from '../../../color/Color';
import type { Matrix } from '../../../maths/matrix/Matrix';
import type { Texture } from '../../../rendering/renderers/shared/texture/Texture';
import type { LineCap, LineJoin } from './const';
import type { FillGradient } from './fill/FillGradient';
import type { FillPattern } from './fill/FillPattern';
/**
* A fill style object.
* @memberof scene
*/
export interface FillStyle {
/** The color to use for the fill. */
color?: ColorSource;
/** The alpha value to use for the fill. */
alpha?: number;
/** The texture to use for the fill. */
texture?: Texture | null;
/** The matrix to apply. */
matrix?: Matrix | null;
/** The fill pattern to use. */
fill?: FillPattern | FillGradient | null;
}
/**
* A stroke attribute object, used to define properties for a stroke.
* @memberof scene
*/
export interface StrokeAttributes {
/** The width of the stroke. */
width?: number;
/** The alignment of the stroke. */
alignment?: number;
/** The line cap style to use. */
cap?: LineCap;
/** The line join style to use. */
join?: LineJoin;
/** The miter limit to use. */
miterLimit?: number;
}
/**
* A stroke style object.
* @memberof scene
*/
export interface StrokeStyle extends FillStyle, StrokeAttributes {
}
/**
* These can be directly used as a fill or a stroke
* ```ts
* graphics.fill(0xff0000);
* graphics.fill(new FillPattern(texture));
* graphics.fill(new FillGradient(0, 0, 200, 0));
* graphics.fill({
* color: 0xff0000,
* alpha: 0.5,
* texture?: null,
* matrix?: null,
* });
* graphics.fill({
* fill: new FillPattern(texture),
* });
* graphics.fill({
* fill: new FillGradient(0, 0, 200, 0),
* });
* ```
* @memberof scene
*/
export type FillInput = ColorSource | FillGradient | FillPattern | FillStyle;
/**
* These can be directly used as a stroke
* ```ts
* graphics.stroke(0xff0000);
* graphics.stroke(new FillPattern(texture));
* graphics.stroke(new FillGradient(0, 0, 200, 0));
* graphics.stroke({
* color: 0xff0000,
* width?: 1,
* alignment?: 0.5,
* });
* graphics.stroke({
* fill: new FillPattern(texture),
* width: 1,
* alignment: 0.5,
* });
* graphics.stroke({
* fill: new FillGradient(0, 0, 200, 0),
* width: 1,
* alignment: 0.5,
* });
* ```
* @memberof scene
*/
export type StrokeInput = ColorSource | FillGradient | FillPattern | StrokeStyle;
export type ConvertedFillStyle = Omit<Required<FillStyle>, 'color'> & {
color: number;
};
export type ConvertedStrokeStyle = ConvertedFillStyle & Required<StrokeAttributes>;
/**
* @deprecated since v8.1.6
* @see scene.FillInput
*/
export type FillStyleInputs = ColorSource | FillGradient | FillPattern | FillStyle | ConvertedFillStyle | StrokeStyle | ConvertedStrokeStyle;

View File

@@ -0,0 +1,4 @@
'use strict';
"use strict";
//# sourceMappingURL=FillTypes.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"FillTypes.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}

View File

@@ -0,0 +1,2 @@
"use strict";
//# sourceMappingURL=FillTypes.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"FillTypes.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}

View File

@@ -0,0 +1,506 @@
import { ViewContainer } from '../../view/View';
import { GraphicsContext } from './GraphicsContext';
import type { ColorSource } from '../../../color/Color';
import type { Matrix } from '../../../maths/matrix/Matrix';
import type { PointData } from '../../../maths/point/PointData';
import type { Instruction } from '../../../rendering/renderers/shared/instructions/Instruction';
import type { Texture } from '../../../rendering/renderers/shared/texture/Texture';
import type { Bounds } from '../../container/bounds/Bounds';
import type { ContainerOptions } from '../../container/Container';
import type { DestroyOptions } from '../../container/destroyTypes';
import type { FillInput, StrokeStyle } from './FillTypes';
import type { GraphicsPath } from './path/GraphicsPath';
import type { RoundedPoint } from './path/roundShape';
/**
* Constructor options used for `Graphics` instances.
* ```js
* const graphics = new Graphics({
* fillStyle: { color: 0xff0000, alpha: 0.5 },
* strokeStyle: { color: 0x00ff00, width: 2 },
* });
* ```
* @see {@link scene.Graphics}
* @memberof scene
*/
export interface GraphicsOptions extends ContainerOptions {
/** The GraphicsContext to use, useful for reuse and optimisation */
context?: GraphicsContext;
/** Whether or not to round the x/y position. */
roundPixels?: boolean;
}
/**
* The Graphics class is primarily used to render primitive shapes such as lines, circles and
* rectangles to the display, and to color and fill them. However, you can also use a Graphics
* object to build a list of primitives to use as a mask, or as a complex hitArea.
* @memberof scene
* @extends scene.Container
*/
export declare class Graphics extends ViewContainer implements Instruction {
readonly renderPipeId: string;
batched: boolean;
_didGraphicsUpdate: boolean;
private _context;
private readonly _ownedContext;
/**
* @param options - Options for the Graphics.
*/
constructor(options?: GraphicsOptions | GraphicsContext);
set context(context: GraphicsContext);
get context(): GraphicsContext;
/**
* The local bounds of the graphic.
* @type {rendering.Bounds}
*/
get bounds(): Bounds;
/**
* Adds the bounds of this object to the bounds object.
* @param bounds - The output bounds object.
*/
addBounds(bounds: Bounds): void;
/**
* Checks if the object contains the given point.
* @param point - The point to check
*/
containsPoint(point: PointData): boolean;
protected onViewUpdate(): void;
/**
* Destroys this graphics renderable and optionally its context.
* @param options - Options parameter. A boolean will act as if all options
*
* If the context was created by this graphics and `destroy(false)` or `destroy()` is called
* then the context will still be destroyed.
*
* If you want to explicitly not destroy this context that this graphics created,
* then you should pass destroy({ context: false })
*
* If the context was passed in as an argument to the constructor then it will not be destroyed
* @param {boolean} [options.texture=false] - Should destroy the texture of the graphics context
* @param {boolean} [options.textureSource=false] - Should destroy the texture source of the graphics context
* @param {boolean} [options.context=false] - Should destroy the context
*/
destroy(options?: DestroyOptions): void;
private _callContextMethod;
/**
* Sets the current fill style of the graphics context. The fill style can be a color, gradient,
* pattern, or a more complex style defined by a FillStyle object.
* @param {FillInput} args - The fill style to apply. This can be a simple color, a gradient or
* pattern object, or a FillStyle or ConvertedFillStyle object.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setFillStyle(...args: Parameters<GraphicsContext['setFillStyle']>): this;
/**
* Sets the current stroke style of the graphics context. Similar to fill styles, stroke styles can
* encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object.
* @param {StrokeInput} args - The stroke style to apply. Can be defined as a color, a gradient or pattern,
* or a StrokeStyle or ConvertedStrokeStyle object.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setStrokeStyle(...args: Parameters<GraphicsContext['setStrokeStyle']>): this;
/**
* Fills the current or given path with the current fill style. This method can optionally take
* a color and alpha for a simple fill, or a more complex FillStyle object for advanced fills.
* @param {FillInput} style - (Optional) The style to fill the path with. Can be a color, gradient, pattern, or a
* complex style object. If omitted, uses the current fill style.
* @returns The instance of the current GraphicsContext for method chaining.
*/
fill(style?: FillInput): this;
/** @deprecated 8.0.0 */
fill(color: ColorSource, alpha?: number): this;
/**
* Strokes the current path with the current stroke style. This method can take an optional
* FillStyle parameter to define the stroke's appearance, including its color, width, and other properties.
* @param {FillStyle} args - (Optional) The stroke style to apply. Can be defined as a simple color or a more
* complex style object. If omitted, uses the current stroke style.
* @returns The instance of the current GraphicsContext for method chaining.
*/
stroke(...args: Parameters<GraphicsContext['stroke']>): this;
/**
* Adds a texture to the graphics context. This method supports multiple overloads for specifying the texture,
* tint, and dimensions. If only a texture is provided, it uses the texture's width and height for drawing.
* Additional parameters allow for specifying a tint color, and custom dimensions for the texture drawing area.
* @param texture - The Texture object to use.
* @param tint - (Optional) A ColorSource to tint the texture. If not provided, defaults to white (0xFFFFFF).
* @param dx - (Optional) The x-coordinate in the destination canvas at which to place the top-left corner of
* the source image.
* @param dy - (Optional) The y-coordinate in the destination canvas at which to place the top-left corner of
* the source image.
* @param dw - (Optional) The width of the rectangle within the source image to draw onto the destination canvas.
* If not provided, uses the texture's frame width.
* @param dh - (Optional) The height of the rectangle within the source image to draw onto the destination canvas.
* If not provided, uses the texture's frame height.
* @returns The instance of the current GraphicsContext for method chaining.
*/
texture(texture: Texture, tint?: ColorSource, dx?: number, dy?: number, dw?: number, dh?: number): this;
texture(texture: Texture): this;
/**
* Resets the current path. Any previous path and its commands are discarded and a new path is
* started. This is typically called before beginning a new shape or series of drawing commands.
* @returns The instance of the current GraphicsContext for method chaining.
*/
beginPath(): this;
/**
* Applies a cutout to the last drawn shape. This is used to create holes or complex shapes by
* subtracting a path from the previously drawn path. If a hole is not completely in a shape, it will
* fail to cut correctly!
*/
cut(): this;
/**
* Adds an arc to the current path, which is centered at (x, y) with the specified radius,
* starting and ending angles, and direction.
* @param x - The x-coordinate of the arc's center.
* @param y - The y-coordinate of the arc's center.
* @param radius - The arc's radius.
* @param startAngle - The starting angle, in radians.
* @param endAngle - The ending angle, in radians.
* @param counterclockwise - (Optional) Specifies whether the arc is drawn counterclockwise (true) or clockwise
* (false). Defaults to false.
* @returns The instance of the current GraphicsContext for method chaining.
*/
arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): this;
/**
* Adds an arc to the current path with the given control points and radius, connected to the previous point
* by a straight line if necessary.
* @param x1 - The x-coordinate of the first control point.
* @param y1 - The y-coordinate of the first control point.
* @param x2 - The x-coordinate of the second control point.
* @param y2 - The y-coordinate of the second control point.
* @param radius - The arc's radius.
* @returns The instance of the current GraphicsContext for method chaining.
*/
arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): this;
/**
* Adds an SVG-style arc to the path, allowing for elliptical arcs based on the SVG spec.
* @param rx - The x-radius of the ellipse.
* @param ry - The y-radius of the ellipse.
* @param xAxisRotation - The rotation of the ellipse's x-axis relative
* to the x-axis of the coordinate system, in degrees.
* @param largeArcFlag - Determines if the arc should be greater than or less than 180 degrees.
* @param sweepFlag - Determines if the arc should be swept in a positive angle direction.
* @param x - The x-coordinate of the arc's end point.
* @param y - The y-coordinate of the arc's end point.
* @returns The instance of the current object for chaining.
*/
arcToSvg(rx: number, ry: number, xAxisRotation: number, largeArcFlag: number, sweepFlag: number, x: number, y: number): this;
/**
* Adds a cubic Bezier curve to the path.
* It requires three points: the first two are control points and the third one is the end point.
* The starting point is the last point in the current path.
* @param cp1x - The x-coordinate of the first control point.
* @param cp1y - The y-coordinate of the first control point.
* @param cp2x - The x-coordinate of the second control point.
* @param cp2y - The y-coordinate of the second control point.
* @param x - The x-coordinate of the end point.
* @param y - The y-coordinate of the end point.
* @param smoothness - Optional parameter to adjust the smoothness of the curve.
* @returns The instance of the current object for chaining.
*/
bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number, smoothness?: number): this;
/**
* Closes the current path by drawing a straight line back to the start.
* If the shape is already closed or there are no points in the path, this method does nothing.
* @returns The instance of the current object for chaining.
*/
closePath(): this;
/**
* Draws an ellipse at the specified location and with the given x and y radii.
* An optional transformation can be applied, allowing for rotation, scaling, and translation.
* @param x - The x-coordinate of the center of the ellipse.
* @param y - The y-coordinate of the center of the ellipse.
* @param radiusX - The horizontal radius of the ellipse.
* @param radiusY - The vertical radius of the ellipse.
* @returns The instance of the current object for chaining.
*/
ellipse(x: number, y: number, radiusX: number, radiusY: number): this;
/**
* Draws a circle shape. This method adds a new circle path to the current drawing.
* @param x - The x-coordinate of the center of the circle.
* @param y - The y-coordinate of the center of the circle.
* @param radius - The radius of the circle.
* @returns The instance of the current object for chaining.
*/
circle(x: number, y: number, radius: number): this;
/**
* Adds another `GraphicsPath` to this path, optionally applying a transformation.
* @param path - The `GraphicsPath` to add.
* @returns The instance of the current object for chaining.
*/
path(path: GraphicsPath): this;
/**
* Connects the current point to a new point with a straight line. This method updates the current path.
* @param x - The x-coordinate of the new point to connect to.
* @param y - The y-coordinate of the new point to connect to.
* @returns The instance of the current object for chaining.
*/
lineTo(x: number, y: number): this;
/**
* Sets the starting point for a new sub-path. Any subsequent drawing commands are considered part of this path.
* @param x - The x-coordinate for the starting point.
* @param y - The y-coordinate for the starting point.
* @returns The instance of the current object for chaining.
*/
moveTo(x: number, y: number): this;
/**
* Adds a quadratic curve to the path. It requires two points: the control point and the end point.
* The starting point is the last point in the current path.
* @param cpx - The x-coordinate of the control point.
* @param cpy - The y-coordinate of the control point.
* @param x - The x-coordinate of the end point.
* @param y - The y-coordinate of the end point.
* @param smoothness - Optional parameter to adjust the smoothness of the curve.
* @returns The instance of the current object for chaining.
*/
quadraticCurveTo(cpx: number, cpy: number, x: number, y: number, smoothness?: number): this;
/**
* Draws a rectangle shape. This method adds a new rectangle path to the current drawing.
* @param x - The x-coordinate of the top-left corner of the rectangle.
* @param y - The y-coordinate of the top-left corner of the rectangle.
* @param w - The width of the rectangle.
* @param h - The height of the rectangle.
* @returns The instance of the current object for chaining.
*/
rect(x: number, y: number, w: number, h: number): this;
/**
* Draws a rectangle with rounded corners.
* The corner radius can be specified to determine how rounded the corners should be.
* An optional transformation can be applied, which allows for rotation, scaling, and translation of the rectangle.
* @param x - The x-coordinate of the top-left corner of the rectangle.
* @param y - The y-coordinate of the top-left corner of the rectangle.
* @param w - The width of the rectangle.
* @param h - The height of the rectangle.
* @param radius - The radius of the rectangle's corners. If not specified, corners will be sharp.
* @returns The instance of the current object for chaining.
*/
roundRect(x: number, y: number, w: number, h: number, radius?: number): this;
/**
* Draws a polygon shape by specifying a sequence of points. This method allows for the creation of complex polygons,
* which can be both open and closed. An optional transformation can be applied, enabling the polygon to be scaled,
* rotated, or translated as needed.
* @param points - An array of numbers, or an array of PointData objects eg [{x,y}, {x,y}, {x,y}]
* representing the x and y coordinates, of the polygon's vertices, in sequence.
* @param close - A boolean indicating whether to close the polygon path. True by default.
* @returns The instance of the current object for chaining further drawing commands.
*/
poly(points: number[] | PointData[], close?: boolean): this;
/**
* Draws a regular polygon with a specified number of sides. All sides and angles are equal.
* @param x - The x-coordinate of the center of the polygon.
* @param y - The y-coordinate of the center of the polygon.
* @param radius - The radius of the circumscribed circle of the polygon.
* @param sides - The number of sides of the polygon. Must be 3 or more.
* @param rotation - The rotation angle of the polygon, in radians. Zero by default.
* @param transform - An optional `Matrix` object to apply a transformation to the polygon.
* @returns The instance of the current object for chaining.
*/
regularPoly(x: number, y: number, radius: number, sides: number, rotation?: number, transform?: Matrix): this;
/**
* Draws a polygon with rounded corners.
* Similar to `regularPoly` but with the ability to round the corners of the polygon.
* @param x - The x-coordinate of the center of the polygon.
* @param y - The y-coordinate of the center of the polygon.
* @param radius - The radius of the circumscribed circle of the polygon.
* @param sides - The number of sides of the polygon. Must be 3 or more.
* @param corner - The radius of the rounding of the corners.
* @param rotation - The rotation angle of the polygon, in radians. Zero by default.
* @returns The instance of the current object for chaining.
*/
roundPoly(x: number, y: number, radius: number, sides: number, corner: number, rotation?: number): this;
/**
* Draws a shape with rounded corners. This function supports custom radius for each corner of the shape.
* Optionally, corners can be rounded using a quadratic curve instead of an arc, providing a different aesthetic.
* @param points - An array of `RoundedPoint` representing the corners of the shape to draw.
* A minimum of 3 points is required.
* @param radius - The default radius for the corners.
* This radius is applied to all corners unless overridden in `points`.
* @param useQuadratic - If set to true, rounded corners are drawn using a quadraticCurve
* method instead of an arc method. Defaults to false.
* @param smoothness - Specifies the smoothness of the curve when `useQuadratic` is true.
* Higher values make the curve smoother.
* @returns The instance of the current object for chaining.
*/
roundShape(points: RoundedPoint[], radius: number, useQuadratic?: boolean, smoothness?: number): this;
/**
* Draw Rectangle with fillet corners. This is much like rounded rectangle
* however it support negative numbers as well for the corner radius.
* @param x - Upper left corner of rect
* @param y - Upper right corner of rect
* @param width - Width of rect
* @param height - Height of rect
* @param fillet - accept negative or positive values
*/
filletRect(x: number, y: number, width: number, height: number, fillet: number): this;
/**
* Draw Rectangle with chamfer corners. These are angled corners.
* @param x - Upper left corner of rect
* @param y - Upper right corner of rect
* @param width - Width of rect
* @param height - Height of rect
* @param chamfer - non-zero real number, size of corner cutout
* @param transform
*/
chamferRect(x: number, y: number, width: number, height: number, chamfer: number, transform?: Matrix): this;
/**
* Draws a star shape centered at a specified location. This method allows for the creation
* of stars with a variable number of points, outer radius, optional inner radius, and rotation.
* The star is drawn as a closed polygon with alternating outer and inner vertices to create the star's points.
* An optional transformation can be applied to scale, rotate, or translate the star as needed.
* @param x - The x-coordinate of the center of the star.
* @param y - The y-coordinate of the center of the star.
* @param points - The number of points of the star.
* @param radius - The outer radius of the star (distance from the center to the outer points).
* @param innerRadius - Optional. The inner radius of the star
* (distance from the center to the inner points between the outer points).
* If not provided, defaults to half of the `radius`.
* @param rotation - Optional. The rotation of the star in radians, where 0 is aligned with the y-axis.
* Defaults to 0, meaning one point is directly upward.
* @returns The instance of the current object for chaining further drawing commands.
*/
star(x: number, y: number, points: number, radius: number, innerRadius?: number, rotation?: number): this;
/**
* Parses and renders an SVG string into the graphics context. This allows for complex shapes and paths
* defined in SVG format to be drawn within the graphics context.
* @param svg - The SVG string to be parsed and rendered.
*/
svg(svg: string): this;
/**
* Restores the most recently saved graphics state by popping the top of the graphics state stack.
* This includes transformations, fill styles, and stroke styles.
*/
restore(): this;
/** Saves the current graphics state, including transformations, fill styles, and stroke styles, onto a stack. */
save(): this;
/**
* Returns the current transformation matrix of the graphics context.
* @returns The current transformation matrix.
*/
getTransform(): Matrix;
/**
* Resets the current transformation matrix to the identity matrix, effectively removing
* any transformations (rotation, scaling, translation) previously applied.
* @returns The instance of the current GraphicsContext for method chaining.
*/
resetTransform(): this;
/**
* Applies a rotation transformation to the graphics context around the current origin.
* @param angle - The angle of rotation in radians.
* @returns The instance of the current GraphicsContext for method chaining.
*/
rotateTransform(angle: number): this;
/**
* Applies a scaling transformation to the graphics context, scaling drawings by x horizontally and by y vertically.
* @param x - The scale factor in the horizontal direction.
* @param y - (Optional) The scale factor in the vertical direction.
* If not specified, the x value is used for both directions.
* @returns The instance of the current GraphicsContext for method chaining.
*/
scaleTransform(x: number, y?: number): this;
/**
* Sets the current transformation matrix of the graphics context to the specified matrix or values.
* This replaces the current transformation matrix.
* @param a - The value for the a property of the matrix, or a Matrix object to use directly.
* @param b - The value for the b property of the matrix.
* @param c - The value for the c property of the matrix.
* @param d - The value for the d property of the matrix.
* @param dx - The value for the tx (translate x) property of the matrix.
* @param dy - The value for the ty (translate y) property of the matrix.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setTransform(transform: Matrix): this;
setTransform(a: number, b: number, c: number, d: number, dx: number, dy: number): this;
setTransform(a: number | Matrix, b?: number, c?: number, d?: number, dx?: number, dy?: number): this;
/**
* Applies the specified transformation matrix to the current graphics context by multiplying
* the current matrix with the specified matrix.
* @param a - The value for the a property of the matrix, or a Matrix object to use directly.
* @param b - The value for the b property of the matrix.
* @param c - The value for the c property of the matrix.
* @param d - The value for the d property of the matrix.
* @param dx - The value for the tx (translate x) property of the matrix.
* @param dy - The value for the ty (translate y) property of the matrix.
* @returns The instance of the current GraphicsContext for method chaining.
*/
transform(transform: Matrix): this;
transform(a: number, b: number, c: number, d: number, dx: number, dy: number): this;
transform(a: number | Matrix, b?: number, c?: number, d?: number, dx?: number, dy?: number): this;
/**
* Applies a translation transformation to the graphics context, moving the origin by the specified amounts.
* @param x - The amount to translate in the horizontal direction.
* @param y - (Optional) The amount to translate in the vertical direction. If not specified,
* the x value is used for both directions.
* @returns The instance of the current GraphicsContext for method chaining.
*/
translateTransform(x: number, y?: number): this;
/**
* Clears all drawing commands from the graphics context, effectively resetting it. This includes clearing the path,
* and optionally resetting transformations to the identity matrix.
* @returns The instance of the current GraphicsContext for method chaining.
*/
clear(): this;
/**
* The fill style to use.
* @type {ConvertedFillStyle}
*/
get fillStyle(): GraphicsContext['fillStyle'];
set fillStyle(value: FillInput);
/**
* The stroke style to use.
* @type {ConvertedStrokeStyle}
*/
get strokeStyle(): GraphicsContext['strokeStyle'];
set strokeStyle(value: StrokeStyle);
/**
* Creates a new Graphics object.
* Note that only the context of the object is cloned, not its transform (position,scale,etc)
* @param deep - Whether to create a deep clone of the graphics object. If false, the context
* will be shared between the two objects (default false). If true, the context will be
* cloned (recommended if you need to modify the context in any way).
* @returns - A clone of the graphics object
*/
clone(deep?: boolean): Graphics;
/**
* @param width
* @param color
* @param alpha
* @deprecated since 8.0.0 Use {@link Graphics#setStrokeStyle} instead
*/
lineStyle(width?: number, color?: ColorSource, alpha?: number): this;
/**
* @param color
* @param alpha
* @deprecated since 8.0.0 Use {@link Graphics#fill} instead
*/
beginFill(color: ColorSource, alpha?: number): this;
/**
* @deprecated since 8.0.0 Use {@link Graphics#fill} instead
*/
endFill(): this;
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#circle} instead
*/
drawCircle(...args: Parameters<GraphicsContext['circle']>): this;
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#ellipse} instead
*/
drawEllipse(...args: Parameters<GraphicsContext['ellipse']>): this;
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#poly} instead
*/
drawPolygon(...args: Parameters<GraphicsContext['poly']>): this;
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#rect} instead
*/
drawRect(...args: Parameters<GraphicsContext['rect']>): this;
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#roundRect} instead
*/
drawRoundedRect(...args: Parameters<GraphicsContext['roundRect']>): this;
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#star} instead
*/
drawStar(...args: Parameters<GraphicsContext['star']>): this;
}

View File

@@ -0,0 +1,397 @@
'use strict';
var deprecation = require('../../../utils/logging/deprecation.js');
var View = require('../../view/View.js');
var GraphicsContext = require('./GraphicsContext.js');
"use strict";
class Graphics extends View.ViewContainer {
/**
* @param options - Options for the Graphics.
*/
constructor(options) {
if (options instanceof GraphicsContext.GraphicsContext) {
options = { context: options };
}
const { context, roundPixels, ...rest } = options || {};
super({
label: "Graphics",
...rest
});
this.renderPipeId = "graphics";
if (!context) {
this._context = this._ownedContext = new GraphicsContext.GraphicsContext();
} else {
this._context = context;
}
this._context.on("update", this.onViewUpdate, this);
this.allowChildren = false;
this.roundPixels = roundPixels ?? false;
}
set context(context) {
if (context === this._context)
return;
this._context.off("update", this.onViewUpdate, this);
this._context = context;
this._context.on("update", this.onViewUpdate, this);
this.onViewUpdate();
}
get context() {
return this._context;
}
/**
* The local bounds of the graphic.
* @type {rendering.Bounds}
*/
get bounds() {
return this._context.bounds;
}
/**
* Adds the bounds of this object to the bounds object.
* @param bounds - The output bounds object.
*/
addBounds(bounds) {
bounds.addBounds(this._context.bounds);
}
/**
* Checks if the object contains the given point.
* @param point - The point to check
*/
containsPoint(point) {
return this._context.containsPoint(point);
}
onViewUpdate() {
this._didViewChangeTick++;
this._didGraphicsUpdate = true;
if (this.didViewUpdate)
return;
this.didViewUpdate = true;
const renderGroup = this.renderGroup || this.parentRenderGroup;
if (renderGroup) {
renderGroup.onChildViewUpdate(this);
}
}
/**
* Destroys this graphics renderable and optionally its context.
* @param options - Options parameter. A boolean will act as if all options
*
* If the context was created by this graphics and `destroy(false)` or `destroy()` is called
* then the context will still be destroyed.
*
* If you want to explicitly not destroy this context that this graphics created,
* then you should pass destroy({ context: false })
*
* If the context was passed in as an argument to the constructor then it will not be destroyed
* @param {boolean} [options.texture=false] - Should destroy the texture of the graphics context
* @param {boolean} [options.textureSource=false] - Should destroy the texture source of the graphics context
* @param {boolean} [options.context=false] - Should destroy the context
*/
destroy(options) {
if (this._ownedContext && !options) {
this._ownedContext.destroy(options);
} else if (options === true || options?.context === true) {
this._context.destroy(options);
}
this._ownedContext = null;
this._context = null;
super.destroy(options);
}
_callContextMethod(method, args) {
this.context[method](...args);
return this;
}
// --------------------------------------- GraphicsContext methods ---------------------------------------
/**
* Sets the current fill style of the graphics context. The fill style can be a color, gradient,
* pattern, or a more complex style defined by a FillStyle object.
* @param {FillInput} args - The fill style to apply. This can be a simple color, a gradient or
* pattern object, or a FillStyle or ConvertedFillStyle object.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setFillStyle(...args) {
return this._callContextMethod("setFillStyle", args);
}
/**
* Sets the current stroke style of the graphics context. Similar to fill styles, stroke styles can
* encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object.
* @param {StrokeInput} args - The stroke style to apply. Can be defined as a color, a gradient or pattern,
* or a StrokeStyle or ConvertedStrokeStyle object.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setStrokeStyle(...args) {
return this._callContextMethod("setStrokeStyle", args);
}
fill(...args) {
return this._callContextMethod("fill", args);
}
/**
* Strokes the current path with the current stroke style. This method can take an optional
* FillStyle parameter to define the stroke's appearance, including its color, width, and other properties.
* @param {FillStyle} args - (Optional) The stroke style to apply. Can be defined as a simple color or a more
* complex style object. If omitted, uses the current stroke style.
* @returns The instance of the current GraphicsContext for method chaining.
*/
stroke(...args) {
return this._callContextMethod("stroke", args);
}
texture(...args) {
return this._callContextMethod("texture", args);
}
/**
* Resets the current path. Any previous path and its commands are discarded and a new path is
* started. This is typically called before beginning a new shape or series of drawing commands.
* @returns The instance of the current GraphicsContext for method chaining.
*/
beginPath() {
return this._callContextMethod("beginPath", []);
}
/**
* Applies a cutout to the last drawn shape. This is used to create holes or complex shapes by
* subtracting a path from the previously drawn path. If a hole is not completely in a shape, it will
* fail to cut correctly!
*/
cut() {
return this._callContextMethod("cut", []);
}
arc(...args) {
return this._callContextMethod("arc", args);
}
arcTo(...args) {
return this._callContextMethod("arcTo", args);
}
arcToSvg(...args) {
return this._callContextMethod("arcToSvg", args);
}
bezierCurveTo(...args) {
return this._callContextMethod("bezierCurveTo", args);
}
/**
* Closes the current path by drawing a straight line back to the start.
* If the shape is already closed or there are no points in the path, this method does nothing.
* @returns The instance of the current object for chaining.
*/
closePath() {
return this._callContextMethod("closePath", []);
}
ellipse(...args) {
return this._callContextMethod("ellipse", args);
}
circle(...args) {
return this._callContextMethod("circle", args);
}
path(...args) {
return this._callContextMethod("path", args);
}
lineTo(...args) {
return this._callContextMethod("lineTo", args);
}
moveTo(...args) {
return this._callContextMethod("moveTo", args);
}
quadraticCurveTo(...args) {
return this._callContextMethod("quadraticCurveTo", args);
}
rect(...args) {
return this._callContextMethod("rect", args);
}
roundRect(...args) {
return this._callContextMethod("roundRect", args);
}
poly(...args) {
return this._callContextMethod("poly", args);
}
regularPoly(...args) {
return this._callContextMethod("regularPoly", args);
}
roundPoly(...args) {
return this._callContextMethod("roundPoly", args);
}
roundShape(...args) {
return this._callContextMethod("roundShape", args);
}
filletRect(...args) {
return this._callContextMethod("filletRect", args);
}
chamferRect(...args) {
return this._callContextMethod("chamferRect", args);
}
star(...args) {
return this._callContextMethod("star", args);
}
svg(...args) {
return this._callContextMethod("svg", args);
}
restore(...args) {
return this._callContextMethod("restore", args);
}
/** Saves the current graphics state, including transformations, fill styles, and stroke styles, onto a stack. */
save() {
return this._callContextMethod("save", []);
}
/**
* Returns the current transformation matrix of the graphics context.
* @returns The current transformation matrix.
*/
getTransform() {
return this.context.getTransform();
}
/**
* Resets the current transformation matrix to the identity matrix, effectively removing
* any transformations (rotation, scaling, translation) previously applied.
* @returns The instance of the current GraphicsContext for method chaining.
*/
resetTransform() {
return this._callContextMethod("resetTransform", []);
}
rotateTransform(...args) {
return this._callContextMethod("rotate", args);
}
scaleTransform(...args) {
return this._callContextMethod("scale", args);
}
setTransform(...args) {
return this._callContextMethod("setTransform", args);
}
transform(...args) {
return this._callContextMethod("transform", args);
}
translateTransform(...args) {
return this._callContextMethod("translate", args);
}
/**
* Clears all drawing commands from the graphics context, effectively resetting it. This includes clearing the path,
* and optionally resetting transformations to the identity matrix.
* @returns The instance of the current GraphicsContext for method chaining.
*/
clear() {
return this._callContextMethod("clear", []);
}
/**
* The fill style to use.
* @type {ConvertedFillStyle}
*/
get fillStyle() {
return this._context.fillStyle;
}
set fillStyle(value) {
this._context.fillStyle = value;
}
/**
* The stroke style to use.
* @type {ConvertedStrokeStyle}
*/
get strokeStyle() {
return this._context.strokeStyle;
}
set strokeStyle(value) {
this._context.strokeStyle = value;
}
/**
* Creates a new Graphics object.
* Note that only the context of the object is cloned, not its transform (position,scale,etc)
* @param deep - Whether to create a deep clone of the graphics object. If false, the context
* will be shared between the two objects (default false). If true, the context will be
* cloned (recommended if you need to modify the context in any way).
* @returns - A clone of the graphics object
*/
clone(deep = false) {
if (deep) {
return new Graphics(this._context.clone());
}
this._ownedContext = null;
const clone = new Graphics(this._context);
return clone;
}
// -------- v7 deprecations ---------
/**
* @param width
* @param color
* @param alpha
* @deprecated since 8.0.0 Use {@link Graphics#setStrokeStyle} instead
*/
lineStyle(width, color, alpha) {
deprecation.deprecation(deprecation.v8_0_0, "Graphics#lineStyle is no longer needed. Use Graphics#setStrokeStyle to set the stroke style.");
const strokeStyle = {};
width && (strokeStyle.width = width);
color && (strokeStyle.color = color);
alpha && (strokeStyle.alpha = alpha);
this.context.strokeStyle = strokeStyle;
return this;
}
/**
* @param color
* @param alpha
* @deprecated since 8.0.0 Use {@link Graphics#fill} instead
*/
beginFill(color, alpha) {
deprecation.deprecation(deprecation.v8_0_0, "Graphics#beginFill is no longer needed. Use Graphics#fill to fill the shape with the desired style.");
const fillStyle = {};
color && (fillStyle.color = color);
alpha && (fillStyle.alpha = alpha);
this.context.fillStyle = fillStyle;
return this;
}
/**
* @deprecated since 8.0.0 Use {@link Graphics#fill} instead
*/
endFill() {
deprecation.deprecation(deprecation.v8_0_0, "Graphics#endFill is no longer needed. Use Graphics#fill to fill the shape with the desired style.");
this.context.fill();
const strokeStyle = this.context.strokeStyle;
if (strokeStyle.width !== GraphicsContext.GraphicsContext.defaultStrokeStyle.width || strokeStyle.color !== GraphicsContext.GraphicsContext.defaultStrokeStyle.color || strokeStyle.alpha !== GraphicsContext.GraphicsContext.defaultStrokeStyle.alpha) {
this.context.stroke();
}
return this;
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#circle} instead
*/
drawCircle(...args) {
deprecation.deprecation(deprecation.v8_0_0, "Graphics#drawCircle has been renamed to Graphics#circle");
return this._callContextMethod("circle", args);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#ellipse} instead
*/
drawEllipse(...args) {
deprecation.deprecation(deprecation.v8_0_0, "Graphics#drawEllipse has been renamed to Graphics#ellipse");
return this._callContextMethod("ellipse", args);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#poly} instead
*/
drawPolygon(...args) {
deprecation.deprecation(deprecation.v8_0_0, "Graphics#drawPolygon has been renamed to Graphics#poly");
return this._callContextMethod("poly", args);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#rect} instead
*/
drawRect(...args) {
deprecation.deprecation(deprecation.v8_0_0, "Graphics#drawRect has been renamed to Graphics#rect");
return this._callContextMethod("rect", args);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#roundRect} instead
*/
drawRoundedRect(...args) {
deprecation.deprecation(deprecation.v8_0_0, "Graphics#drawRoundedRect has been renamed to Graphics#roundRect");
return this._callContextMethod("roundRect", args);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#star} instead
*/
drawStar(...args) {
deprecation.deprecation(deprecation.v8_0_0, "Graphics#drawStar has been renamed to Graphics#star");
return this._callContextMethod("star", args);
}
}
exports.Graphics = Graphics;
//# sourceMappingURL=Graphics.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,395 @@
import { deprecation, v8_0_0 } from '../../../utils/logging/deprecation.mjs';
import { ViewContainer } from '../../view/View.mjs';
import { GraphicsContext } from './GraphicsContext.mjs';
"use strict";
class Graphics extends ViewContainer {
/**
* @param options - Options for the Graphics.
*/
constructor(options) {
if (options instanceof GraphicsContext) {
options = { context: options };
}
const { context, roundPixels, ...rest } = options || {};
super({
label: "Graphics",
...rest
});
this.renderPipeId = "graphics";
if (!context) {
this._context = this._ownedContext = new GraphicsContext();
} else {
this._context = context;
}
this._context.on("update", this.onViewUpdate, this);
this.allowChildren = false;
this.roundPixels = roundPixels ?? false;
}
set context(context) {
if (context === this._context)
return;
this._context.off("update", this.onViewUpdate, this);
this._context = context;
this._context.on("update", this.onViewUpdate, this);
this.onViewUpdate();
}
get context() {
return this._context;
}
/**
* The local bounds of the graphic.
* @type {rendering.Bounds}
*/
get bounds() {
return this._context.bounds;
}
/**
* Adds the bounds of this object to the bounds object.
* @param bounds - The output bounds object.
*/
addBounds(bounds) {
bounds.addBounds(this._context.bounds);
}
/**
* Checks if the object contains the given point.
* @param point - The point to check
*/
containsPoint(point) {
return this._context.containsPoint(point);
}
onViewUpdate() {
this._didViewChangeTick++;
this._didGraphicsUpdate = true;
if (this.didViewUpdate)
return;
this.didViewUpdate = true;
const renderGroup = this.renderGroup || this.parentRenderGroup;
if (renderGroup) {
renderGroup.onChildViewUpdate(this);
}
}
/**
* Destroys this graphics renderable and optionally its context.
* @param options - Options parameter. A boolean will act as if all options
*
* If the context was created by this graphics and `destroy(false)` or `destroy()` is called
* then the context will still be destroyed.
*
* If you want to explicitly not destroy this context that this graphics created,
* then you should pass destroy({ context: false })
*
* If the context was passed in as an argument to the constructor then it will not be destroyed
* @param {boolean} [options.texture=false] - Should destroy the texture of the graphics context
* @param {boolean} [options.textureSource=false] - Should destroy the texture source of the graphics context
* @param {boolean} [options.context=false] - Should destroy the context
*/
destroy(options) {
if (this._ownedContext && !options) {
this._ownedContext.destroy(options);
} else if (options === true || options?.context === true) {
this._context.destroy(options);
}
this._ownedContext = null;
this._context = null;
super.destroy(options);
}
_callContextMethod(method, args) {
this.context[method](...args);
return this;
}
// --------------------------------------- GraphicsContext methods ---------------------------------------
/**
* Sets the current fill style of the graphics context. The fill style can be a color, gradient,
* pattern, or a more complex style defined by a FillStyle object.
* @param {FillInput} args - The fill style to apply. This can be a simple color, a gradient or
* pattern object, or a FillStyle or ConvertedFillStyle object.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setFillStyle(...args) {
return this._callContextMethod("setFillStyle", args);
}
/**
* Sets the current stroke style of the graphics context. Similar to fill styles, stroke styles can
* encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object.
* @param {StrokeInput} args - The stroke style to apply. Can be defined as a color, a gradient or pattern,
* or a StrokeStyle or ConvertedStrokeStyle object.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setStrokeStyle(...args) {
return this._callContextMethod("setStrokeStyle", args);
}
fill(...args) {
return this._callContextMethod("fill", args);
}
/**
* Strokes the current path with the current stroke style. This method can take an optional
* FillStyle parameter to define the stroke's appearance, including its color, width, and other properties.
* @param {FillStyle} args - (Optional) The stroke style to apply. Can be defined as a simple color or a more
* complex style object. If omitted, uses the current stroke style.
* @returns The instance of the current GraphicsContext for method chaining.
*/
stroke(...args) {
return this._callContextMethod("stroke", args);
}
texture(...args) {
return this._callContextMethod("texture", args);
}
/**
* Resets the current path. Any previous path and its commands are discarded and a new path is
* started. This is typically called before beginning a new shape or series of drawing commands.
* @returns The instance of the current GraphicsContext for method chaining.
*/
beginPath() {
return this._callContextMethod("beginPath", []);
}
/**
* Applies a cutout to the last drawn shape. This is used to create holes or complex shapes by
* subtracting a path from the previously drawn path. If a hole is not completely in a shape, it will
* fail to cut correctly!
*/
cut() {
return this._callContextMethod("cut", []);
}
arc(...args) {
return this._callContextMethod("arc", args);
}
arcTo(...args) {
return this._callContextMethod("arcTo", args);
}
arcToSvg(...args) {
return this._callContextMethod("arcToSvg", args);
}
bezierCurveTo(...args) {
return this._callContextMethod("bezierCurveTo", args);
}
/**
* Closes the current path by drawing a straight line back to the start.
* If the shape is already closed or there are no points in the path, this method does nothing.
* @returns The instance of the current object for chaining.
*/
closePath() {
return this._callContextMethod("closePath", []);
}
ellipse(...args) {
return this._callContextMethod("ellipse", args);
}
circle(...args) {
return this._callContextMethod("circle", args);
}
path(...args) {
return this._callContextMethod("path", args);
}
lineTo(...args) {
return this._callContextMethod("lineTo", args);
}
moveTo(...args) {
return this._callContextMethod("moveTo", args);
}
quadraticCurveTo(...args) {
return this._callContextMethod("quadraticCurveTo", args);
}
rect(...args) {
return this._callContextMethod("rect", args);
}
roundRect(...args) {
return this._callContextMethod("roundRect", args);
}
poly(...args) {
return this._callContextMethod("poly", args);
}
regularPoly(...args) {
return this._callContextMethod("regularPoly", args);
}
roundPoly(...args) {
return this._callContextMethod("roundPoly", args);
}
roundShape(...args) {
return this._callContextMethod("roundShape", args);
}
filletRect(...args) {
return this._callContextMethod("filletRect", args);
}
chamferRect(...args) {
return this._callContextMethod("chamferRect", args);
}
star(...args) {
return this._callContextMethod("star", args);
}
svg(...args) {
return this._callContextMethod("svg", args);
}
restore(...args) {
return this._callContextMethod("restore", args);
}
/** Saves the current graphics state, including transformations, fill styles, and stroke styles, onto a stack. */
save() {
return this._callContextMethod("save", []);
}
/**
* Returns the current transformation matrix of the graphics context.
* @returns The current transformation matrix.
*/
getTransform() {
return this.context.getTransform();
}
/**
* Resets the current transformation matrix to the identity matrix, effectively removing
* any transformations (rotation, scaling, translation) previously applied.
* @returns The instance of the current GraphicsContext for method chaining.
*/
resetTransform() {
return this._callContextMethod("resetTransform", []);
}
rotateTransform(...args) {
return this._callContextMethod("rotate", args);
}
scaleTransform(...args) {
return this._callContextMethod("scale", args);
}
setTransform(...args) {
return this._callContextMethod("setTransform", args);
}
transform(...args) {
return this._callContextMethod("transform", args);
}
translateTransform(...args) {
return this._callContextMethod("translate", args);
}
/**
* Clears all drawing commands from the graphics context, effectively resetting it. This includes clearing the path,
* and optionally resetting transformations to the identity matrix.
* @returns The instance of the current GraphicsContext for method chaining.
*/
clear() {
return this._callContextMethod("clear", []);
}
/**
* The fill style to use.
* @type {ConvertedFillStyle}
*/
get fillStyle() {
return this._context.fillStyle;
}
set fillStyle(value) {
this._context.fillStyle = value;
}
/**
* The stroke style to use.
* @type {ConvertedStrokeStyle}
*/
get strokeStyle() {
return this._context.strokeStyle;
}
set strokeStyle(value) {
this._context.strokeStyle = value;
}
/**
* Creates a new Graphics object.
* Note that only the context of the object is cloned, not its transform (position,scale,etc)
* @param deep - Whether to create a deep clone of the graphics object. If false, the context
* will be shared between the two objects (default false). If true, the context will be
* cloned (recommended if you need to modify the context in any way).
* @returns - A clone of the graphics object
*/
clone(deep = false) {
if (deep) {
return new Graphics(this._context.clone());
}
this._ownedContext = null;
const clone = new Graphics(this._context);
return clone;
}
// -------- v7 deprecations ---------
/**
* @param width
* @param color
* @param alpha
* @deprecated since 8.0.0 Use {@link Graphics#setStrokeStyle} instead
*/
lineStyle(width, color, alpha) {
deprecation(v8_0_0, "Graphics#lineStyle is no longer needed. Use Graphics#setStrokeStyle to set the stroke style.");
const strokeStyle = {};
width && (strokeStyle.width = width);
color && (strokeStyle.color = color);
alpha && (strokeStyle.alpha = alpha);
this.context.strokeStyle = strokeStyle;
return this;
}
/**
* @param color
* @param alpha
* @deprecated since 8.0.0 Use {@link Graphics#fill} instead
*/
beginFill(color, alpha) {
deprecation(v8_0_0, "Graphics#beginFill is no longer needed. Use Graphics#fill to fill the shape with the desired style.");
const fillStyle = {};
color && (fillStyle.color = color);
alpha && (fillStyle.alpha = alpha);
this.context.fillStyle = fillStyle;
return this;
}
/**
* @deprecated since 8.0.0 Use {@link Graphics#fill} instead
*/
endFill() {
deprecation(v8_0_0, "Graphics#endFill is no longer needed. Use Graphics#fill to fill the shape with the desired style.");
this.context.fill();
const strokeStyle = this.context.strokeStyle;
if (strokeStyle.width !== GraphicsContext.defaultStrokeStyle.width || strokeStyle.color !== GraphicsContext.defaultStrokeStyle.color || strokeStyle.alpha !== GraphicsContext.defaultStrokeStyle.alpha) {
this.context.stroke();
}
return this;
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#circle} instead
*/
drawCircle(...args) {
deprecation(v8_0_0, "Graphics#drawCircle has been renamed to Graphics#circle");
return this._callContextMethod("circle", args);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#ellipse} instead
*/
drawEllipse(...args) {
deprecation(v8_0_0, "Graphics#drawEllipse has been renamed to Graphics#ellipse");
return this._callContextMethod("ellipse", args);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#poly} instead
*/
drawPolygon(...args) {
deprecation(v8_0_0, "Graphics#drawPolygon has been renamed to Graphics#poly");
return this._callContextMethod("poly", args);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#rect} instead
*/
drawRect(...args) {
deprecation(v8_0_0, "Graphics#drawRect has been renamed to Graphics#rect");
return this._callContextMethod("rect", args);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#roundRect} instead
*/
drawRoundedRect(...args) {
deprecation(v8_0_0, "Graphics#drawRoundedRect has been renamed to Graphics#roundRect");
return this._callContextMethod("roundRect", args);
}
/**
* @param {...any} args
* @deprecated since 8.0.0 Use {@link Graphics#star} instead
*/
drawStar(...args) {
deprecation(v8_0_0, "Graphics#drawStar has been renamed to Graphics#star");
return this._callContextMethod("star", args);
}
}
export { Graphics };
//# sourceMappingURL=Graphics.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,451 @@
import EventEmitter from 'eventemitter3';
import { type ColorSource } from '../../../color/Color';
import { Matrix } from '../../../maths/matrix/Matrix';
import { Texture } from '../../../rendering/renderers/shared/texture/Texture';
import { Bounds } from '../../container/bounds/Bounds';
import { GraphicsPath } from './path/GraphicsPath';
import type { PointData } from '../../../maths/point/PointData';
import type { Shader } from '../../../rendering/renderers/shared/shader/Shader';
import type { TextureDestroyOptions, TypeOrBool } from '../../container/destroyTypes';
import type { ConvertedFillStyle, ConvertedStrokeStyle, FillInput, StrokeInput } from './FillTypes';
import type { RoundedPoint } from './path/roundShape';
export type BatchMode = 'auto' | 'batch' | 'no-batch';
export interface FillInstruction {
action: 'fill' | 'cut';
data: {
style: ConvertedFillStyle;
path: GraphicsPath;
hole?: GraphicsPath;
};
}
export interface StrokeInstruction {
action: 'stroke';
data: {
style: ConvertedStrokeStyle;
path: GraphicsPath;
hole?: GraphicsPath;
};
}
export interface TextureInstruction {
action: 'texture';
data: {
image: Texture;
dx: number;
dy: number;
dw: number;
dh: number;
transform: Matrix;
alpha: number;
style: number;
};
}
export type GraphicsInstructions = FillInstruction | StrokeInstruction | TextureInstruction;
/**
* The GraphicsContext class allows for the creation of lightweight objects that contain instructions for drawing shapes and paths.
* It is used internally by the Graphics class to draw shapes and paths, and can be used directly and shared between Graphics objects,
*
* This sharing of a `GraphicsContext` means that the intensive task of converting graphics instructions into GPU-ready geometry is done once, and the results are reused,
* much like sprites reusing textures.
* @memberof scene
*/
export declare class GraphicsContext extends EventEmitter<{
update: GraphicsContext;
destroy: GraphicsContext;
}> {
/** The default fill style to use when none is provided. */
static defaultFillStyle: ConvertedFillStyle;
/** The default stroke style to use when none is provided. */
static defaultStrokeStyle: ConvertedStrokeStyle;
/** unique id for this graphics context */
readonly uid: number;
dirty: boolean;
batchMode: BatchMode;
instructions: GraphicsInstructions[];
customShader?: Shader;
private _activePath;
private _transform;
private _fillStyle;
private _strokeStyle;
private _stateStack;
private _tick;
private _bounds;
private _boundsDirty;
/**
* Creates a new GraphicsContext object that is a clone of this instance, copying all properties,
* including the current drawing state, transformations, styles, and instructions.
* @returns A new GraphicsContext instance with the same properties and state as this one.
*/
clone(): GraphicsContext;
/**
* The current fill style of the graphics context. This can be a color, gradient, pattern, or a more complex style defined by a FillStyle object.
*/
get fillStyle(): ConvertedFillStyle;
set fillStyle(value: FillInput);
/**
* The current stroke style of the graphics context. Similar to fill styles, stroke styles can encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object.
*/
get strokeStyle(): ConvertedStrokeStyle;
set strokeStyle(value: FillInput);
/**
* Sets the current fill style of the graphics context. The fill style can be a color, gradient,
* pattern, or a more complex style defined by a FillStyle object.
* @param style - The fill style to apply. This can be a simple color, a gradient or pattern object,
* or a FillStyle or ConvertedFillStyle object.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setFillStyle(style: FillInput): this;
/**
* Sets the current stroke style of the graphics context. Similar to fill styles, stroke styles can
* encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object.
* @param style - The stroke style to apply. Can be defined as a color, a gradient or pattern,
* or a StrokeStyle or ConvertedStrokeStyle object.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setStrokeStyle(style: StrokeInput): this;
/**
* Adds a texture to the graphics context. This method supports multiple overloads for specifying the texture, tint, and dimensions.
* If only a texture is provided, it uses the texture's width and height for drawing. Additional parameters allow for specifying
* a tint color, and custom dimensions for the texture drawing area.
* @param texture - The Texture object to use.
* @param tint - (Optional) A ColorSource to tint the texture. If not provided, defaults to white (0xFFFFFF).
* @param dx - (Optional) The x-coordinate in the destination canvas at which to place the top-left corner of the source image.
* @param dy - (Optional) The y-coordinate in the destination canvas at which to place the top-left corner of the source image.
* @param dw - (Optional) The width of the rectangle within the source image to draw onto the destination canvas. If not provided, uses the texture's frame width.
* @param dh - (Optional) The height of the rectangle within the source image to draw onto the destination canvas. If not provided, uses the texture's frame height.
* @returns The instance of the current GraphicsContext for method chaining.
*/
texture(texture: Texture): this;
texture(texture: Texture, tint: ColorSource): this;
texture(texture: Texture, tint: ColorSource, dx: number, dy: number): this;
texture(texture: Texture, tint: ColorSource, dx: number, dy: number, dw: number, dh: number): this;
/**
* Resets the current path. Any previous path and its commands are discarded and a new path is
* started. This is typically called before beginning a new shape or series of drawing commands.
* @returns The instance of the current GraphicsContext for method chaining.
*/
beginPath(): this;
/**
* Fills the current or given path with the current fill style. This method can optionally take
* a color and alpha for a simple fill, or a more complex FillInput object for advanced fills.
* @param style - (Optional) The style to fill the path with. Can be a color, gradient, pattern, or a complex style object. If omitted, uses the current fill style.
* @returns The instance of the current GraphicsContext for method chaining.
*/
fill(style?: FillInput): this;
/** @deprecated 8.0.0 */
fill(color: ColorSource, alpha: number): this;
private _initNextPathLocation;
/**
* Strokes the current path with the current stroke style. This method can take an optional
* FillInput parameter to define the stroke's appearance, including its color, width, and other properties.
* @param style - (Optional) The stroke style to apply. Can be defined as a simple color or a more complex style object. If omitted, uses the current stroke style.
* @returns The instance of the current GraphicsContext for method chaining.
*/
stroke(style?: StrokeInput): this;
/**
* Applies a cutout to the last drawn shape. This is used to create holes or complex shapes by
* subtracting a path from the previously drawn path. If a hole is not completely in a shape, it will
* fail to cut correctly!
* @returns The instance of the current GraphicsContext for method chaining.
*/
cut(): this;
/**
* Adds an arc to the current path, which is centered at (x, y) with the specified radius,
* starting and ending angles, and direction.
* @param x - The x-coordinate of the arc's center.
* @param y - The y-coordinate of the arc's center.
* @param radius - The arc's radius.
* @param startAngle - The starting angle, in radians.
* @param endAngle - The ending angle, in radians.
* @param counterclockwise - (Optional) Specifies whether the arc is drawn counterclockwise (true) or clockwise (false). Defaults to false.
* @returns The instance of the current GraphicsContext for method chaining.
*/
arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): this;
/**
* Adds an arc to the current path with the given control points and radius, connected to the previous point
* by a straight line if necessary.
* @param x1 - The x-coordinate of the first control point.
* @param y1 - The y-coordinate of the first control point.
* @param x2 - The x-coordinate of the second control point.
* @param y2 - The y-coordinate of the second control point.
* @param radius - The arc's radius.
* @returns The instance of the current GraphicsContext for method chaining.
*/
arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): this;
/**
* Adds an SVG-style arc to the path, allowing for elliptical arcs based on the SVG spec.
* @param rx - The x-radius of the ellipse.
* @param ry - The y-radius of the ellipse.
* @param xAxisRotation - The rotation of the ellipse's x-axis relative
* to the x-axis of the coordinate system, in degrees.
* @param largeArcFlag - Determines if the arc should be greater than or less than 180 degrees.
* @param sweepFlag - Determines if the arc should be swept in a positive angle direction.
* @param x - The x-coordinate of the arc's end point.
* @param y - The y-coordinate of the arc's end point.
* @returns The instance of the current object for chaining.
*/
arcToSvg(rx: number, ry: number, xAxisRotation: number, largeArcFlag: number, sweepFlag: number, x: number, y: number): this;
/**
* Adds a cubic Bezier curve to the path.
* It requires three points: the first two are control points and the third one is the end point.
* The starting point is the last point in the current path.
* @param cp1x - The x-coordinate of the first control point.
* @param cp1y - The y-coordinate of the first control point.
* @param cp2x - The x-coordinate of the second control point.
* @param cp2y - The y-coordinate of the second control point.
* @param x - The x-coordinate of the end point.
* @param y - The y-coordinate of the end point.
* @param smoothness - Optional parameter to adjust the smoothness of the curve.
* @returns The instance of the current object for chaining.
*/
bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number, smoothness?: number): this;
/**
* Closes the current path by drawing a straight line back to the start.
* If the shape is already closed or there are no points in the path, this method does nothing.
* @returns The instance of the current object for chaining.
*/
closePath(): this;
/**
* Draws an ellipse at the specified location and with the given x and y radii.
* An optional transformation can be applied, allowing for rotation, scaling, and translation.
* @param x - The x-coordinate of the center of the ellipse.
* @param y - The y-coordinate of the center of the ellipse.
* @param radiusX - The horizontal radius of the ellipse.
* @param radiusY - The vertical radius of the ellipse.
* @returns The instance of the current object for chaining.
*/
ellipse(x: number, y: number, radiusX: number, radiusY: number): this;
/**
* Draws a circle shape. This method adds a new circle path to the current drawing.
* @param x - The x-coordinate of the center of the circle.
* @param y - The y-coordinate of the center of the circle.
* @param radius - The radius of the circle.
* @returns The instance of the current object for chaining.
*/
circle(x: number, y: number, radius: number): this;
/**
* Adds another `GraphicsPath` to this path, optionally applying a transformation.
* @param path - The `GraphicsPath` to add.
* @returns The instance of the current object for chaining.
*/
path(path: GraphicsPath): this;
/**
* Connects the current point to a new point with a straight line. This method updates the current path.
* @param x - The x-coordinate of the new point to connect to.
* @param y - The y-coordinate of the new point to connect to.
* @returns The instance of the current object for chaining.
*/
lineTo(x: number, y: number): this;
/**
* Sets the starting point for a new sub-path. Any subsequent drawing commands are considered part of this path.
* @param x - The x-coordinate for the starting point.
* @param y - The y-coordinate for the starting point.
* @returns The instance of the current object for chaining.
*/
moveTo(x: number, y: number): this;
/**
* Adds a quadratic curve to the path. It requires two points: the control point and the end point.
* The starting point is the last point in the current path.
* @param cpx - The x-coordinate of the control point.
* @param cpy - The y-coordinate of the control point.
* @param x - The x-coordinate of the end point.
* @param y - The y-coordinate of the end point.
* @param smoothness - Optional parameter to adjust the smoothness of the curve.
* @returns The instance of the current object for chaining.
*/
quadraticCurveTo(cpx: number, cpy: number, x: number, y: number, smoothness?: number): this;
/**
* Draws a rectangle shape. This method adds a new rectangle path to the current drawing.
* @param x - The x-coordinate of the top-left corner of the rectangle.
* @param y - The y-coordinate of the top-left corner of the rectangle.
* @param w - The width of the rectangle.
* @param h - The height of the rectangle.
* @returns The instance of the current object for chaining.
*/
rect(x: number, y: number, w: number, h: number): this;
/**
* Draws a rectangle with rounded corners.
* The corner radius can be specified to determine how rounded the corners should be.
* An optional transformation can be applied, which allows for rotation, scaling, and translation of the rectangle.
* @param x - The x-coordinate of the top-left corner of the rectangle.
* @param y - The y-coordinate of the top-left corner of the rectangle.
* @param w - The width of the rectangle.
* @param h - The height of the rectangle.
* @param radius - The radius of the rectangle's corners. If not specified, corners will be sharp.
* @returns The instance of the current object for chaining.
*/
roundRect(x: number, y: number, w: number, h: number, radius?: number): this;
/**
* Draws a polygon shape by specifying a sequence of points. This method allows for the creation of complex polygons,
* which can be both open and closed. An optional transformation can be applied, enabling the polygon to be scaled,
* rotated, or translated as needed.
* @param points - An array of numbers, or an array of PointData objects eg [{x,y}, {x,y}, {x,y}]
* representing the x and y coordinates, of the polygon's vertices, in sequence.
* @param close - A boolean indicating whether to close the polygon path. True by default.
*/
poly(points: number[] | PointData[], close?: boolean): this;
/**
* Draws a regular polygon with a specified number of sides. All sides and angles are equal.
* @param x - The x-coordinate of the center of the polygon.
* @param y - The y-coordinate of the center of the polygon.
* @param radius - The radius of the circumscribed circle of the polygon.
* @param sides - The number of sides of the polygon. Must be 3 or more.
* @param rotation - The rotation angle of the polygon, in radians. Zero by default.
* @param transform - An optional `Matrix` object to apply a transformation to the polygon.
* @returns The instance of the current object for chaining.
*/
regularPoly(x: number, y: number, radius: number, sides: number, rotation?: number, transform?: Matrix): this;
/**
* Draws a polygon with rounded corners.
* Similar to `regularPoly` but with the ability to round the corners of the polygon.
* @param x - The x-coordinate of the center of the polygon.
* @param y - The y-coordinate of the center of the polygon.
* @param radius - The radius of the circumscribed circle of the polygon.
* @param sides - The number of sides of the polygon. Must be 3 or more.
* @param corner - The radius of the rounding of the corners.
* @param rotation - The rotation angle of the polygon, in radians. Zero by default.
* @returns The instance of the current object for chaining.
*/
roundPoly(x: number, y: number, radius: number, sides: number, corner: number, rotation?: number): this;
/**
* Draws a shape with rounded corners. This function supports custom radius for each corner of the shape.
* Optionally, corners can be rounded using a quadratic curve instead of an arc, providing a different aesthetic.
* @param points - An array of `RoundedPoint` representing the corners of the shape to draw.
* A minimum of 3 points is required.
* @param radius - The default radius for the corners.
* This radius is applied to all corners unless overridden in `points`.
* @param useQuadratic - If set to true, rounded corners are drawn using a quadraticCurve
* method instead of an arc method. Defaults to false.
* @param smoothness - Specifies the smoothness of the curve when `useQuadratic` is true.
* Higher values make the curve smoother.
* @returns The instance of the current object for chaining.
*/
roundShape(points: RoundedPoint[], radius: number, useQuadratic?: boolean, smoothness?: number): this;
/**
* Draw Rectangle with fillet corners. This is much like rounded rectangle
* however it support negative numbers as well for the corner radius.
* @param x - Upper left corner of rect
* @param y - Upper right corner of rect
* @param width - Width of rect
* @param height - Height of rect
* @param fillet - accept negative or positive values
*/
filletRect(x: number, y: number, width: number, height: number, fillet: number): this;
/**
* Draw Rectangle with chamfer corners. These are angled corners.
* @param x - Upper left corner of rect
* @param y - Upper right corner of rect
* @param width - Width of rect
* @param height - Height of rect
* @param chamfer - non-zero real number, size of corner cutout
* @param transform
*/
chamferRect(x: number, y: number, width: number, height: number, chamfer: number, transform?: Matrix): this;
/**
* Draws a star shape centered at a specified location. This method allows for the creation
* of stars with a variable number of points, outer radius, optional inner radius, and rotation.
* The star is drawn as a closed polygon with alternating outer and inner vertices to create the star's points.
* An optional transformation can be applied to scale, rotate, or translate the star as needed.
* @param x - The x-coordinate of the center of the star.
* @param y - The y-coordinate of the center of the star.
* @param points - The number of points of the star.
* @param radius - The outer radius of the star (distance from the center to the outer points).
* @param innerRadius - Optional. The inner radius of the star
* (distance from the center to the inner points between the outer points).
* If not provided, defaults to half of the `radius`.
* @param rotation - Optional. The rotation of the star in radians, where 0 is aligned with the y-axis.
* Defaults to 0, meaning one point is directly upward.
* @returns The instance of the current object for chaining further drawing commands.
*/
star(x: number, y: number, points: number, radius: number, innerRadius?: number, rotation?: number): this;
/**
* Parses and renders an SVG string into the graphics context. This allows for complex shapes and paths
* defined in SVG format to be drawn within the graphics context.
* @param svg - The SVG string to be parsed and rendered.
*/
svg(svg: string): this;
/**
* Restores the most recently saved graphics state by popping the top of the graphics state stack.
* This includes transformations, fill styles, and stroke styles.
*/
restore(): this;
/** Saves the current graphics state, including transformations, fill styles, and stroke styles, onto a stack. */
save(): this;
/**
* Returns the current transformation matrix of the graphics context.
* @returns The current transformation matrix.
*/
getTransform(): Matrix;
/**
* Resets the current transformation matrix to the identity matrix, effectively removing any transformations (rotation, scaling, translation) previously applied.
* @returns The instance of the current GraphicsContext for method chaining.
*/
resetTransform(): this;
/**
* Applies a rotation transformation to the graphics context around the current origin.
* @param angle - The angle of rotation in radians.
* @returns The instance of the current GraphicsContext for method chaining.
*/
rotate(angle: number): this;
/**
* Applies a scaling transformation to the graphics context, scaling drawings by x horizontally and by y vertically.
* @param x - The scale factor in the horizontal direction.
* @param y - (Optional) The scale factor in the vertical direction. If not specified, the x value is used for both directions.
* @returns The instance of the current GraphicsContext for method chaining.
*/
scale(x: number, y?: number): this;
/**
* Sets the current transformation matrix of the graphics context to the specified matrix or values.
* This replaces the current transformation matrix.
* @param a - The value for the a property of the matrix, or a Matrix object to use directly.
* @param b - The value for the b property of the matrix.
* @param c - The value for the c property of the matrix.
* @param d - The value for the d property of the matrix.
* @param dx - The value for the tx (translate x) property of the matrix.
* @param dy - The value for the ty (translate y) property of the matrix.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setTransform(transform: Matrix): this;
setTransform(a: number, b: number, c: number, d: number, dx: number, dy: number): this;
/**
* Applies the specified transformation matrix to the current graphics context by multiplying the current matrix with the specified matrix.
* @param a - The value for the a property of the matrix, or a Matrix object to use directly.
* @param b - The value for the b property of the matrix.
* @param c - The value for the c property of the matrix.
* @param d - The value for the d property of the matrix.
* @param dx - The value for the tx (translate x) property of the matrix.
* @param dy - The value for the ty (translate y) property of the matrix.
* @returns The instance of the current GraphicsContext for method chaining.
*/
transform(transform: Matrix): this;
transform(a: number, b: number, c: number, d: number, dx: number, dy: number): this;
/**
* Applies a translation transformation to the graphics context, moving the origin by the specified amounts.
* @param x - The amount to translate in the horizontal direction.
* @param y - (Optional) The amount to translate in the vertical direction. If not specified, the x value is used for both directions.
* @returns The instance of the current GraphicsContext for method chaining.
*/
translate(x: number, y?: number): this;
/**
* Clears all drawing commands from the graphics context, effectively resetting it. This includes clearing the path,
* and optionally resetting transformations to the identity matrix.
* @returns The instance of the current GraphicsContext for method chaining.
*/
clear(): this;
protected onUpdate(): void;
/** The bounds of the graphic shape. */
get bounds(): Bounds;
/**
* Check to see if a point is contained within this geometry.
* @param point - Point to check if it's contained.
* @returns {boolean} `true` if the point is contained within geometry.
*/
containsPoint(point: PointData): boolean;
/**
* Destroys the GraphicsData object.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @param {boolean} [options.texture=false] - Should it destroy the current texture of the fill/stroke style?
* @param {boolean} [options.textureSource=false] - Should it destroy the texture source of the fill/stroke style?
*/
destroy(options?: TypeOrBool<TextureDestroyOptions>): void;
}

View File

@@ -0,0 +1,810 @@
'use strict';
var EventEmitter = require('eventemitter3');
var Color = require('../../../color/Color.js');
var Matrix = require('../../../maths/matrix/Matrix.js');
var Point = require('../../../maths/point/Point.js');
var Texture = require('../../../rendering/renderers/shared/texture/Texture.js');
var uid = require('../../../utils/data/uid.js');
var deprecation = require('../../../utils/logging/deprecation.js');
var Bounds = require('../../container/bounds/Bounds.js');
var GraphicsPath = require('./path/GraphicsPath.js');
var SVGParser = require('./svg/SVGParser.js');
var convertFillInputToFillStyle = require('./utils/convertFillInputToFillStyle.js');
"use strict";
const tmpPoint = new Point.Point();
const tempMatrix = new Matrix.Matrix();
const _GraphicsContext = class _GraphicsContext extends EventEmitter {
constructor() {
super(...arguments);
/** unique id for this graphics context */
this.uid = uid.uid("graphicsContext");
this.dirty = true;
this.batchMode = "auto";
this.instructions = [];
this._activePath = new GraphicsPath.GraphicsPath();
this._transform = new Matrix.Matrix();
this._fillStyle = { ..._GraphicsContext.defaultFillStyle };
this._strokeStyle = { ..._GraphicsContext.defaultStrokeStyle };
this._stateStack = [];
this._tick = 0;
this._bounds = new Bounds.Bounds();
this._boundsDirty = true;
}
/**
* Creates a new GraphicsContext object that is a clone of this instance, copying all properties,
* including the current drawing state, transformations, styles, and instructions.
* @returns A new GraphicsContext instance with the same properties and state as this one.
*/
clone() {
const clone = new _GraphicsContext();
clone.batchMode = this.batchMode;
clone.instructions = this.instructions.slice();
clone._activePath = this._activePath.clone();
clone._transform = this._transform.clone();
clone._fillStyle = { ...this._fillStyle };
clone._strokeStyle = { ...this._strokeStyle };
clone._stateStack = this._stateStack.slice();
clone._bounds = this._bounds.clone();
clone._boundsDirty = true;
return clone;
}
/**
* The current fill style of the graphics context. This can be a color, gradient, pattern, or a more complex style defined by a FillStyle object.
*/
get fillStyle() {
return this._fillStyle;
}
set fillStyle(value) {
this._fillStyle = convertFillInputToFillStyle.toFillStyle(value, _GraphicsContext.defaultFillStyle);
}
/**
* The current stroke style of the graphics context. Similar to fill styles, stroke styles can encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object.
*/
get strokeStyle() {
return this._strokeStyle;
}
set strokeStyle(value) {
this._strokeStyle = convertFillInputToFillStyle.toStrokeStyle(value, _GraphicsContext.defaultStrokeStyle);
}
/**
* Sets the current fill style of the graphics context. The fill style can be a color, gradient,
* pattern, or a more complex style defined by a FillStyle object.
* @param style - The fill style to apply. This can be a simple color, a gradient or pattern object,
* or a FillStyle or ConvertedFillStyle object.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setFillStyle(style) {
this._fillStyle = convertFillInputToFillStyle.toFillStyle(style, _GraphicsContext.defaultFillStyle);
return this;
}
/**
* Sets the current stroke style of the graphics context. Similar to fill styles, stroke styles can
* encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object.
* @param style - The stroke style to apply. Can be defined as a color, a gradient or pattern,
* or a StrokeStyle or ConvertedStrokeStyle object.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setStrokeStyle(style) {
this._strokeStyle = convertFillInputToFillStyle.toFillStyle(style, _GraphicsContext.defaultStrokeStyle);
return this;
}
texture(texture, tint, dx, dy, dw, dh) {
this.instructions.push({
action: "texture",
data: {
image: texture,
dx: dx || 0,
dy: dy || 0,
dw: dw || texture.frame.width,
dh: dh || texture.frame.height,
transform: this._transform.clone(),
alpha: this._fillStyle.alpha,
style: tint ? Color.Color.shared.setValue(tint).toNumber() : 16777215
}
});
this.onUpdate();
return this;
}
/**
* Resets the current path. Any previous path and its commands are discarded and a new path is
* started. This is typically called before beginning a new shape or series of drawing commands.
* @returns The instance of the current GraphicsContext for method chaining.
*/
beginPath() {
this._activePath = new GraphicsPath.GraphicsPath();
return this;
}
fill(style, alpha) {
let path;
const lastInstruction = this.instructions[this.instructions.length - 1];
if (this._tick === 0 && lastInstruction && lastInstruction.action === "stroke") {
path = lastInstruction.data.path;
} else {
path = this._activePath.clone();
}
if (!path)
return this;
if (style != null) {
if (alpha !== void 0 && typeof style === "number") {
deprecation.deprecation(deprecation.v8_0_0, "GraphicsContext.fill(color, alpha) is deprecated, use GraphicsContext.fill({ color, alpha }) instead");
style = { color: style, alpha };
}
this._fillStyle = convertFillInputToFillStyle.toFillStyle(style, _GraphicsContext.defaultFillStyle);
}
this.instructions.push({
action: "fill",
// TODO copy fill style!
data: { style: this.fillStyle, path }
});
this.onUpdate();
this._initNextPathLocation();
this._tick = 0;
return this;
}
_initNextPathLocation() {
const { x, y } = this._activePath.getLastPoint(Point.Point.shared);
this._activePath.clear();
this._activePath.moveTo(x, y);
}
/**
* Strokes the current path with the current stroke style. This method can take an optional
* FillInput parameter to define the stroke's appearance, including its color, width, and other properties.
* @param style - (Optional) The stroke style to apply. Can be defined as a simple color or a more complex style object. If omitted, uses the current stroke style.
* @returns The instance of the current GraphicsContext for method chaining.
*/
stroke(style) {
let path;
const lastInstruction = this.instructions[this.instructions.length - 1];
if (this._tick === 0 && lastInstruction && lastInstruction.action === "fill") {
path = lastInstruction.data.path;
} else {
path = this._activePath.clone();
}
if (!path)
return this;
if (style != null) {
this._strokeStyle = convertFillInputToFillStyle.toStrokeStyle(style, _GraphicsContext.defaultStrokeStyle);
}
this.instructions.push({
action: "stroke",
// TODO copy fill style!
data: { style: this.strokeStyle, path }
});
this.onUpdate();
this._initNextPathLocation();
this._tick = 0;
return this;
}
/**
* Applies a cutout to the last drawn shape. This is used to create holes or complex shapes by
* subtracting a path from the previously drawn path. If a hole is not completely in a shape, it will
* fail to cut correctly!
* @returns The instance of the current GraphicsContext for method chaining.
*/
cut() {
for (let i = 0; i < 2; i++) {
const lastInstruction = this.instructions[this.instructions.length - 1 - i];
const holePath = this._activePath.clone();
if (lastInstruction) {
if (lastInstruction.action === "stroke" || lastInstruction.action === "fill") {
if (lastInstruction.data.hole) {
lastInstruction.data.hole.addPath(holePath);
} else {
lastInstruction.data.hole = holePath;
break;
}
}
}
}
this._initNextPathLocation();
return this;
}
/**
* Adds an arc to the current path, which is centered at (x, y) with the specified radius,
* starting and ending angles, and direction.
* @param x - The x-coordinate of the arc's center.
* @param y - The y-coordinate of the arc's center.
* @param radius - The arc's radius.
* @param startAngle - The starting angle, in radians.
* @param endAngle - The ending angle, in radians.
* @param counterclockwise - (Optional) Specifies whether the arc is drawn counterclockwise (true) or clockwise (false). Defaults to false.
* @returns The instance of the current GraphicsContext for method chaining.
*/
arc(x, y, radius, startAngle, endAngle, counterclockwise) {
this._tick++;
const t = this._transform;
this._activePath.arc(
t.a * x + t.c * y + t.tx,
t.b * x + t.d * y + t.ty,
radius,
startAngle,
endAngle,
counterclockwise
);
return this;
}
/**
* Adds an arc to the current path with the given control points and radius, connected to the previous point
* by a straight line if necessary.
* @param x1 - The x-coordinate of the first control point.
* @param y1 - The y-coordinate of the first control point.
* @param x2 - The x-coordinate of the second control point.
* @param y2 - The y-coordinate of the second control point.
* @param radius - The arc's radius.
* @returns The instance of the current GraphicsContext for method chaining.
*/
arcTo(x1, y1, x2, y2, radius) {
this._tick++;
const t = this._transform;
this._activePath.arcTo(
t.a * x1 + t.c * y1 + t.tx,
t.b * x1 + t.d * y1 + t.ty,
t.a * x2 + t.c * y2 + t.tx,
t.b * x2 + t.d * y2 + t.ty,
radius
);
return this;
}
/**
* Adds an SVG-style arc to the path, allowing for elliptical arcs based on the SVG spec.
* @param rx - The x-radius of the ellipse.
* @param ry - The y-radius of the ellipse.
* @param xAxisRotation - The rotation of the ellipse's x-axis relative
* to the x-axis of the coordinate system, in degrees.
* @param largeArcFlag - Determines if the arc should be greater than or less than 180 degrees.
* @param sweepFlag - Determines if the arc should be swept in a positive angle direction.
* @param x - The x-coordinate of the arc's end point.
* @param y - The y-coordinate of the arc's end point.
* @returns The instance of the current object for chaining.
*/
arcToSvg(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
this._tick++;
const t = this._transform;
this._activePath.arcToSvg(
rx,
ry,
xAxisRotation,
// should we rotate this with transform??
largeArcFlag,
sweepFlag,
t.a * x + t.c * y + t.tx,
t.b * x + t.d * y + t.ty
);
return this;
}
/**
* Adds a cubic Bezier curve to the path.
* It requires three points: the first two are control points and the third one is the end point.
* The starting point is the last point in the current path.
* @param cp1x - The x-coordinate of the first control point.
* @param cp1y - The y-coordinate of the first control point.
* @param cp2x - The x-coordinate of the second control point.
* @param cp2y - The y-coordinate of the second control point.
* @param x - The x-coordinate of the end point.
* @param y - The y-coordinate of the end point.
* @param smoothness - Optional parameter to adjust the smoothness of the curve.
* @returns The instance of the current object for chaining.
*/
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, smoothness) {
this._tick++;
const t = this._transform;
this._activePath.bezierCurveTo(
t.a * cp1x + t.c * cp1y + t.tx,
t.b * cp1x + t.d * cp1y + t.ty,
t.a * cp2x + t.c * cp2y + t.tx,
t.b * cp2x + t.d * cp2y + t.ty,
t.a * x + t.c * y + t.tx,
t.b * x + t.d * y + t.ty,
smoothness
);
return this;
}
/**
* Closes the current path by drawing a straight line back to the start.
* If the shape is already closed or there are no points in the path, this method does nothing.
* @returns The instance of the current object for chaining.
*/
closePath() {
this._tick++;
this._activePath?.closePath();
return this;
}
/**
* Draws an ellipse at the specified location and with the given x and y radii.
* An optional transformation can be applied, allowing for rotation, scaling, and translation.
* @param x - The x-coordinate of the center of the ellipse.
* @param y - The y-coordinate of the center of the ellipse.
* @param radiusX - The horizontal radius of the ellipse.
* @param radiusY - The vertical radius of the ellipse.
* @returns The instance of the current object for chaining.
*/
ellipse(x, y, radiusX, radiusY) {
this._tick++;
this._activePath.ellipse(x, y, radiusX, radiusY, this._transform.clone());
return this;
}
/**
* Draws a circle shape. This method adds a new circle path to the current drawing.
* @param x - The x-coordinate of the center of the circle.
* @param y - The y-coordinate of the center of the circle.
* @param radius - The radius of the circle.
* @returns The instance of the current object for chaining.
*/
circle(x, y, radius) {
this._tick++;
this._activePath.circle(x, y, radius, this._transform.clone());
return this;
}
/**
* Adds another `GraphicsPath` to this path, optionally applying a transformation.
* @param path - The `GraphicsPath` to add.
* @returns The instance of the current object for chaining.
*/
path(path) {
this._tick++;
this._activePath.addPath(path, this._transform.clone());
return this;
}
/**
* Connects the current point to a new point with a straight line. This method updates the current path.
* @param x - The x-coordinate of the new point to connect to.
* @param y - The y-coordinate of the new point to connect to.
* @returns The instance of the current object for chaining.
*/
lineTo(x, y) {
this._tick++;
const t = this._transform;
this._activePath.lineTo(
t.a * x + t.c * y + t.tx,
t.b * x + t.d * y + t.ty
);
return this;
}
/**
* Sets the starting point for a new sub-path. Any subsequent drawing commands are considered part of this path.
* @param x - The x-coordinate for the starting point.
* @param y - The y-coordinate for the starting point.
* @returns The instance of the current object for chaining.
*/
moveTo(x, y) {
this._tick++;
const t = this._transform;
const instructions = this._activePath.instructions;
const transformedX = t.a * x + t.c * y + t.tx;
const transformedY = t.b * x + t.d * y + t.ty;
if (instructions.length === 1 && instructions[0].action === "moveTo") {
instructions[0].data[0] = transformedX;
instructions[0].data[1] = transformedY;
return this;
}
this._activePath.moveTo(
transformedX,
transformedY
);
return this;
}
/**
* Adds a quadratic curve to the path. It requires two points: the control point and the end point.
* The starting point is the last point in the current path.
* @param cpx - The x-coordinate of the control point.
* @param cpy - The y-coordinate of the control point.
* @param x - The x-coordinate of the end point.
* @param y - The y-coordinate of the end point.
* @param smoothness - Optional parameter to adjust the smoothness of the curve.
* @returns The instance of the current object for chaining.
*/
quadraticCurveTo(cpx, cpy, x, y, smoothness) {
this._tick++;
const t = this._transform;
this._activePath.quadraticCurveTo(
t.a * cpx + t.c * cpy + t.tx,
t.b * cpx + t.d * cpy + t.ty,
t.a * x + t.c * y + t.tx,
t.b * x + t.d * y + t.ty,
smoothness
);
return this;
}
/**
* Draws a rectangle shape. This method adds a new rectangle path to the current drawing.
* @param x - The x-coordinate of the top-left corner of the rectangle.
* @param y - The y-coordinate of the top-left corner of the rectangle.
* @param w - The width of the rectangle.
* @param h - The height of the rectangle.
* @returns The instance of the current object for chaining.
*/
rect(x, y, w, h) {
this._tick++;
this._activePath.rect(x, y, w, h, this._transform.clone());
return this;
}
/**
* Draws a rectangle with rounded corners.
* The corner radius can be specified to determine how rounded the corners should be.
* An optional transformation can be applied, which allows for rotation, scaling, and translation of the rectangle.
* @param x - The x-coordinate of the top-left corner of the rectangle.
* @param y - The y-coordinate of the top-left corner of the rectangle.
* @param w - The width of the rectangle.
* @param h - The height of the rectangle.
* @param radius - The radius of the rectangle's corners. If not specified, corners will be sharp.
* @returns The instance of the current object for chaining.
*/
roundRect(x, y, w, h, radius) {
this._tick++;
this._activePath.roundRect(x, y, w, h, radius, this._transform.clone());
return this;
}
/**
* Draws a polygon shape by specifying a sequence of points. This method allows for the creation of complex polygons,
* which can be both open and closed. An optional transformation can be applied, enabling the polygon to be scaled,
* rotated, or translated as needed.
* @param points - An array of numbers, or an array of PointData objects eg [{x,y}, {x,y}, {x,y}]
* representing the x and y coordinates, of the polygon's vertices, in sequence.
* @param close - A boolean indicating whether to close the polygon path. True by default.
*/
poly(points, close) {
this._tick++;
this._activePath.poly(points, close, this._transform.clone());
return this;
}
/**
* Draws a regular polygon with a specified number of sides. All sides and angles are equal.
* @param x - The x-coordinate of the center of the polygon.
* @param y - The y-coordinate of the center of the polygon.
* @param radius - The radius of the circumscribed circle of the polygon.
* @param sides - The number of sides of the polygon. Must be 3 or more.
* @param rotation - The rotation angle of the polygon, in radians. Zero by default.
* @param transform - An optional `Matrix` object to apply a transformation to the polygon.
* @returns The instance of the current object for chaining.
*/
regularPoly(x, y, radius, sides, rotation = 0, transform) {
this._tick++;
this._activePath.regularPoly(x, y, radius, sides, rotation, transform);
return this;
}
/**
* Draws a polygon with rounded corners.
* Similar to `regularPoly` but with the ability to round the corners of the polygon.
* @param x - The x-coordinate of the center of the polygon.
* @param y - The y-coordinate of the center of the polygon.
* @param radius - The radius of the circumscribed circle of the polygon.
* @param sides - The number of sides of the polygon. Must be 3 or more.
* @param corner - The radius of the rounding of the corners.
* @param rotation - The rotation angle of the polygon, in radians. Zero by default.
* @returns The instance of the current object for chaining.
*/
roundPoly(x, y, radius, sides, corner, rotation) {
this._tick++;
this._activePath.roundPoly(x, y, radius, sides, corner, rotation);
return this;
}
/**
* Draws a shape with rounded corners. This function supports custom radius for each corner of the shape.
* Optionally, corners can be rounded using a quadratic curve instead of an arc, providing a different aesthetic.
* @param points - An array of `RoundedPoint` representing the corners of the shape to draw.
* A minimum of 3 points is required.
* @param radius - The default radius for the corners.
* This radius is applied to all corners unless overridden in `points`.
* @param useQuadratic - If set to true, rounded corners are drawn using a quadraticCurve
* method instead of an arc method. Defaults to false.
* @param smoothness - Specifies the smoothness of the curve when `useQuadratic` is true.
* Higher values make the curve smoother.
* @returns The instance of the current object for chaining.
*/
roundShape(points, radius, useQuadratic, smoothness) {
this._tick++;
this._activePath.roundShape(points, radius, useQuadratic, smoothness);
return this;
}
/**
* Draw Rectangle with fillet corners. This is much like rounded rectangle
* however it support negative numbers as well for the corner radius.
* @param x - Upper left corner of rect
* @param y - Upper right corner of rect
* @param width - Width of rect
* @param height - Height of rect
* @param fillet - accept negative or positive values
*/
filletRect(x, y, width, height, fillet) {
this._tick++;
this._activePath.filletRect(x, y, width, height, fillet);
return this;
}
/**
* Draw Rectangle with chamfer corners. These are angled corners.
* @param x - Upper left corner of rect
* @param y - Upper right corner of rect
* @param width - Width of rect
* @param height - Height of rect
* @param chamfer - non-zero real number, size of corner cutout
* @param transform
*/
chamferRect(x, y, width, height, chamfer, transform) {
this._tick++;
this._activePath.chamferRect(x, y, width, height, chamfer, transform);
return this;
}
/**
* Draws a star shape centered at a specified location. This method allows for the creation
* of stars with a variable number of points, outer radius, optional inner radius, and rotation.
* The star is drawn as a closed polygon with alternating outer and inner vertices to create the star's points.
* An optional transformation can be applied to scale, rotate, or translate the star as needed.
* @param x - The x-coordinate of the center of the star.
* @param y - The y-coordinate of the center of the star.
* @param points - The number of points of the star.
* @param radius - The outer radius of the star (distance from the center to the outer points).
* @param innerRadius - Optional. The inner radius of the star
* (distance from the center to the inner points between the outer points).
* If not provided, defaults to half of the `radius`.
* @param rotation - Optional. The rotation of the star in radians, where 0 is aligned with the y-axis.
* Defaults to 0, meaning one point is directly upward.
* @returns The instance of the current object for chaining further drawing commands.
*/
star(x, y, points, radius, innerRadius = 0, rotation = 0) {
this._tick++;
this._activePath.star(x, y, points, radius, innerRadius, rotation, this._transform.clone());
return this;
}
/**
* Parses and renders an SVG string into the graphics context. This allows for complex shapes and paths
* defined in SVG format to be drawn within the graphics context.
* @param svg - The SVG string to be parsed and rendered.
*/
svg(svg) {
this._tick++;
SVGParser.SVGParser(svg, this);
return this;
}
/**
* Restores the most recently saved graphics state by popping the top of the graphics state stack.
* This includes transformations, fill styles, and stroke styles.
*/
restore() {
const state = this._stateStack.pop();
if (state) {
this._transform = state.transform;
this._fillStyle = state.fillStyle;
this._strokeStyle = state.strokeStyle;
}
return this;
}
/** Saves the current graphics state, including transformations, fill styles, and stroke styles, onto a stack. */
save() {
this._stateStack.push({
transform: this._transform.clone(),
fillStyle: { ...this._fillStyle },
strokeStyle: { ...this._strokeStyle }
});
return this;
}
/**
* Returns the current transformation matrix of the graphics context.
* @returns The current transformation matrix.
*/
getTransform() {
return this._transform;
}
/**
* Resets the current transformation matrix to the identity matrix, effectively removing any transformations (rotation, scaling, translation) previously applied.
* @returns The instance of the current GraphicsContext for method chaining.
*/
resetTransform() {
this._transform.identity();
return this;
}
/**
* Applies a rotation transformation to the graphics context around the current origin.
* @param angle - The angle of rotation in radians.
* @returns The instance of the current GraphicsContext for method chaining.
*/
rotate(angle) {
this._transform.rotate(angle);
return this;
}
/**
* Applies a scaling transformation to the graphics context, scaling drawings by x horizontally and by y vertically.
* @param x - The scale factor in the horizontal direction.
* @param y - (Optional) The scale factor in the vertical direction. If not specified, the x value is used for both directions.
* @returns The instance of the current GraphicsContext for method chaining.
*/
scale(x, y = x) {
this._transform.scale(x, y);
return this;
}
setTransform(a, b, c, d, dx, dy) {
if (a instanceof Matrix.Matrix) {
this._transform.set(a.a, a.b, a.c, a.d, a.tx, a.ty);
return this;
}
this._transform.set(a, b, c, d, dx, dy);
return this;
}
transform(a, b, c, d, dx, dy) {
if (a instanceof Matrix.Matrix) {
this._transform.append(a);
return this;
}
tempMatrix.set(a, b, c, d, dx, dy);
this._transform.append(tempMatrix);
return this;
}
/**
* Applies a translation transformation to the graphics context, moving the origin by the specified amounts.
* @param x - The amount to translate in the horizontal direction.
* @param y - (Optional) The amount to translate in the vertical direction. If not specified, the x value is used for both directions.
* @returns The instance of the current GraphicsContext for method chaining.
*/
translate(x, y = x) {
this._transform.translate(x, y);
return this;
}
/**
* Clears all drawing commands from the graphics context, effectively resetting it. This includes clearing the path,
* and optionally resetting transformations to the identity matrix.
* @returns The instance of the current GraphicsContext for method chaining.
*/
clear() {
this._activePath.clear();
this.instructions.length = 0;
this.resetTransform();
this.onUpdate();
return this;
}
onUpdate() {
if (this.dirty)
return;
this.emit("update", this, 16);
this.dirty = true;
this._boundsDirty = true;
}
/** The bounds of the graphic shape. */
get bounds() {
if (!this._boundsDirty)
return this._bounds;
const bounds = this._bounds;
bounds.clear();
for (let i = 0; i < this.instructions.length; i++) {
const instruction = this.instructions[i];
const action = instruction.action;
if (action === "fill") {
const data = instruction.data;
bounds.addBounds(data.path.bounds);
} else if (action === "texture") {
const data = instruction.data;
bounds.addFrame(data.dx, data.dy, data.dx + data.dw, data.dy + data.dh, data.transform);
}
if (action === "stroke") {
const data = instruction.data;
const padding = data.style.width / 2;
const _bounds = data.path.bounds;
bounds.addFrame(
_bounds.minX - padding,
_bounds.minY - padding,
_bounds.maxX + padding,
_bounds.maxY + padding
);
}
}
return bounds;
}
/**
* Check to see if a point is contained within this geometry.
* @param point - Point to check if it's contained.
* @returns {boolean} `true` if the point is contained within geometry.
*/
containsPoint(point) {
if (!this.bounds.containsPoint(point.x, point.y))
return false;
const instructions = this.instructions;
let hasHit = false;
for (let k = 0; k < instructions.length; k++) {
const instruction = instructions[k];
const data = instruction.data;
const path = data.path;
if (!instruction.action || !path)
continue;
const style = data.style;
const shapes = path.shapePath.shapePrimitives;
for (let i = 0; i < shapes.length; i++) {
const shape = shapes[i].shape;
if (!style || !shape)
continue;
const transform = shapes[i].transform;
const transformedPoint = transform ? transform.applyInverse(point, tmpPoint) : point;
if (instruction.action === "fill") {
hasHit = shape.contains(transformedPoint.x, transformedPoint.y);
} else {
hasHit = shape.strokeContains(transformedPoint.x, transformedPoint.y, style.width);
}
const holes = data.hole;
if (holes) {
const holeShapes = holes.shapePath?.shapePrimitives;
if (holeShapes) {
for (let j = 0; j < holeShapes.length; j++) {
if (holeShapes[j].shape.contains(transformedPoint.x, transformedPoint.y)) {
hasHit = false;
}
}
}
}
if (hasHit) {
return true;
}
}
}
return hasHit;
}
/**
* Destroys the GraphicsData object.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @param {boolean} [options.texture=false] - Should it destroy the current texture of the fill/stroke style?
* @param {boolean} [options.textureSource=false] - Should it destroy the texture source of the fill/stroke style?
*/
destroy(options = false) {
this._stateStack.length = 0;
this._transform = null;
this.emit("destroy", this);
this.removeAllListeners();
const destroyTexture = typeof options === "boolean" ? options : options?.texture;
if (destroyTexture) {
const destroyTextureSource = typeof options === "boolean" ? options : options?.textureSource;
if (this._fillStyle.texture) {
this._fillStyle.texture.destroy(destroyTextureSource);
}
if (this._strokeStyle.texture) {
this._strokeStyle.texture.destroy(destroyTextureSource);
}
}
this._fillStyle = null;
this._strokeStyle = null;
this.instructions = null;
this._activePath = null;
this._bounds = null;
this._stateStack = null;
this.customShader = null;
this._transform = null;
}
};
/** The default fill style to use when none is provided. */
_GraphicsContext.defaultFillStyle = {
/** The color to use for the fill. */
color: 16777215,
/** The alpha value to use for the fill. */
alpha: 1,
/** The texture to use for the fill. */
texture: Texture.Texture.WHITE,
/** The matrix to apply. */
matrix: null,
/** The fill pattern to use. */
fill: null
};
/** The default stroke style to use when none is provided. */
_GraphicsContext.defaultStrokeStyle = {
/** The width of the stroke. */
width: 1,
/** The color to use for the stroke. */
color: 16777215,
/** The alpha value to use for the stroke. */
alpha: 1,
/** The alignment of the stroke. */
alignment: 0.5,
/** The miter limit to use. */
miterLimit: 10,
/** The line cap style to use. */
cap: "butt",
/** The line join style to use. */
join: "miter",
/** The texture to use for the fill. */
texture: Texture.Texture.WHITE,
/** The matrix to apply. */
matrix: null,
/** The fill pattern to use. */
fill: null
};
let GraphicsContext = _GraphicsContext;
exports.GraphicsContext = GraphicsContext;
//# sourceMappingURL=GraphicsContext.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,808 @@
import EventEmitter from 'eventemitter3';
import { Color } from '../../../color/Color.mjs';
import { Matrix } from '../../../maths/matrix/Matrix.mjs';
import { Point } from '../../../maths/point/Point.mjs';
import { Texture } from '../../../rendering/renderers/shared/texture/Texture.mjs';
import { uid } from '../../../utils/data/uid.mjs';
import { deprecation, v8_0_0 } from '../../../utils/logging/deprecation.mjs';
import { Bounds } from '../../container/bounds/Bounds.mjs';
import { GraphicsPath } from './path/GraphicsPath.mjs';
import { SVGParser } from './svg/SVGParser.mjs';
import { toFillStyle, toStrokeStyle } from './utils/convertFillInputToFillStyle.mjs';
"use strict";
const tmpPoint = new Point();
const tempMatrix = new Matrix();
const _GraphicsContext = class _GraphicsContext extends EventEmitter {
constructor() {
super(...arguments);
/** unique id for this graphics context */
this.uid = uid("graphicsContext");
this.dirty = true;
this.batchMode = "auto";
this.instructions = [];
this._activePath = new GraphicsPath();
this._transform = new Matrix();
this._fillStyle = { ..._GraphicsContext.defaultFillStyle };
this._strokeStyle = { ..._GraphicsContext.defaultStrokeStyle };
this._stateStack = [];
this._tick = 0;
this._bounds = new Bounds();
this._boundsDirty = true;
}
/**
* Creates a new GraphicsContext object that is a clone of this instance, copying all properties,
* including the current drawing state, transformations, styles, and instructions.
* @returns A new GraphicsContext instance with the same properties and state as this one.
*/
clone() {
const clone = new _GraphicsContext();
clone.batchMode = this.batchMode;
clone.instructions = this.instructions.slice();
clone._activePath = this._activePath.clone();
clone._transform = this._transform.clone();
clone._fillStyle = { ...this._fillStyle };
clone._strokeStyle = { ...this._strokeStyle };
clone._stateStack = this._stateStack.slice();
clone._bounds = this._bounds.clone();
clone._boundsDirty = true;
return clone;
}
/**
* The current fill style of the graphics context. This can be a color, gradient, pattern, or a more complex style defined by a FillStyle object.
*/
get fillStyle() {
return this._fillStyle;
}
set fillStyle(value) {
this._fillStyle = toFillStyle(value, _GraphicsContext.defaultFillStyle);
}
/**
* The current stroke style of the graphics context. Similar to fill styles, stroke styles can encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object.
*/
get strokeStyle() {
return this._strokeStyle;
}
set strokeStyle(value) {
this._strokeStyle = toStrokeStyle(value, _GraphicsContext.defaultStrokeStyle);
}
/**
* Sets the current fill style of the graphics context. The fill style can be a color, gradient,
* pattern, or a more complex style defined by a FillStyle object.
* @param style - The fill style to apply. This can be a simple color, a gradient or pattern object,
* or a FillStyle or ConvertedFillStyle object.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setFillStyle(style) {
this._fillStyle = toFillStyle(style, _GraphicsContext.defaultFillStyle);
return this;
}
/**
* Sets the current stroke style of the graphics context. Similar to fill styles, stroke styles can
* encompass colors, gradients, patterns, or more detailed configurations via a StrokeStyle object.
* @param style - The stroke style to apply. Can be defined as a color, a gradient or pattern,
* or a StrokeStyle or ConvertedStrokeStyle object.
* @returns The instance of the current GraphicsContext for method chaining.
*/
setStrokeStyle(style) {
this._strokeStyle = toFillStyle(style, _GraphicsContext.defaultStrokeStyle);
return this;
}
texture(texture, tint, dx, dy, dw, dh) {
this.instructions.push({
action: "texture",
data: {
image: texture,
dx: dx || 0,
dy: dy || 0,
dw: dw || texture.frame.width,
dh: dh || texture.frame.height,
transform: this._transform.clone(),
alpha: this._fillStyle.alpha,
style: tint ? Color.shared.setValue(tint).toNumber() : 16777215
}
});
this.onUpdate();
return this;
}
/**
* Resets the current path. Any previous path and its commands are discarded and a new path is
* started. This is typically called before beginning a new shape or series of drawing commands.
* @returns The instance of the current GraphicsContext for method chaining.
*/
beginPath() {
this._activePath = new GraphicsPath();
return this;
}
fill(style, alpha) {
let path;
const lastInstruction = this.instructions[this.instructions.length - 1];
if (this._tick === 0 && lastInstruction && lastInstruction.action === "stroke") {
path = lastInstruction.data.path;
} else {
path = this._activePath.clone();
}
if (!path)
return this;
if (style != null) {
if (alpha !== void 0 && typeof style === "number") {
deprecation(v8_0_0, "GraphicsContext.fill(color, alpha) is deprecated, use GraphicsContext.fill({ color, alpha }) instead");
style = { color: style, alpha };
}
this._fillStyle = toFillStyle(style, _GraphicsContext.defaultFillStyle);
}
this.instructions.push({
action: "fill",
// TODO copy fill style!
data: { style: this.fillStyle, path }
});
this.onUpdate();
this._initNextPathLocation();
this._tick = 0;
return this;
}
_initNextPathLocation() {
const { x, y } = this._activePath.getLastPoint(Point.shared);
this._activePath.clear();
this._activePath.moveTo(x, y);
}
/**
* Strokes the current path with the current stroke style. This method can take an optional
* FillInput parameter to define the stroke's appearance, including its color, width, and other properties.
* @param style - (Optional) The stroke style to apply. Can be defined as a simple color or a more complex style object. If omitted, uses the current stroke style.
* @returns The instance of the current GraphicsContext for method chaining.
*/
stroke(style) {
let path;
const lastInstruction = this.instructions[this.instructions.length - 1];
if (this._tick === 0 && lastInstruction && lastInstruction.action === "fill") {
path = lastInstruction.data.path;
} else {
path = this._activePath.clone();
}
if (!path)
return this;
if (style != null) {
this._strokeStyle = toStrokeStyle(style, _GraphicsContext.defaultStrokeStyle);
}
this.instructions.push({
action: "stroke",
// TODO copy fill style!
data: { style: this.strokeStyle, path }
});
this.onUpdate();
this._initNextPathLocation();
this._tick = 0;
return this;
}
/**
* Applies a cutout to the last drawn shape. This is used to create holes or complex shapes by
* subtracting a path from the previously drawn path. If a hole is not completely in a shape, it will
* fail to cut correctly!
* @returns The instance of the current GraphicsContext for method chaining.
*/
cut() {
for (let i = 0; i < 2; i++) {
const lastInstruction = this.instructions[this.instructions.length - 1 - i];
const holePath = this._activePath.clone();
if (lastInstruction) {
if (lastInstruction.action === "stroke" || lastInstruction.action === "fill") {
if (lastInstruction.data.hole) {
lastInstruction.data.hole.addPath(holePath);
} else {
lastInstruction.data.hole = holePath;
break;
}
}
}
}
this._initNextPathLocation();
return this;
}
/**
* Adds an arc to the current path, which is centered at (x, y) with the specified radius,
* starting and ending angles, and direction.
* @param x - The x-coordinate of the arc's center.
* @param y - The y-coordinate of the arc's center.
* @param radius - The arc's radius.
* @param startAngle - The starting angle, in radians.
* @param endAngle - The ending angle, in radians.
* @param counterclockwise - (Optional) Specifies whether the arc is drawn counterclockwise (true) or clockwise (false). Defaults to false.
* @returns The instance of the current GraphicsContext for method chaining.
*/
arc(x, y, radius, startAngle, endAngle, counterclockwise) {
this._tick++;
const t = this._transform;
this._activePath.arc(
t.a * x + t.c * y + t.tx,
t.b * x + t.d * y + t.ty,
radius,
startAngle,
endAngle,
counterclockwise
);
return this;
}
/**
* Adds an arc to the current path with the given control points and radius, connected to the previous point
* by a straight line if necessary.
* @param x1 - The x-coordinate of the first control point.
* @param y1 - The y-coordinate of the first control point.
* @param x2 - The x-coordinate of the second control point.
* @param y2 - The y-coordinate of the second control point.
* @param radius - The arc's radius.
* @returns The instance of the current GraphicsContext for method chaining.
*/
arcTo(x1, y1, x2, y2, radius) {
this._tick++;
const t = this._transform;
this._activePath.arcTo(
t.a * x1 + t.c * y1 + t.tx,
t.b * x1 + t.d * y1 + t.ty,
t.a * x2 + t.c * y2 + t.tx,
t.b * x2 + t.d * y2 + t.ty,
radius
);
return this;
}
/**
* Adds an SVG-style arc to the path, allowing for elliptical arcs based on the SVG spec.
* @param rx - The x-radius of the ellipse.
* @param ry - The y-radius of the ellipse.
* @param xAxisRotation - The rotation of the ellipse's x-axis relative
* to the x-axis of the coordinate system, in degrees.
* @param largeArcFlag - Determines if the arc should be greater than or less than 180 degrees.
* @param sweepFlag - Determines if the arc should be swept in a positive angle direction.
* @param x - The x-coordinate of the arc's end point.
* @param y - The y-coordinate of the arc's end point.
* @returns The instance of the current object for chaining.
*/
arcToSvg(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) {
this._tick++;
const t = this._transform;
this._activePath.arcToSvg(
rx,
ry,
xAxisRotation,
// should we rotate this with transform??
largeArcFlag,
sweepFlag,
t.a * x + t.c * y + t.tx,
t.b * x + t.d * y + t.ty
);
return this;
}
/**
* Adds a cubic Bezier curve to the path.
* It requires three points: the first two are control points and the third one is the end point.
* The starting point is the last point in the current path.
* @param cp1x - The x-coordinate of the first control point.
* @param cp1y - The y-coordinate of the first control point.
* @param cp2x - The x-coordinate of the second control point.
* @param cp2y - The y-coordinate of the second control point.
* @param x - The x-coordinate of the end point.
* @param y - The y-coordinate of the end point.
* @param smoothness - Optional parameter to adjust the smoothness of the curve.
* @returns The instance of the current object for chaining.
*/
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, smoothness) {
this._tick++;
const t = this._transform;
this._activePath.bezierCurveTo(
t.a * cp1x + t.c * cp1y + t.tx,
t.b * cp1x + t.d * cp1y + t.ty,
t.a * cp2x + t.c * cp2y + t.tx,
t.b * cp2x + t.d * cp2y + t.ty,
t.a * x + t.c * y + t.tx,
t.b * x + t.d * y + t.ty,
smoothness
);
return this;
}
/**
* Closes the current path by drawing a straight line back to the start.
* If the shape is already closed or there are no points in the path, this method does nothing.
* @returns The instance of the current object for chaining.
*/
closePath() {
this._tick++;
this._activePath?.closePath();
return this;
}
/**
* Draws an ellipse at the specified location and with the given x and y radii.
* An optional transformation can be applied, allowing for rotation, scaling, and translation.
* @param x - The x-coordinate of the center of the ellipse.
* @param y - The y-coordinate of the center of the ellipse.
* @param radiusX - The horizontal radius of the ellipse.
* @param radiusY - The vertical radius of the ellipse.
* @returns The instance of the current object for chaining.
*/
ellipse(x, y, radiusX, radiusY) {
this._tick++;
this._activePath.ellipse(x, y, radiusX, radiusY, this._transform.clone());
return this;
}
/**
* Draws a circle shape. This method adds a new circle path to the current drawing.
* @param x - The x-coordinate of the center of the circle.
* @param y - The y-coordinate of the center of the circle.
* @param radius - The radius of the circle.
* @returns The instance of the current object for chaining.
*/
circle(x, y, radius) {
this._tick++;
this._activePath.circle(x, y, radius, this._transform.clone());
return this;
}
/**
* Adds another `GraphicsPath` to this path, optionally applying a transformation.
* @param path - The `GraphicsPath` to add.
* @returns The instance of the current object for chaining.
*/
path(path) {
this._tick++;
this._activePath.addPath(path, this._transform.clone());
return this;
}
/**
* Connects the current point to a new point with a straight line. This method updates the current path.
* @param x - The x-coordinate of the new point to connect to.
* @param y - The y-coordinate of the new point to connect to.
* @returns The instance of the current object for chaining.
*/
lineTo(x, y) {
this._tick++;
const t = this._transform;
this._activePath.lineTo(
t.a * x + t.c * y + t.tx,
t.b * x + t.d * y + t.ty
);
return this;
}
/**
* Sets the starting point for a new sub-path. Any subsequent drawing commands are considered part of this path.
* @param x - The x-coordinate for the starting point.
* @param y - The y-coordinate for the starting point.
* @returns The instance of the current object for chaining.
*/
moveTo(x, y) {
this._tick++;
const t = this._transform;
const instructions = this._activePath.instructions;
const transformedX = t.a * x + t.c * y + t.tx;
const transformedY = t.b * x + t.d * y + t.ty;
if (instructions.length === 1 && instructions[0].action === "moveTo") {
instructions[0].data[0] = transformedX;
instructions[0].data[1] = transformedY;
return this;
}
this._activePath.moveTo(
transformedX,
transformedY
);
return this;
}
/**
* Adds a quadratic curve to the path. It requires two points: the control point and the end point.
* The starting point is the last point in the current path.
* @param cpx - The x-coordinate of the control point.
* @param cpy - The y-coordinate of the control point.
* @param x - The x-coordinate of the end point.
* @param y - The y-coordinate of the end point.
* @param smoothness - Optional parameter to adjust the smoothness of the curve.
* @returns The instance of the current object for chaining.
*/
quadraticCurveTo(cpx, cpy, x, y, smoothness) {
this._tick++;
const t = this._transform;
this._activePath.quadraticCurveTo(
t.a * cpx + t.c * cpy + t.tx,
t.b * cpx + t.d * cpy + t.ty,
t.a * x + t.c * y + t.tx,
t.b * x + t.d * y + t.ty,
smoothness
);
return this;
}
/**
* Draws a rectangle shape. This method adds a new rectangle path to the current drawing.
* @param x - The x-coordinate of the top-left corner of the rectangle.
* @param y - The y-coordinate of the top-left corner of the rectangle.
* @param w - The width of the rectangle.
* @param h - The height of the rectangle.
* @returns The instance of the current object for chaining.
*/
rect(x, y, w, h) {
this._tick++;
this._activePath.rect(x, y, w, h, this._transform.clone());
return this;
}
/**
* Draws a rectangle with rounded corners.
* The corner radius can be specified to determine how rounded the corners should be.
* An optional transformation can be applied, which allows for rotation, scaling, and translation of the rectangle.
* @param x - The x-coordinate of the top-left corner of the rectangle.
* @param y - The y-coordinate of the top-left corner of the rectangle.
* @param w - The width of the rectangle.
* @param h - The height of the rectangle.
* @param radius - The radius of the rectangle's corners. If not specified, corners will be sharp.
* @returns The instance of the current object for chaining.
*/
roundRect(x, y, w, h, radius) {
this._tick++;
this._activePath.roundRect(x, y, w, h, radius, this._transform.clone());
return this;
}
/**
* Draws a polygon shape by specifying a sequence of points. This method allows for the creation of complex polygons,
* which can be both open and closed. An optional transformation can be applied, enabling the polygon to be scaled,
* rotated, or translated as needed.
* @param points - An array of numbers, or an array of PointData objects eg [{x,y}, {x,y}, {x,y}]
* representing the x and y coordinates, of the polygon's vertices, in sequence.
* @param close - A boolean indicating whether to close the polygon path. True by default.
*/
poly(points, close) {
this._tick++;
this._activePath.poly(points, close, this._transform.clone());
return this;
}
/**
* Draws a regular polygon with a specified number of sides. All sides and angles are equal.
* @param x - The x-coordinate of the center of the polygon.
* @param y - The y-coordinate of the center of the polygon.
* @param radius - The radius of the circumscribed circle of the polygon.
* @param sides - The number of sides of the polygon. Must be 3 or more.
* @param rotation - The rotation angle of the polygon, in radians. Zero by default.
* @param transform - An optional `Matrix` object to apply a transformation to the polygon.
* @returns The instance of the current object for chaining.
*/
regularPoly(x, y, radius, sides, rotation = 0, transform) {
this._tick++;
this._activePath.regularPoly(x, y, radius, sides, rotation, transform);
return this;
}
/**
* Draws a polygon with rounded corners.
* Similar to `regularPoly` but with the ability to round the corners of the polygon.
* @param x - The x-coordinate of the center of the polygon.
* @param y - The y-coordinate of the center of the polygon.
* @param radius - The radius of the circumscribed circle of the polygon.
* @param sides - The number of sides of the polygon. Must be 3 or more.
* @param corner - The radius of the rounding of the corners.
* @param rotation - The rotation angle of the polygon, in radians. Zero by default.
* @returns The instance of the current object for chaining.
*/
roundPoly(x, y, radius, sides, corner, rotation) {
this._tick++;
this._activePath.roundPoly(x, y, radius, sides, corner, rotation);
return this;
}
/**
* Draws a shape with rounded corners. This function supports custom radius for each corner of the shape.
* Optionally, corners can be rounded using a quadratic curve instead of an arc, providing a different aesthetic.
* @param points - An array of `RoundedPoint` representing the corners of the shape to draw.
* A minimum of 3 points is required.
* @param radius - The default radius for the corners.
* This radius is applied to all corners unless overridden in `points`.
* @param useQuadratic - If set to true, rounded corners are drawn using a quadraticCurve
* method instead of an arc method. Defaults to false.
* @param smoothness - Specifies the smoothness of the curve when `useQuadratic` is true.
* Higher values make the curve smoother.
* @returns The instance of the current object for chaining.
*/
roundShape(points, radius, useQuadratic, smoothness) {
this._tick++;
this._activePath.roundShape(points, radius, useQuadratic, smoothness);
return this;
}
/**
* Draw Rectangle with fillet corners. This is much like rounded rectangle
* however it support negative numbers as well for the corner radius.
* @param x - Upper left corner of rect
* @param y - Upper right corner of rect
* @param width - Width of rect
* @param height - Height of rect
* @param fillet - accept negative or positive values
*/
filletRect(x, y, width, height, fillet) {
this._tick++;
this._activePath.filletRect(x, y, width, height, fillet);
return this;
}
/**
* Draw Rectangle with chamfer corners. These are angled corners.
* @param x - Upper left corner of rect
* @param y - Upper right corner of rect
* @param width - Width of rect
* @param height - Height of rect
* @param chamfer - non-zero real number, size of corner cutout
* @param transform
*/
chamferRect(x, y, width, height, chamfer, transform) {
this._tick++;
this._activePath.chamferRect(x, y, width, height, chamfer, transform);
return this;
}
/**
* Draws a star shape centered at a specified location. This method allows for the creation
* of stars with a variable number of points, outer radius, optional inner radius, and rotation.
* The star is drawn as a closed polygon with alternating outer and inner vertices to create the star's points.
* An optional transformation can be applied to scale, rotate, or translate the star as needed.
* @param x - The x-coordinate of the center of the star.
* @param y - The y-coordinate of the center of the star.
* @param points - The number of points of the star.
* @param radius - The outer radius of the star (distance from the center to the outer points).
* @param innerRadius - Optional. The inner radius of the star
* (distance from the center to the inner points between the outer points).
* If not provided, defaults to half of the `radius`.
* @param rotation - Optional. The rotation of the star in radians, where 0 is aligned with the y-axis.
* Defaults to 0, meaning one point is directly upward.
* @returns The instance of the current object for chaining further drawing commands.
*/
star(x, y, points, radius, innerRadius = 0, rotation = 0) {
this._tick++;
this._activePath.star(x, y, points, radius, innerRadius, rotation, this._transform.clone());
return this;
}
/**
* Parses and renders an SVG string into the graphics context. This allows for complex shapes and paths
* defined in SVG format to be drawn within the graphics context.
* @param svg - The SVG string to be parsed and rendered.
*/
svg(svg) {
this._tick++;
SVGParser(svg, this);
return this;
}
/**
* Restores the most recently saved graphics state by popping the top of the graphics state stack.
* This includes transformations, fill styles, and stroke styles.
*/
restore() {
const state = this._stateStack.pop();
if (state) {
this._transform = state.transform;
this._fillStyle = state.fillStyle;
this._strokeStyle = state.strokeStyle;
}
return this;
}
/** Saves the current graphics state, including transformations, fill styles, and stroke styles, onto a stack. */
save() {
this._stateStack.push({
transform: this._transform.clone(),
fillStyle: { ...this._fillStyle },
strokeStyle: { ...this._strokeStyle }
});
return this;
}
/**
* Returns the current transformation matrix of the graphics context.
* @returns The current transformation matrix.
*/
getTransform() {
return this._transform;
}
/**
* Resets the current transformation matrix to the identity matrix, effectively removing any transformations (rotation, scaling, translation) previously applied.
* @returns The instance of the current GraphicsContext for method chaining.
*/
resetTransform() {
this._transform.identity();
return this;
}
/**
* Applies a rotation transformation to the graphics context around the current origin.
* @param angle - The angle of rotation in radians.
* @returns The instance of the current GraphicsContext for method chaining.
*/
rotate(angle) {
this._transform.rotate(angle);
return this;
}
/**
* Applies a scaling transformation to the graphics context, scaling drawings by x horizontally and by y vertically.
* @param x - The scale factor in the horizontal direction.
* @param y - (Optional) The scale factor in the vertical direction. If not specified, the x value is used for both directions.
* @returns The instance of the current GraphicsContext for method chaining.
*/
scale(x, y = x) {
this._transform.scale(x, y);
return this;
}
setTransform(a, b, c, d, dx, dy) {
if (a instanceof Matrix) {
this._transform.set(a.a, a.b, a.c, a.d, a.tx, a.ty);
return this;
}
this._transform.set(a, b, c, d, dx, dy);
return this;
}
transform(a, b, c, d, dx, dy) {
if (a instanceof Matrix) {
this._transform.append(a);
return this;
}
tempMatrix.set(a, b, c, d, dx, dy);
this._transform.append(tempMatrix);
return this;
}
/**
* Applies a translation transformation to the graphics context, moving the origin by the specified amounts.
* @param x - The amount to translate in the horizontal direction.
* @param y - (Optional) The amount to translate in the vertical direction. If not specified, the x value is used for both directions.
* @returns The instance of the current GraphicsContext for method chaining.
*/
translate(x, y = x) {
this._transform.translate(x, y);
return this;
}
/**
* Clears all drawing commands from the graphics context, effectively resetting it. This includes clearing the path,
* and optionally resetting transformations to the identity matrix.
* @returns The instance of the current GraphicsContext for method chaining.
*/
clear() {
this._activePath.clear();
this.instructions.length = 0;
this.resetTransform();
this.onUpdate();
return this;
}
onUpdate() {
if (this.dirty)
return;
this.emit("update", this, 16);
this.dirty = true;
this._boundsDirty = true;
}
/** The bounds of the graphic shape. */
get bounds() {
if (!this._boundsDirty)
return this._bounds;
const bounds = this._bounds;
bounds.clear();
for (let i = 0; i < this.instructions.length; i++) {
const instruction = this.instructions[i];
const action = instruction.action;
if (action === "fill") {
const data = instruction.data;
bounds.addBounds(data.path.bounds);
} else if (action === "texture") {
const data = instruction.data;
bounds.addFrame(data.dx, data.dy, data.dx + data.dw, data.dy + data.dh, data.transform);
}
if (action === "stroke") {
const data = instruction.data;
const padding = data.style.width / 2;
const _bounds = data.path.bounds;
bounds.addFrame(
_bounds.minX - padding,
_bounds.minY - padding,
_bounds.maxX + padding,
_bounds.maxY + padding
);
}
}
return bounds;
}
/**
* Check to see if a point is contained within this geometry.
* @param point - Point to check if it's contained.
* @returns {boolean} `true` if the point is contained within geometry.
*/
containsPoint(point) {
if (!this.bounds.containsPoint(point.x, point.y))
return false;
const instructions = this.instructions;
let hasHit = false;
for (let k = 0; k < instructions.length; k++) {
const instruction = instructions[k];
const data = instruction.data;
const path = data.path;
if (!instruction.action || !path)
continue;
const style = data.style;
const shapes = path.shapePath.shapePrimitives;
for (let i = 0; i < shapes.length; i++) {
const shape = shapes[i].shape;
if (!style || !shape)
continue;
const transform = shapes[i].transform;
const transformedPoint = transform ? transform.applyInverse(point, tmpPoint) : point;
if (instruction.action === "fill") {
hasHit = shape.contains(transformedPoint.x, transformedPoint.y);
} else {
hasHit = shape.strokeContains(transformedPoint.x, transformedPoint.y, style.width);
}
const holes = data.hole;
if (holes) {
const holeShapes = holes.shapePath?.shapePrimitives;
if (holeShapes) {
for (let j = 0; j < holeShapes.length; j++) {
if (holeShapes[j].shape.contains(transformedPoint.x, transformedPoint.y)) {
hasHit = false;
}
}
}
}
if (hasHit) {
return true;
}
}
}
return hasHit;
}
/**
* Destroys the GraphicsData object.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @param {boolean} [options.texture=false] - Should it destroy the current texture of the fill/stroke style?
* @param {boolean} [options.textureSource=false] - Should it destroy the texture source of the fill/stroke style?
*/
destroy(options = false) {
this._stateStack.length = 0;
this._transform = null;
this.emit("destroy", this);
this.removeAllListeners();
const destroyTexture = typeof options === "boolean" ? options : options?.texture;
if (destroyTexture) {
const destroyTextureSource = typeof options === "boolean" ? options : options?.textureSource;
if (this._fillStyle.texture) {
this._fillStyle.texture.destroy(destroyTextureSource);
}
if (this._strokeStyle.texture) {
this._strokeStyle.texture.destroy(destroyTextureSource);
}
}
this._fillStyle = null;
this._strokeStyle = null;
this.instructions = null;
this._activePath = null;
this._bounds = null;
this._stateStack = null;
this.customShader = null;
this._transform = null;
}
};
/** The default fill style to use when none is provided. */
_GraphicsContext.defaultFillStyle = {
/** The color to use for the fill. */
color: 16777215,
/** The alpha value to use for the fill. */
alpha: 1,
/** The texture to use for the fill. */
texture: Texture.WHITE,
/** The matrix to apply. */
matrix: null,
/** The fill pattern to use. */
fill: null
};
/** The default stroke style to use when none is provided. */
_GraphicsContext.defaultStrokeStyle = {
/** The width of the stroke. */
width: 1,
/** The color to use for the stroke. */
color: 16777215,
/** The alpha value to use for the stroke. */
alpha: 1,
/** The alignment of the stroke. */
alignment: 0.5,
/** The miter limit to use. */
miterLimit: 10,
/** The line cap style to use. */
cap: "butt",
/** The line join style to use. */
join: "miter",
/** The texture to use for the fill. */
texture: Texture.WHITE,
/** The matrix to apply. */
matrix: null,
/** The fill pattern to use. */
fill: null
};
let GraphicsContext = _GraphicsContext;
export { GraphicsContext };
//# sourceMappingURL=GraphicsContext.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,76 @@
import { ExtensionType } from '../../../extensions/Extensions';
import { InstructionSet } from '../../../rendering/renderers/shared/instructions/InstructionSet';
import type { Batcher } from '../../../rendering/batcher/shared/Batcher';
import type { System } from '../../../rendering/renderers/shared/system/System';
import type { BatchableGraphics } from './BatchableGraphics';
import type { GraphicsContext } from './GraphicsContext';
interface GeometryData {
vertices: number[];
uvs: number[];
indices: number[];
}
/**
* A class that holds batchable graphics data for a GraphicsContext.
* @memberof rendering
* @ignore
*/
export declare class GpuGraphicsContext {
isBatchable: boolean;
context: GraphicsContext;
batches: BatchableGraphics[];
geometryData: GeometryData;
graphicsData: GraphicsContextRenderData;
}
/**
* A class that holds the render data for a GraphicsContext.
* @memberof rendering
* @ignore
*/
export declare class GraphicsContextRenderData {
batcher: Batcher;
instructions: InstructionSet;
init(): void;
/**
* @deprecated since version 8.0.0
* Use `batcher.geometry` instead.
* @see {Batcher#geometry}
*/
get geometry(): import("../../..").Geometry;
}
/**
* Options for the GraphicsContextSystem.
* @memberof rendering
*/
export interface GraphicsContextSystemOptions {
/** A value from 0 to 1 that controls the smoothness of bezier curves (the higher the smoother) */
bezierSmoothness?: number;
}
/**
* A system that manages the rendering of GraphicsContexts.
* @memberof rendering
*/
export declare class GraphicsContextSystem implements System<GraphicsContextSystemOptions> {
/** @ignore */
static extension: {
readonly type: readonly [ExtensionType.WebGLSystem, ExtensionType.WebGPUSystem, ExtensionType.CanvasSystem];
readonly name: "graphicsContext";
};
/** The default options for the GraphicsContextSystem. */
static readonly defaultOptions: GraphicsContextSystemOptions;
private _gpuContextHash;
private _graphicsDataContextHash;
/**
* Runner init called, update the default options
* @ignore
*/
init(options?: GraphicsContextSystemOptions): void;
getContextRenderData(context: GraphicsContext): GraphicsContextRenderData;
updateGpuContext(context: GraphicsContext): GpuGraphicsContext;
getGpuContext(context: GraphicsContext): GpuGraphicsContext;
private _initContextRenderData;
private _initContext;
protected onGraphicsContextDestroy(context: GraphicsContext): void;
private _cleanGraphicsContextData;
destroy(): void;
}
export {};

View File

@@ -0,0 +1,165 @@
'use strict';
var Extensions = require('../../../extensions/Extensions.js');
var getTextureBatchBindGroup = require('../../../rendering/batcher/gpu/getTextureBatchBindGroup.js');
var DefaultBatcher = require('../../../rendering/batcher/shared/DefaultBatcher.js');
var InstructionSet = require('../../../rendering/renderers/shared/instructions/InstructionSet.js');
var deprecation = require('../../../utils/logging/deprecation.js');
var PoolGroup = require('../../../utils/pool/PoolGroup.js');
var buildContextBatches = require('./utils/buildContextBatches.js');
"use strict";
class GpuGraphicsContext {
constructor() {
this.batches = [];
this.geometryData = {
vertices: [],
uvs: [],
indices: []
};
}
}
class GraphicsContextRenderData {
constructor() {
this.batcher = new DefaultBatcher.DefaultBatcher();
this.instructions = new InstructionSet.InstructionSet();
}
init() {
this.instructions.reset();
}
/**
* @deprecated since version 8.0.0
* Use `batcher.geometry` instead.
* @see {Batcher#geometry}
*/
get geometry() {
deprecation.deprecation(deprecation.v8_3_4, "GraphicsContextRenderData#geometry is deprecated, please use batcher.geometry instead.");
return this.batcher.geometry;
}
}
const _GraphicsContextSystem = class _GraphicsContextSystem {
constructor() {
// the root context batches, used to either make a batch or geometry
// all graphics use this as a base
this._gpuContextHash = {};
// used for non-batchable graphics
this._graphicsDataContextHash = /* @__PURE__ */ Object.create(null);
}
/**
* Runner init called, update the default options
* @ignore
*/
init(options) {
_GraphicsContextSystem.defaultOptions.bezierSmoothness = options?.bezierSmoothness ?? _GraphicsContextSystem.defaultOptions.bezierSmoothness;
}
getContextRenderData(context) {
return this._graphicsDataContextHash[context.uid] || this._initContextRenderData(context);
}
// Context management functions
updateGpuContext(context) {
let gpuContext = this._gpuContextHash[context.uid] || this._initContext(context);
if (context.dirty) {
if (gpuContext) {
this._cleanGraphicsContextData(context);
} else {
gpuContext = this._initContext(context);
}
buildContextBatches.buildContextBatches(context, gpuContext);
const batchMode = context.batchMode;
if (context.customShader || batchMode === "no-batch") {
gpuContext.isBatchable = false;
} else if (batchMode === "auto") {
gpuContext.isBatchable = gpuContext.geometryData.vertices.length < 400;
}
context.dirty = false;
}
return gpuContext;
}
getGpuContext(context) {
return this._gpuContextHash[context.uid] || this._initContext(context);
}
_initContextRenderData(context) {
const graphicsData = PoolGroup.BigPool.get(GraphicsContextRenderData);
const { batches, geometryData } = this._gpuContextHash[context.uid];
const vertexSize = geometryData.vertices.length;
const indexSize = geometryData.indices.length;
for (let i = 0; i < batches.length; i++) {
batches[i].applyTransform = false;
}
const batcher = graphicsData.batcher;
batcher.ensureAttributeBuffer(vertexSize);
batcher.ensureIndexBuffer(indexSize);
batcher.begin();
for (let i = 0; i < batches.length; i++) {
const batch = batches[i];
batcher.add(batch);
}
batcher.finish(graphicsData.instructions);
const geometry = batcher.geometry;
geometry.indexBuffer.setDataWithSize(batcher.indexBuffer, batcher.indexSize, true);
geometry.buffers[0].setDataWithSize(batcher.attributeBuffer.float32View, batcher.attributeSize, true);
const drawBatches = batcher.batches;
for (let i = 0; i < drawBatches.length; i++) {
const batch = drawBatches[i];
batch.bindGroup = getTextureBatchBindGroup.getTextureBatchBindGroup(batch.textures.textures, batch.textures.count);
}
this._graphicsDataContextHash[context.uid] = graphicsData;
return graphicsData;
}
_initContext(context) {
const gpuContext = new GpuGraphicsContext();
gpuContext.context = context;
this._gpuContextHash[context.uid] = gpuContext;
context.on("destroy", this.onGraphicsContextDestroy, this);
return this._gpuContextHash[context.uid];
}
onGraphicsContextDestroy(context) {
this._cleanGraphicsContextData(context);
context.off("destroy", this.onGraphicsContextDestroy, this);
this._gpuContextHash[context.uid] = null;
}
_cleanGraphicsContextData(context) {
const gpuContext = this._gpuContextHash[context.uid];
if (!gpuContext.isBatchable) {
if (this._graphicsDataContextHash[context.uid]) {
PoolGroup.BigPool.return(this.getContextRenderData(context));
this._graphicsDataContextHash[context.uid] = null;
}
}
if (gpuContext.batches) {
gpuContext.batches.forEach((batch) => {
PoolGroup.BigPool.return(batch);
});
}
}
destroy() {
for (const i in this._gpuContextHash) {
if (this._gpuContextHash[i]) {
this.onGraphicsContextDestroy(this._gpuContextHash[i].context);
}
}
}
};
/** @ignore */
_GraphicsContextSystem.extension = {
type: [
Extensions.ExtensionType.WebGLSystem,
Extensions.ExtensionType.WebGPUSystem,
Extensions.ExtensionType.CanvasSystem
],
name: "graphicsContext"
};
/** The default options for the GraphicsContextSystem. */
_GraphicsContextSystem.defaultOptions = {
/**
* A value from 0 to 1 that controls the smoothness of bezier curves (the higher the smoother)
* @default 0.5
*/
bezierSmoothness: 0.5
};
let GraphicsContextSystem = _GraphicsContextSystem;
exports.GpuGraphicsContext = GpuGraphicsContext;
exports.GraphicsContextRenderData = GraphicsContextRenderData;
exports.GraphicsContextSystem = GraphicsContextSystem;
//# sourceMappingURL=GraphicsContextSystem.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,161 @@
import { ExtensionType } from '../../../extensions/Extensions.mjs';
import { getTextureBatchBindGroup } from '../../../rendering/batcher/gpu/getTextureBatchBindGroup.mjs';
import { DefaultBatcher } from '../../../rendering/batcher/shared/DefaultBatcher.mjs';
import { InstructionSet } from '../../../rendering/renderers/shared/instructions/InstructionSet.mjs';
import { deprecation, v8_3_4 } from '../../../utils/logging/deprecation.mjs';
import { BigPool } from '../../../utils/pool/PoolGroup.mjs';
import { buildContextBatches } from './utils/buildContextBatches.mjs';
"use strict";
class GpuGraphicsContext {
constructor() {
this.batches = [];
this.geometryData = {
vertices: [],
uvs: [],
indices: []
};
}
}
class GraphicsContextRenderData {
constructor() {
this.batcher = new DefaultBatcher();
this.instructions = new InstructionSet();
}
init() {
this.instructions.reset();
}
/**
* @deprecated since version 8.0.0
* Use `batcher.geometry` instead.
* @see {Batcher#geometry}
*/
get geometry() {
deprecation(v8_3_4, "GraphicsContextRenderData#geometry is deprecated, please use batcher.geometry instead.");
return this.batcher.geometry;
}
}
const _GraphicsContextSystem = class _GraphicsContextSystem {
constructor() {
// the root context batches, used to either make a batch or geometry
// all graphics use this as a base
this._gpuContextHash = {};
// used for non-batchable graphics
this._graphicsDataContextHash = /* @__PURE__ */ Object.create(null);
}
/**
* Runner init called, update the default options
* @ignore
*/
init(options) {
_GraphicsContextSystem.defaultOptions.bezierSmoothness = options?.bezierSmoothness ?? _GraphicsContextSystem.defaultOptions.bezierSmoothness;
}
getContextRenderData(context) {
return this._graphicsDataContextHash[context.uid] || this._initContextRenderData(context);
}
// Context management functions
updateGpuContext(context) {
let gpuContext = this._gpuContextHash[context.uid] || this._initContext(context);
if (context.dirty) {
if (gpuContext) {
this._cleanGraphicsContextData(context);
} else {
gpuContext = this._initContext(context);
}
buildContextBatches(context, gpuContext);
const batchMode = context.batchMode;
if (context.customShader || batchMode === "no-batch") {
gpuContext.isBatchable = false;
} else if (batchMode === "auto") {
gpuContext.isBatchable = gpuContext.geometryData.vertices.length < 400;
}
context.dirty = false;
}
return gpuContext;
}
getGpuContext(context) {
return this._gpuContextHash[context.uid] || this._initContext(context);
}
_initContextRenderData(context) {
const graphicsData = BigPool.get(GraphicsContextRenderData);
const { batches, geometryData } = this._gpuContextHash[context.uid];
const vertexSize = geometryData.vertices.length;
const indexSize = geometryData.indices.length;
for (let i = 0; i < batches.length; i++) {
batches[i].applyTransform = false;
}
const batcher = graphicsData.batcher;
batcher.ensureAttributeBuffer(vertexSize);
batcher.ensureIndexBuffer(indexSize);
batcher.begin();
for (let i = 0; i < batches.length; i++) {
const batch = batches[i];
batcher.add(batch);
}
batcher.finish(graphicsData.instructions);
const geometry = batcher.geometry;
geometry.indexBuffer.setDataWithSize(batcher.indexBuffer, batcher.indexSize, true);
geometry.buffers[0].setDataWithSize(batcher.attributeBuffer.float32View, batcher.attributeSize, true);
const drawBatches = batcher.batches;
for (let i = 0; i < drawBatches.length; i++) {
const batch = drawBatches[i];
batch.bindGroup = getTextureBatchBindGroup(batch.textures.textures, batch.textures.count);
}
this._graphicsDataContextHash[context.uid] = graphicsData;
return graphicsData;
}
_initContext(context) {
const gpuContext = new GpuGraphicsContext();
gpuContext.context = context;
this._gpuContextHash[context.uid] = gpuContext;
context.on("destroy", this.onGraphicsContextDestroy, this);
return this._gpuContextHash[context.uid];
}
onGraphicsContextDestroy(context) {
this._cleanGraphicsContextData(context);
context.off("destroy", this.onGraphicsContextDestroy, this);
this._gpuContextHash[context.uid] = null;
}
_cleanGraphicsContextData(context) {
const gpuContext = this._gpuContextHash[context.uid];
if (!gpuContext.isBatchable) {
if (this._graphicsDataContextHash[context.uid]) {
BigPool.return(this.getContextRenderData(context));
this._graphicsDataContextHash[context.uid] = null;
}
}
if (gpuContext.batches) {
gpuContext.batches.forEach((batch) => {
BigPool.return(batch);
});
}
}
destroy() {
for (const i in this._gpuContextHash) {
if (this._gpuContextHash[i]) {
this.onGraphicsContextDestroy(this._gpuContextHash[i].context);
}
}
}
};
/** @ignore */
_GraphicsContextSystem.extension = {
type: [
ExtensionType.WebGLSystem,
ExtensionType.WebGPUSystem,
ExtensionType.CanvasSystem
],
name: "graphicsContext"
};
/** The default options for the GraphicsContextSystem. */
_GraphicsContextSystem.defaultOptions = {
/**
* A value from 0 to 1 that controls the smoothness of bezier curves (the higher the smoother)
* @default 0.5
*/
bezierSmoothness: 0.5
};
let GraphicsContextSystem = _GraphicsContextSystem;
export { GpuGraphicsContext, GraphicsContextRenderData, GraphicsContextSystem };
//# sourceMappingURL=GraphicsContextSystem.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,44 @@
import { ExtensionType } from '../../../extensions/Extensions';
import { State } from '../../../rendering/renderers/shared/state/State';
import type { InstructionSet } from '../../../rendering/renderers/shared/instructions/InstructionSet';
import type { BatchPipe, RenderPipe } from '../../../rendering/renderers/shared/instructions/RenderPipe';
import type { Shader } from '../../../rendering/renderers/shared/shader/Shader';
import type { Graphics } from './Graphics';
import type { GraphicsContextSystem } from './GraphicsContextSystem';
export interface GraphicsAdaptor {
shader: Shader;
init(): void;
execute(graphicsPipe: GraphicsPipe, renderable: Graphics): void;
destroy(): void;
}
export interface GraphicsSystem {
graphicsContext: GraphicsContextSystem;
renderPipes: {
batch: BatchPipe;
};
_roundPixels: 0 | 1;
}
export declare class GraphicsPipe implements RenderPipe<Graphics> {
/** @ignore */
static extension: {
readonly type: readonly [ExtensionType.WebGLPipes, ExtensionType.WebGPUPipes, ExtensionType.CanvasPipes];
readonly name: "graphics";
};
renderer: GraphicsSystem;
state: State;
private _graphicsBatchesHash;
private _adaptor;
private readonly _destroyRenderableBound;
constructor(renderer: GraphicsSystem, adaptor: GraphicsAdaptor);
validateRenderable(graphics: Graphics): boolean;
addRenderable(graphics: Graphics, instructionSet: InstructionSet): void;
updateRenderable(graphics: Graphics): void;
destroyRenderable(graphics: Graphics): void;
execute(graphics: Graphics): void;
private _rebuild;
private _addToBatcher;
private _getBatchesForRenderable;
private _initBatchesForRenderable;
private _removeBatchForRenderable;
destroy(): void;
}

View File

@@ -0,0 +1,145 @@
'use strict';
var Extensions = require('../../../extensions/Extensions.js');
var State = require('../../../rendering/renderers/shared/state/State.js');
var PoolGroup = require('../../../utils/pool/PoolGroup.js');
var colorToUniform = require('../gpu/colorToUniform.js');
var BatchableGraphics = require('./BatchableGraphics.js');
"use strict";
class GraphicsPipe {
constructor(renderer, adaptor) {
this.state = State.State.for2d();
// batchable graphics list, used to render batches
this._graphicsBatchesHash = /* @__PURE__ */ Object.create(null);
this._destroyRenderableBound = this.destroyRenderable.bind(this);
this.renderer = renderer;
this._adaptor = adaptor;
this._adaptor.init();
}
validateRenderable(graphics) {
const context = graphics.context;
const wasBatched = !!this._graphicsBatchesHash[graphics.uid];
const gpuContext = this.renderer.graphicsContext.updateGpuContext(context);
if (gpuContext.isBatchable || wasBatched !== gpuContext.isBatchable) {
return true;
}
return false;
}
addRenderable(graphics, instructionSet) {
const gpuContext = this.renderer.graphicsContext.updateGpuContext(graphics.context);
if (graphics._didGraphicsUpdate) {
graphics._didGraphicsUpdate = false;
this._rebuild(graphics);
}
if (gpuContext.isBatchable) {
this._addToBatcher(graphics, instructionSet);
} else {
this.renderer.renderPipes.batch.break(instructionSet);
instructionSet.add(graphics);
}
}
updateRenderable(graphics) {
const batches = this._graphicsBatchesHash[graphics.uid];
if (batches) {
for (let i = 0; i < batches.length; i++) {
const batch = batches[i];
batch._batcher.updateElement(batch);
}
}
}
destroyRenderable(graphics) {
if (this._graphicsBatchesHash[graphics.uid]) {
this._removeBatchForRenderable(graphics.uid);
}
graphics.off("destroyed", this._destroyRenderableBound);
}
execute(graphics) {
if (!graphics.isRenderable)
return;
const renderer = this.renderer;
const context = graphics.context;
const contextSystem = renderer.graphicsContext;
if (!contextSystem.getGpuContext(context).batches.length) {
return;
}
const shader = context.customShader || this._adaptor.shader;
this.state.blendMode = graphics.groupBlendMode;
const localUniforms = shader.resources.localUniforms.uniforms;
localUniforms.uTransformMatrix = graphics.groupTransform;
localUniforms.uRound = renderer._roundPixels | graphics._roundPixels;
colorToUniform.color32BitToUniform(
graphics.groupColorAlpha,
localUniforms.uColor,
0
);
this._adaptor.execute(this, graphics);
}
_rebuild(graphics) {
const wasBatched = !!this._graphicsBatchesHash[graphics.uid];
const gpuContext = this.renderer.graphicsContext.updateGpuContext(graphics.context);
if (wasBatched) {
this._removeBatchForRenderable(graphics.uid);
}
if (gpuContext.isBatchable) {
this._initBatchesForRenderable(graphics);
}
graphics.batched = gpuContext.isBatchable;
}
_addToBatcher(graphics, instructionSet) {
const batchPipe = this.renderer.renderPipes.batch;
const batches = this._getBatchesForRenderable(graphics);
for (let i = 0; i < batches.length; i++) {
const batch = batches[i];
batchPipe.addToBatch(batch, instructionSet);
}
}
_getBatchesForRenderable(graphics) {
return this._graphicsBatchesHash[graphics.uid] || this._initBatchesForRenderable(graphics);
}
_initBatchesForRenderable(graphics) {
const context = graphics.context;
const gpuContext = this.renderer.graphicsContext.getGpuContext(context);
const roundPixels = this.renderer._roundPixels | graphics._roundPixels;
const batches = gpuContext.batches.map((batch) => {
const batchClone = PoolGroup.BigPool.get(BatchableGraphics.BatchableGraphics);
batch.copyTo(batchClone);
batchClone.renderable = graphics;
batchClone.roundPixels = roundPixels;
return batchClone;
});
if (this._graphicsBatchesHash[graphics.uid] === void 0) {
graphics.on("destroyed", this._destroyRenderableBound);
}
this._graphicsBatchesHash[graphics.uid] = batches;
return batches;
}
_removeBatchForRenderable(graphicsUid) {
this._graphicsBatchesHash[graphicsUid].forEach((batch) => {
PoolGroup.BigPool.return(batch);
});
this._graphicsBatchesHash[graphicsUid] = null;
}
destroy() {
this.renderer = null;
this._adaptor.destroy();
this._adaptor = null;
this.state = null;
for (const i in this._graphicsBatchesHash) {
this._removeBatchForRenderable(i);
}
this._graphicsBatchesHash = null;
}
}
/** @ignore */
GraphicsPipe.extension = {
type: [
Extensions.ExtensionType.WebGLPipes,
Extensions.ExtensionType.WebGPUPipes,
Extensions.ExtensionType.CanvasPipes
],
name: "graphics"
};
exports.GraphicsPipe = GraphicsPipe;
//# sourceMappingURL=GraphicsPipe.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,143 @@
import { ExtensionType } from '../../../extensions/Extensions.mjs';
import { State } from '../../../rendering/renderers/shared/state/State.mjs';
import { BigPool } from '../../../utils/pool/PoolGroup.mjs';
import { color32BitToUniform } from '../gpu/colorToUniform.mjs';
import { BatchableGraphics } from './BatchableGraphics.mjs';
"use strict";
class GraphicsPipe {
constructor(renderer, adaptor) {
this.state = State.for2d();
// batchable graphics list, used to render batches
this._graphicsBatchesHash = /* @__PURE__ */ Object.create(null);
this._destroyRenderableBound = this.destroyRenderable.bind(this);
this.renderer = renderer;
this._adaptor = adaptor;
this._adaptor.init();
}
validateRenderable(graphics) {
const context = graphics.context;
const wasBatched = !!this._graphicsBatchesHash[graphics.uid];
const gpuContext = this.renderer.graphicsContext.updateGpuContext(context);
if (gpuContext.isBatchable || wasBatched !== gpuContext.isBatchable) {
return true;
}
return false;
}
addRenderable(graphics, instructionSet) {
const gpuContext = this.renderer.graphicsContext.updateGpuContext(graphics.context);
if (graphics._didGraphicsUpdate) {
graphics._didGraphicsUpdate = false;
this._rebuild(graphics);
}
if (gpuContext.isBatchable) {
this._addToBatcher(graphics, instructionSet);
} else {
this.renderer.renderPipes.batch.break(instructionSet);
instructionSet.add(graphics);
}
}
updateRenderable(graphics) {
const batches = this._graphicsBatchesHash[graphics.uid];
if (batches) {
for (let i = 0; i < batches.length; i++) {
const batch = batches[i];
batch._batcher.updateElement(batch);
}
}
}
destroyRenderable(graphics) {
if (this._graphicsBatchesHash[graphics.uid]) {
this._removeBatchForRenderable(graphics.uid);
}
graphics.off("destroyed", this._destroyRenderableBound);
}
execute(graphics) {
if (!graphics.isRenderable)
return;
const renderer = this.renderer;
const context = graphics.context;
const contextSystem = renderer.graphicsContext;
if (!contextSystem.getGpuContext(context).batches.length) {
return;
}
const shader = context.customShader || this._adaptor.shader;
this.state.blendMode = graphics.groupBlendMode;
const localUniforms = shader.resources.localUniforms.uniforms;
localUniforms.uTransformMatrix = graphics.groupTransform;
localUniforms.uRound = renderer._roundPixels | graphics._roundPixels;
color32BitToUniform(
graphics.groupColorAlpha,
localUniforms.uColor,
0
);
this._adaptor.execute(this, graphics);
}
_rebuild(graphics) {
const wasBatched = !!this._graphicsBatchesHash[graphics.uid];
const gpuContext = this.renderer.graphicsContext.updateGpuContext(graphics.context);
if (wasBatched) {
this._removeBatchForRenderable(graphics.uid);
}
if (gpuContext.isBatchable) {
this._initBatchesForRenderable(graphics);
}
graphics.batched = gpuContext.isBatchable;
}
_addToBatcher(graphics, instructionSet) {
const batchPipe = this.renderer.renderPipes.batch;
const batches = this._getBatchesForRenderable(graphics);
for (let i = 0; i < batches.length; i++) {
const batch = batches[i];
batchPipe.addToBatch(batch, instructionSet);
}
}
_getBatchesForRenderable(graphics) {
return this._graphicsBatchesHash[graphics.uid] || this._initBatchesForRenderable(graphics);
}
_initBatchesForRenderable(graphics) {
const context = graphics.context;
const gpuContext = this.renderer.graphicsContext.getGpuContext(context);
const roundPixels = this.renderer._roundPixels | graphics._roundPixels;
const batches = gpuContext.batches.map((batch) => {
const batchClone = BigPool.get(BatchableGraphics);
batch.copyTo(batchClone);
batchClone.renderable = graphics;
batchClone.roundPixels = roundPixels;
return batchClone;
});
if (this._graphicsBatchesHash[graphics.uid] === void 0) {
graphics.on("destroyed", this._destroyRenderableBound);
}
this._graphicsBatchesHash[graphics.uid] = batches;
return batches;
}
_removeBatchForRenderable(graphicsUid) {
this._graphicsBatchesHash[graphicsUid].forEach((batch) => {
BigPool.return(batch);
});
this._graphicsBatchesHash[graphicsUid] = null;
}
destroy() {
this.renderer = null;
this._adaptor.destroy();
this._adaptor = null;
this.state = null;
for (const i in this._graphicsBatchesHash) {
this._removeBatchForRenderable(i);
}
this._graphicsBatchesHash = null;
}
}
/** @ignore */
GraphicsPipe.extension = {
type: [
ExtensionType.WebGLPipes,
ExtensionType.WebGPUPipes,
ExtensionType.CanvasPipes
],
name: "graphics"
};
export { GraphicsPipe };
//# sourceMappingURL=GraphicsPipe.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
import type { ExtensionMetadataDetails } from '../../../../extensions/Extensions';
import type { ShapePrimitive } from '../../../../maths/shapes/ShapePrimitive';
export interface ShapeBuildCommand<T extends ShapePrimitive = ShapePrimitive> {
extension: ExtensionMetadataDetails;
build(shape: T, points: number[]): void;
triangulate(points: number[], vertices: number[], verticesStride: number, verticesOffset: number, indices: number[], indicesOffset: number): void;
}

View File

@@ -0,0 +1,4 @@
'use strict';
"use strict";
//# sourceMappingURL=ShapeBuildCommand.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ShapeBuildCommand.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}

View File

@@ -0,0 +1,2 @@
"use strict";
//# sourceMappingURL=ShapeBuildCommand.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ShapeBuildCommand.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}

View File

@@ -0,0 +1 @@
export declare function buildAdaptiveBezier(points: number[], sX: number, sY: number, cp1x: number, cp1y: number, cp2x: number, cp2y: number, eX: number, eY: number, smoothness?: number): number[];

View File

@@ -0,0 +1,136 @@
'use strict';
var GraphicsContextSystem = require('../GraphicsContextSystem.js');
"use strict";
const RECURSION_LIMIT = 8;
const FLT_EPSILON = 11920929e-14;
const PATH_DISTANCE_EPSILON = 1;
const curveAngleToleranceEpsilon = 0.01;
const mAngleTolerance = 0;
const mCuspLimit = 0;
function buildAdaptiveBezier(points, sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, smoothness) {
const scale = 1;
const smoothing = Math.min(
0.99,
// a value of 1.0 actually inverts smoothing, so we cap it at 0.99
Math.max(0, smoothness ?? GraphicsContextSystem.GraphicsContextSystem.defaultOptions.bezierSmoothness)
);
let distanceTolerance = (PATH_DISTANCE_EPSILON - smoothing) / scale;
distanceTolerance *= distanceTolerance;
begin(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance);
return points;
}
function begin(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance) {
recursive(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance, 0);
points.push(eX, eY);
}
function recursive(x1, y1, x2, y2, x3, y3, x4, y4, points, distanceTolerance, level) {
if (level > RECURSION_LIMIT) {
return;
}
const pi = Math.PI;
const x12 = (x1 + x2) / 2;
const y12 = (y1 + y2) / 2;
const x23 = (x2 + x3) / 2;
const y23 = (y2 + y3) / 2;
const x34 = (x3 + x4) / 2;
const y34 = (y3 + y4) / 2;
const x123 = (x12 + x23) / 2;
const y123 = (y12 + y23) / 2;
const x234 = (x23 + x34) / 2;
const y234 = (y23 + y34) / 2;
const x1234 = (x123 + x234) / 2;
const y1234 = (y123 + y234) / 2;
if (level > 0) {
let dx = x4 - x1;
let dy = y4 - y1;
const d2 = Math.abs((x2 - x4) * dy - (y2 - y4) * dx);
const d3 = Math.abs((x3 - x4) * dy - (y3 - y4) * dx);
let da1;
let da2;
if (d2 > FLT_EPSILON && d3 > FLT_EPSILON) {
if ((d2 + d3) * (d2 + d3) <= distanceTolerance * (dx * dx + dy * dy)) {
if (mAngleTolerance < curveAngleToleranceEpsilon) {
points.push(x1234, y1234);
return;
}
const a23 = Math.atan2(y3 - y2, x3 - x2);
da1 = Math.abs(a23 - Math.atan2(y2 - y1, x2 - x1));
da2 = Math.abs(Math.atan2(y4 - y3, x4 - x3) - a23);
if (da1 >= pi)
da1 = 2 * pi - da1;
if (da2 >= pi)
da2 = 2 * pi - da2;
if (da1 + da2 < mAngleTolerance) {
points.push(x1234, y1234);
return;
}
if (mCuspLimit !== 0) {
if (da1 > mCuspLimit) {
points.push(x2, y2);
return;
}
if (da2 > mCuspLimit) {
points.push(x3, y3);
return;
}
}
}
} else if (d2 > FLT_EPSILON) {
if (d2 * d2 <= distanceTolerance * (dx * dx + dy * dy)) {
if (mAngleTolerance < curveAngleToleranceEpsilon) {
points.push(x1234, y1234);
return;
}
da1 = Math.abs(Math.atan2(y3 - y2, x3 - x2) - Math.atan2(y2 - y1, x2 - x1));
if (da1 >= pi)
da1 = 2 * pi - da1;
if (da1 < mAngleTolerance) {
points.push(x2, y2);
points.push(x3, y3);
return;
}
if (mCuspLimit !== 0) {
if (da1 > mCuspLimit) {
points.push(x2, y2);
return;
}
}
}
} else if (d3 > FLT_EPSILON) {
if (d3 * d3 <= distanceTolerance * (dx * dx + dy * dy)) {
if (mAngleTolerance < curveAngleToleranceEpsilon) {
points.push(x1234, y1234);
return;
}
da1 = Math.abs(Math.atan2(y4 - y3, x4 - x3) - Math.atan2(y3 - y2, x3 - x2));
if (da1 >= pi)
da1 = 2 * pi - da1;
if (da1 < mAngleTolerance) {
points.push(x2, y2);
points.push(x3, y3);
return;
}
if (mCuspLimit !== 0) {
if (da1 > mCuspLimit) {
points.push(x3, y3);
return;
}
}
}
} else {
dx = x1234 - (x1 + x4) / 2;
dy = y1234 - (y1 + y4) / 2;
if (dx * dx + dy * dy <= distanceTolerance) {
points.push(x1234, y1234);
return;
}
}
}
recursive(x1, y1, x12, y12, x123, y123, x1234, y1234, points, distanceTolerance, level + 1);
recursive(x1234, y1234, x234, y234, x34, y34, x4, y4, points, distanceTolerance, level + 1);
}
exports.buildAdaptiveBezier = buildAdaptiveBezier;
//# sourceMappingURL=buildAdaptiveBezier.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,134 @@
import { GraphicsContextSystem } from '../GraphicsContextSystem.mjs';
"use strict";
const RECURSION_LIMIT = 8;
const FLT_EPSILON = 11920929e-14;
const PATH_DISTANCE_EPSILON = 1;
const curveAngleToleranceEpsilon = 0.01;
const mAngleTolerance = 0;
const mCuspLimit = 0;
function buildAdaptiveBezier(points, sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, smoothness) {
const scale = 1;
const smoothing = Math.min(
0.99,
// a value of 1.0 actually inverts smoothing, so we cap it at 0.99
Math.max(0, smoothness ?? GraphicsContextSystem.defaultOptions.bezierSmoothness)
);
let distanceTolerance = (PATH_DISTANCE_EPSILON - smoothing) / scale;
distanceTolerance *= distanceTolerance;
begin(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance);
return points;
}
function begin(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance) {
recursive(sX, sY, cp1x, cp1y, cp2x, cp2y, eX, eY, points, distanceTolerance, 0);
points.push(eX, eY);
}
function recursive(x1, y1, x2, y2, x3, y3, x4, y4, points, distanceTolerance, level) {
if (level > RECURSION_LIMIT) {
return;
}
const pi = Math.PI;
const x12 = (x1 + x2) / 2;
const y12 = (y1 + y2) / 2;
const x23 = (x2 + x3) / 2;
const y23 = (y2 + y3) / 2;
const x34 = (x3 + x4) / 2;
const y34 = (y3 + y4) / 2;
const x123 = (x12 + x23) / 2;
const y123 = (y12 + y23) / 2;
const x234 = (x23 + x34) / 2;
const y234 = (y23 + y34) / 2;
const x1234 = (x123 + x234) / 2;
const y1234 = (y123 + y234) / 2;
if (level > 0) {
let dx = x4 - x1;
let dy = y4 - y1;
const d2 = Math.abs((x2 - x4) * dy - (y2 - y4) * dx);
const d3 = Math.abs((x3 - x4) * dy - (y3 - y4) * dx);
let da1;
let da2;
if (d2 > FLT_EPSILON && d3 > FLT_EPSILON) {
if ((d2 + d3) * (d2 + d3) <= distanceTolerance * (dx * dx + dy * dy)) {
if (mAngleTolerance < curveAngleToleranceEpsilon) {
points.push(x1234, y1234);
return;
}
const a23 = Math.atan2(y3 - y2, x3 - x2);
da1 = Math.abs(a23 - Math.atan2(y2 - y1, x2 - x1));
da2 = Math.abs(Math.atan2(y4 - y3, x4 - x3) - a23);
if (da1 >= pi)
da1 = 2 * pi - da1;
if (da2 >= pi)
da2 = 2 * pi - da2;
if (da1 + da2 < mAngleTolerance) {
points.push(x1234, y1234);
return;
}
if (mCuspLimit !== 0) {
if (da1 > mCuspLimit) {
points.push(x2, y2);
return;
}
if (da2 > mCuspLimit) {
points.push(x3, y3);
return;
}
}
}
} else if (d2 > FLT_EPSILON) {
if (d2 * d2 <= distanceTolerance * (dx * dx + dy * dy)) {
if (mAngleTolerance < curveAngleToleranceEpsilon) {
points.push(x1234, y1234);
return;
}
da1 = Math.abs(Math.atan2(y3 - y2, x3 - x2) - Math.atan2(y2 - y1, x2 - x1));
if (da1 >= pi)
da1 = 2 * pi - da1;
if (da1 < mAngleTolerance) {
points.push(x2, y2);
points.push(x3, y3);
return;
}
if (mCuspLimit !== 0) {
if (da1 > mCuspLimit) {
points.push(x2, y2);
return;
}
}
}
} else if (d3 > FLT_EPSILON) {
if (d3 * d3 <= distanceTolerance * (dx * dx + dy * dy)) {
if (mAngleTolerance < curveAngleToleranceEpsilon) {
points.push(x1234, y1234);
return;
}
da1 = Math.abs(Math.atan2(y4 - y3, x4 - x3) - Math.atan2(y3 - y2, x3 - x2));
if (da1 >= pi)
da1 = 2 * pi - da1;
if (da1 < mAngleTolerance) {
points.push(x2, y2);
points.push(x3, y3);
return;
}
if (mCuspLimit !== 0) {
if (da1 > mCuspLimit) {
points.push(x3, y3);
return;
}
}
}
} else {
dx = x1234 - (x1 + x4) / 2;
dy = y1234 - (y1 + y4) / 2;
if (dx * dx + dy * dy <= distanceTolerance) {
points.push(x1234, y1234);
return;
}
}
}
recursive(x1, y1, x12, y12, x123, y123, x1234, y1234, points, distanceTolerance, level + 1);
recursive(x1234, y1234, x234, y234, x34, y34, x4, y4, points, distanceTolerance, level + 1);
}
export { buildAdaptiveBezier };
//# sourceMappingURL=buildAdaptiveBezier.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
export declare function buildAdaptiveQuadratic(points: number[], sX: number, sY: number, cp1x: number, cp1y: number, eX: number, eY: number, smoothness?: number): number[];

View File

@@ -0,0 +1,68 @@
'use strict';
var GraphicsContextSystem = require('../GraphicsContextSystem.js');
"use strict";
const RECURSION_LIMIT = 8;
const FLT_EPSILON = 11920929e-14;
const PATH_DISTANCE_EPSILON = 1;
const curveAngleToleranceEpsilon = 0.01;
const mAngleTolerance = 0;
function buildAdaptiveQuadratic(points, sX, sY, cp1x, cp1y, eX, eY, smoothness) {
const scale = 1;
const smoothing = Math.min(
0.99,
// a value of 1.0 actually inverts smoothing, so we cap it at 0.99
Math.max(0, smoothness ?? GraphicsContextSystem.GraphicsContextSystem.defaultOptions.bezierSmoothness)
);
let distanceTolerance = (PATH_DISTANCE_EPSILON - smoothing) / scale;
distanceTolerance *= distanceTolerance;
begin(sX, sY, cp1x, cp1y, eX, eY, points, distanceTolerance);
return points;
}
function begin(sX, sY, cp1x, cp1y, eX, eY, points, distanceTolerance) {
recursive(points, sX, sY, cp1x, cp1y, eX, eY, distanceTolerance, 0);
points.push(eX, eY);
}
function recursive(points, x1, y1, x2, y2, x3, y3, distanceTolerance, level) {
if (level > RECURSION_LIMIT) {
return;
}
const pi = Math.PI;
const x12 = (x1 + x2) / 2;
const y12 = (y1 + y2) / 2;
const x23 = (x2 + x3) / 2;
const y23 = (y2 + y3) / 2;
const x123 = (x12 + x23) / 2;
const y123 = (y12 + y23) / 2;
let dx = x3 - x1;
let dy = y3 - y1;
const d = Math.abs((x2 - x3) * dy - (y2 - y3) * dx);
if (d > FLT_EPSILON) {
if (d * d <= distanceTolerance * (dx * dx + dy * dy)) {
if (mAngleTolerance < curveAngleToleranceEpsilon) {
points.push(x123, y123);
return;
}
let da = Math.abs(Math.atan2(y3 - y2, x3 - x2) - Math.atan2(y2 - y1, x2 - x1));
if (da >= pi)
da = 2 * pi - da;
if (da < mAngleTolerance) {
points.push(x123, y123);
return;
}
}
} else {
dx = x123 - (x1 + x3) / 2;
dy = y123 - (y1 + y3) / 2;
if (dx * dx + dy * dy <= distanceTolerance) {
points.push(x123, y123);
return;
}
}
recursive(points, x1, y1, x12, y12, x123, y123, distanceTolerance, level + 1);
recursive(points, x123, y123, x23, y23, x3, y3, distanceTolerance, level + 1);
}
exports.buildAdaptiveQuadratic = buildAdaptiveQuadratic;
//# sourceMappingURL=buildAdaptiveQuadratic.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,66 @@
import { GraphicsContextSystem } from '../GraphicsContextSystem.mjs';
"use strict";
const RECURSION_LIMIT = 8;
const FLT_EPSILON = 11920929e-14;
const PATH_DISTANCE_EPSILON = 1;
const curveAngleToleranceEpsilon = 0.01;
const mAngleTolerance = 0;
function buildAdaptiveQuadratic(points, sX, sY, cp1x, cp1y, eX, eY, smoothness) {
const scale = 1;
const smoothing = Math.min(
0.99,
// a value of 1.0 actually inverts smoothing, so we cap it at 0.99
Math.max(0, smoothness ?? GraphicsContextSystem.defaultOptions.bezierSmoothness)
);
let distanceTolerance = (PATH_DISTANCE_EPSILON - smoothing) / scale;
distanceTolerance *= distanceTolerance;
begin(sX, sY, cp1x, cp1y, eX, eY, points, distanceTolerance);
return points;
}
function begin(sX, sY, cp1x, cp1y, eX, eY, points, distanceTolerance) {
recursive(points, sX, sY, cp1x, cp1y, eX, eY, distanceTolerance, 0);
points.push(eX, eY);
}
function recursive(points, x1, y1, x2, y2, x3, y3, distanceTolerance, level) {
if (level > RECURSION_LIMIT) {
return;
}
const pi = Math.PI;
const x12 = (x1 + x2) / 2;
const y12 = (y1 + y2) / 2;
const x23 = (x2 + x3) / 2;
const y23 = (y2 + y3) / 2;
const x123 = (x12 + x23) / 2;
const y123 = (y12 + y23) / 2;
let dx = x3 - x1;
let dy = y3 - y1;
const d = Math.abs((x2 - x3) * dy - (y2 - y3) * dx);
if (d > FLT_EPSILON) {
if (d * d <= distanceTolerance * (dx * dx + dy * dy)) {
if (mAngleTolerance < curveAngleToleranceEpsilon) {
points.push(x123, y123);
return;
}
let da = Math.abs(Math.atan2(y3 - y2, x3 - x2) - Math.atan2(y2 - y1, x2 - x1));
if (da >= pi)
da = 2 * pi - da;
if (da < mAngleTolerance) {
points.push(x123, y123);
return;
}
}
} else {
dx = x123 - (x1 + x3) / 2;
dy = y123 - (y1 + y3) / 2;
if (dx * dx + dy * dy <= distanceTolerance) {
points.push(x123, y123);
return;
}
}
recursive(points, x1, y1, x12, y12, x123, y123, distanceTolerance, level + 1);
recursive(points, x123, y123, x23, y23, x3, y3, distanceTolerance, level + 1);
}
export { buildAdaptiveQuadratic };
//# sourceMappingURL=buildAdaptiveQuadratic.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
export declare function buildArc(points: number[], x: number, y: number, radius: number, start: number, end: number, clockwise: boolean, steps?: number): void;

View File

@@ -0,0 +1,27 @@
'use strict';
"use strict";
function buildArc(points, x, y, radius, start, end, clockwise, steps) {
let dist = Math.abs(start - end);
if (!clockwise && start > end) {
dist = 2 * Math.PI - dist;
} else if (clockwise && end > start) {
dist = 2 * Math.PI - dist;
}
steps = steps || Math.max(6, Math.floor(6 * Math.pow(radius, 1 / 3) * (dist / Math.PI)));
steps = Math.max(steps, 3);
let f = dist / steps;
let t = start;
f *= clockwise ? -1 : 1;
for (let i = 0; i < steps + 1; i++) {
const cs = Math.cos(t);
const sn = Math.sin(t);
const nx = x + cs * radius;
const ny = y + sn * radius;
points.push(nx, ny);
t += f;
}
}
exports.buildArc = buildArc;
//# sourceMappingURL=buildArc.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"buildArc.js","sources":["../../../../../src/scene/graphics/shared/buildCommands/buildArc.ts"],"sourcesContent":["export function buildArc(\n points: number[],\n x: number, y: number,\n radius: number,\n start: number,\n end: number,\n clockwise: boolean,\n steps?: number\n)\n{\n // determine distance between the two angles\n // ...probably a nicer way of writing this\n let dist = Math.abs(start - end);\n\n if (!clockwise && start > end)\n {\n dist = (2 * Math.PI) - dist;\n }\n else if (clockwise && end > start)\n {\n dist = (2 * Math.PI) - dist;\n }\n\n // approximate the # of steps using the cube root of the radius\n\n steps = steps || Math.max(6, Math.floor(6 * Math.pow(radius, 1 / 3) * (dist / (Math.PI))));\n\n // ensure we have at least 3 steps..\n steps = Math.max(steps, 3);\n\n let f = dist / (steps);\n let t = start;\n\n // modify direction\n f *= clockwise ? -1 : 1;\n\n for (let i = 0; i < steps + 1; i++)\n {\n const cs = Math.cos(t);\n const sn = Math.sin(t);\n\n const nx = x + (cs * radius);\n const ny = y + (sn * radius);\n\n points.push(nx, ny);\n\n t += f;\n }\n}\n"],"names":[],"mappings":";;;AAAgB,SAAA,QAAA,CACZ,QACA,CAAW,EAAA,CAAA,EACX,QACA,KACA,EAAA,GAAA,EACA,WACA,KAEJ,EAAA;AAGI,EAAA,IAAI,IAAO,GAAA,IAAA,CAAK,GAAI,CAAA,KAAA,GAAQ,GAAG,CAAA,CAAA;AAE/B,EAAI,IAAA,CAAC,SAAa,IAAA,KAAA,GAAQ,GAC1B,EAAA;AACI,IAAQ,IAAA,GAAA,CAAA,GAAI,KAAK,EAAM,GAAA,IAAA,CAAA;AAAA,GAC3B,MAAA,IACS,SAAa,IAAA,GAAA,GAAM,KAC5B,EAAA;AACI,IAAQ,IAAA,GAAA,CAAA,GAAI,KAAK,EAAM,GAAA,IAAA,CAAA;AAAA,GAC3B;AAIA,EAAA,KAAA,GAAQ,SAAS,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,IAAA,CAAK,MAAM,CAAI,GAAA,IAAA,CAAK,GAAI,CAAA,MAAA,EAAQ,IAAI,CAAC,CAAA,IAAK,IAAQ,GAAA,IAAA,CAAK,GAAI,CAAC,CAAA,CAAA;AAGzF,EAAQ,KAAA,GAAA,IAAA,CAAK,GAAI,CAAA,KAAA,EAAO,CAAC,CAAA,CAAA;AAEzB,EAAA,IAAI,IAAI,IAAQ,GAAA,KAAA,CAAA;AAChB,EAAA,IAAI,CAAI,GAAA,KAAA,CAAA;AAGR,EAAA,CAAA,IAAK,YAAY,CAAK,CAAA,GAAA,CAAA,CAAA;AAEtB,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,KAAA,GAAQ,GAAG,CAC/B,EAAA,EAAA;AACI,IAAM,MAAA,EAAA,GAAK,IAAK,CAAA,GAAA,CAAI,CAAC,CAAA,CAAA;AACrB,IAAM,MAAA,EAAA,GAAK,IAAK,CAAA,GAAA,CAAI,CAAC,CAAA,CAAA;AAErB,IAAM,MAAA,EAAA,GAAK,IAAK,EAAK,GAAA,MAAA,CAAA;AACrB,IAAM,MAAA,EAAA,GAAK,IAAK,EAAK,GAAA,MAAA,CAAA;AAErB,IAAO,MAAA,CAAA,IAAA,CAAK,IAAI,EAAE,CAAA,CAAA;AAElB,IAAK,CAAA,IAAA,CAAA,CAAA;AAAA,GACT;AACJ;;;;"}

View File

@@ -0,0 +1,25 @@
"use strict";
function buildArc(points, x, y, radius, start, end, clockwise, steps) {
let dist = Math.abs(start - end);
if (!clockwise && start > end) {
dist = 2 * Math.PI - dist;
} else if (clockwise && end > start) {
dist = 2 * Math.PI - dist;
}
steps = steps || Math.max(6, Math.floor(6 * Math.pow(radius, 1 / 3) * (dist / Math.PI)));
steps = Math.max(steps, 3);
let f = dist / steps;
let t = start;
f *= clockwise ? -1 : 1;
for (let i = 0; i < steps + 1; i++) {
const cs = Math.cos(t);
const sn = Math.sin(t);
const nx = x + cs * radius;
const ny = y + sn * radius;
points.push(nx, ny);
t += f;
}
}
export { buildArc };
//# sourceMappingURL=buildArc.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"buildArc.mjs","sources":["../../../../../src/scene/graphics/shared/buildCommands/buildArc.ts"],"sourcesContent":["export function buildArc(\n points: number[],\n x: number, y: number,\n radius: number,\n start: number,\n end: number,\n clockwise: boolean,\n steps?: number\n)\n{\n // determine distance between the two angles\n // ...probably a nicer way of writing this\n let dist = Math.abs(start - end);\n\n if (!clockwise && start > end)\n {\n dist = (2 * Math.PI) - dist;\n }\n else if (clockwise && end > start)\n {\n dist = (2 * Math.PI) - dist;\n }\n\n // approximate the # of steps using the cube root of the radius\n\n steps = steps || Math.max(6, Math.floor(6 * Math.pow(radius, 1 / 3) * (dist / (Math.PI))));\n\n // ensure we have at least 3 steps..\n steps = Math.max(steps, 3);\n\n let f = dist / (steps);\n let t = start;\n\n // modify direction\n f *= clockwise ? -1 : 1;\n\n for (let i = 0; i < steps + 1; i++)\n {\n const cs = Math.cos(t);\n const sn = Math.sin(t);\n\n const nx = x + (cs * radius);\n const ny = y + (sn * radius);\n\n points.push(nx, ny);\n\n t += f;\n }\n}\n"],"names":[],"mappings":";AAAgB,SAAA,QAAA,CACZ,QACA,CAAW,EAAA,CAAA,EACX,QACA,KACA,EAAA,GAAA,EACA,WACA,KAEJ,EAAA;AAGI,EAAA,IAAI,IAAO,GAAA,IAAA,CAAK,GAAI,CAAA,KAAA,GAAQ,GAAG,CAAA,CAAA;AAE/B,EAAI,IAAA,CAAC,SAAa,IAAA,KAAA,GAAQ,GAC1B,EAAA;AACI,IAAQ,IAAA,GAAA,CAAA,GAAI,KAAK,EAAM,GAAA,IAAA,CAAA;AAAA,GAC3B,MAAA,IACS,SAAa,IAAA,GAAA,GAAM,KAC5B,EAAA;AACI,IAAQ,IAAA,GAAA,CAAA,GAAI,KAAK,EAAM,GAAA,IAAA,CAAA;AAAA,GAC3B;AAIA,EAAA,KAAA,GAAQ,SAAS,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,IAAA,CAAK,MAAM,CAAI,GAAA,IAAA,CAAK,GAAI,CAAA,MAAA,EAAQ,IAAI,CAAC,CAAA,IAAK,IAAQ,GAAA,IAAA,CAAK,GAAI,CAAC,CAAA,CAAA;AAGzF,EAAQ,KAAA,GAAA,IAAA,CAAK,GAAI,CAAA,KAAA,EAAO,CAAC,CAAA,CAAA;AAEzB,EAAA,IAAI,IAAI,IAAQ,GAAA,KAAA,CAAA;AAChB,EAAA,IAAI,CAAI,GAAA,KAAA,CAAA;AAGR,EAAA,CAAA,IAAK,YAAY,CAAK,CAAA,GAAA,CAAA,CAAA;AAEtB,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,KAAA,GAAQ,GAAG,CAC/B,EAAA,EAAA;AACI,IAAM,MAAA,EAAA,GAAK,IAAK,CAAA,GAAA,CAAI,CAAC,CAAA,CAAA;AACrB,IAAM,MAAA,EAAA,GAAK,IAAK,CAAA,GAAA,CAAI,CAAC,CAAA,CAAA;AAErB,IAAM,MAAA,EAAA,GAAK,IAAK,EAAK,GAAA,MAAA,CAAA;AACrB,IAAM,MAAA,EAAA,GAAK,IAAK,EAAK,GAAA,MAAA,CAAA;AAErB,IAAO,MAAA,CAAA,IAAA,CAAK,IAAI,EAAE,CAAA,CAAA;AAElB,IAAK,CAAA,IAAA,CAAA,CAAA;AAAA,GACT;AACJ;;;;"}

View File

@@ -0,0 +1,12 @@
/**
* The arcTo() method creates an arc/curve between two tangents on the canvas.
*
* "borrowed" from https://code.google.com/p/fxcanvas/ - thanks google!
* @param points
* @param x1
* @param y1
* @param x2
* @param y2
* @param radius
*/
export declare function buildArcTo(points: number[], x1: number, y1: number, x2: number, y2: number, radius: number): void;

View File

@@ -0,0 +1,47 @@
'use strict';
var buildArc = require('./buildArc.js');
"use strict";
function buildArcTo(points, x1, y1, x2, y2, radius) {
const fromX = points[points.length - 2];
const fromY = points[points.length - 1];
const a1 = fromY - y1;
const b1 = fromX - x1;
const a2 = y2 - y1;
const b2 = x2 - x1;
const mm = Math.abs(a1 * b2 - b1 * a2);
if (mm < 1e-8 || radius === 0) {
if (points[points.length - 2] !== x1 || points[points.length - 1] !== y1) {
points.push(x1, y1);
}
return;
}
const dd = a1 * a1 + b1 * b1;
const cc = a2 * a2 + b2 * b2;
const tt = a1 * a2 + b1 * b2;
const k1 = radius * Math.sqrt(dd) / mm;
const k2 = radius * Math.sqrt(cc) / mm;
const j1 = k1 * tt / dd;
const j2 = k2 * tt / cc;
const cx = k1 * b2 + k2 * b1;
const cy = k1 * a2 + k2 * a1;
const px = b1 * (k2 + j1);
const py = a1 * (k2 + j1);
const qx = b2 * (k1 + j2);
const qy = a2 * (k1 + j2);
const startAngle = Math.atan2(py - cy, px - cx);
const endAngle = Math.atan2(qy - cy, qx - cx);
buildArc.buildArc(
points,
cx + x1,
cy + y1,
radius,
startAngle,
endAngle,
b1 * a2 > b2 * a1
);
}
exports.buildArcTo = buildArcTo;
//# sourceMappingURL=buildArcTo.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"buildArcTo.js","sources":["../../../../../src/scene/graphics/shared/buildCommands/buildArcTo.ts"],"sourcesContent":["import { buildArc } from './buildArc';\n\n/**\n * The arcTo() method creates an arc/curve between two tangents on the canvas.\n *\n * \"borrowed\" from https://code.google.com/p/fxcanvas/ - thanks google!\n * @param points\n * @param x1\n * @param y1\n * @param x2\n * @param y2\n * @param radius\n */\nexport function buildArcTo(\n points: number[],\n x1: number, y1: number,\n x2: number, y2: number,\n radius: number,\n): void\n{\n const fromX = points[points.length - 2];\n const fromY = points[points.length - 1];\n\n const a1 = fromY - y1;\n const b1 = fromX - x1;\n const a2 = y2 - y1;\n const b2 = x2 - x1;\n const mm = Math.abs((a1 * b2) - (b1 * a2));\n\n if (mm < 1.0e-8 || radius === 0)\n {\n if (points[points.length - 2] !== x1 || points[points.length - 1] !== y1)\n {\n points.push(x1, y1);\n }\n\n return;\n }\n\n const dd = (a1 * a1) + (b1 * b1);\n const cc = (a2 * a2) + (b2 * b2);\n const tt = (a1 * a2) + (b1 * b2);\n const k1 = radius * Math.sqrt(dd) / mm;\n const k2 = radius * Math.sqrt(cc) / mm;\n const j1 = k1 * tt / dd;\n const j2 = k2 * tt / cc;\n const cx = (k1 * b2) + (k2 * b1);\n const cy = (k1 * a2) + (k2 * a1);\n const px = b1 * (k2 + j1);\n const py = a1 * (k2 + j1);\n const qx = b2 * (k1 + j2);\n const qy = a2 * (k1 + j2);\n const startAngle = Math.atan2(py - cy, px - cx);\n const endAngle = Math.atan2(qy - cy, qx - cx);\n\n buildArc(points,\n (cx + x1),\n (cy + y1),\n radius,\n startAngle,\n endAngle,\n b1 * a2 > b2 * a1\n );\n}\n"],"names":["buildArc"],"mappings":";;;;;AAaO,SAAS,WACZ,MACA,EAAA,EAAA,EAAY,EACZ,EAAA,EAAA,EAAY,IACZ,MAEJ,EAAA;AACI,EAAA,MAAM,KAAQ,GAAA,MAAA,CAAO,MAAO,CAAA,MAAA,GAAS,CAAC,CAAA,CAAA;AACtC,EAAA,MAAM,KAAQ,GAAA,MAAA,CAAO,MAAO,CAAA,MAAA,GAAS,CAAC,CAAA,CAAA;AAEtC,EAAA,MAAM,KAAK,KAAQ,GAAA,EAAA,CAAA;AACnB,EAAA,MAAM,KAAK,KAAQ,GAAA,EAAA,CAAA;AACnB,EAAA,MAAM,KAAK,EAAK,GAAA,EAAA,CAAA;AAChB,EAAA,MAAM,KAAK,EAAK,GAAA,EAAA,CAAA;AAChB,EAAA,MAAM,KAAK,IAAK,CAAA,GAAA,CAAK,EAAK,GAAA,EAAA,GAAO,KAAK,EAAG,CAAA,CAAA;AAEzC,EAAI,IAAA,EAAA,GAAK,IAAU,IAAA,MAAA,KAAW,CAC9B,EAAA;AACI,IAAI,IAAA,MAAA,CAAO,MAAO,CAAA,MAAA,GAAS,CAAC,CAAA,KAAM,EAAM,IAAA,MAAA,CAAO,MAAO,CAAA,MAAA,GAAS,CAAC,CAAA,KAAM,EACtE,EAAA;AACI,MAAO,MAAA,CAAA,IAAA,CAAK,IAAI,EAAE,CAAA,CAAA;AAAA,KACtB;AAEA,IAAA,OAAA;AAAA,GACJ;AAEA,EAAM,MAAA,EAAA,GAAM,EAAK,GAAA,EAAA,GAAO,EAAK,GAAA,EAAA,CAAA;AAC7B,EAAM,MAAA,EAAA,GAAM,EAAK,GAAA,EAAA,GAAO,EAAK,GAAA,EAAA,CAAA;AAC7B,EAAM,MAAA,EAAA,GAAM,EAAK,GAAA,EAAA,GAAO,EAAK,GAAA,EAAA,CAAA;AAC7B,EAAA,MAAM,EAAK,GAAA,MAAA,GAAS,IAAK,CAAA,IAAA,CAAK,EAAE,CAAI,GAAA,EAAA,CAAA;AACpC,EAAA,MAAM,EAAK,GAAA,MAAA,GAAS,IAAK,CAAA,IAAA,CAAK,EAAE,CAAI,GAAA,EAAA,CAAA;AACpC,EAAM,MAAA,EAAA,GAAK,KAAK,EAAK,GAAA,EAAA,CAAA;AACrB,EAAM,MAAA,EAAA,GAAK,KAAK,EAAK,GAAA,EAAA,CAAA;AACrB,EAAM,MAAA,EAAA,GAAM,EAAK,GAAA,EAAA,GAAO,EAAK,GAAA,EAAA,CAAA;AAC7B,EAAM,MAAA,EAAA,GAAM,EAAK,GAAA,EAAA,GAAO,EAAK,GAAA,EAAA,CAAA;AAC7B,EAAM,MAAA,EAAA,GAAK,MAAM,EAAK,GAAA,EAAA,CAAA,CAAA;AACtB,EAAM,MAAA,EAAA,GAAK,MAAM,EAAK,GAAA,EAAA,CAAA,CAAA;AACtB,EAAM,MAAA,EAAA,GAAK,MAAM,EAAK,GAAA,EAAA,CAAA,CAAA;AACtB,EAAM,MAAA,EAAA,GAAK,MAAM,EAAK,GAAA,EAAA,CAAA,CAAA;AACtB,EAAA,MAAM,aAAa,IAAK,CAAA,KAAA,CAAM,EAAK,GAAA,EAAA,EAAI,KAAK,EAAE,CAAA,CAAA;AAC9C,EAAA,MAAM,WAAW,IAAK,CAAA,KAAA,CAAM,EAAK,GAAA,EAAA,EAAI,KAAK,EAAE,CAAA,CAAA;AAE5C,EAAAA,iBAAA;AAAA,IAAS,MAAA;AAAA,IACJ,EAAK,GAAA,EAAA;AAAA,IACL,EAAK,GAAA,EAAA;AAAA,IACN,MAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,EAAA,GAAK,KAAK,EAAK,GAAA,EAAA;AAAA,GACnB,CAAA;AACJ;;;;"}

View File

@@ -0,0 +1,45 @@
import { buildArc } from './buildArc.mjs';
"use strict";
function buildArcTo(points, x1, y1, x2, y2, radius) {
const fromX = points[points.length - 2];
const fromY = points[points.length - 1];
const a1 = fromY - y1;
const b1 = fromX - x1;
const a2 = y2 - y1;
const b2 = x2 - x1;
const mm = Math.abs(a1 * b2 - b1 * a2);
if (mm < 1e-8 || radius === 0) {
if (points[points.length - 2] !== x1 || points[points.length - 1] !== y1) {
points.push(x1, y1);
}
return;
}
const dd = a1 * a1 + b1 * b1;
const cc = a2 * a2 + b2 * b2;
const tt = a1 * a2 + b1 * b2;
const k1 = radius * Math.sqrt(dd) / mm;
const k2 = radius * Math.sqrt(cc) / mm;
const j1 = k1 * tt / dd;
const j2 = k2 * tt / cc;
const cx = k1 * b2 + k2 * b1;
const cy = k1 * a2 + k2 * a1;
const px = b1 * (k2 + j1);
const py = a1 * (k2 + j1);
const qx = b2 * (k1 + j2);
const qy = a2 * (k1 + j2);
const startAngle = Math.atan2(py - cy, px - cx);
const endAngle = Math.atan2(qy - cy, qx - cx);
buildArc(
points,
cx + x1,
cy + y1,
radius,
startAngle,
endAngle,
b1 * a2 > b2 * a1
);
}
export { buildArcTo };
//# sourceMappingURL=buildArcTo.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"buildArcTo.mjs","sources":["../../../../../src/scene/graphics/shared/buildCommands/buildArcTo.ts"],"sourcesContent":["import { buildArc } from './buildArc';\n\n/**\n * The arcTo() method creates an arc/curve between two tangents on the canvas.\n *\n * \"borrowed\" from https://code.google.com/p/fxcanvas/ - thanks google!\n * @param points\n * @param x1\n * @param y1\n * @param x2\n * @param y2\n * @param radius\n */\nexport function buildArcTo(\n points: number[],\n x1: number, y1: number,\n x2: number, y2: number,\n radius: number,\n): void\n{\n const fromX = points[points.length - 2];\n const fromY = points[points.length - 1];\n\n const a1 = fromY - y1;\n const b1 = fromX - x1;\n const a2 = y2 - y1;\n const b2 = x2 - x1;\n const mm = Math.abs((a1 * b2) - (b1 * a2));\n\n if (mm < 1.0e-8 || radius === 0)\n {\n if (points[points.length - 2] !== x1 || points[points.length - 1] !== y1)\n {\n points.push(x1, y1);\n }\n\n return;\n }\n\n const dd = (a1 * a1) + (b1 * b1);\n const cc = (a2 * a2) + (b2 * b2);\n const tt = (a1 * a2) + (b1 * b2);\n const k1 = radius * Math.sqrt(dd) / mm;\n const k2 = radius * Math.sqrt(cc) / mm;\n const j1 = k1 * tt / dd;\n const j2 = k2 * tt / cc;\n const cx = (k1 * b2) + (k2 * b1);\n const cy = (k1 * a2) + (k2 * a1);\n const px = b1 * (k2 + j1);\n const py = a1 * (k2 + j1);\n const qx = b2 * (k1 + j2);\n const qy = a2 * (k1 + j2);\n const startAngle = Math.atan2(py - cy, px - cx);\n const endAngle = Math.atan2(qy - cy, qx - cx);\n\n buildArc(points,\n (cx + x1),\n (cy + y1),\n radius,\n startAngle,\n endAngle,\n b1 * a2 > b2 * a1\n );\n}\n"],"names":[],"mappings":";;;AAaO,SAAS,WACZ,MACA,EAAA,EAAA,EAAY,EACZ,EAAA,EAAA,EAAY,IACZ,MAEJ,EAAA;AACI,EAAA,MAAM,KAAQ,GAAA,MAAA,CAAO,MAAO,CAAA,MAAA,GAAS,CAAC,CAAA,CAAA;AACtC,EAAA,MAAM,KAAQ,GAAA,MAAA,CAAO,MAAO,CAAA,MAAA,GAAS,CAAC,CAAA,CAAA;AAEtC,EAAA,MAAM,KAAK,KAAQ,GAAA,EAAA,CAAA;AACnB,EAAA,MAAM,KAAK,KAAQ,GAAA,EAAA,CAAA;AACnB,EAAA,MAAM,KAAK,EAAK,GAAA,EAAA,CAAA;AAChB,EAAA,MAAM,KAAK,EAAK,GAAA,EAAA,CAAA;AAChB,EAAA,MAAM,KAAK,IAAK,CAAA,GAAA,CAAK,EAAK,GAAA,EAAA,GAAO,KAAK,EAAG,CAAA,CAAA;AAEzC,EAAI,IAAA,EAAA,GAAK,IAAU,IAAA,MAAA,KAAW,CAC9B,EAAA;AACI,IAAI,IAAA,MAAA,CAAO,MAAO,CAAA,MAAA,GAAS,CAAC,CAAA,KAAM,EAAM,IAAA,MAAA,CAAO,MAAO,CAAA,MAAA,GAAS,CAAC,CAAA,KAAM,EACtE,EAAA;AACI,MAAO,MAAA,CAAA,IAAA,CAAK,IAAI,EAAE,CAAA,CAAA;AAAA,KACtB;AAEA,IAAA,OAAA;AAAA,GACJ;AAEA,EAAM,MAAA,EAAA,GAAM,EAAK,GAAA,EAAA,GAAO,EAAK,GAAA,EAAA,CAAA;AAC7B,EAAM,MAAA,EAAA,GAAM,EAAK,GAAA,EAAA,GAAO,EAAK,GAAA,EAAA,CAAA;AAC7B,EAAM,MAAA,EAAA,GAAM,EAAK,GAAA,EAAA,GAAO,EAAK,GAAA,EAAA,CAAA;AAC7B,EAAA,MAAM,EAAK,GAAA,MAAA,GAAS,IAAK,CAAA,IAAA,CAAK,EAAE,CAAI,GAAA,EAAA,CAAA;AACpC,EAAA,MAAM,EAAK,GAAA,MAAA,GAAS,IAAK,CAAA,IAAA,CAAK,EAAE,CAAI,GAAA,EAAA,CAAA;AACpC,EAAM,MAAA,EAAA,GAAK,KAAK,EAAK,GAAA,EAAA,CAAA;AACrB,EAAM,MAAA,EAAA,GAAK,KAAK,EAAK,GAAA,EAAA,CAAA;AACrB,EAAM,MAAA,EAAA,GAAM,EAAK,GAAA,EAAA,GAAO,EAAK,GAAA,EAAA,CAAA;AAC7B,EAAM,MAAA,EAAA,GAAM,EAAK,GAAA,EAAA,GAAO,EAAK,GAAA,EAAA,CAAA;AAC7B,EAAM,MAAA,EAAA,GAAK,MAAM,EAAK,GAAA,EAAA,CAAA,CAAA;AACtB,EAAM,MAAA,EAAA,GAAK,MAAM,EAAK,GAAA,EAAA,CAAA,CAAA;AACtB,EAAM,MAAA,EAAA,GAAK,MAAM,EAAK,GAAA,EAAA,CAAA,CAAA;AACtB,EAAM,MAAA,EAAA,GAAK,MAAM,EAAK,GAAA,EAAA,CAAA,CAAA;AACtB,EAAA,MAAM,aAAa,IAAK,CAAA,KAAA,CAAM,EAAK,GAAA,EAAA,EAAI,KAAK,EAAE,CAAA,CAAA;AAC9C,EAAA,MAAM,WAAW,IAAK,CAAA,KAAA,CAAM,EAAK,GAAA,EAAA,EAAI,KAAK,EAAE,CAAA,CAAA;AAE5C,EAAA,QAAA;AAAA,IAAS,MAAA;AAAA,IACJ,EAAK,GAAA,EAAA;AAAA,IACL,EAAK,GAAA,EAAA;AAAA,IACN,MAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,EAAA,GAAK,KAAK,EAAK,GAAA,EAAA;AAAA,GACnB,CAAA;AACJ;;;;"}

View File

@@ -0,0 +1 @@
export declare function buildArcToSvg(points: number[], px: number, py: number, cx: number, cy: number, rx: number, ry: number, xAxisRotation?: number, largeArcFlag?: number, sweepFlag?: number): void;

View File

@@ -0,0 +1,154 @@
'use strict';
var buildAdaptiveBezier = require('./buildAdaptiveBezier.js');
"use strict";
const TAU = Math.PI * 2;
const out = {
centerX: 0,
centerY: 0,
ang1: 0,
ang2: 0
};
const mapToEllipse = ({ x, y }, rx, ry, cosPhi, sinPhi, centerX, centerY, out2) => {
x *= rx;
y *= ry;
const xp = cosPhi * x - sinPhi * y;
const yp = sinPhi * x + cosPhi * y;
out2.x = xp + centerX;
out2.y = yp + centerY;
return out2;
};
function approxUnitArc(ang1, ang2) {
const a1 = ang2 === -1.5707963267948966 ? -0.551915024494 : 4 / 3 * Math.tan(ang2 / 4);
const a = ang2 === 1.5707963267948966 ? 0.551915024494 : a1;
const x1 = Math.cos(ang1);
const y1 = Math.sin(ang1);
const x2 = Math.cos(ang1 + ang2);
const y2 = Math.sin(ang1 + ang2);
return [
{
x: x1 - y1 * a,
y: y1 + x1 * a
},
{
x: x2 + y2 * a,
y: y2 - x2 * a
},
{
x: x2,
y: y2
}
];
}
const vectorAngle = (ux, uy, vx, vy) => {
const sign = ux * vy - uy * vx < 0 ? -1 : 1;
let dot = ux * vx + uy * vy;
if (dot > 1) {
dot = 1;
}
if (dot < -1) {
dot = -1;
}
return sign * Math.acos(dot);
};
const getArcCenter = (px, py, cx, cy, rx, ry, largeArcFlag, sweepFlag, sinPhi, cosPhi, pxp, pyp, out2) => {
const rxSq = Math.pow(rx, 2);
const rySq = Math.pow(ry, 2);
const pxpSq = Math.pow(pxp, 2);
const pypSq = Math.pow(pyp, 2);
let radicant = rxSq * rySq - rxSq * pypSq - rySq * pxpSq;
if (radicant < 0) {
radicant = 0;
}
radicant /= rxSq * pypSq + rySq * pxpSq;
radicant = Math.sqrt(radicant) * (largeArcFlag === sweepFlag ? -1 : 1);
const centerXp = radicant * rx / ry * pyp;
const centerYp = radicant * -ry / rx * pxp;
const centerX = cosPhi * centerXp - sinPhi * centerYp + (px + cx) / 2;
const centerY = sinPhi * centerXp + cosPhi * centerYp + (py + cy) / 2;
const vx1 = (pxp - centerXp) / rx;
const vy1 = (pyp - centerYp) / ry;
const vx2 = (-pxp - centerXp) / rx;
const vy2 = (-pyp - centerYp) / ry;
const ang1 = vectorAngle(1, 0, vx1, vy1);
let ang2 = vectorAngle(vx1, vy1, vx2, vy2);
if (sweepFlag === 0 && ang2 > 0) {
ang2 -= TAU;
}
if (sweepFlag === 1 && ang2 < 0) {
ang2 += TAU;
}
out2.centerX = centerX;
out2.centerY = centerY;
out2.ang1 = ang1;
out2.ang2 = ang2;
};
function buildArcToSvg(points, px, py, cx, cy, rx, ry, xAxisRotation = 0, largeArcFlag = 0, sweepFlag = 0) {
if (rx === 0 || ry === 0) {
return;
}
const sinPhi = Math.sin(xAxisRotation * TAU / 360);
const cosPhi = Math.cos(xAxisRotation * TAU / 360);
const pxp = cosPhi * (px - cx) / 2 + sinPhi * (py - cy) / 2;
const pyp = -sinPhi * (px - cx) / 2 + cosPhi * (py - cy) / 2;
if (pxp === 0 && pyp === 0) {
return;
}
rx = Math.abs(rx);
ry = Math.abs(ry);
const lambda = Math.pow(pxp, 2) / Math.pow(rx, 2) + Math.pow(pyp, 2) / Math.pow(ry, 2);
if (lambda > 1) {
rx *= Math.sqrt(lambda);
ry *= Math.sqrt(lambda);
}
getArcCenter(
px,
py,
cx,
cy,
rx,
ry,
largeArcFlag,
sweepFlag,
sinPhi,
cosPhi,
pxp,
pyp,
out
);
let { ang1, ang2 } = out;
const { centerX, centerY } = out;
let ratio = Math.abs(ang2) / (TAU / 4);
if (Math.abs(1 - ratio) < 1e-7) {
ratio = 1;
}
const segments = Math.max(Math.ceil(ratio), 1);
ang2 /= segments;
let lastX = points[points.length - 2];
let lastY = points[points.length - 1];
const outCurvePoint = { x: 0, y: 0 };
for (let i = 0; i < segments; i++) {
const curve = approxUnitArc(ang1, ang2);
const { x: x1, y: y1 } = mapToEllipse(curve[0], rx, ry, cosPhi, sinPhi, centerX, centerY, outCurvePoint);
const { x: x2, y: y2 } = mapToEllipse(curve[1], rx, ry, cosPhi, sinPhi, centerX, centerY, outCurvePoint);
const { x, y } = mapToEllipse(curve[2], rx, ry, cosPhi, sinPhi, centerX, centerY, outCurvePoint);
buildAdaptiveBezier.buildAdaptiveBezier(
points,
lastX,
lastY,
x1,
y1,
x2,
y2,
x,
y
);
lastX = x;
lastY = y;
ang1 += ang2;
}
}
exports.buildArcToSvg = buildArcToSvg;
//# sourceMappingURL=buildArcToSvg.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,152 @@
import { buildAdaptiveBezier } from './buildAdaptiveBezier.mjs';
"use strict";
const TAU = Math.PI * 2;
const out = {
centerX: 0,
centerY: 0,
ang1: 0,
ang2: 0
};
const mapToEllipse = ({ x, y }, rx, ry, cosPhi, sinPhi, centerX, centerY, out2) => {
x *= rx;
y *= ry;
const xp = cosPhi * x - sinPhi * y;
const yp = sinPhi * x + cosPhi * y;
out2.x = xp + centerX;
out2.y = yp + centerY;
return out2;
};
function approxUnitArc(ang1, ang2) {
const a1 = ang2 === -1.5707963267948966 ? -0.551915024494 : 4 / 3 * Math.tan(ang2 / 4);
const a = ang2 === 1.5707963267948966 ? 0.551915024494 : a1;
const x1 = Math.cos(ang1);
const y1 = Math.sin(ang1);
const x2 = Math.cos(ang1 + ang2);
const y2 = Math.sin(ang1 + ang2);
return [
{
x: x1 - y1 * a,
y: y1 + x1 * a
},
{
x: x2 + y2 * a,
y: y2 - x2 * a
},
{
x: x2,
y: y2
}
];
}
const vectorAngle = (ux, uy, vx, vy) => {
const sign = ux * vy - uy * vx < 0 ? -1 : 1;
let dot = ux * vx + uy * vy;
if (dot > 1) {
dot = 1;
}
if (dot < -1) {
dot = -1;
}
return sign * Math.acos(dot);
};
const getArcCenter = (px, py, cx, cy, rx, ry, largeArcFlag, sweepFlag, sinPhi, cosPhi, pxp, pyp, out2) => {
const rxSq = Math.pow(rx, 2);
const rySq = Math.pow(ry, 2);
const pxpSq = Math.pow(pxp, 2);
const pypSq = Math.pow(pyp, 2);
let radicant = rxSq * rySq - rxSq * pypSq - rySq * pxpSq;
if (radicant < 0) {
radicant = 0;
}
radicant /= rxSq * pypSq + rySq * pxpSq;
radicant = Math.sqrt(radicant) * (largeArcFlag === sweepFlag ? -1 : 1);
const centerXp = radicant * rx / ry * pyp;
const centerYp = radicant * -ry / rx * pxp;
const centerX = cosPhi * centerXp - sinPhi * centerYp + (px + cx) / 2;
const centerY = sinPhi * centerXp + cosPhi * centerYp + (py + cy) / 2;
const vx1 = (pxp - centerXp) / rx;
const vy1 = (pyp - centerYp) / ry;
const vx2 = (-pxp - centerXp) / rx;
const vy2 = (-pyp - centerYp) / ry;
const ang1 = vectorAngle(1, 0, vx1, vy1);
let ang2 = vectorAngle(vx1, vy1, vx2, vy2);
if (sweepFlag === 0 && ang2 > 0) {
ang2 -= TAU;
}
if (sweepFlag === 1 && ang2 < 0) {
ang2 += TAU;
}
out2.centerX = centerX;
out2.centerY = centerY;
out2.ang1 = ang1;
out2.ang2 = ang2;
};
function buildArcToSvg(points, px, py, cx, cy, rx, ry, xAxisRotation = 0, largeArcFlag = 0, sweepFlag = 0) {
if (rx === 0 || ry === 0) {
return;
}
const sinPhi = Math.sin(xAxisRotation * TAU / 360);
const cosPhi = Math.cos(xAxisRotation * TAU / 360);
const pxp = cosPhi * (px - cx) / 2 + sinPhi * (py - cy) / 2;
const pyp = -sinPhi * (px - cx) / 2 + cosPhi * (py - cy) / 2;
if (pxp === 0 && pyp === 0) {
return;
}
rx = Math.abs(rx);
ry = Math.abs(ry);
const lambda = Math.pow(pxp, 2) / Math.pow(rx, 2) + Math.pow(pyp, 2) / Math.pow(ry, 2);
if (lambda > 1) {
rx *= Math.sqrt(lambda);
ry *= Math.sqrt(lambda);
}
getArcCenter(
px,
py,
cx,
cy,
rx,
ry,
largeArcFlag,
sweepFlag,
sinPhi,
cosPhi,
pxp,
pyp,
out
);
let { ang1, ang2 } = out;
const { centerX, centerY } = out;
let ratio = Math.abs(ang2) / (TAU / 4);
if (Math.abs(1 - ratio) < 1e-7) {
ratio = 1;
}
const segments = Math.max(Math.ceil(ratio), 1);
ang2 /= segments;
let lastX = points[points.length - 2];
let lastY = points[points.length - 1];
const outCurvePoint = { x: 0, y: 0 };
for (let i = 0; i < segments; i++) {
const curve = approxUnitArc(ang1, ang2);
const { x: x1, y: y1 } = mapToEllipse(curve[0], rx, ry, cosPhi, sinPhi, centerX, centerY, outCurvePoint);
const { x: x2, y: y2 } = mapToEllipse(curve[1], rx, ry, cosPhi, sinPhi, centerX, centerY, outCurvePoint);
const { x, y } = mapToEllipse(curve[2], rx, ry, cosPhi, sinPhi, centerX, centerY, outCurvePoint);
buildAdaptiveBezier(
points,
lastX,
lastY,
x1,
y1,
x2,
y2,
x,
y
);
lastX = x;
lastY = y;
ang1 += ang2;
}
}
export { buildArcToSvg };
//# sourceMappingURL=buildArcToSvg.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
import { ExtensionType } from '../../../../extensions/Extensions';
import type { Circle } from '../../../../maths/shapes/Circle';
import type { Ellipse } from '../../../../maths/shapes/Ellipse';
import type { RoundedRectangle } from '../../../../maths/shapes/RoundedRectangle';
import type { ShapeBuildCommand } from './ShapeBuildCommand';
type RoundedShape = Circle | Ellipse | RoundedRectangle;
/**
* Builds a rectangle to draw
*
* Ignored from docs since it is not directly exposed.
* @ignore
* @private
*/
export declare const buildCircle: ShapeBuildCommand<RoundedShape>;
export declare const buildEllipse: {
extension: {
name: string;
type: ExtensionType | ExtensionType[];
priority?: number;
};
build(shape: RoundedShape, points: number[]): void;
triangulate(points: number[], vertices: number[], verticesStride: number, verticesOffset: number, indices: number[], indicesOffset: number): void;
};
export declare const buildRoundedRectangle: {
extension: {
name: string;
type: ExtensionType | ExtensionType[];
priority?: number;
};
build(shape: RoundedShape, points: number[]): void;
triangulate(points: number[], vertices: number[], verticesStride: number, verticesOffset: number, indices: number[], indicesOffset: number): void;
};
export {};

View File

@@ -0,0 +1,148 @@
'use strict';
var Extensions = require('../../../../extensions/Extensions.js');
"use strict";
const buildCircle = {
extension: {
type: Extensions.ExtensionType.ShapeBuilder,
name: "circle"
},
build(shape, points) {
let x;
let y;
let dx;
let dy;
let rx;
let ry;
if (shape.type === "circle") {
const circle = shape;
x = circle.x;
y = circle.y;
rx = ry = circle.radius;
dx = dy = 0;
} else if (shape.type === "ellipse") {
const ellipse = shape;
x = ellipse.x;
y = ellipse.y;
rx = ellipse.halfWidth;
ry = ellipse.halfHeight;
dx = dy = 0;
} else {
const roundedRect = shape;
const halfWidth = roundedRect.width / 2;
const halfHeight = roundedRect.height / 2;
x = roundedRect.x + halfWidth;
y = roundedRect.y + halfHeight;
rx = ry = Math.max(0, Math.min(roundedRect.radius, Math.min(halfWidth, halfHeight)));
dx = halfWidth - rx;
dy = halfHeight - ry;
}
if (!(rx >= 0 && ry >= 0 && dx >= 0 && dy >= 0)) {
return points;
}
const n = Math.ceil(2.3 * Math.sqrt(rx + ry));
const m = n * 8 + (dx ? 4 : 0) + (dy ? 4 : 0);
if (m === 0) {
return points;
}
if (n === 0) {
points[0] = points[6] = x + dx;
points[1] = points[3] = y + dy;
points[2] = points[4] = x - dx;
points[5] = points[7] = y - dy;
return points;
}
let j1 = 0;
let j2 = n * 4 + (dx ? 2 : 0) + 2;
let j3 = j2;
let j4 = m;
let x0 = dx + rx;
let y0 = dy;
let x1 = x + x0;
let x2 = x - x0;
let y1 = y + y0;
points[j1++] = x1;
points[j1++] = y1;
points[--j2] = y1;
points[--j2] = x2;
if (dy) {
const y22 = y - y0;
points[j3++] = x2;
points[j3++] = y22;
points[--j4] = y22;
points[--j4] = x1;
}
for (let i = 1; i < n; i++) {
const a = Math.PI / 2 * (i / n);
const x02 = dx + Math.cos(a) * rx;
const y02 = dy + Math.sin(a) * ry;
const x12 = x + x02;
const x22 = x - x02;
const y12 = y + y02;
const y22 = y - y02;
points[j1++] = x12;
points[j1++] = y12;
points[--j2] = y12;
points[--j2] = x22;
points[j3++] = x22;
points[j3++] = y22;
points[--j4] = y22;
points[--j4] = x12;
}
x0 = dx;
y0 = dy + ry;
x1 = x + x0;
x2 = x - x0;
y1 = y + y0;
const y2 = y - y0;
points[j1++] = x1;
points[j1++] = y1;
points[--j4] = y2;
points[--j4] = x1;
if (dx) {
points[j1++] = x2;
points[j1++] = y1;
points[--j4] = y2;
points[--j4] = x2;
}
return points;
},
triangulate(points, vertices, verticesStride, verticesOffset, indices, indicesOffset) {
if (points.length === 0) {
return;
}
let centerX = 0;
let centerY = 0;
for (let i = 0; i < points.length; i += 2) {
centerX += points[i];
centerY += points[i + 1];
}
centerX /= points.length / 2;
centerY /= points.length / 2;
let count = verticesOffset;
vertices[count * verticesStride] = centerX;
vertices[count * verticesStride + 1] = centerY;
const centerIndex = count++;
for (let i = 0; i < points.length; i += 2) {
vertices[count * verticesStride] = points[i];
vertices[count * verticesStride + 1] = points[i + 1];
if (i > 0) {
indices[indicesOffset++] = count;
indices[indicesOffset++] = centerIndex;
indices[indicesOffset++] = count - 1;
}
count++;
}
indices[indicesOffset++] = centerIndex + 1;
indices[indicesOffset++] = centerIndex;
indices[indicesOffset++] = count - 1;
}
};
const buildEllipse = { ...buildCircle, extension: { ...buildCircle.extension, name: "ellipse" } };
const buildRoundedRectangle = { ...buildCircle, extension: { ...buildCircle.extension, name: "roundedRectangle" } };
exports.buildCircle = buildCircle;
exports.buildEllipse = buildEllipse;
exports.buildRoundedRectangle = buildRoundedRectangle;
//# sourceMappingURL=buildCircle.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,144 @@
import { ExtensionType } from '../../../../extensions/Extensions.mjs';
"use strict";
const buildCircle = {
extension: {
type: ExtensionType.ShapeBuilder,
name: "circle"
},
build(shape, points) {
let x;
let y;
let dx;
let dy;
let rx;
let ry;
if (shape.type === "circle") {
const circle = shape;
x = circle.x;
y = circle.y;
rx = ry = circle.radius;
dx = dy = 0;
} else if (shape.type === "ellipse") {
const ellipse = shape;
x = ellipse.x;
y = ellipse.y;
rx = ellipse.halfWidth;
ry = ellipse.halfHeight;
dx = dy = 0;
} else {
const roundedRect = shape;
const halfWidth = roundedRect.width / 2;
const halfHeight = roundedRect.height / 2;
x = roundedRect.x + halfWidth;
y = roundedRect.y + halfHeight;
rx = ry = Math.max(0, Math.min(roundedRect.radius, Math.min(halfWidth, halfHeight)));
dx = halfWidth - rx;
dy = halfHeight - ry;
}
if (!(rx >= 0 && ry >= 0 && dx >= 0 && dy >= 0)) {
return points;
}
const n = Math.ceil(2.3 * Math.sqrt(rx + ry));
const m = n * 8 + (dx ? 4 : 0) + (dy ? 4 : 0);
if (m === 0) {
return points;
}
if (n === 0) {
points[0] = points[6] = x + dx;
points[1] = points[3] = y + dy;
points[2] = points[4] = x - dx;
points[5] = points[7] = y - dy;
return points;
}
let j1 = 0;
let j2 = n * 4 + (dx ? 2 : 0) + 2;
let j3 = j2;
let j4 = m;
let x0 = dx + rx;
let y0 = dy;
let x1 = x + x0;
let x2 = x - x0;
let y1 = y + y0;
points[j1++] = x1;
points[j1++] = y1;
points[--j2] = y1;
points[--j2] = x2;
if (dy) {
const y22 = y - y0;
points[j3++] = x2;
points[j3++] = y22;
points[--j4] = y22;
points[--j4] = x1;
}
for (let i = 1; i < n; i++) {
const a = Math.PI / 2 * (i / n);
const x02 = dx + Math.cos(a) * rx;
const y02 = dy + Math.sin(a) * ry;
const x12 = x + x02;
const x22 = x - x02;
const y12 = y + y02;
const y22 = y - y02;
points[j1++] = x12;
points[j1++] = y12;
points[--j2] = y12;
points[--j2] = x22;
points[j3++] = x22;
points[j3++] = y22;
points[--j4] = y22;
points[--j4] = x12;
}
x0 = dx;
y0 = dy + ry;
x1 = x + x0;
x2 = x - x0;
y1 = y + y0;
const y2 = y - y0;
points[j1++] = x1;
points[j1++] = y1;
points[--j4] = y2;
points[--j4] = x1;
if (dx) {
points[j1++] = x2;
points[j1++] = y1;
points[--j4] = y2;
points[--j4] = x2;
}
return points;
},
triangulate(points, vertices, verticesStride, verticesOffset, indices, indicesOffset) {
if (points.length === 0) {
return;
}
let centerX = 0;
let centerY = 0;
for (let i = 0; i < points.length; i += 2) {
centerX += points[i];
centerY += points[i + 1];
}
centerX /= points.length / 2;
centerY /= points.length / 2;
let count = verticesOffset;
vertices[count * verticesStride] = centerX;
vertices[count * verticesStride + 1] = centerY;
const centerIndex = count++;
for (let i = 0; i < points.length; i += 2) {
vertices[count * verticesStride] = points[i];
vertices[count * verticesStride + 1] = points[i + 1];
if (i > 0) {
indices[indicesOffset++] = count;
indices[indicesOffset++] = centerIndex;
indices[indicesOffset++] = count - 1;
}
count++;
}
indices[indicesOffset++] = centerIndex + 1;
indices[indicesOffset++] = centerIndex;
indices[indicesOffset++] = count - 1;
}
};
const buildEllipse = { ...buildCircle, extension: { ...buildCircle.extension, name: "ellipse" } };
const buildRoundedRectangle = { ...buildCircle, extension: { ...buildCircle.extension, name: "roundedRectangle" } };
export { buildCircle, buildEllipse, buildRoundedRectangle };
//# sourceMappingURL=buildCircle.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
import type { StrokeAttributes } from '../FillTypes';
/**
* Builds a line to draw using the polygon method.
* @param points
* @param lineStyle
* @param flipAlignment
* @param closed
* @param vertices
* @param _verticesStride
* @param _verticesOffset
* @param indices
* @param _indicesOffset
*/
export declare function buildLine(points: number[], lineStyle: StrokeAttributes, flipAlignment: boolean, closed: boolean, vertices: number[], _verticesStride: number, _verticesOffset: number, indices: number[], _indicesOffset: number): void;

View File

@@ -0,0 +1,365 @@
'use strict';
var Point = require('../../../../maths/point/Point.js');
var _const = require('../const.js');
var getOrientationOfPoints = require('../utils/getOrientationOfPoints.js');
"use strict";
function square(x, y, nx, ny, innerWeight, outerWeight, clockwise, verts) {
const ix = x - nx * innerWeight;
const iy = y - ny * innerWeight;
const ox = x + nx * outerWeight;
const oy = y + ny * outerWeight;
let exx;
let eyy;
if (clockwise) {
exx = ny;
eyy = -nx;
} else {
exx = -ny;
eyy = nx;
}
const eix = ix + exx;
const eiy = iy + eyy;
const eox = ox + exx;
const eoy = oy + eyy;
verts.push(eix, eiy);
verts.push(eox, eoy);
return 2;
}
function round(cx, cy, sx, sy, ex, ey, verts, clockwise) {
const cx2p0x = sx - cx;
const cy2p0y = sy - cy;
let angle0 = Math.atan2(cx2p0x, cy2p0y);
let angle1 = Math.atan2(ex - cx, ey - cy);
if (clockwise && angle0 < angle1) {
angle0 += Math.PI * 2;
} else if (!clockwise && angle0 > angle1) {
angle1 += Math.PI * 2;
}
let startAngle = angle0;
const angleDiff = angle1 - angle0;
const absAngleDiff = Math.abs(angleDiff);
const radius = Math.sqrt(cx2p0x * cx2p0x + cy2p0y * cy2p0y);
const segCount = (15 * absAngleDiff * Math.sqrt(radius) / Math.PI >> 0) + 1;
const angleInc = angleDiff / segCount;
startAngle += angleInc;
if (clockwise) {
verts.push(cx, cy);
verts.push(sx, sy);
for (let i = 1, angle = startAngle; i < segCount; i++, angle += angleInc) {
verts.push(cx, cy);
verts.push(
cx + Math.sin(angle) * radius,
cy + Math.cos(angle) * radius
);
}
verts.push(cx, cy);
verts.push(ex, ey);
} else {
verts.push(sx, sy);
verts.push(cx, cy);
for (let i = 1, angle = startAngle; i < segCount; i++, angle += angleInc) {
verts.push(
cx + Math.sin(angle) * radius,
cy + Math.cos(angle) * radius
);
verts.push(cx, cy);
}
verts.push(ex, ey);
verts.push(cx, cy);
}
return segCount * 2;
}
function buildLine(points, lineStyle, flipAlignment, closed, vertices, _verticesStride, _verticesOffset, indices, _indicesOffset) {
const eps = _const.closePointEps;
if (points.length === 0) {
return;
}
const style = lineStyle;
let alignment = style.alignment;
if (lineStyle.alignment !== 0.5) {
let orientation = getOrientationOfPoints.getOrientationOfPoints(points);
if (flipAlignment)
orientation *= -1;
alignment = (alignment - 0.5) * orientation + 0.5;
}
const firstPoint = new Point.Point(points[0], points[1]);
const lastPoint = new Point.Point(points[points.length - 2], points[points.length - 1]);
const closedShape = closed;
const closedPath = Math.abs(firstPoint.x - lastPoint.x) < eps && Math.abs(firstPoint.y - lastPoint.y) < eps;
if (closedShape) {
points = points.slice();
if (closedPath) {
points.pop();
points.pop();
lastPoint.set(points[points.length - 2], points[points.length - 1]);
}
const midPointX = (firstPoint.x + lastPoint.x) * 0.5;
const midPointY = (lastPoint.y + firstPoint.y) * 0.5;
points.unshift(midPointX, midPointY);
points.push(midPointX, midPointY);
}
const verts = vertices;
const length = points.length / 2;
let indexCount = points.length;
const indexStart = verts.length / 2;
const width = style.width / 2;
const widthSquared = width * width;
const miterLimitSquared = style.miterLimit * style.miterLimit;
let x0 = points[0];
let y0 = points[1];
let x1 = points[2];
let y1 = points[3];
let x2 = 0;
let y2 = 0;
let perpX = -(y0 - y1);
let perpY = x0 - x1;
let perp1x = 0;
let perp1y = 0;
let dist = Math.sqrt(perpX * perpX + perpY * perpY);
perpX /= dist;
perpY /= dist;
perpX *= width;
perpY *= width;
const ratio = alignment;
const innerWeight = (1 - ratio) * 2;
const outerWeight = ratio * 2;
if (!closedShape) {
if (style.cap === "round") {
indexCount += round(
x0 - perpX * (innerWeight - outerWeight) * 0.5,
y0 - perpY * (innerWeight - outerWeight) * 0.5,
x0 - perpX * innerWeight,
y0 - perpY * innerWeight,
x0 + perpX * outerWeight,
y0 + perpY * outerWeight,
verts,
true
) + 2;
} else if (style.cap === "square") {
indexCount += square(x0, y0, perpX, perpY, innerWeight, outerWeight, true, verts);
}
}
verts.push(
x0 - perpX * innerWeight,
y0 - perpY * innerWeight
);
verts.push(
x0 + perpX * outerWeight,
y0 + perpY * outerWeight
);
for (let i = 1; i < length - 1; ++i) {
x0 = points[(i - 1) * 2];
y0 = points[(i - 1) * 2 + 1];
x1 = points[i * 2];
y1 = points[i * 2 + 1];
x2 = points[(i + 1) * 2];
y2 = points[(i + 1) * 2 + 1];
perpX = -(y0 - y1);
perpY = x0 - x1;
dist = Math.sqrt(perpX * perpX + perpY * perpY);
perpX /= dist;
perpY /= dist;
perpX *= width;
perpY *= width;
perp1x = -(y1 - y2);
perp1y = x1 - x2;
dist = Math.sqrt(perp1x * perp1x + perp1y * perp1y);
perp1x /= dist;
perp1y /= dist;
perp1x *= width;
perp1y *= width;
const dx0 = x1 - x0;
const dy0 = y0 - y1;
const dx1 = x1 - x2;
const dy1 = y2 - y1;
const dot = dx0 * dx1 + dy0 * dy1;
const cross = dy0 * dx1 - dy1 * dx0;
const clockwise = cross < 0;
if (Math.abs(cross) < 1e-3 * Math.abs(dot)) {
verts.push(
x1 - perpX * innerWeight,
y1 - perpY * innerWeight
);
verts.push(
x1 + perpX * outerWeight,
y1 + perpY * outerWeight
);
if (dot >= 0) {
if (style.join === "round") {
indexCount += round(
x1,
y1,
x1 - perpX * innerWeight,
y1 - perpY * innerWeight,
x1 - perp1x * innerWeight,
y1 - perp1y * innerWeight,
verts,
false
) + 4;
} else {
indexCount += 2;
}
verts.push(
x1 - perp1x * outerWeight,
y1 - perp1y * outerWeight
);
verts.push(
x1 + perp1x * innerWeight,
y1 + perp1y * innerWeight
);
}
continue;
}
const c1 = (-perpX + x0) * (-perpY + y1) - (-perpX + x1) * (-perpY + y0);
const c2 = (-perp1x + x2) * (-perp1y + y1) - (-perp1x + x1) * (-perp1y + y2);
const px = (dx0 * c2 - dx1 * c1) / cross;
const py = (dy1 * c1 - dy0 * c2) / cross;
const pDist = (px - x1) * (px - x1) + (py - y1) * (py - y1);
const imx = x1 + (px - x1) * innerWeight;
const imy = y1 + (py - y1) * innerWeight;
const omx = x1 - (px - x1) * outerWeight;
const omy = y1 - (py - y1) * outerWeight;
const smallerInsideSegmentSq = Math.min(dx0 * dx0 + dy0 * dy0, dx1 * dx1 + dy1 * dy1);
const insideWeight = clockwise ? innerWeight : outerWeight;
const smallerInsideDiagonalSq = smallerInsideSegmentSq + insideWeight * insideWeight * widthSquared;
const insideMiterOk = pDist <= smallerInsideDiagonalSq;
if (insideMiterOk) {
if (style.join === "bevel" || pDist / widthSquared > miterLimitSquared) {
if (clockwise) {
verts.push(imx, imy);
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
verts.push(imx, imy);
verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
} else {
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
verts.push(omx, omy);
verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
verts.push(omx, omy);
}
indexCount += 2;
} else if (style.join === "round") {
if (clockwise) {
verts.push(imx, imy);
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
indexCount += round(
x1,
y1,
x1 + perpX * outerWeight,
y1 + perpY * outerWeight,
x1 + perp1x * outerWeight,
y1 + perp1y * outerWeight,
verts,
true
) + 4;
verts.push(imx, imy);
verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
} else {
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
verts.push(omx, omy);
indexCount += round(
x1,
y1,
x1 - perpX * innerWeight,
y1 - perpY * innerWeight,
x1 - perp1x * innerWeight,
y1 - perp1y * innerWeight,
verts,
false
) + 4;
verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
verts.push(omx, omy);
}
} else {
verts.push(imx, imy);
verts.push(omx, omy);
}
} else {
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
if (style.join === "round") {
if (clockwise) {
indexCount += round(
x1,
y1,
x1 + perpX * outerWeight,
y1 + perpY * outerWeight,
x1 + perp1x * outerWeight,
y1 + perp1y * outerWeight,
verts,
true
) + 2;
} else {
indexCount += round(
x1,
y1,
x1 - perpX * innerWeight,
y1 - perpY * innerWeight,
x1 - perp1x * innerWeight,
y1 - perp1y * innerWeight,
verts,
false
) + 2;
}
} else if (style.join === "miter" && pDist / widthSquared <= miterLimitSquared) {
if (clockwise) {
verts.push(omx, omy);
verts.push(omx, omy);
} else {
verts.push(imx, imy);
verts.push(imx, imy);
}
indexCount += 2;
}
verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
indexCount += 2;
}
}
x0 = points[(length - 2) * 2];
y0 = points[(length - 2) * 2 + 1];
x1 = points[(length - 1) * 2];
y1 = points[(length - 1) * 2 + 1];
perpX = -(y0 - y1);
perpY = x0 - x1;
dist = Math.sqrt(perpX * perpX + perpY * perpY);
perpX /= dist;
perpY /= dist;
perpX *= width;
perpY *= width;
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
if (!closedShape) {
if (style.cap === "round") {
indexCount += round(
x1 - perpX * (innerWeight - outerWeight) * 0.5,
y1 - perpY * (innerWeight - outerWeight) * 0.5,
x1 - perpX * innerWeight,
y1 - perpY * innerWeight,
x1 + perpX * outerWeight,
y1 + perpY * outerWeight,
verts,
false
) + 2;
} else if (style.cap === "square") {
indexCount += square(x1, y1, perpX, perpY, innerWeight, outerWeight, false, verts);
}
}
const eps2 = _const.curveEps * _const.curveEps;
for (let i = indexStart; i < indexCount + indexStart - 2; ++i) {
x0 = verts[i * 2];
y0 = verts[i * 2 + 1];
x1 = verts[(i + 1) * 2];
y1 = verts[(i + 1) * 2 + 1];
x2 = verts[(i + 2) * 2];
y2 = verts[(i + 2) * 2 + 1];
if (Math.abs(x0 * (y1 - y2) + x1 * (y2 - y0) + x2 * (y0 - y1)) < eps2) {
continue;
}
indices.push(i, i + 1, i + 2);
}
}
exports.buildLine = buildLine;
//# sourceMappingURL=buildLine.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,363 @@
import { Point } from '../../../../maths/point/Point.mjs';
import { closePointEps, curveEps } from '../const.mjs';
import { getOrientationOfPoints } from '../utils/getOrientationOfPoints.mjs';
"use strict";
function square(x, y, nx, ny, innerWeight, outerWeight, clockwise, verts) {
const ix = x - nx * innerWeight;
const iy = y - ny * innerWeight;
const ox = x + nx * outerWeight;
const oy = y + ny * outerWeight;
let exx;
let eyy;
if (clockwise) {
exx = ny;
eyy = -nx;
} else {
exx = -ny;
eyy = nx;
}
const eix = ix + exx;
const eiy = iy + eyy;
const eox = ox + exx;
const eoy = oy + eyy;
verts.push(eix, eiy);
verts.push(eox, eoy);
return 2;
}
function round(cx, cy, sx, sy, ex, ey, verts, clockwise) {
const cx2p0x = sx - cx;
const cy2p0y = sy - cy;
let angle0 = Math.atan2(cx2p0x, cy2p0y);
let angle1 = Math.atan2(ex - cx, ey - cy);
if (clockwise && angle0 < angle1) {
angle0 += Math.PI * 2;
} else if (!clockwise && angle0 > angle1) {
angle1 += Math.PI * 2;
}
let startAngle = angle0;
const angleDiff = angle1 - angle0;
const absAngleDiff = Math.abs(angleDiff);
const radius = Math.sqrt(cx2p0x * cx2p0x + cy2p0y * cy2p0y);
const segCount = (15 * absAngleDiff * Math.sqrt(radius) / Math.PI >> 0) + 1;
const angleInc = angleDiff / segCount;
startAngle += angleInc;
if (clockwise) {
verts.push(cx, cy);
verts.push(sx, sy);
for (let i = 1, angle = startAngle; i < segCount; i++, angle += angleInc) {
verts.push(cx, cy);
verts.push(
cx + Math.sin(angle) * radius,
cy + Math.cos(angle) * radius
);
}
verts.push(cx, cy);
verts.push(ex, ey);
} else {
verts.push(sx, sy);
verts.push(cx, cy);
for (let i = 1, angle = startAngle; i < segCount; i++, angle += angleInc) {
verts.push(
cx + Math.sin(angle) * radius,
cy + Math.cos(angle) * radius
);
verts.push(cx, cy);
}
verts.push(ex, ey);
verts.push(cx, cy);
}
return segCount * 2;
}
function buildLine(points, lineStyle, flipAlignment, closed, vertices, _verticesStride, _verticesOffset, indices, _indicesOffset) {
const eps = closePointEps;
if (points.length === 0) {
return;
}
const style = lineStyle;
let alignment = style.alignment;
if (lineStyle.alignment !== 0.5) {
let orientation = getOrientationOfPoints(points);
if (flipAlignment)
orientation *= -1;
alignment = (alignment - 0.5) * orientation + 0.5;
}
const firstPoint = new Point(points[0], points[1]);
const lastPoint = new Point(points[points.length - 2], points[points.length - 1]);
const closedShape = closed;
const closedPath = Math.abs(firstPoint.x - lastPoint.x) < eps && Math.abs(firstPoint.y - lastPoint.y) < eps;
if (closedShape) {
points = points.slice();
if (closedPath) {
points.pop();
points.pop();
lastPoint.set(points[points.length - 2], points[points.length - 1]);
}
const midPointX = (firstPoint.x + lastPoint.x) * 0.5;
const midPointY = (lastPoint.y + firstPoint.y) * 0.5;
points.unshift(midPointX, midPointY);
points.push(midPointX, midPointY);
}
const verts = vertices;
const length = points.length / 2;
let indexCount = points.length;
const indexStart = verts.length / 2;
const width = style.width / 2;
const widthSquared = width * width;
const miterLimitSquared = style.miterLimit * style.miterLimit;
let x0 = points[0];
let y0 = points[1];
let x1 = points[2];
let y1 = points[3];
let x2 = 0;
let y2 = 0;
let perpX = -(y0 - y1);
let perpY = x0 - x1;
let perp1x = 0;
let perp1y = 0;
let dist = Math.sqrt(perpX * perpX + perpY * perpY);
perpX /= dist;
perpY /= dist;
perpX *= width;
perpY *= width;
const ratio = alignment;
const innerWeight = (1 - ratio) * 2;
const outerWeight = ratio * 2;
if (!closedShape) {
if (style.cap === "round") {
indexCount += round(
x0 - perpX * (innerWeight - outerWeight) * 0.5,
y0 - perpY * (innerWeight - outerWeight) * 0.5,
x0 - perpX * innerWeight,
y0 - perpY * innerWeight,
x0 + perpX * outerWeight,
y0 + perpY * outerWeight,
verts,
true
) + 2;
} else if (style.cap === "square") {
indexCount += square(x0, y0, perpX, perpY, innerWeight, outerWeight, true, verts);
}
}
verts.push(
x0 - perpX * innerWeight,
y0 - perpY * innerWeight
);
verts.push(
x0 + perpX * outerWeight,
y0 + perpY * outerWeight
);
for (let i = 1; i < length - 1; ++i) {
x0 = points[(i - 1) * 2];
y0 = points[(i - 1) * 2 + 1];
x1 = points[i * 2];
y1 = points[i * 2 + 1];
x2 = points[(i + 1) * 2];
y2 = points[(i + 1) * 2 + 1];
perpX = -(y0 - y1);
perpY = x0 - x1;
dist = Math.sqrt(perpX * perpX + perpY * perpY);
perpX /= dist;
perpY /= dist;
perpX *= width;
perpY *= width;
perp1x = -(y1 - y2);
perp1y = x1 - x2;
dist = Math.sqrt(perp1x * perp1x + perp1y * perp1y);
perp1x /= dist;
perp1y /= dist;
perp1x *= width;
perp1y *= width;
const dx0 = x1 - x0;
const dy0 = y0 - y1;
const dx1 = x1 - x2;
const dy1 = y2 - y1;
const dot = dx0 * dx1 + dy0 * dy1;
const cross = dy0 * dx1 - dy1 * dx0;
const clockwise = cross < 0;
if (Math.abs(cross) < 1e-3 * Math.abs(dot)) {
verts.push(
x1 - perpX * innerWeight,
y1 - perpY * innerWeight
);
verts.push(
x1 + perpX * outerWeight,
y1 + perpY * outerWeight
);
if (dot >= 0) {
if (style.join === "round") {
indexCount += round(
x1,
y1,
x1 - perpX * innerWeight,
y1 - perpY * innerWeight,
x1 - perp1x * innerWeight,
y1 - perp1y * innerWeight,
verts,
false
) + 4;
} else {
indexCount += 2;
}
verts.push(
x1 - perp1x * outerWeight,
y1 - perp1y * outerWeight
);
verts.push(
x1 + perp1x * innerWeight,
y1 + perp1y * innerWeight
);
}
continue;
}
const c1 = (-perpX + x0) * (-perpY + y1) - (-perpX + x1) * (-perpY + y0);
const c2 = (-perp1x + x2) * (-perp1y + y1) - (-perp1x + x1) * (-perp1y + y2);
const px = (dx0 * c2 - dx1 * c1) / cross;
const py = (dy1 * c1 - dy0 * c2) / cross;
const pDist = (px - x1) * (px - x1) + (py - y1) * (py - y1);
const imx = x1 + (px - x1) * innerWeight;
const imy = y1 + (py - y1) * innerWeight;
const omx = x1 - (px - x1) * outerWeight;
const omy = y1 - (py - y1) * outerWeight;
const smallerInsideSegmentSq = Math.min(dx0 * dx0 + dy0 * dy0, dx1 * dx1 + dy1 * dy1);
const insideWeight = clockwise ? innerWeight : outerWeight;
const smallerInsideDiagonalSq = smallerInsideSegmentSq + insideWeight * insideWeight * widthSquared;
const insideMiterOk = pDist <= smallerInsideDiagonalSq;
if (insideMiterOk) {
if (style.join === "bevel" || pDist / widthSquared > miterLimitSquared) {
if (clockwise) {
verts.push(imx, imy);
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
verts.push(imx, imy);
verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
} else {
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
verts.push(omx, omy);
verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
verts.push(omx, omy);
}
indexCount += 2;
} else if (style.join === "round") {
if (clockwise) {
verts.push(imx, imy);
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
indexCount += round(
x1,
y1,
x1 + perpX * outerWeight,
y1 + perpY * outerWeight,
x1 + perp1x * outerWeight,
y1 + perp1y * outerWeight,
verts,
true
) + 4;
verts.push(imx, imy);
verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
} else {
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
verts.push(omx, omy);
indexCount += round(
x1,
y1,
x1 - perpX * innerWeight,
y1 - perpY * innerWeight,
x1 - perp1x * innerWeight,
y1 - perp1y * innerWeight,
verts,
false
) + 4;
verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
verts.push(omx, omy);
}
} else {
verts.push(imx, imy);
verts.push(omx, omy);
}
} else {
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
if (style.join === "round") {
if (clockwise) {
indexCount += round(
x1,
y1,
x1 + perpX * outerWeight,
y1 + perpY * outerWeight,
x1 + perp1x * outerWeight,
y1 + perp1y * outerWeight,
verts,
true
) + 2;
} else {
indexCount += round(
x1,
y1,
x1 - perpX * innerWeight,
y1 - perpY * innerWeight,
x1 - perp1x * innerWeight,
y1 - perp1y * innerWeight,
verts,
false
) + 2;
}
} else if (style.join === "miter" && pDist / widthSquared <= miterLimitSquared) {
if (clockwise) {
verts.push(omx, omy);
verts.push(omx, omy);
} else {
verts.push(imx, imy);
verts.push(imx, imy);
}
indexCount += 2;
}
verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight);
verts.push(x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
indexCount += 2;
}
}
x0 = points[(length - 2) * 2];
y0 = points[(length - 2) * 2 + 1];
x1 = points[(length - 1) * 2];
y1 = points[(length - 1) * 2 + 1];
perpX = -(y0 - y1);
perpY = x0 - x1;
dist = Math.sqrt(perpX * perpX + perpY * perpY);
perpX /= dist;
perpY /= dist;
perpX *= width;
perpY *= width;
verts.push(x1 - perpX * innerWeight, y1 - perpY * innerWeight);
verts.push(x1 + perpX * outerWeight, y1 + perpY * outerWeight);
if (!closedShape) {
if (style.cap === "round") {
indexCount += round(
x1 - perpX * (innerWeight - outerWeight) * 0.5,
y1 - perpY * (innerWeight - outerWeight) * 0.5,
x1 - perpX * innerWeight,
y1 - perpY * innerWeight,
x1 + perpX * outerWeight,
y1 + perpY * outerWeight,
verts,
false
) + 2;
} else if (style.cap === "square") {
indexCount += square(x1, y1, perpX, perpY, innerWeight, outerWeight, false, verts);
}
}
const eps2 = curveEps * curveEps;
for (let i = indexStart; i < indexCount + indexStart - 2; ++i) {
x0 = verts[i * 2];
y0 = verts[i * 2 + 1];
x1 = verts[(i + 1) * 2];
y1 = verts[(i + 1) * 2 + 1];
x2 = verts[(i + 2) * 2];
y2 = verts[(i + 2) * 2 + 1];
if (Math.abs(x0 * (y1 - y2) + x1 * (y2 - y0) + x2 * (y0 - y1)) < eps2) {
continue;
}
indices.push(i, i + 1, i + 2);
}
}
export { buildLine };
//# sourceMappingURL=buildLine.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
import type { Polygon } from '../../../../maths/shapes/Polygon';
import type { ShapeBuildCommand } from './ShapeBuildCommand';
/**
* Builds a rectangle to draw
*
* Ignored from docs since it is not directly exposed.
* @ignore
* @private
*/
export declare const buildPolygon: ShapeBuildCommand<Polygon>;

View File

@@ -0,0 +1,25 @@
'use strict';
var Extensions = require('../../../../extensions/Extensions.js');
var triangulateWithHoles = require('../utils/triangulateWithHoles.js');
"use strict";
const emptyArray = [];
const buildPolygon = {
extension: {
type: Extensions.ExtensionType.ShapeBuilder,
name: "polygon"
},
build(shape, points) {
for (let i = 0; i < shape.points.length; i++) {
points[i] = shape.points[i];
}
return points;
},
triangulate(points, vertices, verticesStride, verticesOffset, indices, indicesOffset) {
triangulateWithHoles.triangulateWithHoles(points, emptyArray, vertices, verticesStride, verticesOffset, indices, indicesOffset);
}
};
exports.buildPolygon = buildPolygon;
//# sourceMappingURL=buildPolygon.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"buildPolygon.js","sources":["../../../../../src/scene/graphics/shared/buildCommands/buildPolygon.ts"],"sourcesContent":["import { ExtensionType } from '../../../../extensions/Extensions';\nimport { triangulateWithHoles } from '../utils/triangulateWithHoles';\n\nimport type { Polygon } from '../../../../maths/shapes/Polygon';\nimport type { ShapeBuildCommand } from './ShapeBuildCommand';\n\nconst emptyArray: number[] = [];\n\n/**\n * Builds a rectangle to draw\n *\n * Ignored from docs since it is not directly exposed.\n * @ignore\n * @private\n */\nexport const buildPolygon: ShapeBuildCommand<Polygon> = {\n extension: {\n type: ExtensionType.ShapeBuilder,\n name: 'polygon',\n },\n\n build(shape: Polygon, points: number[]): number[]\n {\n for (let i = 0; i < shape.points.length; i++)\n {\n points[i] = shape.points[i];\n }\n\n return points;\n },\n\n triangulate(\n points: number[],\n // holes: number[],\n vertices: number[],\n verticesStride: number,\n verticesOffset: number,\n\n indices: number[],\n indicesOffset: number\n )\n {\n triangulateWithHoles(points, emptyArray, vertices, verticesStride, verticesOffset, indices, indicesOffset);\n },\n\n};\n"],"names":["ExtensionType","triangulateWithHoles"],"mappings":";;;;;;AAMA,MAAM,aAAuB,EAAC,CAAA;AASvB,MAAM,YAA2C,GAAA;AAAA,EACpD,SAAW,EAAA;AAAA,IACP,MAAMA,wBAAc,CAAA,YAAA;AAAA,IACpB,IAAM,EAAA,SAAA;AAAA,GACV;AAAA,EAEA,KAAA,CAAM,OAAgB,MACtB,EAAA;AACI,IAAA,KAAA,IAAS,IAAI,CAAG,EAAA,CAAA,GAAI,KAAM,CAAA,MAAA,CAAO,QAAQ,CACzC,EAAA,EAAA;AACI,MAAA,MAAA,CAAO,CAAC,CAAA,GAAI,KAAM,CAAA,MAAA,CAAO,CAAC,CAAA,CAAA;AAAA,KAC9B;AAEA,IAAO,OAAA,MAAA,CAAA;AAAA,GACX;AAAA,EAEA,YACI,MAEA,EAAA,QAAA,EACA,cACA,EAAA,cAAA,EAEA,SACA,aAEJ,EAAA;AACI,IAAAC,yCAAA,CAAqB,QAAQ,UAAY,EAAA,QAAA,EAAU,cAAgB,EAAA,cAAA,EAAgB,SAAS,aAAa,CAAA,CAAA;AAAA,GAC7G;AAEJ;;;;"}

View File

@@ -0,0 +1,23 @@
import { ExtensionType } from '../../../../extensions/Extensions.mjs';
import { triangulateWithHoles } from '../utils/triangulateWithHoles.mjs';
"use strict";
const emptyArray = [];
const buildPolygon = {
extension: {
type: ExtensionType.ShapeBuilder,
name: "polygon"
},
build(shape, points) {
for (let i = 0; i < shape.points.length; i++) {
points[i] = shape.points[i];
}
return points;
},
triangulate(points, vertices, verticesStride, verticesOffset, indices, indicesOffset) {
triangulateWithHoles(points, emptyArray, vertices, verticesStride, verticesOffset, indices, indicesOffset);
}
};
export { buildPolygon };
//# sourceMappingURL=buildPolygon.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"buildPolygon.mjs","sources":["../../../../../src/scene/graphics/shared/buildCommands/buildPolygon.ts"],"sourcesContent":["import { ExtensionType } from '../../../../extensions/Extensions';\nimport { triangulateWithHoles } from '../utils/triangulateWithHoles';\n\nimport type { Polygon } from '../../../../maths/shapes/Polygon';\nimport type { ShapeBuildCommand } from './ShapeBuildCommand';\n\nconst emptyArray: number[] = [];\n\n/**\n * Builds a rectangle to draw\n *\n * Ignored from docs since it is not directly exposed.\n * @ignore\n * @private\n */\nexport const buildPolygon: ShapeBuildCommand<Polygon> = {\n extension: {\n type: ExtensionType.ShapeBuilder,\n name: 'polygon',\n },\n\n build(shape: Polygon, points: number[]): number[]\n {\n for (let i = 0; i < shape.points.length; i++)\n {\n points[i] = shape.points[i];\n }\n\n return points;\n },\n\n triangulate(\n points: number[],\n // holes: number[],\n vertices: number[],\n verticesStride: number,\n verticesOffset: number,\n\n indices: number[],\n indicesOffset: number\n )\n {\n triangulateWithHoles(points, emptyArray, vertices, verticesStride, verticesOffset, indices, indicesOffset);\n },\n\n};\n"],"names":[],"mappings":";;;;AAMA,MAAM,aAAuB,EAAC,CAAA;AASvB,MAAM,YAA2C,GAAA;AAAA,EACpD,SAAW,EAAA;AAAA,IACP,MAAM,aAAc,CAAA,YAAA;AAAA,IACpB,IAAM,EAAA,SAAA;AAAA,GACV;AAAA,EAEA,KAAA,CAAM,OAAgB,MACtB,EAAA;AACI,IAAA,KAAA,IAAS,IAAI,CAAG,EAAA,CAAA,GAAI,KAAM,CAAA,MAAA,CAAO,QAAQ,CACzC,EAAA,EAAA;AACI,MAAA,MAAA,CAAO,CAAC,CAAA,GAAI,KAAM,CAAA,MAAA,CAAO,CAAC,CAAA,CAAA;AAAA,KAC9B;AAEA,IAAO,OAAA,MAAA,CAAA;AAAA,GACX;AAAA,EAEA,YACI,MAEA,EAAA,QAAA,EACA,cACA,EAAA,cAAA,EAEA,SACA,aAEJ,EAAA;AACI,IAAA,oBAAA,CAAqB,QAAQ,UAAY,EAAA,QAAA,EAAU,cAAgB,EAAA,cAAA,EAAgB,SAAS,aAAa,CAAA,CAAA;AAAA,GAC7G;AAEJ;;;;"}

View File

@@ -0,0 +1,10 @@
import type { Rectangle } from '../../../../maths/shapes/Rectangle';
import type { ShapeBuildCommand } from './ShapeBuildCommand';
/**
* Builds a rectangle to draw
*
* Ignored from docs since it is not directly exposed.
* @ignore
* @private
*/
export declare const buildRectangle: ShapeBuildCommand<Rectangle>;

View File

@@ -0,0 +1,56 @@
'use strict';
var Extensions = require('../../../../extensions/Extensions.js');
"use strict";
const buildRectangle = {
extension: {
type: Extensions.ExtensionType.ShapeBuilder,
name: "rectangle"
},
build(shape, points) {
const rectData = shape;
const x = rectData.x;
const y = rectData.y;
const width = rectData.width;
const height = rectData.height;
if (!(width >= 0 && height >= 0)) {
return points;
}
points[0] = x;
points[1] = y;
points[2] = x + width;
points[3] = y;
points[4] = x + width;
points[5] = y + height;
points[6] = x;
points[7] = y + height;
return points;
},
triangulate(points, vertices, verticesStride, verticesOffset, indices, indicesOffset) {
let count = 0;
verticesOffset *= verticesStride;
vertices[verticesOffset + count] = points[0];
vertices[verticesOffset + count + 1] = points[1];
count += verticesStride;
vertices[verticesOffset + count] = points[2];
vertices[verticesOffset + count + 1] = points[3];
count += verticesStride;
vertices[verticesOffset + count] = points[6];
vertices[verticesOffset + count + 1] = points[7];
count += verticesStride;
vertices[verticesOffset + count] = points[4];
vertices[verticesOffset + count + 1] = points[5];
count += verticesStride;
const verticesIndex = verticesOffset / verticesStride;
indices[indicesOffset++] = verticesIndex;
indices[indicesOffset++] = verticesIndex + 1;
indices[indicesOffset++] = verticesIndex + 2;
indices[indicesOffset++] = verticesIndex + 1;
indices[indicesOffset++] = verticesIndex + 3;
indices[indicesOffset++] = verticesIndex + 2;
}
};
exports.buildRectangle = buildRectangle;
//# sourceMappingURL=buildRectangle.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"buildRectangle.js","sources":["../../../../../src/scene/graphics/shared/buildCommands/buildRectangle.ts"],"sourcesContent":["import { ExtensionType } from '../../../../extensions/Extensions';\n\nimport type { Rectangle } from '../../../../maths/shapes/Rectangle';\nimport type { ShapeBuildCommand } from './ShapeBuildCommand';\n\n/**\n * Builds a rectangle to draw\n *\n * Ignored from docs since it is not directly exposed.\n * @ignore\n * @private\n */\nexport const buildRectangle: ShapeBuildCommand<Rectangle> = {\n extension: {\n type: ExtensionType.ShapeBuilder,\n name: 'rectangle',\n },\n\n build(shape: Rectangle, points: number[]): number[]\n {\n const rectData = shape;\n const x = rectData.x;\n const y = rectData.y;\n const width = rectData.width;\n const height = rectData.height;\n\n if (!(width >= 0 && height >= 0))\n {\n return points;\n }\n\n points[0] = x;\n points[1] = y;\n points[2] = x + width;\n points[3] = y;\n points[4] = x + width;\n points[5] = y + height;\n points[6] = x;\n points[7] = y + height;\n\n return points;\n },\n\n triangulate(\n points: number[],\n\n vertices: number[],\n verticesStride: number,\n verticesOffset: number,\n\n indices: number[],\n indicesOffset: number\n )\n {\n let count = 0;\n\n verticesOffset *= verticesStride;\n\n vertices[verticesOffset + count] = points[0];\n vertices[verticesOffset + count + 1] = points[1];\n\n count += verticesStride;\n\n vertices[verticesOffset + count] = points[2];\n vertices[verticesOffset + count + 1] = points[3];\n\n count += verticesStride;\n\n vertices[verticesOffset + count] = points[6];\n vertices[verticesOffset + count + 1] = points[7];\n\n count += verticesStride;\n\n vertices[verticesOffset + count] = points[4];\n vertices[verticesOffset + count + 1] = points[5];\n\n count += verticesStride;\n\n const verticesIndex = verticesOffset / verticesStride;\n\n // triangle 1\n indices[indicesOffset++] = verticesIndex;\n indices[indicesOffset++] = verticesIndex + 1;\n indices[indicesOffset++] = verticesIndex + 2;\n\n // triangle 2\n indices[indicesOffset++] = verticesIndex + 1;\n indices[indicesOffset++] = verticesIndex + 3;\n indices[indicesOffset++] = verticesIndex + 2;\n },\n};\n"],"names":["ExtensionType"],"mappings":";;;;;AAYO,MAAM,cAA+C,GAAA;AAAA,EACxD,SAAW,EAAA;AAAA,IACP,MAAMA,wBAAc,CAAA,YAAA;AAAA,IACpB,IAAM,EAAA,WAAA;AAAA,GACV;AAAA,EAEA,KAAA,CAAM,OAAkB,MACxB,EAAA;AACI,IAAA,MAAM,QAAW,GAAA,KAAA,CAAA;AACjB,IAAA,MAAM,IAAI,QAAS,CAAA,CAAA,CAAA;AACnB,IAAA,MAAM,IAAI,QAAS,CAAA,CAAA,CAAA;AACnB,IAAA,MAAM,QAAQ,QAAS,CAAA,KAAA,CAAA;AACvB,IAAA,MAAM,SAAS,QAAS,CAAA,MAAA,CAAA;AAExB,IAAA,IAAI,EAAE,KAAA,IAAS,CAAK,IAAA,MAAA,IAAU,CAC9B,CAAA,EAAA;AACI,MAAO,OAAA,MAAA,CAAA;AAAA,KACX;AAEA,IAAA,MAAA,CAAO,CAAC,CAAI,GAAA,CAAA,CAAA;AACZ,IAAA,MAAA,CAAO,CAAC,CAAI,GAAA,CAAA,CAAA;AACZ,IAAO,MAAA,CAAA,CAAC,IAAI,CAAI,GAAA,KAAA,CAAA;AAChB,IAAA,MAAA,CAAO,CAAC,CAAI,GAAA,CAAA,CAAA;AACZ,IAAO,MAAA,CAAA,CAAC,IAAI,CAAI,GAAA,KAAA,CAAA;AAChB,IAAO,MAAA,CAAA,CAAC,IAAI,CAAI,GAAA,MAAA,CAAA;AAChB,IAAA,MAAA,CAAO,CAAC,CAAI,GAAA,CAAA,CAAA;AACZ,IAAO,MAAA,CAAA,CAAC,IAAI,CAAI,GAAA,MAAA,CAAA;AAEhB,IAAO,OAAA,MAAA,CAAA;AAAA,GACX;AAAA,EAEA,YACI,MAEA,EAAA,QAAA,EACA,cACA,EAAA,cAAA,EAEA,SACA,aAEJ,EAAA;AACI,IAAA,IAAI,KAAQ,GAAA,CAAA,CAAA;AAEZ,IAAkB,cAAA,IAAA,cAAA,CAAA;AAElB,IAAA,QAAA,CAAS,cAAiB,GAAA,KAAK,CAAI,GAAA,MAAA,CAAO,CAAC,CAAA,CAAA;AAC3C,IAAA,QAAA,CAAS,cAAiB,GAAA,KAAA,GAAQ,CAAC,CAAA,GAAI,OAAO,CAAC,CAAA,CAAA;AAE/C,IAAS,KAAA,IAAA,cAAA,CAAA;AAET,IAAA,QAAA,CAAS,cAAiB,GAAA,KAAK,CAAI,GAAA,MAAA,CAAO,CAAC,CAAA,CAAA;AAC3C,IAAA,QAAA,CAAS,cAAiB,GAAA,KAAA,GAAQ,CAAC,CAAA,GAAI,OAAO,CAAC,CAAA,CAAA;AAE/C,IAAS,KAAA,IAAA,cAAA,CAAA;AAET,IAAA,QAAA,CAAS,cAAiB,GAAA,KAAK,CAAI,GAAA,MAAA,CAAO,CAAC,CAAA,CAAA;AAC3C,IAAA,QAAA,CAAS,cAAiB,GAAA,KAAA,GAAQ,CAAC,CAAA,GAAI,OAAO,CAAC,CAAA,CAAA;AAE/C,IAAS,KAAA,IAAA,cAAA,CAAA;AAET,IAAA,QAAA,CAAS,cAAiB,GAAA,KAAK,CAAI,GAAA,MAAA,CAAO,CAAC,CAAA,CAAA;AAC3C,IAAA,QAAA,CAAS,cAAiB,GAAA,KAAA,GAAQ,CAAC,CAAA,GAAI,OAAO,CAAC,CAAA,CAAA;AAE/C,IAAS,KAAA,IAAA,cAAA,CAAA;AAET,IAAA,MAAM,gBAAgB,cAAiB,GAAA,cAAA,CAAA;AAGvC,IAAA,OAAA,CAAQ,eAAe,CAAI,GAAA,aAAA,CAAA;AAC3B,IAAQ,OAAA,CAAA,aAAA,EAAe,IAAI,aAAgB,GAAA,CAAA,CAAA;AAC3C,IAAQ,OAAA,CAAA,aAAA,EAAe,IAAI,aAAgB,GAAA,CAAA,CAAA;AAG3C,IAAQ,OAAA,CAAA,aAAA,EAAe,IAAI,aAAgB,GAAA,CAAA,CAAA;AAC3C,IAAQ,OAAA,CAAA,aAAA,EAAe,IAAI,aAAgB,GAAA,CAAA,CAAA;AAC3C,IAAQ,OAAA,CAAA,aAAA,EAAe,IAAI,aAAgB,GAAA,CAAA,CAAA;AAAA,GAC/C;AACJ;;;;"}

View File

@@ -0,0 +1,54 @@
import { ExtensionType } from '../../../../extensions/Extensions.mjs';
"use strict";
const buildRectangle = {
extension: {
type: ExtensionType.ShapeBuilder,
name: "rectangle"
},
build(shape, points) {
const rectData = shape;
const x = rectData.x;
const y = rectData.y;
const width = rectData.width;
const height = rectData.height;
if (!(width >= 0 && height >= 0)) {
return points;
}
points[0] = x;
points[1] = y;
points[2] = x + width;
points[3] = y;
points[4] = x + width;
points[5] = y + height;
points[6] = x;
points[7] = y + height;
return points;
},
triangulate(points, vertices, verticesStride, verticesOffset, indices, indicesOffset) {
let count = 0;
verticesOffset *= verticesStride;
vertices[verticesOffset + count] = points[0];
vertices[verticesOffset + count + 1] = points[1];
count += verticesStride;
vertices[verticesOffset + count] = points[2];
vertices[verticesOffset + count + 1] = points[3];
count += verticesStride;
vertices[verticesOffset + count] = points[6];
vertices[verticesOffset + count + 1] = points[7];
count += verticesStride;
vertices[verticesOffset + count] = points[4];
vertices[verticesOffset + count + 1] = points[5];
count += verticesStride;
const verticesIndex = verticesOffset / verticesStride;
indices[indicesOffset++] = verticesIndex;
indices[indicesOffset++] = verticesIndex + 1;
indices[indicesOffset++] = verticesIndex + 2;
indices[indicesOffset++] = verticesIndex + 1;
indices[indicesOffset++] = verticesIndex + 3;
indices[indicesOffset++] = verticesIndex + 2;
}
};
export { buildRectangle };
//# sourceMappingURL=buildRectangle.mjs.map

Some files were not shown because too many files have changed in this diff Show More