diff --git a/Core/GDCore/Project/InitialInstance.h b/Core/GDCore/Project/InitialInstance.h
index e521d3dcba1c..783b44044067 100644
--- a/Core/GDCore/Project/InitialInstance.h
+++ b/Core/GDCore/Project/InitialInstance.h
@@ -365,6 +365,12 @@ class GD_CORE_API InitialInstance {
    * the same initial instance between serialization.
    */
   InitialInstance& ResetPersistentUuid();
+
+  /**
+   * \brief Reset the persistent UUID used to recognize
+   * the same initial instance between serialization.
+   */
+  const gd::String& GetPersistentUuid() { return persistentUuid; };
   ///@}
 
  private:
diff --git a/Extensions/3D/A_RuntimeObject3DRenderer.ts b/Extensions/3D/A_RuntimeObject3DRenderer.ts
index e43ba9c0960c..69306c2f2297 100644
--- a/Extensions/3D/A_RuntimeObject3DRenderer.ts
+++ b/Extensions/3D/A_RuntimeObject3DRenderer.ts
@@ -30,6 +30,14 @@ namespace gdjs {
       );
     }
 
+    getObjectPositionFrom3DRendererObject() {
+      return {
+        x: this._threeObject3D.position.x - this._object.getWidth() / 2,
+        y: this._threeObject3D.position.y - this._object.getHeight() / 2,
+        z: this._threeObject3D.position.z - this._object.getDepth() / 2,
+      };
+    }
+
     updateRotation() {
       this._threeObject3D.rotation.set(
         gdjs.toRad(this._object.getRotationX()),
diff --git a/GDJS/Runtime/debugger-client/abstract-debugger-client.ts b/GDJS/Runtime/debugger-client/abstract-debugger-client.ts
index 79bd32af24ff..ded7679f7b99 100644
--- a/GDJS/Runtime/debugger-client/abstract-debugger-client.ts
+++ b/GDJS/Runtime/debugger-client/abstract-debugger-client.ts
@@ -262,6 +262,8 @@ namespace gdjs {
         that.sendProfilerStarted();
       } else if (data.command === 'profiler.stop') {
         runtimeGame.stopCurrentSceneProfiler();
+      } else if (data.command === 'instances.updated') {
+        runtimeGame._editor.reloadInstances(data.payload);
       } else if (data.command === 'hotReload') {
         that._hotReloader.hotReload().then((logs) => {
           that.sendHotReloaderLogs(logs);
@@ -636,11 +638,23 @@ namespace gdjs {
       );
     }
 
-    sendInstancesUpdated(runtimeObjects: gdjs.RuntimeObject[]): void {
+    sendInstancesUpdated(
+      objectUpdates: Array<{
+        object: RuntimeObject3D;
+        position: { x: number; y: number; z: number };
+      }>,
+      layoutName: string
+    ): void {
       this._sendMessage(
         circularSafeStringify({
           command: 'instances.updated',
-          payload: 'TODO',
+          payload: {
+            layoutName,
+            instances: objectUpdates.map((objectUpdate) => ({
+              persistentUuid: objectUpdate.object.persistentUuid,
+              position: objectUpdate.position,
+            })),
+          },
         })
       );
     }
diff --git a/GDJS/Runtime/pixi-renderers/ThreeAddons.js b/GDJS/Runtime/pixi-renderers/ThreeAddons.js
index 93f0c869c527..7cb1e70e151c 100644
--- a/GDJS/Runtime/pixi-renderers/ThreeAddons.js
+++ b/GDJS/Runtime/pixi-renderers/ThreeAddons.js
@@ -1 +1,2 @@
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("three")):"function"==typeof define&&define.amd?define(["exports","three"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).THREE_ADDONS={},e.THREE)}(this,(function(e,t){"use strict";function r(e,r){if(r===t.TrianglesDrawMode)return console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles."),e;if(r===t.TriangleFanDrawMode||r===t.TriangleStripDrawMode){let n=e.getIndex();if(null===n){const t=[],r=e.getAttribute("position");if(void 0===r)return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible."),e;for(let e=0;e<r.count;e++)t.push(e);e.setIndex(t),n=e.getIndex()}const s=n.count-2,o=[];if(r===t.TriangleFanDrawMode)for(let e=1;e<=s;e++)o.push(n.getX(0)),o.push(n.getX(e)),o.push(n.getX(e+1));else for(let e=0;e<s;e++)e%2==0?(o.push(n.getX(e)),o.push(n.getX(e+1)),o.push(n.getX(e+2))):(o.push(n.getX(e+2)),o.push(n.getX(e+1)),o.push(n.getX(e)));o.length/3!==s&&console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.");const i=e.clone();return i.setIndex(o),i.clearGroups(),i}return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:",r),e}class n extends t.Loader{constructor(e){super(e),this.dracoLoader=null,this.ktx2Loader=null,this.meshoptDecoder=null,this.pluginCallbacks=[],this.register((function(e){return new c(e)})),this.register((function(e){return new v(e)})),this.register((function(e){return new A(e)})),this.register((function(e){return new T(e)})),this.register((function(e){return new h(e)})),this.register((function(e){return new d(e)})),this.register((function(e){return new f(e)})),this.register((function(e){return new m(e)})),this.register((function(e){return new l(e)})),this.register((function(e){return new p(e)})),this.register((function(e){return new u(e)})),this.register((function(e){return new x(e)})),this.register((function(e){return new g(e)})),this.register((function(e){return new i(e)})),this.register((function(e){return new b(e)})),this.register((function(e){return new w(e)}))}load(e,r,n,s){const o=this;let i;if(""!==this.resourcePath)i=this.resourcePath;else if(""!==this.path){const r=t.LoaderUtils.extractUrlBase(e);i=t.LoaderUtils.resolveURL(r,this.path)}else i=t.LoaderUtils.extractUrlBase(e);this.manager.itemStart(e);const a=function(t){s?s(t):console.error(t),o.manager.itemError(e),o.manager.itemEnd(e)},l=new t.FileLoader(this.manager);l.setPath(this.path),l.setResponseType("arraybuffer"),l.setRequestHeader(this.requestHeader),l.setWithCredentials(this.withCredentials),l.load(e,(function(t){try{o.parse(t,i,(function(t){r(t),o.manager.itemEnd(e)}),a)}catch(e){a(e)}}),n,a)}setDRACOLoader(e){return this.dracoLoader=e,this}setDDSLoader(){throw new Error('THREE.GLTFLoader: "MSFT_texture_dds" no longer supported. Please update to "KHR_texture_basisu".')}setKTX2Loader(e){return this.ktx2Loader=e,this}setMeshoptDecoder(e){return this.meshoptDecoder=e,this}register(e){return-1===this.pluginCallbacks.indexOf(e)&&this.pluginCallbacks.push(e),this}unregister(e){return-1!==this.pluginCallbacks.indexOf(e)&&this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(e),1),this}parse(e,t,r,n){let s;const i={},l={},c=new TextDecoder;if("string"==typeof e)s=JSON.parse(e);else if(e instanceof ArrayBuffer){if(c.decode(new Uint8Array(e,0,4))===M){try{i[o.KHR_BINARY_GLTF]=new L(e)}catch(e){return void(n&&n(e))}s=JSON.parse(i[o.KHR_BINARY_GLTF].content)}else s=JSON.parse(c.decode(e))}else s=e;if(void 0===s.asset||s.asset.version[0]<2)return void(n&&n(new Error("THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.")));const u=new J(s,{path:t||this.resourcePath||"",crossOrigin:this.crossOrigin,requestHeader:this.requestHeader,manager:this.manager,ktx2Loader:this.ktx2Loader,meshoptDecoder:this.meshoptDecoder});u.fileLoader.setRequestHeader(this.requestHeader);for(let e=0;e<this.pluginCallbacks.length;e++){const t=this.pluginCallbacks[e](u);t.name||console.error("THREE.GLTFLoader: Invalid plugin found: missing name"),l[t.name]=t,i[t.name]=!0}if(s.extensionsUsed)for(let e=0;e<s.extensionsUsed.length;++e){const t=s.extensionsUsed[e],r=s.extensionsRequired||[];switch(t){case o.KHR_MATERIALS_UNLIT:i[t]=new a;break;case o.KHR_DRACO_MESH_COMPRESSION:i[t]=new R(s,this.dracoLoader);break;case o.KHR_TEXTURE_TRANSFORM:i[t]=new E;break;case o.KHR_MESH_QUANTIZATION:i[t]=new C;break;default:r.indexOf(t)>=0&&void 0===l[t]&&console.warn('THREE.GLTFLoader: Unknown extension "'+t+'".')}}u.setExtensions(i),u.setPlugins(l),u.parse(r,n)}parseAsync(e,t){const r=this;return new Promise((function(n,s){r.parse(e,t,n,s)}))}}function s(){let e={};return{get:function(t){return e[t]},add:function(t,r){e[t]=r},remove:function(t){delete e[t]},removeAll:function(){e={}}}}const o={KHR_BINARY_GLTF:"KHR_binary_glTF",KHR_DRACO_MESH_COMPRESSION:"KHR_draco_mesh_compression",KHR_LIGHTS_PUNCTUAL:"KHR_lights_punctual",KHR_MATERIALS_CLEARCOAT:"KHR_materials_clearcoat",KHR_MATERIALS_IOR:"KHR_materials_ior",KHR_MATERIALS_SHEEN:"KHR_materials_sheen",KHR_MATERIALS_SPECULAR:"KHR_materials_specular",KHR_MATERIALS_TRANSMISSION:"KHR_materials_transmission",KHR_MATERIALS_IRIDESCENCE:"KHR_materials_iridescence",KHR_MATERIALS_ANISOTROPY:"KHR_materials_anisotropy",KHR_MATERIALS_UNLIT:"KHR_materials_unlit",KHR_MATERIALS_VOLUME:"KHR_materials_volume",KHR_TEXTURE_BASISU:"KHR_texture_basisu",KHR_TEXTURE_TRANSFORM:"KHR_texture_transform",KHR_MESH_QUANTIZATION:"KHR_mesh_quantization",KHR_MATERIALS_EMISSIVE_STRENGTH:"KHR_materials_emissive_strength",EXT_MATERIALS_BUMP:"EXT_materials_bump",EXT_TEXTURE_WEBP:"EXT_texture_webp",EXT_TEXTURE_AVIF:"EXT_texture_avif",EXT_MESHOPT_COMPRESSION:"EXT_meshopt_compression",EXT_MESH_GPU_INSTANCING:"EXT_mesh_gpu_instancing"};class i{constructor(e){this.parser=e,this.name=o.KHR_LIGHTS_PUNCTUAL,this.cache={refs:{},uses:{}}}_markDefs(){const e=this.parser,t=this.parser.json.nodes||[];for(let r=0,n=t.length;r<n;r++){const n=t[r];n.extensions&&n.extensions[this.name]&&void 0!==n.extensions[this.name].light&&e._addNodeRef(this.cache,n.extensions[this.name].light)}}_loadLight(e){const r=this.parser,n="light:"+e;let s=r.cache.get(n);if(s)return s;const o=r.json,i=((o.extensions&&o.extensions[this.name]||{}).lights||[])[e];let a;const l=new t.Color(16777215);void 0!==i.color&&l.setRGB(i.color[0],i.color[1],i.color[2],t.LinearSRGBColorSpace);const c=void 0!==i.range?i.range:0;switch(i.type){case"directional":a=new t.DirectionalLight(l),a.target.position.set(0,0,-1),a.add(a.target);break;case"point":a=new t.PointLight(l),a.distance=c;break;case"spot":a=new t.SpotLight(l),a.distance=c,i.spot=i.spot||{},i.spot.innerConeAngle=void 0!==i.spot.innerConeAngle?i.spot.innerConeAngle:0,i.spot.outerConeAngle=void 0!==i.spot.outerConeAngle?i.spot.outerConeAngle:Math.PI/4,a.angle=i.spot.outerConeAngle,a.penumbra=1-i.spot.innerConeAngle/i.spot.outerConeAngle,a.target.position.set(0,0,-1),a.add(a.target);break;default:throw new Error("THREE.GLTFLoader: Unexpected light type: "+i.type)}return a.position.set(0,0,0),a.decay=2,V(a,i),void 0!==i.intensity&&(a.intensity=i.intensity),a.name=r.createUniqueName(i.name||"light_"+e),s=Promise.resolve(a),r.cache.add(n,s),s}getDependency(e,t){if("light"===e)return this._loadLight(t)}createNodeAttachment(e){const t=this,r=this.parser,n=r.json.nodes[e],s=(n.extensions&&n.extensions[this.name]||{}).light;return void 0===s?null:this._loadLight(s).then((function(e){return r._getNodeRef(t.cache,s,e)}))}}class a{constructor(){this.name=o.KHR_MATERIALS_UNLIT}getMaterialType(){return t.MeshBasicMaterial}extendParams(e,r,n){const s=[];e.color=new t.Color(1,1,1),e.opacity=1;const o=r.pbrMetallicRoughness;if(o){if(Array.isArray(o.baseColorFactor)){const r=o.baseColorFactor;e.color.setRGB(r[0],r[1],r[2],t.LinearSRGBColorSpace),e.opacity=r[3]}void 0!==o.baseColorTexture&&s.push(n.assignTexture(e,"map",o.baseColorTexture,t.SRGBColorSpace))}return Promise.all(s)}}class l{constructor(e){this.parser=e,this.name=o.KHR_MATERIALS_EMISSIVE_STRENGTH}extendMaterialParams(e,t){const r=this.parser.json.materials[e];if(!r.extensions||!r.extensions[this.name])return Promise.resolve();const n=r.extensions[this.name].emissiveStrength;return void 0!==n&&(t.emissiveIntensity=n),Promise.resolve()}}class c{constructor(e){this.parser=e,this.name=o.KHR_MATERIALS_CLEARCOAT}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,r){const n=this.parser,s=n.json.materials[e];if(!s.extensions||!s.extensions[this.name])return Promise.resolve();const o=[],i=s.extensions[this.name];if(void 0!==i.clearcoatFactor&&(r.clearcoat=i.clearcoatFactor),void 0!==i.clearcoatTexture&&o.push(n.assignTexture(r,"clearcoatMap",i.clearcoatTexture)),void 0!==i.clearcoatRoughnessFactor&&(r.clearcoatRoughness=i.clearcoatRoughnessFactor),void 0!==i.clearcoatRoughnessTexture&&o.push(n.assignTexture(r,"clearcoatRoughnessMap",i.clearcoatRoughnessTexture)),void 0!==i.clearcoatNormalTexture&&(o.push(n.assignTexture(r,"clearcoatNormalMap",i.clearcoatNormalTexture)),void 0!==i.clearcoatNormalTexture.scale)){const e=i.clearcoatNormalTexture.scale;r.clearcoatNormalScale=new t.Vector2(e,e)}return Promise.all(o)}}class u{constructor(e){this.parser=e,this.name=o.KHR_MATERIALS_IRIDESCENCE}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,t){const r=this.parser,n=r.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const s=[],o=n.extensions[this.name];return void 0!==o.iridescenceFactor&&(t.iridescence=o.iridescenceFactor),void 0!==o.iridescenceTexture&&s.push(r.assignTexture(t,"iridescenceMap",o.iridescenceTexture)),void 0!==o.iridescenceIor&&(t.iridescenceIOR=o.iridescenceIor),void 0===t.iridescenceThicknessRange&&(t.iridescenceThicknessRange=[100,400]),void 0!==o.iridescenceThicknessMinimum&&(t.iridescenceThicknessRange[0]=o.iridescenceThicknessMinimum),void 0!==o.iridescenceThicknessMaximum&&(t.iridescenceThicknessRange[1]=o.iridescenceThicknessMaximum),void 0!==o.iridescenceThicknessTexture&&s.push(r.assignTexture(t,"iridescenceThicknessMap",o.iridescenceThicknessTexture)),Promise.all(s)}}class h{constructor(e){this.parser=e,this.name=o.KHR_MATERIALS_SHEEN}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,r){const n=this.parser,s=n.json.materials[e];if(!s.extensions||!s.extensions[this.name])return Promise.resolve();const o=[];r.sheenColor=new t.Color(0,0,0),r.sheenRoughness=0,r.sheen=1;const i=s.extensions[this.name];if(void 0!==i.sheenColorFactor){const e=i.sheenColorFactor;r.sheenColor.setRGB(e[0],e[1],e[2],t.LinearSRGBColorSpace)}return void 0!==i.sheenRoughnessFactor&&(r.sheenRoughness=i.sheenRoughnessFactor),void 0!==i.sheenColorTexture&&o.push(n.assignTexture(r,"sheenColorMap",i.sheenColorTexture,t.SRGBColorSpace)),void 0!==i.sheenRoughnessTexture&&o.push(n.assignTexture(r,"sheenRoughnessMap",i.sheenRoughnessTexture)),Promise.all(o)}}class d{constructor(e){this.parser=e,this.name=o.KHR_MATERIALS_TRANSMISSION}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,t){const r=this.parser,n=r.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const s=[],o=n.extensions[this.name];return void 0!==o.transmissionFactor&&(t.transmission=o.transmissionFactor),void 0!==o.transmissionTexture&&s.push(r.assignTexture(t,"transmissionMap",o.transmissionTexture)),Promise.all(s)}}class f{constructor(e){this.parser=e,this.name=o.KHR_MATERIALS_VOLUME}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,r){const n=this.parser,s=n.json.materials[e];if(!s.extensions||!s.extensions[this.name])return Promise.resolve();const o=[],i=s.extensions[this.name];r.thickness=void 0!==i.thicknessFactor?i.thicknessFactor:0,void 0!==i.thicknessTexture&&o.push(n.assignTexture(r,"thicknessMap",i.thicknessTexture)),r.attenuationDistance=i.attenuationDistance||1/0;const a=i.attenuationColor||[1,1,1];return r.attenuationColor=(new t.Color).setRGB(a[0],a[1],a[2],t.LinearSRGBColorSpace),Promise.all(o)}}class m{constructor(e){this.parser=e,this.name=o.KHR_MATERIALS_IOR}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,t){const r=this.parser.json.materials[e];if(!r.extensions||!r.extensions[this.name])return Promise.resolve();const n=r.extensions[this.name];return t.ior=void 0!==n.ior?n.ior:1.5,Promise.resolve()}}class p{constructor(e){this.parser=e,this.name=o.KHR_MATERIALS_SPECULAR}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,r){const n=this.parser,s=n.json.materials[e];if(!s.extensions||!s.extensions[this.name])return Promise.resolve();const o=[],i=s.extensions[this.name];r.specularIntensity=void 0!==i.specularFactor?i.specularFactor:1,void 0!==i.specularTexture&&o.push(n.assignTexture(r,"specularIntensityMap",i.specularTexture));const a=i.specularColorFactor||[1,1,1];return r.specularColor=(new t.Color).setRGB(a[0],a[1],a[2],t.LinearSRGBColorSpace),void 0!==i.specularColorTexture&&o.push(n.assignTexture(r,"specularColorMap",i.specularColorTexture,t.SRGBColorSpace)),Promise.all(o)}}class g{constructor(e){this.parser=e,this.name=o.EXT_MATERIALS_BUMP}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,t){const r=this.parser,n=r.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const s=[],o=n.extensions[this.name];return t.bumpScale=void 0!==o.bumpFactor?o.bumpFactor:1,void 0!==o.bumpTexture&&s.push(r.assignTexture(t,"bumpMap",o.bumpTexture)),Promise.all(s)}}class x{constructor(e){this.parser=e,this.name=o.KHR_MATERIALS_ANISOTROPY}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,t){const r=this.parser,n=r.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const s=[],o=n.extensions[this.name];return void 0!==o.anisotropyStrength&&(t.anisotropy=o.anisotropyStrength),void 0!==o.anisotropyRotation&&(t.anisotropyRotation=o.anisotropyRotation),void 0!==o.anisotropyTexture&&s.push(r.assignTexture(t,"anisotropyMap",o.anisotropyTexture)),Promise.all(s)}}class v{constructor(e){this.parser=e,this.name=o.KHR_TEXTURE_BASISU}loadTexture(e){const t=this.parser,r=t.json,n=r.textures[e];if(!n.extensions||!n.extensions[this.name])return null;const s=n.extensions[this.name],o=t.options.ktx2Loader;if(!o){if(r.extensionsRequired&&r.extensionsRequired.indexOf(this.name)>=0)throw new Error("THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures");return null}return t.loadTextureImage(e,s.source,o)}}class A{constructor(e){this.parser=e,this.name=o.EXT_TEXTURE_WEBP,this.isSupported=null}loadTexture(e){const t=this.name,r=this.parser,n=r.json,s=n.textures[e];if(!s.extensions||!s.extensions[t])return null;const o=s.extensions[t],i=n.images[o.source];let a=r.textureLoader;if(i.uri){const e=r.options.manager.getHandler(i.uri);null!==e&&(a=e)}return this.detectSupport().then((function(s){if(s)return r.loadTextureImage(e,o.source,a);if(n.extensionsRequired&&n.extensionsRequired.indexOf(t)>=0)throw new Error("THREE.GLTFLoader: WebP required by asset but unsupported.");return r.loadTexture(e)}))}detectSupport(){return this.isSupported||(this.isSupported=new Promise((function(e){const t=new Image;t.src="data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",t.onload=t.onerror=function(){e(1===t.height)}}))),this.isSupported}}class T{constructor(e){this.parser=e,this.name=o.EXT_TEXTURE_AVIF,this.isSupported=null}loadTexture(e){const t=this.name,r=this.parser,n=r.json,s=n.textures[e];if(!s.extensions||!s.extensions[t])return null;const o=s.extensions[t],i=n.images[o.source];let a=r.textureLoader;if(i.uri){const e=r.options.manager.getHandler(i.uri);null!==e&&(a=e)}return this.detectSupport().then((function(s){if(s)return r.loadTextureImage(e,o.source,a);if(n.extensionsRequired&&n.extensionsRequired.indexOf(t)>=0)throw new Error("THREE.GLTFLoader: AVIF required by asset but unsupported.");return r.loadTexture(e)}))}detectSupport(){return this.isSupported||(this.isSupported=new Promise((function(e){const t=new Image;t.src="data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAABcAAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAEAAAABAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQAMAAAAABNjb2xybmNseAACAAIABoAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAAB9tZGF0EgAKCBgABogQEDQgMgkQAAAAB8dSLfI=",t.onload=t.onerror=function(){e(1===t.height)}}))),this.isSupported}}class b{constructor(e){this.name=o.EXT_MESHOPT_COMPRESSION,this.parser=e}loadBufferView(e){const t=this.parser.json,r=t.bufferViews[e];if(r.extensions&&r.extensions[this.name]){const e=r.extensions[this.name],n=this.parser.getDependency("buffer",e.buffer),s=this.parser.options.meshoptDecoder;if(!s||!s.supported){if(t.extensionsRequired&&t.extensionsRequired.indexOf(this.name)>=0)throw new Error("THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files");return null}return n.then((function(t){const r=e.byteOffset||0,n=e.byteLength||0,o=e.count,i=e.byteStride,a=new Uint8Array(t,r,n);return s.decodeGltfBufferAsync?s.decodeGltfBufferAsync(o,i,a,e.mode,e.filter).then((function(e){return e.buffer})):s.ready.then((function(){const t=new ArrayBuffer(o*i);return s.decodeGltfBuffer(new Uint8Array(t),o,i,a,e.mode,e.filter),t}))}))}return null}}class w{constructor(e){this.name=o.EXT_MESH_GPU_INSTANCING,this.parser=e}createNodeMesh(e){const r=this.parser.json,n=r.nodes[e];if(!n.extensions||!n.extensions[this.name]||void 0===n.mesh)return null;const s=r.meshes[n.mesh];for(const e of s.primitives)if(e.mode!==N.TRIANGLES&&e.mode!==N.TRIANGLE_STRIP&&e.mode!==N.TRIANGLE_FAN&&void 0!==e.mode)return null;const o=n.extensions[this.name].attributes,i=[],a={};for(const e in o)i.push(this.parser.getDependency("accessor",o[e]).then((t=>(a[e]=t,a[e]))));return i.length<1?null:(i.push(this.parser.createNodeMesh(e)),Promise.all(i).then((e=>{const r=e.pop(),n=r.isGroup?r.children:[r],s=e[0].count,o=[];for(const e of n){const r=new t.Matrix4,n=new t.Vector3,i=new t.Quaternion,l=new t.Vector3(1,1,1),c=new t.InstancedMesh(e.geometry,e.material,s);for(let e=0;e<s;e++)a.TRANSLATION&&n.fromBufferAttribute(a.TRANSLATION,e),a.ROTATION&&i.fromBufferAttribute(a.ROTATION,e),a.SCALE&&l.fromBufferAttribute(a.SCALE,e),c.setMatrixAt(e,r.compose(n,i,l));for(const r in a)if("_COLOR_0"===r){const e=a[r];c.instanceColor=new t.InstancedBufferAttribute(e.array,e.itemSize,e.normalized)}else"TRANSLATION"!==r&&"ROTATION"!==r&&"SCALE"!==r&&e.geometry.setAttribute(r,a[r]);t.Object3D.prototype.copy.call(c,e),this.parser.assignFinalMaterial(c),o.push(c)}return r.isGroup?(r.clear(),r.add(...o),r):o[0]})))}}const M="glTF",S=1313821514,y=5130562;class L{constructor(e){this.name=o.KHR_BINARY_GLTF,this.content=null,this.body=null;const t=new DataView(e,0,12),r=new TextDecoder;if(this.header={magic:r.decode(new Uint8Array(e.slice(0,4))),version:t.getUint32(4,!0),length:t.getUint32(8,!0)},this.header.magic!==M)throw new Error("THREE.GLTFLoader: Unsupported glTF-Binary header.");if(this.header.version<2)throw new Error("THREE.GLTFLoader: Legacy binary file detected.");const n=this.header.length-12,s=new DataView(e,12);let i=0;for(;i<n;){const t=s.getUint32(i,!0);i+=4;const n=s.getUint32(i,!0);if(i+=4,n===S){const n=new Uint8Array(e,12+i,t);this.content=r.decode(n)}else if(n===y){const r=12+i;this.body=e.slice(r,r+t)}i+=t}if(null===this.content)throw new Error("THREE.GLTFLoader: JSON content not found.")}}class R{constructor(e,t){if(!t)throw new Error("THREE.GLTFLoader: No DRACOLoader instance provided.");this.name=o.KHR_DRACO_MESH_COMPRESSION,this.json=e,this.dracoLoader=t,this.dracoLoader.preload()}decodePrimitive(e,r){const n=this.json,s=this.dracoLoader,o=e.extensions[this.name].bufferView,i=e.extensions[this.name].attributes,a={},l={},c={};for(const e in i){const t=U[e]||e.toLowerCase();a[t]=i[e]}for(const t in e.attributes){const r=U[t]||t.toLowerCase();if(void 0!==i[t]){const s=n.accessors[e.attributes[t]],o=B[s.componentType];c[r]=o.name,l[r]=!0===s.normalized}}return r.getDependency("bufferView",o).then((function(e){return new Promise((function(r,n){s.decodeDracoFile(e,(function(e){for(const t in e.attributes){const r=e.attributes[t],n=l[t];void 0!==n&&(r.normalized=n)}r(e)}),a,c,t.LinearSRGBColorSpace,n)}))}))}}class E{constructor(){this.name=o.KHR_TEXTURE_TRANSFORM}extendTexture(e,t){return void 0!==t.texCoord&&t.texCoord!==e.channel||void 0!==t.offset||void 0!==t.rotation||void 0!==t.scale?(e=e.clone(),void 0!==t.texCoord&&(e.channel=t.texCoord),void 0!==t.offset&&e.offset.fromArray(t.offset),void 0!==t.rotation&&(e.rotation=t.rotation),void 0!==t.scale&&e.repeat.fromArray(t.scale),e.needsUpdate=!0,e):e}}class C{constructor(){this.name=o.KHR_MESH_QUANTIZATION}}class D extends t.Interpolant{constructor(e,t,r,n){super(e,t,r,n)}copySampleValue_(e){const t=this.resultBuffer,r=this.sampleValues,n=this.valueSize,s=e*n*3+n;for(let e=0;e!==n;e++)t[e]=r[s+e];return t}interpolate_(e,t,r,n){const s=this.resultBuffer,o=this.sampleValues,i=this.valueSize,a=2*i,l=3*i,c=n-t,u=(r-t)/c,h=u*u,d=h*u,f=e*l,m=f-l,p=-2*d+3*h,g=d-h,x=1-p,v=g-h+u;for(let e=0;e!==i;e++){const t=o[m+e+i],r=o[m+e+a]*c,n=o[f+e+i],l=o[f+e]*c;s[e]=x*t+v*r+p*n+g*l}return s}}const O=new t.Quaternion;class P extends D{interpolate_(e,t,r,n){const s=super.interpolate_(e,t,r,n);return O.fromArray(s).normalize().toArray(s),s}}const N={FLOAT:5126,FLOAT_MAT3:35675,FLOAT_MAT4:35676,FLOAT_VEC2:35664,FLOAT_VEC3:35665,FLOAT_VEC4:35666,LINEAR:9729,REPEAT:10497,SAMPLER_2D:35678,POINTS:0,LINES:1,LINE_LOOP:2,LINE_STRIP:3,TRIANGLES:4,TRIANGLE_STRIP:5,TRIANGLE_FAN:6,UNSIGNED_BYTE:5121,UNSIGNED_SHORT:5123},B={5120:Int8Array,5121:Uint8Array,5122:Int16Array,5123:Uint16Array,5125:Uint32Array,5126:Float32Array},F={9728:t.NearestFilter,9729:t.LinearFilter,9984:t.NearestMipmapNearestFilter,9985:t.LinearMipmapNearestFilter,9986:t.NearestMipmapLinearFilter,9987:t.LinearMipmapLinearFilter},I={33071:t.ClampToEdgeWrapping,33648:t.MirroredRepeatWrapping,10497:t.RepeatWrapping},H={SCALAR:1,VEC2:2,VEC3:3,VEC4:4,MAT2:4,MAT3:9,MAT4:16},U={POSITION:"position",NORMAL:"normal",TANGENT:"tangent",TEXCOORD_0:"uv",TEXCOORD_1:"uv1",TEXCOORD_2:"uv2",TEXCOORD_3:"uv3",COLOR_0:"color",WEIGHTS_0:"skinWeight",JOINTS_0:"skinIndex"},G={scale:"scale",translation:"position",rotation:"quaternion",weights:"morphTargetInfluences"},k={CUBICSPLINE:void 0,LINEAR:t.InterpolateLinear,STEP:t.InterpolateDiscrete},z="OPAQUE",W="MASK",j="BLEND";function X(e,t,r){for(const n in r.extensions)void 0===e[n]&&(t.userData.gltfExtensions=t.userData.gltfExtensions||{},t.userData.gltfExtensions[n]=r.extensions[n])}function V(e,t){void 0!==t.extras&&("object"==typeof t.extras?Object.assign(e.userData,t.extras):console.warn("THREE.GLTFLoader: Ignoring primitive type .extras, "+t.extras))}function K(e,t){if(e.updateMorphTargets(),void 0!==t.weights)for(let r=0,n=t.weights.length;r<n;r++)e.morphTargetInfluences[r]=t.weights[r];if(t.extras&&Array.isArray(t.extras.targetNames)){const r=t.extras.targetNames;if(e.morphTargetInfluences.length===r.length){e.morphTargetDictionary={};for(let t=0,n=r.length;t<n;t++)e.morphTargetDictionary[r[t]]=t}else console.warn("THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.")}}function q(e){let t;const r=e.extensions&&e.extensions[o.KHR_DRACO_MESH_COMPRESSION];if(t=r?"draco:"+r.bufferView+":"+r.indices+":"+Y(r.attributes):e.indices+":"+Y(e.attributes)+":"+e.mode,void 0!==e.targets)for(let r=0,n=e.targets.length;r<n;r++)t+=":"+Y(e.targets[r]);return t}function Y(e){let t="";const r=Object.keys(e).sort();for(let n=0,s=r.length;n<s;n++)t+=r[n]+":"+e[r[n]]+";";return t}function Q(e){switch(e){case Int8Array:return 1/127;case Uint8Array:return 1/255;case Int16Array:return 1/32767;case Uint16Array:return 1/65535;default:throw new Error("THREE.GLTFLoader: Unsupported normalized accessor component type.")}}const Z=new t.Matrix4;class J{constructor(e={},r={}){this.json=e,this.extensions={},this.plugins={},this.options=r,this.cache=new s,this.associations=new Map,this.primitiveCache={},this.nodeCache={},this.meshCache={refs:{},uses:{}},this.cameraCache={refs:{},uses:{}},this.lightCache={refs:{},uses:{}},this.sourceCache={},this.textureCache={},this.nodeNamesUsed={};let n=!1,o=!1,i=-1;"undefined"!=typeof navigator&&(n=!0===/^((?!chrome|android).)*safari/i.test(navigator.userAgent),o=navigator.userAgent.indexOf("Firefox")>-1,i=o?navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1]:-1),"undefined"==typeof createImageBitmap||n||o&&i<98?this.textureLoader=new t.TextureLoader(this.options.manager):this.textureLoader=new t.ImageBitmapLoader(this.options.manager),this.textureLoader.setCrossOrigin(this.options.crossOrigin),this.textureLoader.setRequestHeader(this.options.requestHeader),this.fileLoader=new t.FileLoader(this.options.manager),this.fileLoader.setResponseType("arraybuffer"),"use-credentials"===this.options.crossOrigin&&this.fileLoader.setWithCredentials(!0)}setExtensions(e){this.extensions=e}setPlugins(e){this.plugins=e}parse(e,t){const r=this,n=this.json,s=this.extensions;this.cache.removeAll(),this.nodeCache={},this._invokeAll((function(e){return e._markDefs&&e._markDefs()})),Promise.all(this._invokeAll((function(e){return e.beforeRoot&&e.beforeRoot()}))).then((function(){return Promise.all([r.getDependencies("scene"),r.getDependencies("animation"),r.getDependencies("camera")])})).then((function(t){const o={scene:t[0][n.scene||0],scenes:t[0],animations:t[1],cameras:t[2],asset:n.asset,parser:r,userData:{}};return X(s,o,n),V(o,n),Promise.all(r._invokeAll((function(e){return e.afterRoot&&e.afterRoot(o)}))).then((function(){e(o)}))})).catch(t)}_markDefs(){const e=this.json.nodes||[],t=this.json.skins||[],r=this.json.meshes||[];for(let r=0,n=t.length;r<n;r++){const n=t[r].joints;for(let t=0,r=n.length;t<r;t++)e[n[t]].isBone=!0}for(let t=0,n=e.length;t<n;t++){const n=e[t];void 0!==n.mesh&&(this._addNodeRef(this.meshCache,n.mesh),void 0!==n.skin&&(r[n.mesh].isSkinnedMesh=!0)),void 0!==n.camera&&this._addNodeRef(this.cameraCache,n.camera)}}_addNodeRef(e,t){void 0!==t&&(void 0===e.refs[t]&&(e.refs[t]=e.uses[t]=0),e.refs[t]++)}_getNodeRef(e,t,r){if(e.refs[t]<=1)return r;const n=r.clone(),s=(e,t)=>{const r=this.associations.get(e);null!=r&&this.associations.set(t,r);for(const[r,n]of e.children.entries())s(n,t.children[r])};return s(r,n),n.name+="_instance_"+e.uses[t]++,n}_invokeOne(e){const t=Object.values(this.plugins);t.push(this);for(let r=0;r<t.length;r++){const n=e(t[r]);if(n)return n}return null}_invokeAll(e){const t=Object.values(this.plugins);t.unshift(this);const r=[];for(let n=0;n<t.length;n++){const s=e(t[n]);s&&r.push(s)}return r}getDependency(e,t){const r=e+":"+t;let n=this.cache.get(r);if(!n){switch(e){case"scene":n=this.loadScene(t);break;case"node":n=this._invokeOne((function(e){return e.loadNode&&e.loadNode(t)}));break;case"mesh":n=this._invokeOne((function(e){return e.loadMesh&&e.loadMesh(t)}));break;case"accessor":n=this.loadAccessor(t);break;case"bufferView":n=this._invokeOne((function(e){return e.loadBufferView&&e.loadBufferView(t)}));break;case"buffer":n=this.loadBuffer(t);break;case"material":n=this._invokeOne((function(e){return e.loadMaterial&&e.loadMaterial(t)}));break;case"texture":n=this._invokeOne((function(e){return e.loadTexture&&e.loadTexture(t)}));break;case"skin":n=this.loadSkin(t);break;case"animation":n=this._invokeOne((function(e){return e.loadAnimation&&e.loadAnimation(t)}));break;case"camera":n=this.loadCamera(t);break;default:if(n=this._invokeOne((function(r){return r!=this&&r.getDependency&&r.getDependency(e,t)})),!n)throw new Error("Unknown type: "+e)}this.cache.add(r,n)}return n}getDependencies(e){let t=this.cache.get(e);if(!t){const r=this,n=this.json[e+("mesh"===e?"es":"s")]||[];t=Promise.all(n.map((function(t,n){return r.getDependency(e,n)}))),this.cache.add(e,t)}return t}loadBuffer(e){const r=this.json.buffers[e],n=this.fileLoader;if(r.type&&"arraybuffer"!==r.type)throw new Error("THREE.GLTFLoader: "+r.type+" buffer type is not supported.");if(void 0===r.uri&&0===e)return Promise.resolve(this.extensions[o.KHR_BINARY_GLTF].body);const s=this.options;return new Promise((function(e,o){n.load(t.LoaderUtils.resolveURL(r.uri,s.path),e,void 0,(function(){o(new Error('THREE.GLTFLoader: Failed to load buffer "'+r.uri+'".'))}))}))}loadBufferView(e){const t=this.json.bufferViews[e];return this.getDependency("buffer",t.buffer).then((function(e){const r=t.byteLength||0,n=t.byteOffset||0;return e.slice(n,n+r)}))}loadAccessor(e){const r=this,n=this.json,s=this.json.accessors[e];if(void 0===s.bufferView&&void 0===s.sparse){const e=H[s.type],r=B[s.componentType],n=!0===s.normalized,o=new r(s.count*e);return Promise.resolve(new t.BufferAttribute(o,e,n))}const o=[];return void 0!==s.bufferView?o.push(this.getDependency("bufferView",s.bufferView)):o.push(null),void 0!==s.sparse&&(o.push(this.getDependency("bufferView",s.sparse.indices.bufferView)),o.push(this.getDependency("bufferView",s.sparse.values.bufferView))),Promise.all(o).then((function(e){const o=e[0],i=H[s.type],a=B[s.componentType],l=a.BYTES_PER_ELEMENT,c=l*i,u=s.byteOffset||0,h=void 0!==s.bufferView?n.bufferViews[s.bufferView].byteStride:void 0,d=!0===s.normalized;let f,m;if(h&&h!==c){const e=Math.floor(u/h),n="InterleavedBuffer:"+s.bufferView+":"+s.componentType+":"+e+":"+s.count;let c=r.cache.get(n);c||(f=new a(o,e*h,s.count*h/l),c=new t.InterleavedBuffer(f,h/l),r.cache.add(n,c)),m=new t.InterleavedBufferAttribute(c,i,u%h/l,d)}else f=null===o?new a(s.count*i):new a(o,u,s.count*i),m=new t.BufferAttribute(f,i,d);if(void 0!==s.sparse){const r=H.SCALAR,n=B[s.sparse.indices.componentType],l=s.sparse.indices.byteOffset||0,c=s.sparse.values.byteOffset||0,u=new n(e[1],l,s.sparse.count*r),h=new a(e[2],c,s.sparse.count*i);null!==o&&(m=new t.BufferAttribute(m.array.slice(),m.itemSize,m.normalized));for(let e=0,t=u.length;e<t;e++){const t=u[e];if(m.setX(t,h[e*i]),i>=2&&m.setY(t,h[e*i+1]),i>=3&&m.setZ(t,h[e*i+2]),i>=4&&m.setW(t,h[e*i+3]),i>=5)throw new Error("THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.")}}return m}))}loadTexture(e){const t=this.json,r=this.options,n=t.textures[e].source,s=t.images[n];let o=this.textureLoader;if(s.uri){const e=r.manager.getHandler(s.uri);null!==e&&(o=e)}return this.loadTextureImage(e,n,o)}loadTextureImage(e,r,n){const s=this,o=this.json,i=o.textures[e],a=o.images[r],l=(a.uri||a.bufferView)+":"+i.sampler;if(this.textureCache[l])return this.textureCache[l];const c=this.loadImageSource(r,n).then((function(r){r.flipY=!1,r.name=i.name||a.name||"",""===r.name&&"string"==typeof a.uri&&!1===a.uri.startsWith("data:image/")&&(r.name=a.uri);const n=(o.samplers||{})[i.sampler]||{};return r.magFilter=F[n.magFilter]||t.LinearFilter,r.minFilter=F[n.minFilter]||t.LinearMipmapLinearFilter,r.wrapS=I[n.wrapS]||t.RepeatWrapping,r.wrapT=I[n.wrapT]||t.RepeatWrapping,s.associations.set(r,{textures:e}),r})).catch((function(){return null}));return this.textureCache[l]=c,c}loadImageSource(e,r){const n=this,s=this.json,o=this.options;if(void 0!==this.sourceCache[e])return this.sourceCache[e].then((e=>e.clone()));const i=s.images[e],a=self.URL||self.webkitURL;let l=i.uri||"",c=!1;if(void 0!==i.bufferView)l=n.getDependency("bufferView",i.bufferView).then((function(e){c=!0;const t=new Blob([e],{type:i.mimeType});return l=a.createObjectURL(t),l}));else if(void 0===i.uri)throw new Error("THREE.GLTFLoader: Image "+e+" is missing URI and bufferView");const u=Promise.resolve(l).then((function(e){return new Promise((function(n,s){let i=n;!0===r.isImageBitmapLoader&&(i=function(e){const r=new t.Texture(e);r.needsUpdate=!0,n(r)}),r.load(t.LoaderUtils.resolveURL(e,o.path),i,void 0,s)}))})).then((function(e){var t;return!0===c&&a.revokeObjectURL(l),e.userData.mimeType=i.mimeType||((t=i.uri).search(/\.jpe?g($|\?)/i)>0||0===t.search(/^data\:image\/jpeg/)?"image/jpeg":t.search(/\.webp($|\?)/i)>0||0===t.search(/^data\:image\/webp/)?"image/webp":"image/png"),e})).catch((function(e){throw console.error("THREE.GLTFLoader: Couldn't load texture",l),e}));return this.sourceCache[e]=u,u}assignTexture(e,t,r,n){const s=this;return this.getDependency("texture",r.index).then((function(i){if(!i)return null;if(void 0!==r.texCoord&&r.texCoord>0&&((i=i.clone()).channel=r.texCoord),s.extensions[o.KHR_TEXTURE_TRANSFORM]){const e=void 0!==r.extensions?r.extensions[o.KHR_TEXTURE_TRANSFORM]:void 0;if(e){const t=s.associations.get(i);i=s.extensions[o.KHR_TEXTURE_TRANSFORM].extendTexture(i,e),s.associations.set(i,t)}}return void 0!==n&&(i.colorSpace=n),e[t]=i,i}))}assignFinalMaterial(e){const r=e.geometry;let n=e.material;const s=void 0===r.attributes.tangent,o=void 0!==r.attributes.color,i=void 0===r.attributes.normal;if(e.isPoints){const e="PointsMaterial:"+n.uuid;let r=this.cache.get(e);r||(r=new t.PointsMaterial,t.Material.prototype.copy.call(r,n),r.color.copy(n.color),r.map=n.map,r.sizeAttenuation=!1,this.cache.add(e,r)),n=r}else if(e.isLine){const e="LineBasicMaterial:"+n.uuid;let r=this.cache.get(e);r||(r=new t.LineBasicMaterial,t.Material.prototype.copy.call(r,n),r.color.copy(n.color),r.map=n.map,this.cache.add(e,r)),n=r}if(s||o||i){let e="ClonedMaterial:"+n.uuid+":";s&&(e+="derivative-tangents:"),o&&(e+="vertex-colors:"),i&&(e+="flat-shading:");let t=this.cache.get(e);t||(t=n.clone(),o&&(t.vertexColors=!0),i&&(t.flatShading=!0),s&&(t.normalScale&&(t.normalScale.y*=-1),t.clearcoatNormalScale&&(t.clearcoatNormalScale.y*=-1)),this.cache.add(e,t),this.associations.set(t,this.associations.get(n))),n=t}e.material=n}getMaterialType(){return t.MeshStandardMaterial}loadMaterial(e){const r=this,n=this.json,s=this.extensions,i=n.materials[e];let a;const l={},c=[];if((i.extensions||{})[o.KHR_MATERIALS_UNLIT]){const e=s[o.KHR_MATERIALS_UNLIT];a=e.getMaterialType(),c.push(e.extendParams(l,i,r))}else{const n=i.pbrMetallicRoughness||{};if(l.color=new t.Color(1,1,1),l.opacity=1,Array.isArray(n.baseColorFactor)){const e=n.baseColorFactor;l.color.setRGB(e[0],e[1],e[2],t.LinearSRGBColorSpace),l.opacity=e[3]}void 0!==n.baseColorTexture&&c.push(r.assignTexture(l,"map",n.baseColorTexture,t.SRGBColorSpace)),l.metalness=void 0!==n.metallicFactor?n.metallicFactor:1,l.roughness=void 0!==n.roughnessFactor?n.roughnessFactor:1,void 0!==n.metallicRoughnessTexture&&(c.push(r.assignTexture(l,"metalnessMap",n.metallicRoughnessTexture)),c.push(r.assignTexture(l,"roughnessMap",n.metallicRoughnessTexture))),a=this._invokeOne((function(t){return t.getMaterialType&&t.getMaterialType(e)})),c.push(Promise.all(this._invokeAll((function(t){return t.extendMaterialParams&&t.extendMaterialParams(e,l)}))))}!0===i.doubleSided&&(l.side=t.DoubleSide);const u=i.alphaMode||z;if(u===j?(l.transparent=!0,l.depthWrite=!1):(l.transparent=!1,u===W&&(l.alphaTest=void 0!==i.alphaCutoff?i.alphaCutoff:.5)),void 0!==i.normalTexture&&a!==t.MeshBasicMaterial&&(c.push(r.assignTexture(l,"normalMap",i.normalTexture)),l.normalScale=new t.Vector2(1,1),void 0!==i.normalTexture.scale)){const e=i.normalTexture.scale;l.normalScale.set(e,e)}if(void 0!==i.occlusionTexture&&a!==t.MeshBasicMaterial&&(c.push(r.assignTexture(l,"aoMap",i.occlusionTexture)),void 0!==i.occlusionTexture.strength&&(l.aoMapIntensity=i.occlusionTexture.strength)),void 0!==i.emissiveFactor&&a!==t.MeshBasicMaterial){const e=i.emissiveFactor;l.emissive=(new t.Color).setRGB(e[0],e[1],e[2],t.LinearSRGBColorSpace)}return void 0!==i.emissiveTexture&&a!==t.MeshBasicMaterial&&c.push(r.assignTexture(l,"emissiveMap",i.emissiveTexture,t.SRGBColorSpace)),Promise.all(c).then((function(){const t=new a(l);return i.name&&(t.name=i.name),V(t,i),r.associations.set(t,{materials:e}),i.extensions&&X(s,t,i),t}))}createUniqueName(e){const r=t.PropertyBinding.sanitizeNodeName(e||"");return r in this.nodeNamesUsed?r+"_"+ ++this.nodeNamesUsed[r]:(this.nodeNamesUsed[r]=0,r)}loadGeometries(e){const r=this,n=this.extensions,s=this.primitiveCache;function i(e){return n[o.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(e,r).then((function(t){return _(t,e,r)}))}const a=[];for(let n=0,l=e.length;n<l;n++){const l=e[n],c=q(l),u=s[c];if(u)a.push(u.promise);else{let e;e=l.extensions&&l.extensions[o.KHR_DRACO_MESH_COMPRESSION]?i(l):_(new t.BufferGeometry,l,r),s[c]={primitive:l,promise:e},a.push(e)}}return Promise.all(a)}loadMesh(e){const n=this,s=this.json,o=this.extensions,i=s.meshes[e],a=i.primitives,l=[];for(let e=0,r=a.length;e<r;e++){const r=void 0===a[e].material?(void 0===(c=this.cache).DefaultMaterial&&(c.DefaultMaterial=new t.MeshStandardMaterial({color:16777215,emissive:0,metalness:1,roughness:1,transparent:!1,depthTest:!0,side:t.FrontSide})),c.DefaultMaterial):this.getDependency("material",a[e].material);l.push(r)}var c;return l.push(n.loadGeometries(a)),Promise.all(l).then((function(s){const l=s.slice(0,s.length-1),c=s[s.length-1],u=[];for(let s=0,h=c.length;s<h;s++){const h=c[s],d=a[s];let f;const m=l[s];if(d.mode===N.TRIANGLES||d.mode===N.TRIANGLE_STRIP||d.mode===N.TRIANGLE_FAN||void 0===d.mode)f=!0===i.isSkinnedMesh?new t.SkinnedMesh(h,m):new t.Mesh(h,m),!0===f.isSkinnedMesh&&f.normalizeSkinWeights(),d.mode===N.TRIANGLE_STRIP?f.geometry=r(f.geometry,t.TriangleStripDrawMode):d.mode===N.TRIANGLE_FAN&&(f.geometry=r(f.geometry,t.TriangleFanDrawMode));else if(d.mode===N.LINES)f=new t.LineSegments(h,m);else if(d.mode===N.LINE_STRIP)f=new t.Line(h,m);else if(d.mode===N.LINE_LOOP)f=new t.LineLoop(h,m);else{if(d.mode!==N.POINTS)throw new Error("THREE.GLTFLoader: Primitive mode unsupported: "+d.mode);f=new t.Points(h,m)}Object.keys(f.geometry.morphAttributes).length>0&&K(f,i),f.name=n.createUniqueName(i.name||"mesh_"+e),V(f,i),d.extensions&&X(o,f,d),n.assignFinalMaterial(f),u.push(f)}for(let t=0,r=u.length;t<r;t++)n.associations.set(u[t],{meshes:e,primitives:t});if(1===u.length)return i.extensions&&X(o,u[0],i),u[0];const h=new t.Group;i.extensions&&X(o,h,i),n.associations.set(h,{meshes:e});for(let e=0,t=u.length;e<t;e++)h.add(u[e]);return h}))}loadCamera(e){let r;const n=this.json.cameras[e],s=n[n.type];if(s)return"perspective"===n.type?r=new t.PerspectiveCamera(t.MathUtils.radToDeg(s.yfov),s.aspectRatio||1,s.znear||1,s.zfar||2e6):"orthographic"===n.type&&(r=new t.OrthographicCamera(-s.xmag,s.xmag,s.ymag,-s.ymag,s.znear,s.zfar)),n.name&&(r.name=this.createUniqueName(n.name)),V(r,n),Promise.resolve(r);console.warn("THREE.GLTFLoader: Missing camera parameters.")}loadSkin(e){const r=this.json.skins[e],n=[];for(let e=0,t=r.joints.length;e<t;e++)n.push(this._loadNodeShallow(r.joints[e]));return void 0!==r.inverseBindMatrices?n.push(this.getDependency("accessor",r.inverseBindMatrices)):n.push(null),Promise.all(n).then((function(e){const n=e.pop(),s=e,o=[],i=[];for(let e=0,a=s.length;e<a;e++){const a=s[e];if(a){o.push(a);const r=new t.Matrix4;null!==n&&r.fromArray(n.array,16*e),i.push(r)}else console.warn('THREE.GLTFLoader: Joint "%s" could not be found.',r.joints[e])}return new t.Skeleton(o,i)}))}loadAnimation(e){const r=this.json,n=this,s=r.animations[e],o=s.name?s.name:"animation_"+e,i=[],a=[],l=[],c=[],u=[];for(let e=0,t=s.channels.length;e<t;e++){const t=s.channels[e],r=s.samplers[t.sampler],n=t.target,o=n.node,h=void 0!==s.parameters?s.parameters[r.input]:r.input,d=void 0!==s.parameters?s.parameters[r.output]:r.output;void 0!==n.node&&(i.push(this.getDependency("node",o)),a.push(this.getDependency("accessor",h)),l.push(this.getDependency("accessor",d)),c.push(r),u.push(n))}return Promise.all([Promise.all(i),Promise.all(a),Promise.all(l),Promise.all(c),Promise.all(u)]).then((function(e){const r=e[0],s=e[1],i=e[2],a=e[3],l=e[4],c=[];for(let e=0,t=r.length;e<t;e++){const t=r[e],o=s[e],u=i[e],h=a[e],d=l[e];if(void 0===t)continue;t.updateMatrix&&t.updateMatrix();const f=n._createAnimationTracks(t,o,u,h,d);if(f)for(let e=0;e<f.length;e++)c.push(f[e])}return new t.AnimationClip(o,void 0,c)}))}createNodeMesh(e){const t=this.json,r=this,n=t.nodes[e];return void 0===n.mesh?null:r.getDependency("mesh",n.mesh).then((function(e){const t=r._getNodeRef(r.meshCache,n.mesh,e);return void 0!==n.weights&&t.traverse((function(e){if(e.isMesh)for(let t=0,r=n.weights.length;t<r;t++)e.morphTargetInfluences[t]=n.weights[t]})),t}))}loadNode(e){const t=this,r=this.json.nodes[e],n=t._loadNodeShallow(e),s=[],o=r.children||[];for(let e=0,r=o.length;e<r;e++)s.push(t.getDependency("node",o[e]));const i=void 0===r.skin?Promise.resolve(null):t.getDependency("skin",r.skin);return Promise.all([n,Promise.all(s),i]).then((function(e){const t=e[0],r=e[1],n=e[2];null!==n&&t.traverse((function(e){e.isSkinnedMesh&&e.bind(n,Z)}));for(let e=0,n=r.length;e<n;e++)t.add(r[e]);return t}))}_loadNodeShallow(e){const r=this.json,n=this.extensions,s=this;if(void 0!==this.nodeCache[e])return this.nodeCache[e];const o=r.nodes[e],i=o.name?s.createUniqueName(o.name):"",a=[],l=s._invokeOne((function(t){return t.createNodeMesh&&t.createNodeMesh(e)}));return l&&a.push(l),void 0!==o.camera&&a.push(s.getDependency("camera",o.camera).then((function(e){return s._getNodeRef(s.cameraCache,o.camera,e)}))),s._invokeAll((function(t){return t.createNodeAttachment&&t.createNodeAttachment(e)})).forEach((function(e){a.push(e)})),this.nodeCache[e]=Promise.all(a).then((function(r){let a;if(a=!0===o.isBone?new t.Bone:r.length>1?new t.Group:1===r.length?r[0]:new t.Object3D,a!==r[0])for(let e=0,t=r.length;e<t;e++)a.add(r[e]);if(o.name&&(a.userData.name=o.name,a.name=i),V(a,o),o.extensions&&X(n,a,o),void 0!==o.matrix){const e=new t.Matrix4;e.fromArray(o.matrix),a.applyMatrix4(e)}else void 0!==o.translation&&a.position.fromArray(o.translation),void 0!==o.rotation&&a.quaternion.fromArray(o.rotation),void 0!==o.scale&&a.scale.fromArray(o.scale);return s.associations.has(a)||s.associations.set(a,{}),s.associations.get(a).nodes=e,a})),this.nodeCache[e]}loadScene(e){const r=this.extensions,n=this.json.scenes[e],s=this,o=new t.Group;n.name&&(o.name=s.createUniqueName(n.name)),V(o,n),n.extensions&&X(r,o,n);const i=n.nodes||[],a=[];for(let e=0,t=i.length;e<t;e++)a.push(s.getDependency("node",i[e]));return Promise.all(a).then((function(e){for(let t=0,r=e.length;t<r;t++)o.add(e[t]);return s.associations=(e=>{const r=new Map;for(const[e,n]of s.associations)(e instanceof t.Material||e instanceof t.Texture)&&r.set(e,n);return e.traverse((e=>{const t=s.associations.get(e);null!=t&&r.set(e,t)})),r})(o),o}))}_createAnimationTracks(e,r,n,s,o){const i=[],a=e.name?e.name:e.uuid,l=[];let c;switch(G[o.path]===G.weights?e.traverse((function(e){e.morphTargetInfluences&&l.push(e.name?e.name:e.uuid)})):l.push(a),G[o.path]){case G.weights:c=t.NumberKeyframeTrack;break;case G.rotation:c=t.QuaternionKeyframeTrack;break;case G.position:case G.scale:c=t.VectorKeyframeTrack;break;default:if(1===n.itemSize)c=t.NumberKeyframeTrack;else c=t.VectorKeyframeTrack}const u=void 0!==s.interpolation?k[s.interpolation]:t.InterpolateLinear,h=this._getArrayFromAccessor(n);for(let e=0,t=l.length;e<t;e++){const t=new c(l[e]+"."+G[o.path],r.array,h,u);"CUBICSPLINE"===s.interpolation&&this._createCubicSplineTrackInterpolant(t),i.push(t)}return i}_getArrayFromAccessor(e){let t=e.array;if(e.normalized){const e=Q(t.constructor),r=new Float32Array(t.length);for(let n=0,s=t.length;n<s;n++)r[n]=t[n]*e;t=r}return t}_createCubicSplineTrackInterpolant(e){e.createInterpolant=function(e){return new(this instanceof t.QuaternionKeyframeTrack?P:D)(this.times,this.values,this.getValueSize()/3,e)},e.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline=!0}}function _(e,r,n){const s=r.attributes,o=[];function i(t,r){return n.getDependency("accessor",t).then((function(t){e.setAttribute(r,t)}))}for(const t in s){const r=U[t]||t.toLowerCase();r in e.attributes||o.push(i(s[t],r))}if(void 0!==r.indices&&!e.index){const t=n.getDependency("accessor",r.indices).then((function(t){e.setIndex(t)}));o.push(t)}return t.ColorManagement.workingColorSpace!==t.LinearSRGBColorSpace&&"COLOR_0"in s&&console.warn(`THREE.GLTFLoader: Converting vertex colors from "srgb-linear" to "${t.ColorManagement.workingColorSpace}" not supported.`),V(e,r),function(e,r,n){const s=r.attributes,o=new t.Box3;if(void 0===s.POSITION)return;{const e=n.json.accessors[s.POSITION],r=e.min,i=e.max;if(void 0===r||void 0===i)return void console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.");if(o.set(new t.Vector3(r[0],r[1],r[2]),new t.Vector3(i[0],i[1],i[2])),e.normalized){const t=Q(B[e.componentType]);o.min.multiplyScalar(t),o.max.multiplyScalar(t)}}const i=r.targets;if(void 0!==i){const e=new t.Vector3,r=new t.Vector3;for(let t=0,s=i.length;t<s;t++){const s=i[t];if(void 0!==s.POSITION){const t=n.json.accessors[s.POSITION],o=t.min,i=t.max;if(void 0!==o&&void 0!==i){if(r.setX(Math.max(Math.abs(o[0]),Math.abs(i[0]))),r.setY(Math.max(Math.abs(o[1]),Math.abs(i[1]))),r.setZ(Math.max(Math.abs(o[2]),Math.abs(i[2]))),t.normalized){const e=Q(B[t.componentType]);r.multiplyScalar(e)}e.max(r)}else console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.")}}o.expandByVector(e)}e.boundingBox=o;const a=new t.Sphere;o.getCenter(a.center),a.radius=o.min.distanceTo(o.max)/2,e.boundingSphere=a}(e,r,n),Promise.all(o).then((function(){return void 0!==r.targets?function(e,t,r){let n=!1,s=!1,o=!1;for(let e=0,r=t.length;e<r;e++){const r=t[e];if(void 0!==r.POSITION&&(n=!0),void 0!==r.NORMAL&&(s=!0),void 0!==r.COLOR_0&&(o=!0),n&&s&&o)break}if(!n&&!s&&!o)return Promise.resolve(e);const i=[],a=[],l=[];for(let c=0,u=t.length;c<u;c++){const u=t[c];if(n){const t=void 0!==u.POSITION?r.getDependency("accessor",u.POSITION):e.attributes.position;i.push(t)}if(s){const t=void 0!==u.NORMAL?r.getDependency("accessor",u.NORMAL):e.attributes.normal;a.push(t)}if(o){const t=void 0!==u.COLOR_0?r.getDependency("accessor",u.COLOR_0):e.attributes.color;l.push(t)}}return Promise.all([Promise.all(i),Promise.all(a),Promise.all(l)]).then((function(t){const r=t[0],i=t[1],a=t[2];return n&&(e.morphAttributes.position=r),s&&(e.morphAttributes.normal=i),o&&(e.morphAttributes.color=a),e.morphTargetsRelative=!0,e}))}(e,r.targets,n):e}))}const $=new WeakMap;class ee extends t.Loader{constructor(e){super(e),this.decoderPath="",this.decoderConfig={},this.decoderBinary=null,this.decoderPending=null,this.workerLimit=4,this.workerPool=[],this.workerNextTaskID=1,this.workerSourceURL="",this.defaultAttributeIDs={position:"POSITION",normal:"NORMAL",color:"COLOR",uv:"TEX_COORD"},this.defaultAttributeTypes={position:"Float32Array",normal:"Float32Array",color:"Float32Array",uv:"Float32Array"}}setDecoderPath(e){return this.decoderPath=e,this}setDecoderConfig(e){return this.decoderConfig=e,this}setWorkerLimit(e){return this.workerLimit=e,this}load(e,r,n,s){const o=new t.FileLoader(this.manager);o.setPath(this.path),o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setWithCredentials(this.withCredentials),o.load(e,(e=>{this.parse(e,r,s)}),n,s)}parse(e,r,n=(()=>{})){this.decodeDracoFile(e,r,null,null,t.SRGBColorSpace).catch(n)}decodeDracoFile(e,r,n,s,o=t.LinearSRGBColorSpace,i=(()=>{})){const a={attributeIDs:n||this.defaultAttributeIDs,attributeTypes:s||this.defaultAttributeTypes,useUniqueIDs:!!n,vertexColorSpace:o};return this.decodeGeometry(e,a).then(r).catch(i)}decodeGeometry(e,t){const r=JSON.stringify(t);if($.has(e)){const t=$.get(e);if(t.key===r)return t.promise;if(0===e.byteLength)throw new Error("THREE.DRACOLoader: Unable to re-decode a buffer with different settings. Buffer has already been transferred.")}let n;const s=this.workerNextTaskID++,o=e.byteLength,i=this._getWorker(s,o).then((r=>(n=r,new Promise(((r,o)=>{n._callbacks[s]={resolve:r,reject:o},n.postMessage({type:"decode",id:s,taskConfig:t,buffer:e},[e])}))))).then((e=>this._createGeometry(e.geometry)));return i.catch((()=>!0)).then((()=>{n&&s&&this._releaseTask(n,s)})),$.set(e,{key:r,promise:i}),i}_createGeometry(e){const r=new t.BufferGeometry;e.index&&r.setIndex(new t.BufferAttribute(e.index.array,1));for(let n=0;n<e.attributes.length;n++){const s=e.attributes[n],o=s.name,i=s.array,a=s.itemSize,l=new t.BufferAttribute(i,a);"color"===o&&(this._assignVertexColorSpace(l,s.vertexColorSpace),l.normalized=i instanceof Float32Array==!1),r.setAttribute(o,l)}return r}_assignVertexColorSpace(e,r){if(r!==t.SRGBColorSpace)return;const n=new t.Color;for(let t=0,r=e.count;t<r;t++)n.fromBufferAttribute(e,t).convertSRGBToLinear(),e.setXYZ(t,n.r,n.g,n.b)}_loadLibrary(e,r){const n=new t.FileLoader(this.manager);return n.setPath(this.decoderPath),n.setResponseType(r),n.setWithCredentials(this.withCredentials),new Promise(((t,r)=>{n.load(e,t,void 0,r)}))}preload(){return this._initDecoder(),this}_initDecoder(){if(this.decoderPending)return this.decoderPending;const e="object"!=typeof WebAssembly||"js"===this.decoderConfig.type,t=[];return e?t.push(this._loadLibrary("draco_decoder.js","text")):(t.push(this._loadLibrary("draco_wasm_wrapper.js","text")),t.push(this._loadLibrary("draco_decoder.wasm","arraybuffer"))),this.decoderPending=Promise.all(t).then((t=>{const r=t[0];e||(this.decoderConfig.wasmBinary=t[1]);const n=te.toString(),s=["/* draco decoder */",r,"","/* worker */",n.substring(n.indexOf("{")+1,n.lastIndexOf("}"))].join("\n");this.workerSourceURL=URL.createObjectURL(new Blob([s]))})),this.decoderPending}_getWorker(e,t){return this._initDecoder().then((()=>{if(this.workerPool.length<this.workerLimit){const e=new Worker(this.workerSourceURL);e._callbacks={},e._taskCosts={},e._taskLoad=0,e.postMessage({type:"init",decoderConfig:this.decoderConfig}),e.onmessage=function(t){const r=t.data;switch(r.type){case"decode":e._callbacks[r.id].resolve(r);break;case"error":e._callbacks[r.id].reject(r);break;default:console.error('THREE.DRACOLoader: Unexpected message, "'+r.type+'"')}},this.workerPool.push(e)}else this.workerPool.sort((function(e,t){return e._taskLoad>t._taskLoad?-1:1}));const r=this.workerPool[this.workerPool.length-1];return r._taskCosts[e]=t,r._taskLoad+=t,r}))}_releaseTask(e,t){e._taskLoad-=e._taskCosts[t],delete e._callbacks[t],delete e._taskCosts[t]}debug(){console.log("Task load: ",this.workerPool.map((e=>e._taskLoad)))}dispose(){for(let e=0;e<this.workerPool.length;++e)this.workerPool[e].terminate();return this.workerPool.length=0,""!==this.workerSourceURL&&URL.revokeObjectURL(this.workerSourceURL),this}}function te(){let e,t;function r(e,t,r,n,s,o){const i=o.num_components(),a=r.num_points()*i,l=a*s.BYTES_PER_ELEMENT,c=function(e,t){switch(t){case Float32Array:return e.DT_FLOAT32;case Int8Array:return e.DT_INT8;case Int16Array:return e.DT_INT16;case Int32Array:return e.DT_INT32;case Uint8Array:return e.DT_UINT8;case Uint16Array:return e.DT_UINT16;case Uint32Array:return e.DT_UINT32}}(e,s),u=e._malloc(l);t.GetAttributeDataArrayForAllPoints(r,o,c,l,u);const h=new s(e.HEAPF32.buffer,u,a).slice();return e._free(u),{name:n,array:h,itemSize:i}}onmessage=function(n){const s=n.data;switch(s.type){case"init":e=s.decoderConfig,t=new Promise((function(t){e.onModuleLoaded=function(e){t({draco:e})},DracoDecoderModule(e)}));break;case"decode":const n=s.buffer,o=s.taskConfig;t.then((e=>{const t=e.draco,i=new t.Decoder;try{const e=function(e,t,n,s){const o=s.attributeIDs,i=s.attributeTypes;let a,l;const c=t.GetEncodedGeometryType(n);if(c===e.TRIANGULAR_MESH)a=new e.Mesh,l=t.DecodeArrayToMesh(n,n.byteLength,a);else{if(c!==e.POINT_CLOUD)throw new Error("THREE.DRACOLoader: Unexpected geometry type.");a=new e.PointCloud,l=t.DecodeArrayToPointCloud(n,n.byteLength,a)}if(!l.ok()||0===a.ptr)throw new Error("THREE.DRACOLoader: Decoding failed: "+l.error_msg());const u={index:null,attributes:[]};for(const n in o){const l=self[i[n]];let c,h;if(s.useUniqueIDs)h=o[n],c=t.GetAttributeByUniqueId(a,h);else{if(h=t.GetAttributeId(a,e[o[n]]),-1===h)continue;c=t.GetAttribute(a,h)}const d=r(e,t,a,n,l,c);"color"===n&&(d.vertexColorSpace=s.vertexColorSpace),u.attributes.push(d)}c===e.TRIANGULAR_MESH&&(u.index=function(e,t,r){const n=r.num_faces(),s=3*n,o=4*s,i=e._malloc(o);t.GetTrianglesUInt32Array(r,o,i);const a=new Uint32Array(e.HEAPF32.buffer,i,s).slice();return e._free(i),{array:a,itemSize:1}}(e,t,a));return e.destroy(a),u}(t,i,new Int8Array(n),o),a=e.attributes.map((e=>e.array.buffer));e.index&&a.push(e.index.array.buffer),self.postMessage({type:"decode",id:s.id,geometry:e},a)}catch(e){console.error(e),self.postMessage({type:"error",id:s.id,error:e.message})}finally{t.destroy(i)}}))}}}function re(e,r,n={}){const s=new t.Vector3,o=new t.Quaternion,i=new t.Vector3,a=new t.Matrix4,l=new t.Matrix4,c=new t.Matrix4;n.preserveMatrix=void 0===n.preserveMatrix||n.preserveMatrix,n.preservePosition=void 0===n.preservePosition||n.preservePosition,n.preserveHipPosition=void 0!==n.preserveHipPosition&&n.preserveHipPosition,n.useTargetMatrix=void 0!==n.useTargetMatrix&&n.useTargetMatrix,n.hip=void 0!==n.hip?n.hip:"hip",n.names=n.names||{};const u=r.isObject3D?r.skeleton.bones:se(r),h=e.isObject3D?e.skeleton.bones:se(e);let d,f,m,p,g;if(e.isObject3D?e.skeleton.pose():(n.useTargetMatrix=!0,n.preserveMatrix=!1),n.preservePosition){g=[];for(let e=0;e<h.length;e++)g.push(h[e].position.clone())}if(n.preserveMatrix){e.updateMatrixWorld(),e.matrixWorld.identity();for(let t=0;t<e.children.length;++t)e.children[t].updateMatrixWorld(!0)}if(n.offsets){d=[];for(let e=0;e<h.length;++e)f=h[e],m=n.names[f.name]||f.name,n.offsets[m]&&(f.matrix.multiply(n.offsets[m]),f.matrix.decompose(f.position,f.quaternion,f.scale),f.updateMatrixWorld()),d.push(f.matrixWorld.clone())}for(let t=0;t<h.length;++t){if(f=h[t],m=n.names[f.name]||f.name,p=ne(m,u),c.copy(f.matrixWorld),p){if(p.updateMatrixWorld(),n.useTargetMatrix?l.copy(p.matrixWorld):(l.copy(e.matrixWorld).invert(),l.multiply(p.matrixWorld)),i.setFromMatrixScale(l),l.scale(i.set(1/i.x,1/i.y,1/i.z)),c.makeRotationFromQuaternion(o.setFromRotationMatrix(l)),e.isObject3D){const t=h.indexOf(f),r=d?d[t]:a.copy(e.skeleton.boneInverses[t]).invert();c.multiply(r)}c.copyPosition(l)}f.parent&&f.parent.isBone?(f.matrix.copy(f.parent.matrixWorld).invert(),f.matrix.multiply(c)):f.matrix.copy(c),n.preserveHipPosition&&m===n.hip&&f.matrix.setPosition(s.set(0,f.position.y,0)),f.matrix.decompose(f.position,f.quaternion,f.scale),f.updateMatrixWorld()}if(n.preservePosition)for(let e=0;e<h.length;++e)f=h[e],m=n.names[f.name]||f.name,m!==n.hip&&f.position.copy(g[e]);n.preserveMatrix&&e.updateMatrixWorld(!0)}function ne(e,t){for(let r=0,n=se(t);r<n.length;r++)if(e===n[r].name)return n[r]}function se(e){return Array.isArray(e)?e:e.bones}function oe(e,t,r){r(e,t);for(let n=0;n<e.children.length;n++)oe(e.children[n],t.children[n],r)}var ie=Object.freeze({__proto__:null,retarget:re,retargetClip:function(e,r,n,s={}){s.useFirstFramePosition=void 0!==s.useFirstFramePosition&&s.useFirstFramePosition,s.fps=void 0!==s.fps?s.fps:30,s.names=s.names||[],r.isObject3D||(r=function(e){const r=new t.SkeletonHelper(e.bones[0]);return r.skeleton=e,r}(r));const o=Math.round(n.duration*(s.fps/1e3)*1e3),i=1/s.fps,a=[],l=new t.AnimationMixer(r),c=se(e.skeleton),u=[];let h,d,f,m,p;l.clipAction(n).play(),l.update(0),r.updateMatrixWorld();for(let t=0;t<o;++t){const n=t*i;re(e,r,s);for(let e=0;e<c.length;++e)p=s.names[c[e].name]||c[e].name,f=ne(p,r.skeleton),f&&(d=c[e],m=u[e]=u[e]||{bone:d},s.hip===p&&(m.pos||(m.pos={times:new Float32Array(o),values:new Float32Array(3*o)}),s.useFirstFramePosition&&(0===t&&(h=d.position.clone()),d.position.sub(h)),m.pos.times[t]=n,d.position.toArray(m.pos.values,3*t)),m.quat||(m.quat={times:new Float32Array(o),values:new Float32Array(4*o)}),m.quat.times[t]=n,d.quaternion.toArray(m.quat.values,4*t));l.update(i),r.updateMatrixWorld()}for(let e=0;e<u.length;++e)m=u[e],m&&(m.pos&&a.push(new t.VectorKeyframeTrack(".bones["+m.bone.name+"].position",m.pos.times,m.pos.values)),a.push(new t.QuaternionKeyframeTrack(".bones["+m.bone.name+"].quaternion",m.quat.times,m.quat.values)));return l.uncacheAction(n),new t.AnimationClip(n.name,-1,a)},clone:function(e){const t=new Map,r=new Map,n=e.clone();return oe(e,n,(function(e,n){t.set(n,e),r.set(e,n)})),n.traverse((function(e){if(!e.isSkinnedMesh)return;const n=e,s=t.get(e),o=s.skeleton.bones;n.skeleton=s.skeleton.clone(),n.bindMatrix.copy(s.bindMatrix),n.skeleton.bones=o.map((function(e){return r.get(e)})),n.bind(n.skeleton,n.bindMatrix)})),n}});const ae={name:"CopyShader",uniforms:{tDiffuse:{value:null},opacity:{value:1}},vertexShader:"\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform float opacity;\n\n\t\tuniform sampler2D tDiffuse;\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvec4 texel = texture2D( tDiffuse, vUv );\n\t\t\tgl_FragColor = opacity * texel;\n\n\n\t\t}"};class le{constructor(){this.isPass=!0,this.enabled=!0,this.needsSwap=!0,this.clear=!1,this.renderToScreen=!1}setSize(){}render(){console.error("THREE.Pass: .render() must be implemented in derived pass.")}dispose(){}}const ce=new t.OrthographicCamera(-1,1,1,-1,0,1);class ue extends t.BufferGeometry{constructor(){super(),this.setAttribute("position",new t.Float32BufferAttribute([-1,3,0,-1,-1,0,3,-1,0],3)),this.setAttribute("uv",new t.Float32BufferAttribute([0,2,0,0,2,0],2))}}const he=new ue;class de{constructor(e){this._mesh=new t.Mesh(he,e)}dispose(){this._mesh.geometry.dispose()}render(e){e.render(this._mesh,ce)}get material(){return this._mesh.material}set material(e){this._mesh.material=e}}class fe extends le{constructor(e,r){super(),this.textureID=void 0!==r?r:"tDiffuse",e instanceof t.ShaderMaterial?(this.uniforms=e.uniforms,this.material=e):e&&(this.uniforms=t.UniformsUtils.clone(e.uniforms),this.material=new t.ShaderMaterial({name:void 0!==e.name?e.name:"unspecified",defines:Object.assign({},e.defines),uniforms:this.uniforms,vertexShader:e.vertexShader,fragmentShader:e.fragmentShader})),this.fsQuad=new de(this.material)}render(e,t,r){this.uniforms[this.textureID]&&(this.uniforms[this.textureID].value=r.texture),this.fsQuad.material=this.material,this.renderToScreen?(e.setRenderTarget(null),this.fsQuad.render(e)):(e.setRenderTarget(t),this.clear&&e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil),this.fsQuad.render(e))}dispose(){this.material.dispose(),this.fsQuad.dispose()}}class me extends le{constructor(e,t){super(),this.scene=e,this.camera=t,this.clear=!0,this.needsSwap=!1,this.inverse=!1}render(e,t,r){const n=e.getContext(),s=e.state;let o,i;s.buffers.color.setMask(!1),s.buffers.depth.setMask(!1),s.buffers.color.setLocked(!0),s.buffers.depth.setLocked(!0),this.inverse?(o=0,i=1):(o=1,i=0),s.buffers.stencil.setTest(!0),s.buffers.stencil.setOp(n.REPLACE,n.REPLACE,n.REPLACE),s.buffers.stencil.setFunc(n.ALWAYS,o,4294967295),s.buffers.stencil.setClear(i),s.buffers.stencil.setLocked(!0),e.setRenderTarget(r),this.clear&&e.clear(),e.render(this.scene,this.camera),e.setRenderTarget(t),this.clear&&e.clear(),e.render(this.scene,this.camera),s.buffers.color.setLocked(!1),s.buffers.depth.setLocked(!1),s.buffers.color.setMask(!0),s.buffers.depth.setMask(!0),s.buffers.stencil.setLocked(!1),s.buffers.stencil.setFunc(n.EQUAL,1,4294967295),s.buffers.stencil.setOp(n.KEEP,n.KEEP,n.KEEP),s.buffers.stencil.setLocked(!0)}}class pe extends le{constructor(){super(),this.needsSwap=!1}render(e){e.state.buffers.stencil.setLocked(!1),e.state.buffers.stencil.setTest(!1)}}const ge={name:"SMAAEdgesShader",defines:{SMAA_THRESHOLD:"0.1"},uniforms:{tDiffuse:{value:null},resolution:{value:new t.Vector2(1/1024,1/512)}},vertexShader:"\n\n\t\tuniform vec2 resolution;\n\n\t\tvarying vec2 vUv;\n\t\tvarying vec4 vOffset[ 3 ];\n\n\t\tvoid SMAAEdgeDetectionVS( vec2 texcoord ) {\n\t\t\tvOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -1.0, 0.0, 0.0,  1.0 ); // WebGL port note: Changed sign in W component\n\t\t\tvOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4(  1.0, 0.0, 0.0, -1.0 ); // WebGL port note: Changed sign in W component\n\t\t\tvOffset[ 2 ] = texcoord.xyxy + resolution.xyxy * vec4( -2.0, 0.0, 0.0,  2.0 ); // WebGL port note: Changed sign in W component\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\n\t\t\tSMAAEdgeDetectionVS( vUv );\n\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform sampler2D tDiffuse;\n\n\t\tvarying vec2 vUv;\n\t\tvarying vec4 vOffset[ 3 ];\n\n\t\tvec4 SMAAColorEdgeDetectionPS( vec2 texcoord, vec4 offset[3], sampler2D colorTex ) {\n\t\t\tvec2 threshold = vec2( SMAA_THRESHOLD, SMAA_THRESHOLD );\n\n\t\t\t// Calculate color deltas:\n\t\t\tvec4 delta;\n\t\t\tvec3 C = texture2D( colorTex, texcoord ).rgb;\n\n\t\t\tvec3 Cleft = texture2D( colorTex, offset[0].xy ).rgb;\n\t\t\tvec3 t = abs( C - Cleft );\n\t\t\tdelta.x = max( max( t.r, t.g ), t.b );\n\n\t\t\tvec3 Ctop = texture2D( colorTex, offset[0].zw ).rgb;\n\t\t\tt = abs( C - Ctop );\n\t\t\tdelta.y = max( max( t.r, t.g ), t.b );\n\n\t\t\t// We do the usual threshold:\n\t\t\tvec2 edges = step( threshold, delta.xy );\n\n\t\t\t// Then discard if there is no edge:\n\t\t\tif ( dot( edges, vec2( 1.0, 1.0 ) ) == 0.0 )\n\t\t\t\tdiscard;\n\n\t\t\t// Calculate right and bottom deltas:\n\t\t\tvec3 Cright = texture2D( colorTex, offset[1].xy ).rgb;\n\t\t\tt = abs( C - Cright );\n\t\t\tdelta.z = max( max( t.r, t.g ), t.b );\n\n\t\t\tvec3 Cbottom  = texture2D( colorTex, offset[1].zw ).rgb;\n\t\t\tt = abs( C - Cbottom );\n\t\t\tdelta.w = max( max( t.r, t.g ), t.b );\n\n\t\t\t// Calculate the maximum delta in the direct neighborhood:\n\t\t\tfloat maxDelta = max( max( max( delta.x, delta.y ), delta.z ), delta.w );\n\n\t\t\t// Calculate left-left and top-top deltas:\n\t\t\tvec3 Cleftleft  = texture2D( colorTex, offset[2].xy ).rgb;\n\t\t\tt = abs( C - Cleftleft );\n\t\t\tdelta.z = max( max( t.r, t.g ), t.b );\n\n\t\t\tvec3 Ctoptop = texture2D( colorTex, offset[2].zw ).rgb;\n\t\t\tt = abs( C - Ctoptop );\n\t\t\tdelta.w = max( max( t.r, t.g ), t.b );\n\n\t\t\t// Calculate the final maximum delta:\n\t\t\tmaxDelta = max( max( maxDelta, delta.z ), delta.w );\n\n\t\t\t// Local contrast adaptation in action:\n\t\t\tedges.xy *= step( 0.5 * maxDelta, delta.xy );\n\n\t\t\treturn vec4( edges, 0.0, 0.0 );\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = SMAAColorEdgeDetectionPS( vUv, vOffset, tDiffuse );\n\n\t\t}"},xe={name:"SMAAWeightsShader",defines:{SMAA_MAX_SEARCH_STEPS:"8",SMAA_AREATEX_MAX_DISTANCE:"16",SMAA_AREATEX_PIXEL_SIZE:"( 1.0 / vec2( 160.0, 560.0 ) )",SMAA_AREATEX_SUBTEX_SIZE:"( 1.0 / 7.0 )"},uniforms:{tDiffuse:{value:null},tArea:{value:null},tSearch:{value:null},resolution:{value:new t.Vector2(1/1024,1/512)}},vertexShader:"\n\n\t\tuniform vec2 resolution;\n\n\t\tvarying vec2 vUv;\n\t\tvarying vec4 vOffset[ 3 ];\n\t\tvarying vec2 vPixcoord;\n\n\t\tvoid SMAABlendingWeightCalculationVS( vec2 texcoord ) {\n\t\t\tvPixcoord = texcoord / resolution;\n\n\t\t\t// We will use these offsets for the searches later on (see @PSEUDO_GATHER4):\n\t\t\tvOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -0.25, 0.125, 1.25, 0.125 ); // WebGL port note: Changed sign in Y and W components\n\t\t\tvOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4( -0.125, 0.25, -0.125, -1.25 ); // WebGL port note: Changed sign in Y and W components\n\n\t\t\t// And these for the searches, they indicate the ends of the loops:\n\t\t\tvOffset[ 2 ] = vec4( vOffset[ 0 ].xz, vOffset[ 1 ].yw ) + vec4( -2.0, 2.0, -2.0, 2.0 ) * resolution.xxyy * float( SMAA_MAX_SEARCH_STEPS );\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\n\t\t\tSMAABlendingWeightCalculationVS( vUv );\n\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\t#define SMAASampleLevelZeroOffset( tex, coord, offset ) texture2D( tex, coord + float( offset ) * resolution, 0.0 )\n\n\t\tuniform sampler2D tDiffuse;\n\t\tuniform sampler2D tArea;\n\t\tuniform sampler2D tSearch;\n\t\tuniform vec2 resolution;\n\n\t\tvarying vec2 vUv;\n\t\tvarying vec4 vOffset[3];\n\t\tvarying vec2 vPixcoord;\n\n\t\t#if __VERSION__ == 100\n\t\tvec2 round( vec2 x ) {\n\t\t\treturn sign( x ) * floor( abs( x ) + 0.5 );\n\t\t}\n\t\t#endif\n\n\t\tfloat SMAASearchLength( sampler2D searchTex, vec2 e, float bias, float scale ) {\n\t\t\t// Not required if searchTex accesses are set to point:\n\t\t\t// float2 SEARCH_TEX_PIXEL_SIZE = 1.0 / float2(66.0, 33.0);\n\t\t\t// e = float2(bias, 0.0) + 0.5 * SEARCH_TEX_PIXEL_SIZE +\n\t\t\t//     e * float2(scale, 1.0) * float2(64.0, 32.0) * SEARCH_TEX_PIXEL_SIZE;\n\t\t\te.r = bias + e.r * scale;\n\t\t\treturn 255.0 * texture2D( searchTex, e, 0.0 ).r;\n\t\t}\n\n\t\tfloat SMAASearchXLeft( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {\n\t\t\t/**\n\t\t\t\t* @PSEUDO_GATHER4\n\t\t\t\t* This texcoord has been offset by (-0.25, -0.125) in the vertex shader to\n\t\t\t\t* sample between edge, thus fetching four edges in a row.\n\t\t\t\t* Sampling with different offsets in each direction allows to disambiguate\n\t\t\t\t* which edges are active from the four fetched ones.\n\t\t\t\t*/\n\t\t\tvec2 e = vec2( 0.0, 1.0 );\n\n\t\t\tfor ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) { // WebGL port note: Changed while to for\n\t\t\t\te = texture2D( edgesTex, texcoord, 0.0 ).rg;\n\t\t\t\ttexcoord -= vec2( 2.0, 0.0 ) * resolution;\n\t\t\t\tif ( ! ( texcoord.x > end && e.g > 0.8281 && e.r == 0.0 ) ) break;\n\t\t\t}\n\n\t\t\t// We correct the previous (-0.25, -0.125) offset we applied:\n\t\t\ttexcoord.x += 0.25 * resolution.x;\n\n\t\t\t// The searches are bias by 1, so adjust the coords accordingly:\n\t\t\ttexcoord.x += resolution.x;\n\n\t\t\t// Disambiguate the length added by the last step:\n\t\t\ttexcoord.x += 2.0 * resolution.x; // Undo last step\n\t\t\ttexcoord.x -= resolution.x * SMAASearchLength(searchTex, e, 0.0, 0.5);\n\n\t\t\treturn texcoord.x;\n\t\t}\n\n\t\tfloat SMAASearchXRight( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {\n\t\t\tvec2 e = vec2( 0.0, 1.0 );\n\n\t\t\tfor ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) { // WebGL port note: Changed while to for\n\t\t\t\te = texture2D( edgesTex, texcoord, 0.0 ).rg;\n\t\t\t\ttexcoord += vec2( 2.0, 0.0 ) * resolution;\n\t\t\t\tif ( ! ( texcoord.x < end && e.g > 0.8281 && e.r == 0.0 ) ) break;\n\t\t\t}\n\n\t\t\ttexcoord.x -= 0.25 * resolution.x;\n\t\t\ttexcoord.x -= resolution.x;\n\t\t\ttexcoord.x -= 2.0 * resolution.x;\n\t\t\ttexcoord.x += resolution.x * SMAASearchLength( searchTex, e, 0.5, 0.5 );\n\n\t\t\treturn texcoord.x;\n\t\t}\n\n\t\tfloat SMAASearchYUp( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {\n\t\t\tvec2 e = vec2( 1.0, 0.0 );\n\n\t\t\tfor ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) { // WebGL port note: Changed while to for\n\t\t\t\te = texture2D( edgesTex, texcoord, 0.0 ).rg;\n\t\t\t\ttexcoord += vec2( 0.0, 2.0 ) * resolution; // WebGL port note: Changed sign\n\t\t\t\tif ( ! ( texcoord.y > end && e.r > 0.8281 && e.g == 0.0 ) ) break;\n\t\t\t}\n\n\t\t\ttexcoord.y -= 0.25 * resolution.y; // WebGL port note: Changed sign\n\t\t\ttexcoord.y -= resolution.y; // WebGL port note: Changed sign\n\t\t\ttexcoord.y -= 2.0 * resolution.y; // WebGL port note: Changed sign\n\t\t\ttexcoord.y += resolution.y * SMAASearchLength( searchTex, e.gr, 0.0, 0.5 ); // WebGL port note: Changed sign\n\n\t\t\treturn texcoord.y;\n\t\t}\n\n\t\tfloat SMAASearchYDown( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {\n\t\t\tvec2 e = vec2( 1.0, 0.0 );\n\n\t\t\tfor ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) { // WebGL port note: Changed while to for\n\t\t\t\te = texture2D( edgesTex, texcoord, 0.0 ).rg;\n\t\t\t\ttexcoord -= vec2( 0.0, 2.0 ) * resolution; // WebGL port note: Changed sign\n\t\t\t\tif ( ! ( texcoord.y < end && e.r > 0.8281 && e.g == 0.0 ) ) break;\n\t\t\t}\n\n\t\t\ttexcoord.y += 0.25 * resolution.y; // WebGL port note: Changed sign\n\t\t\ttexcoord.y += resolution.y; // WebGL port note: Changed sign\n\t\t\ttexcoord.y += 2.0 * resolution.y; // WebGL port note: Changed sign\n\t\t\ttexcoord.y -= resolution.y * SMAASearchLength( searchTex, e.gr, 0.5, 0.5 ); // WebGL port note: Changed sign\n\n\t\t\treturn texcoord.y;\n\t\t}\n\n\t\tvec2 SMAAArea( sampler2D areaTex, vec2 dist, float e1, float e2, float offset ) {\n\t\t\t// Rounding prevents precision errors of bilinear filtering:\n\t\t\tvec2 texcoord = float( SMAA_AREATEX_MAX_DISTANCE ) * round( 4.0 * vec2( e1, e2 ) ) + dist;\n\n\t\t\t// We do a scale and bias for mapping to texel space:\n\t\t\ttexcoord = SMAA_AREATEX_PIXEL_SIZE * texcoord + ( 0.5 * SMAA_AREATEX_PIXEL_SIZE );\n\n\t\t\t// Move to proper place, according to the subpixel offset:\n\t\t\ttexcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset;\n\n\t\t\treturn texture2D( areaTex, texcoord, 0.0 ).rg;\n\t\t}\n\n\t\tvec4 SMAABlendingWeightCalculationPS( vec2 texcoord, vec2 pixcoord, vec4 offset[ 3 ], sampler2D edgesTex, sampler2D areaTex, sampler2D searchTex, ivec4 subsampleIndices ) {\n\t\t\tvec4 weights = vec4( 0.0, 0.0, 0.0, 0.0 );\n\n\t\t\tvec2 e = texture2D( edgesTex, texcoord ).rg;\n\n\t\t\tif ( e.g > 0.0 ) { // Edge at north\n\t\t\t\tvec2 d;\n\n\t\t\t\t// Find the distance to the left:\n\t\t\t\tvec2 coords;\n\t\t\t\tcoords.x = SMAASearchXLeft( edgesTex, searchTex, offset[ 0 ].xy, offset[ 2 ].x );\n\t\t\t\tcoords.y = offset[ 1 ].y; // offset[1].y = texcoord.y - 0.25 * resolution.y (@CROSSING_OFFSET)\n\t\t\t\td.x = coords.x;\n\n\t\t\t\t// Now fetch the left crossing edges, two at a time using bilinear\n\t\t\t\t// filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to\n\t\t\t\t// discern what value each edge has:\n\t\t\t\tfloat e1 = texture2D( edgesTex, coords, 0.0 ).r;\n\n\t\t\t\t// Find the distance to the right:\n\t\t\t\tcoords.x = SMAASearchXRight( edgesTex, searchTex, offset[ 0 ].zw, offset[ 2 ].y );\n\t\t\t\td.y = coords.x;\n\n\t\t\t\t// We want the distances to be in pixel units (doing this here allow to\n\t\t\t\t// better interleave arithmetic and memory accesses):\n\t\t\t\td = d / resolution.x - pixcoord.x;\n\n\t\t\t\t// SMAAArea below needs a sqrt, as the areas texture is compressed\n\t\t\t\t// quadratically:\n\t\t\t\tvec2 sqrt_d = sqrt( abs( d ) );\n\n\t\t\t\t// Fetch the right crossing edges:\n\t\t\t\tcoords.y -= 1.0 * resolution.y; // WebGL port note: Added\n\t\t\t\tfloat e2 = SMAASampleLevelZeroOffset( edgesTex, coords, ivec2( 1, 0 ) ).r;\n\n\t\t\t\t// Ok, we know how this pattern looks like, now it is time for getting\n\t\t\t\t// the actual area:\n\t\t\t\tweights.rg = SMAAArea( areaTex, sqrt_d, e1, e2, float( subsampleIndices.y ) );\n\t\t\t}\n\n\t\t\tif ( e.r > 0.0 ) { // Edge at west\n\t\t\t\tvec2 d;\n\n\t\t\t\t// Find the distance to the top:\n\t\t\t\tvec2 coords;\n\n\t\t\t\tcoords.y = SMAASearchYUp( edgesTex, searchTex, offset[ 1 ].xy, offset[ 2 ].z );\n\t\t\t\tcoords.x = offset[ 0 ].x; // offset[1].x = texcoord.x - 0.25 * resolution.x;\n\t\t\t\td.x = coords.y;\n\n\t\t\t\t// Fetch the top crossing edges:\n\t\t\t\tfloat e1 = texture2D( edgesTex, coords, 0.0 ).g;\n\n\t\t\t\t// Find the distance to the bottom:\n\t\t\t\tcoords.y = SMAASearchYDown( edgesTex, searchTex, offset[ 1 ].zw, offset[ 2 ].w );\n\t\t\t\td.y = coords.y;\n\n\t\t\t\t// We want the distances to be in pixel units:\n\t\t\t\td = d / resolution.y - pixcoord.y;\n\n\t\t\t\t// SMAAArea below needs a sqrt, as the areas texture is compressed\n\t\t\t\t// quadratically:\n\t\t\t\tvec2 sqrt_d = sqrt( abs( d ) );\n\n\t\t\t\t// Fetch the bottom crossing edges:\n\t\t\t\tcoords.y -= 1.0 * resolution.y; // WebGL port note: Added\n\t\t\t\tfloat e2 = SMAASampleLevelZeroOffset( edgesTex, coords, ivec2( 0, 1 ) ).g;\n\n\t\t\t\t// Get the area for this direction:\n\t\t\t\tweights.ba = SMAAArea( areaTex, sqrt_d, e1, e2, float( subsampleIndices.x ) );\n\t\t\t}\n\n\t\t\treturn weights;\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = SMAABlendingWeightCalculationPS( vUv, vPixcoord, vOffset, tDiffuse, tArea, tSearch, ivec4( 0.0 ) );\n\n\t\t}"},ve={name:"SMAABlendShader",uniforms:{tDiffuse:{value:null},tColor:{value:null},resolution:{value:new t.Vector2(1/1024,1/512)}},vertexShader:"\n\n\t\tuniform vec2 resolution;\n\n\t\tvarying vec2 vUv;\n\t\tvarying vec4 vOffset[ 2 ];\n\n\t\tvoid SMAANeighborhoodBlendingVS( vec2 texcoord ) {\n\t\t\tvOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -1.0, 0.0, 0.0, 1.0 ); // WebGL port note: Changed sign in W component\n\t\t\tvOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4( 1.0, 0.0, 0.0, -1.0 ); // WebGL port note: Changed sign in W component\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\n\t\t\tSMAANeighborhoodBlendingVS( vUv );\n\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform sampler2D tDiffuse;\n\t\tuniform sampler2D tColor;\n\t\tuniform vec2 resolution;\n\n\t\tvarying vec2 vUv;\n\t\tvarying vec4 vOffset[ 2 ];\n\n\t\tvec4 SMAANeighborhoodBlendingPS( vec2 texcoord, vec4 offset[ 2 ], sampler2D colorTex, sampler2D blendTex ) {\n\t\t\t// Fetch the blending weights for current pixel:\n\t\t\tvec4 a;\n\t\t\ta.xz = texture2D( blendTex, texcoord ).xz;\n\t\t\ta.y = texture2D( blendTex, offset[ 1 ].zw ).g;\n\t\t\ta.w = texture2D( blendTex, offset[ 1 ].xy ).a;\n\n\t\t\t// Is there any blending weight with a value greater than 0.0?\n\t\t\tif ( dot(a, vec4( 1.0, 1.0, 1.0, 1.0 )) < 1e-5 ) {\n\t\t\t\treturn texture2D( colorTex, texcoord, 0.0 );\n\t\t\t} else {\n\t\t\t\t// Up to 4 lines can be crossing a pixel (one through each edge). We\n\t\t\t\t// favor blending by choosing the line with the maximum weight for each\n\t\t\t\t// direction:\n\t\t\t\tvec2 offset;\n\t\t\t\toffset.x = a.a > a.b ? a.a : -a.b; // left vs. right\n\t\t\t\toffset.y = a.g > a.r ? -a.g : a.r; // top vs. bottom // WebGL port note: Changed signs\n\n\t\t\t\t// Then we go in the direction that has the maximum weight:\n\t\t\t\tif ( abs( offset.x ) > abs( offset.y )) { // horizontal vs. vertical\n\t\t\t\t\toffset.y = 0.0;\n\t\t\t\t} else {\n\t\t\t\t\toffset.x = 0.0;\n\t\t\t\t}\n\n\t\t\t\t// Fetch the opposite color and lerp by hand:\n\t\t\t\tvec4 C = texture2D( colorTex, texcoord, 0.0 );\n\t\t\t\ttexcoord += sign( offset ) * resolution;\n\t\t\t\tvec4 Cop = texture2D( colorTex, texcoord, 0.0 );\n\t\t\t\tfloat s = abs( offset.x ) > abs( offset.y ) ? abs( offset.x ) : abs( offset.y );\n\n\t\t\t\t// WebGL port note: Added gamma correction\n\t\t\t\tC.xyz = pow(C.xyz, vec3(2.2));\n\t\t\t\tCop.xyz = pow(Cop.xyz, vec3(2.2));\n\t\t\t\tvec4 mixed = mix(C, Cop, s);\n\t\t\t\tmixed.xyz = pow(mixed.xyz, vec3(1.0 / 2.2));\n\n\t\t\t\treturn mixed;\n\t\t\t}\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = SMAANeighborhoodBlendingPS( vUv, vOffset, tColor, tDiffuse );\n\n\t\t}"};const Ae={name:"OutputShader",uniforms:{tDiffuse:{value:null},toneMappingExposure:{value:1}},vertexShader:"\n\t\tprecision highp float;\n\n\t\tuniform mat4 modelViewMatrix;\n\t\tuniform mat4 projectionMatrix;\n\n\t\tattribute vec3 position;\n\t\tattribute vec2 uv;\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\t\n\t\tprecision highp float;\n\n\t\tuniform sampler2D tDiffuse;\n\n\t\t#include <tonemapping_pars_fragment>\n\t\t#include <colorspace_pars_fragment>\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = texture2D( tDiffuse, vUv );\n\n\t\t\t// tone mapping\n\n\t\t\t#ifdef LINEAR_TONE_MAPPING\n\n\t\t\t\tgl_FragColor.rgb = LinearToneMapping( gl_FragColor.rgb );\n\n\t\t\t#elif defined( REINHARD_TONE_MAPPING )\n\n\t\t\t\tgl_FragColor.rgb = ReinhardToneMapping( gl_FragColor.rgb );\n\n\t\t\t#elif defined( CINEON_TONE_MAPPING )\n\n\t\t\t\tgl_FragColor.rgb = OptimizedCineonToneMapping( gl_FragColor.rgb );\n\n\t\t\t#elif defined( ACES_FILMIC_TONE_MAPPING )\n\n\t\t\t\tgl_FragColor.rgb = ACESFilmicToneMapping( gl_FragColor.rgb );\n\n\t\t\t#elif defined( AGX_TONE_MAPPING )\n\n\t\t\t\tgl_FragColor.rgb = AgXToneMapping( gl_FragColor.rgb );\n\n\t\t\t#endif\n\n\t\t\t// color space\n\n\t\t\t#ifdef SRGB_TRANSFER\n\n\t\t\t\tgl_FragColor = sRGBTransferOETF( gl_FragColor );\n\n\t\t\t#endif\n\n\t\t}"};const Te={name:"LuminosityHighPassShader",shaderID:"luminosityHighPass",uniforms:{tDiffuse:{value:null},luminosityThreshold:{value:1},smoothWidth:{value:1},defaultColor:{value:new t.Color(0)},defaultOpacity:{value:0}},vertexShader:"\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform sampler2D tDiffuse;\n\t\tuniform vec3 defaultColor;\n\t\tuniform float defaultOpacity;\n\t\tuniform float luminosityThreshold;\n\t\tuniform float smoothWidth;\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvec4 texel = texture2D( tDiffuse, vUv );\n\n\t\t\tvec3 luma = vec3( 0.299, 0.587, 0.114 );\n\n\t\t\tfloat v = dot( texel.xyz, luma );\n\n\t\t\tvec4 outputColor = vec4( defaultColor.rgb, defaultOpacity );\n\n\t\t\tfloat alpha = smoothstep( luminosityThreshold, luminosityThreshold + smoothWidth, v );\n\n\t\t\tgl_FragColor = mix( outputColor, texel, alpha );\n\n\t\t}"};class be extends le{constructor(e,r,n,s){super(),this.strength=void 0!==r?r:1,this.radius=n,this.threshold=s,this.resolution=void 0!==e?new t.Vector2(e.x,e.y):new t.Vector2(256,256),this.clearColor=new t.Color(0,0,0),this.renderTargetsHorizontal=[],this.renderTargetsVertical=[],this.nMips=5;let o=Math.round(this.resolution.x/2),i=Math.round(this.resolution.y/2);this.renderTargetBright=new t.WebGLRenderTarget(o,i,{type:t.HalfFloatType}),this.renderTargetBright.texture.name="UnrealBloomPass.bright",this.renderTargetBright.texture.generateMipmaps=!1;for(let e=0;e<this.nMips;e++){const r=new t.WebGLRenderTarget(o,i,{type:t.HalfFloatType});r.texture.name="UnrealBloomPass.h"+e,r.texture.generateMipmaps=!1,this.renderTargetsHorizontal.push(r);const n=new t.WebGLRenderTarget(o,i,{type:t.HalfFloatType});n.texture.name="UnrealBloomPass.v"+e,n.texture.generateMipmaps=!1,this.renderTargetsVertical.push(n),o=Math.round(o/2),i=Math.round(i/2)}const a=Te;this.highPassUniforms=t.UniformsUtils.clone(a.uniforms),this.highPassUniforms.luminosityThreshold.value=s,this.highPassUniforms.smoothWidth.value=.01,this.materialHighPassFilter=new t.ShaderMaterial({uniforms:this.highPassUniforms,vertexShader:a.vertexShader,fragmentShader:a.fragmentShader}),this.separableBlurMaterials=[];const l=[3,5,7,9,11];o=Math.round(this.resolution.x/2),i=Math.round(this.resolution.y/2);for(let e=0;e<this.nMips;e++)this.separableBlurMaterials.push(this.getSeperableBlurMaterial(l[e])),this.separableBlurMaterials[e].uniforms.invSize.value=new t.Vector2(1/o,1/i),o=Math.round(o/2),i=Math.round(i/2);this.compositeMaterial=this.getCompositeMaterial(this.nMips),this.compositeMaterial.uniforms.blurTexture1.value=this.renderTargetsVertical[0].texture,this.compositeMaterial.uniforms.blurTexture2.value=this.renderTargetsVertical[1].texture,this.compositeMaterial.uniforms.blurTexture3.value=this.renderTargetsVertical[2].texture,this.compositeMaterial.uniforms.blurTexture4.value=this.renderTargetsVertical[3].texture,this.compositeMaterial.uniforms.blurTexture5.value=this.renderTargetsVertical[4].texture,this.compositeMaterial.uniforms.bloomStrength.value=r,this.compositeMaterial.uniforms.bloomRadius.value=.1;this.compositeMaterial.uniforms.bloomFactors.value=[1,.8,.6,.4,.2],this.bloomTintColors=[new t.Vector3(1,1,1),new t.Vector3(1,1,1),new t.Vector3(1,1,1),new t.Vector3(1,1,1),new t.Vector3(1,1,1)],this.compositeMaterial.uniforms.bloomTintColors.value=this.bloomTintColors;const c=ae;this.copyUniforms=t.UniformsUtils.clone(c.uniforms),this.blendMaterial=new t.ShaderMaterial({uniforms:this.copyUniforms,vertexShader:c.vertexShader,fragmentShader:c.fragmentShader,blending:t.AdditiveBlending,depthTest:!1,depthWrite:!1,transparent:!0}),this.enabled=!0,this.needsSwap=!1,this._oldClearColor=new t.Color,this.oldClearAlpha=1,this.basic=new t.MeshBasicMaterial,this.fsQuad=new de(null)}dispose(){for(let e=0;e<this.renderTargetsHorizontal.length;e++)this.renderTargetsHorizontal[e].dispose();for(let e=0;e<this.renderTargetsVertical.length;e++)this.renderTargetsVertical[e].dispose();this.renderTargetBright.dispose();for(let e=0;e<this.separableBlurMaterials.length;e++)this.separableBlurMaterials[e].dispose();this.compositeMaterial.dispose(),this.blendMaterial.dispose(),this.basic.dispose(),this.fsQuad.dispose()}setSize(e,r){let n=Math.round(e/2),s=Math.round(r/2);this.renderTargetBright.setSize(n,s);for(let e=0;e<this.nMips;e++)this.renderTargetsHorizontal[e].setSize(n,s),this.renderTargetsVertical[e].setSize(n,s),this.separableBlurMaterials[e].uniforms.invSize.value=new t.Vector2(1/n,1/s),n=Math.round(n/2),s=Math.round(s/2)}render(e,t,r,n,s){e.getClearColor(this._oldClearColor),this.oldClearAlpha=e.getClearAlpha();const o=e.autoClear;e.autoClear=!1,e.setClearColor(this.clearColor,0),s&&e.state.buffers.stencil.setTest(!1),this.renderToScreen&&(this.fsQuad.material=this.basic,this.basic.map=r.texture,e.setRenderTarget(null),e.clear(),this.fsQuad.render(e)),this.highPassUniforms.tDiffuse.value=r.texture,this.highPassUniforms.luminosityThreshold.value=this.threshold,this.fsQuad.material=this.materialHighPassFilter,e.setRenderTarget(this.renderTargetBright),e.clear(),this.fsQuad.render(e);let i=this.renderTargetBright;for(let t=0;t<this.nMips;t++)this.fsQuad.material=this.separableBlurMaterials[t],this.separableBlurMaterials[t].uniforms.colorTexture.value=i.texture,this.separableBlurMaterials[t].uniforms.direction.value=be.BlurDirectionX,e.setRenderTarget(this.renderTargetsHorizontal[t]),e.clear(),this.fsQuad.render(e),this.separableBlurMaterials[t].uniforms.colorTexture.value=this.renderTargetsHorizontal[t].texture,this.separableBlurMaterials[t].uniforms.direction.value=be.BlurDirectionY,e.setRenderTarget(this.renderTargetsVertical[t]),e.clear(),this.fsQuad.render(e),i=this.renderTargetsVertical[t];this.fsQuad.material=this.compositeMaterial,this.compositeMaterial.uniforms.bloomStrength.value=this.strength,this.compositeMaterial.uniforms.bloomRadius.value=this.radius,this.compositeMaterial.uniforms.bloomTintColors.value=this.bloomTintColors,e.setRenderTarget(this.renderTargetsHorizontal[0]),e.clear(),this.fsQuad.render(e),this.fsQuad.material=this.blendMaterial,this.copyUniforms.tDiffuse.value=this.renderTargetsHorizontal[0].texture,s&&e.state.buffers.stencil.setTest(!0),this.renderToScreen?(e.setRenderTarget(null),this.fsQuad.render(e)):(e.setRenderTarget(r),this.fsQuad.render(e)),e.setClearColor(this._oldClearColor,this.oldClearAlpha),e.autoClear=o}getSeperableBlurMaterial(e){const r=[];for(let t=0;t<e;t++)r.push(.39894*Math.exp(-.5*t*t/(e*e))/e);return new t.ShaderMaterial({defines:{KERNEL_RADIUS:e},uniforms:{colorTexture:{value:null},invSize:{value:new t.Vector2(.5,.5)},direction:{value:new t.Vector2(.5,.5)},gaussianCoefficients:{value:r}},vertexShader:"varying vec2 vUv;\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\t\t\t\t}",fragmentShader:"#include <common>\n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tuniform sampler2D colorTexture;\n\t\t\t\tuniform vec2 invSize;\n\t\t\t\tuniform vec2 direction;\n\t\t\t\tuniform float gaussianCoefficients[KERNEL_RADIUS];\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tfloat weightSum = gaussianCoefficients[0];\n\t\t\t\t\tvec3 diffuseSum = texture2D( colorTexture, vUv ).rgb * weightSum;\n\t\t\t\t\tfor( int i = 1; i < KERNEL_RADIUS; i ++ ) {\n\t\t\t\t\t\tfloat x = float(i);\n\t\t\t\t\t\tfloat w = gaussianCoefficients[i];\n\t\t\t\t\t\tvec2 uvOffset = direction * invSize * x;\n\t\t\t\t\t\tvec3 sample1 = texture2D( colorTexture, vUv + uvOffset ).rgb;\n\t\t\t\t\t\tvec3 sample2 = texture2D( colorTexture, vUv - uvOffset ).rgb;\n\t\t\t\t\t\tdiffuseSum += (sample1 + sample2) * w;\n\t\t\t\t\t\tweightSum += 2.0 * w;\n\t\t\t\t\t}\n\t\t\t\t\tgl_FragColor = vec4(diffuseSum/weightSum, 1.0);\n\t\t\t\t}"})}getCompositeMaterial(e){return new t.ShaderMaterial({defines:{NUM_MIPS:e},uniforms:{blurTexture1:{value:null},blurTexture2:{value:null},blurTexture3:{value:null},blurTexture4:{value:null},blurTexture5:{value:null},bloomStrength:{value:1},bloomFactors:{value:null},bloomTintColors:{value:null},bloomRadius:{value:0}},vertexShader:"varying vec2 vUv;\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\t\t\t\t}",fragmentShader:"varying vec2 vUv;\n\t\t\t\tuniform sampler2D blurTexture1;\n\t\t\t\tuniform sampler2D blurTexture2;\n\t\t\t\tuniform sampler2D blurTexture3;\n\t\t\t\tuniform sampler2D blurTexture4;\n\t\t\t\tuniform sampler2D blurTexture5;\n\t\t\t\tuniform float bloomStrength;\n\t\t\t\tuniform float bloomRadius;\n\t\t\t\tuniform float bloomFactors[NUM_MIPS];\n\t\t\t\tuniform vec3 bloomTintColors[NUM_MIPS];\n\n\t\t\t\tfloat lerpBloomFactor(const in float factor) {\n\t\t\t\t\tfloat mirrorFactor = 1.2 - factor;\n\t\t\t\t\treturn mix(factor, mirrorFactor, bloomRadius);\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tgl_FragColor = bloomStrength * ( lerpBloomFactor(bloomFactors[0]) * vec4(bloomTintColors[0], 1.0) * texture2D(blurTexture1, vUv) +\n\t\t\t\t\t\tlerpBloomFactor(bloomFactors[1]) * vec4(bloomTintColors[1], 1.0) * texture2D(blurTexture2, vUv) +\n\t\t\t\t\t\tlerpBloomFactor(bloomFactors[2]) * vec4(bloomTintColors[2], 1.0) * texture2D(blurTexture3, vUv) +\n\t\t\t\t\t\tlerpBloomFactor(bloomFactors[3]) * vec4(bloomTintColors[3], 1.0) * texture2D(blurTexture4, vUv) +\n\t\t\t\t\t\tlerpBloomFactor(bloomFactors[4]) * vec4(bloomTintColors[4], 1.0) * texture2D(blurTexture5, vUv) );\n\t\t\t\t}"})}}be.BlurDirectionX=new t.Vector2(1,0),be.BlurDirectionY=new t.Vector2(0,1);const we={name:"BrightnessContrastShader",uniforms:{tDiffuse:{value:null},brightness:{value:0},contrast:{value:0}},vertexShader:"\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform sampler2D tDiffuse;\n\t\tuniform float brightness;\n\t\tuniform float contrast;\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = texture2D( tDiffuse, vUv );\n\n\t\t\tgl_FragColor.rgb += brightness;\n\n\t\t\tif (contrast > 0.0) {\n\t\t\t\tgl_FragColor.rgb = (gl_FragColor.rgb - 0.5) / (1.0 - contrast) + 0.5;\n\t\t\t} else {\n\t\t\t\tgl_FragColor.rgb = (gl_FragColor.rgb - 0.5) * (1.0 + contrast) + 0.5;\n\t\t\t}\n\n\t\t}"},Me={name:"HueSaturationShader",uniforms:{tDiffuse:{value:null},hue:{value:0},saturation:{value:0}},vertexShader:"\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform sampler2D tDiffuse;\n\t\tuniform float hue;\n\t\tuniform float saturation;\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = texture2D( tDiffuse, vUv );\n\n\t\t\t// hue\n\t\t\tfloat angle = hue * 3.14159265;\n\t\t\tfloat s = sin(angle), c = cos(angle);\n\t\t\tvec3 weights = (vec3(2.0 * c, -sqrt(3.0) * s - c, sqrt(3.0) * s - c) + 1.0) / 3.0;\n\t\t\tfloat len = length(gl_FragColor.rgb);\n\t\t\tgl_FragColor.rgb = vec3(\n\t\t\t\tdot(gl_FragColor.rgb, weights.xyz),\n\t\t\t\tdot(gl_FragColor.rgb, weights.zxy),\n\t\t\t\tdot(gl_FragColor.rgb, weights.yzx)\n\t\t\t);\n\n\t\t\t// saturation\n\t\t\tfloat average = (gl_FragColor.r + gl_FragColor.g + gl_FragColor.b) / 3.0;\n\t\t\tif (saturation > 0.0) {\n\t\t\t\tgl_FragColor.rgb += (average - gl_FragColor.rgb) * (1.0 - 1.0 / (1.001 - saturation));\n\t\t\t} else {\n\t\t\t\tgl_FragColor.rgb += (average - gl_FragColor.rgb) * (-saturation);\n\t\t\t}\n\n\t\t}"},Se={name:"ExposureShader",uniforms:{tDiffuse:{value:null},exposure:{value:1}},vertexShader:"\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform float exposure;\n\n\t\tuniform sampler2D tDiffuse;\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = texture2D( tDiffuse, vUv );\n\t\t\tgl_FragColor.rgb *= exposure;\n\n\t\t}"};e.BrightnessContrastShader=we,e.DRACOLoader=ee,e.EffectComposer=class{constructor(e,r){if(this.renderer=e,this._pixelRatio=e.getPixelRatio(),void 0===r){const n=e.getSize(new t.Vector2);this._width=n.width,this._height=n.height,(r=new t.WebGLRenderTarget(this._width*this._pixelRatio,this._height*this._pixelRatio,{type:t.HalfFloatType})).texture.name="EffectComposer.rt1"}else this._width=r.width,this._height=r.height;this.renderTarget1=r,this.renderTarget2=r.clone(),this.renderTarget2.texture.name="EffectComposer.rt2",this.writeBuffer=this.renderTarget1,this.readBuffer=this.renderTarget2,this.renderToScreen=!0,this.passes=[],this.copyPass=new fe(ae),this.copyPass.material.blending=t.NoBlending,this.clock=new t.Clock}swapBuffers(){const e=this.readBuffer;this.readBuffer=this.writeBuffer,this.writeBuffer=e}addPass(e){this.passes.push(e),e.setSize(this._width*this._pixelRatio,this._height*this._pixelRatio)}insertPass(e,t){this.passes.splice(t,0,e),e.setSize(this._width*this._pixelRatio,this._height*this._pixelRatio)}removePass(e){const t=this.passes.indexOf(e);-1!==t&&this.passes.splice(t,1)}isLastEnabledPass(e){for(let t=e+1;t<this.passes.length;t++)if(this.passes[t].enabled)return!1;return!0}render(e){void 0===e&&(e=this.clock.getDelta());const t=this.renderer.getRenderTarget();let r=!1;for(let t=0,n=this.passes.length;t<n;t++){const n=this.passes[t];if(!1!==n.enabled){if(n.renderToScreen=this.renderToScreen&&this.isLastEnabledPass(t),n.render(this.renderer,this.writeBuffer,this.readBuffer,e,r),n.needsSwap){if(r){const t=this.renderer.getContext(),r=this.renderer.state.buffers.stencil;r.setFunc(t.NOTEQUAL,1,4294967295),this.copyPass.render(this.renderer,this.writeBuffer,this.readBuffer,e),r.setFunc(t.EQUAL,1,4294967295)}this.swapBuffers()}void 0!==me&&(n instanceof me?r=!0:n instanceof pe&&(r=!1))}}this.renderer.setRenderTarget(t)}reset(e){if(void 0===e){const r=this.renderer.getSize(new t.Vector2);this._pixelRatio=this.renderer.getPixelRatio(),this._width=r.width,this._height=r.height,(e=this.renderTarget1.clone()).setSize(this._width*this._pixelRatio,this._height*this._pixelRatio)}this.renderTarget1.dispose(),this.renderTarget2.dispose(),this.renderTarget1=e,this.renderTarget2=e.clone(),this.writeBuffer=this.renderTarget1,this.readBuffer=this.renderTarget2}setSize(e,t){this._width=e,this._height=t;const r=this._width*this._pixelRatio,n=this._height*this._pixelRatio;this.renderTarget1.setSize(r,n),this.renderTarget2.setSize(r,n);for(let e=0;e<this.passes.length;e++)this.passes[e].setSize(r,n)}setPixelRatio(e){this._pixelRatio=e,this.setSize(this._width,this._height)}dispose(){this.renderTarget1.dispose(),this.renderTarget2.dispose(),this.copyPass.dispose()}},e.ExposureShader=Se,e.GLTFLoader=n,e.HueSaturationShader=Me,e.OutputPass=class extends le{constructor(){super();const e=Ae;this.uniforms=t.UniformsUtils.clone(e.uniforms),this.material=new t.RawShaderMaterial({name:e.name,uniforms:this.uniforms,vertexShader:e.vertexShader,fragmentShader:e.fragmentShader}),this.fsQuad=new de(this.material),this._outputColorSpace=null,this._toneMapping=null}render(e,r,n){this.uniforms.tDiffuse.value=n.texture,this.uniforms.toneMappingExposure.value=e.toneMappingExposure,this._outputColorSpace===e.outputColorSpace&&this._toneMapping===e.toneMapping||(this._outputColorSpace=e.outputColorSpace,this._toneMapping=e.toneMapping,this.material.defines={},t.ColorManagement.getTransfer(this._outputColorSpace)===t.SRGBTransfer&&(this.material.defines.SRGB_TRANSFER=""),this._toneMapping===t.LinearToneMapping?this.material.defines.LINEAR_TONE_MAPPING="":this._toneMapping===t.ReinhardToneMapping?this.material.defines.REINHARD_TONE_MAPPING="":this._toneMapping===t.CineonToneMapping?this.material.defines.CINEON_TONE_MAPPING="":this._toneMapping===t.ACESFilmicToneMapping?this.material.defines.ACES_FILMIC_TONE_MAPPING="":this._toneMapping===t.AgXToneMapping&&(this.material.defines.AGX_TONE_MAPPING=""),this.material.needsUpdate=!0),!0===this.renderToScreen?(e.setRenderTarget(null),this.fsQuad.render(e)):(e.setRenderTarget(r),this.clear&&e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil),this.fsQuad.render(e))}dispose(){this.material.dispose(),this.fsQuad.dispose()}},e.RenderPass=class extends le{constructor(e,r,n=null,s=null,o=null){super(),this.scene=e,this.camera=r,this.overrideMaterial=n,this.clearColor=s,this.clearAlpha=o,this.clear=!0,this.clearDepth=!1,this.needsSwap=!1,this._oldClearColor=new t.Color}render(e,t,r){const n=e.autoClear;let s,o;e.autoClear=!1,null!==this.overrideMaterial&&(o=this.scene.overrideMaterial,this.scene.overrideMaterial=this.overrideMaterial),null!==this.clearColor&&(e.getClearColor(this._oldClearColor),e.setClearColor(this.clearColor)),null!==this.clearAlpha&&(s=e.getClearAlpha(),e.setClearAlpha(this.clearAlpha)),1==this.clearDepth&&e.clearDepth(),e.setRenderTarget(this.renderToScreen?null:r),!0===this.clear&&e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil),e.render(this.scene,this.camera),null!==this.clearColor&&e.setClearColor(this._oldClearColor),null!==this.clearAlpha&&e.setClearAlpha(s),null!==this.overrideMaterial&&(this.scene.overrideMaterial=o),e.autoClear=n}},e.SMAAPass=class extends le{constructor(e,r){super(),this.edgesRT=new t.WebGLRenderTarget(e,r,{depthBuffer:!1,type:t.HalfFloatType}),this.edgesRT.texture.name="SMAAPass.edges",this.weightsRT=new t.WebGLRenderTarget(e,r,{depthBuffer:!1,type:t.HalfFloatType}),this.weightsRT.texture.name="SMAAPass.weights";const n=this,s=new Image;s.src=this.getAreaTexture(),s.onload=function(){n.areaTexture.needsUpdate=!0},this.areaTexture=new t.Texture,this.areaTexture.name="SMAAPass.area",this.areaTexture.image=s,this.areaTexture.minFilter=t.LinearFilter,this.areaTexture.generateMipmaps=!1,this.areaTexture.flipY=!1;const o=new Image;o.src=this.getSearchTexture(),o.onload=function(){n.searchTexture.needsUpdate=!0},this.searchTexture=new t.Texture,this.searchTexture.name="SMAAPass.search",this.searchTexture.image=o,this.searchTexture.magFilter=t.NearestFilter,this.searchTexture.minFilter=t.NearestFilter,this.searchTexture.generateMipmaps=!1,this.searchTexture.flipY=!1,this.uniformsEdges=t.UniformsUtils.clone(ge.uniforms),this.uniformsEdges.resolution.value.set(1/e,1/r),this.materialEdges=new t.ShaderMaterial({defines:Object.assign({},ge.defines),uniforms:this.uniformsEdges,vertexShader:ge.vertexShader,fragmentShader:ge.fragmentShader}),this.uniformsWeights=t.UniformsUtils.clone(xe.uniforms),this.uniformsWeights.resolution.value.set(1/e,1/r),this.uniformsWeights.tDiffuse.value=this.edgesRT.texture,this.uniformsWeights.tArea.value=this.areaTexture,this.uniformsWeights.tSearch.value=this.searchTexture,this.materialWeights=new t.ShaderMaterial({defines:Object.assign({},xe.defines),uniforms:this.uniformsWeights,vertexShader:xe.vertexShader,fragmentShader:xe.fragmentShader}),this.uniformsBlend=t.UniformsUtils.clone(ve.uniforms),this.uniformsBlend.resolution.value.set(1/e,1/r),this.uniformsBlend.tDiffuse.value=this.weightsRT.texture,this.materialBlend=new t.ShaderMaterial({uniforms:this.uniformsBlend,vertexShader:ve.vertexShader,fragmentShader:ve.fragmentShader}),this.fsQuad=new de(null)}render(e,t,r){this.uniformsEdges.tDiffuse.value=r.texture,this.fsQuad.material=this.materialEdges,e.setRenderTarget(this.edgesRT),this.clear&&e.clear(),this.fsQuad.render(e),this.fsQuad.material=this.materialWeights,e.setRenderTarget(this.weightsRT),this.clear&&e.clear(),this.fsQuad.render(e),this.uniformsBlend.tColor.value=r.texture,this.fsQuad.material=this.materialBlend,this.renderToScreen?(e.setRenderTarget(null),this.fsQuad.render(e)):(e.setRenderTarget(t),this.clear&&e.clear(),this.fsQuad.render(e))}setSize(e,t){this.edgesRT.setSize(e,t),this.weightsRT.setSize(e,t),this.materialEdges.uniforms.resolution.value.set(1/e,1/t),this.materialWeights.uniforms.resolution.value.set(1/e,1/t),this.materialBlend.uniforms.resolution.value.set(1/e,1/t)}getAreaTexture(){return"data:image/png;base64,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"}getSearchTexture(){return"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAAhCAAAAABIXyLAAAAAOElEQVRIx2NgGAWjYBSMglEwEICREYRgFBZBqDCSLA2MGPUIVQETE9iNUAqLR5gIeoQKRgwXjwAAGn4AtaFeYLEAAAAASUVORK5CYII="}dispose(){this.edgesRT.dispose(),this.weightsRT.dispose(),this.areaTexture.dispose(),this.searchTexture.dispose(),this.materialEdges.dispose(),this.materialWeights.dispose(),this.materialBlend.dispose(),this.fsQuad.dispose()}},e.ShaderPass=fe,e.SkeletonUtils=ie,e.UnrealBloomPass=be,Object.defineProperty(e,"__esModule",{value:!0})}));
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("three")):"function"==typeof define&&define.amd?define(["exports","three"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).THREE_ADDONS={},e.THREE)}(this,(function(e,t){"use strict";function r(e,r){if(r===t.TrianglesDrawMode)return console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles."),e;if(r===t.TriangleFanDrawMode||r===t.TriangleStripDrawMode){let n=e.getIndex();if(null===n){const t=[],r=e.getAttribute("position");if(void 0===r)return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible."),e;for(let e=0;e<r.count;e++)t.push(e);e.setIndex(t),n=e.getIndex()}const s=n.count-2,i=[];if(r===t.TriangleFanDrawMode)for(let e=1;e<=s;e++)i.push(n.getX(0)),i.push(n.getX(e)),i.push(n.getX(e+1));else for(let e=0;e<s;e++)e%2==0?(i.push(n.getX(e)),i.push(n.getX(e+1)),i.push(n.getX(e+2))):(i.push(n.getX(e+2)),i.push(n.getX(e+1)),i.push(n.getX(e)));i.length/3!==s&&console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.");const o=e.clone();return o.setIndex(i),o.clearGroups(),o}return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:",r),e}class n extends t.Loader{constructor(e){super(e),this.dracoLoader=null,this.ktx2Loader=null,this.meshoptDecoder=null,this.pluginCallbacks=[],this.register((function(e){return new h(e)})),this.register((function(e){return new v(e)})),this.register((function(e){return new T(e)})),this.register((function(e){return new A(e)})),this.register((function(e){return new u(e)})),this.register((function(e){return new d(e)})),this.register((function(e){return new p(e)})),this.register((function(e){return new f(e)})),this.register((function(e){return new l(e)})),this.register((function(e){return new m(e)})),this.register((function(e){return new c(e)})),this.register((function(e){return new x(e)})),this.register((function(e){return new g(e)})),this.register((function(e){return new o(e)})),this.register((function(e){return new M(e)})),this.register((function(e){return new w(e)}))}load(e,r,n,s){const i=this;let o;if(""!==this.resourcePath)o=this.resourcePath;else if(""!==this.path){const r=t.LoaderUtils.extractUrlBase(e);o=t.LoaderUtils.resolveURL(r,this.path)}else o=t.LoaderUtils.extractUrlBase(e);this.manager.itemStart(e);const a=function(t){s?s(t):console.error(t),i.manager.itemError(e),i.manager.itemEnd(e)},l=new t.FileLoader(this.manager);l.setPath(this.path),l.setResponseType("arraybuffer"),l.setRequestHeader(this.requestHeader),l.setWithCredentials(this.withCredentials),l.load(e,(function(t){try{i.parse(t,o,(function(t){r(t),i.manager.itemEnd(e)}),a)}catch(e){a(e)}}),n,a)}setDRACOLoader(e){return this.dracoLoader=e,this}setDDSLoader(){throw new Error('THREE.GLTFLoader: "MSFT_texture_dds" no longer supported. Please update to "KHR_texture_basisu".')}setKTX2Loader(e){return this.ktx2Loader=e,this}setMeshoptDecoder(e){return this.meshoptDecoder=e,this}register(e){return-1===this.pluginCallbacks.indexOf(e)&&this.pluginCallbacks.push(e),this}unregister(e){return-1!==this.pluginCallbacks.indexOf(e)&&this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(e),1),this}parse(e,t,r,n){let s;const o={},l={},h=new TextDecoder;if("string"==typeof e)s=JSON.parse(e);else if(e instanceof ArrayBuffer){if(h.decode(new Uint8Array(e,0,4))===b){try{o[i.KHR_BINARY_GLTF]=new C(e)}catch(e){return void(n&&n(e))}s=JSON.parse(o[i.KHR_BINARY_GLTF].content)}else s=JSON.parse(h.decode(e))}else s=e;if(void 0===s.asset||s.asset.version[0]<2)return void(n&&n(new Error("THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.")));const c=new _(s,{path:t||this.resourcePath||"",crossOrigin:this.crossOrigin,requestHeader:this.requestHeader,manager:this.manager,ktx2Loader:this.ktx2Loader,meshoptDecoder:this.meshoptDecoder});c.fileLoader.setRequestHeader(this.requestHeader);for(let e=0;e<this.pluginCallbacks.length;e++){const t=this.pluginCallbacks[e](c);t.name||console.error("THREE.GLTFLoader: Invalid plugin found: missing name"),l[t.name]=t,o[t.name]=!0}if(s.extensionsUsed)for(let e=0;e<s.extensionsUsed.length;++e){const t=s.extensionsUsed[e],r=s.extensionsRequired||[];switch(t){case i.KHR_MATERIALS_UNLIT:o[t]=new a;break;case i.KHR_DRACO_MESH_COMPRESSION:o[t]=new E(s,this.dracoLoader);break;case i.KHR_TEXTURE_TRANSFORM:o[t]=new R;break;case i.KHR_MESH_QUANTIZATION:o[t]=new L;break;default:r.indexOf(t)>=0&&void 0===l[t]&&console.warn('THREE.GLTFLoader: Unknown extension "'+t+'".')}}c.setExtensions(o),c.setPlugins(l),c.parse(r,n)}parseAsync(e,t){const r=this;return new Promise((function(n,s){r.parse(e,t,n,s)}))}}function s(){let e={};return{get:function(t){return e[t]},add:function(t,r){e[t]=r},remove:function(t){delete e[t]},removeAll:function(){e={}}}}const i={KHR_BINARY_GLTF:"KHR_binary_glTF",KHR_DRACO_MESH_COMPRESSION:"KHR_draco_mesh_compression",KHR_LIGHTS_PUNCTUAL:"KHR_lights_punctual",KHR_MATERIALS_CLEARCOAT:"KHR_materials_clearcoat",KHR_MATERIALS_IOR:"KHR_materials_ior",KHR_MATERIALS_SHEEN:"KHR_materials_sheen",KHR_MATERIALS_SPECULAR:"KHR_materials_specular",KHR_MATERIALS_TRANSMISSION:"KHR_materials_transmission",KHR_MATERIALS_IRIDESCENCE:"KHR_materials_iridescence",KHR_MATERIALS_ANISOTROPY:"KHR_materials_anisotropy",KHR_MATERIALS_UNLIT:"KHR_materials_unlit",KHR_MATERIALS_VOLUME:"KHR_materials_volume",KHR_TEXTURE_BASISU:"KHR_texture_basisu",KHR_TEXTURE_TRANSFORM:"KHR_texture_transform",KHR_MESH_QUANTIZATION:"KHR_mesh_quantization",KHR_MATERIALS_EMISSIVE_STRENGTH:"KHR_materials_emissive_strength",EXT_MATERIALS_BUMP:"EXT_materials_bump",EXT_TEXTURE_WEBP:"EXT_texture_webp",EXT_TEXTURE_AVIF:"EXT_texture_avif",EXT_MESHOPT_COMPRESSION:"EXT_meshopt_compression",EXT_MESH_GPU_INSTANCING:"EXT_mesh_gpu_instancing"};class o{constructor(e){this.parser=e,this.name=i.KHR_LIGHTS_PUNCTUAL,this.cache={refs:{},uses:{}}}_markDefs(){const e=this.parser,t=this.parser.json.nodes||[];for(let r=0,n=t.length;r<n;r++){const n=t[r];n.extensions&&n.extensions[this.name]&&void 0!==n.extensions[this.name].light&&e._addNodeRef(this.cache,n.extensions[this.name].light)}}_loadLight(e){const r=this.parser,n="light:"+e;let s=r.cache.get(n);if(s)return s;const i=r.json,o=((i.extensions&&i.extensions[this.name]||{}).lights||[])[e];let a;const l=new t.Color(16777215);void 0!==o.color&&l.setRGB(o.color[0],o.color[1],o.color[2],t.LinearSRGBColorSpace);const h=void 0!==o.range?o.range:0;switch(o.type){case"directional":a=new t.DirectionalLight(l),a.target.position.set(0,0,-1),a.add(a.target);break;case"point":a=new t.PointLight(l),a.distance=h;break;case"spot":a=new t.SpotLight(l),a.distance=h,o.spot=o.spot||{},o.spot.innerConeAngle=void 0!==o.spot.innerConeAngle?o.spot.innerConeAngle:0,o.spot.outerConeAngle=void 0!==o.spot.outerConeAngle?o.spot.outerConeAngle:Math.PI/4,a.angle=o.spot.outerConeAngle,a.penumbra=1-o.spot.innerConeAngle/o.spot.outerConeAngle,a.target.position.set(0,0,-1),a.add(a.target);break;default:throw new Error("THREE.GLTFLoader: Unexpected light type: "+o.type)}return a.position.set(0,0,0),a.decay=2,V(a,o),void 0!==o.intensity&&(a.intensity=o.intensity),a.name=r.createUniqueName(o.name||"light_"+e),s=Promise.resolve(a),r.cache.add(n,s),s}getDependency(e,t){if("light"===e)return this._loadLight(t)}createNodeAttachment(e){const t=this,r=this.parser,n=r.json.nodes[e],s=(n.extensions&&n.extensions[this.name]||{}).light;return void 0===s?null:this._loadLight(s).then((function(e){return r._getNodeRef(t.cache,s,e)}))}}class a{constructor(){this.name=i.KHR_MATERIALS_UNLIT}getMaterialType(){return t.MeshBasicMaterial}extendParams(e,r,n){const s=[];e.color=new t.Color(1,1,1),e.opacity=1;const i=r.pbrMetallicRoughness;if(i){if(Array.isArray(i.baseColorFactor)){const r=i.baseColorFactor;e.color.setRGB(r[0],r[1],r[2],t.LinearSRGBColorSpace),e.opacity=r[3]}void 0!==i.baseColorTexture&&s.push(n.assignTexture(e,"map",i.baseColorTexture,t.SRGBColorSpace))}return Promise.all(s)}}class l{constructor(e){this.parser=e,this.name=i.KHR_MATERIALS_EMISSIVE_STRENGTH}extendMaterialParams(e,t){const r=this.parser.json.materials[e];if(!r.extensions||!r.extensions[this.name])return Promise.resolve();const n=r.extensions[this.name].emissiveStrength;return void 0!==n&&(t.emissiveIntensity=n),Promise.resolve()}}class h{constructor(e){this.parser=e,this.name=i.KHR_MATERIALS_CLEARCOAT}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,r){const n=this.parser,s=n.json.materials[e];if(!s.extensions||!s.extensions[this.name])return Promise.resolve();const i=[],o=s.extensions[this.name];if(void 0!==o.clearcoatFactor&&(r.clearcoat=o.clearcoatFactor),void 0!==o.clearcoatTexture&&i.push(n.assignTexture(r,"clearcoatMap",o.clearcoatTexture)),void 0!==o.clearcoatRoughnessFactor&&(r.clearcoatRoughness=o.clearcoatRoughnessFactor),void 0!==o.clearcoatRoughnessTexture&&i.push(n.assignTexture(r,"clearcoatRoughnessMap",o.clearcoatRoughnessTexture)),void 0!==o.clearcoatNormalTexture&&(i.push(n.assignTexture(r,"clearcoatNormalMap",o.clearcoatNormalTexture)),void 0!==o.clearcoatNormalTexture.scale)){const e=o.clearcoatNormalTexture.scale;r.clearcoatNormalScale=new t.Vector2(e,e)}return Promise.all(i)}}class c{constructor(e){this.parser=e,this.name=i.KHR_MATERIALS_IRIDESCENCE}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,t){const r=this.parser,n=r.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const s=[],i=n.extensions[this.name];return void 0!==i.iridescenceFactor&&(t.iridescence=i.iridescenceFactor),void 0!==i.iridescenceTexture&&s.push(r.assignTexture(t,"iridescenceMap",i.iridescenceTexture)),void 0!==i.iridescenceIor&&(t.iridescenceIOR=i.iridescenceIor),void 0===t.iridescenceThicknessRange&&(t.iridescenceThicknessRange=[100,400]),void 0!==i.iridescenceThicknessMinimum&&(t.iridescenceThicknessRange[0]=i.iridescenceThicknessMinimum),void 0!==i.iridescenceThicknessMaximum&&(t.iridescenceThicknessRange[1]=i.iridescenceThicknessMaximum),void 0!==i.iridescenceThicknessTexture&&s.push(r.assignTexture(t,"iridescenceThicknessMap",i.iridescenceThicknessTexture)),Promise.all(s)}}class u{constructor(e){this.parser=e,this.name=i.KHR_MATERIALS_SHEEN}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,r){const n=this.parser,s=n.json.materials[e];if(!s.extensions||!s.extensions[this.name])return Promise.resolve();const i=[];r.sheenColor=new t.Color(0,0,0),r.sheenRoughness=0,r.sheen=1;const o=s.extensions[this.name];if(void 0!==o.sheenColorFactor){const e=o.sheenColorFactor;r.sheenColor.setRGB(e[0],e[1],e[2],t.LinearSRGBColorSpace)}return void 0!==o.sheenRoughnessFactor&&(r.sheenRoughness=o.sheenRoughnessFactor),void 0!==o.sheenColorTexture&&i.push(n.assignTexture(r,"sheenColorMap",o.sheenColorTexture,t.SRGBColorSpace)),void 0!==o.sheenRoughnessTexture&&i.push(n.assignTexture(r,"sheenRoughnessMap",o.sheenRoughnessTexture)),Promise.all(i)}}class d{constructor(e){this.parser=e,this.name=i.KHR_MATERIALS_TRANSMISSION}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,t){const r=this.parser,n=r.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const s=[],i=n.extensions[this.name];return void 0!==i.transmissionFactor&&(t.transmission=i.transmissionFactor),void 0!==i.transmissionTexture&&s.push(r.assignTexture(t,"transmissionMap",i.transmissionTexture)),Promise.all(s)}}class p{constructor(e){this.parser=e,this.name=i.KHR_MATERIALS_VOLUME}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,r){const n=this.parser,s=n.json.materials[e];if(!s.extensions||!s.extensions[this.name])return Promise.resolve();const i=[],o=s.extensions[this.name];r.thickness=void 0!==o.thicknessFactor?o.thicknessFactor:0,void 0!==o.thicknessTexture&&i.push(n.assignTexture(r,"thicknessMap",o.thicknessTexture)),r.attenuationDistance=o.attenuationDistance||1/0;const a=o.attenuationColor||[1,1,1];return r.attenuationColor=(new t.Color).setRGB(a[0],a[1],a[2],t.LinearSRGBColorSpace),Promise.all(i)}}class f{constructor(e){this.parser=e,this.name=i.KHR_MATERIALS_IOR}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,t){const r=this.parser.json.materials[e];if(!r.extensions||!r.extensions[this.name])return Promise.resolve();const n=r.extensions[this.name];return t.ior=void 0!==n.ior?n.ior:1.5,Promise.resolve()}}class m{constructor(e){this.parser=e,this.name=i.KHR_MATERIALS_SPECULAR}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,r){const n=this.parser,s=n.json.materials[e];if(!s.extensions||!s.extensions[this.name])return Promise.resolve();const i=[],o=s.extensions[this.name];r.specularIntensity=void 0!==o.specularFactor?o.specularFactor:1,void 0!==o.specularTexture&&i.push(n.assignTexture(r,"specularIntensityMap",o.specularTexture));const a=o.specularColorFactor||[1,1,1];return r.specularColor=(new t.Color).setRGB(a[0],a[1],a[2],t.LinearSRGBColorSpace),void 0!==o.specularColorTexture&&i.push(n.assignTexture(r,"specularColorMap",o.specularColorTexture,t.SRGBColorSpace)),Promise.all(i)}}class g{constructor(e){this.parser=e,this.name=i.EXT_MATERIALS_BUMP}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,t){const r=this.parser,n=r.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const s=[],i=n.extensions[this.name];return t.bumpScale=void 0!==i.bumpFactor?i.bumpFactor:1,void 0!==i.bumpTexture&&s.push(r.assignTexture(t,"bumpMap",i.bumpTexture)),Promise.all(s)}}class x{constructor(e){this.parser=e,this.name=i.KHR_MATERIALS_ANISOTROPY}getMaterialType(e){const r=this.parser.json.materials[e];return r.extensions&&r.extensions[this.name]?t.MeshPhysicalMaterial:null}extendMaterialParams(e,t){const r=this.parser,n=r.json.materials[e];if(!n.extensions||!n.extensions[this.name])return Promise.resolve();const s=[],i=n.extensions[this.name];return void 0!==i.anisotropyStrength&&(t.anisotropy=i.anisotropyStrength),void 0!==i.anisotropyRotation&&(t.anisotropyRotation=i.anisotropyRotation),void 0!==i.anisotropyTexture&&s.push(r.assignTexture(t,"anisotropyMap",i.anisotropyTexture)),Promise.all(s)}}class v{constructor(e){this.parser=e,this.name=i.KHR_TEXTURE_BASISU}loadTexture(e){const t=this.parser,r=t.json,n=r.textures[e];if(!n.extensions||!n.extensions[this.name])return null;const s=n.extensions[this.name],i=t.options.ktx2Loader;if(!i){if(r.extensionsRequired&&r.extensionsRequired.indexOf(this.name)>=0)throw new Error("THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures");return null}return t.loadTextureImage(e,s.source,i)}}class T{constructor(e){this.parser=e,this.name=i.EXT_TEXTURE_WEBP,this.isSupported=null}loadTexture(e){const t=this.name,r=this.parser,n=r.json,s=n.textures[e];if(!s.extensions||!s.extensions[t])return null;const i=s.extensions[t],o=n.images[i.source];let a=r.textureLoader;if(o.uri){const e=r.options.manager.getHandler(o.uri);null!==e&&(a=e)}return this.detectSupport().then((function(s){if(s)return r.loadTextureImage(e,i.source,a);if(n.extensionsRequired&&n.extensionsRequired.indexOf(t)>=0)throw new Error("THREE.GLTFLoader: WebP required by asset but unsupported.");return r.loadTexture(e)}))}detectSupport(){return this.isSupported||(this.isSupported=new Promise((function(e){const t=new Image;t.src="data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",t.onload=t.onerror=function(){e(1===t.height)}}))),this.isSupported}}class A{constructor(e){this.parser=e,this.name=i.EXT_TEXTURE_AVIF,this.isSupported=null}loadTexture(e){const t=this.name,r=this.parser,n=r.json,s=n.textures[e];if(!s.extensions||!s.extensions[t])return null;const i=s.extensions[t],o=n.images[i.source];let a=r.textureLoader;if(o.uri){const e=r.options.manager.getHandler(o.uri);null!==e&&(a=e)}return this.detectSupport().then((function(s){if(s)return r.loadTextureImage(e,i.source,a);if(n.extensionsRequired&&n.extensionsRequired.indexOf(t)>=0)throw new Error("THREE.GLTFLoader: AVIF required by asset but unsupported.");return r.loadTexture(e)}))}detectSupport(){return this.isSupported||(this.isSupported=new Promise((function(e){const t=new Image;t.src="data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAABcAAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAEAAAABAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQAMAAAAABNjb2xybmNseAACAAIABoAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAAB9tZGF0EgAKCBgABogQEDQgMgkQAAAAB8dSLfI=",t.onload=t.onerror=function(){e(1===t.height)}}))),this.isSupported}}class M{constructor(e){this.name=i.EXT_MESHOPT_COMPRESSION,this.parser=e}loadBufferView(e){const t=this.parser.json,r=t.bufferViews[e];if(r.extensions&&r.extensions[this.name]){const e=r.extensions[this.name],n=this.parser.getDependency("buffer",e.buffer),s=this.parser.options.meshoptDecoder;if(!s||!s.supported){if(t.extensionsRequired&&t.extensionsRequired.indexOf(this.name)>=0)throw new Error("THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files");return null}return n.then((function(t){const r=e.byteOffset||0,n=e.byteLength||0,i=e.count,o=e.byteStride,a=new Uint8Array(t,r,n);return s.decodeGltfBufferAsync?s.decodeGltfBufferAsync(i,o,a,e.mode,e.filter).then((function(e){return e.buffer})):s.ready.then((function(){const t=new ArrayBuffer(i*o);return s.decodeGltfBuffer(new Uint8Array(t),i,o,a,e.mode,e.filter),t}))}))}return null}}class w{constructor(e){this.name=i.EXT_MESH_GPU_INSTANCING,this.parser=e}createNodeMesh(e){const r=this.parser.json,n=r.nodes[e];if(!n.extensions||!n.extensions[this.name]||void 0===n.mesh)return null;const s=r.meshes[n.mesh];for(const e of s.primitives)if(e.mode!==B.TRIANGLES&&e.mode!==B.TRIANGLE_STRIP&&e.mode!==B.TRIANGLE_FAN&&void 0!==e.mode)return null;const i=n.extensions[this.name].attributes,o=[],a={};for(const e in i)o.push(this.parser.getDependency("accessor",i[e]).then((t=>(a[e]=t,a[e]))));return o.length<1?null:(o.push(this.parser.createNodeMesh(e)),Promise.all(o).then((e=>{const r=e.pop(),n=r.isGroup?r.children:[r],s=e[0].count,i=[];for(const e of n){const r=new t.Matrix4,n=new t.Vector3,o=new t.Quaternion,l=new t.Vector3(1,1,1),h=new t.InstancedMesh(e.geometry,e.material,s);for(let e=0;e<s;e++)a.TRANSLATION&&n.fromBufferAttribute(a.TRANSLATION,e),a.ROTATION&&o.fromBufferAttribute(a.ROTATION,e),a.SCALE&&l.fromBufferAttribute(a.SCALE,e),h.setMatrixAt(e,r.compose(n,o,l));for(const r in a)if("_COLOR_0"===r){const e=a[r];h.instanceColor=new t.InstancedBufferAttribute(e.array,e.itemSize,e.normalized)}else"TRANSLATION"!==r&&"ROTATION"!==r&&"SCALE"!==r&&e.geometry.setAttribute(r,a[r]);t.Object3D.prototype.copy.call(h,e),this.parser.assignFinalMaterial(h),i.push(h)}return r.isGroup?(r.clear(),r.add(...i),r):i[0]})))}}const b="glTF",y=1313821514,S=5130562;class C{constructor(e){this.name=i.KHR_BINARY_GLTF,this.content=null,this.body=null;const t=new DataView(e,0,12),r=new TextDecoder;if(this.header={magic:r.decode(new Uint8Array(e.slice(0,4))),version:t.getUint32(4,!0),length:t.getUint32(8,!0)},this.header.magic!==b)throw new Error("THREE.GLTFLoader: Unsupported glTF-Binary header.");if(this.header.version<2)throw new Error("THREE.GLTFLoader: Legacy binary file detected.");const n=this.header.length-12,s=new DataView(e,12);let o=0;for(;o<n;){const t=s.getUint32(o,!0);o+=4;const n=s.getUint32(o,!0);if(o+=4,n===y){const n=new Uint8Array(e,12+o,t);this.content=r.decode(n)}else if(n===S){const r=12+o;this.body=e.slice(r,r+t)}o+=t}if(null===this.content)throw new Error("THREE.GLTFLoader: JSON content not found.")}}class E{constructor(e,t){if(!t)throw new Error("THREE.GLTFLoader: No DRACOLoader instance provided.");this.name=i.KHR_DRACO_MESH_COMPRESSION,this.json=e,this.dracoLoader=t,this.dracoLoader.preload()}decodePrimitive(e,r){const n=this.json,s=this.dracoLoader,i=e.extensions[this.name].bufferView,o=e.extensions[this.name].attributes,a={},l={},h={};for(const e in o){const t=H[e]||e.toLowerCase();a[t]=o[e]}for(const t in e.attributes){const r=H[t]||t.toLowerCase();if(void 0!==o[t]){const s=n.accessors[e.attributes[t]],i=N[s.componentType];h[r]=i.name,l[r]=!0===s.normalized}}return r.getDependency("bufferView",i).then((function(e){return new Promise((function(r,n){s.decodeDracoFile(e,(function(e){for(const t in e.attributes){const r=e.attributes[t],n=l[t];void 0!==n&&(r.normalized=n)}r(e)}),a,h,t.LinearSRGBColorSpace,n)}))}))}}class R{constructor(){this.name=i.KHR_TEXTURE_TRANSFORM}extendTexture(e,t){return void 0!==t.texCoord&&t.texCoord!==e.channel||void 0!==t.offset||void 0!==t.rotation||void 0!==t.scale?(e=e.clone(),void 0!==t.texCoord&&(e.channel=t.texCoord),void 0!==t.offset&&e.offset.fromArray(t.offset),void 0!==t.rotation&&(e.rotation=t.rotation),void 0!==t.scale&&e.repeat.fromArray(t.scale),e.needsUpdate=!0,e):e}}class L{constructor(){this.name=i.KHR_MESH_QUANTIZATION}}class P extends t.Interpolant{constructor(e,t,r,n){super(e,t,r,n)}copySampleValue_(e){const t=this.resultBuffer,r=this.sampleValues,n=this.valueSize,s=e*n*3+n;for(let e=0;e!==n;e++)t[e]=r[s+e];return t}interpolate_(e,t,r,n){const s=this.resultBuffer,i=this.sampleValues,o=this.valueSize,a=2*o,l=3*o,h=n-t,c=(r-t)/h,u=c*c,d=u*c,p=e*l,f=p-l,m=-2*d+3*u,g=d-u,x=1-m,v=g-u+c;for(let e=0;e!==o;e++){const t=i[f+e+o],r=i[f+e+a]*h,n=i[p+e+o],l=i[p+e]*h;s[e]=x*t+v*r+m*n+g*l}return s}}const D=new t.Quaternion;class O extends P{interpolate_(e,t,r,n){const s=super.interpolate_(e,t,r,n);return D.fromArray(s).normalize().toArray(s),s}}const B={FLOAT:5126,FLOAT_MAT3:35675,FLOAT_MAT4:35676,FLOAT_VEC2:35664,FLOAT_VEC3:35665,FLOAT_VEC4:35666,LINEAR:9729,REPEAT:10497,SAMPLER_2D:35678,POINTS:0,LINES:1,LINE_LOOP:2,LINE_STRIP:3,TRIANGLES:4,TRIANGLE_STRIP:5,TRIANGLE_FAN:6,UNSIGNED_BYTE:5121,UNSIGNED_SHORT:5123},N={5120:Int8Array,5121:Uint8Array,5122:Int16Array,5123:Uint16Array,5125:Uint32Array,5126:Float32Array},I={9728:t.NearestFilter,9729:t.LinearFilter,9984:t.NearestMipmapNearestFilter,9985:t.LinearMipmapNearestFilter,9986:t.NearestMipmapLinearFilter,9987:t.LinearMipmapLinearFilter},F={33071:t.ClampToEdgeWrapping,33648:t.MirroredRepeatWrapping,10497:t.RepeatWrapping},U={SCALAR:1,VEC2:2,VEC3:3,VEC4:4,MAT2:4,MAT3:9,MAT4:16},H={POSITION:"position",NORMAL:"normal",TANGENT:"tangent",TEXCOORD_0:"uv",TEXCOORD_1:"uv1",TEXCOORD_2:"uv2",TEXCOORD_3:"uv3",COLOR_0:"color",WEIGHTS_0:"skinWeight",JOINTS_0:"skinIndex"},k={scale:"scale",translation:"position",rotation:"quaternion",weights:"morphTargetInfluences"},G={CUBICSPLINE:void 0,LINEAR:t.InterpolateLinear,STEP:t.InterpolateDiscrete},z="OPAQUE",j="MASK",W="BLEND";function X(e,t,r){for(const n in r.extensions)void 0===e[n]&&(t.userData.gltfExtensions=t.userData.gltfExtensions||{},t.userData.gltfExtensions[n]=r.extensions[n])}function V(e,t){void 0!==t.extras&&("object"==typeof t.extras?Object.assign(e.userData,t.extras):console.warn("THREE.GLTFLoader: Ignoring primitive type .extras, "+t.extras))}function Y(e,t){if(e.updateMorphTargets(),void 0!==t.weights)for(let r=0,n=t.weights.length;r<n;r++)e.morphTargetInfluences[r]=t.weights[r];if(t.extras&&Array.isArray(t.extras.targetNames)){const r=t.extras.targetNames;if(e.morphTargetInfluences.length===r.length){e.morphTargetDictionary={};for(let t=0,n=r.length;t<n;t++)e.morphTargetDictionary[r[t]]=t}else console.warn("THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.")}}function Q(e){let t;const r=e.extensions&&e.extensions[i.KHR_DRACO_MESH_COMPRESSION];if(t=r?"draco:"+r.bufferView+":"+r.indices+":"+q(r.attributes):e.indices+":"+q(e.attributes)+":"+e.mode,void 0!==e.targets)for(let r=0,n=e.targets.length;r<n;r++)t+=":"+q(e.targets[r]);return t}function q(e){let t="";const r=Object.keys(e).sort();for(let n=0,s=r.length;n<s;n++)t+=r[n]+":"+e[r[n]]+";";return t}function K(e){switch(e){case Int8Array:return 1/127;case Uint8Array:return 1/255;case Int16Array:return 1/32767;case Uint16Array:return 1/65535;default:throw new Error("THREE.GLTFLoader: Unsupported normalized accessor component type.")}}const Z=new t.Matrix4;class _{constructor(e={},r={}){this.json=e,this.extensions={},this.plugins={},this.options=r,this.cache=new s,this.associations=new Map,this.primitiveCache={},this.nodeCache={},this.meshCache={refs:{},uses:{}},this.cameraCache={refs:{},uses:{}},this.lightCache={refs:{},uses:{}},this.sourceCache={},this.textureCache={},this.nodeNamesUsed={};let n=!1,i=!1,o=-1;"undefined"!=typeof navigator&&(n=!0===/^((?!chrome|android).)*safari/i.test(navigator.userAgent),i=navigator.userAgent.indexOf("Firefox")>-1,o=i?navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1]:-1),"undefined"==typeof createImageBitmap||n||i&&o<98?this.textureLoader=new t.TextureLoader(this.options.manager):this.textureLoader=new t.ImageBitmapLoader(this.options.manager),this.textureLoader.setCrossOrigin(this.options.crossOrigin),this.textureLoader.setRequestHeader(this.options.requestHeader),this.fileLoader=new t.FileLoader(this.options.manager),this.fileLoader.setResponseType("arraybuffer"),"use-credentials"===this.options.crossOrigin&&this.fileLoader.setWithCredentials(!0)}setExtensions(e){this.extensions=e}setPlugins(e){this.plugins=e}parse(e,t){const r=this,n=this.json,s=this.extensions;this.cache.removeAll(),this.nodeCache={},this._invokeAll((function(e){return e._markDefs&&e._markDefs()})),Promise.all(this._invokeAll((function(e){return e.beforeRoot&&e.beforeRoot()}))).then((function(){return Promise.all([r.getDependencies("scene"),r.getDependencies("animation"),r.getDependencies("camera")])})).then((function(t){const i={scene:t[0][n.scene||0],scenes:t[0],animations:t[1],cameras:t[2],asset:n.asset,parser:r,userData:{}};return X(s,i,n),V(i,n),Promise.all(r._invokeAll((function(e){return e.afterRoot&&e.afterRoot(i)}))).then((function(){e(i)}))})).catch(t)}_markDefs(){const e=this.json.nodes||[],t=this.json.skins||[],r=this.json.meshes||[];for(let r=0,n=t.length;r<n;r++){const n=t[r].joints;for(let t=0,r=n.length;t<r;t++)e[n[t]].isBone=!0}for(let t=0,n=e.length;t<n;t++){const n=e[t];void 0!==n.mesh&&(this._addNodeRef(this.meshCache,n.mesh),void 0!==n.skin&&(r[n.mesh].isSkinnedMesh=!0)),void 0!==n.camera&&this._addNodeRef(this.cameraCache,n.camera)}}_addNodeRef(e,t){void 0!==t&&(void 0===e.refs[t]&&(e.refs[t]=e.uses[t]=0),e.refs[t]++)}_getNodeRef(e,t,r){if(e.refs[t]<=1)return r;const n=r.clone(),s=(e,t)=>{const r=this.associations.get(e);null!=r&&this.associations.set(t,r);for(const[r,n]of e.children.entries())s(n,t.children[r])};return s(r,n),n.name+="_instance_"+e.uses[t]++,n}_invokeOne(e){const t=Object.values(this.plugins);t.push(this);for(let r=0;r<t.length;r++){const n=e(t[r]);if(n)return n}return null}_invokeAll(e){const t=Object.values(this.plugins);t.unshift(this);const r=[];for(let n=0;n<t.length;n++){const s=e(t[n]);s&&r.push(s)}return r}getDependency(e,t){const r=e+":"+t;let n=this.cache.get(r);if(!n){switch(e){case"scene":n=this.loadScene(t);break;case"node":n=this._invokeOne((function(e){return e.loadNode&&e.loadNode(t)}));break;case"mesh":n=this._invokeOne((function(e){return e.loadMesh&&e.loadMesh(t)}));break;case"accessor":n=this.loadAccessor(t);break;case"bufferView":n=this._invokeOne((function(e){return e.loadBufferView&&e.loadBufferView(t)}));break;case"buffer":n=this.loadBuffer(t);break;case"material":n=this._invokeOne((function(e){return e.loadMaterial&&e.loadMaterial(t)}));break;case"texture":n=this._invokeOne((function(e){return e.loadTexture&&e.loadTexture(t)}));break;case"skin":n=this.loadSkin(t);break;case"animation":n=this._invokeOne((function(e){return e.loadAnimation&&e.loadAnimation(t)}));break;case"camera":n=this.loadCamera(t);break;default:if(n=this._invokeOne((function(r){return r!=this&&r.getDependency&&r.getDependency(e,t)})),!n)throw new Error("Unknown type: "+e)}this.cache.add(r,n)}return n}getDependencies(e){let t=this.cache.get(e);if(!t){const r=this,n=this.json[e+("mesh"===e?"es":"s")]||[];t=Promise.all(n.map((function(t,n){return r.getDependency(e,n)}))),this.cache.add(e,t)}return t}loadBuffer(e){const r=this.json.buffers[e],n=this.fileLoader;if(r.type&&"arraybuffer"!==r.type)throw new Error("THREE.GLTFLoader: "+r.type+" buffer type is not supported.");if(void 0===r.uri&&0===e)return Promise.resolve(this.extensions[i.KHR_BINARY_GLTF].body);const s=this.options;return new Promise((function(e,i){n.load(t.LoaderUtils.resolveURL(r.uri,s.path),e,void 0,(function(){i(new Error('THREE.GLTFLoader: Failed to load buffer "'+r.uri+'".'))}))}))}loadBufferView(e){const t=this.json.bufferViews[e];return this.getDependency("buffer",t.buffer).then((function(e){const r=t.byteLength||0,n=t.byteOffset||0;return e.slice(n,n+r)}))}loadAccessor(e){const r=this,n=this.json,s=this.json.accessors[e];if(void 0===s.bufferView&&void 0===s.sparse){const e=U[s.type],r=N[s.componentType],n=!0===s.normalized,i=new r(s.count*e);return Promise.resolve(new t.BufferAttribute(i,e,n))}const i=[];return void 0!==s.bufferView?i.push(this.getDependency("bufferView",s.bufferView)):i.push(null),void 0!==s.sparse&&(i.push(this.getDependency("bufferView",s.sparse.indices.bufferView)),i.push(this.getDependency("bufferView",s.sparse.values.bufferView))),Promise.all(i).then((function(e){const i=e[0],o=U[s.type],a=N[s.componentType],l=a.BYTES_PER_ELEMENT,h=l*o,c=s.byteOffset||0,u=void 0!==s.bufferView?n.bufferViews[s.bufferView].byteStride:void 0,d=!0===s.normalized;let p,f;if(u&&u!==h){const e=Math.floor(c/u),n="InterleavedBuffer:"+s.bufferView+":"+s.componentType+":"+e+":"+s.count;let h=r.cache.get(n);h||(p=new a(i,e*u,s.count*u/l),h=new t.InterleavedBuffer(p,u/l),r.cache.add(n,h)),f=new t.InterleavedBufferAttribute(h,o,c%u/l,d)}else p=null===i?new a(s.count*o):new a(i,c,s.count*o),f=new t.BufferAttribute(p,o,d);if(void 0!==s.sparse){const r=U.SCALAR,n=N[s.sparse.indices.componentType],l=s.sparse.indices.byteOffset||0,h=s.sparse.values.byteOffset||0,c=new n(e[1],l,s.sparse.count*r),u=new a(e[2],h,s.sparse.count*o);null!==i&&(f=new t.BufferAttribute(f.array.slice(),f.itemSize,f.normalized));for(let e=0,t=c.length;e<t;e++){const t=c[e];if(f.setX(t,u[e*o]),o>=2&&f.setY(t,u[e*o+1]),o>=3&&f.setZ(t,u[e*o+2]),o>=4&&f.setW(t,u[e*o+3]),o>=5)throw new Error("THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.")}}return f}))}loadTexture(e){const t=this.json,r=this.options,n=t.textures[e].source,s=t.images[n];let i=this.textureLoader;if(s.uri){const e=r.manager.getHandler(s.uri);null!==e&&(i=e)}return this.loadTextureImage(e,n,i)}loadTextureImage(e,r,n){const s=this,i=this.json,o=i.textures[e],a=i.images[r],l=(a.uri||a.bufferView)+":"+o.sampler;if(this.textureCache[l])return this.textureCache[l];const h=this.loadImageSource(r,n).then((function(r){r.flipY=!1,r.name=o.name||a.name||"",""===r.name&&"string"==typeof a.uri&&!1===a.uri.startsWith("data:image/")&&(r.name=a.uri);const n=(i.samplers||{})[o.sampler]||{};return r.magFilter=I[n.magFilter]||t.LinearFilter,r.minFilter=I[n.minFilter]||t.LinearMipmapLinearFilter,r.wrapS=F[n.wrapS]||t.RepeatWrapping,r.wrapT=F[n.wrapT]||t.RepeatWrapping,s.associations.set(r,{textures:e}),r})).catch((function(){return null}));return this.textureCache[l]=h,h}loadImageSource(e,r){const n=this,s=this.json,i=this.options;if(void 0!==this.sourceCache[e])return this.sourceCache[e].then((e=>e.clone()));const o=s.images[e],a=self.URL||self.webkitURL;let l=o.uri||"",h=!1;if(void 0!==o.bufferView)l=n.getDependency("bufferView",o.bufferView).then((function(e){h=!0;const t=new Blob([e],{type:o.mimeType});return l=a.createObjectURL(t),l}));else if(void 0===o.uri)throw new Error("THREE.GLTFLoader: Image "+e+" is missing URI and bufferView");const c=Promise.resolve(l).then((function(e){return new Promise((function(n,s){let o=n;!0===r.isImageBitmapLoader&&(o=function(e){const r=new t.Texture(e);r.needsUpdate=!0,n(r)}),r.load(t.LoaderUtils.resolveURL(e,i.path),o,void 0,s)}))})).then((function(e){var t;return!0===h&&a.revokeObjectURL(l),e.userData.mimeType=o.mimeType||((t=o.uri).search(/\.jpe?g($|\?)/i)>0||0===t.search(/^data\:image\/jpeg/)?"image/jpeg":t.search(/\.webp($|\?)/i)>0||0===t.search(/^data\:image\/webp/)?"image/webp":"image/png"),e})).catch((function(e){throw console.error("THREE.GLTFLoader: Couldn't load texture",l),e}));return this.sourceCache[e]=c,c}assignTexture(e,t,r,n){const s=this;return this.getDependency("texture",r.index).then((function(o){if(!o)return null;if(void 0!==r.texCoord&&r.texCoord>0&&((o=o.clone()).channel=r.texCoord),s.extensions[i.KHR_TEXTURE_TRANSFORM]){const e=void 0!==r.extensions?r.extensions[i.KHR_TEXTURE_TRANSFORM]:void 0;if(e){const t=s.associations.get(o);o=s.extensions[i.KHR_TEXTURE_TRANSFORM].extendTexture(o,e),s.associations.set(o,t)}}return void 0!==n&&(o.colorSpace=n),e[t]=o,o}))}assignFinalMaterial(e){const r=e.geometry;let n=e.material;const s=void 0===r.attributes.tangent,i=void 0!==r.attributes.color,o=void 0===r.attributes.normal;if(e.isPoints){const e="PointsMaterial:"+n.uuid;let r=this.cache.get(e);r||(r=new t.PointsMaterial,t.Material.prototype.copy.call(r,n),r.color.copy(n.color),r.map=n.map,r.sizeAttenuation=!1,this.cache.add(e,r)),n=r}else if(e.isLine){const e="LineBasicMaterial:"+n.uuid;let r=this.cache.get(e);r||(r=new t.LineBasicMaterial,t.Material.prototype.copy.call(r,n),r.color.copy(n.color),r.map=n.map,this.cache.add(e,r)),n=r}if(s||i||o){let e="ClonedMaterial:"+n.uuid+":";s&&(e+="derivative-tangents:"),i&&(e+="vertex-colors:"),o&&(e+="flat-shading:");let t=this.cache.get(e);t||(t=n.clone(),i&&(t.vertexColors=!0),o&&(t.flatShading=!0),s&&(t.normalScale&&(t.normalScale.y*=-1),t.clearcoatNormalScale&&(t.clearcoatNormalScale.y*=-1)),this.cache.add(e,t),this.associations.set(t,this.associations.get(n))),n=t}e.material=n}getMaterialType(){return t.MeshStandardMaterial}loadMaterial(e){const r=this,n=this.json,s=this.extensions,o=n.materials[e];let a;const l={},h=[];if((o.extensions||{})[i.KHR_MATERIALS_UNLIT]){const e=s[i.KHR_MATERIALS_UNLIT];a=e.getMaterialType(),h.push(e.extendParams(l,o,r))}else{const n=o.pbrMetallicRoughness||{};if(l.color=new t.Color(1,1,1),l.opacity=1,Array.isArray(n.baseColorFactor)){const e=n.baseColorFactor;l.color.setRGB(e[0],e[1],e[2],t.LinearSRGBColorSpace),l.opacity=e[3]}void 0!==n.baseColorTexture&&h.push(r.assignTexture(l,"map",n.baseColorTexture,t.SRGBColorSpace)),l.metalness=void 0!==n.metallicFactor?n.metallicFactor:1,l.roughness=void 0!==n.roughnessFactor?n.roughnessFactor:1,void 0!==n.metallicRoughnessTexture&&(h.push(r.assignTexture(l,"metalnessMap",n.metallicRoughnessTexture)),h.push(r.assignTexture(l,"roughnessMap",n.metallicRoughnessTexture))),a=this._invokeOne((function(t){return t.getMaterialType&&t.getMaterialType(e)})),h.push(Promise.all(this._invokeAll((function(t){return t.extendMaterialParams&&t.extendMaterialParams(e,l)}))))}!0===o.doubleSided&&(l.side=t.DoubleSide);const c=o.alphaMode||z;if(c===W?(l.transparent=!0,l.depthWrite=!1):(l.transparent=!1,c===j&&(l.alphaTest=void 0!==o.alphaCutoff?o.alphaCutoff:.5)),void 0!==o.normalTexture&&a!==t.MeshBasicMaterial&&(h.push(r.assignTexture(l,"normalMap",o.normalTexture)),l.normalScale=new t.Vector2(1,1),void 0!==o.normalTexture.scale)){const e=o.normalTexture.scale;l.normalScale.set(e,e)}if(void 0!==o.occlusionTexture&&a!==t.MeshBasicMaterial&&(h.push(r.assignTexture(l,"aoMap",o.occlusionTexture)),void 0!==o.occlusionTexture.strength&&(l.aoMapIntensity=o.occlusionTexture.strength)),void 0!==o.emissiveFactor&&a!==t.MeshBasicMaterial){const e=o.emissiveFactor;l.emissive=(new t.Color).setRGB(e[0],e[1],e[2],t.LinearSRGBColorSpace)}return void 0!==o.emissiveTexture&&a!==t.MeshBasicMaterial&&h.push(r.assignTexture(l,"emissiveMap",o.emissiveTexture,t.SRGBColorSpace)),Promise.all(h).then((function(){const t=new a(l);return o.name&&(t.name=o.name),V(t,o),r.associations.set(t,{materials:e}),o.extensions&&X(s,t,o),t}))}createUniqueName(e){const r=t.PropertyBinding.sanitizeNodeName(e||"");return r in this.nodeNamesUsed?r+"_"+ ++this.nodeNamesUsed[r]:(this.nodeNamesUsed[r]=0,r)}loadGeometries(e){const r=this,n=this.extensions,s=this.primitiveCache;function o(e){return n[i.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(e,r).then((function(t){return J(t,e,r)}))}const a=[];for(let n=0,l=e.length;n<l;n++){const l=e[n],h=Q(l),c=s[h];if(c)a.push(c.promise);else{let e;e=l.extensions&&l.extensions[i.KHR_DRACO_MESH_COMPRESSION]?o(l):J(new t.BufferGeometry,l,r),s[h]={primitive:l,promise:e},a.push(e)}}return Promise.all(a)}loadMesh(e){const n=this,s=this.json,i=this.extensions,o=s.meshes[e],a=o.primitives,l=[];for(let e=0,r=a.length;e<r;e++){const r=void 0===a[e].material?(void 0===(h=this.cache).DefaultMaterial&&(h.DefaultMaterial=new t.MeshStandardMaterial({color:16777215,emissive:0,metalness:1,roughness:1,transparent:!1,depthTest:!0,side:t.FrontSide})),h.DefaultMaterial):this.getDependency("material",a[e].material);l.push(r)}var h;return l.push(n.loadGeometries(a)),Promise.all(l).then((function(s){const l=s.slice(0,s.length-1),h=s[s.length-1],c=[];for(let s=0,u=h.length;s<u;s++){const u=h[s],d=a[s];let p;const f=l[s];if(d.mode===B.TRIANGLES||d.mode===B.TRIANGLE_STRIP||d.mode===B.TRIANGLE_FAN||void 0===d.mode)p=!0===o.isSkinnedMesh?new t.SkinnedMesh(u,f):new t.Mesh(u,f),!0===p.isSkinnedMesh&&p.normalizeSkinWeights(),d.mode===B.TRIANGLE_STRIP?p.geometry=r(p.geometry,t.TriangleStripDrawMode):d.mode===B.TRIANGLE_FAN&&(p.geometry=r(p.geometry,t.TriangleFanDrawMode));else if(d.mode===B.LINES)p=new t.LineSegments(u,f);else if(d.mode===B.LINE_STRIP)p=new t.Line(u,f);else if(d.mode===B.LINE_LOOP)p=new t.LineLoop(u,f);else{if(d.mode!==B.POINTS)throw new Error("THREE.GLTFLoader: Primitive mode unsupported: "+d.mode);p=new t.Points(u,f)}Object.keys(p.geometry.morphAttributes).length>0&&Y(p,o),p.name=n.createUniqueName(o.name||"mesh_"+e),V(p,o),d.extensions&&X(i,p,d),n.assignFinalMaterial(p),c.push(p)}for(let t=0,r=c.length;t<r;t++)n.associations.set(c[t],{meshes:e,primitives:t});if(1===c.length)return o.extensions&&X(i,c[0],o),c[0];const u=new t.Group;o.extensions&&X(i,u,o),n.associations.set(u,{meshes:e});for(let e=0,t=c.length;e<t;e++)u.add(c[e]);return u}))}loadCamera(e){let r;const n=this.json.cameras[e],s=n[n.type];if(s)return"perspective"===n.type?r=new t.PerspectiveCamera(t.MathUtils.radToDeg(s.yfov),s.aspectRatio||1,s.znear||1,s.zfar||2e6):"orthographic"===n.type&&(r=new t.OrthographicCamera(-s.xmag,s.xmag,s.ymag,-s.ymag,s.znear,s.zfar)),n.name&&(r.name=this.createUniqueName(n.name)),V(r,n),Promise.resolve(r);console.warn("THREE.GLTFLoader: Missing camera parameters.")}loadSkin(e){const r=this.json.skins[e],n=[];for(let e=0,t=r.joints.length;e<t;e++)n.push(this._loadNodeShallow(r.joints[e]));return void 0!==r.inverseBindMatrices?n.push(this.getDependency("accessor",r.inverseBindMatrices)):n.push(null),Promise.all(n).then((function(e){const n=e.pop(),s=e,i=[],o=[];for(let e=0,a=s.length;e<a;e++){const a=s[e];if(a){i.push(a);const r=new t.Matrix4;null!==n&&r.fromArray(n.array,16*e),o.push(r)}else console.warn('THREE.GLTFLoader: Joint "%s" could not be found.',r.joints[e])}return new t.Skeleton(i,o)}))}loadAnimation(e){const r=this.json,n=this,s=r.animations[e],i=s.name?s.name:"animation_"+e,o=[],a=[],l=[],h=[],c=[];for(let e=0,t=s.channels.length;e<t;e++){const t=s.channels[e],r=s.samplers[t.sampler],n=t.target,i=n.node,u=void 0!==s.parameters?s.parameters[r.input]:r.input,d=void 0!==s.parameters?s.parameters[r.output]:r.output;void 0!==n.node&&(o.push(this.getDependency("node",i)),a.push(this.getDependency("accessor",u)),l.push(this.getDependency("accessor",d)),h.push(r),c.push(n))}return Promise.all([Promise.all(o),Promise.all(a),Promise.all(l),Promise.all(h),Promise.all(c)]).then((function(e){const r=e[0],s=e[1],o=e[2],a=e[3],l=e[4],h=[];for(let e=0,t=r.length;e<t;e++){const t=r[e],i=s[e],c=o[e],u=a[e],d=l[e];if(void 0===t)continue;t.updateMatrix&&t.updateMatrix();const p=n._createAnimationTracks(t,i,c,u,d);if(p)for(let e=0;e<p.length;e++)h.push(p[e])}return new t.AnimationClip(i,void 0,h)}))}createNodeMesh(e){const t=this.json,r=this,n=t.nodes[e];return void 0===n.mesh?null:r.getDependency("mesh",n.mesh).then((function(e){const t=r._getNodeRef(r.meshCache,n.mesh,e);return void 0!==n.weights&&t.traverse((function(e){if(e.isMesh)for(let t=0,r=n.weights.length;t<r;t++)e.morphTargetInfluences[t]=n.weights[t]})),t}))}loadNode(e){const t=this,r=this.json.nodes[e],n=t._loadNodeShallow(e),s=[],i=r.children||[];for(let e=0,r=i.length;e<r;e++)s.push(t.getDependency("node",i[e]));const o=void 0===r.skin?Promise.resolve(null):t.getDependency("skin",r.skin);return Promise.all([n,Promise.all(s),o]).then((function(e){const t=e[0],r=e[1],n=e[2];null!==n&&t.traverse((function(e){e.isSkinnedMesh&&e.bind(n,Z)}));for(let e=0,n=r.length;e<n;e++)t.add(r[e]);return t}))}_loadNodeShallow(e){const r=this.json,n=this.extensions,s=this;if(void 0!==this.nodeCache[e])return this.nodeCache[e];const i=r.nodes[e],o=i.name?s.createUniqueName(i.name):"",a=[],l=s._invokeOne((function(t){return t.createNodeMesh&&t.createNodeMesh(e)}));return l&&a.push(l),void 0!==i.camera&&a.push(s.getDependency("camera",i.camera).then((function(e){return s._getNodeRef(s.cameraCache,i.camera,e)}))),s._invokeAll((function(t){return t.createNodeAttachment&&t.createNodeAttachment(e)})).forEach((function(e){a.push(e)})),this.nodeCache[e]=Promise.all(a).then((function(r){let a;if(a=!0===i.isBone?new t.Bone:r.length>1?new t.Group:1===r.length?r[0]:new t.Object3D,a!==r[0])for(let e=0,t=r.length;e<t;e++)a.add(r[e]);if(i.name&&(a.userData.name=i.name,a.name=o),V(a,i),i.extensions&&X(n,a,i),void 0!==i.matrix){const e=new t.Matrix4;e.fromArray(i.matrix),a.applyMatrix4(e)}else void 0!==i.translation&&a.position.fromArray(i.translation),void 0!==i.rotation&&a.quaternion.fromArray(i.rotation),void 0!==i.scale&&a.scale.fromArray(i.scale);return s.associations.has(a)||s.associations.set(a,{}),s.associations.get(a).nodes=e,a})),this.nodeCache[e]}loadScene(e){const r=this.extensions,n=this.json.scenes[e],s=this,i=new t.Group;n.name&&(i.name=s.createUniqueName(n.name)),V(i,n),n.extensions&&X(r,i,n);const o=n.nodes||[],a=[];for(let e=0,t=o.length;e<t;e++)a.push(s.getDependency("node",o[e]));return Promise.all(a).then((function(e){for(let t=0,r=e.length;t<r;t++)i.add(e[t]);return s.associations=(e=>{const r=new Map;for(const[e,n]of s.associations)(e instanceof t.Material||e instanceof t.Texture)&&r.set(e,n);return e.traverse((e=>{const t=s.associations.get(e);null!=t&&r.set(e,t)})),r})(i),i}))}_createAnimationTracks(e,r,n,s,i){const o=[],a=e.name?e.name:e.uuid,l=[];let h;switch(k[i.path]===k.weights?e.traverse((function(e){e.morphTargetInfluences&&l.push(e.name?e.name:e.uuid)})):l.push(a),k[i.path]){case k.weights:h=t.NumberKeyframeTrack;break;case k.rotation:h=t.QuaternionKeyframeTrack;break;case k.position:case k.scale:h=t.VectorKeyframeTrack;break;default:if(1===n.itemSize)h=t.NumberKeyframeTrack;else h=t.VectorKeyframeTrack}const c=void 0!==s.interpolation?G[s.interpolation]:t.InterpolateLinear,u=this._getArrayFromAccessor(n);for(let e=0,t=l.length;e<t;e++){const t=new h(l[e]+"."+k[i.path],r.array,u,c);"CUBICSPLINE"===s.interpolation&&this._createCubicSplineTrackInterpolant(t),o.push(t)}return o}_getArrayFromAccessor(e){let t=e.array;if(e.normalized){const e=K(t.constructor),r=new Float32Array(t.length);for(let n=0,s=t.length;n<s;n++)r[n]=t[n]*e;t=r}return t}_createCubicSplineTrackInterpolant(e){e.createInterpolant=function(e){return new(this instanceof t.QuaternionKeyframeTrack?O:P)(this.times,this.values,this.getValueSize()/3,e)},e.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline=!0}}function J(e,r,n){const s=r.attributes,i=[];function o(t,r){return n.getDependency("accessor",t).then((function(t){e.setAttribute(r,t)}))}for(const t in s){const r=H[t]||t.toLowerCase();r in e.attributes||i.push(o(s[t],r))}if(void 0!==r.indices&&!e.index){const t=n.getDependency("accessor",r.indices).then((function(t){e.setIndex(t)}));i.push(t)}return t.ColorManagement.workingColorSpace!==t.LinearSRGBColorSpace&&"COLOR_0"in s&&console.warn(`THREE.GLTFLoader: Converting vertex colors from "srgb-linear" to "${t.ColorManagement.workingColorSpace}" not supported.`),V(e,r),function(e,r,n){const s=r.attributes,i=new t.Box3;if(void 0===s.POSITION)return;{const e=n.json.accessors[s.POSITION],r=e.min,o=e.max;if(void 0===r||void 0===o)return void console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.");if(i.set(new t.Vector3(r[0],r[1],r[2]),new t.Vector3(o[0],o[1],o[2])),e.normalized){const t=K(N[e.componentType]);i.min.multiplyScalar(t),i.max.multiplyScalar(t)}}const o=r.targets;if(void 0!==o){const e=new t.Vector3,r=new t.Vector3;for(let t=0,s=o.length;t<s;t++){const s=o[t];if(void 0!==s.POSITION){const t=n.json.accessors[s.POSITION],i=t.min,o=t.max;if(void 0!==i&&void 0!==o){if(r.setX(Math.max(Math.abs(i[0]),Math.abs(o[0]))),r.setY(Math.max(Math.abs(i[1]),Math.abs(o[1]))),r.setZ(Math.max(Math.abs(i[2]),Math.abs(o[2]))),t.normalized){const e=K(N[t.componentType]);r.multiplyScalar(e)}e.max(r)}else console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.")}}i.expandByVector(e)}e.boundingBox=i;const a=new t.Sphere;i.getCenter(a.center),a.radius=i.min.distanceTo(i.max)/2,e.boundingSphere=a}(e,r,n),Promise.all(i).then((function(){return void 0!==r.targets?function(e,t,r){let n=!1,s=!1,i=!1;for(let e=0,r=t.length;e<r;e++){const r=t[e];if(void 0!==r.POSITION&&(n=!0),void 0!==r.NORMAL&&(s=!0),void 0!==r.COLOR_0&&(i=!0),n&&s&&i)break}if(!n&&!s&&!i)return Promise.resolve(e);const o=[],a=[],l=[];for(let h=0,c=t.length;h<c;h++){const c=t[h];if(n){const t=void 0!==c.POSITION?r.getDependency("accessor",c.POSITION):e.attributes.position;o.push(t)}if(s){const t=void 0!==c.NORMAL?r.getDependency("accessor",c.NORMAL):e.attributes.normal;a.push(t)}if(i){const t=void 0!==c.COLOR_0?r.getDependency("accessor",c.COLOR_0):e.attributes.color;l.push(t)}}return Promise.all([Promise.all(o),Promise.all(a),Promise.all(l)]).then((function(t){const r=t[0],o=t[1],a=t[2];return n&&(e.morphAttributes.position=r),s&&(e.morphAttributes.normal=o),i&&(e.morphAttributes.color=a),e.morphTargetsRelative=!0,e}))}(e,r.targets,n):e}))}const $=new WeakMap;class ee extends t.Loader{constructor(e){super(e),this.decoderPath="",this.decoderConfig={},this.decoderBinary=null,this.decoderPending=null,this.workerLimit=4,this.workerPool=[],this.workerNextTaskID=1,this.workerSourceURL="",this.defaultAttributeIDs={position:"POSITION",normal:"NORMAL",color:"COLOR",uv:"TEX_COORD"},this.defaultAttributeTypes={position:"Float32Array",normal:"Float32Array",color:"Float32Array",uv:"Float32Array"}}setDecoderPath(e){return this.decoderPath=e,this}setDecoderConfig(e){return this.decoderConfig=e,this}setWorkerLimit(e){return this.workerLimit=e,this}load(e,r,n,s){const i=new t.FileLoader(this.manager);i.setPath(this.path),i.setResponseType("arraybuffer"),i.setRequestHeader(this.requestHeader),i.setWithCredentials(this.withCredentials),i.load(e,(e=>{this.parse(e,r,s)}),n,s)}parse(e,r,n=()=>{}){this.decodeDracoFile(e,r,null,null,t.SRGBColorSpace).catch(n)}decodeDracoFile(e,r,n,s,i=t.LinearSRGBColorSpace,o=()=>{}){const a={attributeIDs:n||this.defaultAttributeIDs,attributeTypes:s||this.defaultAttributeTypes,useUniqueIDs:!!n,vertexColorSpace:i};return this.decodeGeometry(e,a).then(r).catch(o)}decodeGeometry(e,t){const r=JSON.stringify(t);if($.has(e)){const t=$.get(e);if(t.key===r)return t.promise;if(0===e.byteLength)throw new Error("THREE.DRACOLoader: Unable to re-decode a buffer with different settings. Buffer has already been transferred.")}let n;const s=this.workerNextTaskID++,i=e.byteLength,o=this._getWorker(s,i).then((r=>(n=r,new Promise(((r,i)=>{n._callbacks[s]={resolve:r,reject:i},n.postMessage({type:"decode",id:s,taskConfig:t,buffer:e},[e])}))))).then((e=>this._createGeometry(e.geometry)));return o.catch((()=>!0)).then((()=>{n&&s&&this._releaseTask(n,s)})),$.set(e,{key:r,promise:o}),o}_createGeometry(e){const r=new t.BufferGeometry;e.index&&r.setIndex(new t.BufferAttribute(e.index.array,1));for(let n=0;n<e.attributes.length;n++){const s=e.attributes[n],i=s.name,o=s.array,a=s.itemSize,l=new t.BufferAttribute(o,a);"color"===i&&(this._assignVertexColorSpace(l,s.vertexColorSpace),l.normalized=o instanceof Float32Array==!1),r.setAttribute(i,l)}return r}_assignVertexColorSpace(e,r){if(r!==t.SRGBColorSpace)return;const n=new t.Color;for(let t=0,r=e.count;t<r;t++)n.fromBufferAttribute(e,t).convertSRGBToLinear(),e.setXYZ(t,n.r,n.g,n.b)}_loadLibrary(e,r){const n=new t.FileLoader(this.manager);return n.setPath(this.decoderPath),n.setResponseType(r),n.setWithCredentials(this.withCredentials),new Promise(((t,r)=>{n.load(e,t,void 0,r)}))}preload(){return this._initDecoder(),this}_initDecoder(){if(this.decoderPending)return this.decoderPending;const e="object"!=typeof WebAssembly||"js"===this.decoderConfig.type,t=[];return e?t.push(this._loadLibrary("draco_decoder.js","text")):(t.push(this._loadLibrary("draco_wasm_wrapper.js","text")),t.push(this._loadLibrary("draco_decoder.wasm","arraybuffer"))),this.decoderPending=Promise.all(t).then((t=>{const r=t[0];e||(this.decoderConfig.wasmBinary=t[1]);const n=te.toString(),s=["/* draco decoder */",r,"","/* worker */",n.substring(n.indexOf("{")+1,n.lastIndexOf("}"))].join("\n");this.workerSourceURL=URL.createObjectURL(new Blob([s]))})),this.decoderPending}_getWorker(e,t){return this._initDecoder().then((()=>{if(this.workerPool.length<this.workerLimit){const e=new Worker(this.workerSourceURL);e._callbacks={},e._taskCosts={},e._taskLoad=0,e.postMessage({type:"init",decoderConfig:this.decoderConfig}),e.onmessage=function(t){const r=t.data;switch(r.type){case"decode":e._callbacks[r.id].resolve(r);break;case"error":e._callbacks[r.id].reject(r);break;default:console.error('THREE.DRACOLoader: Unexpected message, "'+r.type+'"')}},this.workerPool.push(e)}else this.workerPool.sort((function(e,t){return e._taskLoad>t._taskLoad?-1:1}));const r=this.workerPool[this.workerPool.length-1];return r._taskCosts[e]=t,r._taskLoad+=t,r}))}_releaseTask(e,t){e._taskLoad-=e._taskCosts[t],delete e._callbacks[t],delete e._taskCosts[t]}debug(){console.log("Task load: ",this.workerPool.map((e=>e._taskLoad)))}dispose(){for(let e=0;e<this.workerPool.length;++e)this.workerPool[e].terminate();return this.workerPool.length=0,""!==this.workerSourceURL&&URL.revokeObjectURL(this.workerSourceURL),this}}function te(){let e,t;function r(e,t,r,n,s,i){const o=i.num_components(),a=r.num_points()*o,l=a*s.BYTES_PER_ELEMENT,h=function(e,t){switch(t){case Float32Array:return e.DT_FLOAT32;case Int8Array:return e.DT_INT8;case Int16Array:return e.DT_INT16;case Int32Array:return e.DT_INT32;case Uint8Array:return e.DT_UINT8;case Uint16Array:return e.DT_UINT16;case Uint32Array:return e.DT_UINT32}}(e,s),c=e._malloc(l);t.GetAttributeDataArrayForAllPoints(r,i,h,l,c);const u=new s(e.HEAPF32.buffer,c,a).slice();return e._free(c),{name:n,array:u,itemSize:o}}onmessage=function(n){const s=n.data;switch(s.type){case"init":e=s.decoderConfig,t=new Promise((function(t){e.onModuleLoaded=function(e){t({draco:e})},DracoDecoderModule(e)}));break;case"decode":const n=s.buffer,i=s.taskConfig;t.then((e=>{const t=e.draco,o=new t.Decoder;try{const e=function(e,t,n,s){const i=s.attributeIDs,o=s.attributeTypes;let a,l;const h=t.GetEncodedGeometryType(n);if(h===e.TRIANGULAR_MESH)a=new e.Mesh,l=t.DecodeArrayToMesh(n,n.byteLength,a);else{if(h!==e.POINT_CLOUD)throw new Error("THREE.DRACOLoader: Unexpected geometry type.");a=new e.PointCloud,l=t.DecodeArrayToPointCloud(n,n.byteLength,a)}if(!l.ok()||0===a.ptr)throw new Error("THREE.DRACOLoader: Decoding failed: "+l.error_msg());const c={index:null,attributes:[]};for(const n in i){const l=self[o[n]];let h,u;if(s.useUniqueIDs)u=i[n],h=t.GetAttributeByUniqueId(a,u);else{if(u=t.GetAttributeId(a,e[i[n]]),-1===u)continue;h=t.GetAttribute(a,u)}const d=r(e,t,a,n,l,h);"color"===n&&(d.vertexColorSpace=s.vertexColorSpace),c.attributes.push(d)}h===e.TRIANGULAR_MESH&&(c.index=function(e,t,r){const n=r.num_faces(),s=3*n,i=4*s,o=e._malloc(i);t.GetTrianglesUInt32Array(r,i,o);const a=new Uint32Array(e.HEAPF32.buffer,o,s).slice();return e._free(o),{array:a,itemSize:1}}(e,t,a));return e.destroy(a),c}(t,o,new Int8Array(n),i),a=e.attributes.map((e=>e.array.buffer));e.index&&a.push(e.index.array.buffer),self.postMessage({type:"decode",id:s.id,geometry:e},a)}catch(e){console.error(e),self.postMessage({type:"error",id:s.id,error:e.message})}finally{t.destroy(o)}}))}}}function re(e,r,n={}){const s=new t.Vector3,i=new t.Quaternion,o=new t.Vector3,a=new t.Matrix4,l=new t.Matrix4,h=new t.Matrix4;n.preserveMatrix=void 0===n.preserveMatrix||n.preserveMatrix,n.preservePosition=void 0===n.preservePosition||n.preservePosition,n.preserveHipPosition=void 0!==n.preserveHipPosition&&n.preserveHipPosition,n.useTargetMatrix=void 0!==n.useTargetMatrix&&n.useTargetMatrix,n.hip=void 0!==n.hip?n.hip:"hip",n.names=n.names||{};const c=r.isObject3D?r.skeleton.bones:se(r),u=e.isObject3D?e.skeleton.bones:se(e);let d,p,f,m,g;if(e.isObject3D?e.skeleton.pose():(n.useTargetMatrix=!0,n.preserveMatrix=!1),n.preservePosition){g=[];for(let e=0;e<u.length;e++)g.push(u[e].position.clone())}if(n.preserveMatrix){e.updateMatrixWorld(),e.matrixWorld.identity();for(let t=0;t<e.children.length;++t)e.children[t].updateMatrixWorld(!0)}if(n.offsets){d=[];for(let e=0;e<u.length;++e)p=u[e],f=n.names[p.name]||p.name,n.offsets[f]&&(p.matrix.multiply(n.offsets[f]),p.matrix.decompose(p.position,p.quaternion,p.scale),p.updateMatrixWorld()),d.push(p.matrixWorld.clone())}for(let t=0;t<u.length;++t){if(p=u[t],f=n.names[p.name]||p.name,m=ne(f,c),h.copy(p.matrixWorld),m){if(m.updateMatrixWorld(),n.useTargetMatrix?l.copy(m.matrixWorld):(l.copy(e.matrixWorld).invert(),l.multiply(m.matrixWorld)),o.setFromMatrixScale(l),l.scale(o.set(1/o.x,1/o.y,1/o.z)),h.makeRotationFromQuaternion(i.setFromRotationMatrix(l)),e.isObject3D){const t=u.indexOf(p),r=d?d[t]:a.copy(e.skeleton.boneInverses[t]).invert();h.multiply(r)}h.copyPosition(l)}p.parent&&p.parent.isBone?(p.matrix.copy(p.parent.matrixWorld).invert(),p.matrix.multiply(h)):p.matrix.copy(h),n.preserveHipPosition&&f===n.hip&&p.matrix.setPosition(s.set(0,p.position.y,0)),p.matrix.decompose(p.position,p.quaternion,p.scale),p.updateMatrixWorld()}if(n.preservePosition)for(let e=0;e<u.length;++e)p=u[e],f=n.names[p.name]||p.name,f!==n.hip&&p.position.copy(g[e]);n.preserveMatrix&&e.updateMatrixWorld(!0)}function ne(e,t){for(let r=0,n=se(t);r<n.length;r++)if(e===n[r].name)return n[r]}function se(e){return Array.isArray(e)?e:e.bones}function ie(e,t,r){r(e,t);for(let n=0;n<e.children.length;n++)ie(e.children[n],t.children[n],r)}var oe=Object.freeze({__proto__:null,retarget:re,retargetClip:function(e,r,n,s={}){s.useFirstFramePosition=void 0!==s.useFirstFramePosition&&s.useFirstFramePosition,s.fps=void 0!==s.fps?s.fps:30,s.names=s.names||[],r.isObject3D||(r=function(e){const r=new t.SkeletonHelper(e.bones[0]);return r.skeleton=e,r}(r));const i=Math.round(n.duration*(s.fps/1e3)*1e3),o=1/s.fps,a=[],l=new t.AnimationMixer(r),h=se(e.skeleton),c=[];let u,d,p,f,m;l.clipAction(n).play(),l.update(0),r.updateMatrixWorld();for(let t=0;t<i;++t){const n=t*o;re(e,r,s);for(let e=0;e<h.length;++e)m=s.names[h[e].name]||h[e].name,p=ne(m,r.skeleton),p&&(d=h[e],f=c[e]=c[e]||{bone:d},s.hip===m&&(f.pos||(f.pos={times:new Float32Array(i),values:new Float32Array(3*i)}),s.useFirstFramePosition&&(0===t&&(u=d.position.clone()),d.position.sub(u)),f.pos.times[t]=n,d.position.toArray(f.pos.values,3*t)),f.quat||(f.quat={times:new Float32Array(i),values:new Float32Array(4*i)}),f.quat.times[t]=n,d.quaternion.toArray(f.quat.values,4*t));l.update(o),r.updateMatrixWorld()}for(let e=0;e<c.length;++e)f=c[e],f&&(f.pos&&a.push(new t.VectorKeyframeTrack(".bones["+f.bone.name+"].position",f.pos.times,f.pos.values)),a.push(new t.QuaternionKeyframeTrack(".bones["+f.bone.name+"].quaternion",f.quat.times,f.quat.values)));return l.uncacheAction(n),new t.AnimationClip(n.name,-1,a)},clone:function(e){const t=new Map,r=new Map,n=e.clone();return ie(e,n,(function(e,n){t.set(n,e),r.set(e,n)})),n.traverse((function(e){if(!e.isSkinnedMesh)return;const n=e,s=t.get(e),i=s.skeleton.bones;n.skeleton=s.skeleton.clone(),n.bindMatrix.copy(s.bindMatrix),n.skeleton.bones=i.map((function(e){return r.get(e)})),n.bind(n.skeleton,n.bindMatrix)})),n}});const ae=new t.Raycaster,le=new t.Vector3,he=new t.Vector3,ce=new t.Quaternion,ue={X:new t.Vector3(1,0,0),Y:new t.Vector3(0,1,0),Z:new t.Vector3(0,0,1)},de={type:"change"},pe={type:"mouseDown"},fe={type:"mouseUp",mode:null},me={type:"objectChange"};class ge extends t.Object3D{constructor(e,r){super(),void 0===r&&(console.warn('THREE.TransformControls: The second parameter "domElement" is now mandatory.'),r=document),this.isTransformControls=!0,this.visible=!1,this.domElement=r,this.domElement.style.touchAction="none";const n=new Ue;this._gizmo=n,this.add(n);const s=new He;this._plane=s,this.add(s);const i=this;function o(e,t){let r=t;Object.defineProperty(i,e,{get:function(){return void 0!==r?r:t},set:function(t){r!==t&&(r=t,s[e]=t,n[e]=t,i.dispatchEvent({type:e+"-changed",value:t}),i.dispatchEvent(de))}}),i[e]=t,s[e]=t,n[e]=t}o("camera",e),o("object",void 0),o("enabled",!0),o("axis",null),o("mode","translate"),o("translationSnap",null),o("rotationSnap",null),o("scaleSnap",null),o("space","world"),o("size",1),o("dragging",!1),o("showX",!0),o("showY",!0),o("showZ",!0);const a=new t.Vector3,l=new t.Vector3,h=new t.Quaternion,c=new t.Quaternion,u=new t.Vector3,d=new t.Quaternion,p=new t.Vector3,f=new t.Vector3,m=new t.Vector3,g=new t.Vector3;o("worldPosition",a),o("worldPositionStart",l),o("worldQuaternion",h),o("worldQuaternionStart",c),o("cameraPosition",u),o("cameraQuaternion",d),o("pointStart",p),o("pointEnd",f),o("rotationAxis",m),o("rotationAngle",0),o("eye",g),this._offset=new t.Vector3,this._startNorm=new t.Vector3,this._endNorm=new t.Vector3,this._cameraScale=new t.Vector3,this._parentPosition=new t.Vector3,this._parentQuaternion=new t.Quaternion,this._parentQuaternionInv=new t.Quaternion,this._parentScale=new t.Vector3,this._worldScaleStart=new t.Vector3,this._worldQuaternionInv=new t.Quaternion,this._worldScale=new t.Vector3,this._positionStart=new t.Vector3,this._quaternionStart=new t.Quaternion,this._scaleStart=new t.Vector3,this._getPointer=xe.bind(this),this._onPointerDown=Te.bind(this),this._onPointerHover=ve.bind(this),this._onPointerMove=Ae.bind(this),this._onPointerUp=Me.bind(this),this.domElement.addEventListener("pointerdown",this._onPointerDown),this.domElement.addEventListener("pointermove",this._onPointerHover),this.domElement.addEventListener("pointerup",this._onPointerUp)}updateMatrixWorld(){void 0!==this.object&&(this.object.updateMatrixWorld(),null===this.object.parent?console.error("TransformControls: The attached 3D object must be a part of the scene graph."):this.object.parent.matrixWorld.decompose(this._parentPosition,this._parentQuaternion,this._parentScale),this.object.matrixWorld.decompose(this.worldPosition,this.worldQuaternion,this._worldScale),this._parentQuaternionInv.copy(this._parentQuaternion).invert(),this._worldQuaternionInv.copy(this.worldQuaternion).invert()),this.camera.updateMatrixWorld(),this.camera.matrixWorld.decompose(this.cameraPosition,this.cameraQuaternion,this._cameraScale),this.camera.isOrthographicCamera?this.camera.getWorldDirection(this.eye).negate():this.eye.copy(this.cameraPosition).sub(this.worldPosition).normalize(),super.updateMatrixWorld(this)}pointerHover(e){if(void 0===this.object||!0===this.dragging)return;ae.setFromCamera(e,this.camera);const t=we(this._gizmo.picker[this.mode],ae);this.axis=t?t.object.name:null}pointerDown(e){if(void 0!==this.object&&!0!==this.dragging&&0===e.button&&null!==this.axis){ae.setFromCamera(e,this.camera);const t=we(this._plane,ae,!0);t&&(this.object.updateMatrixWorld(),this.object.parent.updateMatrixWorld(),this._positionStart.copy(this.object.position),this._quaternionStart.copy(this.object.quaternion),this._scaleStart.copy(this.object.scale),this.object.matrixWorld.decompose(this.worldPositionStart,this.worldQuaternionStart,this._worldScaleStart),this.pointStart.copy(t.point).sub(this.worldPositionStart)),this.dragging=!0,pe.mode=this.mode,this.dispatchEvent(pe)}}pointerMove(e){const t=this.axis,r=this.mode,n=this.object;let s=this.space;if("scale"===r?s="local":"E"!==t&&"XYZE"!==t&&"XYZ"!==t||(s="world"),void 0===n||null===t||!1===this.dragging||-1!==e.button)return;ae.setFromCamera(e,this.camera);const i=we(this._plane,ae,!0);if(i){if(this.pointEnd.copy(i.point).sub(this.worldPositionStart),"translate"===r)this._offset.copy(this.pointEnd).sub(this.pointStart),"local"===s&&"XYZ"!==t&&this._offset.applyQuaternion(this._worldQuaternionInv),-1===t.indexOf("X")&&(this._offset.x=0),-1===t.indexOf("Y")&&(this._offset.y=0),-1===t.indexOf("Z")&&(this._offset.z=0),"local"===s&&"XYZ"!==t?this._offset.applyQuaternion(this._quaternionStart).divide(this._parentScale):this._offset.applyQuaternion(this._parentQuaternionInv).divide(this._parentScale),n.position.copy(this._offset).add(this._positionStart),this.translationSnap&&("local"===s&&(n.position.applyQuaternion(ce.copy(this._quaternionStart).invert()),-1!==t.search("X")&&(n.position.x=Math.round(n.position.x/this.translationSnap)*this.translationSnap),-1!==t.search("Y")&&(n.position.y=Math.round(n.position.y/this.translationSnap)*this.translationSnap),-1!==t.search("Z")&&(n.position.z=Math.round(n.position.z/this.translationSnap)*this.translationSnap),n.position.applyQuaternion(this._quaternionStart)),"world"===s&&(n.parent&&n.position.add(le.setFromMatrixPosition(n.parent.matrixWorld)),-1!==t.search("X")&&(n.position.x=Math.round(n.position.x/this.translationSnap)*this.translationSnap),-1!==t.search("Y")&&(n.position.y=Math.round(n.position.y/this.translationSnap)*this.translationSnap),-1!==t.search("Z")&&(n.position.z=Math.round(n.position.z/this.translationSnap)*this.translationSnap),n.parent&&n.position.sub(le.setFromMatrixPosition(n.parent.matrixWorld))));else if("scale"===r){if(-1!==t.search("XYZ")){let e=this.pointEnd.length()/this.pointStart.length();this.pointEnd.dot(this.pointStart)<0&&(e*=-1),he.set(e,e,e)}else le.copy(this.pointStart),he.copy(this.pointEnd),le.applyQuaternion(this._worldQuaternionInv),he.applyQuaternion(this._worldQuaternionInv),he.divide(le),-1===t.search("X")&&(he.x=1),-1===t.search("Y")&&(he.y=1),-1===t.search("Z")&&(he.z=1);n.scale.copy(this._scaleStart).multiply(he),this.scaleSnap&&(-1!==t.search("X")&&(n.scale.x=Math.round(n.scale.x/this.scaleSnap)*this.scaleSnap||this.scaleSnap),-1!==t.search("Y")&&(n.scale.y=Math.round(n.scale.y/this.scaleSnap)*this.scaleSnap||this.scaleSnap),-1!==t.search("Z")&&(n.scale.z=Math.round(n.scale.z/this.scaleSnap)*this.scaleSnap||this.scaleSnap))}else if("rotate"===r){this._offset.copy(this.pointEnd).sub(this.pointStart);const e=20/this.worldPosition.distanceTo(le.setFromMatrixPosition(this.camera.matrixWorld));let r=!1;"XYZE"===t?(this.rotationAxis.copy(this._offset).cross(this.eye).normalize(),this.rotationAngle=this._offset.dot(le.copy(this.rotationAxis).cross(this.eye))*e):"X"!==t&&"Y"!==t&&"Z"!==t||(this.rotationAxis.copy(ue[t]),le.copy(ue[t]),"local"===s&&le.applyQuaternion(this.worldQuaternion),le.cross(this.eye),0===le.length()?r=!0:this.rotationAngle=this._offset.dot(le.normalize())*e),("E"===t||r)&&(this.rotationAxis.copy(this.eye),this.rotationAngle=this.pointEnd.angleTo(this.pointStart),this._startNorm.copy(this.pointStart).normalize(),this._endNorm.copy(this.pointEnd).normalize(),this.rotationAngle*=this._endNorm.cross(this._startNorm).dot(this.eye)<0?1:-1),this.rotationSnap&&(this.rotationAngle=Math.round(this.rotationAngle/this.rotationSnap)*this.rotationSnap),"local"===s&&"E"!==t&&"XYZE"!==t?(n.quaternion.copy(this._quaternionStart),n.quaternion.multiply(ce.setFromAxisAngle(this.rotationAxis,this.rotationAngle)).normalize()):(this.rotationAxis.applyQuaternion(this._parentQuaternionInv),n.quaternion.copy(ce.setFromAxisAngle(this.rotationAxis,this.rotationAngle)),n.quaternion.multiply(this._quaternionStart).normalize())}this.dispatchEvent(de),this.dispatchEvent(me)}}pointerUp(e){0===e.button&&(this.dragging&&null!==this.axis&&(fe.mode=this.mode,this.dispatchEvent(fe)),this.dragging=!1,this.axis=null)}dispose(){this.domElement.removeEventListener("pointerdown",this._onPointerDown),this.domElement.removeEventListener("pointermove",this._onPointerHover),this.domElement.removeEventListener("pointermove",this._onPointerMove),this.domElement.removeEventListener("pointerup",this._onPointerUp),this.traverse((function(e){e.geometry&&e.geometry.dispose(),e.material&&e.material.dispose()}))}attach(e){return this.object=e,this.visible=!0,this}detach(){return this.object=void 0,this.visible=!1,this.axis=null,this}reset(){this.enabled&&this.dragging&&(this.object.position.copy(this._positionStart),this.object.quaternion.copy(this._quaternionStart),this.object.scale.copy(this._scaleStart),this.dispatchEvent(de),this.dispatchEvent(me),this.pointStart.copy(this.pointEnd))}getRaycaster(){return ae}getMode(){return this.mode}setMode(e){this.mode=e}setTranslationSnap(e){this.translationSnap=e}setRotationSnap(e){this.rotationSnap=e}setScaleSnap(e){this.scaleSnap=e}setSize(e){this.size=e}setSpace(e){this.space=e}}function xe(e){if(this.domElement.ownerDocument.pointerLockElement)return{x:0,y:0,button:e.button};{const t=this.domElement.getBoundingClientRect();return{x:(e.clientX-t.left)/t.width*2-1,y:-(e.clientY-t.top)/t.height*2+1,button:e.button}}}function ve(e){if(this.enabled)switch(e.pointerType){case"mouse":case"pen":this.pointerHover(this._getPointer(e))}}function Te(e){this.enabled&&(document.pointerLockElement||this.domElement.setPointerCapture(e.pointerId),this.domElement.addEventListener("pointermove",this._onPointerMove),this.pointerHover(this._getPointer(e)),this.pointerDown(this._getPointer(e)))}function Ae(e){this.enabled&&this.pointerMove(this._getPointer(e))}function Me(e){this.enabled&&(this.domElement.releasePointerCapture(e.pointerId),this.domElement.removeEventListener("pointermove",this._onPointerMove),this.pointerUp(this._getPointer(e)))}function we(e,t,r){const n=t.intersectObject(e,!0);for(let e=0;e<n.length;e++)if(n[e].object.visible||r)return n[e];return!1}const be=new t.Euler,ye=new t.Vector3(0,1,0),Se=new t.Vector3(0,0,0),Ce=new t.Matrix4,Ee=new t.Quaternion,Re=new t.Quaternion,Le=new t.Vector3,Pe=new t.Matrix4,De=new t.Vector3(1,0,0),Oe=new t.Vector3(0,1,0),Be=new t.Vector3(0,0,1),Ne=new t.Vector3,Ie=new t.Vector3,Fe=new t.Vector3;class Ue extends t.Object3D{constructor(){super(),this.isTransformControlsGizmo=!0,this.type="TransformControlsGizmo";const e=new t.MeshBasicMaterial({depthTest:!1,depthWrite:!1,fog:!1,toneMapped:!1,transparent:!0}),r=new t.LineBasicMaterial({depthTest:!1,depthWrite:!1,fog:!1,toneMapped:!1,transparent:!0}),n=e.clone();n.opacity=.15;const s=r.clone();s.opacity=.5;const i=e.clone();i.color.setHex(16711680);const o=e.clone();o.color.setHex(65280);const a=e.clone();a.color.setHex(255);const l=e.clone();l.color.setHex(16711680),l.opacity=.5;const h=e.clone();h.color.setHex(65280),h.opacity=.5;const c=e.clone();c.color.setHex(255),c.opacity=.5;const u=e.clone();u.opacity=.25;const d=e.clone();d.color.setHex(16776960),d.opacity=.25;e.clone().color.setHex(16776960);const p=e.clone();p.color.setHex(7895160);const f=new t.CylinderGeometry(0,.04,.1,12);f.translate(0,.05,0);const m=new t.BoxGeometry(.08,.08,.08);m.translate(0,.04,0);const g=new t.BufferGeometry;g.setAttribute("position",new t.Float32BufferAttribute([0,0,0,1,0,0],3));const x=new t.CylinderGeometry(.0075,.0075,.5,3);function v(e,r){const n=new t.TorusGeometry(e,.0075,3,64,r*Math.PI*2);return n.rotateY(Math.PI/2),n.rotateX(Math.PI/2),n}x.translate(0,.25,0);const T={X:[[new t.Mesh(f,i),[.5,0,0],[0,0,-Math.PI/2]],[new t.Mesh(f,i),[-.5,0,0],[0,0,Math.PI/2]],[new t.Mesh(x,i),[0,0,0],[0,0,-Math.PI/2]]],Y:[[new t.Mesh(f,o),[0,.5,0]],[new t.Mesh(f,o),[0,-.5,0],[Math.PI,0,0]],[new t.Mesh(x,o)]],Z:[[new t.Mesh(f,a),[0,0,.5],[Math.PI/2,0,0]],[new t.Mesh(f,a),[0,0,-.5],[-Math.PI/2,0,0]],[new t.Mesh(x,a),null,[Math.PI/2,0,0]]],XYZ:[[new t.Mesh(new t.OctahedronGeometry(.1,0),u.clone()),[0,0,0]]],XY:[[new t.Mesh(new t.BoxGeometry(.15,.15,.01),c.clone()),[.15,.15,0]]],YZ:[[new t.Mesh(new t.BoxGeometry(.15,.15,.01),l.clone()),[0,.15,.15],[0,Math.PI/2,0]]],XZ:[[new t.Mesh(new t.BoxGeometry(.15,.15,.01),h.clone()),[.15,0,.15],[-Math.PI/2,0,0]]]},A={X:[[new t.Mesh(new t.CylinderGeometry(.2,0,.6,4),n),[.3,0,0],[0,0,-Math.PI/2]],[new t.Mesh(new t.CylinderGeometry(.2,0,.6,4),n),[-.3,0,0],[0,0,Math.PI/2]]],Y:[[new t.Mesh(new t.CylinderGeometry(.2,0,.6,4),n),[0,.3,0]],[new t.Mesh(new t.CylinderGeometry(.2,0,.6,4),n),[0,-.3,0],[0,0,Math.PI]]],Z:[[new t.Mesh(new t.CylinderGeometry(.2,0,.6,4),n),[0,0,.3],[Math.PI/2,0,0]],[new t.Mesh(new t.CylinderGeometry(.2,0,.6,4),n),[0,0,-.3],[-Math.PI/2,0,0]]],XYZ:[[new t.Mesh(new t.OctahedronGeometry(.2,0),n)]],XY:[[new t.Mesh(new t.BoxGeometry(.2,.2,.01),n),[.15,.15,0]]],YZ:[[new t.Mesh(new t.BoxGeometry(.2,.2,.01),n),[0,.15,.15],[0,Math.PI/2,0]]],XZ:[[new t.Mesh(new t.BoxGeometry(.2,.2,.01),n),[.15,0,.15],[-Math.PI/2,0,0]]]},M={START:[[new t.Mesh(new t.OctahedronGeometry(.01,2),s),null,null,null,"helper"]],END:[[new t.Mesh(new t.OctahedronGeometry(.01,2),s),null,null,null,"helper"]],DELTA:[[new t.Line(function(){const e=new t.BufferGeometry;return e.setAttribute("position",new t.Float32BufferAttribute([0,0,0,1,1,1],3)),e}(),s),null,null,null,"helper"]],X:[[new t.Line(g,s.clone()),[-1e3,0,0],null,[1e6,1,1],"helper"]],Y:[[new t.Line(g,s.clone()),[0,-1e3,0],[0,0,Math.PI/2],[1e6,1,1],"helper"]],Z:[[new t.Line(g,s.clone()),[0,0,-1e3],[0,-Math.PI/2,0],[1e6,1,1],"helper"]]},w={XYZE:[[new t.Mesh(v(.5,1),p),null,[0,Math.PI/2,0]]],X:[[new t.Mesh(v(.5,.5),i)]],Y:[[new t.Mesh(v(.5,.5),o),null,[0,0,-Math.PI/2]]],Z:[[new t.Mesh(v(.5,.5),a),null,[0,Math.PI/2,0]]],E:[[new t.Mesh(v(.75,1),d),null,[0,Math.PI/2,0]]]},b={AXIS:[[new t.Line(g,s.clone()),[-1e3,0,0],null,[1e6,1,1],"helper"]]},y={XYZE:[[new t.Mesh(new t.SphereGeometry(.25,10,8),n)]],X:[[new t.Mesh(new t.TorusGeometry(.5,.1,4,24),n),[0,0,0],[0,-Math.PI/2,-Math.PI/2]]],Y:[[new t.Mesh(new t.TorusGeometry(.5,.1,4,24),n),[0,0,0],[Math.PI/2,0,0]]],Z:[[new t.Mesh(new t.TorusGeometry(.5,.1,4,24),n),[0,0,0],[0,0,-Math.PI/2]]],E:[[new t.Mesh(new t.TorusGeometry(.75,.1,2,24),n)]]},S={X:[[new t.Mesh(m,i),[.5,0,0],[0,0,-Math.PI/2]],[new t.Mesh(x,i),[0,0,0],[0,0,-Math.PI/2]],[new t.Mesh(m,i),[-.5,0,0],[0,0,Math.PI/2]]],Y:[[new t.Mesh(m,o),[0,.5,0]],[new t.Mesh(x,o)],[new t.Mesh(m,o),[0,-.5,0],[0,0,Math.PI]]],Z:[[new t.Mesh(m,a),[0,0,.5],[Math.PI/2,0,0]],[new t.Mesh(x,a),[0,0,0],[Math.PI/2,0,0]],[new t.Mesh(m,a),[0,0,-.5],[-Math.PI/2,0,0]]],XY:[[new t.Mesh(new t.BoxGeometry(.15,.15,.01),c),[.15,.15,0]]],YZ:[[new t.Mesh(new t.BoxGeometry(.15,.15,.01),l),[0,.15,.15],[0,Math.PI/2,0]]],XZ:[[new t.Mesh(new t.BoxGeometry(.15,.15,.01),h),[.15,0,.15],[-Math.PI/2,0,0]]],XYZ:[[new t.Mesh(new t.BoxGeometry(.1,.1,.1),u.clone())]]},C={X:[[new t.Mesh(new t.CylinderGeometry(.2,0,.6,4),n),[.3,0,0],[0,0,-Math.PI/2]],[new t.Mesh(new t.CylinderGeometry(.2,0,.6,4),n),[-.3,0,0],[0,0,Math.PI/2]]],Y:[[new t.Mesh(new t.CylinderGeometry(.2,0,.6,4),n),[0,.3,0]],[new t.Mesh(new t.CylinderGeometry(.2,0,.6,4),n),[0,-.3,0],[0,0,Math.PI]]],Z:[[new t.Mesh(new t.CylinderGeometry(.2,0,.6,4),n),[0,0,.3],[Math.PI/2,0,0]],[new t.Mesh(new t.CylinderGeometry(.2,0,.6,4),n),[0,0,-.3],[-Math.PI/2,0,0]]],XY:[[new t.Mesh(new t.BoxGeometry(.2,.2,.01),n),[.15,.15,0]]],YZ:[[new t.Mesh(new t.BoxGeometry(.2,.2,.01),n),[0,.15,.15],[0,Math.PI/2,0]]],XZ:[[new t.Mesh(new t.BoxGeometry(.2,.2,.01),n),[.15,0,.15],[-Math.PI/2,0,0]]],XYZ:[[new t.Mesh(new t.BoxGeometry(.2,.2,.2),n),[0,0,0]]]},E={X:[[new t.Line(g,s.clone()),[-1e3,0,0],null,[1e6,1,1],"helper"]],Y:[[new t.Line(g,s.clone()),[0,-1e3,0],[0,0,Math.PI/2],[1e6,1,1],"helper"]],Z:[[new t.Line(g,s.clone()),[0,0,-1e3],[0,-Math.PI/2,0],[1e6,1,1],"helper"]]};function R(e){const r=new t.Object3D;for(const t in e)for(let n=e[t].length;n--;){const s=e[t][n][0].clone(),i=e[t][n][1],o=e[t][n][2],a=e[t][n][3],l=e[t][n][4];s.name=t,s.tag=l,i&&s.position.set(i[0],i[1],i[2]),o&&s.rotation.set(o[0],o[1],o[2]),a&&s.scale.set(a[0],a[1],a[2]),s.updateMatrix();const h=s.geometry.clone();h.applyMatrix4(s.matrix),s.geometry=h,s.renderOrder=1/0,s.position.set(0,0,0),s.rotation.set(0,0,0),s.scale.set(1,1,1),r.add(s)}return r}this.gizmo={},this.picker={},this.helper={},this.add(this.gizmo.translate=R(T)),this.add(this.gizmo.rotate=R(w)),this.add(this.gizmo.scale=R(S)),this.add(this.picker.translate=R(A)),this.add(this.picker.rotate=R(y)),this.add(this.picker.scale=R(C)),this.add(this.helper.translate=R(M)),this.add(this.helper.rotate=R(b)),this.add(this.helper.scale=R(E)),this.picker.translate.visible=!1,this.picker.rotate.visible=!1,this.picker.scale.visible=!1}updateMatrixWorld(e){const t="local"===("scale"===this.mode?"local":this.space)?this.worldQuaternion:Re;this.gizmo.translate.visible="translate"===this.mode,this.gizmo.rotate.visible="rotate"===this.mode,this.gizmo.scale.visible="scale"===this.mode,this.helper.translate.visible="translate"===this.mode,this.helper.rotate.visible="rotate"===this.mode,this.helper.scale.visible="scale"===this.mode;let r=[];r=r.concat(this.picker[this.mode].children),r=r.concat(this.gizmo[this.mode].children),r=r.concat(this.helper[this.mode].children);for(let e=0;e<r.length;e++){const n=r[e];let s;if(n.visible=!0,n.rotation.set(0,0,0),n.position.copy(this.worldPosition),s=this.camera.isOrthographicCamera?(this.camera.top-this.camera.bottom)/this.camera.zoom:this.worldPosition.distanceTo(this.cameraPosition)*Math.min(1.9*Math.tan(Math.PI*this.camera.fov/360)/this.camera.zoom,7),n.scale.set(1,1,1).multiplyScalar(s*this.size/4),"helper"!==n.tag){if(n.quaternion.copy(t),"translate"===this.mode||"scale"===this.mode){const e=.99,r=.2;"X"===n.name&&Math.abs(ye.copy(De).applyQuaternion(t).dot(this.eye))>e&&(n.scale.set(1e-10,1e-10,1e-10),n.visible=!1),"Y"===n.name&&Math.abs(ye.copy(Oe).applyQuaternion(t).dot(this.eye))>e&&(n.scale.set(1e-10,1e-10,1e-10),n.visible=!1),"Z"===n.name&&Math.abs(ye.copy(Be).applyQuaternion(t).dot(this.eye))>e&&(n.scale.set(1e-10,1e-10,1e-10),n.visible=!1),"XY"===n.name&&Math.abs(ye.copy(Be).applyQuaternion(t).dot(this.eye))<r&&(n.scale.set(1e-10,1e-10,1e-10),n.visible=!1),"YZ"===n.name&&Math.abs(ye.copy(De).applyQuaternion(t).dot(this.eye))<r&&(n.scale.set(1e-10,1e-10,1e-10),n.visible=!1),"XZ"===n.name&&Math.abs(ye.copy(Oe).applyQuaternion(t).dot(this.eye))<r&&(n.scale.set(1e-10,1e-10,1e-10),n.visible=!1)}else"rotate"===this.mode&&(Ee.copy(t),ye.copy(this.eye).applyQuaternion(ce.copy(t).invert()),-1!==n.name.search("E")&&n.quaternion.setFromRotationMatrix(Ce.lookAt(this.eye,Se,Oe)),"X"===n.name&&(ce.setFromAxisAngle(De,Math.atan2(-ye.y,ye.z)),ce.multiplyQuaternions(Ee,ce),n.quaternion.copy(ce)),"Y"===n.name&&(ce.setFromAxisAngle(Oe,Math.atan2(ye.x,ye.z)),ce.multiplyQuaternions(Ee,ce),n.quaternion.copy(ce)),"Z"===n.name&&(ce.setFromAxisAngle(Be,Math.atan2(ye.y,ye.x)),ce.multiplyQuaternions(Ee,ce),n.quaternion.copy(ce)));n.visible=n.visible&&(-1===n.name.indexOf("X")||this.showX),n.visible=n.visible&&(-1===n.name.indexOf("Y")||this.showY),n.visible=n.visible&&(-1===n.name.indexOf("Z")||this.showZ),n.visible=n.visible&&(-1===n.name.indexOf("E")||this.showX&&this.showY&&this.showZ),n.material._color=n.material._color||n.material.color.clone(),n.material._opacity=n.material._opacity||n.material.opacity,n.material.color.copy(n.material._color),n.material.opacity=n.material._opacity,this.enabled&&this.axis&&(n.name===this.axis||this.axis.split("").some((function(e){return n.name===e})))&&(n.material.color.setHex(16776960),n.material.opacity=1)}else n.visible=!1,"AXIS"===n.name?(n.visible=!!this.axis,"X"===this.axis&&(ce.setFromEuler(be.set(0,0,0)),n.quaternion.copy(t).multiply(ce),Math.abs(ye.copy(De).applyQuaternion(t).dot(this.eye))>.9&&(n.visible=!1)),"Y"===this.axis&&(ce.setFromEuler(be.set(0,0,Math.PI/2)),n.quaternion.copy(t).multiply(ce),Math.abs(ye.copy(Oe).applyQuaternion(t).dot(this.eye))>.9&&(n.visible=!1)),"Z"===this.axis&&(ce.setFromEuler(be.set(0,Math.PI/2,0)),n.quaternion.copy(t).multiply(ce),Math.abs(ye.copy(Be).applyQuaternion(t).dot(this.eye))>.9&&(n.visible=!1)),"XYZE"===this.axis&&(ce.setFromEuler(be.set(0,Math.PI/2,0)),ye.copy(this.rotationAxis),n.quaternion.setFromRotationMatrix(Ce.lookAt(Se,ye,Oe)),n.quaternion.multiply(ce),n.visible=this.dragging),"E"===this.axis&&(n.visible=!1)):"START"===n.name?(n.position.copy(this.worldPositionStart),n.visible=this.dragging):"END"===n.name?(n.position.copy(this.worldPosition),n.visible=this.dragging):"DELTA"===n.name?(n.position.copy(this.worldPositionStart),n.quaternion.copy(this.worldQuaternionStart),le.set(1e-10,1e-10,1e-10).add(this.worldPositionStart).sub(this.worldPosition).multiplyScalar(-1),le.applyQuaternion(this.worldQuaternionStart.clone().invert()),n.scale.copy(le),n.visible=this.dragging):(n.quaternion.copy(t),this.dragging?n.position.copy(this.worldPositionStart):n.position.copy(this.worldPosition),this.axis&&(n.visible=-1!==this.axis.search(n.name)))}super.updateMatrixWorld(e)}}class He extends t.Mesh{constructor(){super(new t.PlaneGeometry(1e5,1e5,2,2),new t.MeshBasicMaterial({visible:!1,wireframe:!0,side:t.DoubleSide,transparent:!0,opacity:.1,toneMapped:!1})),this.isTransformControlsPlane=!0,this.type="TransformControlsPlane"}updateMatrixWorld(e){let t=this.space;switch(this.position.copy(this.worldPosition),"scale"===this.mode&&(t="local"),Ne.copy(De).applyQuaternion("local"===t?this.worldQuaternion:Re),Ie.copy(Oe).applyQuaternion("local"===t?this.worldQuaternion:Re),Fe.copy(Be).applyQuaternion("local"===t?this.worldQuaternion:Re),ye.copy(Ie),this.mode){case"translate":case"scale":switch(this.axis){case"X":ye.copy(this.eye).cross(Ne),Le.copy(Ne).cross(ye);break;case"Y":ye.copy(this.eye).cross(Ie),Le.copy(Ie).cross(ye);break;case"Z":ye.copy(this.eye).cross(Fe),Le.copy(Fe).cross(ye);break;case"XY":Le.copy(Fe);break;case"YZ":Le.copy(Ne);break;case"XZ":ye.copy(Fe),Le.copy(Ie);break;case"XYZ":case"E":Le.set(0,0,0)}break;default:Le.set(0,0,0)}0===Le.length()?this.quaternion.copy(this.cameraQuaternion):(Pe.lookAt(le.set(0,0,0),Le,ye),this.quaternion.setFromRotationMatrix(Pe)),super.updateMatrixWorld(e)}}const ke={name:"CopyShader",uniforms:{tDiffuse:{value:null},opacity:{value:1}},vertexShader:"\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform float opacity;\n\n\t\tuniform sampler2D tDiffuse;\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvec4 texel = texture2D( tDiffuse, vUv );\n\t\t\tgl_FragColor = opacity * texel;\n\n\n\t\t}"};class Ge{constructor(){this.isPass=!0,this.enabled=!0,this.needsSwap=!0,this.clear=!1,this.renderToScreen=!1}setSize(){}render(){console.error("THREE.Pass: .render() must be implemented in derived pass.")}dispose(){}}const ze=new t.OrthographicCamera(-1,1,1,-1,0,1);class je extends t.BufferGeometry{constructor(){super(),this.setAttribute("position",new t.Float32BufferAttribute([-1,3,0,-1,-1,0,3,-1,0],3)),this.setAttribute("uv",new t.Float32BufferAttribute([0,2,0,0,2,0],2))}}const We=new je;class Xe{constructor(e){this._mesh=new t.Mesh(We,e)}dispose(){this._mesh.geometry.dispose()}render(e){e.render(this._mesh,ze)}get material(){return this._mesh.material}set material(e){this._mesh.material=e}}class Ve extends Ge{constructor(e,r){super(),this.textureID=void 0!==r?r:"tDiffuse",e instanceof t.ShaderMaterial?(this.uniforms=e.uniforms,this.material=e):e&&(this.uniforms=t.UniformsUtils.clone(e.uniforms),this.material=new t.ShaderMaterial({name:void 0!==e.name?e.name:"unspecified",defines:Object.assign({},e.defines),uniforms:this.uniforms,vertexShader:e.vertexShader,fragmentShader:e.fragmentShader})),this.fsQuad=new Xe(this.material)}render(e,t,r){this.uniforms[this.textureID]&&(this.uniforms[this.textureID].value=r.texture),this.fsQuad.material=this.material,this.renderToScreen?(e.setRenderTarget(null),this.fsQuad.render(e)):(e.setRenderTarget(t),this.clear&&e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil),this.fsQuad.render(e))}dispose(){this.material.dispose(),this.fsQuad.dispose()}}class Ye extends Ge{constructor(e,t){super(),this.scene=e,this.camera=t,this.clear=!0,this.needsSwap=!1,this.inverse=!1}render(e,t,r){const n=e.getContext(),s=e.state;let i,o;s.buffers.color.setMask(!1),s.buffers.depth.setMask(!1),s.buffers.color.setLocked(!0),s.buffers.depth.setLocked(!0),this.inverse?(i=0,o=1):(i=1,o=0),s.buffers.stencil.setTest(!0),s.buffers.stencil.setOp(n.REPLACE,n.REPLACE,n.REPLACE),s.buffers.stencil.setFunc(n.ALWAYS,i,4294967295),s.buffers.stencil.setClear(o),s.buffers.stencil.setLocked(!0),e.setRenderTarget(r),this.clear&&e.clear(),e.render(this.scene,this.camera),e.setRenderTarget(t),this.clear&&e.clear(),e.render(this.scene,this.camera),s.buffers.color.setLocked(!1),s.buffers.depth.setLocked(!1),s.buffers.color.setMask(!0),s.buffers.depth.setMask(!0),s.buffers.stencil.setLocked(!1),s.buffers.stencil.setFunc(n.EQUAL,1,4294967295),s.buffers.stencil.setOp(n.KEEP,n.KEEP,n.KEEP),s.buffers.stencil.setLocked(!0)}}class Qe extends Ge{constructor(){super(),this.needsSwap=!1}render(e){e.state.buffers.stencil.setLocked(!1),e.state.buffers.stencil.setTest(!1)}}class qe extends Ge{constructor(e,r,n,s){super(),this.renderScene=r,this.renderCamera=n,this.selectedObjects=void 0!==s?s:[],this.visibleEdgeColor=new t.Color(1,1,1),this.hiddenEdgeColor=new t.Color(.1,.04,.02),this.edgeGlow=0,this.usePatternTexture=!1,this.edgeThickness=1,this.edgeStrength=3,this.downSampleRatio=2,this.pulsePeriod=0,this._visibilityCache=new Map,this.resolution=void 0!==e?new t.Vector2(e.x,e.y):new t.Vector2(256,256);const i=Math.round(this.resolution.x/this.downSampleRatio),o=Math.round(this.resolution.y/this.downSampleRatio);this.renderTargetMaskBuffer=new t.WebGLRenderTarget(this.resolution.x,this.resolution.y),this.renderTargetMaskBuffer.texture.name="OutlinePass.mask",this.renderTargetMaskBuffer.texture.generateMipmaps=!1,this.depthMaterial=new t.MeshDepthMaterial,this.depthMaterial.side=t.DoubleSide,this.depthMaterial.depthPacking=t.RGBADepthPacking,this.depthMaterial.blending=t.NoBlending,this.prepareMaskMaterial=this.getPrepareMaskMaterial(),this.prepareMaskMaterial.side=t.DoubleSide,this.prepareMaskMaterial.fragmentShader=function(e,t){const r=t.isPerspectiveCamera?"perspective":"orthographic";return e.replace(/DEPTH_TO_VIEW_Z/g,r+"DepthToViewZ")}(this.prepareMaskMaterial.fragmentShader,this.renderCamera),this.renderTargetDepthBuffer=new t.WebGLRenderTarget(this.resolution.x,this.resolution.y,{type:t.HalfFloatType}),this.renderTargetDepthBuffer.texture.name="OutlinePass.depth",this.renderTargetDepthBuffer.texture.generateMipmaps=!1,this.renderTargetMaskDownSampleBuffer=new t.WebGLRenderTarget(i,o,{type:t.HalfFloatType}),this.renderTargetMaskDownSampleBuffer.texture.name="OutlinePass.depthDownSample",this.renderTargetMaskDownSampleBuffer.texture.generateMipmaps=!1,this.renderTargetBlurBuffer1=new t.WebGLRenderTarget(i,o,{type:t.HalfFloatType}),this.renderTargetBlurBuffer1.texture.name="OutlinePass.blur1",this.renderTargetBlurBuffer1.texture.generateMipmaps=!1,this.renderTargetBlurBuffer2=new t.WebGLRenderTarget(Math.round(i/2),Math.round(o/2),{type:t.HalfFloatType}),this.renderTargetBlurBuffer2.texture.name="OutlinePass.blur2",this.renderTargetBlurBuffer2.texture.generateMipmaps=!1,this.edgeDetectionMaterial=this.getEdgeDetectionMaterial(),this.renderTargetEdgeBuffer1=new t.WebGLRenderTarget(i,o,{type:t.HalfFloatType}),this.renderTargetEdgeBuffer1.texture.name="OutlinePass.edge1",this.renderTargetEdgeBuffer1.texture.generateMipmaps=!1,this.renderTargetEdgeBuffer2=new t.WebGLRenderTarget(Math.round(i/2),Math.round(o/2),{type:t.HalfFloatType}),this.renderTargetEdgeBuffer2.texture.name="OutlinePass.edge2",this.renderTargetEdgeBuffer2.texture.generateMipmaps=!1;this.separableBlurMaterial1=this.getSeperableBlurMaterial(4),this.separableBlurMaterial1.uniforms.texSize.value.set(i,o),this.separableBlurMaterial1.uniforms.kernelRadius.value=1,this.separableBlurMaterial2=this.getSeperableBlurMaterial(4),this.separableBlurMaterial2.uniforms.texSize.value.set(Math.round(i/2),Math.round(o/2)),this.separableBlurMaterial2.uniforms.kernelRadius.value=4,this.overlayMaterial=this.getOverlayMaterial();const a=ke;this.copyUniforms=t.UniformsUtils.clone(a.uniforms),this.materialCopy=new t.ShaderMaterial({uniforms:this.copyUniforms,vertexShader:a.vertexShader,fragmentShader:a.fragmentShader,blending:t.NoBlending,depthTest:!1,depthWrite:!1}),this.enabled=!0,this.needsSwap=!1,this._oldClearColor=new t.Color,this.oldClearAlpha=1,this.fsQuad=new Xe(null),this.tempPulseColor1=new t.Color,this.tempPulseColor2=new t.Color,this.textureMatrix=new t.Matrix4}dispose(){this.renderTargetMaskBuffer.dispose(),this.renderTargetDepthBuffer.dispose(),this.renderTargetMaskDownSampleBuffer.dispose(),this.renderTargetBlurBuffer1.dispose(),this.renderTargetBlurBuffer2.dispose(),this.renderTargetEdgeBuffer1.dispose(),this.renderTargetEdgeBuffer2.dispose(),this.depthMaterial.dispose(),this.prepareMaskMaterial.dispose(),this.edgeDetectionMaterial.dispose(),this.separableBlurMaterial1.dispose(),this.separableBlurMaterial2.dispose(),this.overlayMaterial.dispose(),this.materialCopy.dispose(),this.fsQuad.dispose()}setSize(e,t){this.renderTargetMaskBuffer.setSize(e,t),this.renderTargetDepthBuffer.setSize(e,t);let r=Math.round(e/this.downSampleRatio),n=Math.round(t/this.downSampleRatio);this.renderTargetMaskDownSampleBuffer.setSize(r,n),this.renderTargetBlurBuffer1.setSize(r,n),this.renderTargetEdgeBuffer1.setSize(r,n),this.separableBlurMaterial1.uniforms.texSize.value.set(r,n),r=Math.round(r/2),n=Math.round(n/2),this.renderTargetBlurBuffer2.setSize(r,n),this.renderTargetEdgeBuffer2.setSize(r,n),this.separableBlurMaterial2.uniforms.texSize.value.set(r,n)}changeVisibilityOfSelectedObjects(e){const t=this._visibilityCache;function r(r){r.isMesh&&(!0===e?r.visible=t.get(r):(t.set(r,r.visible),r.visible=e))}for(let e=0;e<this.selectedObjects.length;e++){this.selectedObjects[e].traverse(r)}}changeVisibilityOfNonSelectedObjects(e){const t=this._visibilityCache,r=[];function n(e){e.isMesh&&r.push(e)}for(let e=0;e<this.selectedObjects.length;e++){this.selectedObjects[e].traverse(n)}this.renderScene.traverse((function(n){if(n.isMesh||n.isSprite){let s=!1;for(let e=0;e<r.length;e++){if(r[e].id===n.id){s=!0;break}}if(!1===s){const r=n.visible;!1!==e&&!0!==t.get(n)||(n.visible=e),t.set(n,r)}}else(n.isPoints||n.isLine)&&(!0===e?n.visible=t.get(n):(t.set(n,n.visible),n.visible=e))}))}updateTextureMatrix(){this.textureMatrix.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),this.textureMatrix.multiply(this.renderCamera.projectionMatrix),this.textureMatrix.multiply(this.renderCamera.matrixWorldInverse)}render(e,t,r,n,s){if(this.selectedObjects.length>0){e.getClearColor(this._oldClearColor),this.oldClearAlpha=e.getClearAlpha();const t=e.autoClear;e.autoClear=!1,s&&e.state.buffers.stencil.setTest(!1),e.setClearColor(16777215,1),this.changeVisibilityOfSelectedObjects(!1);const n=this.renderScene.background;if(this.renderScene.background=null,this.renderScene.overrideMaterial=this.depthMaterial,e.setRenderTarget(this.renderTargetDepthBuffer),e.clear(),e.render(this.renderScene,this.renderCamera),this.changeVisibilityOfSelectedObjects(!0),this._visibilityCache.clear(),this.updateTextureMatrix(),this.changeVisibilityOfNonSelectedObjects(!1),this.renderScene.overrideMaterial=this.prepareMaskMaterial,this.prepareMaskMaterial.uniforms.cameraNearFar.value.set(this.renderCamera.near,this.renderCamera.far),this.prepareMaskMaterial.uniforms.depthTexture.value=this.renderTargetDepthBuffer.texture,this.prepareMaskMaterial.uniforms.textureMatrix.value=this.textureMatrix,e.setRenderTarget(this.renderTargetMaskBuffer),e.clear(),e.render(this.renderScene,this.renderCamera),this.renderScene.overrideMaterial=null,this.changeVisibilityOfNonSelectedObjects(!0),this._visibilityCache.clear(),this.renderScene.background=n,this.fsQuad.material=this.materialCopy,this.copyUniforms.tDiffuse.value=this.renderTargetMaskBuffer.texture,e.setRenderTarget(this.renderTargetMaskDownSampleBuffer),e.clear(),this.fsQuad.render(e),this.tempPulseColor1.copy(this.visibleEdgeColor),this.tempPulseColor2.copy(this.hiddenEdgeColor),this.pulsePeriod>0){const e=.625+.75*Math.cos(.01*performance.now()/this.pulsePeriod)/2;this.tempPulseColor1.multiplyScalar(e),this.tempPulseColor2.multiplyScalar(e)}this.fsQuad.material=this.edgeDetectionMaterial,this.edgeDetectionMaterial.uniforms.maskTexture.value=this.renderTargetMaskDownSampleBuffer.texture,this.edgeDetectionMaterial.uniforms.texSize.value.set(this.renderTargetMaskDownSampleBuffer.width,this.renderTargetMaskDownSampleBuffer.height),this.edgeDetectionMaterial.uniforms.visibleEdgeColor.value=this.tempPulseColor1,this.edgeDetectionMaterial.uniforms.hiddenEdgeColor.value=this.tempPulseColor2,e.setRenderTarget(this.renderTargetEdgeBuffer1),e.clear(),this.fsQuad.render(e),this.fsQuad.material=this.separableBlurMaterial1,this.separableBlurMaterial1.uniforms.colorTexture.value=this.renderTargetEdgeBuffer1.texture,this.separableBlurMaterial1.uniforms.direction.value=qe.BlurDirectionX,this.separableBlurMaterial1.uniforms.kernelRadius.value=this.edgeThickness,e.setRenderTarget(this.renderTargetBlurBuffer1),e.clear(),this.fsQuad.render(e),this.separableBlurMaterial1.uniforms.colorTexture.value=this.renderTargetBlurBuffer1.texture,this.separableBlurMaterial1.uniforms.direction.value=qe.BlurDirectionY,e.setRenderTarget(this.renderTargetEdgeBuffer1),e.clear(),this.fsQuad.render(e),this.fsQuad.material=this.separableBlurMaterial2,this.separableBlurMaterial2.uniforms.colorTexture.value=this.renderTargetEdgeBuffer1.texture,this.separableBlurMaterial2.uniforms.direction.value=qe.BlurDirectionX,e.setRenderTarget(this.renderTargetBlurBuffer2),e.clear(),this.fsQuad.render(e),this.separableBlurMaterial2.uniforms.colorTexture.value=this.renderTargetBlurBuffer2.texture,this.separableBlurMaterial2.uniforms.direction.value=qe.BlurDirectionY,e.setRenderTarget(this.renderTargetEdgeBuffer2),e.clear(),this.fsQuad.render(e),this.fsQuad.material=this.overlayMaterial,this.overlayMaterial.uniforms.maskTexture.value=this.renderTargetMaskBuffer.texture,this.overlayMaterial.uniforms.edgeTexture1.value=this.renderTargetEdgeBuffer1.texture,this.overlayMaterial.uniforms.edgeTexture2.value=this.renderTargetEdgeBuffer2.texture,this.overlayMaterial.uniforms.patternTexture.value=this.patternTexture,this.overlayMaterial.uniforms.edgeStrength.value=this.edgeStrength,this.overlayMaterial.uniforms.edgeGlow.value=this.edgeGlow,this.overlayMaterial.uniforms.usePatternTexture.value=this.usePatternTexture,s&&e.state.buffers.stencil.setTest(!0),e.setRenderTarget(r),this.fsQuad.render(e),e.setClearColor(this._oldClearColor,this.oldClearAlpha),e.autoClear=t}this.renderToScreen&&(this.fsQuad.material=this.materialCopy,this.copyUniforms.tDiffuse.value=r.texture,e.setRenderTarget(null),this.fsQuad.render(e))}getPrepareMaskMaterial(){return new t.ShaderMaterial({uniforms:{depthTexture:{value:null},cameraNearFar:{value:new t.Vector2(.5,.5)},textureMatrix:{value:null}},vertexShader:"#include <morphtarget_pars_vertex>\n\t\t\t\t#include <skinning_pars_vertex>\n\n\t\t\t\tvarying vec4 projTexCoord;\n\t\t\t\tvarying vec4 vPosition;\n\t\t\t\tuniform mat4 textureMatrix;\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\t#include <skinbase_vertex>\n\t\t\t\t\t#include <begin_vertex>\n\t\t\t\t\t#include <morphtarget_vertex>\n\t\t\t\t\t#include <skinning_vertex>\n\t\t\t\t\t#include <project_vertex>\n\n\t\t\t\t\tvPosition = mvPosition;\n\n\t\t\t\t\tvec4 worldPosition = vec4( transformed, 1.0 );\n\n\t\t\t\t\t#ifdef USE_INSTANCING\n\n\t\t\t\t\t\tworldPosition = instanceMatrix * worldPosition;\n\n\t\t\t\t\t#endif\n\n\t\t\t\t\tworldPosition = modelMatrix * worldPosition;\n\n\t\t\t\t\tprojTexCoord = textureMatrix * worldPosition;\n\n\t\t\t\t}",fragmentShader:"#include <packing>\n\t\t\t\tvarying vec4 vPosition;\n\t\t\t\tvarying vec4 projTexCoord;\n\t\t\t\tuniform sampler2D depthTexture;\n\t\t\t\tuniform vec2 cameraNearFar;\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tfloat depth = unpackRGBAToDepth(texture2DProj( depthTexture, projTexCoord ));\n\t\t\t\t\tfloat viewZ = - DEPTH_TO_VIEW_Z( depth, cameraNearFar.x, cameraNearFar.y );\n\t\t\t\t\tfloat depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;\n\t\t\t\t\tgl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);\n\n\t\t\t\t}"})}getEdgeDetectionMaterial(){return new t.ShaderMaterial({uniforms:{maskTexture:{value:null},texSize:{value:new t.Vector2(.5,.5)},visibleEdgeColor:{value:new t.Vector3(1,1,1)},hiddenEdgeColor:{value:new t.Vector3(1,1,1)}},vertexShader:"varying vec2 vUv;\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\t\t\t\t}",fragmentShader:"varying vec2 vUv;\n\n\t\t\t\tuniform sampler2D maskTexture;\n\t\t\t\tuniform vec2 texSize;\n\t\t\t\tuniform vec3 visibleEdgeColor;\n\t\t\t\tuniform vec3 hiddenEdgeColor;\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tvec2 invSize = 1.0 / texSize;\n\t\t\t\t\tvec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize);\n\t\t\t\t\tvec4 c1 = texture2D( maskTexture, vUv + uvOffset.xy);\n\t\t\t\t\tvec4 c2 = texture2D( maskTexture, vUv - uvOffset.xy);\n\t\t\t\t\tvec4 c3 = texture2D( maskTexture, vUv + uvOffset.yw);\n\t\t\t\t\tvec4 c4 = texture2D( maskTexture, vUv - uvOffset.yw);\n\t\t\t\t\tfloat diff1 = (c1.r - c2.r)*0.5;\n\t\t\t\t\tfloat diff2 = (c3.r - c4.r)*0.5;\n\t\t\t\t\tfloat d = length( vec2(diff1, diff2) );\n\t\t\t\t\tfloat a1 = min(c1.g, c2.g);\n\t\t\t\t\tfloat a2 = min(c3.g, c4.g);\n\t\t\t\t\tfloat visibilityFactor = min(a1, a2);\n\t\t\t\t\tvec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;\n\t\t\t\t\tgl_FragColor = vec4(edgeColor, 1.0) * vec4(d);\n\t\t\t\t}"})}getSeperableBlurMaterial(e){return new t.ShaderMaterial({defines:{MAX_RADIUS:e},uniforms:{colorTexture:{value:null},texSize:{value:new t.Vector2(.5,.5)},direction:{value:new t.Vector2(.5,.5)},kernelRadius:{value:1}},vertexShader:"varying vec2 vUv;\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\t\t\t\t}",fragmentShader:"#include <common>\n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tuniform sampler2D colorTexture;\n\t\t\t\tuniform vec2 texSize;\n\t\t\t\tuniform vec2 direction;\n\t\t\t\tuniform float kernelRadius;\n\n\t\t\t\tfloat gaussianPdf(in float x, in float sigma) {\n\t\t\t\t\treturn 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tvec2 invSize = 1.0 / texSize;\n\t\t\t\t\tfloat sigma = kernelRadius/2.0;\n\t\t\t\t\tfloat weightSum = gaussianPdf(0.0, sigma);\n\t\t\t\t\tvec4 diffuseSum = texture2D( colorTexture, vUv) * weightSum;\n\t\t\t\t\tvec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS);\n\t\t\t\t\tvec2 uvOffset = delta;\n\t\t\t\t\tfor( int i = 1; i <= MAX_RADIUS; i ++ ) {\n\t\t\t\t\t\tfloat x = kernelRadius * float(i) / float(MAX_RADIUS);\n\t\t\t\t\t\tfloat w = gaussianPdf(x, sigma);\n\t\t\t\t\t\tvec4 sample1 = texture2D( colorTexture, vUv + uvOffset);\n\t\t\t\t\t\tvec4 sample2 = texture2D( colorTexture, vUv - uvOffset);\n\t\t\t\t\t\tdiffuseSum += ((sample1 + sample2) * w);\n\t\t\t\t\t\tweightSum += (2.0 * w);\n\t\t\t\t\t\tuvOffset += delta;\n\t\t\t\t\t}\n\t\t\t\t\tgl_FragColor = diffuseSum/weightSum;\n\t\t\t\t}"})}getOverlayMaterial(){return new t.ShaderMaterial({uniforms:{maskTexture:{value:null},edgeTexture1:{value:null},edgeTexture2:{value:null},patternTexture:{value:null},edgeStrength:{value:1},edgeGlow:{value:1},usePatternTexture:{value:0}},vertexShader:"varying vec2 vUv;\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\t\t\t\t}",fragmentShader:"varying vec2 vUv;\n\n\t\t\t\tuniform sampler2D maskTexture;\n\t\t\t\tuniform sampler2D edgeTexture1;\n\t\t\t\tuniform sampler2D edgeTexture2;\n\t\t\t\tuniform sampler2D patternTexture;\n\t\t\t\tuniform float edgeStrength;\n\t\t\t\tuniform float edgeGlow;\n\t\t\t\tuniform bool usePatternTexture;\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tvec4 edgeValue1 = texture2D(edgeTexture1, vUv);\n\t\t\t\t\tvec4 edgeValue2 = texture2D(edgeTexture2, vUv);\n\t\t\t\t\tvec4 maskColor = texture2D(maskTexture, vUv);\n\t\t\t\t\tvec4 patternColor = texture2D(patternTexture, 6.0 * vUv);\n\t\t\t\t\tfloat visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5;\n\t\t\t\t\tvec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow;\n\t\t\t\t\tvec4 finalColor = edgeStrength * maskColor.r * edgeValue;\n\t\t\t\t\tif(usePatternTexture)\n\t\t\t\t\t\tfinalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);\n\t\t\t\t\tgl_FragColor = finalColor;\n\t\t\t\t}",blending:t.AdditiveBlending,depthTest:!1,depthWrite:!1,transparent:!0})}}qe.BlurDirectionX=new t.Vector2(1,0),qe.BlurDirectionY=new t.Vector2(0,1);const Ke={name:"SMAAEdgesShader",defines:{SMAA_THRESHOLD:"0.1"},uniforms:{tDiffuse:{value:null},resolution:{value:new t.Vector2(1/1024,1/512)}},vertexShader:"\n\n\t\tuniform vec2 resolution;\n\n\t\tvarying vec2 vUv;\n\t\tvarying vec4 vOffset[ 3 ];\n\n\t\tvoid SMAAEdgeDetectionVS( vec2 texcoord ) {\n\t\t\tvOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -1.0, 0.0, 0.0,  1.0 ); // WebGL port note: Changed sign in W component\n\t\t\tvOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4(  1.0, 0.0, 0.0, -1.0 ); // WebGL port note: Changed sign in W component\n\t\t\tvOffset[ 2 ] = texcoord.xyxy + resolution.xyxy * vec4( -2.0, 0.0, 0.0,  2.0 ); // WebGL port note: Changed sign in W component\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\n\t\t\tSMAAEdgeDetectionVS( vUv );\n\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform sampler2D tDiffuse;\n\n\t\tvarying vec2 vUv;\n\t\tvarying vec4 vOffset[ 3 ];\n\n\t\tvec4 SMAAColorEdgeDetectionPS( vec2 texcoord, vec4 offset[3], sampler2D colorTex ) {\n\t\t\tvec2 threshold = vec2( SMAA_THRESHOLD, SMAA_THRESHOLD );\n\n\t\t\t// Calculate color deltas:\n\t\t\tvec4 delta;\n\t\t\tvec3 C = texture2D( colorTex, texcoord ).rgb;\n\n\t\t\tvec3 Cleft = texture2D( colorTex, offset[0].xy ).rgb;\n\t\t\tvec3 t = abs( C - Cleft );\n\t\t\tdelta.x = max( max( t.r, t.g ), t.b );\n\n\t\t\tvec3 Ctop = texture2D( colorTex, offset[0].zw ).rgb;\n\t\t\tt = abs( C - Ctop );\n\t\t\tdelta.y = max( max( t.r, t.g ), t.b );\n\n\t\t\t// We do the usual threshold:\n\t\t\tvec2 edges = step( threshold, delta.xy );\n\n\t\t\t// Then discard if there is no edge:\n\t\t\tif ( dot( edges, vec2( 1.0, 1.0 ) ) == 0.0 )\n\t\t\t\tdiscard;\n\n\t\t\t// Calculate right and bottom deltas:\n\t\t\tvec3 Cright = texture2D( colorTex, offset[1].xy ).rgb;\n\t\t\tt = abs( C - Cright );\n\t\t\tdelta.z = max( max( t.r, t.g ), t.b );\n\n\t\t\tvec3 Cbottom  = texture2D( colorTex, offset[1].zw ).rgb;\n\t\t\tt = abs( C - Cbottom );\n\t\t\tdelta.w = max( max( t.r, t.g ), t.b );\n\n\t\t\t// Calculate the maximum delta in the direct neighborhood:\n\t\t\tfloat maxDelta = max( max( max( delta.x, delta.y ), delta.z ), delta.w );\n\n\t\t\t// Calculate left-left and top-top deltas:\n\t\t\tvec3 Cleftleft  = texture2D( colorTex, offset[2].xy ).rgb;\n\t\t\tt = abs( C - Cleftleft );\n\t\t\tdelta.z = max( max( t.r, t.g ), t.b );\n\n\t\t\tvec3 Ctoptop = texture2D( colorTex, offset[2].zw ).rgb;\n\t\t\tt = abs( C - Ctoptop );\n\t\t\tdelta.w = max( max( t.r, t.g ), t.b );\n\n\t\t\t// Calculate the final maximum delta:\n\t\t\tmaxDelta = max( max( maxDelta, delta.z ), delta.w );\n\n\t\t\t// Local contrast adaptation in action:\n\t\t\tedges.xy *= step( 0.5 * maxDelta, delta.xy );\n\n\t\t\treturn vec4( edges, 0.0, 0.0 );\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = SMAAColorEdgeDetectionPS( vUv, vOffset, tDiffuse );\n\n\t\t}"},Ze={name:"SMAAWeightsShader",defines:{SMAA_MAX_SEARCH_STEPS:"8",SMAA_AREATEX_MAX_DISTANCE:"16",SMAA_AREATEX_PIXEL_SIZE:"( 1.0 / vec2( 160.0, 560.0 ) )",SMAA_AREATEX_SUBTEX_SIZE:"( 1.0 / 7.0 )"},uniforms:{tDiffuse:{value:null},tArea:{value:null},tSearch:{value:null},resolution:{value:new t.Vector2(1/1024,1/512)}},vertexShader:"\n\n\t\tuniform vec2 resolution;\n\n\t\tvarying vec2 vUv;\n\t\tvarying vec4 vOffset[ 3 ];\n\t\tvarying vec2 vPixcoord;\n\n\t\tvoid SMAABlendingWeightCalculationVS( vec2 texcoord ) {\n\t\t\tvPixcoord = texcoord / resolution;\n\n\t\t\t// We will use these offsets for the searches later on (see @PSEUDO_GATHER4):\n\t\t\tvOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -0.25, 0.125, 1.25, 0.125 ); // WebGL port note: Changed sign in Y and W components\n\t\t\tvOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4( -0.125, 0.25, -0.125, -1.25 ); // WebGL port note: Changed sign in Y and W components\n\n\t\t\t// And these for the searches, they indicate the ends of the loops:\n\t\t\tvOffset[ 2 ] = vec4( vOffset[ 0 ].xz, vOffset[ 1 ].yw ) + vec4( -2.0, 2.0, -2.0, 2.0 ) * resolution.xxyy * float( SMAA_MAX_SEARCH_STEPS );\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\n\t\t\tSMAABlendingWeightCalculationVS( vUv );\n\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\t#define SMAASampleLevelZeroOffset( tex, coord, offset ) texture2D( tex, coord + float( offset ) * resolution, 0.0 )\n\n\t\tuniform sampler2D tDiffuse;\n\t\tuniform sampler2D tArea;\n\t\tuniform sampler2D tSearch;\n\t\tuniform vec2 resolution;\n\n\t\tvarying vec2 vUv;\n\t\tvarying vec4 vOffset[3];\n\t\tvarying vec2 vPixcoord;\n\n\t\t#if __VERSION__ == 100\n\t\tvec2 round( vec2 x ) {\n\t\t\treturn sign( x ) * floor( abs( x ) + 0.5 );\n\t\t}\n\t\t#endif\n\n\t\tfloat SMAASearchLength( sampler2D searchTex, vec2 e, float bias, float scale ) {\n\t\t\t// Not required if searchTex accesses are set to point:\n\t\t\t// float2 SEARCH_TEX_PIXEL_SIZE = 1.0 / float2(66.0, 33.0);\n\t\t\t// e = float2(bias, 0.0) + 0.5 * SEARCH_TEX_PIXEL_SIZE +\n\t\t\t//     e * float2(scale, 1.0) * float2(64.0, 32.0) * SEARCH_TEX_PIXEL_SIZE;\n\t\t\te.r = bias + e.r * scale;\n\t\t\treturn 255.0 * texture2D( searchTex, e, 0.0 ).r;\n\t\t}\n\n\t\tfloat SMAASearchXLeft( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {\n\t\t\t/**\n\t\t\t\t* @PSEUDO_GATHER4\n\t\t\t\t* This texcoord has been offset by (-0.25, -0.125) in the vertex shader to\n\t\t\t\t* sample between edge, thus fetching four edges in a row.\n\t\t\t\t* Sampling with different offsets in each direction allows to disambiguate\n\t\t\t\t* which edges are active from the four fetched ones.\n\t\t\t\t*/\n\t\t\tvec2 e = vec2( 0.0, 1.0 );\n\n\t\t\tfor ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) { // WebGL port note: Changed while to for\n\t\t\t\te = texture2D( edgesTex, texcoord, 0.0 ).rg;\n\t\t\t\ttexcoord -= vec2( 2.0, 0.0 ) * resolution;\n\t\t\t\tif ( ! ( texcoord.x > end && e.g > 0.8281 && e.r == 0.0 ) ) break;\n\t\t\t}\n\n\t\t\t// We correct the previous (-0.25, -0.125) offset we applied:\n\t\t\ttexcoord.x += 0.25 * resolution.x;\n\n\t\t\t// The searches are bias by 1, so adjust the coords accordingly:\n\t\t\ttexcoord.x += resolution.x;\n\n\t\t\t// Disambiguate the length added by the last step:\n\t\t\ttexcoord.x += 2.0 * resolution.x; // Undo last step\n\t\t\ttexcoord.x -= resolution.x * SMAASearchLength(searchTex, e, 0.0, 0.5);\n\n\t\t\treturn texcoord.x;\n\t\t}\n\n\t\tfloat SMAASearchXRight( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {\n\t\t\tvec2 e = vec2( 0.0, 1.0 );\n\n\t\t\tfor ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) { // WebGL port note: Changed while to for\n\t\t\t\te = texture2D( edgesTex, texcoord, 0.0 ).rg;\n\t\t\t\ttexcoord += vec2( 2.0, 0.0 ) * resolution;\n\t\t\t\tif ( ! ( texcoord.x < end && e.g > 0.8281 && e.r == 0.0 ) ) break;\n\t\t\t}\n\n\t\t\ttexcoord.x -= 0.25 * resolution.x;\n\t\t\ttexcoord.x -= resolution.x;\n\t\t\ttexcoord.x -= 2.0 * resolution.x;\n\t\t\ttexcoord.x += resolution.x * SMAASearchLength( searchTex, e, 0.5, 0.5 );\n\n\t\t\treturn texcoord.x;\n\t\t}\n\n\t\tfloat SMAASearchYUp( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {\n\t\t\tvec2 e = vec2( 1.0, 0.0 );\n\n\t\t\tfor ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) { // WebGL port note: Changed while to for\n\t\t\t\te = texture2D( edgesTex, texcoord, 0.0 ).rg;\n\t\t\t\ttexcoord += vec2( 0.0, 2.0 ) * resolution; // WebGL port note: Changed sign\n\t\t\t\tif ( ! ( texcoord.y > end && e.r > 0.8281 && e.g == 0.0 ) ) break;\n\t\t\t}\n\n\t\t\ttexcoord.y -= 0.25 * resolution.y; // WebGL port note: Changed sign\n\t\t\ttexcoord.y -= resolution.y; // WebGL port note: Changed sign\n\t\t\ttexcoord.y -= 2.0 * resolution.y; // WebGL port note: Changed sign\n\t\t\ttexcoord.y += resolution.y * SMAASearchLength( searchTex, e.gr, 0.0, 0.5 ); // WebGL port note: Changed sign\n\n\t\t\treturn texcoord.y;\n\t\t}\n\n\t\tfloat SMAASearchYDown( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {\n\t\t\tvec2 e = vec2( 1.0, 0.0 );\n\n\t\t\tfor ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) { // WebGL port note: Changed while to for\n\t\t\t\te = texture2D( edgesTex, texcoord, 0.0 ).rg;\n\t\t\t\ttexcoord -= vec2( 0.0, 2.0 ) * resolution; // WebGL port note: Changed sign\n\t\t\t\tif ( ! ( texcoord.y < end && e.r > 0.8281 && e.g == 0.0 ) ) break;\n\t\t\t}\n\n\t\t\ttexcoord.y += 0.25 * resolution.y; // WebGL port note: Changed sign\n\t\t\ttexcoord.y += resolution.y; // WebGL port note: Changed sign\n\t\t\ttexcoord.y += 2.0 * resolution.y; // WebGL port note: Changed sign\n\t\t\ttexcoord.y -= resolution.y * SMAASearchLength( searchTex, e.gr, 0.5, 0.5 ); // WebGL port note: Changed sign\n\n\t\t\treturn texcoord.y;\n\t\t}\n\n\t\tvec2 SMAAArea( sampler2D areaTex, vec2 dist, float e1, float e2, float offset ) {\n\t\t\t// Rounding prevents precision errors of bilinear filtering:\n\t\t\tvec2 texcoord = float( SMAA_AREATEX_MAX_DISTANCE ) * round( 4.0 * vec2( e1, e2 ) ) + dist;\n\n\t\t\t// We do a scale and bias for mapping to texel space:\n\t\t\ttexcoord = SMAA_AREATEX_PIXEL_SIZE * texcoord + ( 0.5 * SMAA_AREATEX_PIXEL_SIZE );\n\n\t\t\t// Move to proper place, according to the subpixel offset:\n\t\t\ttexcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset;\n\n\t\t\treturn texture2D( areaTex, texcoord, 0.0 ).rg;\n\t\t}\n\n\t\tvec4 SMAABlendingWeightCalculationPS( vec2 texcoord, vec2 pixcoord, vec4 offset[ 3 ], sampler2D edgesTex, sampler2D areaTex, sampler2D searchTex, ivec4 subsampleIndices ) {\n\t\t\tvec4 weights = vec4( 0.0, 0.0, 0.0, 0.0 );\n\n\t\t\tvec2 e = texture2D( edgesTex, texcoord ).rg;\n\n\t\t\tif ( e.g > 0.0 ) { // Edge at north\n\t\t\t\tvec2 d;\n\n\t\t\t\t// Find the distance to the left:\n\t\t\t\tvec2 coords;\n\t\t\t\tcoords.x = SMAASearchXLeft( edgesTex, searchTex, offset[ 0 ].xy, offset[ 2 ].x );\n\t\t\t\tcoords.y = offset[ 1 ].y; // offset[1].y = texcoord.y - 0.25 * resolution.y (@CROSSING_OFFSET)\n\t\t\t\td.x = coords.x;\n\n\t\t\t\t// Now fetch the left crossing edges, two at a time using bilinear\n\t\t\t\t// filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to\n\t\t\t\t// discern what value each edge has:\n\t\t\t\tfloat e1 = texture2D( edgesTex, coords, 0.0 ).r;\n\n\t\t\t\t// Find the distance to the right:\n\t\t\t\tcoords.x = SMAASearchXRight( edgesTex, searchTex, offset[ 0 ].zw, offset[ 2 ].y );\n\t\t\t\td.y = coords.x;\n\n\t\t\t\t// We want the distances to be in pixel units (doing this here allow to\n\t\t\t\t// better interleave arithmetic and memory accesses):\n\t\t\t\td = d / resolution.x - pixcoord.x;\n\n\t\t\t\t// SMAAArea below needs a sqrt, as the areas texture is compressed\n\t\t\t\t// quadratically:\n\t\t\t\tvec2 sqrt_d = sqrt( abs( d ) );\n\n\t\t\t\t// Fetch the right crossing edges:\n\t\t\t\tcoords.y -= 1.0 * resolution.y; // WebGL port note: Added\n\t\t\t\tfloat e2 = SMAASampleLevelZeroOffset( edgesTex, coords, ivec2( 1, 0 ) ).r;\n\n\t\t\t\t// Ok, we know how this pattern looks like, now it is time for getting\n\t\t\t\t// the actual area:\n\t\t\t\tweights.rg = SMAAArea( areaTex, sqrt_d, e1, e2, float( subsampleIndices.y ) );\n\t\t\t}\n\n\t\t\tif ( e.r > 0.0 ) { // Edge at west\n\t\t\t\tvec2 d;\n\n\t\t\t\t// Find the distance to the top:\n\t\t\t\tvec2 coords;\n\n\t\t\t\tcoords.y = SMAASearchYUp( edgesTex, searchTex, offset[ 1 ].xy, offset[ 2 ].z );\n\t\t\t\tcoords.x = offset[ 0 ].x; // offset[1].x = texcoord.x - 0.25 * resolution.x;\n\t\t\t\td.x = coords.y;\n\n\t\t\t\t// Fetch the top crossing edges:\n\t\t\t\tfloat e1 = texture2D( edgesTex, coords, 0.0 ).g;\n\n\t\t\t\t// Find the distance to the bottom:\n\t\t\t\tcoords.y = SMAASearchYDown( edgesTex, searchTex, offset[ 1 ].zw, offset[ 2 ].w );\n\t\t\t\td.y = coords.y;\n\n\t\t\t\t// We want the distances to be in pixel units:\n\t\t\t\td = d / resolution.y - pixcoord.y;\n\n\t\t\t\t// SMAAArea below needs a sqrt, as the areas texture is compressed\n\t\t\t\t// quadratically:\n\t\t\t\tvec2 sqrt_d = sqrt( abs( d ) );\n\n\t\t\t\t// Fetch the bottom crossing edges:\n\t\t\t\tcoords.y -= 1.0 * resolution.y; // WebGL port note: Added\n\t\t\t\tfloat e2 = SMAASampleLevelZeroOffset( edgesTex, coords, ivec2( 0, 1 ) ).g;\n\n\t\t\t\t// Get the area for this direction:\n\t\t\t\tweights.ba = SMAAArea( areaTex, sqrt_d, e1, e2, float( subsampleIndices.x ) );\n\t\t\t}\n\n\t\t\treturn weights;\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = SMAABlendingWeightCalculationPS( vUv, vPixcoord, vOffset, tDiffuse, tArea, tSearch, ivec4( 0.0 ) );\n\n\t\t}"},_e={name:"SMAABlendShader",uniforms:{tDiffuse:{value:null},tColor:{value:null},resolution:{value:new t.Vector2(1/1024,1/512)}},vertexShader:"\n\n\t\tuniform vec2 resolution;\n\n\t\tvarying vec2 vUv;\n\t\tvarying vec4 vOffset[ 2 ];\n\n\t\tvoid SMAANeighborhoodBlendingVS( vec2 texcoord ) {\n\t\t\tvOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -1.0, 0.0, 0.0, 1.0 ); // WebGL port note: Changed sign in W component\n\t\t\tvOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4( 1.0, 0.0, 0.0, -1.0 ); // WebGL port note: Changed sign in W component\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\n\t\t\tSMAANeighborhoodBlendingVS( vUv );\n\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform sampler2D tDiffuse;\n\t\tuniform sampler2D tColor;\n\t\tuniform vec2 resolution;\n\n\t\tvarying vec2 vUv;\n\t\tvarying vec4 vOffset[ 2 ];\n\n\t\tvec4 SMAANeighborhoodBlendingPS( vec2 texcoord, vec4 offset[ 2 ], sampler2D colorTex, sampler2D blendTex ) {\n\t\t\t// Fetch the blending weights for current pixel:\n\t\t\tvec4 a;\n\t\t\ta.xz = texture2D( blendTex, texcoord ).xz;\n\t\t\ta.y = texture2D( blendTex, offset[ 1 ].zw ).g;\n\t\t\ta.w = texture2D( blendTex, offset[ 1 ].xy ).a;\n\n\t\t\t// Is there any blending weight with a value greater than 0.0?\n\t\t\tif ( dot(a, vec4( 1.0, 1.0, 1.0, 1.0 )) < 1e-5 ) {\n\t\t\t\treturn texture2D( colorTex, texcoord, 0.0 );\n\t\t\t} else {\n\t\t\t\t// Up to 4 lines can be crossing a pixel (one through each edge). We\n\t\t\t\t// favor blending by choosing the line with the maximum weight for each\n\t\t\t\t// direction:\n\t\t\t\tvec2 offset;\n\t\t\t\toffset.x = a.a > a.b ? a.a : -a.b; // left vs. right\n\t\t\t\toffset.y = a.g > a.r ? -a.g : a.r; // top vs. bottom // WebGL port note: Changed signs\n\n\t\t\t\t// Then we go in the direction that has the maximum weight:\n\t\t\t\tif ( abs( offset.x ) > abs( offset.y )) { // horizontal vs. vertical\n\t\t\t\t\toffset.y = 0.0;\n\t\t\t\t} else {\n\t\t\t\t\toffset.x = 0.0;\n\t\t\t\t}\n\n\t\t\t\t// Fetch the opposite color and lerp by hand:\n\t\t\t\tvec4 C = texture2D( colorTex, texcoord, 0.0 );\n\t\t\t\ttexcoord += sign( offset ) * resolution;\n\t\t\t\tvec4 Cop = texture2D( colorTex, texcoord, 0.0 );\n\t\t\t\tfloat s = abs( offset.x ) > abs( offset.y ) ? abs( offset.x ) : abs( offset.y );\n\n\t\t\t\t// WebGL port note: Added gamma correction\n\t\t\t\tC.xyz = pow(C.xyz, vec3(2.2));\n\t\t\t\tCop.xyz = pow(Cop.xyz, vec3(2.2));\n\t\t\t\tvec4 mixed = mix(C, Cop, s);\n\t\t\t\tmixed.xyz = pow(mixed.xyz, vec3(1.0 / 2.2));\n\n\t\t\t\treturn mixed;\n\t\t\t}\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = SMAANeighborhoodBlendingPS( vUv, vOffset, tColor, tDiffuse );\n\n\t\t}"};const Je={name:"OutputShader",uniforms:{tDiffuse:{value:null},toneMappingExposure:{value:1}},vertexShader:"\n\t\tprecision highp float;\n\n\t\tuniform mat4 modelViewMatrix;\n\t\tuniform mat4 projectionMatrix;\n\n\t\tattribute vec3 position;\n\t\tattribute vec2 uv;\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\t\n\t\tprecision highp float;\n\n\t\tuniform sampler2D tDiffuse;\n\n\t\t#include <tonemapping_pars_fragment>\n\t\t#include <colorspace_pars_fragment>\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = texture2D( tDiffuse, vUv );\n\n\t\t\t// tone mapping\n\n\t\t\t#ifdef LINEAR_TONE_MAPPING\n\n\t\t\t\tgl_FragColor.rgb = LinearToneMapping( gl_FragColor.rgb );\n\n\t\t\t#elif defined( REINHARD_TONE_MAPPING )\n\n\t\t\t\tgl_FragColor.rgb = ReinhardToneMapping( gl_FragColor.rgb );\n\n\t\t\t#elif defined( CINEON_TONE_MAPPING )\n\n\t\t\t\tgl_FragColor.rgb = OptimizedCineonToneMapping( gl_FragColor.rgb );\n\n\t\t\t#elif defined( ACES_FILMIC_TONE_MAPPING )\n\n\t\t\t\tgl_FragColor.rgb = ACESFilmicToneMapping( gl_FragColor.rgb );\n\n\t\t\t#elif defined( AGX_TONE_MAPPING )\n\n\t\t\t\tgl_FragColor.rgb = AgXToneMapping( gl_FragColor.rgb );\n\n\t\t\t#endif\n\n\t\t\t// color space\n\n\t\t\t#ifdef SRGB_TRANSFER\n\n\t\t\t\tgl_FragColor = sRGBTransferOETF( gl_FragColor );\n\n\t\t\t#endif\n\n\t\t}"};const $e={name:"LuminosityHighPassShader",shaderID:"luminosityHighPass",uniforms:{tDiffuse:{value:null},luminosityThreshold:{value:1},smoothWidth:{value:1},defaultColor:{value:new t.Color(0)},defaultOpacity:{value:0}},vertexShader:"\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform sampler2D tDiffuse;\n\t\tuniform vec3 defaultColor;\n\t\tuniform float defaultOpacity;\n\t\tuniform float luminosityThreshold;\n\t\tuniform float smoothWidth;\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvec4 texel = texture2D( tDiffuse, vUv );\n\n\t\t\tvec3 luma = vec3( 0.299, 0.587, 0.114 );\n\n\t\t\tfloat v = dot( texel.xyz, luma );\n\n\t\t\tvec4 outputColor = vec4( defaultColor.rgb, defaultOpacity );\n\n\t\t\tfloat alpha = smoothstep( luminosityThreshold, luminosityThreshold + smoothWidth, v );\n\n\t\t\tgl_FragColor = mix( outputColor, texel, alpha );\n\n\t\t}"};class et extends Ge{constructor(e,r,n,s){super(),this.strength=void 0!==r?r:1,this.radius=n,this.threshold=s,this.resolution=void 0!==e?new t.Vector2(e.x,e.y):new t.Vector2(256,256),this.clearColor=new t.Color(0,0,0),this.renderTargetsHorizontal=[],this.renderTargetsVertical=[],this.nMips=5;let i=Math.round(this.resolution.x/2),o=Math.round(this.resolution.y/2);this.renderTargetBright=new t.WebGLRenderTarget(i,o,{type:t.HalfFloatType}),this.renderTargetBright.texture.name="UnrealBloomPass.bright",this.renderTargetBright.texture.generateMipmaps=!1;for(let e=0;e<this.nMips;e++){const r=new t.WebGLRenderTarget(i,o,{type:t.HalfFloatType});r.texture.name="UnrealBloomPass.h"+e,r.texture.generateMipmaps=!1,this.renderTargetsHorizontal.push(r);const n=new t.WebGLRenderTarget(i,o,{type:t.HalfFloatType});n.texture.name="UnrealBloomPass.v"+e,n.texture.generateMipmaps=!1,this.renderTargetsVertical.push(n),i=Math.round(i/2),o=Math.round(o/2)}const a=$e;this.highPassUniforms=t.UniformsUtils.clone(a.uniforms),this.highPassUniforms.luminosityThreshold.value=s,this.highPassUniforms.smoothWidth.value=.01,this.materialHighPassFilter=new t.ShaderMaterial({uniforms:this.highPassUniforms,vertexShader:a.vertexShader,fragmentShader:a.fragmentShader}),this.separableBlurMaterials=[];const l=[3,5,7,9,11];i=Math.round(this.resolution.x/2),o=Math.round(this.resolution.y/2);for(let e=0;e<this.nMips;e++)this.separableBlurMaterials.push(this.getSeperableBlurMaterial(l[e])),this.separableBlurMaterials[e].uniforms.invSize.value=new t.Vector2(1/i,1/o),i=Math.round(i/2),o=Math.round(o/2);this.compositeMaterial=this.getCompositeMaterial(this.nMips),this.compositeMaterial.uniforms.blurTexture1.value=this.renderTargetsVertical[0].texture,this.compositeMaterial.uniforms.blurTexture2.value=this.renderTargetsVertical[1].texture,this.compositeMaterial.uniforms.blurTexture3.value=this.renderTargetsVertical[2].texture,this.compositeMaterial.uniforms.blurTexture4.value=this.renderTargetsVertical[3].texture,this.compositeMaterial.uniforms.blurTexture5.value=this.renderTargetsVertical[4].texture,this.compositeMaterial.uniforms.bloomStrength.value=r,this.compositeMaterial.uniforms.bloomRadius.value=.1;this.compositeMaterial.uniforms.bloomFactors.value=[1,.8,.6,.4,.2],this.bloomTintColors=[new t.Vector3(1,1,1),new t.Vector3(1,1,1),new t.Vector3(1,1,1),new t.Vector3(1,1,1),new t.Vector3(1,1,1)],this.compositeMaterial.uniforms.bloomTintColors.value=this.bloomTintColors;const h=ke;this.copyUniforms=t.UniformsUtils.clone(h.uniforms),this.blendMaterial=new t.ShaderMaterial({uniforms:this.copyUniforms,vertexShader:h.vertexShader,fragmentShader:h.fragmentShader,blending:t.AdditiveBlending,depthTest:!1,depthWrite:!1,transparent:!0}),this.enabled=!0,this.needsSwap=!1,this._oldClearColor=new t.Color,this.oldClearAlpha=1,this.basic=new t.MeshBasicMaterial,this.fsQuad=new Xe(null)}dispose(){for(let e=0;e<this.renderTargetsHorizontal.length;e++)this.renderTargetsHorizontal[e].dispose();for(let e=0;e<this.renderTargetsVertical.length;e++)this.renderTargetsVertical[e].dispose();this.renderTargetBright.dispose();for(let e=0;e<this.separableBlurMaterials.length;e++)this.separableBlurMaterials[e].dispose();this.compositeMaterial.dispose(),this.blendMaterial.dispose(),this.basic.dispose(),this.fsQuad.dispose()}setSize(e,r){let n=Math.round(e/2),s=Math.round(r/2);this.renderTargetBright.setSize(n,s);for(let e=0;e<this.nMips;e++)this.renderTargetsHorizontal[e].setSize(n,s),this.renderTargetsVertical[e].setSize(n,s),this.separableBlurMaterials[e].uniforms.invSize.value=new t.Vector2(1/n,1/s),n=Math.round(n/2),s=Math.round(s/2)}render(e,t,r,n,s){e.getClearColor(this._oldClearColor),this.oldClearAlpha=e.getClearAlpha();const i=e.autoClear;e.autoClear=!1,e.setClearColor(this.clearColor,0),s&&e.state.buffers.stencil.setTest(!1),this.renderToScreen&&(this.fsQuad.material=this.basic,this.basic.map=r.texture,e.setRenderTarget(null),e.clear(),this.fsQuad.render(e)),this.highPassUniforms.tDiffuse.value=r.texture,this.highPassUniforms.luminosityThreshold.value=this.threshold,this.fsQuad.material=this.materialHighPassFilter,e.setRenderTarget(this.renderTargetBright),e.clear(),this.fsQuad.render(e);let o=this.renderTargetBright;for(let t=0;t<this.nMips;t++)this.fsQuad.material=this.separableBlurMaterials[t],this.separableBlurMaterials[t].uniforms.colorTexture.value=o.texture,this.separableBlurMaterials[t].uniforms.direction.value=et.BlurDirectionX,e.setRenderTarget(this.renderTargetsHorizontal[t]),e.clear(),this.fsQuad.render(e),this.separableBlurMaterials[t].uniforms.colorTexture.value=this.renderTargetsHorizontal[t].texture,this.separableBlurMaterials[t].uniforms.direction.value=et.BlurDirectionY,e.setRenderTarget(this.renderTargetsVertical[t]),e.clear(),this.fsQuad.render(e),o=this.renderTargetsVertical[t];this.fsQuad.material=this.compositeMaterial,this.compositeMaterial.uniforms.bloomStrength.value=this.strength,this.compositeMaterial.uniforms.bloomRadius.value=this.radius,this.compositeMaterial.uniforms.bloomTintColors.value=this.bloomTintColors,e.setRenderTarget(this.renderTargetsHorizontal[0]),e.clear(),this.fsQuad.render(e),this.fsQuad.material=this.blendMaterial,this.copyUniforms.tDiffuse.value=this.renderTargetsHorizontal[0].texture,s&&e.state.buffers.stencil.setTest(!0),this.renderToScreen?(e.setRenderTarget(null),this.fsQuad.render(e)):(e.setRenderTarget(r),this.fsQuad.render(e)),e.setClearColor(this._oldClearColor,this.oldClearAlpha),e.autoClear=i}getSeperableBlurMaterial(e){const r=[];for(let t=0;t<e;t++)r.push(.39894*Math.exp(-.5*t*t/(e*e))/e);return new t.ShaderMaterial({defines:{KERNEL_RADIUS:e},uniforms:{colorTexture:{value:null},invSize:{value:new t.Vector2(.5,.5)},direction:{value:new t.Vector2(.5,.5)},gaussianCoefficients:{value:r}},vertexShader:"varying vec2 vUv;\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\t\t\t\t}",fragmentShader:"#include <common>\n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tuniform sampler2D colorTexture;\n\t\t\t\tuniform vec2 invSize;\n\t\t\t\tuniform vec2 direction;\n\t\t\t\tuniform float gaussianCoefficients[KERNEL_RADIUS];\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tfloat weightSum = gaussianCoefficients[0];\n\t\t\t\t\tvec3 diffuseSum = texture2D( colorTexture, vUv ).rgb * weightSum;\n\t\t\t\t\tfor( int i = 1; i < KERNEL_RADIUS; i ++ ) {\n\t\t\t\t\t\tfloat x = float(i);\n\t\t\t\t\t\tfloat w = gaussianCoefficients[i];\n\t\t\t\t\t\tvec2 uvOffset = direction * invSize * x;\n\t\t\t\t\t\tvec3 sample1 = texture2D( colorTexture, vUv + uvOffset ).rgb;\n\t\t\t\t\t\tvec3 sample2 = texture2D( colorTexture, vUv - uvOffset ).rgb;\n\t\t\t\t\t\tdiffuseSum += (sample1 + sample2) * w;\n\t\t\t\t\t\tweightSum += 2.0 * w;\n\t\t\t\t\t}\n\t\t\t\t\tgl_FragColor = vec4(diffuseSum/weightSum, 1.0);\n\t\t\t\t}"})}getCompositeMaterial(e){return new t.ShaderMaterial({defines:{NUM_MIPS:e},uniforms:{blurTexture1:{value:null},blurTexture2:{value:null},blurTexture3:{value:null},blurTexture4:{value:null},blurTexture5:{value:null},bloomStrength:{value:1},bloomFactors:{value:null},bloomTintColors:{value:null},bloomRadius:{value:0}},vertexShader:"varying vec2 vUv;\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\t\t\t\t}",fragmentShader:"varying vec2 vUv;\n\t\t\t\tuniform sampler2D blurTexture1;\n\t\t\t\tuniform sampler2D blurTexture2;\n\t\t\t\tuniform sampler2D blurTexture3;\n\t\t\t\tuniform sampler2D blurTexture4;\n\t\t\t\tuniform sampler2D blurTexture5;\n\t\t\t\tuniform float bloomStrength;\n\t\t\t\tuniform float bloomRadius;\n\t\t\t\tuniform float bloomFactors[NUM_MIPS];\n\t\t\t\tuniform vec3 bloomTintColors[NUM_MIPS];\n\n\t\t\t\tfloat lerpBloomFactor(const in float factor) {\n\t\t\t\t\tfloat mirrorFactor = 1.2 - factor;\n\t\t\t\t\treturn mix(factor, mirrorFactor, bloomRadius);\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tgl_FragColor = bloomStrength * ( lerpBloomFactor(bloomFactors[0]) * vec4(bloomTintColors[0], 1.0) * texture2D(blurTexture1, vUv) +\n\t\t\t\t\t\tlerpBloomFactor(bloomFactors[1]) * vec4(bloomTintColors[1], 1.0) * texture2D(blurTexture2, vUv) +\n\t\t\t\t\t\tlerpBloomFactor(bloomFactors[2]) * vec4(bloomTintColors[2], 1.0) * texture2D(blurTexture3, vUv) +\n\t\t\t\t\t\tlerpBloomFactor(bloomFactors[3]) * vec4(bloomTintColors[3], 1.0) * texture2D(blurTexture4, vUv) +\n\t\t\t\t\t\tlerpBloomFactor(bloomFactors[4]) * vec4(bloomTintColors[4], 1.0) * texture2D(blurTexture5, vUv) );\n\t\t\t\t}"})}}et.BlurDirectionX=new t.Vector2(1,0),et.BlurDirectionY=new t.Vector2(0,1);const tt={name:"BrightnessContrastShader",uniforms:{tDiffuse:{value:null},brightness:{value:0},contrast:{value:0}},vertexShader:"\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform sampler2D tDiffuse;\n\t\tuniform float brightness;\n\t\tuniform float contrast;\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = texture2D( tDiffuse, vUv );\n\n\t\t\tgl_FragColor.rgb += brightness;\n\n\t\t\tif (contrast > 0.0) {\n\t\t\t\tgl_FragColor.rgb = (gl_FragColor.rgb - 0.5) / (1.0 - contrast) + 0.5;\n\t\t\t} else {\n\t\t\t\tgl_FragColor.rgb = (gl_FragColor.rgb - 0.5) * (1.0 + contrast) + 0.5;\n\t\t\t}\n\n\t\t}"},rt={name:"HueSaturationShader",uniforms:{tDiffuse:{value:null},hue:{value:0},saturation:{value:0}},vertexShader:"\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform sampler2D tDiffuse;\n\t\tuniform float hue;\n\t\tuniform float saturation;\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = texture2D( tDiffuse, vUv );\n\n\t\t\t// hue\n\t\t\tfloat angle = hue * 3.14159265;\n\t\t\tfloat s = sin(angle), c = cos(angle);\n\t\t\tvec3 weights = (vec3(2.0 * c, -sqrt(3.0) * s - c, sqrt(3.0) * s - c) + 1.0) / 3.0;\n\t\t\tfloat len = length(gl_FragColor.rgb);\n\t\t\tgl_FragColor.rgb = vec3(\n\t\t\t\tdot(gl_FragColor.rgb, weights.xyz),\n\t\t\t\tdot(gl_FragColor.rgb, weights.zxy),\n\t\t\t\tdot(gl_FragColor.rgb, weights.yzx)\n\t\t\t);\n\n\t\t\t// saturation\n\t\t\tfloat average = (gl_FragColor.r + gl_FragColor.g + gl_FragColor.b) / 3.0;\n\t\t\tif (saturation > 0.0) {\n\t\t\t\tgl_FragColor.rgb += (average - gl_FragColor.rgb) * (1.0 - 1.0 / (1.001 - saturation));\n\t\t\t} else {\n\t\t\t\tgl_FragColor.rgb += (average - gl_FragColor.rgb) * (-saturation);\n\t\t\t}\n\n\t\t}"},nt={name:"ExposureShader",uniforms:{tDiffuse:{value:null},exposure:{value:1}},vertexShader:"\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",fragmentShader:"\n\n\t\tuniform float exposure;\n\n\t\tuniform sampler2D tDiffuse;\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tgl_FragColor = texture2D( tDiffuse, vUv );\n\t\t\tgl_FragColor.rgb *= exposure;\n\n\t\t}"};e.BrightnessContrastShader=tt,e.DRACOLoader=ee,e.EffectComposer=class{constructor(e,r){if(this.renderer=e,this._pixelRatio=e.getPixelRatio(),void 0===r){const n=e.getSize(new t.Vector2);this._width=n.width,this._height=n.height,(r=new t.WebGLRenderTarget(this._width*this._pixelRatio,this._height*this._pixelRatio,{type:t.HalfFloatType})).texture.name="EffectComposer.rt1"}else this._width=r.width,this._height=r.height;this.renderTarget1=r,this.renderTarget2=r.clone(),this.renderTarget2.texture.name="EffectComposer.rt2",this.writeBuffer=this.renderTarget1,this.readBuffer=this.renderTarget2,this.renderToScreen=!0,this.passes=[],this.copyPass=new Ve(ke),this.copyPass.material.blending=t.NoBlending,this.clock=new t.Clock}swapBuffers(){const e=this.readBuffer;this.readBuffer=this.writeBuffer,this.writeBuffer=e}addPass(e){this.passes.push(e),e.setSize(this._width*this._pixelRatio,this._height*this._pixelRatio)}insertPass(e,t){this.passes.splice(t,0,e),e.setSize(this._width*this._pixelRatio,this._height*this._pixelRatio)}removePass(e){const t=this.passes.indexOf(e);-1!==t&&this.passes.splice(t,1)}isLastEnabledPass(e){for(let t=e+1;t<this.passes.length;t++)if(this.passes[t].enabled)return!1;return!0}render(e){void 0===e&&(e=this.clock.getDelta());const t=this.renderer.getRenderTarget();let r=!1;for(let t=0,n=this.passes.length;t<n;t++){const n=this.passes[t];if(!1!==n.enabled){if(n.renderToScreen=this.renderToScreen&&this.isLastEnabledPass(t),n.render(this.renderer,this.writeBuffer,this.readBuffer,e,r),n.needsSwap){if(r){const t=this.renderer.getContext(),r=this.renderer.state.buffers.stencil;r.setFunc(t.NOTEQUAL,1,4294967295),this.copyPass.render(this.renderer,this.writeBuffer,this.readBuffer,e),r.setFunc(t.EQUAL,1,4294967295)}this.swapBuffers()}void 0!==Ye&&(n instanceof Ye?r=!0:n instanceof Qe&&(r=!1))}}this.renderer.setRenderTarget(t)}reset(e){if(void 0===e){const r=this.renderer.getSize(new t.Vector2);this._pixelRatio=this.renderer.getPixelRatio(),this._width=r.width,this._height=r.height,(e=this.renderTarget1.clone()).setSize(this._width*this._pixelRatio,this._height*this._pixelRatio)}this.renderTarget1.dispose(),this.renderTarget2.dispose(),this.renderTarget1=e,this.renderTarget2=e.clone(),this.writeBuffer=this.renderTarget1,this.readBuffer=this.renderTarget2}setSize(e,t){this._width=e,this._height=t;const r=this._width*this._pixelRatio,n=this._height*this._pixelRatio;this.renderTarget1.setSize(r,n),this.renderTarget2.setSize(r,n);for(let e=0;e<this.passes.length;e++)this.passes[e].setSize(r,n)}setPixelRatio(e){this._pixelRatio=e,this.setSize(this._width,this._height)}dispose(){this.renderTarget1.dispose(),this.renderTarget2.dispose(),this.copyPass.dispose()}},e.ExposureShader=nt,e.GLTFLoader=n,e.HueSaturationShader=rt,e.OutlinePass=qe,e.OutputPass=class extends Ge{constructor(){super();const e=Je;this.uniforms=t.UniformsUtils.clone(e.uniforms),this.material=new t.RawShaderMaterial({name:e.name,uniforms:this.uniforms,vertexShader:e.vertexShader,fragmentShader:e.fragmentShader}),this.fsQuad=new Xe(this.material),this._outputColorSpace=null,this._toneMapping=null}render(e,r,n){this.uniforms.tDiffuse.value=n.texture,this.uniforms.toneMappingExposure.value=e.toneMappingExposure,this._outputColorSpace===e.outputColorSpace&&this._toneMapping===e.toneMapping||(this._outputColorSpace=e.outputColorSpace,this._toneMapping=e.toneMapping,this.material.defines={},t.ColorManagement.getTransfer(this._outputColorSpace)===t.SRGBTransfer&&(this.material.defines.SRGB_TRANSFER=""),this._toneMapping===t.LinearToneMapping?this.material.defines.LINEAR_TONE_MAPPING="":this._toneMapping===t.ReinhardToneMapping?this.material.defines.REINHARD_TONE_MAPPING="":this._toneMapping===t.CineonToneMapping?this.material.defines.CINEON_TONE_MAPPING="":this._toneMapping===t.ACESFilmicToneMapping?this.material.defines.ACES_FILMIC_TONE_MAPPING="":this._toneMapping===t.AgXToneMapping&&(this.material.defines.AGX_TONE_MAPPING=""),this.material.needsUpdate=!0),!0===this.renderToScreen?(e.setRenderTarget(null),this.fsQuad.render(e)):(e.setRenderTarget(r),this.clear&&e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil),this.fsQuad.render(e))}dispose(){this.material.dispose(),this.fsQuad.dispose()}},e.RenderPass=class extends Ge{constructor(e,r,n=null,s=null,i=null){super(),this.scene=e,this.camera=r,this.overrideMaterial=n,this.clearColor=s,this.clearAlpha=i,this.clear=!0,this.clearDepth=!1,this.needsSwap=!1,this._oldClearColor=new t.Color}render(e,t,r){const n=e.autoClear;let s,i;e.autoClear=!1,null!==this.overrideMaterial&&(i=this.scene.overrideMaterial,this.scene.overrideMaterial=this.overrideMaterial),null!==this.clearColor&&(e.getClearColor(this._oldClearColor),e.setClearColor(this.clearColor)),null!==this.clearAlpha&&(s=e.getClearAlpha(),e.setClearAlpha(this.clearAlpha)),1==this.clearDepth&&e.clearDepth(),e.setRenderTarget(this.renderToScreen?null:r),!0===this.clear&&e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil),e.render(this.scene,this.camera),null!==this.clearColor&&e.setClearColor(this._oldClearColor),null!==this.clearAlpha&&e.setClearAlpha(s),null!==this.overrideMaterial&&(this.scene.overrideMaterial=i),e.autoClear=n}},e.SMAAPass=class extends Ge{constructor(e,r){super(),this.edgesRT=new t.WebGLRenderTarget(e,r,{depthBuffer:!1,type:t.HalfFloatType}),this.edgesRT.texture.name="SMAAPass.edges",this.weightsRT=new t.WebGLRenderTarget(e,r,{depthBuffer:!1,type:t.HalfFloatType}),this.weightsRT.texture.name="SMAAPass.weights";const n=this,s=new Image;s.src=this.getAreaTexture(),s.onload=function(){n.areaTexture.needsUpdate=!0},this.areaTexture=new t.Texture,this.areaTexture.name="SMAAPass.area",this.areaTexture.image=s,this.areaTexture.minFilter=t.LinearFilter,this.areaTexture.generateMipmaps=!1,this.areaTexture.flipY=!1;const i=new Image;i.src=this.getSearchTexture(),i.onload=function(){n.searchTexture.needsUpdate=!0},this.searchTexture=new t.Texture,this.searchTexture.name="SMAAPass.search",this.searchTexture.image=i,this.searchTexture.magFilter=t.NearestFilter,this.searchTexture.minFilter=t.NearestFilter,this.searchTexture.generateMipmaps=!1,this.searchTexture.flipY=!1,this.uniformsEdges=t.UniformsUtils.clone(Ke.uniforms),this.uniformsEdges.resolution.value.set(1/e,1/r),this.materialEdges=new t.ShaderMaterial({defines:Object.assign({},Ke.defines),uniforms:this.uniformsEdges,vertexShader:Ke.vertexShader,fragmentShader:Ke.fragmentShader}),this.uniformsWeights=t.UniformsUtils.clone(Ze.uniforms),this.uniformsWeights.resolution.value.set(1/e,1/r),this.uniformsWeights.tDiffuse.value=this.edgesRT.texture,this.uniformsWeights.tArea.value=this.areaTexture,this.uniformsWeights.tSearch.value=this.searchTexture,this.materialWeights=new t.ShaderMaterial({defines:Object.assign({},Ze.defines),uniforms:this.uniformsWeights,vertexShader:Ze.vertexShader,fragmentShader:Ze.fragmentShader}),this.uniformsBlend=t.UniformsUtils.clone(_e.uniforms),this.uniformsBlend.resolution.value.set(1/e,1/r),this.uniformsBlend.tDiffuse.value=this.weightsRT.texture,this.materialBlend=new t.ShaderMaterial({uniforms:this.uniformsBlend,vertexShader:_e.vertexShader,fragmentShader:_e.fragmentShader}),this.fsQuad=new Xe(null)}render(e,t,r){this.uniformsEdges.tDiffuse.value=r.texture,this.fsQuad.material=this.materialEdges,e.setRenderTarget(this.edgesRT),this.clear&&e.clear(),this.fsQuad.render(e),this.fsQuad.material=this.materialWeights,e.setRenderTarget(this.weightsRT),this.clear&&e.clear(),this.fsQuad.render(e),this.uniformsBlend.tColor.value=r.texture,this.fsQuad.material=this.materialBlend,this.renderToScreen?(e.setRenderTarget(null),this.fsQuad.render(e)):(e.setRenderTarget(t),this.clear&&e.clear(),this.fsQuad.render(e))}setSize(e,t){this.edgesRT.setSize(e,t),this.weightsRT.setSize(e,t),this.materialEdges.uniforms.resolution.value.set(1/e,1/t),this.materialWeights.uniforms.resolution.value.set(1/e,1/t),this.materialBlend.uniforms.resolution.value.set(1/e,1/t)}getAreaTexture(){return"data:image/png;base64,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"}getSearchTexture(){return"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAAhCAAAAABIXyLAAAAAOElEQVRIx2NgGAWjYBSMglEwEICREYRgFBZBqDCSLA2MGPUIVQETE9iNUAqLR5gIeoQKRgwXjwAAGn4AtaFeYLEAAAAASUVORK5CYII="}dispose(){this.edgesRT.dispose(),this.weightsRT.dispose(),this.areaTexture.dispose(),this.searchTexture.dispose(),this.materialEdges.dispose(),this.materialWeights.dispose(),this.materialBlend.dispose(),this.fsQuad.dispose()}},e.ShaderPass=Ve,e.SkeletonUtils=oe,e.TransformControls=ge,e.UnrealBloomPass=et,Object.defineProperty(e,"__esModule",{value:!0})}));
+//# sourceMappingURL=ThreeAddons.js.map
diff --git a/GDJS/Runtime/runtimegame.ts b/GDJS/Runtime/runtimegame.ts
index 4ff1cd5c2fe5..e6f5c4b65720 100644
--- a/GDJS/Runtime/runtimegame.ts
+++ b/GDJS/Runtime/runtimegame.ts
@@ -46,7 +46,7 @@ namespace gdjs {
    * Either stored in the options generated by the preview or in the URL
    * in case of a hard reload.
    */
-  type RuntimeGameStatus = {
+  export type RuntimeGameStatus = {
     isPaused: boolean;
     isInGameEdition: boolean;
     sceneName: string | null;
@@ -158,6 +158,239 @@ namespace gdjs {
     environment?: 'dev';
   };
 
+  class RuntimeEditor {
+    _game: RuntimeGame;
+    _pointer = new THREE.Vector2();
+    // TODO: Use array
+    _selectedObjectData: {
+      intersect: THREE.Intersection;
+      camera: THREE.Camera;
+      scene: THREE.Scene;
+    } | null = null;
+    _outlinePasses: Record<string, THREE_ADDONS.OutlinePass> = {};
+    _raycaster = new THREE.Raycaster()
+    _editionAbortController: AbortController = new AbortController();
+    _clearCurrentPasses: (() => void)[] = [];
+    _currentTransformControls: THREE_ADDONS.TransformControls | null = null;
+    _shouldIgnoreNextClick: boolean = false;
+
+    constructor(game: RuntimeGame) {
+      this._game = game;
+    }
+
+    onPointerMove(event) {
+      // calculate pointer position in normalized device coordinates
+      // (-1 to +1) for both components
+
+      this._pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
+      this._pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
+    }
+
+    selectObject() {
+      if (this._shouldIgnoreNextClick) {
+        this._shouldIgnoreNextClick = false;
+        return;
+      }
+      const firstIntersectsByLayer = this.getFirstIntersectsOnEachLayer(false);
+      if (!firstIntersectsByLayer) return;
+      let closestIntersect;
+      for (const intersect of Object.values(firstIntersectsByLayer)) {
+        if (
+          !closestIntersect ||
+          intersect.intersect.distance < closestIntersect.intersect.distance
+        ) {
+          closestIntersect = intersect;
+        }
+      }
+      this._selectedObjectData = closestIntersect;
+      if (!this._selectedObjectData) return;
+
+      if (
+        this._currentTransformControls &&
+        this._currentTransformControls.camera ===
+          this._selectedObjectData.camera
+      ) {
+        this._currentTransformControls.detach();
+        this._currentTransformControls.attach(
+          this._selectedObjectData.intersect.object
+        );
+      } else {
+        if (this._currentTransformControls) {
+          this._currentTransformControls.detach();
+          this._currentTransformControls = null;
+        }
+        this._currentTransformControls = new THREE_ADDONS.TransformControls(
+          this._selectedObjectData.camera,
+          this._game.getRenderer().getCanvas() || undefined
+        );
+        this._currentTransformControls.addEventListener('mouseDown', () => {
+          this._shouldIgnoreNextClick = true;
+        });
+        this._currentTransformControls.addEventListener(
+          'dragging-changed',
+          (e) => {
+            if (!this._selectedObjectData) return;
+            if (e.value) {
+              // Ignore if the user starts dragging
+              return;
+            }
+            const rendererObject = this._selectedObjectData.intersect.object;
+            const object = this._game.getObjectFromRenderer(rendererObject);
+            if (!object) return;
+            if (object instanceof gdjs.RuntimeObject3D) {
+              this._game.sendRuntimeObjectsUpdated([
+                {
+                  object,
+                  position: object
+                    .getRenderer()
+                    .getObjectPositionFrom3DRendererObject(),
+                },
+              ]);
+            }
+          }
+        );
+        this._currentTransformControls.scale.y = -1;
+        this._currentTransformControls.attach(
+          this._selectedObjectData.intersect.object
+        );
+        this._selectedObjectData.scene.add(this._currentTransformControls);
+      }
+    }
+
+    setupListeners() {
+      const canvas = this._game.getRenderer().getCanvas();
+      this._editionAbortController = new AbortController();
+      canvas?.addEventListener('pointermove', this.onPointerMove.bind(this), {
+        signal: this._editionAbortController.signal,
+      });
+      canvas?.addEventListener('click', this.selectObject.bind(this), {
+        signal: this._editionAbortController.signal,
+      });
+    }
+    cleanListeners() {
+      this._editionAbortController.abort();
+    }
+    activate(enable: boolean) {
+      if (enable) this.setupListeners();
+      else {
+        this.cleanListeners();
+        if (this._currentTransformControls) {
+          this._currentTransformControls.detach();
+          this._currentTransformControls = null;
+        }
+      }
+    }
+
+    reloadInstances(payload: {
+      layoutName: string;
+      instances: Array<{
+        persistentUuid: string;
+        position: { x: number; y: number; z: number };
+      }>;
+    }) {
+      const currentScene = this._game.getSceneStack().getCurrentScene();
+      if (!currentScene || currentScene.getName() !== payload.layoutName) {
+        return;
+      }
+      // TODO: Might be worth indexing instances data and runtime objects by their
+      // persistentUuid (See HotReloader.indexByPersistentUuid).
+      currentScene.getAdhocListOfAllInstances().forEach((runtimeObject) => {
+        const instance = payload.instances.find(
+          (instance) => instance.persistentUuid === runtimeObject.persistentUuid
+        );
+        if (instance) {
+          runtimeObject.setX(instance.position.x);
+          runtimeObject.setY(instance.position.y);
+          if (runtimeObject instanceof gdjs.RuntimeObject3D) {
+            runtimeObject.setZ(instance.position.z);
+          }
+        }
+      });
+    }
+
+    getFirstIntersectsOnEachLayer(highlightObject: boolean) {
+      if (highlightObject) {
+        this._clearCurrentPasses.forEach((callback) => callback());
+        this._clearCurrentPasses.length = 0;
+      }
+      const layerNames = new Array();
+      const currentScene = this._game.getSceneStack().getCurrentScene();
+      if (!currentScene) return;
+      const threeRenderer = this._game.getRenderer().getThreeRenderer();
+      if (!threeRenderer) return;
+
+      currentScene.getAllLayerNames(layerNames);
+      const firstIntersectsByLayer: {
+        [layerName: string]: {
+          intersect: THREE.Intersection;
+          camera: THREE.Camera;
+          scene: THREE.Scene;
+        };
+      } = layerNames.reduce((acc, layerName) => {
+        const runtimeLayerRender = currentScene
+          .getLayer(layerName)
+          .getRenderer();
+        const threeCamera = runtimeLayerRender.getThreeCamera();
+        const threeScene = runtimeLayerRender.getThreeScene();
+        if (!threeCamera || !threeScene) return acc;
+
+        if (!this._outlinePasses[layerName]) {
+          this._outlinePasses[layerName] = new THREE_ADDONS.OutlinePass(
+            new THREE.Vector2(window.innerWidth, window.innerHeight),
+            threeScene,
+            threeCamera
+          );
+
+          runtimeLayerRender.addPostProcessingPass(this._outlinePasses[layerName]);
+        }
+        const outlinePass = this._outlinePasses[layerName];
+
+        // Note that raycasting is done by Three.js, which means it could slow down
+        // if lots of 3D objects are shown. We consider that if this needs improvements,
+        // this must be handled by the game engine culling
+        this._raycaster.setFromCamera(this._pointer, threeCamera);
+        const intersects = this._raycaster.intersectObjects(threeScene.children);
+
+        const firstIntersect = intersects.filter((intersect) => {
+          let isObjectChildOfTransformControls = false;
+          intersect.object.traverseAncestors((ancestor) => {
+            if (ancestor === this._currentTransformControls) {
+              isObjectChildOfTransformControls = true;
+            }
+          });
+          return !isObjectChildOfTransformControls;
+        })[0];
+
+        if (
+          firstIntersect &&
+          highlightObject &&
+          (!this._currentTransformControls ||
+            !this._currentTransformControls.dragging)
+        ) {
+          // TODO: OutlinePass currently wrongly highlights the transform controls helper.
+          // (See https://discourse.threejs.org/t/outlinepass-with-transform-control/18722)
+
+          outlinePass.edgeStrength = 6.0;
+          outlinePass.edgeGlow = 0;
+          outlinePass.edgeThickness = 1.0;
+          outlinePass.pulsePeriod = 0;
+          outlinePass.selectedObjects = [firstIntersect.object];
+        }
+        acc[layerName] = {
+          intersect: firstIntersect,
+          camera: threeCamera,
+          scene: threeScene,
+        };
+        return acc;
+      }, {});
+      return firstIntersectsByLayer;
+    }
+
+    render() {
+      this.getFirstIntersectsOnEachLayer(true);
+    }
+  }
+
   /**
    * Represents a game being played.
    */
@@ -233,6 +466,8 @@ namespace gdjs {
     /** True if the RuntimeGame has been disposed and should not be used anymore. */
     _wasDisposed: boolean = false;
 
+    _editor: RuntimeEditor;
+
     /**
      * @param data The object (usually stored in data.json) containing the full project data
      * @param
@@ -275,7 +510,7 @@ namespace gdjs {
         getGlobalResourceNames(data),
         data.layouts
       );
-
+      this._editor = new RuntimeEditor(this);
       this._effectsManager = new gdjs.EffectsManager();
       this._maxFPS = this._data.properties.maxFPS;
       this._minFPS = this._data.properties.minFPS;
@@ -757,6 +992,7 @@ namespace gdjs {
       if (this._paused === enable) return;
 
       this._paused = enable;
+      this._editor.activate(enable);
       if (this._debuggerClient) {
         this._debuggerClient.sendRuntimeGameStatus();
       }
@@ -991,8 +1227,12 @@ namespace gdjs {
               }
             }
 
-            if (this._paused && !this._isInGameEdition) {
-              // The game is paused, but not being edited, so we entirely skip any logic.
+            if (this._paused) {
+              this._editor.render();
+              // The game is paused for edition: the game loop continues to run,
+              // but the game logic is not executed.
+              this._sceneStack.renderWithoutStep();
+
               return true;
             }
 
@@ -1017,20 +1257,13 @@ namespace gdjs {
               this._notifyScenesForGameResolutionResize = false;
             }
 
-            if (this._paused && this._isInGameEdition) {
-              // The game is paused for edition: the game loop continues to run,
-              // but the game logic is not executed.
-              this._sceneStack.renderWithoutStep();
+            // Render and step the scene.
+            if (this._sceneStack.step(elapsedTime)) {
+              this.getInputManager().onFrameEnded();
+              this._hasJustResumed = false;
               return true;
-            } else {
-              // Render and step the scene.
-              if (this._sceneStack.step(elapsedTime)) {
-                this.getInputManager().onFrameEnded();
-                this._hasJustResumed = false;
-                return true;
-              }
-              return false;
             }
+            return false;
           } catch (e) {
             if (this._debuggerClient)
               this._debuggerClient.onUncaughtException(e);
@@ -1413,6 +1646,38 @@ namespace gdjs {
         : embeddedResourceName;
     }
 
+    getObjectFromRenderer(
+      renderer: THREE.Object3D | gdjs.RendererObjectInterface
+    ): RuntimeObject | null {
+      const currentScene = this.getSceneStack().getCurrentScene();
+      if (!currentScene) return null;
+      // TODO: Should we instead have an index on the runtime object persistentUuid?
+      // In that case, it would require to store the persistentUuid on the renderer object.
+      const allInstances = currentScene.getAdhocListOfAllInstances();
+      const object = allInstances.find(
+        renderer instanceof THREE.Object3D
+          ? (instance) => instance.get3DRendererObject() === renderer
+          : (instance) => instance.getRendererObject() === renderer
+      );
+
+      return object || null;
+    }
+
+    sendRuntimeObjectsUpdated(
+      runtimeObjectUpdates: Array<{
+        object: RuntimeObject3D;
+        position: { x: number; y: number; z: number };
+      }>
+    ) {
+      if (!this._debuggerClient) return;
+      const currentScene = this.getSceneStack().getCurrentScene();
+      if (!currentScene) return;
+      this._debuggerClient.sendInstancesUpdated(
+        runtimeObjectUpdates,
+        currentScene.getName()
+      );
+    }
+
     /**
      * Returns the array of resources that are embedded to passed one.
      * @param resourceName The name of resource to find embedded resources of.
diff --git a/GDJS/Runtime/runtimescene.ts b/GDJS/Runtime/runtimescene.ts
index 48415eff5006..2487d3414a71 100644
--- a/GDJS/Runtime/runtimescene.ts
+++ b/GDJS/Runtime/runtimescene.ts
@@ -427,7 +427,6 @@ namespace gdjs {
       }
 
       this.render();
-
       this._isJustResumed = false;
       if (this._profiler) {
         this._profiler.end('render');
@@ -437,7 +436,6 @@ namespace gdjs {
       }
       return !!this.getRequestedChange();
     }
-
     /**
      * Render the scene (but do not execute the game logic).
      */
diff --git a/GDJS/Runtime/types/global-three-addons.d.ts b/GDJS/Runtime/types/global-three-addons.d.ts
index 5de5e672cf6d..2427962cdd8d 100644
--- a/GDJS/Runtime/types/global-three-addons.d.ts
+++ b/GDJS/Runtime/types/global-three-addons.d.ts
@@ -2,7 +2,9 @@ import { GLTFLoader, GLTF } from 'three/examples/jsm/loaders/GLTFLoader';
 import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
 import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils';
 
+import { TransformControls } from 'three/examples/jsm/controls/TransformControls';
 import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
+import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass';
 import { Pass } from 'three/examples/jsm/postprocessing/Pass';
 import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass';
 import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass';
@@ -21,7 +23,9 @@ declare global {
       GLTF,
       DRACOLoader,
       SkeletonUtils,
+      TransformControls,
       EffectComposer,
+      OutlinePass,
       Pass,
       RenderPass,
       ShaderPass,
diff --git a/GDevelop.js/Bindings/Bindings.idl b/GDevelop.js/Bindings/Bindings.idl
index 7f2566762bda..6191d232f541 100644
--- a/GDevelop.js/Bindings/Bindings.idl
+++ b/GDevelop.js/Bindings/Bindings.idl
@@ -1373,6 +1373,7 @@ interface InitialInstance {
     double GetCustomDepth();
 
     [Ref] InitialInstance ResetPersistentUuid();
+    [Const, Value] DOMString GetPersistentUuid();
 
     void UpdateCustomProperty(
         [Const] DOMString name,
diff --git a/GDevelop.js/types.d.ts b/GDevelop.js/types.d.ts
index 64cdfdbe330e..611f39d6f28a 100644
--- a/GDevelop.js/types.d.ts
+++ b/GDevelop.js/types.d.ts
@@ -1145,6 +1145,7 @@ export class InitialInstance extends EmscriptenObject {
   setCustomDepth(depth: number): void;
   getCustomDepth(): number;
   resetPersistentUuid(): InitialInstance;
+  getPersistentUuid(): string;
   updateCustomProperty(name: string, value: string, globalObjectsContainer: ObjectsContainer, objectsContainer: ObjectsContainer): void;
   getCustomProperties(globalObjectsContainer: ObjectsContainer, objectsContainer: ObjectsContainer): MapStringPropertyDescriptor;
   getRawDoubleProperty(name: string): number;
diff --git a/GDevelop.js/types/gdinitialinstance.js b/GDevelop.js/types/gdinitialinstance.js
index e2f540f2ca9b..57e0a5eb62d6 100644
--- a/GDevelop.js/types/gdinitialinstance.js
+++ b/GDevelop.js/types/gdinitialinstance.js
@@ -44,6 +44,7 @@ declare class gdInitialInstance {
   setCustomDepth(depth: number): void;
   getCustomDepth(): number;
   resetPersistentUuid(): gdInitialInstance;
+  getPersistentUuid(): string;
   updateCustomProperty(name: string, value: string, globalObjectsContainer: gdObjectsContainer, objectsContainer: gdObjectsContainer): void;
   getCustomProperties(globalObjectsContainer: gdObjectsContainer, objectsContainer: gdObjectsContainer): gdMapStringPropertyDescriptor;
   getRawDoubleProperty(name: string): number;
diff --git a/SharedLibs/ThreeAddons/src/examples/jsm/controls/TransformControls.js b/SharedLibs/ThreeAddons/src/examples/jsm/controls/TransformControls.js
new file mode 100644
index 000000000000..f78ba2325af2
--- /dev/null
+++ b/SharedLibs/ThreeAddons/src/examples/jsm/controls/TransformControls.js
@@ -0,0 +1,1573 @@
+import {
+	BoxGeometry,
+	BufferGeometry,
+	CylinderGeometry,
+	DoubleSide,
+	Euler,
+	Float32BufferAttribute,
+	Line,
+	LineBasicMaterial,
+	Matrix4,
+	Mesh,
+	MeshBasicMaterial,
+	Object3D,
+	OctahedronGeometry,
+	PlaneGeometry,
+	Quaternion,
+	Raycaster,
+	SphereGeometry,
+	TorusGeometry,
+	Vector3
+} from 'three';
+
+const _raycaster = new Raycaster();
+
+const _tempVector = new Vector3();
+const _tempVector2 = new Vector3();
+const _tempQuaternion = new Quaternion();
+const _unit = {
+	X: new Vector3( 1, 0, 0 ),
+	Y: new Vector3( 0, 1, 0 ),
+	Z: new Vector3( 0, 0, 1 )
+};
+
+const _changeEvent = { type: 'change' };
+const _mouseDownEvent = { type: 'mouseDown' };
+const _mouseUpEvent = { type: 'mouseUp', mode: null };
+const _objectChangeEvent = { type: 'objectChange' };
+
+class TransformControls extends Object3D {
+
+	constructor( camera, domElement ) {
+
+		super();
+
+		if ( domElement === undefined ) {
+
+			console.warn( 'THREE.TransformControls: The second parameter "domElement" is now mandatory.' );
+			domElement = document;
+
+		}
+
+		this.isTransformControls = true;
+
+		this.visible = false;
+		this.domElement = domElement;
+		this.domElement.style.touchAction = 'none'; // disable touch scroll
+
+		const _gizmo = new TransformControlsGizmo();
+		this._gizmo = _gizmo;
+		this.add( _gizmo );
+
+		const _plane = new TransformControlsPlane();
+		this._plane = _plane;
+		this.add( _plane );
+
+		const scope = this;
+
+		// Defined getter, setter and store for a property
+		function defineProperty( propName, defaultValue ) {
+
+			let propValue = defaultValue;
+
+			Object.defineProperty( scope, propName, {
+
+				get: function () {
+
+					return propValue !== undefined ? propValue : defaultValue;
+
+				},
+
+				set: function ( value ) {
+
+					if ( propValue !== value ) {
+
+						propValue = value;
+						_plane[ propName ] = value;
+						_gizmo[ propName ] = value;
+
+						scope.dispatchEvent( { type: propName + '-changed', value: value } );
+						scope.dispatchEvent( _changeEvent );
+
+					}
+
+				}
+
+			} );
+
+			scope[ propName ] = defaultValue;
+			_plane[ propName ] = defaultValue;
+			_gizmo[ propName ] = defaultValue;
+
+		}
+
+		// Define properties with getters/setter
+		// Setting the defined property will automatically trigger change event
+		// Defined properties are passed down to gizmo and plane
+
+		defineProperty( 'camera', camera );
+		defineProperty( 'object', undefined );
+		defineProperty( 'enabled', true );
+		defineProperty( 'axis', null );
+		defineProperty( 'mode', 'translate' );
+		defineProperty( 'translationSnap', null );
+		defineProperty( 'rotationSnap', null );
+		defineProperty( 'scaleSnap', null );
+		defineProperty( 'space', 'world' );
+		defineProperty( 'size', 1 );
+		defineProperty( 'dragging', false );
+		defineProperty( 'showX', true );
+		defineProperty( 'showY', true );
+		defineProperty( 'showZ', true );
+
+		// Reusable utility variables
+
+		const worldPosition = new Vector3();
+		const worldPositionStart = new Vector3();
+		const worldQuaternion = new Quaternion();
+		const worldQuaternionStart = new Quaternion();
+		const cameraPosition = new Vector3();
+		const cameraQuaternion = new Quaternion();
+		const pointStart = new Vector3();
+		const pointEnd = new Vector3();
+		const rotationAxis = new Vector3();
+		const rotationAngle = 0;
+		const eye = new Vector3();
+
+		// TODO: remove properties unused in plane and gizmo
+
+		defineProperty( 'worldPosition', worldPosition );
+		defineProperty( 'worldPositionStart', worldPositionStart );
+		defineProperty( 'worldQuaternion', worldQuaternion );
+		defineProperty( 'worldQuaternionStart', worldQuaternionStart );
+		defineProperty( 'cameraPosition', cameraPosition );
+		defineProperty( 'cameraQuaternion', cameraQuaternion );
+		defineProperty( 'pointStart', pointStart );
+		defineProperty( 'pointEnd', pointEnd );
+		defineProperty( 'rotationAxis', rotationAxis );
+		defineProperty( 'rotationAngle', rotationAngle );
+		defineProperty( 'eye', eye );
+
+		this._offset = new Vector3();
+		this._startNorm = new Vector3();
+		this._endNorm = new Vector3();
+		this._cameraScale = new Vector3();
+
+		this._parentPosition = new Vector3();
+		this._parentQuaternion = new Quaternion();
+		this._parentQuaternionInv = new Quaternion();
+		this._parentScale = new Vector3();
+
+		this._worldScaleStart = new Vector3();
+		this._worldQuaternionInv = new Quaternion();
+		this._worldScale = new Vector3();
+
+		this._positionStart = new Vector3();
+		this._quaternionStart = new Quaternion();
+		this._scaleStart = new Vector3();
+
+		this._getPointer = getPointer.bind( this );
+		this._onPointerDown = onPointerDown.bind( this );
+		this._onPointerHover = onPointerHover.bind( this );
+		this._onPointerMove = onPointerMove.bind( this );
+		this._onPointerUp = onPointerUp.bind( this );
+
+		this.domElement.addEventListener( 'pointerdown', this._onPointerDown );
+		this.domElement.addEventListener( 'pointermove', this._onPointerHover );
+		this.domElement.addEventListener( 'pointerup', this._onPointerUp );
+
+	}
+
+	// updateMatrixWorld  updates key transformation variables
+	updateMatrixWorld() {
+
+		if ( this.object !== undefined ) {
+
+			this.object.updateMatrixWorld();
+
+			if ( this.object.parent === null ) {
+
+				console.error( 'TransformControls: The attached 3D object must be a part of the scene graph.' );
+
+			} else {
+
+				this.object.parent.matrixWorld.decompose( this._parentPosition, this._parentQuaternion, this._parentScale );
+
+			}
+
+			this.object.matrixWorld.decompose( this.worldPosition, this.worldQuaternion, this._worldScale );
+
+			this._parentQuaternionInv.copy( this._parentQuaternion ).invert();
+			this._worldQuaternionInv.copy( this.worldQuaternion ).invert();
+
+		}
+
+		this.camera.updateMatrixWorld();
+		this.camera.matrixWorld.decompose( this.cameraPosition, this.cameraQuaternion, this._cameraScale );
+
+		if ( this.camera.isOrthographicCamera ) {
+
+			this.camera.getWorldDirection( this.eye ).negate();
+
+		} else {
+
+			this.eye.copy( this.cameraPosition ).sub( this.worldPosition ).normalize();
+
+		}
+
+		super.updateMatrixWorld( this );
+
+	}
+
+	pointerHover( pointer ) {
+
+		if ( this.object === undefined || this.dragging === true ) return;
+
+		_raycaster.setFromCamera( pointer, this.camera );
+
+		const intersect = intersectObjectWithRay( this._gizmo.picker[ this.mode ], _raycaster );
+
+		if ( intersect ) {
+
+			this.axis = intersect.object.name;
+
+		} else {
+
+			this.axis = null;
+
+		}
+
+	}
+
+	pointerDown( pointer ) {
+
+		if ( this.object === undefined || this.dragging === true || pointer.button !== 0 ) return;
+
+		if ( this.axis !== null ) {
+
+			_raycaster.setFromCamera( pointer, this.camera );
+
+			const planeIntersect = intersectObjectWithRay( this._plane, _raycaster, true );
+
+			if ( planeIntersect ) {
+
+				this.object.updateMatrixWorld();
+				this.object.parent.updateMatrixWorld();
+
+				this._positionStart.copy( this.object.position );
+				this._quaternionStart.copy( this.object.quaternion );
+				this._scaleStart.copy( this.object.scale );
+
+				this.object.matrixWorld.decompose( this.worldPositionStart, this.worldQuaternionStart, this._worldScaleStart );
+
+				this.pointStart.copy( planeIntersect.point ).sub( this.worldPositionStart );
+
+			}
+
+			this.dragging = true;
+			_mouseDownEvent.mode = this.mode;
+			this.dispatchEvent( _mouseDownEvent );
+
+		}
+
+	}
+
+	pointerMove( pointer ) {
+
+		const axis = this.axis;
+		const mode = this.mode;
+		const object = this.object;
+		let space = this.space;
+
+		if ( mode === 'scale' ) {
+
+			space = 'local';
+
+		} else if ( axis === 'E' || axis === 'XYZE' || axis === 'XYZ' ) {
+
+			space = 'world';
+
+		}
+
+		if ( object === undefined || axis === null || this.dragging === false || pointer.button !== - 1 ) return;
+
+		_raycaster.setFromCamera( pointer, this.camera );
+
+		const planeIntersect = intersectObjectWithRay( this._plane, _raycaster, true );
+
+		if ( ! planeIntersect ) return;
+
+		this.pointEnd.copy( planeIntersect.point ).sub( this.worldPositionStart );
+
+		if ( mode === 'translate' ) {
+
+			// Apply translate
+
+			this._offset.copy( this.pointEnd ).sub( this.pointStart );
+
+			if ( space === 'local' && axis !== 'XYZ' ) {
+
+				this._offset.applyQuaternion( this._worldQuaternionInv );
+
+			}
+
+			if ( axis.indexOf( 'X' ) === - 1 ) this._offset.x = 0;
+			if ( axis.indexOf( 'Y' ) === - 1 ) this._offset.y = 0;
+			if ( axis.indexOf( 'Z' ) === - 1 ) this._offset.z = 0;
+
+			if ( space === 'local' && axis !== 'XYZ' ) {
+
+				this._offset.applyQuaternion( this._quaternionStart ).divide( this._parentScale );
+
+			} else {
+
+				this._offset.applyQuaternion( this._parentQuaternionInv ).divide( this._parentScale );
+
+			}
+
+			object.position.copy( this._offset ).add( this._positionStart );
+
+			// Apply translation snap
+
+			if ( this.translationSnap ) {
+
+				if ( space === 'local' ) {
+
+					object.position.applyQuaternion( _tempQuaternion.copy( this._quaternionStart ).invert() );
+
+					if ( axis.search( 'X' ) !== - 1 ) {
+
+						object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap;
+
+					}
+
+					if ( axis.search( 'Y' ) !== - 1 ) {
+
+						object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap;
+
+					}
+
+					if ( axis.search( 'Z' ) !== - 1 ) {
+
+						object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap;
+
+					}
+
+					object.position.applyQuaternion( this._quaternionStart );
+
+				}
+
+				if ( space === 'world' ) {
+
+					if ( object.parent ) {
+
+						object.position.add( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) );
+
+					}
+
+					if ( axis.search( 'X' ) !== - 1 ) {
+
+						object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap;
+
+					}
+
+					if ( axis.search( 'Y' ) !== - 1 ) {
+
+						object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap;
+
+					}
+
+					if ( axis.search( 'Z' ) !== - 1 ) {
+
+						object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap;
+
+					}
+
+					if ( object.parent ) {
+
+						object.position.sub( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) );
+
+					}
+
+				}
+
+			}
+
+		} else if ( mode === 'scale' ) {
+
+			if ( axis.search( 'XYZ' ) !== - 1 ) {
+
+				let d = this.pointEnd.length() / this.pointStart.length();
+
+				if ( this.pointEnd.dot( this.pointStart ) < 0 ) d *= - 1;
+
+				_tempVector2.set( d, d, d );
+
+			} else {
+
+				_tempVector.copy( this.pointStart );
+				_tempVector2.copy( this.pointEnd );
+
+				_tempVector.applyQuaternion( this._worldQuaternionInv );
+				_tempVector2.applyQuaternion( this._worldQuaternionInv );
+
+				_tempVector2.divide( _tempVector );
+
+				if ( axis.search( 'X' ) === - 1 ) {
+
+					_tempVector2.x = 1;
+
+				}
+
+				if ( axis.search( 'Y' ) === - 1 ) {
+
+					_tempVector2.y = 1;
+
+				}
+
+				if ( axis.search( 'Z' ) === - 1 ) {
+
+					_tempVector2.z = 1;
+
+				}
+
+			}
+
+			// Apply scale
+
+			object.scale.copy( this._scaleStart ).multiply( _tempVector2 );
+
+			if ( this.scaleSnap ) {
+
+				if ( axis.search( 'X' ) !== - 1 ) {
+
+					object.scale.x = Math.round( object.scale.x / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;
+
+				}
+
+				if ( axis.search( 'Y' ) !== - 1 ) {
+
+					object.scale.y = Math.round( object.scale.y / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;
+
+				}
+
+				if ( axis.search( 'Z' ) !== - 1 ) {
+
+					object.scale.z = Math.round( object.scale.z / this.scaleSnap ) * this.scaleSnap || this.scaleSnap;
+
+				}
+
+			}
+
+		} else if ( mode === 'rotate' ) {
+
+			this._offset.copy( this.pointEnd ).sub( this.pointStart );
+
+			const ROTATION_SPEED = 20 / this.worldPosition.distanceTo( _tempVector.setFromMatrixPosition( this.camera.matrixWorld ) );
+
+			let _inPlaneRotation = false;
+
+			if ( axis === 'XYZE' ) {
+
+				this.rotationAxis.copy( this._offset ).cross( this.eye ).normalize();
+				this.rotationAngle = this._offset.dot( _tempVector.copy( this.rotationAxis ).cross( this.eye ) ) * ROTATION_SPEED;
+
+			} else if ( axis === 'X' || axis === 'Y' || axis === 'Z' ) {
+
+				this.rotationAxis.copy( _unit[ axis ] );
+
+				_tempVector.copy( _unit[ axis ] );
+
+				if ( space === 'local' ) {
+
+					_tempVector.applyQuaternion( this.worldQuaternion );
+
+				}
+
+				_tempVector.cross( this.eye );
+
+				// When _tempVector is 0 after cross with this.eye the vectors are parallel and should use in-plane rotation logic.
+				if ( _tempVector.length() === 0 ) {
+
+					_inPlaneRotation = true;
+
+				} else {
+
+					this.rotationAngle = this._offset.dot( _tempVector.normalize() ) * ROTATION_SPEED;
+
+				}
+
+
+			}
+
+			if ( axis === 'E' || _inPlaneRotation ) {
+
+				this.rotationAxis.copy( this.eye );
+				this.rotationAngle = this.pointEnd.angleTo( this.pointStart );
+
+				this._startNorm.copy( this.pointStart ).normalize();
+				this._endNorm.copy( this.pointEnd ).normalize();
+
+				this.rotationAngle *= ( this._endNorm.cross( this._startNorm ).dot( this.eye ) < 0 ? 1 : - 1 );
+
+			}
+
+			// Apply rotation snap
+
+			if ( this.rotationSnap ) this.rotationAngle = Math.round( this.rotationAngle / this.rotationSnap ) * this.rotationSnap;
+
+			// Apply rotate
+			if ( space === 'local' && axis !== 'E' && axis !== 'XYZE' ) {
+
+				object.quaternion.copy( this._quaternionStart );
+				object.quaternion.multiply( _tempQuaternion.setFromAxisAngle( this.rotationAxis, this.rotationAngle ) ).normalize();
+
+			} else {
+
+				this.rotationAxis.applyQuaternion( this._parentQuaternionInv );
+				object.quaternion.copy( _tempQuaternion.setFromAxisAngle( this.rotationAxis, this.rotationAngle ) );
+				object.quaternion.multiply( this._quaternionStart ).normalize();
+
+			}
+
+		}
+
+		this.dispatchEvent( _changeEvent );
+		this.dispatchEvent( _objectChangeEvent );
+
+	}
+
+	pointerUp( pointer ) {
+
+		if ( pointer.button !== 0 ) return;
+
+		if ( this.dragging && ( this.axis !== null ) ) {
+
+			_mouseUpEvent.mode = this.mode;
+			this.dispatchEvent( _mouseUpEvent );
+
+		}
+
+		this.dragging = false;
+		this.axis = null;
+
+	}
+
+	dispose() {
+
+		this.domElement.removeEventListener( 'pointerdown', this._onPointerDown );
+		this.domElement.removeEventListener( 'pointermove', this._onPointerHover );
+		this.domElement.removeEventListener( 'pointermove', this._onPointerMove );
+		this.domElement.removeEventListener( 'pointerup', this._onPointerUp );
+
+		this.traverse( function ( child ) {
+
+			if ( child.geometry ) child.geometry.dispose();
+			if ( child.material ) child.material.dispose();
+
+		} );
+
+	}
+
+	// Set current object
+	attach( object ) {
+
+		this.object = object;
+		this.visible = true;
+
+		return this;
+
+	}
+
+	// Detach from object
+	detach() {
+
+		this.object = undefined;
+		this.visible = false;
+		this.axis = null;
+
+		return this;
+
+	}
+
+	reset() {
+
+		if ( ! this.enabled ) return;
+
+		if ( this.dragging ) {
+
+			this.object.position.copy( this._positionStart );
+			this.object.quaternion.copy( this._quaternionStart );
+			this.object.scale.copy( this._scaleStart );
+
+			this.dispatchEvent( _changeEvent );
+			this.dispatchEvent( _objectChangeEvent );
+
+			this.pointStart.copy( this.pointEnd );
+
+		}
+
+	}
+
+	getRaycaster() {
+
+		return _raycaster;
+
+	}
+
+	// TODO: deprecate
+
+	getMode() {
+
+		return this.mode;
+
+	}
+
+	setMode( mode ) {
+
+		this.mode = mode;
+
+	}
+
+	setTranslationSnap( translationSnap ) {
+
+		this.translationSnap = translationSnap;
+
+	}
+
+	setRotationSnap( rotationSnap ) {
+
+		this.rotationSnap = rotationSnap;
+
+	}
+
+	setScaleSnap( scaleSnap ) {
+
+		this.scaleSnap = scaleSnap;
+
+	}
+
+	setSize( size ) {
+
+		this.size = size;
+
+	}
+
+	setSpace( space ) {
+
+		this.space = space;
+
+	}
+
+}
+
+// mouse / touch event handlers
+
+function getPointer( event ) {
+
+	if ( this.domElement.ownerDocument.pointerLockElement ) {
+
+		return {
+			x: 0,
+			y: 0,
+			button: event.button
+		};
+
+	} else {
+
+		const rect = this.domElement.getBoundingClientRect();
+
+		return {
+			x: ( event.clientX - rect.left ) / rect.width * 2 - 1,
+			y: - ( event.clientY - rect.top ) / rect.height * 2 + 1,
+			button: event.button
+		};
+
+	}
+
+}
+
+function onPointerHover( event ) {
+
+	if ( ! this.enabled ) return;
+
+	switch ( event.pointerType ) {
+
+		case 'mouse':
+		case 'pen':
+			this.pointerHover( this._getPointer( event ) );
+			break;
+
+	}
+
+}
+
+function onPointerDown( event ) {
+
+	if ( ! this.enabled ) return;
+
+	if ( ! document.pointerLockElement ) {
+
+		this.domElement.setPointerCapture( event.pointerId );
+
+	}
+
+	this.domElement.addEventListener( 'pointermove', this._onPointerMove );
+
+	this.pointerHover( this._getPointer( event ) );
+	this.pointerDown( this._getPointer( event ) );
+
+}
+
+function onPointerMove( event ) {
+
+	if ( ! this.enabled ) return;
+
+	this.pointerMove( this._getPointer( event ) );
+
+}
+
+function onPointerUp( event ) {
+
+	if ( ! this.enabled ) return;
+
+	this.domElement.releasePointerCapture( event.pointerId );
+
+	this.domElement.removeEventListener( 'pointermove', this._onPointerMove );
+
+	this.pointerUp( this._getPointer( event ) );
+
+}
+
+function intersectObjectWithRay( object, raycaster, includeInvisible ) {
+
+	const allIntersections = raycaster.intersectObject( object, true );
+
+	for ( let i = 0; i < allIntersections.length; i ++ ) {
+
+		if ( allIntersections[ i ].object.visible || includeInvisible ) {
+
+			return allIntersections[ i ];
+
+		}
+
+	}
+
+	return false;
+
+}
+
+//
+
+// Reusable utility variables
+
+const _tempEuler = new Euler();
+const _alignVector = new Vector3( 0, 1, 0 );
+const _zeroVector = new Vector3( 0, 0, 0 );
+const _lookAtMatrix = new Matrix4();
+const _tempQuaternion2 = new Quaternion();
+const _identityQuaternion = new Quaternion();
+const _dirVector = new Vector3();
+const _tempMatrix = new Matrix4();
+
+const _unitX = new Vector3( 1, 0, 0 );
+const _unitY = new Vector3( 0, 1, 0 );
+const _unitZ = new Vector3( 0, 0, 1 );
+
+const _v1 = new Vector3();
+const _v2 = new Vector3();
+const _v3 = new Vector3();
+
+class TransformControlsGizmo extends Object3D {
+
+	constructor() {
+
+		super();
+
+		this.isTransformControlsGizmo = true;
+
+		this.type = 'TransformControlsGizmo';
+
+		// shared materials
+
+		const gizmoMaterial = new MeshBasicMaterial( {
+			depthTest: false,
+			depthWrite: false,
+			fog: false,
+			toneMapped: false,
+			transparent: true
+		} );
+
+		const gizmoLineMaterial = new LineBasicMaterial( {
+			depthTest: false,
+			depthWrite: false,
+			fog: false,
+			toneMapped: false,
+			transparent: true
+		} );
+
+		// Make unique material for each axis/color
+
+		const matInvisible = gizmoMaterial.clone();
+		matInvisible.opacity = 0.15;
+
+		const matHelper = gizmoLineMaterial.clone();
+		matHelper.opacity = 0.5;
+
+		const matRed = gizmoMaterial.clone();
+		matRed.color.setHex( 0xff0000 );
+
+		const matGreen = gizmoMaterial.clone();
+		matGreen.color.setHex( 0x00ff00 );
+
+		const matBlue = gizmoMaterial.clone();
+		matBlue.color.setHex( 0x0000ff );
+
+		const matRedTransparent = gizmoMaterial.clone();
+		matRedTransparent.color.setHex( 0xff0000 );
+		matRedTransparent.opacity = 0.5;
+
+		const matGreenTransparent = gizmoMaterial.clone();
+		matGreenTransparent.color.setHex( 0x00ff00 );
+		matGreenTransparent.opacity = 0.5;
+
+		const matBlueTransparent = gizmoMaterial.clone();
+		matBlueTransparent.color.setHex( 0x0000ff );
+		matBlueTransparent.opacity = 0.5;
+
+		const matWhiteTransparent = gizmoMaterial.clone();
+		matWhiteTransparent.opacity = 0.25;
+
+		const matYellowTransparent = gizmoMaterial.clone();
+		matYellowTransparent.color.setHex( 0xffff00 );
+		matYellowTransparent.opacity = 0.25;
+
+		const matYellow = gizmoMaterial.clone();
+		matYellow.color.setHex( 0xffff00 );
+
+		const matGray = gizmoMaterial.clone();
+		matGray.color.setHex( 0x787878 );
+
+		// reusable geometry
+
+		const arrowGeometry = new CylinderGeometry( 0, 0.04, 0.1, 12 );
+		arrowGeometry.translate( 0, 0.05, 0 );
+
+		const scaleHandleGeometry = new BoxGeometry( 0.08, 0.08, 0.08 );
+		scaleHandleGeometry.translate( 0, 0.04, 0 );
+
+		const lineGeometry = new BufferGeometry();
+		lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0,	1, 0, 0 ], 3 ) );
+
+		const lineGeometry2 = new CylinderGeometry( 0.0075, 0.0075, 0.5, 3 );
+		lineGeometry2.translate( 0, 0.25, 0 );
+
+		function CircleGeometry( radius, arc ) {
+
+			const geometry = new TorusGeometry( radius, 0.0075, 3, 64, arc * Math.PI * 2 );
+			geometry.rotateY( Math.PI / 2 );
+			geometry.rotateX( Math.PI / 2 );
+			return geometry;
+
+		}
+
+		// Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position
+
+		function TranslateHelperGeometry() {
+
+			const geometry = new BufferGeometry();
+
+			geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 1, 1, 1 ], 3 ) );
+
+			return geometry;
+
+		}
+
+		// Gizmo definitions - custom hierarchy definitions for setupGizmo() function
+
+		const gizmoTranslate = {
+			X: [
+				[ new Mesh( arrowGeometry, matRed ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
+				[ new Mesh( arrowGeometry, matRed ), [ - 0.5, 0, 0 ], [ 0, 0, Math.PI / 2 ]],
+				[ new Mesh( lineGeometry2, matRed ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]]
+			],
+			Y: [
+				[ new Mesh( arrowGeometry, matGreen ), [ 0, 0.5, 0 ]],
+				[ new Mesh( arrowGeometry, matGreen ), [ 0, - 0.5, 0 ], [ Math.PI, 0, 0 ]],
+				[ new Mesh( lineGeometry2, matGreen ) ]
+			],
+			Z: [
+				[ new Mesh( arrowGeometry, matBlue ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ]],
+				[ new Mesh( arrowGeometry, matBlue ), [ 0, 0, - 0.5 ], [ - Math.PI / 2, 0, 0 ]],
+				[ new Mesh( lineGeometry2, matBlue ), null, [ Math.PI / 2, 0, 0 ]]
+			],
+			XYZ: [
+				[ new Mesh( new OctahedronGeometry( 0.1, 0 ), matWhiteTransparent.clone() ), [ 0, 0, 0 ]]
+			],
+			XY: [
+				[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matBlueTransparent.clone() ), [ 0.15, 0.15, 0 ]]
+			],
+			YZ: [
+				[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matRedTransparent.clone() ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]]
+			],
+			XZ: [
+				[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matGreenTransparent.clone() ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]]
+			]
+		};
+
+		const pickerTranslate = {
+			X: [
+				[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0.3, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
+				[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ - 0.3, 0, 0 ], [ 0, 0, Math.PI / 2 ]]
+			],
+			Y: [
+				[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0.3, 0 ]],
+				[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, - 0.3, 0 ], [ 0, 0, Math.PI ]]
+			],
+			Z: [
+				[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, 0.3 ], [ Math.PI / 2, 0, 0 ]],
+				[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, - 0.3 ], [ - Math.PI / 2, 0, 0 ]]
+			],
+			XYZ: [
+				[ new Mesh( new OctahedronGeometry( 0.2, 0 ), matInvisible ) ]
+			],
+			XY: [
+				[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0.15, 0 ]]
+			],
+			YZ: [
+				[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]]
+			],
+			XZ: [
+				[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]]
+			]
+		};
+
+		const helperTranslate = {
+			START: [
+				[ new Mesh( new OctahedronGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]
+			],
+			END: [
+				[ new Mesh( new OctahedronGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]
+			],
+			DELTA: [
+				[ new Line( TranslateHelperGeometry(), matHelper ), null, null, null, 'helper' ]
+			],
+			X: [
+				[ new Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]
+			],
+			Y: [
+				[ new Line( lineGeometry, matHelper.clone() ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]
+			],
+			Z: [
+				[ new Line( lineGeometry, matHelper.clone() ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]
+			]
+		};
+
+		const gizmoRotate = {
+			XYZE: [
+				[ new Mesh( CircleGeometry( 0.5, 1 ), matGray ), null, [ 0, Math.PI / 2, 0 ]]
+			],
+			X: [
+				[ new Mesh( CircleGeometry( 0.5, 0.5 ), matRed ) ]
+			],
+			Y: [
+				[ new Mesh( CircleGeometry( 0.5, 0.5 ), matGreen ), null, [ 0, 0, - Math.PI / 2 ]]
+			],
+			Z: [
+				[ new Mesh( CircleGeometry( 0.5, 0.5 ), matBlue ), null, [ 0, Math.PI / 2, 0 ]]
+			],
+			E: [
+				[ new Mesh( CircleGeometry( 0.75, 1 ), matYellowTransparent ), null, [ 0, Math.PI / 2, 0 ]]
+			]
+		};
+
+		const helperRotate = {
+			AXIS: [
+				[ new Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]
+			]
+		};
+
+		const pickerRotate = {
+			XYZE: [
+				[ new Mesh( new SphereGeometry( 0.25, 10, 8 ), matInvisible ) ]
+			],
+			X: [
+				[ new Mesh( new TorusGeometry( 0.5, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, - Math.PI / 2, - Math.PI / 2 ]],
+			],
+			Y: [
+				[ new Mesh( new TorusGeometry( 0.5, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ]],
+			],
+			Z: [
+				[ new Mesh( new TorusGeometry( 0.5, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
+			],
+			E: [
+				[ new Mesh( new TorusGeometry( 0.75, 0.1, 2, 24 ), matInvisible ) ]
+			]
+		};
+
+		const gizmoScale = {
+			X: [
+				[ new Mesh( scaleHandleGeometry, matRed ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
+				[ new Mesh( lineGeometry2, matRed ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
+				[ new Mesh( scaleHandleGeometry, matRed ), [ - 0.5, 0, 0 ], [ 0, 0, Math.PI / 2 ]],
+			],
+			Y: [
+				[ new Mesh( scaleHandleGeometry, matGreen ), [ 0, 0.5, 0 ]],
+				[ new Mesh( lineGeometry2, matGreen ) ],
+				[ new Mesh( scaleHandleGeometry, matGreen ), [ 0, - 0.5, 0 ], [ 0, 0, Math.PI ]],
+			],
+			Z: [
+				[ new Mesh( scaleHandleGeometry, matBlue ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ]],
+				[ new Mesh( lineGeometry2, matBlue ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ]],
+				[ new Mesh( scaleHandleGeometry, matBlue ), [ 0, 0, - 0.5 ], [ - Math.PI / 2, 0, 0 ]]
+			],
+			XY: [
+				[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matBlueTransparent ), [ 0.15, 0.15, 0 ]]
+			],
+			YZ: [
+				[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matRedTransparent ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]]
+			],
+			XZ: [
+				[ new Mesh( new BoxGeometry( 0.15, 0.15, 0.01 ), matGreenTransparent ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]]
+			],
+			XYZ: [
+				[ new Mesh( new BoxGeometry( 0.1, 0.1, 0.1 ), matWhiteTransparent.clone() ) ],
+			]
+		};
+
+		const pickerScale = {
+			X: [
+				[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0.3, 0, 0 ], [ 0, 0, - Math.PI / 2 ]],
+				[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ - 0.3, 0, 0 ], [ 0, 0, Math.PI / 2 ]]
+			],
+			Y: [
+				[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0.3, 0 ]],
+				[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, - 0.3, 0 ], [ 0, 0, Math.PI ]]
+			],
+			Z: [
+				[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, 0.3 ], [ Math.PI / 2, 0, 0 ]],
+				[ new Mesh( new CylinderGeometry( 0.2, 0, 0.6, 4 ), matInvisible ), [ 0, 0, - 0.3 ], [ - Math.PI / 2, 0, 0 ]]
+			],
+			XY: [
+				[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0.15, 0 ]],
+			],
+			YZ: [
+				[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]],
+			],
+			XZ: [
+				[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.01 ), matInvisible ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]],
+			],
+			XYZ: [
+				[ new Mesh( new BoxGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 0, 0 ]],
+			]
+		};
+
+		const helperScale = {
+			X: [
+				[ new Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]
+			],
+			Y: [
+				[ new Line( lineGeometry, matHelper.clone() ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]
+			],
+			Z: [
+				[ new Line( lineGeometry, matHelper.clone() ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]
+			]
+		};
+
+		// Creates an Object3D with gizmos described in custom hierarchy definition.
+
+		function setupGizmo( gizmoMap ) {
+
+			const gizmo = new Object3D();
+
+			for ( const name in gizmoMap ) {
+
+				for ( let i = gizmoMap[ name ].length; i --; ) {
+
+					const object = gizmoMap[ name ][ i ][ 0 ].clone();
+					const position = gizmoMap[ name ][ i ][ 1 ];
+					const rotation = gizmoMap[ name ][ i ][ 2 ];
+					const scale = gizmoMap[ name ][ i ][ 3 ];
+					const tag = gizmoMap[ name ][ i ][ 4 ];
+
+					// name and tag properties are essential for picking and updating logic.
+					object.name = name;
+					object.tag = tag;
+
+					if ( position ) {
+
+						object.position.set( position[ 0 ], position[ 1 ], position[ 2 ] );
+
+					}
+
+					if ( rotation ) {
+
+						object.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation[ 2 ] );
+
+					}
+
+					if ( scale ) {
+
+						object.scale.set( scale[ 0 ], scale[ 1 ], scale[ 2 ] );
+
+					}
+
+					object.updateMatrix();
+
+					const tempGeometry = object.geometry.clone();
+					tempGeometry.applyMatrix4( object.matrix );
+					object.geometry = tempGeometry;
+					object.renderOrder = Infinity;
+
+					object.position.set( 0, 0, 0 );
+					object.rotation.set( 0, 0, 0 );
+					object.scale.set( 1, 1, 1 );
+
+					gizmo.add( object );
+
+				}
+
+			}
+
+			return gizmo;
+
+		}
+
+		// Gizmo creation
+
+		this.gizmo = {};
+		this.picker = {};
+		this.helper = {};
+
+		this.add( this.gizmo[ 'translate' ] = setupGizmo( gizmoTranslate ) );
+		this.add( this.gizmo[ 'rotate' ] = setupGizmo( gizmoRotate ) );
+		this.add( this.gizmo[ 'scale' ] = setupGizmo( gizmoScale ) );
+		this.add( this.picker[ 'translate' ] = setupGizmo( pickerTranslate ) );
+		this.add( this.picker[ 'rotate' ] = setupGizmo( pickerRotate ) );
+		this.add( this.picker[ 'scale' ] = setupGizmo( pickerScale ) );
+		this.add( this.helper[ 'translate' ] = setupGizmo( helperTranslate ) );
+		this.add( this.helper[ 'rotate' ] = setupGizmo( helperRotate ) );
+		this.add( this.helper[ 'scale' ] = setupGizmo( helperScale ) );
+
+		// Pickers should be hidden always
+
+		this.picker[ 'translate' ].visible = false;
+		this.picker[ 'rotate' ].visible = false;
+		this.picker[ 'scale' ].visible = false;
+
+	}
+
+	// updateMatrixWorld will update transformations and appearance of individual handles
+
+	updateMatrixWorld( force ) {
+
+		const space = ( this.mode === 'scale' ) ? 'local' : this.space; // scale always oriented to local rotation
+
+		const quaternion = ( space === 'local' ) ? this.worldQuaternion : _identityQuaternion;
+
+		// Show only gizmos for current transform mode
+
+		this.gizmo[ 'translate' ].visible = this.mode === 'translate';
+		this.gizmo[ 'rotate' ].visible = this.mode === 'rotate';
+		this.gizmo[ 'scale' ].visible = this.mode === 'scale';
+
+		this.helper[ 'translate' ].visible = this.mode === 'translate';
+		this.helper[ 'rotate' ].visible = this.mode === 'rotate';
+		this.helper[ 'scale' ].visible = this.mode === 'scale';
+
+
+		let handles = [];
+		handles = handles.concat( this.picker[ this.mode ].children );
+		handles = handles.concat( this.gizmo[ this.mode ].children );
+		handles = handles.concat( this.helper[ this.mode ].children );
+
+		for ( let i = 0; i < handles.length; i ++ ) {
+
+			const handle = handles[ i ];
+
+			// hide aligned to camera
+
+			handle.visible = true;
+			handle.rotation.set( 0, 0, 0 );
+			handle.position.copy( this.worldPosition );
+
+			let factor;
+
+			if ( this.camera.isOrthographicCamera ) {
+
+				factor = ( this.camera.top - this.camera.bottom ) / this.camera.zoom;
+
+			} else {
+
+				factor = this.worldPosition.distanceTo( this.cameraPosition ) * Math.min( 1.9 * Math.tan( Math.PI * this.camera.fov / 360 ) / this.camera.zoom, 7 );
+
+			}
+
+			handle.scale.set( 1, 1, 1 ).multiplyScalar( factor * this.size / 4 );
+
+			// TODO: simplify helpers and consider decoupling from gizmo
+
+			if ( handle.tag === 'helper' ) {
+
+				handle.visible = false;
+
+				if ( handle.name === 'AXIS' ) {
+
+					handle.visible = !! this.axis;
+
+					if ( this.axis === 'X' ) {
+
+						_tempQuaternion.setFromEuler( _tempEuler.set( 0, 0, 0 ) );
+						handle.quaternion.copy( quaternion ).multiply( _tempQuaternion );
+
+						if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {
+
+							handle.visible = false;
+
+						}
+
+					}
+
+					if ( this.axis === 'Y' ) {
+
+						_tempQuaternion.setFromEuler( _tempEuler.set( 0, 0, Math.PI / 2 ) );
+						handle.quaternion.copy( quaternion ).multiply( _tempQuaternion );
+
+						if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {
+
+							handle.visible = false;
+
+						}
+
+					}
+
+					if ( this.axis === 'Z' ) {
+
+						_tempQuaternion.setFromEuler( _tempEuler.set( 0, Math.PI / 2, 0 ) );
+						handle.quaternion.copy( quaternion ).multiply( _tempQuaternion );
+
+						if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) {
+
+							handle.visible = false;
+
+						}
+
+					}
+
+					if ( this.axis === 'XYZE' ) {
+
+						_tempQuaternion.setFromEuler( _tempEuler.set( 0, Math.PI / 2, 0 ) );
+						_alignVector.copy( this.rotationAxis );
+						handle.quaternion.setFromRotationMatrix( _lookAtMatrix.lookAt( _zeroVector, _alignVector, _unitY ) );
+						handle.quaternion.multiply( _tempQuaternion );
+						handle.visible = this.dragging;
+
+					}
+
+					if ( this.axis === 'E' ) {
+
+						handle.visible = false;
+
+					}
+
+
+				} else if ( handle.name === 'START' ) {
+
+					handle.position.copy( this.worldPositionStart );
+					handle.visible = this.dragging;
+
+				} else if ( handle.name === 'END' ) {
+
+					handle.position.copy( this.worldPosition );
+					handle.visible = this.dragging;
+
+				} else if ( handle.name === 'DELTA' ) {
+
+					handle.position.copy( this.worldPositionStart );
+					handle.quaternion.copy( this.worldQuaternionStart );
+					_tempVector.set( 1e-10, 1e-10, 1e-10 ).add( this.worldPositionStart ).sub( this.worldPosition ).multiplyScalar( - 1 );
+					_tempVector.applyQuaternion( this.worldQuaternionStart.clone().invert() );
+					handle.scale.copy( _tempVector );
+					handle.visible = this.dragging;
+
+				} else {
+
+					handle.quaternion.copy( quaternion );
+
+					if ( this.dragging ) {
+
+						handle.position.copy( this.worldPositionStart );
+
+					} else {
+
+						handle.position.copy( this.worldPosition );
+
+					}
+
+					if ( this.axis ) {
+
+						handle.visible = this.axis.search( handle.name ) !== - 1;
+
+					}
+
+				}
+
+				// If updating helper, skip rest of the loop
+				continue;
+
+			}
+
+			// Align handles to current local or world rotation
+
+			handle.quaternion.copy( quaternion );
+
+			if ( this.mode === 'translate' || this.mode === 'scale' ) {
+
+				// Hide translate and scale axis facing the camera
+
+				const AXIS_HIDE_THRESHOLD = 0.99;
+				const PLANE_HIDE_THRESHOLD = 0.2;
+
+				if ( handle.name === 'X' ) {
+
+					if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {
+
+						handle.scale.set( 1e-10, 1e-10, 1e-10 );
+						handle.visible = false;
+
+					}
+
+				}
+
+				if ( handle.name === 'Y' ) {
+
+					if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {
+
+						handle.scale.set( 1e-10, 1e-10, 1e-10 );
+						handle.visible = false;
+
+					}
+
+				}
+
+				if ( handle.name === 'Z' ) {
+
+					if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {
+
+						handle.scale.set( 1e-10, 1e-10, 1e-10 );
+						handle.visible = false;
+
+					}
+
+				}
+
+				if ( handle.name === 'XY' ) {
+
+					if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {
+
+						handle.scale.set( 1e-10, 1e-10, 1e-10 );
+						handle.visible = false;
+
+					}
+
+				}
+
+				if ( handle.name === 'YZ' ) {
+
+					if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {
+
+						handle.scale.set( 1e-10, 1e-10, 1e-10 );
+						handle.visible = false;
+
+					}
+
+				}
+
+				if ( handle.name === 'XZ' ) {
+
+					if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {
+
+						handle.scale.set( 1e-10, 1e-10, 1e-10 );
+						handle.visible = false;
+
+					}
+
+				}
+
+			} else if ( this.mode === 'rotate' ) {
+
+				// Align handles to current local or world rotation
+
+				_tempQuaternion2.copy( quaternion );
+				_alignVector.copy( this.eye ).applyQuaternion( _tempQuaternion.copy( quaternion ).invert() );
+
+				if ( handle.name.search( 'E' ) !== - 1 ) {
+
+					handle.quaternion.setFromRotationMatrix( _lookAtMatrix.lookAt( this.eye, _zeroVector, _unitY ) );
+
+				}
+
+				if ( handle.name === 'X' ) {
+
+					_tempQuaternion.setFromAxisAngle( _unitX, Math.atan2( - _alignVector.y, _alignVector.z ) );
+					_tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion );
+					handle.quaternion.copy( _tempQuaternion );
+
+				}
+
+				if ( handle.name === 'Y' ) {
+
+					_tempQuaternion.setFromAxisAngle( _unitY, Math.atan2( _alignVector.x, _alignVector.z ) );
+					_tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion );
+					handle.quaternion.copy( _tempQuaternion );
+
+				}
+
+				if ( handle.name === 'Z' ) {
+
+					_tempQuaternion.setFromAxisAngle( _unitZ, Math.atan2( _alignVector.y, _alignVector.x ) );
+					_tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion );
+					handle.quaternion.copy( _tempQuaternion );
+
+				}
+
+			}
+
+			// Hide disabled axes
+			handle.visible = handle.visible && ( handle.name.indexOf( 'X' ) === - 1 || this.showX );
+			handle.visible = handle.visible && ( handle.name.indexOf( 'Y' ) === - 1 || this.showY );
+			handle.visible = handle.visible && ( handle.name.indexOf( 'Z' ) === - 1 || this.showZ );
+			handle.visible = handle.visible && ( handle.name.indexOf( 'E' ) === - 1 || ( this.showX && this.showY && this.showZ ) );
+
+			// highlight selected axis
+
+			handle.material._color = handle.material._color || handle.material.color.clone();
+			handle.material._opacity = handle.material._opacity || handle.material.opacity;
+
+			handle.material.color.copy( handle.material._color );
+			handle.material.opacity = handle.material._opacity;
+
+			if ( this.enabled && this.axis ) {
+
+				if ( handle.name === this.axis ) {
+
+					handle.material.color.setHex( 0xffff00 );
+					handle.material.opacity = 1.0;
+
+				} else if ( this.axis.split( '' ).some( function ( a ) {
+
+					return handle.name === a;
+
+				} ) ) {
+
+					handle.material.color.setHex( 0xffff00 );
+					handle.material.opacity = 1.0;
+
+				}
+
+			}
+
+		}
+
+		super.updateMatrixWorld( force );
+
+	}
+
+}
+
+//
+
+class TransformControlsPlane extends Mesh {
+
+	constructor() {
+
+		super(
+			new PlaneGeometry( 100000, 100000, 2, 2 ),
+			new MeshBasicMaterial( { visible: false, wireframe: true, side: DoubleSide, transparent: true, opacity: 0.1, toneMapped: false } )
+		);
+
+		this.isTransformControlsPlane = true;
+
+		this.type = 'TransformControlsPlane';
+
+	}
+
+	updateMatrixWorld( force ) {
+
+		let space = this.space;
+
+		this.position.copy( this.worldPosition );
+
+		if ( this.mode === 'scale' ) space = 'local'; // scale always oriented to local rotation
+
+		_v1.copy( _unitX ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion );
+		_v2.copy( _unitY ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion );
+		_v3.copy( _unitZ ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion );
+
+		// Align the plane for current transform mode, axis and space.
+
+		_alignVector.copy( _v2 );
+
+		switch ( this.mode ) {
+
+			case 'translate':
+			case 'scale':
+				switch ( this.axis ) {
+
+					case 'X':
+						_alignVector.copy( this.eye ).cross( _v1 );
+						_dirVector.copy( _v1 ).cross( _alignVector );
+						break;
+					case 'Y':
+						_alignVector.copy( this.eye ).cross( _v2 );
+						_dirVector.copy( _v2 ).cross( _alignVector );
+						break;
+					case 'Z':
+						_alignVector.copy( this.eye ).cross( _v3 );
+						_dirVector.copy( _v3 ).cross( _alignVector );
+						break;
+					case 'XY':
+						_dirVector.copy( _v3 );
+						break;
+					case 'YZ':
+						_dirVector.copy( _v1 );
+						break;
+					case 'XZ':
+						_alignVector.copy( _v3 );
+						_dirVector.copy( _v2 );
+						break;
+					case 'XYZ':
+					case 'E':
+						_dirVector.set( 0, 0, 0 );
+						break;
+
+				}
+
+				break;
+			case 'rotate':
+			default:
+				// special case for rotate
+				_dirVector.set( 0, 0, 0 );
+
+		}
+
+		if ( _dirVector.length() === 0 ) {
+
+			// If in rotate mode, make the plane parallel to camera
+			this.quaternion.copy( this.cameraQuaternion );
+
+		} else {
+
+			_tempMatrix.lookAt( _tempVector.set( 0, 0, 0 ), _dirVector, _alignVector );
+
+			this.quaternion.setFromRotationMatrix( _tempMatrix );
+
+		}
+
+		super.updateMatrixWorld( force );
+
+	}
+
+}
+
+export { TransformControls, TransformControlsGizmo, TransformControlsPlane };
\ No newline at end of file
diff --git a/SharedLibs/ThreeAddons/src/examples/jsm/postprocessing/OutlinePass.js b/SharedLibs/ThreeAddons/src/examples/jsm/postprocessing/OutlinePass.js
new file mode 100644
index 000000000000..df701b86cd17
--- /dev/null
+++ b/SharedLibs/ThreeAddons/src/examples/jsm/postprocessing/OutlinePass.js
@@ -0,0 +1,654 @@
+import {
+	AdditiveBlending,
+	Color,
+	DoubleSide,
+	HalfFloatType,
+	Matrix4,
+	MeshDepthMaterial,
+	NoBlending,
+	RGBADepthPacking,
+	ShaderMaterial,
+	UniformsUtils,
+	Vector2,
+	Vector3,
+	WebGLRenderTarget
+} from 'three';
+import { Pass, FullScreenQuad } from './Pass.js';
+import { CopyShader } from '../shaders/CopyShader.js';
+
+class OutlinePass extends Pass {
+
+	constructor( resolution, scene, camera, selectedObjects ) {
+
+		super();
+
+		this.renderScene = scene;
+		this.renderCamera = camera;
+		this.selectedObjects = selectedObjects !== undefined ? selectedObjects : [];
+		this.visibleEdgeColor = new Color( 1, 1, 1 );
+		this.hiddenEdgeColor = new Color( 0.1, 0.04, 0.02 );
+		this.edgeGlow = 0.0;
+		this.usePatternTexture = false;
+		this.edgeThickness = 1.0;
+		this.edgeStrength = 3.0;
+		this.downSampleRatio = 2;
+		this.pulsePeriod = 0;
+
+		this._visibilityCache = new Map();
+
+
+		this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 );
+
+		const resx = Math.round( this.resolution.x / this.downSampleRatio );
+		const resy = Math.round( this.resolution.y / this.downSampleRatio );
+
+		this.renderTargetMaskBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y );
+		this.renderTargetMaskBuffer.texture.name = 'OutlinePass.mask';
+		this.renderTargetMaskBuffer.texture.generateMipmaps = false;
+
+		this.depthMaterial = new MeshDepthMaterial();
+		this.depthMaterial.side = DoubleSide;
+		this.depthMaterial.depthPacking = RGBADepthPacking;
+		this.depthMaterial.blending = NoBlending;
+
+		this.prepareMaskMaterial = this.getPrepareMaskMaterial();
+		this.prepareMaskMaterial.side = DoubleSide;
+		this.prepareMaskMaterial.fragmentShader = replaceDepthToViewZ( this.prepareMaskMaterial.fragmentShader, this.renderCamera );
+
+		this.renderTargetDepthBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y, { type: HalfFloatType } );
+		this.renderTargetDepthBuffer.texture.name = 'OutlinePass.depth';
+		this.renderTargetDepthBuffer.texture.generateMipmaps = false;
+
+		this.renderTargetMaskDownSampleBuffer = new WebGLRenderTarget( resx, resy, { type: HalfFloatType } );
+		this.renderTargetMaskDownSampleBuffer.texture.name = 'OutlinePass.depthDownSample';
+		this.renderTargetMaskDownSampleBuffer.texture.generateMipmaps = false;
+
+		this.renderTargetBlurBuffer1 = new WebGLRenderTarget( resx, resy, { type: HalfFloatType } );
+		this.renderTargetBlurBuffer1.texture.name = 'OutlinePass.blur1';
+		this.renderTargetBlurBuffer1.texture.generateMipmaps = false;
+		this.renderTargetBlurBuffer2 = new WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), { type: HalfFloatType } );
+		this.renderTargetBlurBuffer2.texture.name = 'OutlinePass.blur2';
+		this.renderTargetBlurBuffer2.texture.generateMipmaps = false;
+
+		this.edgeDetectionMaterial = this.getEdgeDetectionMaterial();
+		this.renderTargetEdgeBuffer1 = new WebGLRenderTarget( resx, resy, { type: HalfFloatType } );
+		this.renderTargetEdgeBuffer1.texture.name = 'OutlinePass.edge1';
+		this.renderTargetEdgeBuffer1.texture.generateMipmaps = false;
+		this.renderTargetEdgeBuffer2 = new WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), { type: HalfFloatType } );
+		this.renderTargetEdgeBuffer2.texture.name = 'OutlinePass.edge2';
+		this.renderTargetEdgeBuffer2.texture.generateMipmaps = false;
+
+		const MAX_EDGE_THICKNESS = 4;
+		const MAX_EDGE_GLOW = 4;
+
+		this.separableBlurMaterial1 = this.getSeperableBlurMaterial( MAX_EDGE_THICKNESS );
+		this.separableBlurMaterial1.uniforms[ 'texSize' ].value.set( resx, resy );
+		this.separableBlurMaterial1.uniforms[ 'kernelRadius' ].value = 1;
+		this.separableBlurMaterial2 = this.getSeperableBlurMaterial( MAX_EDGE_GLOW );
+		this.separableBlurMaterial2.uniforms[ 'texSize' ].value.set( Math.round( resx / 2 ), Math.round( resy / 2 ) );
+		this.separableBlurMaterial2.uniforms[ 'kernelRadius' ].value = MAX_EDGE_GLOW;
+
+		// Overlay material
+		this.overlayMaterial = this.getOverlayMaterial();
+
+		// copy material
+
+		const copyShader = CopyShader;
+
+		this.copyUniforms = UniformsUtils.clone( copyShader.uniforms );
+
+		this.materialCopy = new ShaderMaterial( {
+			uniforms: this.copyUniforms,
+			vertexShader: copyShader.vertexShader,
+			fragmentShader: copyShader.fragmentShader,
+			blending: NoBlending,
+			depthTest: false,
+			depthWrite: false
+		} );
+
+		this.enabled = true;
+		this.needsSwap = false;
+
+		this._oldClearColor = new Color();
+		this.oldClearAlpha = 1;
+
+		this.fsQuad = new FullScreenQuad( null );
+
+		this.tempPulseColor1 = new Color();
+		this.tempPulseColor2 = new Color();
+		this.textureMatrix = new Matrix4();
+
+		function replaceDepthToViewZ( string, camera ) {
+
+			const type = camera.isPerspectiveCamera ? 'perspective' : 'orthographic';
+
+			return string.replace( /DEPTH_TO_VIEW_Z/g, type + 'DepthToViewZ' );
+
+		}
+
+	}
+
+	dispose() {
+
+		this.renderTargetMaskBuffer.dispose();
+		this.renderTargetDepthBuffer.dispose();
+		this.renderTargetMaskDownSampleBuffer.dispose();
+		this.renderTargetBlurBuffer1.dispose();
+		this.renderTargetBlurBuffer2.dispose();
+		this.renderTargetEdgeBuffer1.dispose();
+		this.renderTargetEdgeBuffer2.dispose();
+
+		this.depthMaterial.dispose();
+		this.prepareMaskMaterial.dispose();
+		this.edgeDetectionMaterial.dispose();
+		this.separableBlurMaterial1.dispose();
+		this.separableBlurMaterial2.dispose();
+		this.overlayMaterial.dispose();
+		this.materialCopy.dispose();
+
+		this.fsQuad.dispose();
+
+	}
+
+	setSize( width, height ) {
+
+		this.renderTargetMaskBuffer.setSize( width, height );
+		this.renderTargetDepthBuffer.setSize( width, height );
+
+		let resx = Math.round( width / this.downSampleRatio );
+		let resy = Math.round( height / this.downSampleRatio );
+		this.renderTargetMaskDownSampleBuffer.setSize( resx, resy );
+		this.renderTargetBlurBuffer1.setSize( resx, resy );
+		this.renderTargetEdgeBuffer1.setSize( resx, resy );
+		this.separableBlurMaterial1.uniforms[ 'texSize' ].value.set( resx, resy );
+
+		resx = Math.round( resx / 2 );
+		resy = Math.round( resy / 2 );
+
+		this.renderTargetBlurBuffer2.setSize( resx, resy );
+		this.renderTargetEdgeBuffer2.setSize( resx, resy );
+
+		this.separableBlurMaterial2.uniforms[ 'texSize' ].value.set( resx, resy );
+
+	}
+
+	changeVisibilityOfSelectedObjects( bVisible ) {
+
+		const cache = this._visibilityCache;
+
+		function gatherSelectedMeshesCallBack( object ) {
+
+			if ( object.isMesh ) {
+
+				if ( bVisible === true ) {
+
+					object.visible = cache.get( object );
+
+				} else {
+
+					cache.set( object, object.visible );
+					object.visible = bVisible;
+
+				}
+
+			}
+
+		}
+
+		for ( let i = 0; i < this.selectedObjects.length; i ++ ) {
+
+			const selectedObject = this.selectedObjects[ i ];
+			selectedObject.traverse( gatherSelectedMeshesCallBack );
+
+		}
+
+	}
+
+	changeVisibilityOfNonSelectedObjects( bVisible ) {
+
+		const cache = this._visibilityCache;
+		const selectedMeshes = [];
+
+		function gatherSelectedMeshesCallBack( object ) {
+
+			if ( object.isMesh ) selectedMeshes.push( object );
+
+		}
+
+		for ( let i = 0; i < this.selectedObjects.length; i ++ ) {
+
+			const selectedObject = this.selectedObjects[ i ];
+			selectedObject.traverse( gatherSelectedMeshesCallBack );
+
+		}
+
+		function VisibilityChangeCallBack( object ) {
+
+			if ( object.isMesh || object.isSprite ) {
+
+				// only meshes and sprites are supported by OutlinePass
+
+				let bFound = false;
+
+				for ( let i = 0; i < selectedMeshes.length; i ++ ) {
+
+					const selectedObjectId = selectedMeshes[ i ].id;
+
+					if ( selectedObjectId === object.id ) {
+
+						bFound = true;
+						break;
+
+					}
+
+				}
+
+				if ( bFound === false ) {
+
+					const visibility = object.visible;
+
+					if ( bVisible === false || cache.get( object ) === true ) {
+
+						object.visible = bVisible;
+
+					}
+
+					cache.set( object, visibility );
+
+				}
+
+			} else if ( object.isPoints || object.isLine ) {
+
+				// the visibilty of points and lines is always set to false in order to
+				// not affect the outline computation
+
+				if ( bVisible === true ) {
+
+					object.visible = cache.get( object ); // restore
+
+				} else {
+
+					cache.set( object, object.visible );
+					object.visible = bVisible;
+
+				}
+
+			}
+
+		}
+
+		this.renderScene.traverse( VisibilityChangeCallBack );
+
+	}
+
+	updateTextureMatrix() {
+
+		this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5,
+			0.0, 0.5, 0.0, 0.5,
+			0.0, 0.0, 0.5, 0.5,
+			0.0, 0.0, 0.0, 1.0 );
+		this.textureMatrix.multiply( this.renderCamera.projectionMatrix );
+		this.textureMatrix.multiply( this.renderCamera.matrixWorldInverse );
+
+	}
+
+	render( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
+
+		if ( this.selectedObjects.length > 0 ) {
+
+			renderer.getClearColor( this._oldClearColor );
+			this.oldClearAlpha = renderer.getClearAlpha();
+			const oldAutoClear = renderer.autoClear;
+
+			renderer.autoClear = false;
+
+			if ( maskActive ) renderer.state.buffers.stencil.setTest( false );
+
+			renderer.setClearColor( 0xffffff, 1 );
+
+			// Make selected objects invisible
+			this.changeVisibilityOfSelectedObjects( false );
+
+			const currentBackground = this.renderScene.background;
+			this.renderScene.background = null;
+
+			// 1. Draw Non Selected objects in the depth buffer
+			this.renderScene.overrideMaterial = this.depthMaterial;
+			renderer.setRenderTarget( this.renderTargetDepthBuffer );
+			renderer.clear();
+			renderer.render( this.renderScene, this.renderCamera );
+
+			// Make selected objects visible
+			this.changeVisibilityOfSelectedObjects( true );
+			this._visibilityCache.clear();
+
+			// Update Texture Matrix for Depth compare
+			this.updateTextureMatrix();
+
+			// Make non selected objects invisible, and draw only the selected objects, by comparing the depth buffer of non selected objects
+			this.changeVisibilityOfNonSelectedObjects( false );
+			this.renderScene.overrideMaterial = this.prepareMaskMaterial;
+			this.prepareMaskMaterial.uniforms[ 'cameraNearFar' ].value.set( this.renderCamera.near, this.renderCamera.far );
+			this.prepareMaskMaterial.uniforms[ 'depthTexture' ].value = this.renderTargetDepthBuffer.texture;
+			this.prepareMaskMaterial.uniforms[ 'textureMatrix' ].value = this.textureMatrix;
+			renderer.setRenderTarget( this.renderTargetMaskBuffer );
+			renderer.clear();
+			renderer.render( this.renderScene, this.renderCamera );
+			this.renderScene.overrideMaterial = null;
+			this.changeVisibilityOfNonSelectedObjects( true );
+			this._visibilityCache.clear();
+
+			this.renderScene.background = currentBackground;
+
+			// 2. Downsample to Half resolution
+			this.fsQuad.material = this.materialCopy;
+			this.copyUniforms[ 'tDiffuse' ].value = this.renderTargetMaskBuffer.texture;
+			renderer.setRenderTarget( this.renderTargetMaskDownSampleBuffer );
+			renderer.clear();
+			this.fsQuad.render( renderer );
+
+			this.tempPulseColor1.copy( this.visibleEdgeColor );
+			this.tempPulseColor2.copy( this.hiddenEdgeColor );
+
+			if ( this.pulsePeriod > 0 ) {
+
+				const scalar = ( 1 + 0.25 ) / 2 + Math.cos( performance.now() * 0.01 / this.pulsePeriod ) * ( 1.0 - 0.25 ) / 2;
+				this.tempPulseColor1.multiplyScalar( scalar );
+				this.tempPulseColor2.multiplyScalar( scalar );
+
+			}
+
+			// 3. Apply Edge Detection Pass
+			this.fsQuad.material = this.edgeDetectionMaterial;
+			this.edgeDetectionMaterial.uniforms[ 'maskTexture' ].value = this.renderTargetMaskDownSampleBuffer.texture;
+			this.edgeDetectionMaterial.uniforms[ 'texSize' ].value.set( this.renderTargetMaskDownSampleBuffer.width, this.renderTargetMaskDownSampleBuffer.height );
+			this.edgeDetectionMaterial.uniforms[ 'visibleEdgeColor' ].value = this.tempPulseColor1;
+			this.edgeDetectionMaterial.uniforms[ 'hiddenEdgeColor' ].value = this.tempPulseColor2;
+			renderer.setRenderTarget( this.renderTargetEdgeBuffer1 );
+			renderer.clear();
+			this.fsQuad.render( renderer );
+
+			// 4. Apply Blur on Half res
+			this.fsQuad.material = this.separableBlurMaterial1;
+			this.separableBlurMaterial1.uniforms[ 'colorTexture' ].value = this.renderTargetEdgeBuffer1.texture;
+			this.separableBlurMaterial1.uniforms[ 'direction' ].value = OutlinePass.BlurDirectionX;
+			this.separableBlurMaterial1.uniforms[ 'kernelRadius' ].value = this.edgeThickness;
+			renderer.setRenderTarget( this.renderTargetBlurBuffer1 );
+			renderer.clear();
+			this.fsQuad.render( renderer );
+			this.separableBlurMaterial1.uniforms[ 'colorTexture' ].value = this.renderTargetBlurBuffer1.texture;
+			this.separableBlurMaterial1.uniforms[ 'direction' ].value = OutlinePass.BlurDirectionY;
+			renderer.setRenderTarget( this.renderTargetEdgeBuffer1 );
+			renderer.clear();
+			this.fsQuad.render( renderer );
+
+			// Apply Blur on quarter res
+			this.fsQuad.material = this.separableBlurMaterial2;
+			this.separableBlurMaterial2.uniforms[ 'colorTexture' ].value = this.renderTargetEdgeBuffer1.texture;
+			this.separableBlurMaterial2.uniforms[ 'direction' ].value = OutlinePass.BlurDirectionX;
+			renderer.setRenderTarget( this.renderTargetBlurBuffer2 );
+			renderer.clear();
+			this.fsQuad.render( renderer );
+			this.separableBlurMaterial2.uniforms[ 'colorTexture' ].value = this.renderTargetBlurBuffer2.texture;
+			this.separableBlurMaterial2.uniforms[ 'direction' ].value = OutlinePass.BlurDirectionY;
+			renderer.setRenderTarget( this.renderTargetEdgeBuffer2 );
+			renderer.clear();
+			this.fsQuad.render( renderer );
+
+			// Blend it additively over the input texture
+			this.fsQuad.material = this.overlayMaterial;
+			this.overlayMaterial.uniforms[ 'maskTexture' ].value = this.renderTargetMaskBuffer.texture;
+			this.overlayMaterial.uniforms[ 'edgeTexture1' ].value = this.renderTargetEdgeBuffer1.texture;
+			this.overlayMaterial.uniforms[ 'edgeTexture2' ].value = this.renderTargetEdgeBuffer2.texture;
+			this.overlayMaterial.uniforms[ 'patternTexture' ].value = this.patternTexture;
+			this.overlayMaterial.uniforms[ 'edgeStrength' ].value = this.edgeStrength;
+			this.overlayMaterial.uniforms[ 'edgeGlow' ].value = this.edgeGlow;
+			this.overlayMaterial.uniforms[ 'usePatternTexture' ].value = this.usePatternTexture;
+
+
+			if ( maskActive ) renderer.state.buffers.stencil.setTest( true );
+
+			renderer.setRenderTarget( readBuffer );
+			this.fsQuad.render( renderer );
+
+			renderer.setClearColor( this._oldClearColor, this.oldClearAlpha );
+			renderer.autoClear = oldAutoClear;
+
+		}
+
+		if ( this.renderToScreen ) {
+
+			this.fsQuad.material = this.materialCopy;
+			this.copyUniforms[ 'tDiffuse' ].value = readBuffer.texture;
+			renderer.setRenderTarget( null );
+			this.fsQuad.render( renderer );
+
+		}
+
+	}
+
+	getPrepareMaskMaterial() {
+
+		return new ShaderMaterial( {
+
+			uniforms: {
+				'depthTexture': { value: null },
+				'cameraNearFar': { value: new Vector2( 0.5, 0.5 ) },
+				'textureMatrix': { value: null }
+			},
+
+			vertexShader:
+				`#include <morphtarget_pars_vertex>
+				#include <skinning_pars_vertex>
+
+				varying vec4 projTexCoord;
+				varying vec4 vPosition;
+				uniform mat4 textureMatrix;
+
+				void main() {
+
+					#include <skinbase_vertex>
+					#include <begin_vertex>
+					#include <morphtarget_vertex>
+					#include <skinning_vertex>
+					#include <project_vertex>
+
+					vPosition = mvPosition;
+
+					vec4 worldPosition = vec4( transformed, 1.0 );
+
+					#ifdef USE_INSTANCING
+
+						worldPosition = instanceMatrix * worldPosition;
+
+					#endif
+
+					worldPosition = modelMatrix * worldPosition;
+
+					projTexCoord = textureMatrix * worldPosition;
+
+				}`,
+
+			fragmentShader:
+				`#include <packing>
+				varying vec4 vPosition;
+				varying vec4 projTexCoord;
+				uniform sampler2D depthTexture;
+				uniform vec2 cameraNearFar;
+
+				void main() {
+
+					float depth = unpackRGBAToDepth(texture2DProj( depthTexture, projTexCoord ));
+					float viewZ = - DEPTH_TO_VIEW_Z( depth, cameraNearFar.x, cameraNearFar.y );
+					float depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;
+					gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);
+
+				}`
+
+		} );
+
+	}
+
+	getEdgeDetectionMaterial() {
+
+		return new ShaderMaterial( {
+
+			uniforms: {
+				'maskTexture': { value: null },
+				'texSize': { value: new Vector2( 0.5, 0.5 ) },
+				'visibleEdgeColor': { value: new Vector3( 1.0, 1.0, 1.0 ) },
+				'hiddenEdgeColor': { value: new Vector3( 1.0, 1.0, 1.0 ) },
+			},
+
+			vertexShader:
+				`varying vec2 vUv;
+
+				void main() {
+					vUv = uv;
+					gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
+				}`,
+
+			fragmentShader:
+				`varying vec2 vUv;
+
+				uniform sampler2D maskTexture;
+				uniform vec2 texSize;
+				uniform vec3 visibleEdgeColor;
+				uniform vec3 hiddenEdgeColor;
+
+				void main() {
+					vec2 invSize = 1.0 / texSize;
+					vec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize);
+					vec4 c1 = texture2D( maskTexture, vUv + uvOffset.xy);
+					vec4 c2 = texture2D( maskTexture, vUv - uvOffset.xy);
+					vec4 c3 = texture2D( maskTexture, vUv + uvOffset.yw);
+					vec4 c4 = texture2D( maskTexture, vUv - uvOffset.yw);
+					float diff1 = (c1.r - c2.r)*0.5;
+					float diff2 = (c3.r - c4.r)*0.5;
+					float d = length( vec2(diff1, diff2) );
+					float a1 = min(c1.g, c2.g);
+					float a2 = min(c3.g, c4.g);
+					float visibilityFactor = min(a1, a2);
+					vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;
+					gl_FragColor = vec4(edgeColor, 1.0) * vec4(d);
+				}`
+		} );
+
+	}
+
+	getSeperableBlurMaterial( maxRadius ) {
+
+		return new ShaderMaterial( {
+
+			defines: {
+				'MAX_RADIUS': maxRadius,
+			},
+
+			uniforms: {
+				'colorTexture': { value: null },
+				'texSize': { value: new Vector2( 0.5, 0.5 ) },
+				'direction': { value: new Vector2( 0.5, 0.5 ) },
+				'kernelRadius': { value: 1.0 }
+			},
+
+			vertexShader:
+				`varying vec2 vUv;
+
+				void main() {
+					vUv = uv;
+					gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
+				}`,
+
+			fragmentShader:
+				`#include <common>
+				varying vec2 vUv;
+				uniform sampler2D colorTexture;
+				uniform vec2 texSize;
+				uniform vec2 direction;
+				uniform float kernelRadius;
+
+				float gaussianPdf(in float x, in float sigma) {
+					return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;
+				}
+
+				void main() {
+					vec2 invSize = 1.0 / texSize;
+					float sigma = kernelRadius/2.0;
+					float weightSum = gaussianPdf(0.0, sigma);
+					vec4 diffuseSum = texture2D( colorTexture, vUv) * weightSum;
+					vec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS);
+					vec2 uvOffset = delta;
+					for( int i = 1; i <= MAX_RADIUS; i ++ ) {
+						float x = kernelRadius * float(i) / float(MAX_RADIUS);
+						float w = gaussianPdf(x, sigma);
+						vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);
+						vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);
+						diffuseSum += ((sample1 + sample2) * w);
+						weightSum += (2.0 * w);
+						uvOffset += delta;
+					}
+					gl_FragColor = diffuseSum/weightSum;
+				}`
+		} );
+
+	}
+
+	getOverlayMaterial() {
+
+		return new ShaderMaterial( {
+
+			uniforms: {
+				'maskTexture': { value: null },
+				'edgeTexture1': { value: null },
+				'edgeTexture2': { value: null },
+				'patternTexture': { value: null },
+				'edgeStrength': { value: 1.0 },
+				'edgeGlow': { value: 1.0 },
+				'usePatternTexture': { value: 0.0 }
+			},
+
+			vertexShader:
+				`varying vec2 vUv;
+
+				void main() {
+					vUv = uv;
+					gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
+				}`,
+
+			fragmentShader:
+				`varying vec2 vUv;
+
+				uniform sampler2D maskTexture;
+				uniform sampler2D edgeTexture1;
+				uniform sampler2D edgeTexture2;
+				uniform sampler2D patternTexture;
+				uniform float edgeStrength;
+				uniform float edgeGlow;
+				uniform bool usePatternTexture;
+
+				void main() {
+					vec4 edgeValue1 = texture2D(edgeTexture1, vUv);
+					vec4 edgeValue2 = texture2D(edgeTexture2, vUv);
+					vec4 maskColor = texture2D(maskTexture, vUv);
+					vec4 patternColor = texture2D(patternTexture, 6.0 * vUv);
+					float visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5;
+					vec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow;
+					vec4 finalColor = edgeStrength * maskColor.r * edgeValue;
+					if(usePatternTexture)
+						finalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);
+					gl_FragColor = finalColor;
+				}`,
+			blending: AdditiveBlending,
+			depthTest: false,
+			depthWrite: false,
+			transparent: true
+		} );
+
+	}
+
+}
+
+OutlinePass.BlurDirectionX = new Vector2( 1.0, 0.0 );
+OutlinePass.BlurDirectionY = new Vector2( 0.0, 1.0 );
+
+export { OutlinePass };
\ No newline at end of file
diff --git a/SharedLibs/ThreeAddons/src/index.ts b/SharedLibs/ThreeAddons/src/index.ts
index 42a029c1be5c..6d1b143d0e86 100644
--- a/SharedLibs/ThreeAddons/src/index.ts
+++ b/SharedLibs/ThreeAddons/src/index.ts
@@ -5,14 +5,19 @@
 
 export { GLTFLoader } from "./examples/jsm/loaders/GLTFLoader";
 export { DRACOLoader } from "./examples/jsm/loaders/DRACOLoader";
+
 export * as SkeletonUtils from "./examples/jsm/utils/SkeletonUtils";
 
+export { TransformControls } from "./examples/jsm/controls/TransformControls";
+
 export { EffectComposer } from "./examples/jsm/postprocessing/EffectComposer";
 export { RenderPass } from "./examples/jsm/postprocessing/RenderPass";
+export { OutlinePass } from "./examples/jsm/postprocessing/OutlinePass";
 export { ShaderPass } from "./examples/jsm/postprocessing/ShaderPass";
 export { SMAAPass } from "./examples/jsm/postprocessing/SMAAPass";
 export { OutputPass } from "./examples/jsm/postprocessing/OutputPass";
 export { UnrealBloomPass } from "./examples/jsm/postprocessing/UnrealBloomPass";
+
 export { BrightnessContrastShader } from "./examples/jsm/shaders/BrightnessContrastShader";
 export { HueSaturationShader } from "./examples/jsm/shaders/HueSaturationShader";
 export { ExposureShader } from "./examples/jsm/shaders/ExposureShader";
diff --git a/newIDE/app/src/Debugger/index.js b/newIDE/app/src/Debugger/index.js
index 819ba4194ab5..73d2cadf70f7 100644
--- a/newIDE/app/src/Debugger/index.js
+++ b/newIDE/app/src/Debugger/index.js
@@ -266,6 +266,8 @@ export default class Debugger extends React.Component<Props, State> {
       }));
     } else if (data.command === 'hotReloader.logs') {
       // Nothing to do.
+    } else if (data.command === 'instances.updated') {
+      // Nothing to do.
     } else if (data.command === 'console.log') {
       // Filter out unavoidable warnings that do not concern non-engine devs.
       if (isUnavoidableLibraryWarning(data.payload)) return;
diff --git a/newIDE/app/src/ExportAndShare/LocalExporters/LocalPreviewLauncher/index.js b/newIDE/app/src/ExportAndShare/LocalExporters/LocalPreviewLauncher/index.js
index 4545b2db03bf..b349646ee20c 100644
--- a/newIDE/app/src/ExportAndShare/LocalExporters/LocalPreviewLauncher/index.js
+++ b/newIDE/app/src/ExportAndShare/LocalExporters/LocalPreviewLauncher/index.js
@@ -4,7 +4,6 @@ import { Trans } from '@lingui/macro';
 import * as React from 'react';
 import LocalFileSystem from '../LocalFileSystem';
 import optionalRequire from '../../../Utils/OptionalRequire';
-import { timeFunction } from '../../../Utils/TimeFunction';
 import { findGDJS } from '../../../GameEngineFinder/LocalGDJSFinder';
 import LocalNetworkPreviewDialog from './LocalNetworkPreviewDialog';
 import assignIn from 'lodash/assignIn';
diff --git a/newIDE/app/src/MainFrame/EditorContainers/SceneEditorContainer.js b/newIDE/app/src/MainFrame/EditorContainers/SceneEditorContainer.js
index 3d8ac8094012..712b9131c871 100644
--- a/newIDE/app/src/MainFrame/EditorContainers/SceneEditorContainer.js
+++ b/newIDE/app/src/MainFrame/EditorContainers/SceneEditorContainer.js
@@ -155,6 +155,7 @@ export class SceneEditorContainer extends React.Component<RenderEditorContainerP
         }
         onOpenEvents={this.props.onOpenEvents}
         isActive={isActive}
+        previewDebuggerServer={this.props.previewDebuggerServer}
         hotReloadPreviewButtonProps={this.props.hotReloadPreviewButtonProps}
         openBehaviorEvents={this.props.openBehaviorEvents}
         onExtractAsExternalLayout={this.props.onExtractAsExternalLayout}
diff --git a/newIDE/app/src/SceneEditor/EditorsDisplay.flow.js b/newIDE/app/src/SceneEditor/EditorsDisplay.flow.js
index c35747b779d3..9f371c27c4ae 100644
--- a/newIDE/app/src/SceneEditor/EditorsDisplay.flow.js
+++ b/newIDE/app/src/SceneEditor/EditorsDisplay.flow.js
@@ -39,6 +39,7 @@ export type SceneEditorsDisplayProps = {|
     multiSelect: boolean,
     targetPosition?: 'center' | 'upperCenter'
   ) => void,
+  onInstancesModified?: (Array<gdInitialInstance>) => void,
   editInstanceVariables: (instance: ?gdInitialInstance) => void,
   editObjectByName: (objectName: string, initialTab?: ObjectEditorTab) => void,
   editObjectInPropertiesPanel: (objectName: string) => void,
diff --git a/newIDE/app/src/SceneEditor/MosaicEditorsDisplay/index.js b/newIDE/app/src/SceneEditor/MosaicEditorsDisplay/index.js
index e6fa9e583dbb..b9a0fc24beef 100644
--- a/newIDE/app/src/SceneEditor/MosaicEditorsDisplay/index.js
+++ b/newIDE/app/src/SceneEditor/MosaicEditorsDisplay/index.js
@@ -96,6 +96,7 @@ const MosaicEditorsDisplay = React.forwardRef<
     initialInstances,
     selectedLayer,
     onSelectInstances,
+    onInstancesModified,
   } = props;
   const { isMobile } = useResponsiveWindowSize();
   const {
@@ -145,6 +146,13 @@ const MosaicEditorsDisplay = React.forwardRef<
 
     return editorRef.current.getInstanceSize(instance);
   }, []);
+  const _onInstancesModified = React.useCallback(
+    instances => {
+      if (onInstancesModified) onInstancesModified(instances);
+      forceUpdateInstancesList();
+    },
+    [onInstancesModified, forceUpdateInstancesList]
+  );
   const toggleEditorView = React.useCallback((editorId: EditorId) => {
     if (!editorMosaicRef.current) return;
     const config = defaultPanelConfigByEditor[editorId];
@@ -276,7 +284,7 @@ const MosaicEditorsDisplay = React.forwardRef<
               editInstanceVariables={props.editInstanceVariables}
               editObjectInPropertiesPanel={props.editObjectInPropertiesPanel}
               onEditObject={props.onEditObject}
-              onInstancesModified={forceUpdateInstancesList}
+              onInstancesModified={_onInstancesModified}
               onGetInstanceSize={getInstanceSize}
               ref={instanceOrObjectPropertiesEditorRef}
               unsavedChanges={props.unsavedChanges}
diff --git a/newIDE/app/src/SceneEditor/index.js b/newIDE/app/src/SceneEditor/index.js
index 45b1aa058fd3..5bb9a194ce24 100644
--- a/newIDE/app/src/SceneEditor/index.js
+++ b/newIDE/app/src/SceneEditor/index.js
@@ -31,6 +31,7 @@ import getObjectByName from '../Utils/GetObjectByName';
 import UseSceneEditorCommands from './UseSceneEditorCommands';
 import { type InstancesEditorSettings } from '../InstancesEditor/InstancesEditorSettings';
 import { type ResourceManagementProps } from '../ResourcesList/ResourceSource';
+import { type PreviewDebuggerServer } from '../ExportAndShare/PreviewLauncher.flow';
 import EditSceneIcon from '../UI/CustomSvgIcons/EditScene';
 import {
   type HistoryState,
@@ -54,7 +55,10 @@ import { type InfoBarDetails } from '../Hints/ObjectsAdditionalWork';
 import { type HotReloadPreviewButtonProps } from '../HotReload/HotReloadPreviewButton';
 import EventsRootVariablesFinder from '../Utils/EventsRootVariablesFinder';
 import { MOVEMENT_BIG_DELTA } from '../UI/KeyboardShortcuts';
-import { getInstancesInLayoutForObject } from '../Utils/Layout';
+import {
+  getInstanceInLayoutWithPersistentUuid,
+  getInstancesInLayoutForObject,
+} from '../Utils/Layout';
 import { zoomInFactor, zoomOutFactor } from '../Utils/ZoomUtils';
 import debounce from 'lodash/debounce';
 import { mapFor } from '../Utils/MapFor';
@@ -138,6 +142,7 @@ type Props = {|
 
   // Preview:
   hotReloadPreviewButtonProps: HotReloadPreviewButtonProps,
+  previewDebuggerServer: ?PreviewDebuggerServer,
 |};
 
 type State = {|
@@ -191,6 +196,7 @@ export default class SceneEditor extends React.Component<Props, State> {
   contextMenu: ?ContextMenuInterface;
   editorDisplay: ?SceneEditorsDisplayInterface;
   resourceExternallyChangedCallbackId: ?string;
+  unregisterDebuggerCallback: (() => void) | null = null;
 
   constructor(props: Props) {
     super(props);
@@ -248,17 +254,66 @@ export default class SceneEditor extends React.Component<Props, State> {
     this.resourceExternallyChangedCallbackId = registerOnResourceExternallyChangedCallback(
       this.onResourceExternallyChanged.bind(this)
     );
+
+    if (this.props.previewDebuggerServer) {
+      this.unregisterDebuggerCallback = this.props.previewDebuggerServer.registerCallbacks(
+        {
+          onErrorReceived: () => {},
+          onConnectionClosed: () => {},
+          onConnectionOpened: () => {},
+          onConnectionErrored: () => {},
+          onServerStateChanged: () => {},
+          onHandleParsedMessage: this.onReceiveMessageFromGame.bind(this),
+        }
+      );
+    }
   }
   componentWillUnmount() {
     unregisterOnResourceExternallyChangedCallback(
       this.resourceExternallyChangedCallbackId
     );
+    if (this.unregisterDebuggerCallback) {
+      this.unregisterDebuggerCallback();
+    }
   }
 
   getInstancesEditorSettings() {
     return this.state.instancesEditorSettings;
   }
 
+  onReceiveMessageFromGame({
+    id,
+    parsedMessage,
+  }: {
+    id: number,
+    parsedMessage: {| command: string, payload: any |},
+  }) {
+    if (parsedMessage.command === 'instances.updated') {
+      if (
+        !this.props.layout ||
+        this.props.layout.getName() !== parsedMessage.payload.layoutName
+      ) {
+        // TODO: handle external layout as well.
+        return;
+      }
+      const modifiedInstances: gdInitialInstance[] = [];
+      parsedMessage.payload.instances.forEach(instanceUpdateData => {
+        const { persistentUuid, position } = instanceUpdateData;
+        const instance = getInstanceInLayoutWithPersistentUuid(
+          this.props.initialInstances,
+          persistentUuid
+        );
+        if (!instance) return;
+        instance.setX(position.x);
+        instance.setY(position.y);
+        instance.setZ(position.z);
+
+        modifiedInstances.push(instance);
+      });
+      this._onInstancesMoved(modifiedInstances);
+    }
+  }
+
   onResourceExternallyChanged = async (resourceInfo: {|
     identifier: string,
   |}) => {
@@ -814,7 +869,42 @@ export default class SceneEditor extends React.Component<Props, State> {
     );
   };
 
+  _exportDataOnly = debounce(() => {
+    this.props.hotReloadPreviewButtonProps.launchProjectDataOnlyPreview();
+  }, 250);
+
+  /**
+   * TODO: Accept parameter that indicates which data has been modified
+   * (position, rotation, size, something else?)
+   */
   _onInstancesModified = (instances: Array<gdInitialInstance>) => {
+    const { previewDebuggerServer, layout } = this.props;
+    if (!layout) {
+      // TODO: Handle external layout
+      return;
+    }
+    if (!previewDebuggerServer) return;
+
+    previewDebuggerServer.getExistingDebuggerIds().forEach(debuggerId => {
+      previewDebuggerServer.sendMessage(debuggerId, {
+        command: 'instances.updated',
+        payload: {
+          layoutName: layout.getName(),
+          instances: instances.map(instance => ({
+            persistentUuid: instance.getPersistentUuid(),
+            position: {
+              x: instance.getX(),
+              y: instance.getY(),
+              z: instance.getZ(),
+            },
+          })),
+        },
+      });
+    });
+    // TODO: Create a new export mode that will generate only the bare minimum
+    // so that the runtime game has up-to-date data without unnecessary reloading scripts.
+    // Once the mode exists, call it here.
+    // this._exportDataOnly();
     this.forceUpdate();
     //TODO: Save for redo with debounce (and cancel on unmount)
   };
@@ -1971,6 +2061,7 @@ export default class SceneEditor extends React.Component<Props, State> {
                 initialInstances={initialInstances}
                 instancesSelection={this.instancesSelection}
                 onSelectInstances={this._onSelectInstances}
+                onInstancesModified={this._onInstancesModified}
                 onAddObjectInstance={this.addInstanceOnTheScene}
                 selectedLayer={this.state.selectedLayer}
                 editLayer={this.editLayer}
diff --git a/newIDE/app/src/Utils/Layout.js b/newIDE/app/src/Utils/Layout.js
index 079e23b78383..09edaa369bb1 100644
--- a/newIDE/app/src/Utils/Layout.js
+++ b/newIDE/app/src/Utils/Layout.js
@@ -1,6 +1,30 @@
 // @flow
 const gd: libGDevelop = global.gd;
 
+export const getInstanceInLayoutWithPersistentUuid = (
+  initialInstancesContainer: gdInitialInstancesContainer,
+  persistentUuid: string
+): gdInitialInstance | null => {
+  if (initialInstancesContainer.getInstancesCount() === 0) return null;
+  let matchingInstance = null;
+  const instanceGetter = new gd.InitialInstanceJSFunctor();
+  // $FlowFixMe - invoke is not writable
+  instanceGetter.invoke = instancePtr => {
+    // $FlowFixMe - wrapPointer is not exposed
+    const instance: gdInitialInstance = gd.wrapPointer(
+      instancePtr,
+      gd.InitialInstance
+    );
+    if (instance.getPersistentUuid() === persistentUuid) {
+      matchingInstance = instance;
+    }
+  };
+  // $FlowFixMe - JSFunctor is incompatible with Functor
+  initialInstancesContainer.iterateOverInstances(instanceGetter);
+  instanceGetter.delete();
+  return matchingInstance;
+};
+
 export const getInstancesInLayoutForObject = (
   initialInstancesContainer: gdInitialInstancesContainer,
   objectName: string