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,22 @@
import { Container } from '../../../scene/container/Container';
import type { ExtensionMetadata } from '../../../extensions/Extensions';
import type { Point } from '../../../maths/point/Point';
import type { Bounds } from '../../../scene/container/bounds/Bounds';
import type { Effect } from '../../../scene/container/Effect';
import type { PoolItem } from '../../../utils/pool/Pool';
export declare class StencilMask implements Effect, PoolItem {
static extension: ExtensionMetadata;
priority: number;
mask: Container;
pipe: string;
constructor(options: {
mask: Container;
});
init(mask: Container): void;
reset(): void;
addBounds(bounds: Bounds, skipUpdateTransform: boolean): void;
addLocalBounds(bounds: Bounds, localRoot: Container): void;
containsPoint(point: Point, hitTestFn: (container: Container, point: Point) => boolean): boolean;
destroy(): void;
static test(mask: any): boolean;
}

View File

@@ -0,0 +1,47 @@
'use strict';
var Extensions = require('../../../extensions/Extensions.js');
var Container = require('../../../scene/container/Container.js');
var addMaskBounds = require('../utils/addMaskBounds.js');
var addMaskLocalBounds = require('../utils/addMaskLocalBounds.js');
"use strict";
class StencilMask {
constructor(options) {
this.priority = 0;
this.pipe = "stencilMask";
if (options?.mask) {
this.init(options.mask);
}
}
init(mask) {
this.mask = mask;
this.mask.includeInBuild = false;
this.mask.measurable = false;
}
reset() {
this.mask.measurable = true;
this.mask.includeInBuild = true;
this.mask = null;
}
addBounds(bounds, skipUpdateTransform) {
addMaskBounds.addMaskBounds(this.mask, bounds, skipUpdateTransform);
}
addLocalBounds(bounds, localRoot) {
addMaskLocalBounds.addMaskLocalBounds(this.mask, bounds, localRoot);
}
containsPoint(point, hitTestFn) {
const mask = this.mask;
return hitTestFn(mask, point);
}
destroy() {
this.reset();
}
static test(mask) {
return mask instanceof Container.Container;
}
}
StencilMask.extension = Extensions.ExtensionType.MaskEffect;
exports.StencilMask = StencilMask;
//# sourceMappingURL=StencilMask.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"StencilMask.js","sources":["../../../../src/rendering/mask/stencil/StencilMask.ts"],"sourcesContent":["import { ExtensionType } from '../../../extensions/Extensions';\nimport { Container } from '../../../scene/container/Container';\nimport { addMaskBounds } from '../utils/addMaskBounds';\nimport { addMaskLocalBounds } from '../utils/addMaskLocalBounds';\n\nimport type { ExtensionMetadata } from '../../../extensions/Extensions';\nimport type { Point } from '../../../maths/point/Point';\nimport type { Bounds } from '../../../scene/container/bounds/Bounds';\nimport type { Effect } from '../../../scene/container/Effect';\nimport type { PoolItem } from '../../../utils/pool/Pool';\n\nexport class StencilMask implements Effect, PoolItem\n{\n public static extension: ExtensionMetadata = ExtensionType.MaskEffect;\n\n public priority = 0;\n public mask: Container;\n public pipe = 'stencilMask';\n\n constructor(options: {mask: Container})\n {\n if (options?.mask)\n {\n this.init(options.mask);\n }\n }\n\n public init(mask: Container): void\n {\n this.mask = mask;\n this.mask.includeInBuild = false;\n this.mask.measurable = false;\n }\n\n public reset()\n {\n this.mask.measurable = true;\n this.mask.includeInBuild = true;\n this.mask = null;\n }\n\n public addBounds(bounds: Bounds, skipUpdateTransform: boolean): void\n {\n addMaskBounds(this.mask, bounds, skipUpdateTransform);\n }\n\n public addLocalBounds(bounds: Bounds, localRoot: Container): void\n {\n addMaskLocalBounds(this.mask, bounds, localRoot);\n }\n\n public containsPoint(point: Point, hitTestFn: (container: Container, point: Point) => boolean): boolean\n {\n const mask = this.mask as any;\n\n // if the point is in the mask, yay!\n return hitTestFn(mask, point);\n }\n\n public destroy(): void\n {\n this.reset();\n }\n\n public static test(mask: any): boolean\n {\n return mask instanceof Container;\n }\n}\n"],"names":["addMaskBounds","addMaskLocalBounds","Container","ExtensionType"],"mappings":";;;;;;;;AAWO,MAAM,WACb,CAAA;AAAA,EAOI,YAAY,OACZ,EAAA;AALA,IAAA,IAAA,CAAO,QAAW,GAAA,CAAA,CAAA;AAElB,IAAA,IAAA,CAAO,IAAO,GAAA,aAAA,CAAA;AAIV,IAAA,IAAI,SAAS,IACb,EAAA;AACI,MAAK,IAAA,CAAA,IAAA,CAAK,QAAQ,IAAI,CAAA,CAAA;AAAA,KAC1B;AAAA,GACJ;AAAA,EAEO,KAAK,IACZ,EAAA;AACI,IAAA,IAAA,CAAK,IAAO,GAAA,IAAA,CAAA;AACZ,IAAA,IAAA,CAAK,KAAK,cAAiB,GAAA,KAAA,CAAA;AAC3B,IAAA,IAAA,CAAK,KAAK,UAAa,GAAA,KAAA,CAAA;AAAA,GAC3B;AAAA,EAEO,KACP,GAAA;AACI,IAAA,IAAA,CAAK,KAAK,UAAa,GAAA,IAAA,CAAA;AACvB,IAAA,IAAA,CAAK,KAAK,cAAiB,GAAA,IAAA,CAAA;AAC3B,IAAA,IAAA,CAAK,IAAO,GAAA,IAAA,CAAA;AAAA,GAChB;AAAA,EAEO,SAAA,CAAU,QAAgB,mBACjC,EAAA;AACI,IAAcA,2BAAA,CAAA,IAAA,CAAK,IAAM,EAAA,MAAA,EAAQ,mBAAmB,CAAA,CAAA;AAAA,GACxD;AAAA,EAEO,cAAA,CAAe,QAAgB,SACtC,EAAA;AACI,IAAmBC,qCAAA,CAAA,IAAA,CAAK,IAAM,EAAA,MAAA,EAAQ,SAAS,CAAA,CAAA;AAAA,GACnD;AAAA,EAEO,aAAA,CAAc,OAAc,SACnC,EAAA;AACI,IAAA,MAAM,OAAO,IAAK,CAAA,IAAA,CAAA;AAGlB,IAAO,OAAA,SAAA,CAAU,MAAM,KAAK,CAAA,CAAA;AAAA,GAChC;AAAA,EAEO,OACP,GAAA;AACI,IAAA,IAAA,CAAK,KAAM,EAAA,CAAA;AAAA,GACf;AAAA,EAEA,OAAc,KAAK,IACnB,EAAA;AACI,IAAA,OAAO,IAAgB,YAAAC,mBAAA,CAAA;AAAA,GAC3B;AACJ,CAAA;AAzDa,WAAA,CAEK,YAA+BC,wBAAc,CAAA,UAAA;;;;"}

