@needle-tools/engine
Version:
Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.
1,488 lines • 714 kB
JavaScript
import { Uniform$1 as u, Vector4 as de, Color as Q, Vector2 as p, CanvasTexture as Qi, RepeatWrapping as se, ShaderMaterial as T, NoBlending as z, WebGLRenderTarget as w, NearestFilter as P, EventDispatcher as wt, SRGBColorSpace as S, UnsignedByteType as Y, PerspectiveCamera as Be, BasicDepthPacking as W, REVISION as Pe, AlwaysDepth as Kt, LinearFilter as R, RGBADepthPacking as ae, FloatType as J, LessDepth as Pt, Vector3 as F, MeshDepthMaterial as Vi, LinearSRGBColorSpace as Je, NoColorSpace as tt, DepthTexture as Ce, DepthStencilFormat as Xt, UnsignedInt248Type as Zt, UnsignedIntType as Oe, RGBAFormat as H, Scene as dt, Matrix4 as O, HalfFloatType as $, Data3DTexture as Ze, Loader as Et, LoadingManager as ve, FileLoader as jt, ClampToEdgeWrapping as st, DataTexture as it, RedFormat as rt, MeshNormalMaterial as Wi, BackSide as Qe, DoubleSide as Ve, FrontSide as Yi, OrthographicCamera as Jt, Mesh as qt, Texture as qe, EqualDepth as vt, NotEqualDepth as _t, LinearMipmapLinearFilter as Ki, GreaterDepth as Xi, GreaterEqualDepth as Zi, LessEqualDepth as ji, NeverDepth as Ji, Material as $t, BufferGeometry as ei, BufferAttribute as _e, RGFormat as qi, DepthFormat as It, Sphere as _i } from "./three.js";
import { Pass as $i } from "./three-examples.js";
var er = "6.38.2", tr = class {
/**
* Frees internal resources.
*/
dispose() {
}
}, nt = 1 / 1e3, ir = 1e3, ti = class {
/**
* Constructs a new timer.
*/
constructor() {
this.startTime = performance.now(), this.previousTime = 0, this.currentTime = 0, this._delta = 0, this._elapsed = 0, this._fixedDelta = 1e3 / 60, this.timescale = 1, this.useFixedDelta = !1, this._autoReset = !1;
}
/**
* Enables or disables auto reset based on page visibility.
*
* If enabled, the timer will be reset when the page becomes visible. This effectively pauses the timer when the page
* is hidden. Has no effect if the API is not supported.
*
* @type {Boolean}
* @see https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
*/
get autoReset() {
return this._autoReset;
}
set autoReset(e) {
typeof document < "u" && document.hidden !== void 0 && (e ? document.addEventListener("visibilitychange", this) : document.removeEventListener("visibilitychange", this), this._autoReset = e);
}
get delta() {
return this._delta * nt;
}
get fixedDelta() {
return this._fixedDelta * nt;
}
set fixedDelta(e) {
this._fixedDelta = e * ir;
}
get elapsed() {
return this._elapsed * nt;
}
/**
* Updates this timer.
*
* @param {Boolean} [timestamp] - The current time in milliseconds.
*/
update(e) {
this.useFixedDelta ? this._delta = this.fixedDelta : (this.previousTime = this.currentTime, this.currentTime = (e !== void 0 ? e : performance.now()) - this.startTime, this._delta = this.currentTime - this.previousTime), this._delta *= this.timescale, this._elapsed += this._delta;
}
/**
* Resets this timer.
*/
reset() {
this._delta = 0, this._elapsed = 0, this.currentTime = performance.now() - this.startTime;
}
getDelta() {
return this.delta;
}
getElapsed() {
return this.elapsed;
}
handleEvent(e) {
document.hidden || (this.currentTime = performance.now() - this.startTime);
}
dispose() {
this.autoReset = !1;
}
}, rr = /* @__PURE__ */ (() => {
const e = new Float32Array([-1, -1, 0, 3, -1, 0, -1, 3, 0]), t = new Float32Array([0, 0, 2, 0, 0, 2]), i = new ei();
return i.setAttribute("position", new _e(e, 3)), i.setAttribute("uv", new _e(t, 2)), i;
})(), N = class pt {
/**
* A shared fullscreen triangle.
*
* The screen size is 2x2 units (NDC). A triangle needs to be 4x4 units to fill the screen.
* @see https://michaldrobot.com/2014/04/01/gcn-execution-patterns-in-full-screen-passes/
* @type {BufferGeometry}
* @internal
*/
static get fullscreenGeometry() {
return rr;
}
/**
* Constructs a new pass.
*
* @param {String} [name] - The name of this pass. Does not have to be unique.
* @param {Scene} [scene] - The scene to render. The default scene contains a single mesh that fills the screen.
* @param {Camera} [camera] - A camera. Fullscreen effect passes don't require a camera.
*/
constructor(t = "Pass", i = new dt(), r = new Jt()) {
this.name = t, this.renderer = null, this.scene = i, this.camera = r, this.screen = null, this.rtt = !0, this.needsSwap = !0, this.needsDepthTexture = !1, this.enabled = !0;
}
/**
* Sets the render to screen flag.
*
* If this flag is changed, the fullscreen material will be updated as well.
*
* @type {Boolean}
*/
get renderToScreen() {
return !this.rtt;
}
set renderToScreen(t) {
if (this.rtt === t) {
const i = this.fullscreenMaterial;
i !== null && (i.needsUpdate = !0), this.rtt = !t;
}
}
/**
* Sets the main scene.
*
* @type {Scene}
*/
set mainScene(t) {
}
/**
* Sets the main camera.
*
* @type {Camera}
*/
set mainCamera(t) {
}
/**
* Sets the renderer
*
* @deprecated
* @param {WebGLRenderer} renderer - The renderer.
*/
setRenderer(t) {
this.renderer = t;
}
/**
* Indicates whether this pass is enabled.
*
* @deprecated Use enabled instead.
* @return {Boolean} Whether this pass is enabled.
*/
isEnabled() {
return this.enabled;
}
/**
* Enables or disables this pass.
*
* @deprecated Use enabled instead.
* @param {Boolean} value - Whether the pass should be enabled.
*/
setEnabled(t) {
this.enabled = t;
}
/**
* The fullscreen material.
*
* @type {Material}
*/
get fullscreenMaterial() {
return this.screen !== null ? this.screen.material : null;
}
set fullscreenMaterial(t) {
let i = this.screen;
i !== null ? i.material = t : (i = new qt(pt.fullscreenGeometry, t), i.frustumCulled = !1, this.scene === null && (this.scene = new dt()), this.scene.add(i), this.screen = i);
}
/**
* Returns the current fullscreen material.
*
* @deprecated Use fullscreenMaterial instead.
* @return {Material} The current fullscreen material, or null if there is none.
*/
getFullscreenMaterial() {
return this.fullscreenMaterial;
}
/**
* Sets the fullscreen material.
*
* @deprecated Use fullscreenMaterial instead.
* @protected
* @param {Material} value - A fullscreen material.
*/
setFullscreenMaterial(t) {
this.fullscreenMaterial = t;
}
/**
* Returns the current depth texture.
*
* @return {Texture} The current depth texture, or null if there is none.
*/
getDepthTexture() {
return null;
}
/**
* Sets the depth texture.
*
* This method will be called automatically by the {@link EffectComposer}.
* You may override this method if your pass relies on the depth information of a preceding {@link RenderPass}.
*
* @param {Texture} depthTexture - A depth texture.
* @param {DepthPackingStrategy} [depthPacking=BasicDepthPacking] - The depth packing.
*/
setDepthTexture(t, i = W) {
}
/**
* Renders this pass.
*
* This is an abstract method that must be overridden.
*
* @abstract
* @throws {Error} An error is thrown if the method is not overridden.
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} inputBuffer - A frame buffer that contains the result of the previous pass.
* @param {WebGLRenderTarget} outputBuffer - A frame buffer that serves as the output render target unless this pass renders to screen.
* @param {Number} [deltaTime] - The time between the last frame and the current one in seconds.
* @param {Boolean} [stencilTest] - Indicates whether a stencil mask is active.
*/
render(t, i, r, a, n) {
throw new Error("Render method not implemented!");
}
/**
* Sets the size.
*
* You may override this method if you want to be informed about the size of the backbuffer/canvas.
* This method is called before {@link initialize} and every time the size of the {@link EffectComposer} changes.
*
* @param {Number} width - The width.
* @param {Number} height - The height.
*/
setSize(t, i) {
}
/**
* Performs initialization tasks.
*
* This method is called when this pass is added to an {@link EffectComposer}.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {Boolean} alpha - Whether the renderer uses the alpha channel or not.
* @param {Number} frameBufferType - The type of the main frame buffers.
*/
initialize(t, i, r) {
}
/**
* Performs a shallow search for disposable properties and deletes them.
*
* The {@link EffectComposer} calls this method when it is being destroyed. You can use it independently to free
* memory when you're certain that you don't need this pass anymore.
*/
dispose() {
for (const t of Object.keys(this)) {
const i = this[t];
(i instanceof w || i instanceof $t || i instanceof qe || i instanceof pt) && this[t].dispose();
}
this.fullscreenMaterial !== null && this.fullscreenMaterial.dispose();
}
}, ii = class extends N {
/**
* Constructs a new clear mask pass.
*/
constructor() {
super("ClearMaskPass", null, null), this.needsSwap = !1;
}
/**
* Disables the global stencil test.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} inputBuffer - A frame buffer that contains the result of the previous pass.
* @param {WebGLRenderTarget} outputBuffer - A frame buffer that serves as the output render target unless this pass renders to screen.
* @param {Number} [deltaTime] - The time between the last frame and the current one in seconds.
* @param {Boolean} [stencilTest] - Indicates whether a stencil mask is active.
*/
render(e, t, i, r, a) {
const n = e.state.buffers.stencil;
n.setLocked(!1), n.setTest(!1);
}
}, ar = `#ifdef COLOR_WRITE
#include <common>
#include <dithering_pars_fragment>
#ifdef FRAMEBUFFER_PRECISION_HIGH
uniform mediump sampler2D inputBuffer;
#else
uniform lowp sampler2D inputBuffer;
#endif
#endif
#ifdef DEPTH_WRITE
#include <packing>
#ifdef GL_FRAGMENT_PRECISION_HIGH
uniform highp sampler2D depthBuffer;
#else
uniform mediump sampler2D depthBuffer;
#endif
float readDepth(const in vec2 uv){
#if DEPTH_PACKING == 3201
return unpackRGBAToDepth(texture2D(depthBuffer,uv));
#else
return texture2D(depthBuffer,uv).r;
#endif
}
#endif
#ifdef USE_WEIGHTS
uniform vec4 channelWeights;
#endif
uniform float opacity;varying vec2 vUv;void main(){
#ifdef COLOR_WRITE
vec4 texel=texture2D(inputBuffer,vUv);
#ifdef USE_WEIGHTS
texel*=channelWeights;
#endif
gl_FragColor=opacity*texel;
#ifdef COLOR_SPACE_CONVERSION
#include <colorspace_fragment>
#endif
#include <dithering_fragment>
#else
gl_FragColor=vec4(0.0);
#endif
#ifdef DEPTH_WRITE
gl_FragDepth=readDepth(vUv);
#endif
}`, ue = "varying vec2 vUv;void main(){vUv=position.xy*0.5+0.5;gl_Position=vec4(position.xy,1.0,1.0);}", ze = class extends T {
/**
* Constructs a new copy material.
*/
constructor() {
super({
name: "CopyMaterial",
defines: {
COLOR_SPACE_CONVERSION: "1",
DEPTH_PACKING: "0",
COLOR_WRITE: "1"
},
uniforms: {
inputBuffer: new u(null),
depthBuffer: new u(null),
channelWeights: new u(null),
opacity: new u(1)
},
blending: z,
toneMapped: !1,
depthWrite: !1,
depthTest: !1,
fragmentShader: ar,
vertexShader: ue
}), this.depthFunc = Kt;
}
/**
* The input buffer.
*
* @type {Texture}
*/
get inputBuffer() {
return this.uniforms.inputBuffer.value;
}
set inputBuffer(e) {
const t = e !== null;
this.colorWrite !== t && (t ? this.defines.COLOR_WRITE = !0 : delete this.defines.COLOR_WRITE, this.colorWrite = t, this.needsUpdate = !0), this.uniforms.inputBuffer.value = e;
}
/**
* A depth buffer.
*
* @type {Texture}
*/
get depthBuffer() {
return this.uniforms.depthBuffer.value;
}
set depthBuffer(e) {
const t = e !== null;
this.depthWrite !== t && (t ? this.defines.DEPTH_WRITE = !0 : delete this.defines.DEPTH_WRITE, this.depthTest = t, this.depthWrite = t, this.needsUpdate = !0), this.uniforms.depthBuffer.value = e;
}
/**
* The depth packing strategy of the depth buffer.
*
* @type {DepthPackingStrategies}
*/
set depthPacking(e) {
this.defines.DEPTH_PACKING = e.toFixed(0), this.needsUpdate = !0;
}
/**
* Indicates whether output color space conversion is enabled.
*
* @type {Boolean}
*/
get colorSpaceConversion() {
return this.defines.COLOR_SPACE_CONVERSION !== void 0;
}
set colorSpaceConversion(e) {
this.colorSpaceConversion !== e && (e ? this.defines.COLOR_SPACE_CONVERSION = !0 : delete this.defines.COLOR_SPACE_CONVERSION, this.needsUpdate = !0);
}
/**
* Color channel weights that modulate texels from the input buffer.
*
* Set to `null` to disable.
*
* @type {Vector4 | null}
*/
get channelWeights() {
return this.uniforms.channelWeights.value;
}
set channelWeights(e) {
e !== null ? (this.defines.USE_WEIGHTS = "1", this.uniforms.channelWeights.value = e) : delete this.defines.USE_WEIGHTS, this.needsUpdate = !0;
}
/**
* Sets the input buffer.
*
* @deprecated Use inputBuffer instead.
* @param {Number} value - The buffer.
*/
setInputBuffer(e) {
this.uniforms.inputBuffer.value = e;
}
/**
* Returns the opacity.
*
* @deprecated Use opacity instead.
* @return {Number} The opacity.
*/
getOpacity(e) {
return this.uniforms.opacity.value;
}
/**
* Sets the opacity.
*
* @deprecated Use opacity instead.
* @param {Number} value - The opacity.
*/
setOpacity(e) {
this.uniforms.opacity.value = e;
}
}, Ne = class extends N {
/**
* Constructs a new save pass.
*
* @param {WebGLRenderTarget} [renderTarget] - A render target.
* @param {Boolean} [autoResize=true] - Whether the render target size should be updated automatically.
*/
constructor(e, t = !0) {
super("CopyPass"), this.fullscreenMaterial = new ze(), this.needsSwap = !1, this.renderTarget = e, e === void 0 && (this.renderTarget = new w(1, 1, {
minFilter: R,
magFilter: R,
stencilBuffer: !1,
depthBuffer: !1
}), this.renderTarget.texture.name = "CopyPass.Target"), this.autoResize = t;
}
/**
* Enables or disables auto resizing of the render target.
*
* @deprecated Use autoResize instead.
* @type {Boolean}
*/
get resize() {
return this.autoResize;
}
set resize(e) {
this.autoResize = e;
}
/**
* The output texture.
*
* @type {Texture}
*/
get texture() {
return this.renderTarget.texture;
}
/**
* Returns the output texture.
*
* @deprecated Use texture instead.
* @return {Texture} The texture.
*/
getTexture() {
return this.renderTarget.texture;
}
/**
* Enables or disables auto resizing of the render target.
*
* @deprecated Use autoResize instead.
* @param {Boolean} value - Whether the render target size should be updated automatically.
*/
setAutoResizeEnabled(e) {
this.autoResize = e;
}
/**
* Saves the input buffer.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} inputBuffer - A frame buffer that contains the result of the previous pass.
* @param {WebGLRenderTarget} outputBuffer - A frame buffer that serves as the output render target unless this pass renders to screen.
* @param {Number} [deltaTime] - The time between the last frame and the current one in seconds.
* @param {Boolean} [stencilTest] - Indicates whether a stencil mask is active.
*/
render(e, t, i, r, a) {
this.fullscreenMaterial.inputBuffer = t.texture, e.setRenderTarget(this.renderToScreen ? null : this.renderTarget), e.render(this.scene, this.camera);
}
/**
* Updates the size of this pass.
*
* @param {Number} width - The width.
* @param {Number} height - The height.
*/
setSize(e, t) {
this.autoResize && this.renderTarget.setSize(e, t);
}
/**
* Performs initialization tasks.
*
* @param {WebGLRenderer} renderer - A renderer.
* @param {Boolean} alpha - Whether the renderer uses the alpha channel.
* @param {Number} frameBufferType - The type of the main frame buffers.
*/
initialize(e, t, i) {
i !== void 0 && (this.renderTarget.texture.type = i, i !== Y ? this.fullscreenMaterial.defines.FRAMEBUFFER_PRECISION_HIGH = "1" : e !== null && e.outputColorSpace === S && (this.renderTarget.texture.colorSpace = S));
}
}, Rt = /* @__PURE__ */ new Q(), Ie = class extends N {
/**
* Constructs a new clear pass.
*
* @param {Boolean} [color=true] - Determines whether the color buffer should be cleared.
* @param {Boolean} [depth=true] - Determines whether the depth buffer should be cleared.
* @param {Boolean} [stencil=false] - Determines whether the stencil buffer should be cleared.
*/
constructor(e = !0, t = !0, i = !1) {
super("ClearPass", null, null), this.needsSwap = !1, this.color = e, this.depth = t, this.stencil = i, this.overrideClearColor = null, this.overrideClearAlpha = -1;
}
/**
* Sets the clear flags.
*
* @param {Boolean} color - Whether the color buffer should be cleared.
* @param {Boolean} depth - Whether the depth buffer should be cleared.
* @param {Boolean} stencil - Whether the stencil buffer should be cleared.
*/
setClearFlags(e, t, i) {
this.color = e, this.depth = t, this.stencil = i;
}
/**
* Returns the override clear color. Default is null.
*
* @deprecated Use overrideClearColor instead.
* @return {Color} The clear color.
*/
getOverrideClearColor() {
return this.overrideClearColor;
}
/**
* Sets the override clear color.
*
* @deprecated Use overrideClearColor instead.
* @param {Color} value - The clear color.
*/
setOverrideClearColor(e) {
this.overrideClearColor = e;
}
/**
* Returns the override clear alpha. Default is -1.
*
* @deprecated Use overrideClearAlpha instead.
* @return {Number} The clear alpha.
*/
getOverrideClearAlpha() {
return this.overrideClearAlpha;
}
/**
* Sets the override clear alpha.
*
* @deprecated Use overrideClearAlpha instead.
* @param {Number} value - The clear alpha.
*/
setOverrideClearAlpha(e) {
this.overrideClearAlpha = e;
}
/**
* Clears the input buffer or the screen.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} inputBuffer - A frame buffer that contains the result of the previous pass.
* @param {WebGLRenderTarget} outputBuffer - A frame buffer that serves as the output render target unless this pass renders to screen.
* @param {Number} [deltaTime] - The time between the last frame and the current one in seconds.
* @param {Boolean} [stencilTest] - Indicates whether a stencil mask is active.
*/
render(e, t, i, r, a) {
const n = this.overrideClearColor, s = this.overrideClearAlpha, o = e.getClearAlpha(), l = n !== null, c = s >= 0;
l ? (e.getClearColor(Rt), e.setClearColor(n, c ? s : o)) : c && e.setClearAlpha(s), e.setRenderTarget(this.renderToScreen ? null : t), e.clear(this.color, this.depth, this.stencil), l ? e.setClearColor(Rt, o) : c && e.setClearAlpha(o);
}
}, ri = class extends N {
/**
* Constructs a new mask pass.
*
* @param {Scene} scene - The scene to render.
* @param {Camera} camera - The camera to use.
*/
constructor(e, t) {
super("MaskPass", e, t), this.needsSwap = !1, this.clearPass = new Ie(!1, !1, !0), this.inverse = !1;
}
set mainScene(e) {
this.scene = e;
}
set mainCamera(e) {
this.camera = e;
}
/**
* Indicates whether the mask should be inverted.
*
* @type {Boolean}
*/
get inverted() {
return this.inverse;
}
set inverted(e) {
this.inverse = e;
}
/**
* Indicates whether this pass should clear the stencil buffer.
*
* @type {Boolean}
* @deprecated Use clearPass.enabled instead.
*/
get clear() {
return this.clearPass.enabled;
}
set clear(e) {
this.clearPass.enabled = e;
}
/**
* Returns the internal clear pass.
*
* @deprecated Use clearPass.enabled instead.
* @return {ClearPass} The clear pass.
*/
getClearPass() {
return this.clearPass;
}
/**
* Indicates whether the mask is inverted.
*
* @deprecated Use inverted instead.
* @return {Boolean} Whether the mask is inverted.
*/
isInverted() {
return this.inverted;
}
/**
* Enables or disable mask inversion.
*
* @deprecated Use inverted instead.
* @param {Boolean} value - Whether the mask should be inverted.
*/
setInverted(e) {
this.inverted = e;
}
/**
* Renders the effect.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} inputBuffer - A frame buffer that contains the result of the previous pass.
* @param {WebGLRenderTarget} outputBuffer - A frame buffer that serves as the output render target unless this pass renders to screen.
* @param {Number} [deltaTime] - The time between the last frame and the current one in seconds.
* @param {Boolean} [stencilTest] - Indicates whether a stencil mask is active.
*/
render(e, t, i, r, a) {
const n = e.getContext(), s = e.state.buffers, o = this.scene, l = this.camera, c = this.clearPass, f = this.inverted ? 0 : 1, h = 1 - f;
s.color.setMask(!1), s.depth.setMask(!1), s.color.setLocked(!0), s.depth.setLocked(!0), s.stencil.setTest(!0), s.stencil.setOp(n.REPLACE, n.REPLACE, n.REPLACE), s.stencil.setFunc(n.ALWAYS, f, 4294967295), s.stencil.setClear(h), s.stencil.setLocked(!0), this.clearPass.enabled && (this.renderToScreen ? c.render(e, null) : (c.render(e, t), c.render(e, i))), this.renderToScreen ? (e.setRenderTarget(null), e.render(o, l)) : (e.setRenderTarget(t), e.render(o, l), e.setRenderTarget(i), e.render(o, l)), s.color.setLocked(!1), s.depth.setLocked(!1), s.stencil.setLocked(!1), s.stencil.setFunc(n.EQUAL, 1, 4294967295), s.stencil.setOp(n.KEEP, n.KEEP, n.KEEP), s.stencil.setLocked(!0);
}
}, sr = class {
/**
* Constructs a new effect composer.
*
* @param {WebGLRenderer} renderer - The renderer that should be used.
* @param {Object} [options] - The options.
* @param {Boolean} [options.depthBuffer=true] - Whether the main render targets should have a depth buffer.
* @param {Boolean} [options.stencilBuffer=false] - Whether the main render targets should have a stencil buffer.
* @param {Boolean} [options.alpha] - Deprecated. Buffers are always RGBA since three r137.
* @param {Number} [options.multisampling=0] - The number of samples used for multisample antialiasing. Requires WebGL 2.
* @param {Number} [options.frameBufferType] - The type of the internal frame buffers. It's recommended to use HalfFloatType if possible.
*/
constructor(e = null, {
depthBuffer: t = !0,
stencilBuffer: i = !1,
multisampling: r = 0,
frameBufferType: a
} = {}) {
this.renderer = null, this.inputBuffer = this.createBuffer(t, i, a, r), this.outputBuffer = this.inputBuffer.clone(), this.copyPass = new Ne(), this.depthTexture = null, this.passes = [], this.timer = new ti(), this.autoRenderToScreen = !0, this.setRenderer(e);
}
/**
* The current amount of samples used for multisample anti-aliasing.
*
* @type {Number}
*/
get multisampling() {
return this.inputBuffer.samples || 0;
}
/**
* Sets the amount of MSAA samples.
*
* Requires WebGL 2. Set to zero to disable multisampling.
*
* @type {Number}
*/
set multisampling(e) {
const t = this.inputBuffer, i = this.multisampling;
i > 0 && e > 0 ? (this.inputBuffer.samples = e, this.outputBuffer.samples = e, this.inputBuffer.dispose(), this.outputBuffer.dispose()) : i !== e && (this.inputBuffer.dispose(), this.outputBuffer.dispose(), this.inputBuffer = this.createBuffer(
t.depthBuffer,
t.stencilBuffer,
t.texture.type,
e
), this.inputBuffer.depthTexture = this.depthTexture, this.outputBuffer = this.inputBuffer.clone());
}
/**
* Returns the internal timer.
*
* @return {Timer} The timer.
*/
getTimer() {
return this.timer;
}
/**
* Returns the renderer.
*
* @return {WebGLRenderer} The renderer.
*/
getRenderer() {
return this.renderer;
}
/**
* Sets the renderer.
*
* @param {WebGLRenderer} renderer - The renderer.
*/
setRenderer(e) {
if (this.renderer = e, e !== null) {
const t = e.getSize(new p()), i = e.getContext().getContextAttributes().alpha, r = this.inputBuffer.texture.type;
r === Y && e.outputColorSpace === S && (this.inputBuffer.texture.colorSpace = S, this.outputBuffer.texture.colorSpace = S, this.inputBuffer.dispose(), this.outputBuffer.dispose()), e.autoClear = !1, this.setSize(t.width, t.height);
for (const a of this.passes)
a.initialize(e, i, r);
}
}
/**
* Replaces the current renderer with the given one.
*
* The auto clear mechanism of the provided renderer will be disabled. If the new render size differs from the
* previous one, all passes will be updated.
*
* By default, the DOM element of the current renderer will automatically be removed from its parent node and the DOM
* element of the new renderer will take its place.
*
* @deprecated Use setRenderer instead.
* @param {WebGLRenderer} renderer - The new renderer.
* @param {Boolean} updateDOM - Indicates whether the old canvas should be replaced by the new one in the DOM.
* @return {WebGLRenderer} The old renderer.
*/
replaceRenderer(e, t = !0) {
const i = this.renderer, r = i.domElement.parentNode;
return this.setRenderer(e), t && r !== null && (r.removeChild(i.domElement), r.appendChild(e.domElement)), i;
}
/**
* Creates a depth texture attachment that will be provided to all passes.
*
* Note: When a shader reads from a depth texture and writes to a render target that uses the same depth texture
* attachment, the depth information will be lost. This happens even if `depthWrite` is disabled.
*
* @private
* @return {DepthTexture} The depth texture.
*/
createDepthTexture() {
const e = this.depthTexture = new Ce();
return this.inputBuffer.depthTexture = e, this.inputBuffer.dispose(), this.inputBuffer.stencilBuffer ? (e.format = Xt, e.type = Zt) : e.type = Oe, e;
}
/**
* Deletes the current depth texture.
*
* @private
*/
deleteDepthTexture() {
if (this.depthTexture !== null) {
this.depthTexture.dispose(), this.depthTexture = null, this.inputBuffer.depthTexture = null, this.inputBuffer.dispose();
for (const e of this.passes)
e.setDepthTexture(null);
}
}
/**
* Creates a new render target.
*
* @deprecated Create buffers manually via WebGLRenderTarget instead.
* @param {Boolean} depthBuffer - Whether the render target should have a depth buffer.
* @param {Boolean} stencilBuffer - Whether the render target should have a stencil buffer.
* @param {Number} type - The frame buffer type.
* @param {Number} multisampling - The number of samples to use for antialiasing.
* @return {WebGLRenderTarget} A new render target that equals the renderer's canvas.
*/
createBuffer(e, t, i, r) {
const a = this.renderer, n = a === null ? new p() : a.getDrawingBufferSize(new p()), s = {
minFilter: R,
magFilter: R,
stencilBuffer: t,
depthBuffer: e,
type: i
}, o = new w(n.width, n.height, s);
return r > 0 && (o.samples = r), i === Y && a !== null && a.outputColorSpace === S && (o.texture.colorSpace = S), o.texture.name = "EffectComposer.Buffer", o.texture.generateMipmaps = !1, o;
}
/**
* Can be used to change the main scene for all registered passes and effects.
*
* @param {Scene} scene - The scene.
*/
setMainScene(e) {
for (const t of this.passes)
t.mainScene = e;
}
/**
* Can be used to change the main camera for all registered passes and effects.
*
* @param {Camera} camera - The camera.
*/
setMainCamera(e) {
for (const t of this.passes)
t.mainCamera = e;
}
/**
* Adds a pass, optionally at a specific index.
*
* @param {Pass} pass - A new pass.
* @param {Number} [index] - An index at which the pass should be inserted.
*/
addPass(e, t) {
const i = this.passes, r = this.renderer, a = r.getDrawingBufferSize(new p()), n = r.getContext().getContextAttributes().alpha, s = this.inputBuffer.texture.type;
if (e.setRenderer(r), e.setSize(a.width, a.height), e.initialize(r, n, s), this.autoRenderToScreen && (i.length > 0 && (i[i.length - 1].renderToScreen = !1), e.renderToScreen && (this.autoRenderToScreen = !1)), t !== void 0 ? i.splice(t, 0, e) : i.push(e), this.autoRenderToScreen && (i[i.length - 1].renderToScreen = !0), e.needsDepthTexture || this.depthTexture !== null)
if (this.depthTexture === null) {
const o = this.createDepthTexture();
for (e of i)
e.setDepthTexture(o);
} else
e.setDepthTexture(this.depthTexture);
}
/**
* Removes a pass.
*
* @param {Pass} pass - The pass.
*/
removePass(e) {
const t = this.passes, i = t.indexOf(e);
if (i !== -1 && t.splice(i, 1).length > 0) {
if (this.depthTexture !== null) {
const n = (o, l) => o || l.needsDepthTexture;
t.reduce(n, !1) || (e.getDepthTexture() === this.depthTexture && e.setDepthTexture(null), this.deleteDepthTexture());
}
this.autoRenderToScreen && i === t.length && (e.renderToScreen = !1, t.length > 0 && (t[t.length - 1].renderToScreen = !0));
}
}
/**
* Removes all passes.
*/
removeAllPasses() {
const e = this.passes;
this.deleteDepthTexture(), e.length > 0 && (this.autoRenderToScreen && (e[e.length - 1].renderToScreen = !1), this.passes = []);
}
/**
* Renders all enabled passes in the order in which they were added.
*
* @param {Number} [deltaTime] - The time since the last frame in seconds.
*/
render(e) {
const t = this.renderer, i = this.copyPass;
let r = this.inputBuffer, a = this.outputBuffer, n = !1, s, o, l;
e === void 0 && (this.timer.update(), e = this.timer.getDelta());
for (const c of this.passes)
c.enabled && (c.render(t, r, a, e, n), c.needsSwap && (n && (i.renderToScreen = c.renderToScreen, s = t.getContext(), o = t.state.buffers.stencil, o.setFunc(s.NOTEQUAL, 1, 4294967295), i.render(t, r, a, e, n), o.setFunc(s.EQUAL, 1, 4294967295)), l = r, r = a, a = l), c instanceof ri ? n = !0 : c instanceof ii && (n = !1));
}
/**
* Sets the size of the buffers, passes and the renderer.
*
* @param {Number} width - The width.
* @param {Number} height - The height.
* @param {Boolean} [updateStyle] - Determines whether the style of the canvas should be updated.
*/
setSize(e, t, i) {
const r = this.renderer, a = r.getSize(new p());
(e === void 0 || t === void 0) && (e = a.width, t = a.height), (a.width !== e || a.height !== t) && r.setSize(e, t, i);
const n = r.getDrawingBufferSize(new p());
this.inputBuffer.setSize(n.width, n.height), this.outputBuffer.setSize(n.width, n.height);
for (const s of this.passes)
s.setSize(n.width, n.height);
}
/**
* Resets this composer by deleting all passes and creating new buffers.
*/
reset() {
this.dispose(), this.autoRenderToScreen = !0;
}
/**
* Disposes this composer and all passes.
*/
dispose() {
for (const e of this.passes)
e.dispose();
this.passes = [], this.inputBuffer !== null && this.inputBuffer.dispose(), this.outputBuffer !== null && this.outputBuffer.dispose(), this.deleteDepthTexture(), this.copyPass.dispose(), this.timer.dispose(), N.fullscreenGeometry.dispose();
}
}, V = {
NONE: 0,
DEPTH: 1,
CONVOLUTION: 2
}, B = {
FRAGMENT_HEAD: "FRAGMENT_HEAD",
FRAGMENT_MAIN_UV: "FRAGMENT_MAIN_UV",
FRAGMENT_MAIN_IMAGE: "FRAGMENT_MAIN_IMAGE",
VERTEX_HEAD: "VERTEX_HEAD",
VERTEX_MAIN_SUPPORT: "VERTEX_MAIN_SUPPORT"
}, ai = class {
/**
* Constructs new shader data.
*/
constructor() {
this.shaderParts = /* @__PURE__ */ new Map([
[B.FRAGMENT_HEAD, null],
[B.FRAGMENT_MAIN_UV, null],
[B.FRAGMENT_MAIN_IMAGE, null],
[B.VERTEX_HEAD, null],
[B.VERTEX_MAIN_SUPPORT, null]
]), this.defines = /* @__PURE__ */ new Map(), this.uniforms = /* @__PURE__ */ new Map(), this.blendModes = /* @__PURE__ */ new Map(), this.extensions = /* @__PURE__ */ new Set(), this.attributes = V.NONE, this.varyings = /* @__PURE__ */ new Set(), this.uvTransformation = !1, this.readDepth = !1, this.colorSpace = Je;
}
};
function bt(e) {
let t;
if (e === 0)
t = new Float64Array(0);
else if (e === 1)
t = new Float64Array([1]);
else if (e > 1) {
let i = new Float64Array(e), r = new Float64Array(e);
for (let a = 1; a <= e; ++a) {
for (let n = 0; n < a; ++n)
r[n] = n === 0 || n === a - 1 ? 1 : i[n - 1] + i[n];
t = r, r = i, i = t;
}
}
return t;
}
var si = class {
/**
* Constructs a new Gauss kernel.
*
* @param {Number} kernelSize - The kernel size. Should be an odd number in the range [3, 1020].
* @param {Number} [edgeBias=2] - Determines how many edge coefficients should be cut off for increased accuracy.
*/
constructor(e, t = 2) {
this.weights = null, this.offsets = null, this.linearWeights = null, this.linearOffsets = null, this.generate(e, t);
}
/**
* The number of steps for discrete sampling.
*
* @type {Number}
*/
get steps() {
return this.offsets === null ? 0 : this.offsets.length;
}
/**
* The number of steps for linear sampling.
*
* @type {Number}
*/
get linearSteps() {
return this.linearOffsets === null ? 0 : this.linearOffsets.length;
}
/**
* Generates the kernel.
*
* @private
* @param {Number} kernelSize - The kernel size.
* @param {Number} edgeBias - The amount of edge coefficients to ignore.
*/
generate(e, t) {
if (e < 3 || e > 1020)
throw new Error("The kernel size must be in the range [3, 1020]");
const i = e + t * 2, r = t > 0 ? bt(i).slice(t, -t) : bt(i), a = Math.floor((r.length - 1) / 2), n = r.reduce((h, d) => h + d, 0), s = r.slice(a), o = [...Array(a + 1).keys()], l = new Float64Array(Math.floor(o.length / 2)), c = new Float64Array(l.length);
l[0] = s[0] / n;
for (let h = 1, d = 1, v = o.length - 1; h < v; h += 2, ++d) {
const A = o[h], m = o[h + 1], x = s[h], y = s[h + 1], C = x + y, E = (A * x + m * y) / C;
l[d] = C / n, c[d] = E;
}
for (let h = 0, d = s.length, v = 1 / n; h < d; ++h)
s[h] *= v;
const f = (l.reduce((h, d) => h + d, 0) - l[0] * 0.5) * 2;
if (f !== 0)
for (let h = 0, d = l.length, v = 1 / f; h < d; ++h)
l[h] *= v;
this.offsets = o, this.weights = s, this.linearOffsets = c, this.linearWeights = l;
}
}, nr = class {
/**
* The current delta time in seconds.
*
* @type {Number}
*/
getDelta() {
return NaN;
}
/**
* The elapsed time in seconds.
*
* @type {Number}
*/
getElapsed() {
return NaN;
}
}, or = class {
/**
* Performs initialization tasks.
*
* @param {WebGLRenderer} renderer - A renderer.
* @param {Boolean} alpha - Whether the renderer uses the alpha channel.
* @param {Number} frameBufferType - The type of the main frame buffers.
*/
initialize(e, t, i) {
}
}, ot = !1, gt = class {
/**
* Constructs a new override material manager.
*
* @param {Material} [material=null] - An override material.
*/
constructor(e = null) {
this.originalMaterials = /* @__PURE__ */ new Map(), this.material = null, this.materials = null, this.materialsBackSide = null, this.materialsDoubleSide = null, this.materialsFlatShaded = null, this.materialsFlatShadedBackSide = null, this.materialsFlatShadedDoubleSide = null, this.setMaterial(e), this.meshCount = 0, this.replaceMaterial = (t) => {
if (t.isMesh) {
let i;
if (t.material.flatShading)
switch (t.material.side) {
case Ve:
i = this.materialsFlatShadedDoubleSide;
break;
case Qe:
i = this.materialsFlatShadedBackSide;
break;
default:
i = this.materialsFlatShaded;
break;
}
else
switch (t.material.side) {
case Ve:
i = this.materialsDoubleSide;
break;
case Qe:
i = this.materialsBackSide;
break;
default:
i = this.materials;
break;
}
this.originalMaterials.set(t, t.material), t.isSkinnedMesh ? t.material = i[2] : t.isInstancedMesh ? t.material = i[1] : t.material = i[0], ++this.meshCount;
}
};
}
/**
* Clones the given material.
*
* @private
* @param {Material} material - The material.
* @return {Material} The cloned material.
*/
cloneMaterial(e) {
if (!(e instanceof T))
return e.clone();
const t = e.uniforms, i = /* @__PURE__ */ new Map();
for (const a in t) {
const n = t[a].value;
n.isRenderTargetTexture && (t[a].value = null, i.set(a, n));
}
const r = e.clone();
for (const a of i)
t[a[0]].value = a[1], r.uniforms[a[0]].value = a[1];
return r;
}
/**
* Sets the override material.
*
* @param {Material} material - The material.
*/
setMaterial(e) {
if (this.disposeMaterials(), this.material = e, e !== null) {
const t = this.materials = [
this.cloneMaterial(e),
this.cloneMaterial(e),
this.cloneMaterial(e)
];
for (const i of t)
i.uniforms = Object.assign({}, e.uniforms), i.side = Yi;
t[2].skinning = !0, this.materialsBackSide = t.map((i) => {
const r = this.cloneMaterial(i);
return r.uniforms = Object.assign({}, e.uniforms), r.side = Qe, r;
}), this.materialsDoubleSide = t.map((i) => {
const r = this.cloneMaterial(i);
return r.uniforms = Object.assign({}, e.uniforms), r.side = Ve, r;
}), this.materialsFlatShaded = t.map((i) => {
const r = this.cloneMaterial(i);
return r.uniforms = Object.assign({}, e.uniforms), r.flatShading = !0, r;
}), this.materialsFlatShadedBackSide = t.map((i) => {
const r = this.cloneMaterial(i);
return r.uniforms = Object.assign({}, e.uniforms), r.flatShading = !0, r.side = Qe, r;
}), this.materialsFlatShadedDoubleSide = t.map((i) => {
const r = this.cloneMaterial(i);
return r.uniforms = Object.assign({}, e.uniforms), r.flatShading = !0, r.side = Ve, r;
});
}
}
/**
* Renders the scene with the override material.
*
* @private
* @param {WebGLRenderer} renderer - The renderer.
* @param {Scene} scene - A scene.
* @param {Camera} camera - A camera.
*/
render(e, t, i) {
const r = e.shadowMap.enabled;
if (e.shadowMap.enabled = !1, ot) {
const a = this.originalMaterials;
this.meshCount = 0, t.traverse(this.replaceMaterial), e.render(t, i);
for (const n of a)
n[0].material = n[1];
this.meshCount !== a.size && a.clear();
} else {
const a = t.overrideMaterial;
t.overrideMaterial = this.material, e.render(t, i), t.overrideMaterial = a;
}
e.shadowMap.enabled = r;
}
/**
* Deletes cloned override materials.
*
* @private
*/
disposeMaterials() {
if (this.material !== null) {
const e = this.materials.concat(this.materialsBackSide).concat(this.materialsDoubleSide).concat(this.materialsFlatShaded).concat(this.materialsFlatShadedBackSide).concat(this.materialsFlatShadedDoubleSide);
for (const t of e)
t.dispose();
}
}
/**
* Performs cleanup tasks.
*/
dispose() {
this.originalMaterials.clear(), this.disposeMaterials();
}
/**
* Indicates whether the override material workaround is enabled.
*
* @type {Boolean}
*/
static get workaroundEnabled() {
return ot;
}
/**
* Enables or disables the override material workaround globally.
*
* This only affects post processing passes and effects.
*
* @type {Boolean}
*/
static set workaroundEnabled(e) {
ot = e;
}
}, lr = class {
/**
* Sets the size of this object.
*
* @param {Number} width - The width.
* @param {Number} height - The height.
*/
setSize(e, t) {
}
}, oe = -1, D = class extends wt {
/**
* Constructs a new resolution.
*
* TODO Remove resizable param.
* @param {Resizable} resizable - A resizable object.
* @param {Number} [width=Resolution.AUTO_SIZE] - The preferred width.
* @param {Number} [height=Resolution.AUTO_SIZE] - The preferred height.
* @param {Number} [scale=1.0] - A resolution scale.
*/
constructor(e, t = oe, i = oe, r = 1) {
super(), this.resizable = e, this.baseSize = new p(1, 1), this.preferredSize = new p(t, i), this.target = this.preferredSize, this.s = r, this.effectiveSize = new p(), this.addEventListener("change", () => this.updateEffectiveSize()), this.updateEffectiveSize();
}
/**
* Calculates the effective size.
*
* @private
*/
updateEffectiveSize() {
const e = this.baseSize, t = this.preferredSize, i = this.effectiveSize, r = this.scale;
t.width !== oe ? i.width = t.width : t.height !== oe ? i.width = Math.round(t.height * (e.width / Math.max(e.height, 1))) : i.width = Math.round(e.width * r), t.height !== oe ? i.height = t.height : t.width !== oe ? i.height = Math.round(t.width / Math.max(e.width / Math.max(e.height, 1), 1)) : i.height = Math.round(e.height * r);
}
/**
* The effective width.
*
* If the preferred width and height are set to {@link Resizer.AUTO_SIZE}, the base width will be returned.
*
* @type {Number}
*/
get width() {
return this.effectiveSize.width;
}
set width(e) {
this.preferredWidth = e;
}
/**
* The effective height.
*
* If the preferred width and height are set to {@link Resizer.AUTO_SIZE}, the base height will be returned.
*
* @type {Number}
*/
get height() {
return this.effectiveSize.height;
}
set height(e) {
this.preferredHeight = e;
}
/**
* Returns the effective width.
*
* If the preferred width and height are set to {@link Resizer.AUTO_SIZE}, the base width will be returned.
*
* @deprecated Use width instead.
* @return {Number} The effective width.
*/
getWidth() {
return this.width;
}
/**
* Returns the effective height.
*
* If the preferred width and height are set to {@link Resizer.AUTO_SIZE}, the base height will be returned.
*
* @deprecated Use height instead.
* @return {Number} The effective height.
*/
getHeight() {
return this.height;
}
/**
* The resolution scale.
*
* @type {Number}
*/
get scale() {
return this.s;
}
set scale(e) {
this.s !== e && (this.s = e, this.preferredSize.setScalar(oe), this.dispatchEvent({ type: "change" }), this.resizable.setSize(this.baseSize.width, this.baseSize.height));
}
/**
* Returns the current resolution scale.
*
* @deprecated Use scale instead.
* @return {Number} The scale.
*/
getScale() {
return this.scale;
}
/**
* Sets the resolution scale.
*
* Also sets the preferred resolution to {@link Resizer.AUTO_SIZE}.
*
* @deprecated Use scale instead.
* @param {Number} value - The scale.
*/
setScale(e) {
this.scale = e;
}
/**
* The base width.
*
* @type {Number}
*/
get baseWidth() {
return this.baseSize.width;
}
set baseWidth(e) {
this.baseSize.width !== e && (this.baseSize.width = e, this.dispatchEvent({ type: "change" }), this.resizable.setSize(this.baseSize.width, this.baseSize.height));
}
/**
* Returns the base width.
*
* @deprecated Use baseWidth instead.
* @return {Number} The base width.
*/
getBaseWidth() {
return this.baseWidth;
}
/**
* Sets the base width.
*
* @deprecated Use baseWidth instead.
* @param {Number} value - The width.
*/
setBaseWidth(e) {
this.baseWidth = e;
}
/**
* The base height.
*
* @type {Number}
*/
get baseHeight() {
return this.baseSize.height;
}
set baseHeight(e) {
this.baseSize.height !== e && (this.baseSize.height = e, this.dispatchEvent({ type: "change" }), this.resizable.setSize(this.baseSize.width, this.baseSize.height));
}
/**
* Returns the base height.
*
* @deprecated Use baseHeight instead.
* @return {Number} The base height.
*/
getBaseHeight() {
return this.baseHeight;
}
/**
* Sets the base height.
*
* @deprecated Use baseHeight instead.
* @param {Number} value - The height.
*/
setBaseHeight(e) {
this.baseHeight = e;
}
/**
* Sets the base size.
*
* @param {Number} width - The width.
* @param {Number} height - The height.
*/
setBaseSize(e, t) {
(this.baseSize.width !== e || this.baseSize.height !== t) && (this.baseSize.set(e, t), this.dispatchEvent({ type: "change" }), this.resizable.setSize(this.baseSize.width, this.baseSize.height));
}
/**
* The preferred width.
*
* @type {Number}
*/
get preferredWidth() {
return this.preferredSize.width;
}
set preferredWidth(e) {
this.preferredSize.width !== e && (this.preferredSize.width = e, this.dispatchEvent({ type: "change" }), this.resizable.setSize(this.baseSize.width, this.baseSize.height));
}
/**
* Returns the preferred width.
*
* @deprecated Use preferredWidth instead.
* @return {Number} The preferred width.
*/
getPreferredWidth() {
return this.preferredWidth;
}
/**
* Sets the preferred width.
*
* Use {@link Resizer.AUTO_SIZE} to automatically calculate the width based on the height and aspect ratio.
*
* @deprecated Use preferredWidth instead.
* @param {Number} value - The width.
*/
setPreferredWidth(e) {
this.preferredWidth = e;
}
/**
* The preferred height.
*
* @type {Number}
*/
get preferredHeight() {
return this.preferredSize.height;
}
set preferredHeight(e) {
this.preferredSize.height !== e && (this.preferredSize.height = e, this.dispatchEvent({ type: "change" }), this.resizable.setSize(this.baseSize.width, this.baseSize.height));
}
/**
* Returns the preferred height.
*
* @deprecated Use preferredHeight instead.
* @return {Number} The preferred height.
*/
getPreferredHeight() {
return this.preferredHeight;
}
/**
* Sets the preferred height.
*
* Use {@link Resizer.AUTO_SIZE} to automatically calculate the height based on the width and aspect ratio.
*
* @deprecated Use preferredHeight instead.
* @param {Number} value - The height.
*/
setPreferredHeight(e) {
this.preferredHeight = e;
}
/**
* Sets the preferred size.
*
* @param {Number} width - The width.
* @param {Number} height - The height.
*/
setPreferredSize(e, t) {
(this.preferredSize.width !== e || this.preferredSize.height !== t) && (this.preferredSize.set(e, t), this.dispatchEvent({ type: "change" }), this.resizable.setSize(this.baseSize.width, this.baseSize.height));
}
/**
* Copies the given resolution.
*
* @param {Resolution} resolution - The resolution.
*/
copy(e) {
this.s = e.scale, this.baseSize.set(e.baseWidth, e.baseHeight), this.preferredSize.set(e.preferredWidth, e.preferredHeight), this.dispatchEvent({ type: "change" }), this.resizable.setSize(this.baseSize.width, this.baseSize.height);
}
/**
* An auto sizing constant.
*
* Can be used to automatically calculate the width or height based on the original aspect ratio.
*
* @type {Number}
*/
static get AUTO_SIZE() {
return oe;
}
}, ur = class {
/**
* Constructs a new ID manager.
*
* @param initialId - The first ID.
*/
constructor(e = 0) {
this.nextId = e;
}
/**
* Returns the next unique ID.
*
* @return The ID.
*/
getNextId() {
return this.nextId++;
}
/**
* Resets the ID counter.
*
* @param initialId - The first ID.
* @return This manager.
*/
reset(e = 0) {
return this.nextId = e, this;
}
}, lt = /* @__PURE__ */ new ur(2), St = class extends Set {
/**
* Constructs a new selection.
*
* @param {Iterable<Object3D>} [iterable] - A collection of objects that should be added to this selection.
* @param {Number} [layer] - A dedicated render layer for selected objects. Range is `[2, 31]`. Starts at 2 if omitted.
*/
constructor(e, t = lt.getNextId()) {
super(), this.exclusive = !1, this._layer = t, (this._layer < 1 || this._layer > 31) && (console.warn("Layer out of range, resetting to 2"), lt.reset(2), this._layer = lt.getNextId()), e !== void 0 && this.set(e);
}
/**
* The render layer for selected objects.
*
* @type {Number}
*/
get layer() {
return this._layer;
}
set layer(e) {
const t = this._layer;
for (const i of this)
i.layers.disable(t), i.layers.enable(e);
this._layer = e;
}
/**
* Returns the current render layer for selected objects.
*
* The default layer is 2. If this collides with your own custom layers, please change it before rendering!
*
* @deprecated Use layer instead.
* @return {Number} The layer.
*/
getLayer() {
return this.layer;
}
/**
* Sets the render layer for selected objects.
*
* The current selection will be updated accordingly.
*
* @depreca