View File

@@ -0,0 +1,45 @@
import { ExtensionType } from '../../../extensions/Extensions.mjs';
import { Container } from '../../../scene/container/Container.mjs';
import { addMaskBounds } from '../utils/addMaskBounds.mjs';
import { addMaskLocalBounds } from '../utils/addMaskLocalBounds.mjs';
"use strict";
class StencilMask {
constructor(options) {
this.priority = 0;
this.pipe = "stencilMask";
if (options?.mask) {
this.init(options.mask);
}
}
init(mask) {
this.mask = mask;
this.mask.includeInBuild = false;
this.mask.measurable = false;
}
reset() {
this.mask.measurable = true;
this.mask.includeInBuild = true;
this.mask = null;
}
addBounds(bounds, skipUpdateTransform) {
addMaskBounds(this.mask, bounds, skipUpdateTransform);
}
addLocalBounds(bounds, localRoot) {
addMaskLocalBounds(this.mask, bounds, localRoot);
}
containsPoint(point, hitTestFn) {
const mask = this.mask;
return hitTestFn(mask, point);
}
destroy() {
this.reset();
}
static test(mask) {
return mask instanceof Container;
}
}
StencilMask.extension = ExtensionType.MaskEffect;
export { StencilMask };
//# sourceMappingURL=StencilMask.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"StencilMask.mjs","sources":["../../../../src/rendering/mask/stencil/StencilMask.ts"],"sourcesContent":["import { ExtensionType } from '../../../extensions/Extensions';\nimport { Container } from '../../../scene/container/Container';\nimport { addMaskBounds } from '../utils/addMaskBounds';\nimport { addMaskLocalBounds } from '../utils/addMaskLocalBounds';\n\nimport type { ExtensionMetadata } from '../../../extensions/Extensions';\nimport type { Point } from '../../../maths/point/Point';\nimport type { Bounds } from '../../../scene/container/bounds/Bounds';\nimport type { Effect } from '../../../scene/container/Effect';\nimport type { PoolItem } from '../../../utils/pool/Pool';\n\nexport class StencilMask implements Effect, PoolItem\n{\n public static extension: ExtensionMetadata = ExtensionType.MaskEffect;\n\n public priority = 0;\n public mask: Container;\n public pipe = 'stencilMask';\n\n constructor(options: {mask: Container})\n {\n if (options?.mask)\n {\n this.init(options.mask);\n }\n }\n\n public init(mask: Container): void\n {\n this.mask = mask;\n this.mask.includeInBuild = false;\n this.mask.measurable = false;\n }\n\n public reset()\n {\n this.mask.measurable = true;\n this.mask.includeInBuild = true;\n this.mask = null;\n }\n\n public addBounds(bounds: Bounds, skipUpdateTransform: boolean): void\n {\n addMaskBounds(this.mask, bounds, skipUpdateTransform);\n }\n\n public addLocalBounds(bounds: Bounds, localRoot: Container): void\n {\n addMaskLocalBounds(this.mask, bounds, localRoot);\n }\n\n public containsPoint(point: Point, hitTestFn: (container: Container, point: Point) => boolean): boolean\n {\n const mask = this.mask as any;\n\n // if the point is in the mask, yay!\n return hitTestFn(mask, point);\n }\n\n public destroy(): void\n {\n this.reset();\n }\n\n public static test(mask: any): boolean\n {\n return mask instanceof Container;\n }\n}\n"],"names":[],"mappings":";;;;;;AAWO,MAAM,WACb,CAAA;AAAA,EAOI,YAAY,OACZ,EAAA;AALA,IAAA,IAAA,CAAO,QAAW,GAAA,CAAA,CAAA;AAElB,IAAA,IAAA,CAAO,IAAO,GAAA,aAAA,CAAA;AAIV,IAAA,IAAI,SAAS,IACb,EAAA;AACI,MAAK,IAAA,CAAA,IAAA,CAAK,QAAQ,IAAI,CAAA,CAAA;AAAA,KAC1B;AAAA,GACJ;AAAA,EAEO,KAAK,IACZ,EAAA;AACI,IAAA,IAAA,CAAK,IAAO,GAAA,IAAA,CAAA;AACZ,IAAA,IAAA,CAAK,KAAK,cAAiB,GAAA,KAAA,CAAA;AAC3B,IAAA,IAAA,CAAK,KAAK,UAAa,GAAA,KAAA,CAAA;AAAA,GAC3B;AAAA,EAEO,KACP,GAAA;AACI,IAAA,IAAA,CAAK,KAAK,UAAa,GAAA,IAAA,CAAA;AACvB,IAAA,IAAA,CAAK,KAAK,cAAiB,GAAA,IAAA,CAAA;AAC3B,IAAA,IAAA,CAAK,IAAO,GAAA,IAAA,CAAA;AAAA,GAChB;AAAA,EAEO,SAAA,CAAU,QAAgB,mBACjC,EAAA;AACI,IAAc,aAAA,CAAA,IAAA,CAAK,IAAM,EAAA,MAAA,EAAQ,mBAAmB,CAAA,CAAA;AAAA,GACxD;AAAA,EAEO,cAAA,CAAe,QAAgB,SACtC,EAAA;AACI,IAAmB,kBAAA,CAAA,IAAA,CAAK,IAAM,EAAA,MAAA,EAAQ,SAAS,CAAA,CAAA;AAAA,GACnD;AAAA,EAEO,aAAA,CAAc,OAAc,SACnC,EAAA;AACI,IAAA,MAAM,OAAO,IAAK,CAAA,IAAA,CAAA;AAGlB,IAAO,OAAA,SAAA,CAAU,MAAM,KAAK,CAAA,CAAA;AAAA,GAChC;AAAA,EAEO,OACP,GAAA;AACI,IAAA,IAAA,CAAK,KAAM,EAAA,CAAA;AAAA,GACf;AAAA,EAEA,OAAc,KAAK,IACnB,EAAA;AACI,IAAA,OAAO,IAAgB,YAAA,SAAA,CAAA;AAAA,GAC3B;AACJ,CAAA;AAzDa,WAAA,CAEK,YAA+B,aAAc,CAAA,UAAA;;;;"}

View File

@@ -0,0 +1,29 @@
import { ExtensionType } from '../../../extensions/Extensions';
import type { Container } from '../../../scene/container/Container';
import type { Effect } from '../../../scene/container/Effect';
import type { Instruction } from '../../renderers/shared/instructions/Instruction';
import type { InstructionSet } from '../../renderers/shared/instructions/InstructionSet';
import type { InstructionPipe } from '../../renderers/shared/instructions/RenderPipe';
import type { Renderer } from '../../renderers/types';
import type { StencilMask } from './StencilMask';
type MaskMode = 'pushMaskBegin' | 'pushMaskEnd' | 'popMaskBegin' | 'popMaskEnd';
export interface StencilMaskInstruction extends Instruction {
renderPipeId: 'stencilMask';
action: MaskMode;
mask: StencilMask;
}
export declare class StencilMaskPipe implements InstructionPipe<StencilMaskInstruction> {
static extension: {
readonly type: readonly [ExtensionType.WebGLPipes, ExtensionType.WebGPUPipes, ExtensionType.CanvasPipes];
readonly name: "stencilMask";
};
private _renderer;
private _maskStackHash;
private _maskHash;
constructor(renderer: Renderer);
push(mask: Effect, _container: Container, instructionSet: InstructionSet): void;
pop(mask: Effect, _container: Container, instructionSet: InstructionSet): void;
execute(instruction: StencilMaskInstruction): void;
destroy(): void;
}
export {};

View File

@@ -0,0 +1,120 @@
'use strict';
var Extensions = require('../../../extensions/Extensions.js');
var buildInstructions = require('../../../scene/container/utils/buildInstructions.js');
var _const$1 = require('../../renderers/gl/const.js');
var _const = require('../../renderers/shared/state/const.js');
"use strict";
class StencilMaskPipe {
constructor(renderer) {
// used when building and also when executing..
this._maskStackHash = {};
this._maskHash = /* @__PURE__ */ new WeakMap();
this._renderer = renderer;
}
push(mask, _container, instructionSet) {
var _a;
const effect = mask;
const renderer = this._renderer;
renderer.renderPipes.batch.break(instructionSet);
renderer.renderPipes.blendMode.setBlendMode(effect.mask, "none", instructionSet);
instructionSet.add({
renderPipeId: "stencilMask",
action: "pushMaskBegin",
mask,
canBundle: false
});
const maskContainer = effect.mask;
maskContainer.includeInBuild = true;
if (!this._maskHash.has(effect)) {
this._maskHash.set(effect, {
instructionsStart: 0,
instructionsLength: 0
});
}
const maskData = this._maskHash.get(effect);
maskData.instructionsStart = instructionSet.instructionSize;
buildInstructions.collectAllRenderables(
maskContainer,
instructionSet,
renderer
);
maskContainer.includeInBuild = false;
renderer.renderPipes.batch.break(instructionSet);
instructionSet.add({
renderPipeId: "stencilMask",
action: "pushMaskEnd",
mask,
canBundle: false
});
const instructionsLength = instructionSet.instructionSize - maskData.instructionsStart - 1;
maskData.instructionsLength = instructionsLength;
const renderTargetUid = renderer.renderTarget.renderTarget.uid;
(_a = this._maskStackHash)[renderTargetUid] ?? (_a[renderTargetUid] = 0);
}
pop(mask, _container, instructionSet) {
const effect = mask;
const renderer = this._renderer;
renderer.renderPipes.batch.break(instructionSet);
renderer.renderPipes.blendMode.setBlendMode(effect.mask, "none", instructionSet);
instructionSet.add({
renderPipeId: "stencilMask",
action: "popMaskBegin",
canBundle: false
});
const maskData = this._maskHash.get(mask);
for (let i = 0; i < maskData.instructionsLength; i++) {
instructionSet.instructions[instructionSet.instructionSize++] = instructionSet.instructions[maskData.instructionsStart++];
}
instructionSet.add({
renderPipeId: "stencilMask",
action: "popMaskEnd",
canBundle: false
});
}
execute(instruction) {
var _a;
const renderer = this._renderer;
const renderTargetUid = renderer.renderTarget.renderTarget.uid;
let maskStackIndex = (_a = this._maskStackHash)[renderTargetUid] ?? (_a[renderTargetUid] = 0);
if (instruction.action === "pushMaskBegin") {
renderer.renderTarget.ensureDepthStencil();
renderer.stencil.setStencilMode(_const.STENCIL_MODES.RENDERING_MASK_ADD, maskStackIndex);
maskStackIndex++;
renderer.colorMask.setMask(0);
} else if (instruction.action === "pushMaskEnd") {
renderer.stencil.setStencilMode(_const.STENCIL_MODES.MASK_ACTIVE, maskStackIndex);
renderer.colorMask.setMask(15);
} else if (instruction.action === "popMaskBegin") {
renderer.colorMask.setMask(0);
if (maskStackIndex !== 0) {
renderer.stencil.setStencilMode(_const.STENCIL_MODES.RENDERING_MASK_REMOVE, maskStackIndex);
} else {
renderer.renderTarget.clear(null, _const$1.CLEAR.STENCIL);
renderer.stencil.setStencilMode(_const.STENCIL_MODES.DISABLED, maskStackIndex);
}
maskStackIndex--;
} else if (instruction.action === "popMaskEnd") {
renderer.stencil.setStencilMode(_const.STENCIL_MODES.MASK_ACTIVE, maskStackIndex);
renderer.colorMask.setMask(15);
}
this._maskStackHash[renderTargetUid] = maskStackIndex;
}
destroy() {
this._renderer = null;
this._maskStackHash = null;
this._maskHash = null;
}
}
StencilMaskPipe.extension = {
type: [
Extensions.ExtensionType.WebGLPipes,
Extensions.ExtensionType.WebGPUPipes,
Extensions.ExtensionType.CanvasPipes
],
name: "stencilMask"
};
exports.StencilMaskPipe = StencilMaskPipe;
//# sourceMappingURL=StencilMaskPipe.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,118 @@
import { ExtensionType } from '../../../extensions/Extensions.mjs';
import { collectAllRenderables } from '../../../scene/container/utils/buildInstructions.mjs';
import { CLEAR } from '../../renderers/gl/const.mjs';
import { STENCIL_MODES } from '../../renderers/shared/state/const.mjs';
"use strict";
class StencilMaskPipe {
constructor(renderer) {
// used when building and also when executing..
this._maskStackHash = {};
this._maskHash = /* @__PURE__ */ new WeakMap();
this._renderer = renderer;
}
push(mask, _container, instructionSet) {
var _a;
const effect = mask;
const renderer = this._renderer;
renderer.renderPipes.batch.break(instructionSet);
renderer.renderPipes.blendMode.setBlendMode(effect.mask, "none", instructionSet);
instructionSet.add({
renderPipeId: "stencilMask",
action: "pushMaskBegin",
mask,
canBundle: false
});
const maskContainer = effect.mask;
maskContainer.includeInBuild = true;
if (!this._maskHash.has(effect)) {
this._maskHash.set(effect, {
instructionsStart: 0,
instructionsLength: 0
});
}
const maskData = this._maskHash.get(effect);
maskData.instructionsStart = instructionSet.instructionSize;
collectAllRenderables(
maskContainer,
instructionSet,
renderer
);
maskContainer.includeInBuild = false;
renderer.renderPipes.batch.break(instructionSet);
instructionSet.add({
renderPipeId: "stencilMask",
action: "pushMaskEnd",
mask,
canBundle: false
});
const instructionsLength = instructionSet.instructionSize - maskData.instructionsStart - 1;
maskData.instructionsLength = instructionsLength;
const renderTargetUid = renderer.renderTarget.renderTarget.uid;
(_a = this._maskStackHash)[renderTargetUid] ?? (_a[renderTargetUid] = 0);
}
pop(mask, _container, instructionSet) {
const effect = mask;
const renderer = this._renderer;
renderer.renderPipes.batch.break(instructionSet);
renderer.renderPipes.blendMode.setBlendMode(effect.mask, "none", instructionSet);
instructionSet.add({
renderPipeId: "stencilMask",
action: "popMaskBegin",
canBundle: false
});
const maskData = this._maskHash.get(mask);
for (let i = 0; i < maskData.instructionsLength; i++) {
instructionSet.instructions[instructionSet.instructionSize++] = instructionSet.instructions[maskData.instructionsStart++];
}
instructionSet.add({
renderPipeId: "stencilMask",
action: "popMaskEnd",
canBundle: false
});
}
execute(instruction) {
var _a;
const renderer = this._renderer;
const renderTargetUid = renderer.renderTarget.renderTarget.uid;
let maskStackIndex = (_a = this._maskStackHash)[renderTargetUid] ?? (_a[renderTargetUid] = 0);
if (instruction.action === "pushMaskBegin") {
renderer.renderTarget.ensureDepthStencil();
renderer.stencil.setStencilMode(STENCIL_MODES.RENDERING_MASK_ADD, maskStackIndex);
maskStackIndex++;
renderer.colorMask.setMask(0);
} else if (instruction.action === "pushMaskEnd") {
renderer.stencil.setStencilMode(STENCIL_MODES.MASK_ACTIVE, maskStackIndex);
renderer.colorMask.setMask(15);
} else if (instruction.action === "popMaskBegin") {
renderer.colorMask.setMask(0);
if (maskStackIndex !== 0) {
renderer.stencil.setStencilMode(STENCIL_MODES.RENDERING_MASK_REMOVE, maskStackIndex);
} else {
renderer.renderTarget.clear(null, CLEAR.STENCIL);
renderer.stencil.setStencilMode(STENCIL_MODES.DISABLED, maskStackIndex);
}
maskStackIndex--;
} else if (instruction.action === "popMaskEnd") {
renderer.stencil.setStencilMode(STENCIL_MODES.MASK_ACTIVE, maskStackIndex);
renderer.colorMask.setMask(15);
}
this._maskStackHash[renderTargetUid] = maskStackIndex;
}
destroy() {
this._renderer = null;
this._maskStackHash = null;
this._maskHash = null;
}
}
StencilMaskPipe.extension = {
type: [
ExtensionType.WebGLPipes,
ExtensionType.WebGPUPipes,
ExtensionType.CanvasPipes
],
name: "stencilMask"
};
export { StencilMaskPipe };
//# sourceMappingURL=StencilMaskPipe.mjs.map

File diff suppressed because one or more lines are too long