diff --git a/docs/en/graphics/material/examples/shaderlab-05-advance.mdx b/docs/en/graphics/material/examples/shaderlab-05-advance.mdx index 4a21ce1c25..4e8c257ea1 100644 --- a/docs/en/graphics/material/examples/shaderlab-05-advance.mdx +++ b/docs/en/graphics/material/examples/shaderlab-05-advance.mdx @@ -190,7 +190,6 @@ gl_FragColor = vec4(lighting, 1.0); The engine provides a rich set of built-in variables that can be used directly, such as transformation matrix variables: ```glsl -mat4 renderer_LocalMat; // Local transformation matrix mat4 renderer_ModelMat; // Model matrix mat4 renderer_MVMat; // Model-view matrix mat4 renderer_MVPMat; // MVP matrix diff --git a/docs/en/graphics/material/shaderAPI.mdx b/docs/en/graphics/material/shaderAPI.mdx index f546447e19..63e646c37e 100644 --- a/docs/en/graphics/material/shaderAPI.mdx +++ b/docs/en/graphics/material/shaderAPI.mdx @@ -27,7 +27,6 @@ vec4 fog(vec4 color, vec3 positionVS); Provides system variables for model space, view space, world space, and camera coordinates: ```glsl -mat4 renderer_LocalMat; mat4 renderer_ModelMat; mat4 camera_ViewMat; mat4 camera_ProjMat; diff --git a/docs/en/graphics/material/variables.mdx b/docs/en/graphics/material/variables.mdx index f64f02b3a3..779f86130b 100644 --- a/docs/en/graphics/material/variables.mdx +++ b/docs/en/graphics/material/variables.mdx @@ -25,7 +25,6 @@ Below are the engine's built-in variables for reference when writing Shaders: | Name | Type | Description | | :---------------- | :--- | :--------------------------- | -| renderer_LocalMat | mat4 | Model local coordinate matrix | | renderer_ModelMat | mat4 | Model world coordinate matrix | | renderer_MVMat | mat4 | Model view matrix | | renderer_MVPMat | mat4 | Model view projection matrix | diff --git a/docs/zh/graphics/material/examples/shaderlab-05-advance.mdx b/docs/zh/graphics/material/examples/shaderlab-05-advance.mdx index c2d4d779dc..a9490581ac 100644 --- a/docs/zh/graphics/material/examples/shaderlab-05-advance.mdx +++ b/docs/zh/graphics/material/examples/shaderlab-05-advance.mdx @@ -193,7 +193,6 @@ void frag() { 引擎提供了丰富的内置变量,直接声明使用即可,比如变换矩阵相关变量: ```glsl -mat4 renderer_LocalMat; // 本地变换矩阵 mat4 renderer_ModelMat; // 模型矩阵 mat4 renderer_MVMat; // 模型视图矩阵 mat4 renderer_MVPMat; // MVP矩阵 diff --git a/docs/zh/graphics/material/shaderAPI.mdx b/docs/zh/graphics/material/shaderAPI.mdx index d6fcd4ac25..0c0879054b 100644 --- a/docs/zh/graphics/material/shaderAPI.mdx +++ b/docs/zh/graphics/material/shaderAPI.mdx @@ -29,7 +29,6 @@ vec4 fog(vec4 color, vec3 positionVS); 提供了模型空间、视图空间、世界空间、相机坐标等[系统变量](/docs/graphics/material/variables/): ```glsl -mat4 renderer_LocalMat; mat4 renderer_ModelMat; mat4 camera_ViewMat; mat4 camera_ProjMat; diff --git a/docs/zh/graphics/material/variables.mdx b/docs/zh/graphics/material/variables.mdx index 6059e0d0e1..48deab814b 100644 --- a/docs/zh/graphics/material/variables.mdx +++ b/docs/zh/graphics/material/variables.mdx @@ -25,7 +25,6 @@ Shader 代码中会经常用到内置变量,一种是**逐顶点**的 `attribu | 名字 | 类型 | 解释 | | :----------------- | :--- | ------------------ | -| renderer_LocalMat | mat4 | 模型本地坐标系矩阵 | | renderer_ModelMat | mat4 | 模型世界坐标系矩阵 | | renderer_MVMat | mat4 | 模型视口矩阵 | | renderer_MVPMat | mat4 | 模型视口投影矩阵 | diff --git a/e2e/.dev/physx.release.js b/e2e/.dev/physx.release.js index 426e4ca185..f816e9dce3 100644 --- a/e2e/.dev/physx.release.js +++ b/e2e/.dev/physx.release.js @@ -1,2 +1,2 @@ -var PHYSX=(()=>{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["P"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return "https://mdn.alipayobjects.com/rms/afts/file/A*RkDQSaUOhxsAAAAAgCAAAAgAehQnAQ/physx.release.wasm"}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var __abort_js=()=>abort("");var createNamedFunction=(name,func)=>Object.defineProperty(func,"name",{value:name});var emval_freelist=[];var emval_handles=[0,1,,1,null,1,true,1,false,1];var BindingError=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};var throwBindingError=message=>{throw new BindingError(message)};var Emval={toValue:handle=>{if(!handle){throwBindingError(`Cannot use deleted val. handle = ${handle}`)}return emval_handles[handle]},toHandle:value=>{switch(value){case undefined:return 2;case null:return 4;case true:return 6;case false:return 8;default:{const handle=emval_freelist.pop()||emval_handles.length;emval_handles[handle]=value;emval_handles[handle+1]=1;return handle}}}};class PureVirtualError extends Error{}var AsciiToString=ptr=>{var str="";while(1){var ch=HEAPU8[ptr++];if(!ch)return str;str+=String.fromCharCode(ch)}};var registeredInstances={};var getBasestPointer=(class_,ptr)=>{if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr};var registerInheritedInstance=(class_,ptr,instance)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){throwBindingError(`Tried to register registered instance: ${ptr}`)}else{registeredInstances[ptr]=instance}};var registeredTypes={};var getTypeName=type=>{var ptr=___getTypeName(type);var rv=AsciiToString(ptr);_free(ptr);return rv};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`)}return impl};var unregisterInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){delete registeredInstances[ptr]}else{throwBindingError(`Tried to unregister unregistered instance: ${ptr}`)}};var detachFinalizer=handle=>{};var finalizationRegistry=false;var runDestructor=$$=>{if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}};var releaseClassHandle=$$=>{$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}};var attachFinalizer=handle=>{if(!globalThis.FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$};finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)};var __embind_create_inheriting_constructor=(constructorName,wrapperType,properties)=>{constructorName=AsciiToString(constructorName);wrapperType=requireRegisteredType(wrapperType,"wrapper");properties=Emval.toValue(properties);var registeredClass=wrapperType.registeredClass;var wrapperPrototype=registeredClass.instancePrototype;var baseClass=registeredClass.baseClass;var baseClassPrototype=baseClass.instancePrototype;var baseConstructor=registeredClass.baseClass.constructor;var ctor=createNamedFunction(constructorName,function(...args){for(var name of registeredClass.baseClass.pureVirtualFunctions){if(this[name]===baseClassPrototype[name]){throw new PureVirtualError(`Pure virtual function ${name} must be implemented in JavaScript`)}}Object.defineProperty(this,"__parent",{value:wrapperPrototype});this["__construct"](...args)});wrapperPrototype["__construct"]=function __construct(...args){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __construct")}var inner=baseConstructor["implement"](this,...args);detachFinalizer(inner);var $$=inner.$$;inner["notifyOnDestruction"]();$$.preservePointerOnDelete=true;Object.defineProperties(this,{$$:{value:$$}});attachFinalizer(this);registerInheritedInstance(registeredClass,$$.ptr,this)};wrapperPrototype["__destruct"]=function __destruct(){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __destruct")}detachFinalizer(this);unregisterInheritedInstance(registeredClass,this.$$.ptr)};ctor.prototype=Object.create(wrapperPrototype);Object.assign(ctor.prototype,properties);return Emval.toHandle(ctor)};var structRegistrations={};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function readPointer(pointer){return this.fromWireType(HEAPU32[pointer>>2])}var awaitingDependencies={};var typeDependencies={};var InternalError=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};var throwInternalError=message=>{throw new InternalError(message)};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(type=>typeDependencies[type]=dependentTypes);function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}}if(0===unregisteredTypes.length){onComplete(typeConverters)}};var __embind_finalize_value_object=structType=>{var reg=structRegistrations[structType];delete structRegistrations[structType];var rawConstructor=reg.rawConstructor;var rawDestructor=reg.rawDestructor;var fieldRecords=reg.fields;var fieldTypes=fieldRecords.map(field=>field.getterReturnType).concat(fieldRecords.map(field=>field.setterArgumentType));whenDependentTypesAreResolved([structType],fieldTypes,fieldTypes=>{var fields={};for(var[i,field]of fieldRecords.entries()){const getterReturnType=fieldTypes[i];const getter=field.getter;const getterContext=field.getterContext;const setterArgumentType=fieldTypes[i+fieldRecords.length];const setter=field.setter;const setterContext=field.setterContext;fields[field.fieldName]={read:ptr=>getterReturnType.fromWireType(getter(getterContext,ptr)),write:(ptr,o)=>{var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,o));runDestructors(destructors)},optional:getterReturnType.optional}}return[{name:reg.name,fromWireType:ptr=>{var rv={};for(var i in fields){rv[i]=fields[i].read(ptr)}rawDestructor(ptr);return rv},toWireType:(destructors,o)=>{for(var fieldName in fields){if(!(fieldName in o)&&!fields[fieldName].optional){throw new TypeError(`Missing field: "${fieldName}"`)}}var ptr=rawConstructor();for(fieldName in fields){fields[fieldName].write(ptr,o[fieldName])}if(destructors!==null){destructors.push(rawDestructor,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction:rawDestructor}]})};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){return sharedRegisterType(rawType,registeredInstance,options)}var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>HEAP8[pointer]:pointer=>HEAPU8[pointer];case 2:return signed?pointer=>HEAP16[pointer>>1]:pointer=>HEAPU16[pointer>>1];case 4:return signed?pointer=>HEAP32[pointer>>2]:pointer=>HEAPU32[pointer>>2];case 8:return signed?pointer=>HEAP64[pointer>>3]:pointer=>HEAPU64[pointer>>3];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_bigint=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0n;let fromWireType=value=>value;if(isUnsignedType){const bitSize=size*8;fromWireType=value=>BigInt.asUintN(bitSize,value);maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>{if(typeof value=="number"){value=BigInt(value)}return value},readValueFromPointer:integerReadValueFromPointer(name,size,!isUnsignedType),destructorFunction:null})};var __embind_register_bool=(rawType,name,trueValue,falseValue)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:function(wt){return!!wt},toWireType:function(destructors,o){return o?trueValue:falseValue},readValueFromPointer:function(pointer){return this.fromWireType(HEAPU8[pointer])},destructorFunction:null})};var shallowCopyInternalPointer=o=>({count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType});var throwInstanceAlreadyDeleted=obj=>{function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")};var deletionQueue=[];var flushPendingDeletes=()=>{while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}};var delayFunction;var init_ClassHandle=()=>{let proto=ClassHandle.prototype;Object.assign(proto,{isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;other.$$=other.$$;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right},clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}},delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}},isDeleted(){return!this.$$.ptr},deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}});const symbolDispose=Symbol.dispose;if(symbolDispose){proto[symbolDispose]=proto["delete"]}};function ClassHandle(){}var registeredPointers={};var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(...args){if(!proto[methodName].overloadTable.hasOwnProperty(args.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[args.length].apply(this,args)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module[name].overloadTable.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}var upcastPointer=(ptr,ptrClass,desiredClass)=>{while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr};var embindRepr=v=>{if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}};function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle||!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(()=>clonedHandle["delete"]()));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupported sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}var downcastPointer=(ptr,ptrClass,desiredClass)=>{if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)};var getInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]};var makeClassHandle=(prototype,record)=>{if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record,writable:true}}))};function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}var init_RegisteredPointer=()=>{Object.assign(RegisteredPointer.prototype,{getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr},destructor(ptr){this.rawDestructor?.(ptr)},readValueFromPointer:readPointer,fromWireType:RegisteredPointer_fromWireType})};function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this.toWireType=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this.toWireType=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this.toWireType=genericPointerToWireType}}var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistent public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var wasmTableMirror=[];var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var embind__requireFunction=(signature,rawFunction,isAsync=false)=>{signature=AsciiToString(signature);function makeDynCaller(){var rtn=getWasmTableEntry(rawFunction);return rtn}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};class UnboundTypeError extends Error{}var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};var __embind_register_class=(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor)=>{name=AsciiToString(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);upcast&&=embind__requireFunction(upcastSignature,upcast);downcast&&=embind__requireFunction(downcastSignature,downcast);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],base=>{base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(name,function(...args){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError(`Use 'new' to construct ${name}`)}if(undefined===registeredClass.constructor_body){throw new BindingError(`${name} has no accessible constructor`)}var body=registeredClass.constructor_body[args.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,args)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){registeredClass.baseClass.__derivedClasses??=[];registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})};function usesDestructorStack(argTypes){for(var i=1;i{var array=[];for(var i=0;i>2])}return array};var getFunctionName=signature=>{signature=signature.trim();const argsIndex=signature.indexOf("(");if(argsIndex===-1)return signature;return signature.slice(0,argsIndex)};var __embind_register_class_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}var proto=classType.registeredClass.constructor;if(undefined===proto[methodName]){unboundTypesHandler.argCount=argCount-1;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-1]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));var func=craftInvokerFunction(humanName,invokerArgsArray,null,rawInvoker,fn,isAsync);if(undefined===proto[methodName].overloadTable){func.argCount=argCount-1;proto[methodName]=func}else{proto[methodName].overloadTable[argCount-1]=func}if(classType.registeredClass.__derivedClasses){for(const derivedClass of classType.registeredClass.__derivedClasses){if(!derivedClass.constructor.hasOwnProperty(methodName)){derivedClass.constructor[methodName]=func}}}return[]});return[]})};var __embind_register_class_constructor=(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`constructor ${classType.name}`;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`)}classType.registeredClass.constructor_body[argCount-1]=()=>{throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`,rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{argTypes.splice(1,0,null);classType.registeredClass.constructor_body[argCount-1]=craftInvokerFunction(humanName,argTypes,null,invoker,rawConstructor);return[]});return[]})};var __embind_register_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context,isAsync);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]});return[]})};var validateThis=(this_,classType,humanName)=>{if(!(this_ instanceof Object)){throwBindingError(`${humanName} with invalid "this": ${this_}`)}if(!(this_ instanceof classType.registeredClass.constructor)){throwBindingError(`${humanName} incompatible with "this" of type ${this_.constructor.name}`)}if(!this_.$$.ptr){throwBindingError(`cannot call emscripten binding method ${humanName} on deleted object`)}return upcastPointer(this_.$$.ptr,this_.$$.ptrType.registeredClass,classType.registeredClass)};var __embind_register_class_property=(classType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{fieldName=AsciiToString(fieldName);getter=embind__requireFunction(getterSignature,getter);whenDependentTypesAreResolved([],[classType],classType=>{classType=classType[0];var humanName=`${classType.name}.${fieldName}`;var desc={get(){throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])},enumerable:true,configurable:true};if(setter){desc.set=()=>throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])}else{desc.set=v=>throwBindingError(humanName+" is a read-only property")}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);whenDependentTypesAreResolved([],setter?[getterReturnType,setterArgumentType]:[getterReturnType],types=>{var getterReturnType=types[0];var desc={get(){var ptr=validateThis(this,classType,humanName+" getter");return getterReturnType.fromWireType(getter(getterContext,ptr))},enumerable:true};if(setter){setter=embind__requireFunction(setterSignature,setter);var setterArgumentType=types[1];desc.set=function(v){var ptr=validateThis(this,classType,humanName+" setter");var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,v));runDestructors(destructors)}}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);return[]});return[]})};var __embind_register_constant=(name,type,value)=>{name=AsciiToString(name);whenDependentTypesAreResolved([],[type],type=>{type=type[0];Module[name]=type.fromWireType(value);return[]})};var __emval_decref=handle=>{if(handle>9&&0===--emval_handles[handle+1]){emval_handles[handle]=undefined;emval_freelist.push(handle)}};var EmValType={name:"emscripten::val",fromWireType:handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},toWireType:(destructors,value)=>Emval.toHandle(value),readValueFromPointer:readPointer,destructorFunction:null};var __embind_register_emval=rawType=>registerType(rawType,EmValType);var enumReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?function(pointer){return this.fromWireType(HEAP8[pointer])}:function(pointer){return this.fromWireType(HEAPU8[pointer])};case 2:return signed?function(pointer){return this.fromWireType(HEAP16[pointer>>1])}:function(pointer){return this.fromWireType(HEAPU16[pointer>>1])};case 4:return signed?function(pointer){return this.fromWireType(HEAP32[pointer>>2])}:function(pointer){return this.fromWireType(HEAPU32[pointer>>2])};default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};function getEnumValueType(rawValueType){return rawValueType===0?"object":rawValueType===1?"number":"string"}var __embind_register_enum=(rawType,name,size,isSigned,rawValueType)=>{name=AsciiToString(name);const valueType=getEnumValueType(rawValueType);switch(valueType){case"object":{function ctor(){}ctor.values={};registerType(rawType,{name,constructor:ctor,valueType,fromWireType:function(c){return this.constructor.values[c]},toWireType:(destructors,c)=>c.value,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor);break}case"number":{var keysMap={};registerType(rawType,{name,keysMap,valueType,fromWireType:c=>c,toWireType:(destructors,c)=>c,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}case"string":{var valuesMap={};var reverseMap={};var keysMap={};registerType(rawType,{name,valuesMap,reverseMap,keysMap,valueType,fromWireType:function(c){return this.reverseMap[c]},toWireType:function(destructors,c){return this.valuesMap[c]},readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}}};var __embind_register_enum_value=(rawEnumType,name,enumValue)=>{var enumType=requireRegisteredType(rawEnumType,"enum");name=AsciiToString(name);switch(enumType.valueType){case"object":{var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(`${enumType.name}_${name}`,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value;break}case"number":{enumType.keysMap[name]=enumValue;break}case"string":{enumType.valuesMap[name]=enumValue;enumType.reverseMap[enumValue]=name;enumType.keysMap[name]=name;break}}};var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this.fromWireType(HEAPF32[pointer>>2])};case 8:return function(pointer){return this.fromWireType(HEAPF64[pointer>>3])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=(rawType,name,size)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:value=>value,toWireType:(destructors,value)=>value,readValueFromPointer:floatReadValueFromPointer(name,size),destructorFunction:null})};var __embind_register_function=(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=AsciiToString(name);name=getFunctionName(name);rawInvoker=embind__requireFunction(signature,rawInvoker,isAsync);exposePublicSymbol(name,function(){throwUnboundTypeError(`Cannot call ${name} due to unbound types`,argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn,isAsync),argCount-1);return[]})};var __embind_register_integer=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0;let fromWireType=value=>value;if(isUnsignedType){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift;maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>value,readValueFromPointer:integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})};var installIndexedIterator=(proto,sizeMethodName,getMethodName)=>{const makeIterator=(size,getValue)=>{let index=0;return{next(){if(index>=size){return{done:true}}const current=index;index++;const value=getValue(current);return{value,done:false}},[Symbol.iterator](){return this}}};if(!proto[Symbol.iterator]){proto[Symbol.iterator]=function(){const size=this[sizeMethodName]();return makeIterator(size,i=>this[getMethodName](i))}}};var __embind_register_iterable=(rawClassType,rawElementType,sizeMethodName,getMethodName)=>{sizeMethodName=AsciiToString(sizeMethodName);getMethodName=AsciiToString(getMethodName);whenDependentTypesAreResolved([],[rawClassType,rawElementType],types=>{const classType=types[0];installIndexedIterator(classType.registeredClass.instancePrototype,sizeMethodName,getMethodName);return[]})};var __embind_register_memory_view=(rawType,dataTypeIndex,name)=>{var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=HEAPU32[handle>>2];var data=HEAPU32[handle+4>>2];return new TA(HEAP8.buffer,data,size)}name=AsciiToString(name);registerType(rawType,{name,fromWireType:decodeMemoryView,readValueFromPointer:decodeMemoryView},{ignoreDuplicateRegistrations:true})};var EmValOptionalType=Object.assign({optional:true},EmValType);var __embind_register_optional=(rawOptionalType,rawType)=>{registerType(rawOptionalType,EmValOptionalType)};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var UTF8Decoder=globalThis.TextDecoder&&new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var __embind_register_std_string=(rawType,name)=>{name=AsciiToString(name);var stdStringIsUTF8=true;registerType(rawType,{name,fromWireType(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){str=UTF8ToString(payload,length,true)}else{str="";for(var i=0;i>2]=length;if(valueIsOfTypeString){if(stdStringIsUTF8){stringToUTF8(value,ptr,length+1)}else{for(var i=0;i255){_free(base);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}}else{HEAPU8.set(value,ptr)}if(destructors!==null){destructors.push(_free,base)}return base},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var UTF16Decoder=globalThis.TextDecoder?new TextDecoder("utf-16le"):undefined;var UTF16ToString=(ptr,maxBytesToRead,ignoreNul)=>{var idx=ptr>>1;var endIdx=findStringEnd(HEAPU16,idx,maxBytesToRead/2,ignoreNul);if(endIdx-idx>16&&UTF16Decoder)return UTF16Decoder.decode(HEAPU16.subarray(idx,endIdx));var str="";for(var i=idx;i{maxBytesToWrite??=2147483647;if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead,ignoreNul)=>{var str="";var startIdx=ptr>>2;for(var i=0;!(i>=maxBytesToRead/4);i++){var utf32=HEAPU32[startIdx+i];if(!utf32&&!ignoreNul)break;str+=String.fromCodePoint(utf32)}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i65535){i++}HEAP32[outPtr>>2]=codePoint;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i65535){i++}len+=4}return len};var __embind_register_std_wstring=(rawType,charSize,name)=>{name=AsciiToString(name);var decodeString,encodeString,lengthBytesUTF;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16}else{decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32}registerType(rawType,{name,fromWireType:value=>{var length=HEAPU32[value>>2];var str=decodeString(value+4,length*charSize,true);_free(value);return str},toWireType:(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length/charSize;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var __embind_register_value_object=(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor)=>{structRegistrations[rawType]={name:AsciiToString(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}};var __embind_register_value_object_field=(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{structRegistrations[structType].fields.push({fieldName:AsciiToString(fieldName),getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext,setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext})};var __embind_register_void=(rawType,name)=>{name=AsciiToString(name);registerType(rawType,{isVoid:true,name,fromWireType:()=>undefined,toWireType:(destructors,o)=>undefined})};var runtimeKeepaliveCounter=0;var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var emval_methodCallers=[];var emval_addMethodCaller=caller=>{var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id};var emval_lookupTypes=(argCount,argTypes)=>{var a=new Array(argCount);for(var i=0;i>2],`parameter ${i}`)}return a};var emval_returnValue=(toReturnWire,destructorsRef,handle)=>{var destructors=[];var result=toReturnWire(destructors,handle);if(destructors.length){HEAPU32[destructorsRef>>2]=Emval.toHandle(destructors)}return result};var emval_symbols={};var getStringOrSymbol=address=>{var symbol=emval_symbols[address];if(symbol===undefined){return AsciiToString(address)}return symbol};var __emval_create_invoker=(argCount,argTypesPtr,kind)=>{var GenericWireTypeSize=8;var[retType,...argTypes]=emval_lookupTypes(argCount,argTypesPtr);var toReturnWire=retType.toWireType.bind(retType);var argFromPtr=argTypes.map(type=>type.readValueFromPointer.bind(type));argCount--;var argN=new Array(argCount);var invokerFunction=(handle,methodName,destructorsRef,args)=>{var offset=0;for(var i=0;it.name)}) => ${retType.name}>`;return emval_addMethodCaller(createNamedFunction(functionName,invokerFunction))};var __emval_invoke=(caller,handle,methodName,destructorsRef,args)=>emval_methodCallers[caller](handle,methodName,destructorsRef,args);var __emval_new_cstring=v=>Emval.toHandle(getStringOrSymbol(v));var __emval_new_object=()=>Emval.toHandle({});var __emval_run_destructors=handle=>{var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)};var __emval_set_property=(handle,key,value)=>{handle=Emval.toValue(handle);key=Emval.toValue(key);value=Emval.toValue(value);handle[key]=value};var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{return func()}catch(e){handleException(e)}finally{maybeExit()}};var _emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()))},timeout_ms);timers[which]={id,timeout_ms};return 0};var _emscripten_date_now=()=>Date.now();var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var printCharBuffers=[null,[],[]];var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer));buffer.length=0}else{buffer.push(curr)}};var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0};init_ClassHandle();init_RegisteredPointer();{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}var ___getTypeName,_free,_malloc,__emscripten_timeout,memory,__indirect_function_table,wasmMemory,wasmTable;function assignWasmExports(wasmExports){___getTypeName=wasmExports["Q"];_free=Module["_free"]=wasmExports["R"];_malloc=Module["_malloc"]=wasmExports["S"];__emscripten_timeout=wasmExports["U"];memory=wasmMemory=wasmExports["O"];__indirect_function_table=wasmTable=wasmExports["T"]}var wasmImports={J:__abort_js,x:__embind_create_inheriting_constructor,s:__embind_finalize_value_object,z:__embind_register_bigint,A:__embind_register_bool,b:__embind_register_class,p:__embind_register_class_class_function,e:__embind_register_class_constructor,a:__embind_register_class_function,d:__embind_register_class_property,K:__embind_register_constant,M:__embind_register_emval,l:__embind_register_enum,f:__embind_register_enum_value,y:__embind_register_float,g:__embind_register_function,o:__embind_register_integer,q:__embind_register_iterable,h:__embind_register_memory_view,r:__embind_register_optional,N:__embind_register_std_string,u:__embind_register_std_wstring,t:__embind_register_value_object,m:__embind_register_value_object_field,B:__embind_register_void,D:__emscripten_runtime_keepalive_clear,k:__emval_create_invoker,n:__emval_decref,j:__emval_invoke,v:__emval_new_cstring,L:__emval_new_object,i:__emval_run_destructors,w:__emval_set_property,E:__setitimer_js,I:_emscripten_date_now,c:_emscripten_get_now,F:_emscripten_resize_heap,G:_exit,H:_fd_write,C:_proc_exit};function run(){preRun();function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})} +var PHYSX=(()=>{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["P"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("physx.release.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var __abort_js=()=>abort("");var createNamedFunction=(name,func)=>Object.defineProperty(func,"name",{value:name});var emval_freelist=[];var emval_handles=[0,1,,1,null,1,true,1,false,1];var BindingError=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};var throwBindingError=message=>{throw new BindingError(message)};var Emval={toValue:handle=>{if(!handle){throwBindingError(`Cannot use deleted val. handle = ${handle}`)}return emval_handles[handle]},toHandle:value=>{switch(value){case undefined:return 2;case null:return 4;case true:return 6;case false:return 8;default:{const handle=emval_freelist.pop()||emval_handles.length;emval_handles[handle]=value;emval_handles[handle+1]=1;return handle}}}};class PureVirtualError extends Error{}var AsciiToString=ptr=>{var str="";while(1){var ch=HEAPU8[ptr++];if(!ch)return str;str+=String.fromCharCode(ch)}};var registeredInstances={};var getBasestPointer=(class_,ptr)=>{if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr};var registerInheritedInstance=(class_,ptr,instance)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){throwBindingError(`Tried to register registered instance: ${ptr}`)}else{registeredInstances[ptr]=instance}};var registeredTypes={};var getTypeName=type=>{var ptr=___getTypeName(type);var rv=AsciiToString(ptr);_free(ptr);return rv};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`)}return impl};var unregisterInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){delete registeredInstances[ptr]}else{throwBindingError(`Tried to unregister unregistered instance: ${ptr}`)}};var detachFinalizer=handle=>{};var finalizationRegistry=false;var runDestructor=$$=>{if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}};var releaseClassHandle=$$=>{$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}};var attachFinalizer=handle=>{if(!globalThis.FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$};finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)};var __embind_create_inheriting_constructor=(constructorName,wrapperType,properties)=>{constructorName=AsciiToString(constructorName);wrapperType=requireRegisteredType(wrapperType,"wrapper");properties=Emval.toValue(properties);var registeredClass=wrapperType.registeredClass;var wrapperPrototype=registeredClass.instancePrototype;var baseClass=registeredClass.baseClass;var baseClassPrototype=baseClass.instancePrototype;var baseConstructor=registeredClass.baseClass.constructor;var ctor=createNamedFunction(constructorName,function(...args){for(var name of registeredClass.baseClass.pureVirtualFunctions){if(this[name]===baseClassPrototype[name]){throw new PureVirtualError(`Pure virtual function ${name} must be implemented in JavaScript`)}}Object.defineProperty(this,"__parent",{value:wrapperPrototype});this["__construct"](...args)});wrapperPrototype["__construct"]=function __construct(...args){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __construct")}var inner=baseConstructor["implement"](this,...args);detachFinalizer(inner);var $$=inner.$$;inner["notifyOnDestruction"]();$$.preservePointerOnDelete=true;Object.defineProperties(this,{$$:{value:$$}});attachFinalizer(this);registerInheritedInstance(registeredClass,$$.ptr,this)};wrapperPrototype["__destruct"]=function __destruct(){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __destruct")}detachFinalizer(this);unregisterInheritedInstance(registeredClass,this.$$.ptr)};ctor.prototype=Object.create(wrapperPrototype);Object.assign(ctor.prototype,properties);return Emval.toHandle(ctor)};var structRegistrations={};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function readPointer(pointer){return this.fromWireType(HEAPU32[pointer>>2])}var awaitingDependencies={};var typeDependencies={};var InternalError=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};var throwInternalError=message=>{throw new InternalError(message)};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(type=>typeDependencies[type]=dependentTypes);function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}}if(0===unregisteredTypes.length){onComplete(typeConverters)}};var __embind_finalize_value_object=structType=>{var reg=structRegistrations[structType];delete structRegistrations[structType];var rawConstructor=reg.rawConstructor;var rawDestructor=reg.rawDestructor;var fieldRecords=reg.fields;var fieldTypes=fieldRecords.map(field=>field.getterReturnType).concat(fieldRecords.map(field=>field.setterArgumentType));whenDependentTypesAreResolved([structType],fieldTypes,fieldTypes=>{var fields={};for(var[i,field]of fieldRecords.entries()){const getterReturnType=fieldTypes[i];const getter=field.getter;const getterContext=field.getterContext;const setterArgumentType=fieldTypes[i+fieldRecords.length];const setter=field.setter;const setterContext=field.setterContext;fields[field.fieldName]={read:ptr=>getterReturnType.fromWireType(getter(getterContext,ptr)),write:(ptr,o)=>{var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,o));runDestructors(destructors)},optional:getterReturnType.optional}}return[{name:reg.name,fromWireType:ptr=>{var rv={};for(var i in fields){rv[i]=fields[i].read(ptr)}rawDestructor(ptr);return rv},toWireType:(destructors,o)=>{for(var fieldName in fields){if(!(fieldName in o)&&!fields[fieldName].optional){throw new TypeError(`Missing field: "${fieldName}"`)}}var ptr=rawConstructor();for(fieldName in fields){fields[fieldName].write(ptr,o[fieldName])}if(destructors!==null){destructors.push(rawDestructor,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction:rawDestructor}]})};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){return sharedRegisterType(rawType,registeredInstance,options)}var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>HEAP8[pointer]:pointer=>HEAPU8[pointer];case 2:return signed?pointer=>HEAP16[pointer>>1]:pointer=>HEAPU16[pointer>>1];case 4:return signed?pointer=>HEAP32[pointer>>2]:pointer=>HEAPU32[pointer>>2];case 8:return signed?pointer=>HEAP64[pointer>>3]:pointer=>HEAPU64[pointer>>3];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_bigint=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0n;let fromWireType=value=>value;if(isUnsignedType){const bitSize=size*8;fromWireType=value=>BigInt.asUintN(bitSize,value);maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>{if(typeof value=="number"){value=BigInt(value)}return value},readValueFromPointer:integerReadValueFromPointer(name,size,!isUnsignedType),destructorFunction:null})};var __embind_register_bool=(rawType,name,trueValue,falseValue)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:function(wt){return!!wt},toWireType:function(destructors,o){return o?trueValue:falseValue},readValueFromPointer:function(pointer){return this.fromWireType(HEAPU8[pointer])},destructorFunction:null})};var shallowCopyInternalPointer=o=>({count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType});var throwInstanceAlreadyDeleted=obj=>{function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")};var deletionQueue=[];var flushPendingDeletes=()=>{while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}};var delayFunction;var init_ClassHandle=()=>{let proto=ClassHandle.prototype;Object.assign(proto,{isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;other.$$=other.$$;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right},clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}},delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}},isDeleted(){return!this.$$.ptr},deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}});const symbolDispose=Symbol.dispose;if(symbolDispose){proto[symbolDispose]=proto["delete"]}};function ClassHandle(){}var registeredPointers={};var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(...args){if(!proto[methodName].overloadTable.hasOwnProperty(args.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[args.length].apply(this,args)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module[name].overloadTable.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}var upcastPointer=(ptr,ptrClass,desiredClass)=>{while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr};var embindRepr=v=>{if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}};function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle||!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(()=>clonedHandle["delete"]()));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupported sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}var downcastPointer=(ptr,ptrClass,desiredClass)=>{if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)};var getInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]};var makeClassHandle=(prototype,record)=>{if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record,writable:true}}))};function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}var init_RegisteredPointer=()=>{Object.assign(RegisteredPointer.prototype,{getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr},destructor(ptr){this.rawDestructor?.(ptr)},readValueFromPointer:readPointer,fromWireType:RegisteredPointer_fromWireType})};function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this.toWireType=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this.toWireType=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this.toWireType=genericPointerToWireType}}var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistent public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var wasmTableMirror=[];var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var embind__requireFunction=(signature,rawFunction,isAsync=false)=>{signature=AsciiToString(signature);function makeDynCaller(){var rtn=getWasmTableEntry(rawFunction);return rtn}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};class UnboundTypeError extends Error{}var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};var __embind_register_class=(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor)=>{name=AsciiToString(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);upcast&&=embind__requireFunction(upcastSignature,upcast);downcast&&=embind__requireFunction(downcastSignature,downcast);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],base=>{base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(name,function(...args){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError(`Use 'new' to construct ${name}`)}if(undefined===registeredClass.constructor_body){throw new BindingError(`${name} has no accessible constructor`)}var body=registeredClass.constructor_body[args.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,args)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){registeredClass.baseClass.__derivedClasses??=[];registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})};function usesDestructorStack(argTypes){for(var i=1;i{var array=[];for(var i=0;i>2])}return array};var getFunctionName=signature=>{signature=signature.trim();const argsIndex=signature.indexOf("(");if(argsIndex===-1)return signature;return signature.slice(0,argsIndex)};var __embind_register_class_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}var proto=classType.registeredClass.constructor;if(undefined===proto[methodName]){unboundTypesHandler.argCount=argCount-1;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-1]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));var func=craftInvokerFunction(humanName,invokerArgsArray,null,rawInvoker,fn,isAsync);if(undefined===proto[methodName].overloadTable){func.argCount=argCount-1;proto[methodName]=func}else{proto[methodName].overloadTable[argCount-1]=func}if(classType.registeredClass.__derivedClasses){for(const derivedClass of classType.registeredClass.__derivedClasses){if(!derivedClass.constructor.hasOwnProperty(methodName)){derivedClass.constructor[methodName]=func}}}return[]});return[]})};var __embind_register_class_constructor=(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`constructor ${classType.name}`;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`)}classType.registeredClass.constructor_body[argCount-1]=()=>{throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`,rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{argTypes.splice(1,0,null);classType.registeredClass.constructor_body[argCount-1]=craftInvokerFunction(humanName,argTypes,null,invoker,rawConstructor);return[]});return[]})};var __embind_register_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context,isAsync);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]});return[]})};var validateThis=(this_,classType,humanName)=>{if(!(this_ instanceof Object)){throwBindingError(`${humanName} with invalid "this": ${this_}`)}if(!(this_ instanceof classType.registeredClass.constructor)){throwBindingError(`${humanName} incompatible with "this" of type ${this_.constructor.name}`)}if(!this_.$$.ptr){throwBindingError(`cannot call emscripten binding method ${humanName} on deleted object`)}return upcastPointer(this_.$$.ptr,this_.$$.ptrType.registeredClass,classType.registeredClass)};var __embind_register_class_property=(classType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{fieldName=AsciiToString(fieldName);getter=embind__requireFunction(getterSignature,getter);whenDependentTypesAreResolved([],[classType],classType=>{classType=classType[0];var humanName=`${classType.name}.${fieldName}`;var desc={get(){throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])},enumerable:true,configurable:true};if(setter){desc.set=()=>throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])}else{desc.set=v=>throwBindingError(humanName+" is a read-only property")}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);whenDependentTypesAreResolved([],setter?[getterReturnType,setterArgumentType]:[getterReturnType],types=>{var getterReturnType=types[0];var desc={get(){var ptr=validateThis(this,classType,humanName+" getter");return getterReturnType.fromWireType(getter(getterContext,ptr))},enumerable:true};if(setter){setter=embind__requireFunction(setterSignature,setter);var setterArgumentType=types[1];desc.set=function(v){var ptr=validateThis(this,classType,humanName+" setter");var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,v));runDestructors(destructors)}}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);return[]});return[]})};var __embind_register_constant=(name,type,value)=>{name=AsciiToString(name);whenDependentTypesAreResolved([],[type],type=>{type=type[0];Module[name]=type.fromWireType(value);return[]})};var __emval_decref=handle=>{if(handle>9&&0===--emval_handles[handle+1]){emval_handles[handle]=undefined;emval_freelist.push(handle)}};var EmValType={name:"emscripten::val",fromWireType:handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},toWireType:(destructors,value)=>Emval.toHandle(value),readValueFromPointer:readPointer,destructorFunction:null};var __embind_register_emval=rawType=>registerType(rawType,EmValType);var enumReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?function(pointer){return this.fromWireType(HEAP8[pointer])}:function(pointer){return this.fromWireType(HEAPU8[pointer])};case 2:return signed?function(pointer){return this.fromWireType(HEAP16[pointer>>1])}:function(pointer){return this.fromWireType(HEAPU16[pointer>>1])};case 4:return signed?function(pointer){return this.fromWireType(HEAP32[pointer>>2])}:function(pointer){return this.fromWireType(HEAPU32[pointer>>2])};default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};function getEnumValueType(rawValueType){return rawValueType===0?"object":rawValueType===1?"number":"string"}var __embind_register_enum=(rawType,name,size,isSigned,rawValueType)=>{name=AsciiToString(name);const valueType=getEnumValueType(rawValueType);switch(valueType){case"object":{function ctor(){}ctor.values={};registerType(rawType,{name,constructor:ctor,valueType,fromWireType:function(c){return this.constructor.values[c]},toWireType:(destructors,c)=>c.value,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor);break}case"number":{var keysMap={};registerType(rawType,{name,keysMap,valueType,fromWireType:c=>c,toWireType:(destructors,c)=>c,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}case"string":{var valuesMap={};var reverseMap={};var keysMap={};registerType(rawType,{name,valuesMap,reverseMap,keysMap,valueType,fromWireType:function(c){return this.reverseMap[c]},toWireType:function(destructors,c){return this.valuesMap[c]},readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}}};var __embind_register_enum_value=(rawEnumType,name,enumValue)=>{var enumType=requireRegisteredType(rawEnumType,"enum");name=AsciiToString(name);switch(enumType.valueType){case"object":{var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(`${enumType.name}_${name}`,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value;break}case"number":{enumType.keysMap[name]=enumValue;break}case"string":{enumType.valuesMap[name]=enumValue;enumType.reverseMap[enumValue]=name;enumType.keysMap[name]=name;break}}};var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this.fromWireType(HEAPF32[pointer>>2])};case 8:return function(pointer){return this.fromWireType(HEAPF64[pointer>>3])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=(rawType,name,size)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:value=>value,toWireType:(destructors,value)=>value,readValueFromPointer:floatReadValueFromPointer(name,size),destructorFunction:null})};var __embind_register_function=(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=AsciiToString(name);name=getFunctionName(name);rawInvoker=embind__requireFunction(signature,rawInvoker,isAsync);exposePublicSymbol(name,function(){throwUnboundTypeError(`Cannot call ${name} due to unbound types`,argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn,isAsync),argCount-1);return[]})};var __embind_register_integer=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0;let fromWireType=value=>value;if(isUnsignedType){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift;maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>value,readValueFromPointer:integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})};var installIndexedIterator=(proto,sizeMethodName,getMethodName)=>{const makeIterator=(size,getValue)=>{let index=0;return{next(){if(index>=size){return{done:true}}const current=index;index++;const value=getValue(current);return{value,done:false}},[Symbol.iterator](){return this}}};if(!proto[Symbol.iterator]){proto[Symbol.iterator]=function(){const size=this[sizeMethodName]();return makeIterator(size,i=>this[getMethodName](i))}}};var __embind_register_iterable=(rawClassType,rawElementType,sizeMethodName,getMethodName)=>{sizeMethodName=AsciiToString(sizeMethodName);getMethodName=AsciiToString(getMethodName);whenDependentTypesAreResolved([],[rawClassType,rawElementType],types=>{const classType=types[0];installIndexedIterator(classType.registeredClass.instancePrototype,sizeMethodName,getMethodName);return[]})};var __embind_register_memory_view=(rawType,dataTypeIndex,name)=>{var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=HEAPU32[handle>>2];var data=HEAPU32[handle+4>>2];return new TA(HEAP8.buffer,data,size)}name=AsciiToString(name);registerType(rawType,{name,fromWireType:decodeMemoryView,readValueFromPointer:decodeMemoryView},{ignoreDuplicateRegistrations:true})};var EmValOptionalType=Object.assign({optional:true},EmValType);var __embind_register_optional=(rawOptionalType,rawType)=>{registerType(rawOptionalType,EmValOptionalType)};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var UTF8Decoder=globalThis.TextDecoder&&new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var __embind_register_std_string=(rawType,name)=>{name=AsciiToString(name);var stdStringIsUTF8=true;registerType(rawType,{name,fromWireType(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){str=UTF8ToString(payload,length,true)}else{str="";for(var i=0;i>2]=length;if(valueIsOfTypeString){if(stdStringIsUTF8){stringToUTF8(value,ptr,length+1)}else{for(var i=0;i255){_free(base);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}}else{HEAPU8.set(value,ptr)}if(destructors!==null){destructors.push(_free,base)}return base},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var UTF16Decoder=globalThis.TextDecoder?new TextDecoder("utf-16le"):undefined;var UTF16ToString=(ptr,maxBytesToRead,ignoreNul)=>{var idx=ptr>>1;var endIdx=findStringEnd(HEAPU16,idx,maxBytesToRead/2,ignoreNul);if(endIdx-idx>16&&UTF16Decoder)return UTF16Decoder.decode(HEAPU16.subarray(idx,endIdx));var str="";for(var i=idx;i{maxBytesToWrite??=2147483647;if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead,ignoreNul)=>{var str="";var startIdx=ptr>>2;for(var i=0;!(i>=maxBytesToRead/4);i++){var utf32=HEAPU32[startIdx+i];if(!utf32&&!ignoreNul)break;str+=String.fromCodePoint(utf32)}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i65535){i++}HEAP32[outPtr>>2]=codePoint;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i65535){i++}len+=4}return len};var __embind_register_std_wstring=(rawType,charSize,name)=>{name=AsciiToString(name);var decodeString,encodeString,lengthBytesUTF;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16}else{decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32}registerType(rawType,{name,fromWireType:value=>{var length=HEAPU32[value>>2];var str=decodeString(value+4,length*charSize,true);_free(value);return str},toWireType:(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length/charSize;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var __embind_register_value_object=(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor)=>{structRegistrations[rawType]={name:AsciiToString(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}};var __embind_register_value_object_field=(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{structRegistrations[structType].fields.push({fieldName:AsciiToString(fieldName),getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext,setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext})};var __embind_register_void=(rawType,name)=>{name=AsciiToString(name);registerType(rawType,{isVoid:true,name,fromWireType:()=>undefined,toWireType:(destructors,o)=>undefined})};var runtimeKeepaliveCounter=0;var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var emval_methodCallers=[];var emval_addMethodCaller=caller=>{var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id};var emval_lookupTypes=(argCount,argTypes)=>{var a=new Array(argCount);for(var i=0;i>2],`parameter ${i}`)}return a};var emval_returnValue=(toReturnWire,destructorsRef,handle)=>{var destructors=[];var result=toReturnWire(destructors,handle);if(destructors.length){HEAPU32[destructorsRef>>2]=Emval.toHandle(destructors)}return result};var emval_symbols={};var getStringOrSymbol=address=>{var symbol=emval_symbols[address];if(symbol===undefined){return AsciiToString(address)}return symbol};var __emval_create_invoker=(argCount,argTypesPtr,kind)=>{var GenericWireTypeSize=8;var[retType,...argTypes]=emval_lookupTypes(argCount,argTypesPtr);var toReturnWire=retType.toWireType.bind(retType);var argFromPtr=argTypes.map(type=>type.readValueFromPointer.bind(type));argCount--;var argN=new Array(argCount);var invokerFunction=(handle,methodName,destructorsRef,args)=>{var offset=0;for(var i=0;it.name)}) => ${retType.name}>`;return emval_addMethodCaller(createNamedFunction(functionName,invokerFunction))};var __emval_invoke=(caller,handle,methodName,destructorsRef,args)=>emval_methodCallers[caller](handle,methodName,destructorsRef,args);var __emval_new_cstring=v=>Emval.toHandle(getStringOrSymbol(v));var __emval_new_object=()=>Emval.toHandle({});var __emval_run_destructors=handle=>{var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)};var __emval_set_property=(handle,key,value)=>{handle=Emval.toValue(handle);key=Emval.toValue(key);value=Emval.toValue(value);handle[key]=value};var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{return func()}catch(e){handleException(e)}finally{maybeExit()}};var _emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()))},timeout_ms);timers[which]={id,timeout_ms};return 0};var _emscripten_date_now=()=>Date.now();var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var printCharBuffers=[null,[],[]];var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer));buffer.length=0}else{buffer.push(curr)}};var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0};init_ClassHandle();init_RegisteredPointer();{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}var ___getTypeName,_free,_malloc,__emscripten_timeout,memory,__indirect_function_table,wasmMemory,wasmTable;function assignWasmExports(wasmExports){___getTypeName=wasmExports["Q"];_free=Module["_free"]=wasmExports["R"];_malloc=Module["_malloc"]=wasmExports["S"];__emscripten_timeout=wasmExports["U"];memory=wasmMemory=wasmExports["O"];__indirect_function_table=wasmTable=wasmExports["T"]}var wasmImports={J:__abort_js,x:__embind_create_inheriting_constructor,s:__embind_finalize_value_object,z:__embind_register_bigint,A:__embind_register_bool,b:__embind_register_class,p:__embind_register_class_class_function,e:__embind_register_class_constructor,a:__embind_register_class_function,d:__embind_register_class_property,K:__embind_register_constant,M:__embind_register_emval,l:__embind_register_enum,f:__embind_register_enum_value,y:__embind_register_float,g:__embind_register_function,o:__embind_register_integer,q:__embind_register_iterable,h:__embind_register_memory_view,r:__embind_register_optional,N:__embind_register_std_string,u:__embind_register_std_wstring,t:__embind_register_value_object,m:__embind_register_value_object_field,B:__embind_register_void,D:__emscripten_runtime_keepalive_clear,k:__emval_create_invoker,n:__emval_decref,j:__emval_invoke,v:__emval_new_cstring,L:__emval_new_object,i:__emval_run_destructors,w:__emval_set_property,E:__setitimer_js,I:_emscripten_date_now,c:_emscripten_get_now,F:_emscripten_resize_heap,G:_exit,H:_fd_write,C:_proc_exit};function run(){preRun();function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})} ;return moduleRtn}})();if(typeof exports==="object"&&typeof module==="object"){module.exports=PHYSX;module.exports.default=PHYSX}else if(typeof define==="function"&&define["amd"])define([],()=>PHYSX); diff --git a/e2e/.dev/physx.release.simd.js b/e2e/.dev/physx.release.simd.js index bdb1d70990..45843d369b 100644 --- a/e2e/.dev/physx.release.simd.js +++ b/e2e/.dev/physx.release.simd.js @@ -1,2 +1,2 @@ -var PHYSX=(()=>{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["P"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return "https://mdn.alipayobjects.com/rms/afts/file/A*6vi1SJaSJ6IAAAAAgDAAAAgAehQnAQ/physx.release.simd.wasm"}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var __abort_js=()=>abort("");var createNamedFunction=(name,func)=>Object.defineProperty(func,"name",{value:name});var emval_freelist=[];var emval_handles=[0,1,,1,null,1,true,1,false,1];var BindingError=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};var throwBindingError=message=>{throw new BindingError(message)};var Emval={toValue:handle=>{if(!handle){throwBindingError(`Cannot use deleted val. handle = ${handle}`)}return emval_handles[handle]},toHandle:value=>{switch(value){case undefined:return 2;case null:return 4;case true:return 6;case false:return 8;default:{const handle=emval_freelist.pop()||emval_handles.length;emval_handles[handle]=value;emval_handles[handle+1]=1;return handle}}}};class PureVirtualError extends Error{}var AsciiToString=ptr=>{var str="";while(1){var ch=HEAPU8[ptr++];if(!ch)return str;str+=String.fromCharCode(ch)}};var registeredInstances={};var getBasestPointer=(class_,ptr)=>{if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr};var registerInheritedInstance=(class_,ptr,instance)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){throwBindingError(`Tried to register registered instance: ${ptr}`)}else{registeredInstances[ptr]=instance}};var registeredTypes={};var getTypeName=type=>{var ptr=___getTypeName(type);var rv=AsciiToString(ptr);_free(ptr);return rv};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`)}return impl};var unregisterInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){delete registeredInstances[ptr]}else{throwBindingError(`Tried to unregister unregistered instance: ${ptr}`)}};var detachFinalizer=handle=>{};var finalizationRegistry=false;var runDestructor=$$=>{if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}};var releaseClassHandle=$$=>{$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}};var attachFinalizer=handle=>{if(!globalThis.FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$};finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)};var __embind_create_inheriting_constructor=(constructorName,wrapperType,properties)=>{constructorName=AsciiToString(constructorName);wrapperType=requireRegisteredType(wrapperType,"wrapper");properties=Emval.toValue(properties);var registeredClass=wrapperType.registeredClass;var wrapperPrototype=registeredClass.instancePrototype;var baseClass=registeredClass.baseClass;var baseClassPrototype=baseClass.instancePrototype;var baseConstructor=registeredClass.baseClass.constructor;var ctor=createNamedFunction(constructorName,function(...args){for(var name of registeredClass.baseClass.pureVirtualFunctions){if(this[name]===baseClassPrototype[name]){throw new PureVirtualError(`Pure virtual function ${name} must be implemented in JavaScript`)}}Object.defineProperty(this,"__parent",{value:wrapperPrototype});this["__construct"](...args)});wrapperPrototype["__construct"]=function __construct(...args){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __construct")}var inner=baseConstructor["implement"](this,...args);detachFinalizer(inner);var $$=inner.$$;inner["notifyOnDestruction"]();$$.preservePointerOnDelete=true;Object.defineProperties(this,{$$:{value:$$}});attachFinalizer(this);registerInheritedInstance(registeredClass,$$.ptr,this)};wrapperPrototype["__destruct"]=function __destruct(){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __destruct")}detachFinalizer(this);unregisterInheritedInstance(registeredClass,this.$$.ptr)};ctor.prototype=Object.create(wrapperPrototype);Object.assign(ctor.prototype,properties);return Emval.toHandle(ctor)};var structRegistrations={};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function readPointer(pointer){return this.fromWireType(HEAPU32[pointer>>2])}var awaitingDependencies={};var typeDependencies={};var InternalError=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};var throwInternalError=message=>{throw new InternalError(message)};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(type=>typeDependencies[type]=dependentTypes);function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}}if(0===unregisteredTypes.length){onComplete(typeConverters)}};var __embind_finalize_value_object=structType=>{var reg=structRegistrations[structType];delete structRegistrations[structType];var rawConstructor=reg.rawConstructor;var rawDestructor=reg.rawDestructor;var fieldRecords=reg.fields;var fieldTypes=fieldRecords.map(field=>field.getterReturnType).concat(fieldRecords.map(field=>field.setterArgumentType));whenDependentTypesAreResolved([structType],fieldTypes,fieldTypes=>{var fields={};for(var[i,field]of fieldRecords.entries()){const getterReturnType=fieldTypes[i];const getter=field.getter;const getterContext=field.getterContext;const setterArgumentType=fieldTypes[i+fieldRecords.length];const setter=field.setter;const setterContext=field.setterContext;fields[field.fieldName]={read:ptr=>getterReturnType.fromWireType(getter(getterContext,ptr)),write:(ptr,o)=>{var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,o));runDestructors(destructors)},optional:getterReturnType.optional}}return[{name:reg.name,fromWireType:ptr=>{var rv={};for(var i in fields){rv[i]=fields[i].read(ptr)}rawDestructor(ptr);return rv},toWireType:(destructors,o)=>{for(var fieldName in fields){if(!(fieldName in o)&&!fields[fieldName].optional){throw new TypeError(`Missing field: "${fieldName}"`)}}var ptr=rawConstructor();for(fieldName in fields){fields[fieldName].write(ptr,o[fieldName])}if(destructors!==null){destructors.push(rawDestructor,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction:rawDestructor}]})};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){return sharedRegisterType(rawType,registeredInstance,options)}var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>HEAP8[pointer]:pointer=>HEAPU8[pointer];case 2:return signed?pointer=>HEAP16[pointer>>1]:pointer=>HEAPU16[pointer>>1];case 4:return signed?pointer=>HEAP32[pointer>>2]:pointer=>HEAPU32[pointer>>2];case 8:return signed?pointer=>HEAP64[pointer>>3]:pointer=>HEAPU64[pointer>>3];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_bigint=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0n;let fromWireType=value=>value;if(isUnsignedType){const bitSize=size*8;fromWireType=value=>BigInt.asUintN(bitSize,value);maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>{if(typeof value=="number"){value=BigInt(value)}return value},readValueFromPointer:integerReadValueFromPointer(name,size,!isUnsignedType),destructorFunction:null})};var __embind_register_bool=(rawType,name,trueValue,falseValue)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:function(wt){return!!wt},toWireType:function(destructors,o){return o?trueValue:falseValue},readValueFromPointer:function(pointer){return this.fromWireType(HEAPU8[pointer])},destructorFunction:null})};var shallowCopyInternalPointer=o=>({count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType});var throwInstanceAlreadyDeleted=obj=>{function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")};var deletionQueue=[];var flushPendingDeletes=()=>{while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}};var delayFunction;var init_ClassHandle=()=>{let proto=ClassHandle.prototype;Object.assign(proto,{isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;other.$$=other.$$;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right},clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}},delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}},isDeleted(){return!this.$$.ptr},deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}});const symbolDispose=Symbol.dispose;if(symbolDispose){proto[symbolDispose]=proto["delete"]}};function ClassHandle(){}var registeredPointers={};var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(...args){if(!proto[methodName].overloadTable.hasOwnProperty(args.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[args.length].apply(this,args)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module[name].overloadTable.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}var upcastPointer=(ptr,ptrClass,desiredClass)=>{while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr};var embindRepr=v=>{if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}};function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle||!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(()=>clonedHandle["delete"]()));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupported sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}var downcastPointer=(ptr,ptrClass,desiredClass)=>{if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)};var getInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]};var makeClassHandle=(prototype,record)=>{if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record,writable:true}}))};function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}var init_RegisteredPointer=()=>{Object.assign(RegisteredPointer.prototype,{getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr},destructor(ptr){this.rawDestructor?.(ptr)},readValueFromPointer:readPointer,fromWireType:RegisteredPointer_fromWireType})};function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this.toWireType=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this.toWireType=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this.toWireType=genericPointerToWireType}}var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistent public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var wasmTableMirror=[];var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var embind__requireFunction=(signature,rawFunction,isAsync=false)=>{signature=AsciiToString(signature);function makeDynCaller(){var rtn=getWasmTableEntry(rawFunction);return rtn}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};class UnboundTypeError extends Error{}var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};var __embind_register_class=(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor)=>{name=AsciiToString(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);upcast&&=embind__requireFunction(upcastSignature,upcast);downcast&&=embind__requireFunction(downcastSignature,downcast);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],base=>{base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(name,function(...args){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError(`Use 'new' to construct ${name}`)}if(undefined===registeredClass.constructor_body){throw new BindingError(`${name} has no accessible constructor`)}var body=registeredClass.constructor_body[args.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,args)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){registeredClass.baseClass.__derivedClasses??=[];registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})};function usesDestructorStack(argTypes){for(var i=1;i{var array=[];for(var i=0;i>2])}return array};var getFunctionName=signature=>{signature=signature.trim();const argsIndex=signature.indexOf("(");if(argsIndex===-1)return signature;return signature.slice(0,argsIndex)};var __embind_register_class_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}var proto=classType.registeredClass.constructor;if(undefined===proto[methodName]){unboundTypesHandler.argCount=argCount-1;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-1]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));var func=craftInvokerFunction(humanName,invokerArgsArray,null,rawInvoker,fn,isAsync);if(undefined===proto[methodName].overloadTable){func.argCount=argCount-1;proto[methodName]=func}else{proto[methodName].overloadTable[argCount-1]=func}if(classType.registeredClass.__derivedClasses){for(const derivedClass of classType.registeredClass.__derivedClasses){if(!derivedClass.constructor.hasOwnProperty(methodName)){derivedClass.constructor[methodName]=func}}}return[]});return[]})};var __embind_register_class_constructor=(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`constructor ${classType.name}`;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`)}classType.registeredClass.constructor_body[argCount-1]=()=>{throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`,rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{argTypes.splice(1,0,null);classType.registeredClass.constructor_body[argCount-1]=craftInvokerFunction(humanName,argTypes,null,invoker,rawConstructor);return[]});return[]})};var __embind_register_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context,isAsync);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]});return[]})};var validateThis=(this_,classType,humanName)=>{if(!(this_ instanceof Object)){throwBindingError(`${humanName} with invalid "this": ${this_}`)}if(!(this_ instanceof classType.registeredClass.constructor)){throwBindingError(`${humanName} incompatible with "this" of type ${this_.constructor.name}`)}if(!this_.$$.ptr){throwBindingError(`cannot call emscripten binding method ${humanName} on deleted object`)}return upcastPointer(this_.$$.ptr,this_.$$.ptrType.registeredClass,classType.registeredClass)};var __embind_register_class_property=(classType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{fieldName=AsciiToString(fieldName);getter=embind__requireFunction(getterSignature,getter);whenDependentTypesAreResolved([],[classType],classType=>{classType=classType[0];var humanName=`${classType.name}.${fieldName}`;var desc={get(){throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])},enumerable:true,configurable:true};if(setter){desc.set=()=>throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])}else{desc.set=v=>throwBindingError(humanName+" is a read-only property")}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);whenDependentTypesAreResolved([],setter?[getterReturnType,setterArgumentType]:[getterReturnType],types=>{var getterReturnType=types[0];var desc={get(){var ptr=validateThis(this,classType,humanName+" getter");return getterReturnType.fromWireType(getter(getterContext,ptr))},enumerable:true};if(setter){setter=embind__requireFunction(setterSignature,setter);var setterArgumentType=types[1];desc.set=function(v){var ptr=validateThis(this,classType,humanName+" setter");var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,v));runDestructors(destructors)}}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);return[]});return[]})};var __embind_register_constant=(name,type,value)=>{name=AsciiToString(name);whenDependentTypesAreResolved([],[type],type=>{type=type[0];Module[name]=type.fromWireType(value);return[]})};var __emval_decref=handle=>{if(handle>9&&0===--emval_handles[handle+1]){emval_handles[handle]=undefined;emval_freelist.push(handle)}};var EmValType={name:"emscripten::val",fromWireType:handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},toWireType:(destructors,value)=>Emval.toHandle(value),readValueFromPointer:readPointer,destructorFunction:null};var __embind_register_emval=rawType=>registerType(rawType,EmValType);var enumReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?function(pointer){return this.fromWireType(HEAP8[pointer])}:function(pointer){return this.fromWireType(HEAPU8[pointer])};case 2:return signed?function(pointer){return this.fromWireType(HEAP16[pointer>>1])}:function(pointer){return this.fromWireType(HEAPU16[pointer>>1])};case 4:return signed?function(pointer){return this.fromWireType(HEAP32[pointer>>2])}:function(pointer){return this.fromWireType(HEAPU32[pointer>>2])};default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};function getEnumValueType(rawValueType){return rawValueType===0?"object":rawValueType===1?"number":"string"}var __embind_register_enum=(rawType,name,size,isSigned,rawValueType)=>{name=AsciiToString(name);const valueType=getEnumValueType(rawValueType);switch(valueType){case"object":{function ctor(){}ctor.values={};registerType(rawType,{name,constructor:ctor,valueType,fromWireType:function(c){return this.constructor.values[c]},toWireType:(destructors,c)=>c.value,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor);break}case"number":{var keysMap={};registerType(rawType,{name,keysMap,valueType,fromWireType:c=>c,toWireType:(destructors,c)=>c,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}case"string":{var valuesMap={};var reverseMap={};var keysMap={};registerType(rawType,{name,valuesMap,reverseMap,keysMap,valueType,fromWireType:function(c){return this.reverseMap[c]},toWireType:function(destructors,c){return this.valuesMap[c]},readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}}};var __embind_register_enum_value=(rawEnumType,name,enumValue)=>{var enumType=requireRegisteredType(rawEnumType,"enum");name=AsciiToString(name);switch(enumType.valueType){case"object":{var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(`${enumType.name}_${name}`,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value;break}case"number":{enumType.keysMap[name]=enumValue;break}case"string":{enumType.valuesMap[name]=enumValue;enumType.reverseMap[enumValue]=name;enumType.keysMap[name]=name;break}}};var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this.fromWireType(HEAPF32[pointer>>2])};case 8:return function(pointer){return this.fromWireType(HEAPF64[pointer>>3])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=(rawType,name,size)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:value=>value,toWireType:(destructors,value)=>value,readValueFromPointer:floatReadValueFromPointer(name,size),destructorFunction:null})};var __embind_register_function=(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=AsciiToString(name);name=getFunctionName(name);rawInvoker=embind__requireFunction(signature,rawInvoker,isAsync);exposePublicSymbol(name,function(){throwUnboundTypeError(`Cannot call ${name} due to unbound types`,argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn,isAsync),argCount-1);return[]})};var __embind_register_integer=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0;let fromWireType=value=>value;if(isUnsignedType){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift;maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>value,readValueFromPointer:integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})};var installIndexedIterator=(proto,sizeMethodName,getMethodName)=>{const makeIterator=(size,getValue)=>{let index=0;return{next(){if(index>=size){return{done:true}}const current=index;index++;const value=getValue(current);return{value,done:false}},[Symbol.iterator](){return this}}};if(!proto[Symbol.iterator]){proto[Symbol.iterator]=function(){const size=this[sizeMethodName]();return makeIterator(size,i=>this[getMethodName](i))}}};var __embind_register_iterable=(rawClassType,rawElementType,sizeMethodName,getMethodName)=>{sizeMethodName=AsciiToString(sizeMethodName);getMethodName=AsciiToString(getMethodName);whenDependentTypesAreResolved([],[rawClassType,rawElementType],types=>{const classType=types[0];installIndexedIterator(classType.registeredClass.instancePrototype,sizeMethodName,getMethodName);return[]})};var __embind_register_memory_view=(rawType,dataTypeIndex,name)=>{var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=HEAPU32[handle>>2];var data=HEAPU32[handle+4>>2];return new TA(HEAP8.buffer,data,size)}name=AsciiToString(name);registerType(rawType,{name,fromWireType:decodeMemoryView,readValueFromPointer:decodeMemoryView},{ignoreDuplicateRegistrations:true})};var EmValOptionalType=Object.assign({optional:true},EmValType);var __embind_register_optional=(rawOptionalType,rawType)=>{registerType(rawOptionalType,EmValOptionalType)};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var UTF8Decoder=globalThis.TextDecoder&&new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var __embind_register_std_string=(rawType,name)=>{name=AsciiToString(name);var stdStringIsUTF8=true;registerType(rawType,{name,fromWireType(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){str=UTF8ToString(payload,length,true)}else{str="";for(var i=0;i>2]=length;if(valueIsOfTypeString){if(stdStringIsUTF8){stringToUTF8(value,ptr,length+1)}else{for(var i=0;i255){_free(base);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}}else{HEAPU8.set(value,ptr)}if(destructors!==null){destructors.push(_free,base)}return base},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var UTF16Decoder=globalThis.TextDecoder?new TextDecoder("utf-16le"):undefined;var UTF16ToString=(ptr,maxBytesToRead,ignoreNul)=>{var idx=ptr>>1;var endIdx=findStringEnd(HEAPU16,idx,maxBytesToRead/2,ignoreNul);if(endIdx-idx>16&&UTF16Decoder)return UTF16Decoder.decode(HEAPU16.subarray(idx,endIdx));var str="";for(var i=idx;i{maxBytesToWrite??=2147483647;if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead,ignoreNul)=>{var str="";var startIdx=ptr>>2;for(var i=0;!(i>=maxBytesToRead/4);i++){var utf32=HEAPU32[startIdx+i];if(!utf32&&!ignoreNul)break;str+=String.fromCodePoint(utf32)}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i65535){i++}HEAP32[outPtr>>2]=codePoint;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i65535){i++}len+=4}return len};var __embind_register_std_wstring=(rawType,charSize,name)=>{name=AsciiToString(name);var decodeString,encodeString,lengthBytesUTF;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16}else{decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32}registerType(rawType,{name,fromWireType:value=>{var length=HEAPU32[value>>2];var str=decodeString(value+4,length*charSize,true);_free(value);return str},toWireType:(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length/charSize;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var __embind_register_value_object=(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor)=>{structRegistrations[rawType]={name:AsciiToString(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}};var __embind_register_value_object_field=(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{structRegistrations[structType].fields.push({fieldName:AsciiToString(fieldName),getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext,setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext})};var __embind_register_void=(rawType,name)=>{name=AsciiToString(name);registerType(rawType,{isVoid:true,name,fromWireType:()=>undefined,toWireType:(destructors,o)=>undefined})};var runtimeKeepaliveCounter=0;var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var emval_methodCallers=[];var emval_addMethodCaller=caller=>{var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id};var emval_lookupTypes=(argCount,argTypes)=>{var a=new Array(argCount);for(var i=0;i>2],`parameter ${i}`)}return a};var emval_returnValue=(toReturnWire,destructorsRef,handle)=>{var destructors=[];var result=toReturnWire(destructors,handle);if(destructors.length){HEAPU32[destructorsRef>>2]=Emval.toHandle(destructors)}return result};var emval_symbols={};var getStringOrSymbol=address=>{var symbol=emval_symbols[address];if(symbol===undefined){return AsciiToString(address)}return symbol};var __emval_create_invoker=(argCount,argTypesPtr,kind)=>{var GenericWireTypeSize=8;var[retType,...argTypes]=emval_lookupTypes(argCount,argTypesPtr);var toReturnWire=retType.toWireType.bind(retType);var argFromPtr=argTypes.map(type=>type.readValueFromPointer.bind(type));argCount--;var argN=new Array(argCount);var invokerFunction=(handle,methodName,destructorsRef,args)=>{var offset=0;for(var i=0;it.name)}) => ${retType.name}>`;return emval_addMethodCaller(createNamedFunction(functionName,invokerFunction))};var __emval_invoke=(caller,handle,methodName,destructorsRef,args)=>emval_methodCallers[caller](handle,methodName,destructorsRef,args);var __emval_new_cstring=v=>Emval.toHandle(getStringOrSymbol(v));var __emval_new_object=()=>Emval.toHandle({});var __emval_run_destructors=handle=>{var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)};var __emval_set_property=(handle,key,value)=>{handle=Emval.toValue(handle);key=Emval.toValue(key);value=Emval.toValue(value);handle[key]=value};var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{return func()}catch(e){handleException(e)}finally{maybeExit()}};var _emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()))},timeout_ms);timers[which]={id,timeout_ms};return 0};var _emscripten_date_now=()=>Date.now();var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var printCharBuffers=[null,[],[]];var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer));buffer.length=0}else{buffer.push(curr)}};var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0};init_ClassHandle();init_RegisteredPointer();{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}var ___getTypeName,_free,_malloc,__emscripten_timeout,memory,__indirect_function_table,wasmMemory,wasmTable;function assignWasmExports(wasmExports){___getTypeName=wasmExports["Q"];_free=Module["_free"]=wasmExports["R"];_malloc=Module["_malloc"]=wasmExports["S"];__emscripten_timeout=wasmExports["U"];memory=wasmMemory=wasmExports["O"];__indirect_function_table=wasmTable=wasmExports["T"]}var wasmImports={J:__abort_js,x:__embind_create_inheriting_constructor,s:__embind_finalize_value_object,z:__embind_register_bigint,A:__embind_register_bool,b:__embind_register_class,p:__embind_register_class_class_function,e:__embind_register_class_constructor,a:__embind_register_class_function,d:__embind_register_class_property,K:__embind_register_constant,M:__embind_register_emval,l:__embind_register_enum,f:__embind_register_enum_value,y:__embind_register_float,g:__embind_register_function,o:__embind_register_integer,q:__embind_register_iterable,h:__embind_register_memory_view,r:__embind_register_optional,N:__embind_register_std_string,u:__embind_register_std_wstring,t:__embind_register_value_object,m:__embind_register_value_object_field,B:__embind_register_void,D:__emscripten_runtime_keepalive_clear,k:__emval_create_invoker,n:__emval_decref,j:__emval_invoke,v:__emval_new_cstring,L:__emval_new_object,i:__emval_run_destructors,w:__emval_set_property,E:__setitimer_js,I:_emscripten_date_now,c:_emscripten_get_now,F:_emscripten_resize_heap,G:_exit,H:_fd_write,C:_proc_exit};function run(){preRun();function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})} +var PHYSX=(()=>{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["P"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("physx.release.simd.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var __abort_js=()=>abort("");var createNamedFunction=(name,func)=>Object.defineProperty(func,"name",{value:name});var emval_freelist=[];var emval_handles=[0,1,,1,null,1,true,1,false,1];var BindingError=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};var throwBindingError=message=>{throw new BindingError(message)};var Emval={toValue:handle=>{if(!handle){throwBindingError(`Cannot use deleted val. handle = ${handle}`)}return emval_handles[handle]},toHandle:value=>{switch(value){case undefined:return 2;case null:return 4;case true:return 6;case false:return 8;default:{const handle=emval_freelist.pop()||emval_handles.length;emval_handles[handle]=value;emval_handles[handle+1]=1;return handle}}}};class PureVirtualError extends Error{}var AsciiToString=ptr=>{var str="";while(1){var ch=HEAPU8[ptr++];if(!ch)return str;str+=String.fromCharCode(ch)}};var registeredInstances={};var getBasestPointer=(class_,ptr)=>{if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr};var registerInheritedInstance=(class_,ptr,instance)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){throwBindingError(`Tried to register registered instance: ${ptr}`)}else{registeredInstances[ptr]=instance}};var registeredTypes={};var getTypeName=type=>{var ptr=___getTypeName(type);var rv=AsciiToString(ptr);_free(ptr);return rv};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`)}return impl};var unregisterInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){delete registeredInstances[ptr]}else{throwBindingError(`Tried to unregister unregistered instance: ${ptr}`)}};var detachFinalizer=handle=>{};var finalizationRegistry=false;var runDestructor=$$=>{if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}};var releaseClassHandle=$$=>{$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}};var attachFinalizer=handle=>{if(!globalThis.FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$};finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)};var __embind_create_inheriting_constructor=(constructorName,wrapperType,properties)=>{constructorName=AsciiToString(constructorName);wrapperType=requireRegisteredType(wrapperType,"wrapper");properties=Emval.toValue(properties);var registeredClass=wrapperType.registeredClass;var wrapperPrototype=registeredClass.instancePrototype;var baseClass=registeredClass.baseClass;var baseClassPrototype=baseClass.instancePrototype;var baseConstructor=registeredClass.baseClass.constructor;var ctor=createNamedFunction(constructorName,function(...args){for(var name of registeredClass.baseClass.pureVirtualFunctions){if(this[name]===baseClassPrototype[name]){throw new PureVirtualError(`Pure virtual function ${name} must be implemented in JavaScript`)}}Object.defineProperty(this,"__parent",{value:wrapperPrototype});this["__construct"](...args)});wrapperPrototype["__construct"]=function __construct(...args){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __construct")}var inner=baseConstructor["implement"](this,...args);detachFinalizer(inner);var $$=inner.$$;inner["notifyOnDestruction"]();$$.preservePointerOnDelete=true;Object.defineProperties(this,{$$:{value:$$}});attachFinalizer(this);registerInheritedInstance(registeredClass,$$.ptr,this)};wrapperPrototype["__destruct"]=function __destruct(){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __destruct")}detachFinalizer(this);unregisterInheritedInstance(registeredClass,this.$$.ptr)};ctor.prototype=Object.create(wrapperPrototype);Object.assign(ctor.prototype,properties);return Emval.toHandle(ctor)};var structRegistrations={};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function readPointer(pointer){return this.fromWireType(HEAPU32[pointer>>2])}var awaitingDependencies={};var typeDependencies={};var InternalError=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};var throwInternalError=message=>{throw new InternalError(message)};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(type=>typeDependencies[type]=dependentTypes);function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}}if(0===unregisteredTypes.length){onComplete(typeConverters)}};var __embind_finalize_value_object=structType=>{var reg=structRegistrations[structType];delete structRegistrations[structType];var rawConstructor=reg.rawConstructor;var rawDestructor=reg.rawDestructor;var fieldRecords=reg.fields;var fieldTypes=fieldRecords.map(field=>field.getterReturnType).concat(fieldRecords.map(field=>field.setterArgumentType));whenDependentTypesAreResolved([structType],fieldTypes,fieldTypes=>{var fields={};for(var[i,field]of fieldRecords.entries()){const getterReturnType=fieldTypes[i];const getter=field.getter;const getterContext=field.getterContext;const setterArgumentType=fieldTypes[i+fieldRecords.length];const setter=field.setter;const setterContext=field.setterContext;fields[field.fieldName]={read:ptr=>getterReturnType.fromWireType(getter(getterContext,ptr)),write:(ptr,o)=>{var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,o));runDestructors(destructors)},optional:getterReturnType.optional}}return[{name:reg.name,fromWireType:ptr=>{var rv={};for(var i in fields){rv[i]=fields[i].read(ptr)}rawDestructor(ptr);return rv},toWireType:(destructors,o)=>{for(var fieldName in fields){if(!(fieldName in o)&&!fields[fieldName].optional){throw new TypeError(`Missing field: "${fieldName}"`)}}var ptr=rawConstructor();for(fieldName in fields){fields[fieldName].write(ptr,o[fieldName])}if(destructors!==null){destructors.push(rawDestructor,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction:rawDestructor}]})};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){return sharedRegisterType(rawType,registeredInstance,options)}var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>HEAP8[pointer]:pointer=>HEAPU8[pointer];case 2:return signed?pointer=>HEAP16[pointer>>1]:pointer=>HEAPU16[pointer>>1];case 4:return signed?pointer=>HEAP32[pointer>>2]:pointer=>HEAPU32[pointer>>2];case 8:return signed?pointer=>HEAP64[pointer>>3]:pointer=>HEAPU64[pointer>>3];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_bigint=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0n;let fromWireType=value=>value;if(isUnsignedType){const bitSize=size*8;fromWireType=value=>BigInt.asUintN(bitSize,value);maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>{if(typeof value=="number"){value=BigInt(value)}return value},readValueFromPointer:integerReadValueFromPointer(name,size,!isUnsignedType),destructorFunction:null})};var __embind_register_bool=(rawType,name,trueValue,falseValue)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:function(wt){return!!wt},toWireType:function(destructors,o){return o?trueValue:falseValue},readValueFromPointer:function(pointer){return this.fromWireType(HEAPU8[pointer])},destructorFunction:null})};var shallowCopyInternalPointer=o=>({count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType});var throwInstanceAlreadyDeleted=obj=>{function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")};var deletionQueue=[];var flushPendingDeletes=()=>{while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}};var delayFunction;var init_ClassHandle=()=>{let proto=ClassHandle.prototype;Object.assign(proto,{isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;other.$$=other.$$;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right},clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}},delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}},isDeleted(){return!this.$$.ptr},deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}});const symbolDispose=Symbol.dispose;if(symbolDispose){proto[symbolDispose]=proto["delete"]}};function ClassHandle(){}var registeredPointers={};var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(...args){if(!proto[methodName].overloadTable.hasOwnProperty(args.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[args.length].apply(this,args)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module[name].overloadTable.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}var upcastPointer=(ptr,ptrClass,desiredClass)=>{while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr};var embindRepr=v=>{if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}};function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle||!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(()=>clonedHandle["delete"]()));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupported sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}var downcastPointer=(ptr,ptrClass,desiredClass)=>{if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)};var getInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]};var makeClassHandle=(prototype,record)=>{if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record,writable:true}}))};function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}var init_RegisteredPointer=()=>{Object.assign(RegisteredPointer.prototype,{getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr},destructor(ptr){this.rawDestructor?.(ptr)},readValueFromPointer:readPointer,fromWireType:RegisteredPointer_fromWireType})};function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this.toWireType=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this.toWireType=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this.toWireType=genericPointerToWireType}}var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistent public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var wasmTableMirror=[];var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var embind__requireFunction=(signature,rawFunction,isAsync=false)=>{signature=AsciiToString(signature);function makeDynCaller(){var rtn=getWasmTableEntry(rawFunction);return rtn}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};class UnboundTypeError extends Error{}var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};var __embind_register_class=(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor)=>{name=AsciiToString(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);upcast&&=embind__requireFunction(upcastSignature,upcast);downcast&&=embind__requireFunction(downcastSignature,downcast);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],base=>{base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(name,function(...args){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError(`Use 'new' to construct ${name}`)}if(undefined===registeredClass.constructor_body){throw new BindingError(`${name} has no accessible constructor`)}var body=registeredClass.constructor_body[args.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,args)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){registeredClass.baseClass.__derivedClasses??=[];registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})};function usesDestructorStack(argTypes){for(var i=1;i{var array=[];for(var i=0;i>2])}return array};var getFunctionName=signature=>{signature=signature.trim();const argsIndex=signature.indexOf("(");if(argsIndex===-1)return signature;return signature.slice(0,argsIndex)};var __embind_register_class_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}var proto=classType.registeredClass.constructor;if(undefined===proto[methodName]){unboundTypesHandler.argCount=argCount-1;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-1]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));var func=craftInvokerFunction(humanName,invokerArgsArray,null,rawInvoker,fn,isAsync);if(undefined===proto[methodName].overloadTable){func.argCount=argCount-1;proto[methodName]=func}else{proto[methodName].overloadTable[argCount-1]=func}if(classType.registeredClass.__derivedClasses){for(const derivedClass of classType.registeredClass.__derivedClasses){if(!derivedClass.constructor.hasOwnProperty(methodName)){derivedClass.constructor[methodName]=func}}}return[]});return[]})};var __embind_register_class_constructor=(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`constructor ${classType.name}`;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`)}classType.registeredClass.constructor_body[argCount-1]=()=>{throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`,rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{argTypes.splice(1,0,null);classType.registeredClass.constructor_body[argCount-1]=craftInvokerFunction(humanName,argTypes,null,invoker,rawConstructor);return[]});return[]})};var __embind_register_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context,isAsync);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]});return[]})};var validateThis=(this_,classType,humanName)=>{if(!(this_ instanceof Object)){throwBindingError(`${humanName} with invalid "this": ${this_}`)}if(!(this_ instanceof classType.registeredClass.constructor)){throwBindingError(`${humanName} incompatible with "this" of type ${this_.constructor.name}`)}if(!this_.$$.ptr){throwBindingError(`cannot call emscripten binding method ${humanName} on deleted object`)}return upcastPointer(this_.$$.ptr,this_.$$.ptrType.registeredClass,classType.registeredClass)};var __embind_register_class_property=(classType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{fieldName=AsciiToString(fieldName);getter=embind__requireFunction(getterSignature,getter);whenDependentTypesAreResolved([],[classType],classType=>{classType=classType[0];var humanName=`${classType.name}.${fieldName}`;var desc={get(){throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])},enumerable:true,configurable:true};if(setter){desc.set=()=>throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])}else{desc.set=v=>throwBindingError(humanName+" is a read-only property")}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);whenDependentTypesAreResolved([],setter?[getterReturnType,setterArgumentType]:[getterReturnType],types=>{var getterReturnType=types[0];var desc={get(){var ptr=validateThis(this,classType,humanName+" getter");return getterReturnType.fromWireType(getter(getterContext,ptr))},enumerable:true};if(setter){setter=embind__requireFunction(setterSignature,setter);var setterArgumentType=types[1];desc.set=function(v){var ptr=validateThis(this,classType,humanName+" setter");var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,v));runDestructors(destructors)}}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);return[]});return[]})};var __embind_register_constant=(name,type,value)=>{name=AsciiToString(name);whenDependentTypesAreResolved([],[type],type=>{type=type[0];Module[name]=type.fromWireType(value);return[]})};var __emval_decref=handle=>{if(handle>9&&0===--emval_handles[handle+1]){emval_handles[handle]=undefined;emval_freelist.push(handle)}};var EmValType={name:"emscripten::val",fromWireType:handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},toWireType:(destructors,value)=>Emval.toHandle(value),readValueFromPointer:readPointer,destructorFunction:null};var __embind_register_emval=rawType=>registerType(rawType,EmValType);var enumReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?function(pointer){return this.fromWireType(HEAP8[pointer])}:function(pointer){return this.fromWireType(HEAPU8[pointer])};case 2:return signed?function(pointer){return this.fromWireType(HEAP16[pointer>>1])}:function(pointer){return this.fromWireType(HEAPU16[pointer>>1])};case 4:return signed?function(pointer){return this.fromWireType(HEAP32[pointer>>2])}:function(pointer){return this.fromWireType(HEAPU32[pointer>>2])};default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};function getEnumValueType(rawValueType){return rawValueType===0?"object":rawValueType===1?"number":"string"}var __embind_register_enum=(rawType,name,size,isSigned,rawValueType)=>{name=AsciiToString(name);const valueType=getEnumValueType(rawValueType);switch(valueType){case"object":{function ctor(){}ctor.values={};registerType(rawType,{name,constructor:ctor,valueType,fromWireType:function(c){return this.constructor.values[c]},toWireType:(destructors,c)=>c.value,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor);break}case"number":{var keysMap={};registerType(rawType,{name,keysMap,valueType,fromWireType:c=>c,toWireType:(destructors,c)=>c,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}case"string":{var valuesMap={};var reverseMap={};var keysMap={};registerType(rawType,{name,valuesMap,reverseMap,keysMap,valueType,fromWireType:function(c){return this.reverseMap[c]},toWireType:function(destructors,c){return this.valuesMap[c]},readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}}};var __embind_register_enum_value=(rawEnumType,name,enumValue)=>{var enumType=requireRegisteredType(rawEnumType,"enum");name=AsciiToString(name);switch(enumType.valueType){case"object":{var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(`${enumType.name}_${name}`,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value;break}case"number":{enumType.keysMap[name]=enumValue;break}case"string":{enumType.valuesMap[name]=enumValue;enumType.reverseMap[enumValue]=name;enumType.keysMap[name]=name;break}}};var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this.fromWireType(HEAPF32[pointer>>2])};case 8:return function(pointer){return this.fromWireType(HEAPF64[pointer>>3])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=(rawType,name,size)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:value=>value,toWireType:(destructors,value)=>value,readValueFromPointer:floatReadValueFromPointer(name,size),destructorFunction:null})};var __embind_register_function=(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=AsciiToString(name);name=getFunctionName(name);rawInvoker=embind__requireFunction(signature,rawInvoker,isAsync);exposePublicSymbol(name,function(){throwUnboundTypeError(`Cannot call ${name} due to unbound types`,argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn,isAsync),argCount-1);return[]})};var __embind_register_integer=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0;let fromWireType=value=>value;if(isUnsignedType){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift;maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>value,readValueFromPointer:integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})};var installIndexedIterator=(proto,sizeMethodName,getMethodName)=>{const makeIterator=(size,getValue)=>{let index=0;return{next(){if(index>=size){return{done:true}}const current=index;index++;const value=getValue(current);return{value,done:false}},[Symbol.iterator](){return this}}};if(!proto[Symbol.iterator]){proto[Symbol.iterator]=function(){const size=this[sizeMethodName]();return makeIterator(size,i=>this[getMethodName](i))}}};var __embind_register_iterable=(rawClassType,rawElementType,sizeMethodName,getMethodName)=>{sizeMethodName=AsciiToString(sizeMethodName);getMethodName=AsciiToString(getMethodName);whenDependentTypesAreResolved([],[rawClassType,rawElementType],types=>{const classType=types[0];installIndexedIterator(classType.registeredClass.instancePrototype,sizeMethodName,getMethodName);return[]})};var __embind_register_memory_view=(rawType,dataTypeIndex,name)=>{var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=HEAPU32[handle>>2];var data=HEAPU32[handle+4>>2];return new TA(HEAP8.buffer,data,size)}name=AsciiToString(name);registerType(rawType,{name,fromWireType:decodeMemoryView,readValueFromPointer:decodeMemoryView},{ignoreDuplicateRegistrations:true})};var EmValOptionalType=Object.assign({optional:true},EmValType);var __embind_register_optional=(rawOptionalType,rawType)=>{registerType(rawOptionalType,EmValOptionalType)};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var UTF8Decoder=globalThis.TextDecoder&&new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var __embind_register_std_string=(rawType,name)=>{name=AsciiToString(name);var stdStringIsUTF8=true;registerType(rawType,{name,fromWireType(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){str=UTF8ToString(payload,length,true)}else{str="";for(var i=0;i>2]=length;if(valueIsOfTypeString){if(stdStringIsUTF8){stringToUTF8(value,ptr,length+1)}else{for(var i=0;i255){_free(base);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}}else{HEAPU8.set(value,ptr)}if(destructors!==null){destructors.push(_free,base)}return base},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var UTF16Decoder=globalThis.TextDecoder?new TextDecoder("utf-16le"):undefined;var UTF16ToString=(ptr,maxBytesToRead,ignoreNul)=>{var idx=ptr>>1;var endIdx=findStringEnd(HEAPU16,idx,maxBytesToRead/2,ignoreNul);if(endIdx-idx>16&&UTF16Decoder)return UTF16Decoder.decode(HEAPU16.subarray(idx,endIdx));var str="";for(var i=idx;i{maxBytesToWrite??=2147483647;if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead,ignoreNul)=>{var str="";var startIdx=ptr>>2;for(var i=0;!(i>=maxBytesToRead/4);i++){var utf32=HEAPU32[startIdx+i];if(!utf32&&!ignoreNul)break;str+=String.fromCodePoint(utf32)}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i65535){i++}HEAP32[outPtr>>2]=codePoint;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i65535){i++}len+=4}return len};var __embind_register_std_wstring=(rawType,charSize,name)=>{name=AsciiToString(name);var decodeString,encodeString,lengthBytesUTF;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16}else{decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32}registerType(rawType,{name,fromWireType:value=>{var length=HEAPU32[value>>2];var str=decodeString(value+4,length*charSize,true);_free(value);return str},toWireType:(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length/charSize;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var __embind_register_value_object=(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor)=>{structRegistrations[rawType]={name:AsciiToString(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}};var __embind_register_value_object_field=(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{structRegistrations[structType].fields.push({fieldName:AsciiToString(fieldName),getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext,setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext})};var __embind_register_void=(rawType,name)=>{name=AsciiToString(name);registerType(rawType,{isVoid:true,name,fromWireType:()=>undefined,toWireType:(destructors,o)=>undefined})};var runtimeKeepaliveCounter=0;var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var emval_methodCallers=[];var emval_addMethodCaller=caller=>{var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id};var emval_lookupTypes=(argCount,argTypes)=>{var a=new Array(argCount);for(var i=0;i>2],`parameter ${i}`)}return a};var emval_returnValue=(toReturnWire,destructorsRef,handle)=>{var destructors=[];var result=toReturnWire(destructors,handle);if(destructors.length){HEAPU32[destructorsRef>>2]=Emval.toHandle(destructors)}return result};var emval_symbols={};var getStringOrSymbol=address=>{var symbol=emval_symbols[address];if(symbol===undefined){return AsciiToString(address)}return symbol};var __emval_create_invoker=(argCount,argTypesPtr,kind)=>{var GenericWireTypeSize=8;var[retType,...argTypes]=emval_lookupTypes(argCount,argTypesPtr);var toReturnWire=retType.toWireType.bind(retType);var argFromPtr=argTypes.map(type=>type.readValueFromPointer.bind(type));argCount--;var argN=new Array(argCount);var invokerFunction=(handle,methodName,destructorsRef,args)=>{var offset=0;for(var i=0;it.name)}) => ${retType.name}>`;return emval_addMethodCaller(createNamedFunction(functionName,invokerFunction))};var __emval_invoke=(caller,handle,methodName,destructorsRef,args)=>emval_methodCallers[caller](handle,methodName,destructorsRef,args);var __emval_new_cstring=v=>Emval.toHandle(getStringOrSymbol(v));var __emval_new_object=()=>Emval.toHandle({});var __emval_run_destructors=handle=>{var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)};var __emval_set_property=(handle,key,value)=>{handle=Emval.toValue(handle);key=Emval.toValue(key);value=Emval.toValue(value);handle[key]=value};var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{return func()}catch(e){handleException(e)}finally{maybeExit()}};var _emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()))},timeout_ms);timers[which]={id,timeout_ms};return 0};var _emscripten_date_now=()=>Date.now();var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var printCharBuffers=[null,[],[]];var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer));buffer.length=0}else{buffer.push(curr)}};var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0};init_ClassHandle();init_RegisteredPointer();{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}var ___getTypeName,_free,_malloc,__emscripten_timeout,memory,__indirect_function_table,wasmMemory,wasmTable;function assignWasmExports(wasmExports){___getTypeName=wasmExports["Q"];_free=Module["_free"]=wasmExports["R"];_malloc=Module["_malloc"]=wasmExports["S"];__emscripten_timeout=wasmExports["U"];memory=wasmMemory=wasmExports["O"];__indirect_function_table=wasmTable=wasmExports["T"]}var wasmImports={J:__abort_js,x:__embind_create_inheriting_constructor,s:__embind_finalize_value_object,z:__embind_register_bigint,A:__embind_register_bool,b:__embind_register_class,p:__embind_register_class_class_function,e:__embind_register_class_constructor,a:__embind_register_class_function,d:__embind_register_class_property,K:__embind_register_constant,M:__embind_register_emval,l:__embind_register_enum,f:__embind_register_enum_value,y:__embind_register_float,g:__embind_register_function,o:__embind_register_integer,q:__embind_register_iterable,h:__embind_register_memory_view,r:__embind_register_optional,N:__embind_register_std_string,u:__embind_register_std_wstring,t:__embind_register_value_object,m:__embind_register_value_object_field,B:__embind_register_void,D:__emscripten_runtime_keepalive_clear,k:__emval_create_invoker,n:__emval_decref,j:__emval_invoke,v:__emval_new_cstring,L:__emval_new_object,i:__emval_run_destructors,w:__emval_set_property,E:__setitimer_js,I:_emscripten_date_now,c:_emscripten_get_now,F:_emscripten_resize_heap,G:_exit,H:_fd_write,C:_proc_exit};function run(){preRun();function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})} ;return moduleRtn}})();if(typeof exports==="object"&&typeof module==="object"){module.exports=PHYSX;module.exports.default=PHYSX}else if(typeof define==="function"&&define["amd"])define([],()=>PHYSX); diff --git a/e2e/.dev/physx.release.simd.wasm b/e2e/.dev/physx.release.simd.wasm index 91e5bab34b..f52b48110a 100755 Binary files a/e2e/.dev/physx.release.simd.wasm and b/e2e/.dev/physx.release.simd.wasm differ diff --git a/e2e/.dev/physx.release.wasm b/e2e/.dev/physx.release.wasm index d9e03eee6a..3efb26a288 100755 Binary files a/e2e/.dev/physx.release.wasm and b/e2e/.dev/physx.release.wasm differ diff --git a/e2e/.dev/vite.config.js b/e2e/.dev/vite.config.js index 2cfc11d824..498a9a0244 100644 --- a/e2e/.dev/vite.config.js +++ b/e2e/.dev/vite.config.js @@ -42,6 +42,7 @@ demoList.forEach(({ file }) => { fs.outputJSONSync(path.join(__dirname, OUT_PATH, ".demoList.json"), demoSorted); module.exports = { + publicDir: path.resolve(__dirname, "public"), server: { open: true, host: "0.0.0.0", diff --git a/e2e/case/animator-blendShape.ts b/e2e/case/animator-blendShape.ts index 28641ca91f..27307ec95d 100644 --- a/e2e/case/animator-blendShape.ts +++ b/e2e/case/animator-blendShape.ts @@ -38,7 +38,7 @@ WebGLEngine.create({ canvas: "canvas" }).then((engine) => { const { defaultSceneRoot } = asset; rootEntity.addChild(defaultSceneRoot); const animator = defaultSceneRoot.getComponent(Animator); - const skinMeshRenderer = defaultSceneRoot.getComponent(SkinnedMeshRenderer); + const skinMeshRenderer = defaultSceneRoot.getComponentsIncludeChildren(SkinnedMeshRenderer, [])[0]; skinMeshRenderer.blendShapeWeights[0] = 1.0; animator.play("TheWave"); diff --git a/e2e/case/animator-multiSubMeshBlendShape.ts b/e2e/case/animator-multiSubMeshBlendShape.ts index 546d9b8f3d..5c1365a758 100644 --- a/e2e/case/animator-multiSubMeshBlendShape.ts +++ b/e2e/case/animator-multiSubMeshBlendShape.ts @@ -45,8 +45,8 @@ WebGLEngine.create({ canvas: "canvas" }).then((engine) => { .then((asset) => { const { defaultSceneRoot } = asset; rootEntity.addChild(defaultSceneRoot); - const entity = defaultSceneRoot; - defaultSceneRoot.transform.rotation = new Vector3(-90, -0, 0); + const entity = defaultSceneRoot.children[0]; + entity.transform.rotation = new Vector3(-90, -0, 0); const animator = entity.addComponent(Animator); animator.animatorController = new AnimatorController(engine); diff --git a/e2e/case/gpu-instancing-auto-batch.ts b/e2e/case/gpu-instancing-auto-batch.ts new file mode 100644 index 0000000000..e9f80e35ab --- /dev/null +++ b/e2e/case/gpu-instancing-auto-batch.ts @@ -0,0 +1,68 @@ +/** + * @title GPU Instancing Auto Batch + * @category Mesh + */ +import { + AmbientLight, + AssetType, + Camera, + Color, + DirectLight, + GLTFResource, + Logger, + Vector3, + WebGLEngine +} from "@galacean/engine"; +import { initScreenshot, updateForE2E } from "./.mockForE2E"; + +Logger.enable(); +WebGLEngine.create({ canvas: "canvas" }).then(async (engine) => { + engine.canvas.resizeByClientSize(2); + + const scene = engine.sceneManager.activeScene; + const rootEntity = scene.createRootEntity("Root"); + + // Camera + const cameraEntity = rootEntity.createChild("Camera"); + cameraEntity.transform.setPosition(0, 10, 80); + cameraEntity.transform.lookAt(new Vector3(0, 0, 0)); + const camera = cameraEntity.addComponent(Camera); + camera.farClipPlane = 300; + + // Light + const lightEntity = rootEntity.createChild("Light"); + lightEntity.transform.setRotation(-45, -45, 0); + lightEntity.addComponent(DirectLight).color = new Color(1, 1, 1, 1); + + // Load Duck model and ambient light + const [glTF, ambientLight] = await Promise.all([ + engine.resourceManager.load({ + url: "https://gw.alipayobjects.com/os/bmw-prod/6cb8f543-285c-491a-8cfd-57a1160dc9ab.glb", + type: AssetType.GLTF + }), + engine.resourceManager.load({ + url: "https://mdn.alipayobjects.com/oasis_be/afts/file/A*eRJ8QKzf5zAAAAAAgBAAAAgAekp5AQ/ambient.ambLight", + type: AssetType.AmbientLight + }) + ]); + scene.ambientLight = ambientLight; + + // Clone ducks with fixed seed positions for deterministic output + const count = 500; + const spread = 50; + for (let i = 0; i < count; i++) { + const duck = glTF.instantiateSceneRoot(); + // Use deterministic positions based on index + const t = i / count; + duck.transform.setPosition( + Math.sin(t * 137.5) * spread * 0.5, + Math.cos(t * 97.3) * spread * 0.5, + Math.sin(t * 59.1) * spread * 0.5 + ); + duck.transform.setRotation(t * 360, t * 720, t * 1080); + rootEntity.addChild(duck); + } + + updateForE2E(engine); + initScreenshot(engine, camera); +}); diff --git a/e2e/case/gpu-instancing-custom-data.ts b/e2e/case/gpu-instancing-custom-data.ts new file mode 100644 index 0000000000..f64b01a8f7 --- /dev/null +++ b/e2e/case/gpu-instancing-custom-data.ts @@ -0,0 +1,100 @@ +/** + * @title GPU Instancing Custom Data + * @category Mesh + */ +import { + Camera, + Color, + DirectLight, + Logger, + Material, + MeshRenderer, + PrimitiveMesh, + Shader, + ShaderProperty, + Vector3, + Vector4, + WebGLEngine +} from "@galacean/engine"; +import { initScreenshot, updateForE2E } from "./.mockForE2E"; + +Logger.enable(); + +// Custom shader: uses renderer_CustomColor (per-instance) for fragment output +Shader.create( + "CustomInstanceShader", + ` + #include + attribute vec3 POSITION; + attribute vec3 NORMAL; + + varying vec3 v_normal; + + void main() { + gl_Position = renderer_MVPMat * vec4(POSITION, 1.0); + v_normal = normalize((renderer_NormalMat * vec4(NORMAL, 0.0)).xyz); + } + `, + ` + uniform vec4 renderer_CustomColor; + + varying vec3 v_normal; + + void main() { + vec3 lightDir = normalize(vec3(1.0, 1.0, 1.0)); + float NdotL = max(dot(v_normal, lightDir), 0.2); + gl_FragColor = vec4(renderer_CustomColor.rgb * NdotL, 1.0); + } + ` +); + +WebGLEngine.create({ canvas: "canvas" }).then((engine) => { + engine.canvas.resizeByClientSize(2); + + const scene = engine.sceneManager.activeScene; + const rootEntity = scene.createRootEntity("Root"); + + // Camera + const cameraEntity = rootEntity.createChild("Camera"); + cameraEntity.transform.setPosition(0, 10, 80); + cameraEntity.transform.lookAt(new Vector3(0, 0, 0)); + const camera = cameraEntity.addComponent(Camera); + camera.farClipPlane = 300; + + // Light + const lightEntity = rootEntity.createChild("Light"); + lightEntity.transform.setRotation(-45, -45, 0); + lightEntity.addComponent(DirectLight).color = new Color(1, 1, 1, 1); + + // Shared mesh and material + const mesh = PrimitiveMesh.createCuboid(engine, 1, 1, 1); + const material = new Material(engine, Shader.find("CustomInstanceShader")); + const customColorProperty = ShaderProperty.getByName("renderer_CustomColor"); + + // Create cubes with deterministic positions and colors + const count = 500; + const spread = 50; + for (let i = 0; i < count; i++) { + const entity = rootEntity.createChild("Cube" + i); + const t = i / count; + entity.transform.setPosition( + Math.sin(t * 137.5) * spread * 0.5, + Math.cos(t * 97.3) * spread * 0.5, + Math.sin(t * 59.1) * spread * 0.5 + ); + entity.transform.setRotation(t * 360, t * 720, t * 1080); + + const renderer = entity.addComponent(MeshRenderer); + renderer.mesh = mesh; + renderer.setMaterial(material); + + // Deterministic colors based on index + renderer.shaderData.setVector4( + customColorProperty, + new Vector4(Math.sin(t * 6.28) * 0.5 + 0.5, Math.cos(t * 4.71) * 0.5 + 0.5, Math.sin(t * 3.14) * 0.5 + 0.5, 1.0) + ); + } + + updateForE2E(engine); + initScreenshot(engine, camera); +}); diff --git a/e2e/case/particleRenderer-dream.ts b/e2e/case/particleRenderer-dream.ts index e515bd4fbf..6eb51637ed 100644 --- a/e2e/case/particleRenderer-dream.ts +++ b/e2e/case/particleRenderer-dream.ts @@ -68,8 +68,8 @@ WebGLEngine.create({ cameraEntity.addChild(fireEntity); - updateForE2E(engine, 500); - initScreenshot(engine, camera); + // updateForE2E(engine, 500); + // initScreenshot(engine, camera); }); }); diff --git a/e2e/config.ts b/e2e/config.ts deleted file mode 100644 index e5a9b621cf..0000000000 --- a/e2e/config.ts +++ /dev/null @@ -1,518 +0,0 @@ -export const E2E_CONFIG = { - Animator: { - additive: { - category: "Animator", - caseFileName: "animator-additive", - threshold: 0, - diffPercentage: 0 - }, - blendShape: { - category: "Animator", - caseFileName: "animator-blendShape", - threshold: 0, - diffPercentage: 0.01 - }, - blendShapeQuantization: { - category: "Animator", - caseFileName: "animator-blendShape-quantization", - threshold: 0, - diffPercentage: 0.05 - }, - crossfade: { - category: "Animator", - caseFileName: "animator-crossfade", - threshold: 0, - diffPercentage: 0 - }, - customAnimationClip: { - category: "Animator", - caseFileName: "animator-customAnimationClip", - threshold: 0, - diffPercentage: 0 - }, - customBlendShape: { - category: "Animator", - caseFileName: "animator-customBlendShape", - threshold: 0, - diffPercentage: 0 - }, - multiSubMeshBlendShape: { - category: "Animator", - caseFileName: "animator-multiSubMeshBlendShape", - threshold: 0, - diffPercentage: 0 - }, - event: { - category: "Animator", - caseFileName: "animator-event", - threshold: 0, - diffPercentage: 0.0036 - }, - play: { - category: "Animator", - caseFileName: "animator-play", - threshold: 0, - diffPercentage: 0 - }, - playBackWards: { - category: "Animator", - caseFileName: "animator-play-backwards", - threshold: 0, - diffPercentage: 0 - }, - playBeforeActive: { - category: "Animator", - caseFileName: "animator-play-beforeActive", - threshold: 0, - diffPercentage: 0 - }, - reuse: { - category: "Animator", - caseFileName: "animator-reuse", - threshold: 0, - diffPercentage: 0 - }, - stateMachineScript: { - category: "Animator", - caseFileName: "animator-stateMachineScript", - threshold: 0, - diffPercentage: 0.0036 - }, - stateMachine: { - category: "Animator", - caseFileName: "animator-stateMachine", - threshold: 0, - diffPercentage: 0 - } - }, - GLTF: { - meshopt: { - category: "GLTF", - caseFileName: "gltf-meshopt", - threshold: 0, - diffPercentage: 0.059 - }, - blendShape: { - category: "GLTF", - caseFileName: "gltf-blendshape", - threshold: 0, - diffPercentage: 0.05 - } - }, - - Material: { - blendMode: { - category: "Material", - caseFileName: "material-blendMode", - threshold: 0, - diffPercentage: 0.02 - }, - "blinn-phong": { - category: "Material", - caseFileName: "material-blinn-phong", - threshold: 0, - diffPercentage: 0.36 - }, - "pbr-clearcoat": { - category: "Material", - caseFileName: "material-pbr-clearcoat", - threshold: 0, - diffPercentage: 0.12 - }, - "white-furnace": { - category: "Material", - caseFileName: "material-white-furnace", - threshold: 0, - diffPercentage: 0.0 - }, - "pbr-specular": { - category: "Material", - caseFileName: "material-pbr-specular", - threshold: 0, - diffPercentage: 0.055 - }, - pbr: { - category: "Material", - caseFileName: "material-pbr", - threshold: 0, - diffPercentage: 0.0044 - }, - shaderLab: { - category: "Material", - caseFileName: "material-shaderLab", - threshold: 0, - diffPercentage: 0 - }, - shaderLabMRT: { - category: "Material", - caseFileName: "shaderLab-mrt", - threshold: 0, - diffPercentage: 0 - }, - shaderReplacement: { - category: "Material", - caseFileName: "material-shaderReplacement", - threshold: 0, - diffPercentage: 0.049 - }, - unlit: { - category: "Material", - caseFileName: "material-unlit", - threshold: 0, - diffPercentage: 0.033 - }, - "shaderLab-renderState": { - category: "Material", - caseFileName: "shaderLab-renderState", - threshold: 0, - diffPercentage: 0 - }, - LUT: { - category: "Material", - caseFileName: "material-LUT", - threshold: 0, - diffPercentage: 0 - } - }, - Texture: { - sRGB: { - category: "Texture", - caseFileName: "texture-sRGB-KTX2", - threshold: 0, - diffPercentage: 0.072 - }, - R8G8: { - category: "Texture", - caseFileName: "texture-R8G8", - threshold: 0, - diffPercentage: 0 - }, - KTX2HDR: { - category: "Texture", - caseFileName: "texture-hdr-ktx2", - threshold: 0, - diffPercentage: 0.015 - }, - HDR: { - category: "Texture", - caseFileName: "texture-hdr", - threshold: 0, - diffPercentage: 0.0512 - } - }, - Shadow: { - basic: { - category: "Shadow", - caseFileName: "shadow-basic", - threshold: 0, - diffPercentage: 0.008 - }, - transparent: { - category: "Shadow", - caseFileName: "shadow-transparent", - threshold: 0, - diffPercentage: 0.0552 - } - }, - Primitive: { - capsule: { - category: "Primitive", - caseFileName: "primitive-capsule", - threshold: 0, - diffPercentage: 0.0016 - }, - cone: { - category: "Primitive", - caseFileName: "primitive-cone", - threshold: 0, - diffPercentage: 0.0054 - }, - cuboid: { - category: "Primitive", - caseFileName: "primitive-cuboid", - threshold: 0, - diffPercentage: 0.0016 - }, - cylinder: { - category: "Primitive", - caseFileName: "primitive-cylinder", - threshold: 0, - diffPercentage: 0.0036 - }, - plane: { - category: "Primitive", - caseFileName: "primitive-plane", - threshold: 0, - diffPercentage: 0.0016 - }, - sphere: { - category: "Primitive", - caseFileName: "primitive-sphere", - threshold: 0, - diffPercentage: 0.0058 - }, - torus: { - category: "Primitive", - caseFileName: "primitive-torus", - threshold: 0, - diffPercentage: 0 - } - }, - Camera: { - opaqueTexture: { - category: "Camera", - caseFileName: "camera-opaque-texture", - threshold: 0, - diffPercentage: 0 - }, - fxaa: { - category: "Camera", - caseFileName: "camera-fxaa", - threshold: 0, - diffPercentage: 0.161 - }, - ssao: { - category: "Camera", - caseFileName: "camera-ssao", - threshold: 0, - diffPercentage: 0.12 - } - }, - Physics: { - "physx-collision": { - category: "Physics", - caseFileName: "physx-collision", - threshold: 0, - diffPercentage: 0 - }, - "LitePhysics Collision Group": { - category: "Physics", - caseFileName: "litePhysics-collision-group", - threshold: 0, - diffPercentage: 0 - }, - "PhysXPhysics Collision Group": { - category: "Physics", - caseFileName: "physx-collision-group", - threshold: 0, - diffPercentage: 0 - }, - "PhysXPhysics Custom Url": { - category: "Physics", - caseFileName: "physx-customUrl", - threshold: 0, - diffPercentage: 0 - }, - "PhysX Mesh Collider": { - category: "Physics", - caseFileName: "physx-mesh-collider", - threshold: 0, - diffPercentage: 0.12094 - }, - "PhysX Mesh Collider Data": { - category: "Physics", - caseFileName: "physx-mesh-collider-data", - threshold: 0, - diffPercentage: 0.02 - }, - "PhysX Deferred Contact": { - category: "Physics", - caseFileName: "physx-deferred-contact", - threshold: 0, - diffPercentage: 0.0 - } - }, - Particle: { - particleDream: { - category: "Particle", - caseFileName: "particleRenderer-dream", - threshold: 0.005, - diffPercentage: 0.015 - }, - particleFire: { - category: "Particle", - caseFileName: "particleRenderer-fire", - threshold: 0, - diffPercentage: 0.0707 - }, - forceOverLifetime: { - category: "Particle", - caseFileName: "particleRenderer-force", - threshold: 0, - diffPercentage: 0.1630209 - }, - limitVelocityOverLifetime: { - category: "Particle", - caseFileName: "particleRenderer-limitVelocity", - threshold: 0, - diffPercentage: 0.0364 - }, - textureSheetAnimation: { - category: "Particle", - caseFileName: "particleRenderer-textureSheetAnimation", - threshold: 0, - diffPercentage: 0 - }, - particleShapeMesh: { - category: "Particle", - caseFileName: "particleRenderer-shape-mesh", - threshold: 0, - diffPercentage: 0.01698 - }, - particleEmissive: { - category: "Particle", - caseFileName: "particleRenderer-emissive", - threshold: 0, - diffPercentage: 0 - }, - particleEmitMeshNoShape: { - category: "Particle", - caseFileName: "particleRenderer-emit-mesh-no-shape", - threshold: 0, - diffPercentage: 0.00136 - }, - particleEmitMeshCone: { - category: "Particle", - caseFileName: "particleRenderer-emit-mesh-cone", - threshold: 0, - diffPercentage: 0.00219 - }, - particleEmitMeshConeScaleRotation: { - category: "Particle", - caseFileName: "particleRenderer-emit-mesh-cone-scale-rotation", - threshold: 0, - diffPercentage: 0.0031 - }, - particleEmitMeshConeScaleRotationWorld: { - category: "Particle", - caseFileName: "particleRenderer-emit-mesh-cone-scale-rotation-world", - threshold: 0, - diffPercentage: 0.00928 - }, - particleEmitMeshNoShapeWorld: { - category: "Particle", - caseFileName: "particleRenderer-emit-mesh-no-shape-world", - threshold: 0, - diffPercentage: 0.00146 - }, - particleEmitMeshConeScale3DRotation: { - category: "Particle", - caseFileName: "particleRenderer-emit-mesh-cone-scale-3d-rotation", - threshold: 0, - diffPercentage: 0.0184 - }, - particleEmitMeshConeScaleRotationLife: { - category: "Particle", - caseFileName: "particleRenderer-emit-mesh-cone-scale-rotation-life", - threshold: 0, - diffPercentage: 0.036459 - }, - particleEmitMeshConeScaleRotationLifeSeperate: { - category: "Particle", - caseFileName: "particleRenderer-emit-mesh-cone-scale-rotation-life-seperate", - threshold: 0, - diffPercentage: 0.0068 - }, - particleEmitMeshConeScale3DRotationLifeSeperate: { - category: "Particle", - caseFileName: "particleRenderer-emit-mesh-cone-scale-3d-rotation-life-seperate", - threshold: 0, - diffPercentage: 0.00782 - }, - particleEmitBillboardStretched: { - category: "Particle", - caseFileName: "particleRenderer-emit-billboard-stretched", - threshold: 0, - diffPercentage: 0.0 - }, - particleHorizontalBillboard: { - category: "Particle", - caseFileName: "particleRenderer-horizontal-billboard", - threshold: 0, - diffPercentage: 0.2162 - } - }, - PostProcess: { - HDRBloomACES: { - category: "PostProcess", - caseFileName: "postProcess-HDR-bloom-ACES", - threshold: 0, - diffPercentage: 0.148 - }, - HDRBloomNeutral: { - category: "PostProcess", - caseFileName: "postProcess-HDR-bloom-neutral", - threshold: 0, - diffPercentage: 0.072 - }, - LDRBloomNeutral: { - category: "PostProcess", - caseFileName: "postProcess-LDR-bloom-neutral", - threshold: 0, - diffPercentage: 0.097 - }, - customPass: { - category: "PostProcess", - caseFileName: "postProcess-customPass", - threshold: 0, - diffPercentage: 0.03 - } - }, - SpriteMask: { - CustomStencil: { - category: "SpriteMask", - caseFileName: "spriteMask-customStencil", - threshold: 0, - diffPercentage: 0.0024 - } - }, - Text: { - TypedText: { - category: "Text", - caseFileName: "text-typed", - threshold: 0.016, - diffPercentage: 0.00136 - }, - CharacterSpacing: { - category: "Text", - caseFileName: "text-character-spacing", - threshold: 0.0, - diffPercentage: 0.0 - } - }, - Trail: { - basic: { - category: "Trail", - caseFileName: "trailRenderer-basic", - threshold: 0, - diffPercentage: 0 - } - }, - Other: { - MultiSceneClear: { - category: "Advance", - caseFileName: "multi-scene-clear", - threshold: 0, - diffPercentage: 0 - }, - MultiSceneNoClear: { - category: "Advance", - caseFileName: "multi-scene-no-clear", - threshold: 0, - diffPercentage: 0 - }, - MultiCameraNoClear: { - category: "Advance", - caseFileName: "multi-camera-no-clear", - threshold: 0, - diffPercentage: 0 - }, - - CanvasTransparency: { - category: "Advance", - caseFileName: "canvas-transparency", - threshold: 0, - diffPercentage: 0.044 - } - } -}; diff --git a/e2e/fixtures/originImage/Animator_animator-crossfade.jpg b/e2e/fixtures/originImage/Animator_animator-crossfade.jpg index ab638de414..c71cd431c8 100644 --- a/e2e/fixtures/originImage/Animator_animator-crossfade.jpg +++ b/e2e/fixtures/originImage/Animator_animator-crossfade.jpg @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e18021c1e0a3b682259046e812eba199c907ffd9a634dda12379f1f0c3b8b43a -size 45710 +oid sha256:a1dfa2435f26222617b08ce2830ca28d8d84e083678dde1a9d945479c7b6d019 +size 45716 diff --git a/e2e/fixtures/originImage/Animator_animator-play.jpg b/e2e/fixtures/originImage/Animator_animator-play.jpg index 79170b806b..ddfb02c4e7 100644 --- a/e2e/fixtures/originImage/Animator_animator-play.jpg +++ b/e2e/fixtures/originImage/Animator_animator-play.jpg @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4910985a371b9022e73d2a7efbd71ca6754bcc7bf4c25edc2a41391f1bb1533b -size 46499 +oid sha256:82d8ba4776b6b27b923d0f1f0094d48d0d4c59e61e8666275690fec70c39e854 +size 46527 diff --git a/e2e/fixtures/originImage/Camera_camera-opaque-texture.jpg b/e2e/fixtures/originImage/Camera_camera-opaque-texture.jpg index bcc2d5f331..1d409ae544 100644 --- a/e2e/fixtures/originImage/Camera_camera-opaque-texture.jpg +++ b/e2e/fixtures/originImage/Camera_camera-opaque-texture.jpg @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fdde03beb8ead802b61a14e8649102c18ccfe6b9e1e176d3b9f8bc0dfe7f9c76 -size 47500 +oid sha256:a2068be8d0b35c94ec1ddaed9da63494f1a93294ea6128e2036563df1947e854 +size 47482 diff --git a/e2e/fixtures/originImage/GPUInstancing_gpu-instancing-auto-batch.jpg b/e2e/fixtures/originImage/GPUInstancing_gpu-instancing-auto-batch.jpg new file mode 100644 index 0000000000..ecec018d8c --- /dev/null +++ b/e2e/fixtures/originImage/GPUInstancing_gpu-instancing-auto-batch.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dc2a26d0ad06c2dfa722484b2e914b43c4c6671c76ec31d18715dc4a89ec1d88 +size 590047 diff --git a/e2e/fixtures/originImage/GPUInstancing_gpu-instancing-custom-data.jpg b/e2e/fixtures/originImage/GPUInstancing_gpu-instancing-custom-data.jpg new file mode 100644 index 0000000000..79399c097c --- /dev/null +++ b/e2e/fixtures/originImage/GPUInstancing_gpu-instancing-custom-data.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:baece2c4437803e1474699eb4e99214b38caa05393f747fe0f7e47bd6469a693 +size 427005 diff --git a/e2e/fixtures/originImage/Physics_physx-collision.jpg b/e2e/fixtures/originImage/Physics_physx-collision.jpg deleted file mode 100644 index b1e9becba9..0000000000 --- a/e2e/fixtures/originImage/Physics_physx-collision.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:55cd5d3035ef575743d7332317b571ea2403f9330c918a3c45e96dbbe853e164 -size 39366 diff --git a/e2e/fixtures/originImage/Physics_physx-customUrl.jpg b/e2e/fixtures/originImage/Physics_physx-customUrl.jpg deleted file mode 100644 index b1e9becba9..0000000000 --- a/e2e/fixtures/originImage/Physics_physx-customUrl.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:55cd5d3035ef575743d7332317b571ea2403f9330c918a3c45e96dbbe853e164 -size 39366 diff --git a/e2e/fixtures/originImage/Physics_physx-mesh-collider-data.jpg b/e2e/fixtures/originImage/Physics_physx-mesh-collider-data.jpg deleted file mode 100644 index 6bdbf7360d..0000000000 --- a/e2e/fixtures/originImage/Physics_physx-mesh-collider-data.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e62ca32193b97c4a47ce59666a4f7754f0f20486e055ac3998de2e07aa4d1272 -size 128943 diff --git a/e2e/package.json b/e2e/package.json index 34a2f56922..10d8108fed 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -1,7 +1,7 @@ { "name": "@galacean/engine-e2e", "private": true, - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "license": "MIT", "scripts": { "case": "vite serve .dev --config .dev/vite.config.js", diff --git a/examples/package.json b/examples/package.json index a57e6c4187..2afee7da55 100644 --- a/examples/package.json +++ b/examples/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-examples", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "private": true, "license": "MIT", "main": "dist/main.js", @@ -22,6 +22,7 @@ "@galacean/engine-shader": "workspace:*", "@galacean/engine-shaderlab": "workspace:*", "@galacean/engine-toolkit": "latest", + "@galacean/engine-toolkit-stats": "latest", "@galacean/engine-ui": "workspace:*" }, "devDependencies": { diff --git a/examples/src/gpu-instancing-auto-batch.ts b/examples/src/gpu-instancing-auto-batch.ts new file mode 100644 index 0000000000..d7aa1b9f80 --- /dev/null +++ b/examples/src/gpu-instancing-auto-batch.ts @@ -0,0 +1,194 @@ +/** + * @title GPU Instancing Auto Batch + * @category Mesh + * @thumbnail https://mdn.alipayobjects.com/merchant_appfe/afts/img/A*jjZMTrp-vU8AAAAAAAAAAAAADiR2AQ/original + */ +import { OrbitControl, Stats } from "@galacean/engine-toolkit"; +import { + AmbientLight, + AssetType, + Camera, + Color, + DirectLight, + GLTFResource, + Logger, + Material, + MeshRenderer, + PrimitiveMesh, + Script, + Shader, + ShaderProperty, + Vector3, + Vector4, + WebGLEngine, + WebGLMode +} from "@galacean/engine"; + +const _customColorProperty = ShaderProperty.getByName("renderer_CustomColor"); + +class SpiralAnimate extends Script { + radius: number = 0; + radiusSpeed: number = 0; + theta: number = 0; + thetaSpeed: number = 0; + phi: number = 0; + phiSpeed: number = 0; + rotateSpeed: Vector3 = new Vector3(); + scaleBase: number = 1; + scaleFreq: number = 0; + colorPhase: number = 0; + colorSpeed: number = 0; + private _time: number = 0; + private _color: Vector4 = new Vector4(); + private _hasColor: boolean = false; + + onUpdate(deltaTime: number): void { + this._time += deltaTime; + const t = this._time; + const transform = this.entity.transform; + + // Spiral breathing motion + const r = this.radius * (0.6 + 0.4 * Math.sin(t * this.radiusSpeed)); + const theta = this.theta + t * this.thetaSpeed; + const phi = this.phi + t * this.phiSpeed; + + const sinTheta = Math.sin(theta); + transform.setPosition(r * sinTheta * Math.cos(phi), r * Math.cos(theta), r * sinTheta * Math.sin(phi)); + + // Rotation + const { rotateSpeed } = this; + transform.rotate(rotateSpeed.x * deltaTime, rotateSpeed.y * deltaTime, rotateSpeed.z * deltaTime); + + // Scale pulse + const s = this.scaleBase * (0.7 + 0.3 * Math.sin(t * this.scaleFreq)); + transform.setScale(s, s, s); + + // Color animation (cubes only) + if (this._hasColor) { + const ct = t * this.colorSpeed + this.colorPhase; + this._color.set( + 0.5 + 0.5 * Math.sin(ct), + 0.5 + 0.5 * Math.sin(ct + 2.094), + 0.5 + 0.5 * Math.sin(ct + 4.189), + 1.0 + ); + this.entity.getComponent(MeshRenderer).shaderData.setVector4(_customColorProperty, this._color); + } + } + + enableColor(): void { + this._hasColor = true; + } +} + +// Custom shader for cubes +Shader.create( + "CustomInstanceShader", + ` + #include + attribute vec3 POSITION; + attribute vec3 NORMAL; + + varying vec3 v_normal; + + void main() { + gl_Position = renderer_MVPMat * vec4(POSITION, 1.0); + v_normal = normalize((renderer_NormalMat * vec4(NORMAL, 0.0)).xyz); + } + `, + ` + uniform vec4 renderer_CustomColor; + + varying vec3 v_normal; + + void main() { + vec3 lightDir = normalize(vec3(1.0, 1.0, 1.0)); + float NdotL = max(dot(v_normal, lightDir), 0.2); + gl_FragColor = vec4(renderer_CustomColor.rgb * NdotL, 1.0); + } + ` +); + +WebGLEngine.create({ canvas: "canvas", graphicDeviceOptions: { webGLMode: WebGLMode.WebGL2 } }).then(async (engine) => { + engine.canvas.resizeByClientSize(); + + const scene = engine.sceneManager.activeScene; + const rootEntity = scene.createRootEntity("Root"); + + // Camera + const cameraEntity = rootEntity.createChild("Camera"); + cameraEntity.transform.setPosition(0, 0, 100); + cameraEntity.transform.lookAt(new Vector3(0, 0, 0)); + const camera = cameraEntity.addComponent(Camera); + camera.farClipPlane = 500; + cameraEntity.addComponent(OrbitControl); + + // Stats + cameraEntity.addComponent(Stats); + + // Light + const lightEntity = rootEntity.createChild("Light"); + lightEntity.transform.setRotation(-45, -45, 0); + lightEntity.addComponent(DirectLight).color = new Color(1, 1, 1, 1); + + // Load Duck model and ambient light + const [glTF, ambientLight] = await Promise.all([ + engine.resourceManager.load({ + url: "https://mdn.alipayobjects.com/rms/afts/file/A*9R-_TY9K_6oAAAAAgIAAAAgAehQnAQ/Avocado.glb", + type: AssetType.GLTF + }), + engine.resourceManager.load({ + url: "https://mdn.alipayobjects.com/oasis_be/afts/file/A*eRJ8QKzf5zAAAAAAgBAAAAgAekp5AQ/ambient.ambLight", + type: AssetType.AmbientLight + }) + ]); + scene.ambientLight = ambientLight; + + // Cube resources + const cubeMesh = PrimitiveMesh.createCuboid(engine, 1, 1, 1); + const cubeMaterial = new Material(engine, Shader.find("CustomInstanceShader")); + const customColorProperty = ShaderProperty.getByName("renderer_CustomColor"); + + // Interleave ducks and cubes to break batching — instancing shines here + const duckCount = 2500; + const cubeCount = 2500; + const totalCount = duckCount + cubeCount; + + for (let i = 0; i < totalCount; i++) { + const ti = i / totalCount; + const isDuck = i % 2 === 0 && i / 2 < duckCount; + const isCube = !isDuck; + + let entity; + if (isDuck) { + entity = glTF.instantiateSceneRoot(); + rootEntity.addChild(entity); + } else { + entity = rootEntity.createChild("Cube" + i); + const renderer = entity.addComponent(MeshRenderer); + renderer.mesh = cubeMesh; + renderer.setMaterial(cubeMaterial); + const initColor = new Vector4(Math.random(), Math.random(), Math.random(), 1.0); + renderer.shaderData.setVector4(customColorProperty, initColor); + } + + const anim = entity.addComponent(SpiralAnimate); + anim.radius = 10 + Math.random() * 40; + anim.radiusSpeed = 0.3 + Math.random() * 0.6; + anim.theta = ti * Math.PI * 2 * 13.7; + anim.phi = ti * Math.PI * 2 * 7.3; + anim.thetaSpeed = (0.2 + Math.random() * 0.4) * (Math.random() > 0.5 ? 1 : -1); + anim.phiSpeed = (0.3 + Math.random() * 0.5) * (Math.random() > 0.5 ? 1 : -1); + anim.rotateSpeed = new Vector3((Math.random() - 0.5) * 60, (Math.random() - 0.5) * 60, (Math.random() - 0.5) * 60); + anim.scaleBase = (isDuck ? 20 : 1) * (0.6 + Math.random() * 0.8); + anim.scaleFreq = 0.5 + Math.random() * 2; + + if (isCube) { + anim.colorPhase = Math.random() * Math.PI * 2; + anim.colorSpeed = 0.5 + Math.random() * 2; + anim.enableColor(); + } + } + + engine.run(); +}); diff --git a/examples/src/gpu-instancing-custom-data.ts b/examples/src/gpu-instancing-custom-data.ts new file mode 100644 index 0000000000..27857d5730 --- /dev/null +++ b/examples/src/gpu-instancing-custom-data.ts @@ -0,0 +1,151 @@ +/** + * @title GPU Instancing Custom Data + * @category Mesh + * @thumbnail https://mdn.alipayobjects.com/merchant_appfe/afts/img/A*jjZMTrp-vU8AAAAAAAAAAAAADiR2AQ/original + */ +import { OrbitControl, Stats } from "@galacean/engine-toolkit"; +import { + Camera, + Color, + DirectLight, + Logger, + Material, + MeshRenderer, + PrimitiveMesh, + Script, + Shader, + ShaderProperty, + Vector3, + Vector4, + WebGLEngine, + WebGLMode +} from "@galacean/engine"; + +const _customColorProperty = ShaderProperty.getByName("renderer_CustomColor"); + +class SpiralFlash extends Script { + radius: number = 0; + radiusSpeed: number = 0; + theta: number = 0; + thetaSpeed: number = 0; + phi: number = 0; + phiSpeed: number = 0; + rotateSpeed: Vector3 = new Vector3(); + scaleBase: number = 1; + scaleFreq: number = 0; + colorPhase: number = 0; + colorSpeed: number = 1; + private _time: number = 0; + private _color: Vector4 = new Vector4(); + + onUpdate(deltaTime: number): void { + this._time += deltaTime; + const t = this._time; + const transform = this.entity.transform; + + // Spiral breathing motion + const r = this.radius * (0.6 + 0.4 * Math.sin(t * this.radiusSpeed)); + const theta = this.theta + t * this.thetaSpeed; + const phi = this.phi + t * this.phiSpeed; + + const sinTheta = Math.sin(theta); + transform.setPosition(r * sinTheta * Math.cos(phi), r * Math.cos(theta), r * sinTheta * Math.sin(phi)); + + // Rotation + const { rotateSpeed } = this; + transform.rotate(rotateSpeed.x * deltaTime, rotateSpeed.y * deltaTime, rotateSpeed.z * deltaTime); + + // Scale pulse + const s = this.scaleBase * (0.7 + 0.3 * Math.sin(t * this.scaleFreq)); + transform.setScale(s, s, s); + + // Color cycles through hue based on time + unique phase + const ct = t * this.colorSpeed + this.colorPhase; + this._color.set(0.5 + 0.5 * Math.sin(ct), 0.5 + 0.5 * Math.sin(ct + 2.094), 0.5 + 0.5 * Math.sin(ct + 4.189), 1.0); + this.entity.getComponent(MeshRenderer).shaderData.setVector4(_customColorProperty, this._color); + } +} + +Logger.enable(); + +Shader.create( + "CustomInstanceShader", + ` + #include + attribute vec3 POSITION; + attribute vec3 NORMAL; + + varying vec3 v_normal; + + void main() { + gl_Position = renderer_MVPMat * vec4(POSITION, 1.0); + v_normal = normalize((renderer_NormalMat * vec4(NORMAL, 0.0)).xyz); + } + `, + ` + uniform vec4 renderer_CustomColor; + + varying vec3 v_normal; + + void main() { + vec3 lightDir = normalize(vec3(1.0, 1.0, 1.0)); + float NdotL = max(dot(v_normal, lightDir), 0.2); + gl_FragColor = vec4(renderer_CustomColor.rgb * NdotL, 1.0); + } + ` +); + +WebGLEngine.create({ canvas: "canvas", graphicDeviceOptions: { webGLMode: WebGLMode.WebGL2 } }).then((engine) => { + engine.canvas.resizeByClientSize(); + + const scene = engine.sceneManager.activeScene; + const rootEntity = scene.createRootEntity("Root"); + + // Camera + const cameraEntity = rootEntity.createChild("Camera"); + cameraEntity.transform.setPosition(0, 0, 100); + cameraEntity.transform.lookAt(new Vector3(0, 0, 0)); + const camera = cameraEntity.addComponent(Camera); + camera.farClipPlane = 500; + cameraEntity.addComponent(OrbitControl); + + // Stats + cameraEntity.addComponent(Stats); + + // Light + const lightEntity = rootEntity.createChild("Light"); + lightEntity.transform.setRotation(-45, -45, 0); + lightEntity.addComponent(DirectLight).color = new Color(1, 1, 1, 1); + + const mesh = PrimitiveMesh.createCuboid(engine, 1, 1, 1); + const material = new Material(engine, Shader.find("CustomInstanceShader")); + const customColorProperty = ShaderProperty.getByName("renderer_CustomColor"); + + const count = 5000; + for (let i = 0; i < count; i++) { + const entity = rootEntity.createChild("Cube" + i); + const ti = i / count; + + const renderer = entity.addComponent(MeshRenderer); + renderer.mesh = mesh; + renderer.setMaterial(material); + + const initColor = new Vector4(Math.random(), Math.random(), Math.random(), 1.0); + renderer.shaderData.setVector4(customColorProperty, initColor); + + const anim = entity.addComponent(SpiralFlash); + anim.radius = 10 + Math.random() * 40; + anim.radiusSpeed = 0.3 + Math.random() * 0.6; + anim.theta = ti * Math.PI * 2 * 13.7; + anim.phi = ti * Math.PI * 2 * 7.3; + anim.thetaSpeed = (0.2 + Math.random() * 0.4) * (Math.random() > 0.5 ? 1 : -1); + anim.phiSpeed = (0.3 + Math.random() * 0.5) * (Math.random() > 0.5 ? 1 : -1); + anim.rotateSpeed = new Vector3((Math.random() - 0.5) * 60, (Math.random() - 0.5) * 60, (Math.random() - 0.5) * 60); + anim.scaleBase = 0.6 + Math.random() * 0.8; + anim.scaleFreq = 0.5 + Math.random() * 2; + anim.colorPhase = Math.random() * Math.PI * 2; + anim.colorSpeed = 0.5 + Math.random() * 2; + } + + engine.run(); +}); diff --git a/examples/src/sprite-renderer-filled.ts b/examples/src/sprite-renderer-filled.ts new file mode 100644 index 0000000000..e31504875f --- /dev/null +++ b/examples/src/sprite-renderer-filled.ts @@ -0,0 +1,146 @@ +/** + * @title Sprite Filled + * @category 2D + */ + +import * as dat from "dat.gui"; +import { + AssetType, + Camera, + Sprite, + SpriteDrawMode, + SpriteFilledMode, + SpriteFilledOrigin, + SpriteRenderer, + Texture2D, + Vector3, + WebGLEngine +} from "@galacean/engine"; + +WebGLEngine.create({ canvas: "canvas" }).then((engine) => { + engine.canvas.resizeByClientSize(); + + const scene = engine.sceneManager.activeScene; + scene.background.solidColor.set(0.15, 0.15, 0.18, 1); + const rootEntity = scene.createRootEntity(); + + // Create camera + const cameraEntity = rootEntity.createChild("camera"); + cameraEntity.transform.setPosition(0, 0, 50); + cameraEntity.addComponent(Camera); + + // Load texture and create sprite + engine.resourceManager + .load({ + url: "https://gw.alipayobjects.com/mdn/rms_7c464e/afts/img/A*ApFPTZSqcMkAAAAAAAAAAAAAARQnAQ", + type: AssetType.Texture2D + }) + .then((texture) => { + const spriteEntity = rootEntity.createChild("sprite"); + spriteEntity.transform.position = new Vector3(0, 0, 0); + spriteEntity.transform.setScale(2, 2, 2); + const renderer = spriteEntity.addComponent(SpriteRenderer); + renderer.sprite = new Sprite(engine, texture); + + // Set filled mode + renderer.drawMode = SpriteDrawMode.Filled; + renderer.filledMode = SpriteFilledMode.Radial360; + renderer.filledOrigin = SpriteFilledOrigin.Bottom; + renderer.filledAmount = 0.75; + renderer.filledClockWise = true; + + addGUI(renderer); + }); + + engine.run(); + + function addGUI(renderer: SpriteRenderer) { + const gui = new dat.GUI(); + + const filledModeMap: Record = { + Horizontal: SpriteFilledMode.Horizontal, + Vertical: SpriteFilledMode.Vertical, + Radial90: SpriteFilledMode.Radial90, + Radial180: SpriteFilledMode.Radial180, + Radial360: SpriteFilledMode.Radial360 + }; + + const originForRadial360: string[] = ["Right", "Top", "Left", "Bottom"]; + const originForRadial180: string[] = ["Right", "Top", "Left", "Bottom"]; + const originForRadial90: string[] = ["BottomLeft", "BottomRight", "TopRight", "TopLeft"]; + const originForHorizontal: string[] = ["Left", "Right"]; + const originForVertical: string[] = ["Bottom", "Top"]; + + const originMap: Record = { + Right: SpriteFilledOrigin.Right, + TopRight: SpriteFilledOrigin.TopRight, + Top: SpriteFilledOrigin.Top, + TopLeft: SpriteFilledOrigin.TopLeft, + Left: SpriteFilledOrigin.Left, + BottomLeft: SpriteFilledOrigin.BottomLeft, + Bottom: SpriteFilledOrigin.Bottom, + BottomRight: SpriteFilledOrigin.BottomRight + }; + + const state = { + filledMode: "Radial360", + origin: "Bottom", + amount: 0.75, + clockWise: true + }; + + const folder = gui.addFolder("Filled Sprite"); + folder.open(); + + // Filled mode + folder.add(state, "filledMode", Object.keys(filledModeMap)).onChange((value: string) => { + renderer.filledMode = filledModeMap[value]; + updateOriginOptions(value); + }); + + // Origin + let originCtrl = folder.add(state, "origin", originForRadial360).onChange((value: string) => { + renderer.filledOrigin = originMap[value]; + }); + + // Amount + folder.add(state, "amount", 0.0, 1.0, 0.01).onChange((value: number) => { + renderer.filledAmount = value; + }); + + // ClockWise + folder.add(state, "clockWise").onChange((value: boolean) => { + renderer.filledClockWise = value; + }); + + function updateOriginOptions(mode: string) { + folder.remove(originCtrl); + + let options: string[]; + switch (mode) { + case "Horizontal": + options = originForHorizontal; + break; + case "Vertical": + options = originForVertical; + break; + case "Radial90": + options = originForRadial90; + break; + case "Radial180": + options = originForRadial180; + break; + default: + options = originForRadial360; + break; + } + + state.origin = options[0]; + renderer.filledOrigin = originMap[state.origin]; + + originCtrl = folder.add(state, "origin", options).onChange((value: string) => { + renderer.filledOrigin = originMap[value]; + }); + } + } +}); diff --git a/package.json b/package.json index 6be276f782..dc0b6d4c78 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-root", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "packageManager": "pnpm@9.3.0", "private": true, "scripts": { @@ -41,18 +41,18 @@ "@types/dom-webcodecs": "^0.1.13", "@types/node": "^18.7.16", "@types/webxr": "latest", - "@typescript-eslint/eslint-plugin": "^6.1.0", - "@typescript-eslint/parser": "^6.1.0", + "@typescript-eslint/eslint-plugin": "^8.58.1", + "@typescript-eslint/parser": "^8.58.1", "@vitest/coverage-v8": "2.1.3", "bumpp": "^9.5.2", "cross-env": "^5.2.0", "electron": "^13", - "eslint": "^8.44.0", + "eslint": "^8.57.1", "eslint-config-prettier": "^8.8.0", "eslint-plugin-prettier": "^5.0.0", "fs-extra": "^10.1.0", "husky": "^8.0.0", - "lint-staged": "^10.5.3", + "lint-staged": "^16.4.0", "nyc": "^15.1.0", "odiff-bin": "^2.5.0", "prettier": "^3.0.0", @@ -65,9 +65,8 @@ "vitest": "2.1.3" }, "lint-staged": { - "*.{ts}": [ - "eslint --fix", - "git add" + "**/*.ts": [ + "eslint --fix" ] }, "repository": "git@github.com:galacean/runtime.git" diff --git a/packages/core/package.json b/packages/core/package.json index be735da868..545099402b 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-core", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" diff --git a/packages/core/src/2d/assembler/FilledSpriteAssembler.ts b/packages/core/src/2d/assembler/FilledSpriteAssembler.ts new file mode 100644 index 0000000000..b5e9797119 --- /dev/null +++ b/packages/core/src/2d/assembler/FilledSpriteAssembler.ts @@ -0,0 +1,613 @@ +import { BoundingBox, Matrix, Vector2, Vector3 } from "@galacean/engine-math"; +import { SubPrimitiveChunk } from "../../RenderPipeline/SubPrimitiveChunk"; +import { StaticInterfaceImplement } from "../../base/StaticInterfaceImplement"; +import { SpriteFilledMode } from "../enums/SpriteFilledMode"; +import { SpriteFilledOrigin } from "../enums/SpriteFilledOrigin"; +import { ISpriteAssembler } from "./ISpriteAssembler"; +import { ISpriteRenderer } from "./ISpriteRenderer"; + +/** + * Assemble vertex data for the sprite renderer in filled mode. + */ +@StaticInterfaceImplement() +export class FilledSpriteAssembler { + private static _matrix = new Matrix(); + private static _worldPositions = [ + new Vector3(), + new Vector3(), + new Vector3(), + new Vector3(), + new Vector3(), + new Vector3(), + new Vector3(), + new Vector3(), + new Vector3() + ]; + private static _uvs = [ + new Vector2(), + new Vector2(), + new Vector2(), + new Vector2(), + new Vector2(), + new Vector2(), + new Vector2(), + new Vector2(), + new Vector2() + ]; + private static _inPositions: Vector3[] = []; + private static _inUVs: Vector2[] = []; + private static _outPositions: Vector3[] = [new Vector3(), new Vector3(), new Vector3(), new Vector3()]; + private static _outUVs: Vector2[] = [new Vector2(), new Vector2(), new Vector2(), new Vector2()]; + private static _vertexOffset = 0; + private static _indicesOffset = 0; + + static resetData(renderer: ISpriteRenderer): void { + const manager = renderer._getChunkManager(); + const lastSubChunk = renderer._subChunk; + lastSubChunk && manager.freeSubChunk(lastSubChunk); + const subChunk = manager.allocateSubChunk(16); + subChunk.indices = []; + renderer._subChunk = subChunk; + } + + static updatePositions( + renderer: ISpriteRenderer, + worldMatrix: Matrix, + width: number, + height: number, + pivot: Vector2, + flipX: boolean, + flipY: boolean + ): void { + const { x: pivotX, y: pivotY } = pivot; + const modelMatrix = FilledSpriteAssembler._matrix; + const { elements: wE } = modelMatrix; + const { elements: pWE } = worldMatrix; + const sx = flipX ? -width : width; + const sy = flipY ? -height : height; + (wE[0] = pWE[0] * sx), (wE[1] = pWE[1] * sx), (wE[2] = pWE[2] * sx); + (wE[4] = pWE[4] * sy), (wE[5] = pWE[5] * sy), (wE[6] = pWE[6] * sy); + (wE[8] = pWE[8]), (wE[9] = pWE[9]), (wE[10] = pWE[10]); + wE[12] = pWE[12] - pivotX * wE[0] - pivotY * wE[4]; + wE[13] = pWE[13] - pivotX * wE[1] - pivotY * wE[5]; + wE[14] = pWE[14] - pivotX * wE[2] - pivotY * wE[6]; + + switch (renderer.filledMode) { + case SpriteFilledMode.Horizontal: + this._filledLinear(renderer, modelMatrix, true); + break; + case SpriteFilledMode.Vertical: + this._filledLinear(renderer, modelMatrix, false); + break; + case SpriteFilledMode.Radial90: + this._filledRadial90( + renderer, + modelMatrix, + renderer.filledOrigin, + renderer.filledAmount, + renderer.filledClockWise + ); + break; + case SpriteFilledMode.Radial180: + this._filledRadial180( + renderer, + modelMatrix, + renderer.filledOrigin, + renderer.filledAmount, + renderer.filledClockWise + ); + break; + case SpriteFilledMode.Radial360: + this._filledRadial360( + renderer, + modelMatrix, + renderer.filledOrigin, + renderer.filledAmount, + renderer.filledClockWise + ); + break; + default: + break; + } + + // @ts-ignore + BoundingBox.transform(renderer.sprite._getBounds(), modelMatrix, renderer._bounds); + } + + static updateUVs(renderer: ISpriteRenderer): void { + // UVs are computed in updatePositions. + } + + static updateColor(renderer: ISpriteRenderer, alpha: number): void { + const subChunk = renderer._subChunk; + const { r, g, b, a } = renderer.color; + const finalAlpha = a * alpha; + const vertices = subChunk.chunk.vertices; + const vertexArea = subChunk.vertexArea; + for (let i = 0, o = vertexArea.start + 5, n = vertexArea.size / 9; i < n; ++i, o += 9) { + vertices[o] = r; + vertices[o + 1] = g; + vertices[o + 2] = b; + vertices[o + 3] = finalAlpha; + } + } + + private static _filledLinear(renderer: ISpriteRenderer, matrix: Matrix, isHorizontal: boolean): void { + const amount = renderer.filledAmount; + if (amount <= 0.001) { + renderer._subChunk.indices.length = 0; + return; + } + + const sprite = renderer.sprite; + const [lPosLB, lPosRB, lPosLT, lPosRT] = sprite._getPositions(); + const spriteUVs = sprite._getUVs(); + const { x: left, y: bottom } = spriteUVs[0]; + const { x: right, y: top } = spriteUVs[15]; + + const subChunk = renderer._subChunk; + const vertices = subChunk.chunk.vertices; + + let x0: number, y0: number, u0: number, v0: number; + let x1: number, y1: number, u1: number, v1: number; + let x2: number, y2: number, u2: number, v2: number; + let x3: number, y3: number, u3: number, v3: number; + + if (isHorizontal) { + const originIsStart = renderer.filledOrigin === SpriteFilledOrigin.Left; + const startX = originIsStart ? lPosLB.x : lPosRB.x - (lPosRB.x - lPosLB.x) * amount; + const endX = originIsStart ? lPosLB.x + (lPosRB.x - lPosLB.x) * amount : lPosRB.x; + const startU = originIsStart ? left : right - (right - left) * amount; + const endU = originIsStart ? left + (right - left) * amount : right; + (x0 = startX), (y0 = lPosLB.y), (u0 = startU), (v0 = bottom); + (x1 = endX), (y1 = lPosRB.y), (u1 = endU), (v1 = bottom); + (x2 = startX), (y2 = lPosLT.y), (u2 = startU), (v2 = top); + (x3 = endX), (y3 = lPosRT.y), (u3 = endU), (v3 = top); + } else { + const originIsStart = renderer.filledOrigin === SpriteFilledOrigin.Bottom; + const startY = originIsStart ? lPosLB.y : lPosLT.y - (lPosLT.y - lPosLB.y) * amount; + const endY = originIsStart ? lPosLB.y + (lPosLT.y - lPosLB.y) * amount : lPosLT.y; + const startV = originIsStart ? bottom : top - (top - bottom) * amount; + const endV = originIsStart ? bottom + (top - bottom) * amount : top; + (x0 = lPosLB.x), (y0 = startY), (u0 = left), (v0 = startV); + (x1 = lPosRB.x), (y1 = startY), (u1 = right), (v1 = startV); + (x2 = lPosLT.x), (y2 = endY), (u2 = left), (v2 = endV); + (x3 = lPosRT.x), (y3 = endY), (u3 = right), (v3 = endV); + } + + const { elements: wE } = matrix; + const start = subChunk.vertexArea.start; + // LB + vertices[start] = wE[0] * x0 + wE[4] * y0 + wE[12]; + vertices[start + 1] = wE[1] * x0 + wE[5] * y0 + wE[13]; + vertices[start + 2] = wE[2] * x0 + wE[6] * y0 + wE[14]; + vertices[start + 3] = u0; + vertices[start + 4] = v0; + // RB + vertices[start + 9] = wE[0] * x1 + wE[4] * y1 + wE[12]; + vertices[start + 10] = wE[1] * x1 + wE[5] * y1 + wE[13]; + vertices[start + 11] = wE[2] * x1 + wE[6] * y1 + wE[14]; + vertices[start + 12] = u1; + vertices[start + 13] = v1; + // LT + vertices[start + 18] = wE[0] * x2 + wE[4] * y2 + wE[12]; + vertices[start + 19] = wE[1] * x2 + wE[5] * y2 + wE[13]; + vertices[start + 20] = wE[2] * x2 + wE[6] * y2 + wE[14]; + vertices[start + 21] = u2; + vertices[start + 22] = v2; + // RT + vertices[start + 27] = wE[0] * x3 + wE[4] * y3 + wE[12]; + vertices[start + 28] = wE[1] * x3 + wE[5] * y3 + wE[13]; + vertices[start + 29] = wE[2] * x3 + wE[6] * y3 + wE[14]; + vertices[start + 30] = u3; + vertices[start + 31] = v3; + + const indices = subChunk.indices; + indices[0] = 0; + indices[1] = 1; + indices[2] = 2; + indices[3] = 2; + indices[4] = 1; + indices[5] = 3; + indices.length = 6; + } + + private static _filledRadial90( + renderer: ISpriteRenderer, + matrix: Matrix, + origin: SpriteFilledOrigin, + amount: number, + cw: boolean + ): void { + if (amount <= 0.001) { + renderer._subChunk.indices.length = 0; + return; + } + + const sprite = renderer.sprite; + const [lPosLB, lPosRB, lPosLT, lPosRT] = sprite._getPositions(); + const spriteUVs = sprite._getUVs(); + const { x: left, y: bottom } = spriteUVs[0]; + const { x: right, y: top } = spriteUVs[15]; + + // Transform 4 corners to world space + const [wLB, wRB, wLT, wRT] = this._worldPositions; + const [uvLB, uvRB, uvLT, uvRT] = this._uvs; + wLB.set(lPosLB.x, lPosLB.y, 0).transformToVec3(matrix), uvLB.set(left, bottom); + wRB.set(lPosRB.x, lPosRB.y, 0).transformToVec3(matrix), uvRB.set(right, bottom); + wLT.set(lPosLT.x, lPosLT.y, 0).transformToVec3(matrix), uvLT.set(left, top); + wRT.set(lPosRT.x, lPosRT.y, 0).transformToVec3(matrix), uvRT.set(right, top); + + // Map vertices based on origin corner: + // [center, CW-adjacent, CCW-adjacent, opposite] + const { _inPositions: inPositions, _inUVs: inUVs, _outPositions: outPositions, _outUVs: outUVs } = this; + switch (origin) { + case SpriteFilledOrigin.BottomLeft: + (inPositions[0] = wLB), (inUVs[0] = uvLB); + (inPositions[1] = wRB), (inUVs[1] = uvRB); + (inPositions[2] = wLT), (inUVs[2] = uvLT); + (inPositions[3] = wRT), (inUVs[3] = uvRT); + break; + case SpriteFilledOrigin.BottomRight: + (inPositions[0] = wRB), (inUVs[0] = uvRB); + (inPositions[1] = wRT), (inUVs[1] = uvRT); + (inPositions[2] = wLB), (inUVs[2] = uvLB); + (inPositions[3] = wLT), (inUVs[3] = uvLT); + break; + case SpriteFilledOrigin.TopRight: + (inPositions[0] = wRT), (inUVs[0] = uvRT); + (inPositions[1] = wLT), (inUVs[1] = uvLT); + (inPositions[2] = wRB), (inUVs[2] = uvRB); + (inPositions[3] = wLB), (inUVs[3] = uvLB); + break; + case SpriteFilledOrigin.TopLeft: + (inPositions[0] = wLT), (inUVs[0] = uvLT); + (inPositions[1] = wLB), (inUVs[1] = uvLB); + (inPositions[2] = wRT), (inUVs[2] = uvRT); + (inPositions[3] = wRB), (inUVs[3] = uvRB); + break; + default: + break; + } + + const startAngle = cw ? 90 - amount * 90 : 0; + const endAngle = cw ? 90 : amount * 90; + + this._vertexOffset = this._indicesOffset = 0; + this._radialCut(renderer._subChunk, inPositions, inUVs, startAngle, endAngle, outPositions, outUVs); + renderer._subChunk.indices.length = this._indicesOffset; + } + + private static _filledRadial180( + renderer: ISpriteRenderer, + matrix: Matrix, + origin: SpriteFilledOrigin, + amount: number, + cw: boolean + ): void { + if (amount <= 0.001) { + renderer._subChunk.indices.length = 0; + return; + } + + const sprite = renderer.sprite; + const [lPosLB, lPosRB, lPosLT, lPosRT] = sprite._getPositions(); + const spriteUVs = sprite._getUVs(); + const { x: left, y: bottom } = spriteUVs[0]; + const { x: right, y: top } = spriteUVs[15]; + + // Transform corners and compute edge midpoints + const [wLB, wMB, wRB, wLM, , wRM, wLT, wMT, wRT] = this._worldPositions; + const [uvLB, uvMB, uvRB, uvLM, , uvRM, uvLT, uvMT, uvRT] = this._uvs; + wLB.set(lPosLB.x, lPosLB.y, 0).transformToVec3(matrix), uvLB.set(left, bottom); + wRB.set(lPosRB.x, lPosRB.y, 0).transformToVec3(matrix), uvRB.set(right, bottom); + wLT.set(lPosLT.x, lPosLT.y, 0).transformToVec3(matrix), uvLT.set(left, top); + wRT.set(lPosRT.x, lPosRT.y, 0).transformToVec3(matrix), uvRT.set(right, top); + Vector3.lerp(wLB, wRB, 0.5, wMB), Vector2.lerp(uvLB, uvRB, 0.5, uvMB); + Vector3.lerp(wLB, wLT, 0.5, wLM), Vector2.lerp(uvLB, uvLT, 0.5, uvLM); + Vector3.lerp(wLT, wRT, 0.5, wMT), Vector2.lerp(uvLT, uvRT, 0.5, uvMT); + Vector3.lerp(wRB, wRT, 0.5, wRM), Vector2.lerp(uvRB, uvRT, 0.5, uvRM); + + const startAngle = cw ? 180 - amount * 180 : 0; + const endAngle = cw ? 180 : amount * 180; + + this._vertexOffset = this._indicesOffset = 0; + const { _inPositions: inPositions, _inUVs: inUVs, _outPositions: outPositions, _outUVs: outUVs } = this; + const { _subChunk: subChunk } = renderer; + + // Center is at the origin edge midpoint; two quadrants cover the full sprite. + // Quadrant A (0°-90°), Quadrant B (90°-180°) + switch (origin) { + case SpriteFilledOrigin.Bottom: + // Center=MB, A: [MB,RB,MT,RT], B: [MB,MT,LB,LT] + (inPositions[0] = wMB), (inUVs[0] = uvMB); + (inPositions[1] = wRB), (inUVs[1] = uvRB); + (inPositions[2] = wMT), (inUVs[2] = uvMT); + (inPositions[3] = wRT), (inUVs[3] = uvRT); + this._radialCut(subChunk, inPositions, inUVs, startAngle, endAngle, outPositions, outUVs); + (inPositions[1] = wMT), (inUVs[1] = uvMT); + (inPositions[2] = wLB), (inUVs[2] = uvLB); + (inPositions[3] = wLT), (inUVs[3] = uvLT); + this._radialCut(subChunk, inPositions, inUVs, startAngle - 90, endAngle - 90, outPositions, outUVs); + break; + case SpriteFilledOrigin.Top: + // Center=MT, A: [MT,LT,MB,LB], B: [MT,MB,RT,RB] + (inPositions[0] = wMT), (inUVs[0] = uvMT); + (inPositions[1] = wLT), (inUVs[1] = uvLT); + (inPositions[2] = wMB), (inUVs[2] = uvMB); + (inPositions[3] = wLB), (inUVs[3] = uvLB); + this._radialCut(subChunk, inPositions, inUVs, startAngle, endAngle, outPositions, outUVs); + (inPositions[1] = wMB), (inUVs[1] = uvMB); + (inPositions[2] = wRT), (inUVs[2] = uvRT); + (inPositions[3] = wRB), (inUVs[3] = uvRB); + this._radialCut(subChunk, inPositions, inUVs, startAngle - 90, endAngle - 90, outPositions, outUVs); + break; + case SpriteFilledOrigin.Left: + // Center=LM, A: [LM,LB,RM,RB], B: [LM,RM,LT,RT] + (inPositions[0] = wLM), (inUVs[0] = uvLM); + (inPositions[1] = wLB), (inUVs[1] = uvLB); + (inPositions[2] = wRM), (inUVs[2] = uvRM); + (inPositions[3] = wRB), (inUVs[3] = uvRB); + this._radialCut(subChunk, inPositions, inUVs, startAngle, endAngle, outPositions, outUVs); + (inPositions[1] = wRM), (inUVs[1] = uvRM); + (inPositions[2] = wLT), (inUVs[2] = uvLT); + (inPositions[3] = wRT), (inUVs[3] = uvRT); + this._radialCut(subChunk, inPositions, inUVs, startAngle - 90, endAngle - 90, outPositions, outUVs); + break; + case SpriteFilledOrigin.Right: + // Center=RM, A: [RM,RT,LM,LT], B: [RM,LM,RB,LB] + (inPositions[0] = wRM), (inUVs[0] = uvRM); + (inPositions[1] = wRT), (inUVs[1] = uvRT); + (inPositions[2] = wLM), (inUVs[2] = uvLM); + (inPositions[3] = wLT), (inUVs[3] = uvLT); + this._radialCut(subChunk, inPositions, inUVs, startAngle, endAngle, outPositions, outUVs); + (inPositions[1] = wLM), (inUVs[1] = uvLM); + (inPositions[2] = wRB), (inUVs[2] = uvRB); + (inPositions[3] = wLB), (inUVs[3] = uvLB); + this._radialCut(subChunk, inPositions, inUVs, startAngle - 90, endAngle - 90, outPositions, outUVs); + break; + default: + break; + } + + subChunk.indices.length = this._indicesOffset; + } + + private static _filledRadial360( + renderer: ISpriteRenderer, + matrix: Matrix, + origin: SpriteFilledOrigin, + amount: number, + cw: boolean + ): void { + if (amount <= 0.001) { + renderer._subChunk.indices.length = 0; + return; + } + + let startAngle = 0; + switch (origin) { + case SpriteFilledOrigin.Right: + startAngle = cw ? 360 - amount * 360 : 0; + break; + case SpriteFilledOrigin.Top: + startAngle = cw ? 450 - amount * 360 : 90; + break; + case SpriteFilledOrigin.Left: + startAngle = cw ? 540 - amount * 360 : 180; + break; + case SpriteFilledOrigin.Bottom: + startAngle = cw ? 630 - amount * 360 : 270; + break; + default: + break; + } + const endAngle = startAngle + amount * 360; + + this._processRadialGrid(renderer, matrix, startAngle, endAngle); + } + + /** + * Prepare the 3x3 grid and process 4 quadrants for radial fill. + */ + private static _processRadialGrid( + renderer: ISpriteRenderer, + matrix: Matrix, + startAngle: number, + endAngle: number + ): void { + const sprite = renderer.sprite; + const [lPosLB, lPosRB, lPosLT, lPosRT] = sprite._getPositions(); + const spriteUVs = sprite._getUVs(); + const { x: left, y: bottom } = spriteUVs[0]; + const { x: right, y: top } = spriteUVs[15]; + + // --------------- + // LT - MT - RT + // | | | + // LM - C - RM + // | | | + // LB - MB - RB + // --------------- + const [wPosLB, wPosMB, wPosRB, wPosLM, wPosC, wPosRM, wPosLT, wPosMT, wPosRT] = this._worldPositions; + const [uvLB, uvMB, uvRB, uvLM, uvC, uvRM, uvLT, uvMT, uvRT] = this._uvs; + + wPosLB.set(lPosLB.x, lPosLB.y, 0).transformToVec3(matrix), uvLB.set(left, bottom); + wPosRB.set(lPosRB.x, lPosRB.y, 0).transformToVec3(matrix), uvRB.set(right, bottom); + wPosLT.set(lPosLT.x, lPosLT.y, 0).transformToVec3(matrix), uvLT.set(left, top); + wPosRT.set(lPosRT.x, lPosRT.y, 0).transformToVec3(matrix), uvRT.set(right, top); + Vector3.lerp(wPosLB, wPosRB, 0.5, wPosMB), Vector2.lerp(uvLB, uvRB, 0.5, uvMB); + Vector3.lerp(wPosLB, wPosLT, 0.5, wPosLM), Vector2.lerp(uvLB, uvLT, 0.5, uvLM); + Vector3.lerp(wPosLT, wPosRT, 0.5, wPosMT), Vector2.lerp(uvLT, uvRT, 0.5, uvMT); + Vector3.lerp(wPosRB, wPosRT, 0.5, wPosRM), Vector2.lerp(uvRB, uvRT, 0.5, uvRM); + Vector3.lerp(wPosLB, wPosRT, 0.5, wPosC), Vector2.lerp(uvLB, uvRT, 0.5, uvC); + + this._vertexOffset = this._indicesOffset = 0; + const { _inPositions: inPositions, _inUVs: inUVs, _outPositions: outPositions, _outUVs: outUVs } = this; + const { _subChunk: subChunk } = renderer; + let quadrantStart = 0; + let quadrantEnd = 0; + (inPositions[0] = wPosC), (inUVs[0] = uvC); + + { + // First quadrant (0°-90°) + if (startAngle >= 90) { + quadrantStart = startAngle - 360; + quadrantEnd = endAngle - 360; + } else { + quadrantStart = startAngle; + quadrantEnd = endAngle; + } + (inPositions[1] = wPosRM), (inUVs[1] = uvRM); + (inPositions[2] = wPosMT), (inUVs[2] = uvMT); + (inPositions[3] = wPosRT), (inUVs[3] = uvRT); + this._radialCut(subChunk, inPositions, inUVs, quadrantStart, quadrantEnd, outPositions, outUVs); + } + + { + // Second quadrant (90°-180°) + if (startAngle >= 180) { + quadrantStart = startAngle - 360 - 90; + quadrantEnd = endAngle - 360 - 90; + } else { + quadrantStart = startAngle - 90; + quadrantEnd = endAngle - 90; + } + (inPositions[1] = wPosMT), (inUVs[1] = uvMT); + (inPositions[2] = wPosLM), (inUVs[2] = uvLM); + (inPositions[3] = wPosLT), (inUVs[3] = uvLT); + this._radialCut(subChunk, inPositions, inUVs, quadrantStart, quadrantEnd, outPositions, outUVs); + } + + { + // Third quadrant (180°-270°) + if (startAngle >= 270) { + quadrantStart = startAngle - 360 - 180; + quadrantEnd = endAngle - 360 - 180; + } else { + quadrantStart = startAngle - 180; + quadrantEnd = endAngle - 180; + } + (inPositions[1] = wPosLM), (inUVs[1] = uvLM); + (inPositions[2] = wPosMB), (inUVs[2] = uvMB); + (inPositions[3] = wPosLB), (inUVs[3] = uvLB); + this._radialCut(subChunk, inPositions, inUVs, quadrantStart, quadrantEnd, outPositions, outUVs); + } + + { + // Fourth quadrant (270°-360°) + if (startAngle >= 360) { + quadrantStart = startAngle - 360 - 270; + quadrantEnd = endAngle - 360 - 270; + } else { + quadrantStart = startAngle - 270; + quadrantEnd = endAngle - 270; + } + (inPositions[1] = wPosMB), (inUVs[1] = uvMB); + (inPositions[2] = wPosRM), (inUVs[2] = uvRM); + (inPositions[3] = wPosRB), (inUVs[3] = uvRB); + this._radialCut(subChunk, inPositions, inUVs, quadrantStart, quadrantEnd, outPositions, outUVs); + } + + subChunk.indices.length = this._indicesOffset; + } + + private static _radialCut( + subChunk: SubPrimitiveChunk, + positions: Vector3[], + uvs: Vector2[], + start: number, + end: number, + outPositions: Vector3[], + outUVs: Vector2[] + ): void { + if (start >= 90 || end <= 0) return; + outPositions[0].copyFrom(positions[0]); + outUVs[0].copyFrom(uvs[0]); + + if (start <= 0) { + outPositions[1].copyFrom(positions[1]); + outUVs[1].copyFrom(uvs[1]); + } else { + const startTan = Math.tan((start * Math.PI) / 180); + if (startTan < 1) { + Vector3.lerp(positions[1], positions[3], startTan, outPositions[1]); + Vector2.lerp(uvs[1], uvs[3], startTan, outUVs[1]); + } else { + Vector3.lerp(positions[2], positions[3], 1 / startTan, outPositions[1]); + Vector2.lerp(uvs[2], uvs[3], 1 / startTan, outUVs[1]); + } + } + + if (end >= 90) { + outPositions[2].copyFrom(positions[2]); + outUVs[2].copyFrom(uvs[2]); + } else { + const endTan = Math.tan((end * Math.PI) / 180); + if (endTan < 1) { + Vector3.lerp(positions[1], positions[3], endTan, outPositions[2]); + Vector2.lerp(uvs[1], uvs[3], endTan, outUVs[2]); + } else { + Vector3.lerp(positions[2], positions[3], 1 / endTan, outPositions[2]); + Vector2.lerp(uvs[2], uvs[3], 1 / endTan, outUVs[2]); + } + } + + if (start < 45 && end > 45) { + outPositions[3].copyFrom(positions[3]); + outUVs[3].copyFrom(uvs[3]); + this._addQuad(subChunk, outPositions, outUVs); + } else { + this._addTriangle(subChunk, outPositions, outUVs); + } + } + + private static _addTriangle(subChunk: SubPrimitiveChunk, positions: Vector3[], uvs: Vector2[]): void { + const vertices = subChunk.chunk.vertices; + const indices = subChunk.indices; + const vertexOffset = this._vertexOffset; + const vertexCount = vertexOffset / 9; + const start = subChunk.vertexArea.start + vertexOffset; + for (let i = 0, o = start; i < 3; ++i, o += 9) { + const position = positions[i]; + const uv = uvs[i]; + vertices[o] = position.x; + vertices[o + 1] = position.y; + vertices[o + 2] = position.z; + vertices[o + 3] = uv.x; + vertices[o + 4] = uv.y; + } + const indicesOffset = this._indicesOffset; + indices[indicesOffset] = vertexCount; + indices[indicesOffset + 1] = vertexCount + 1; + indices[indicesOffset + 2] = vertexCount + 2; + this._vertexOffset += 3 * 9; + this._indicesOffset += 3; + } + + private static _addQuad(subChunk: SubPrimitiveChunk, positions: Vector3[], uvs: Vector2[]): void { + const vertices = subChunk.chunk.vertices; + const indices = subChunk.indices; + const vertexOffset = this._vertexOffset; + const vertexCount = vertexOffset / 9; + const start = subChunk.vertexArea.start + vertexOffset; + for (let i = 0, o = start; i < 4; ++i, o += 9) { + const position = positions[i]; + const uv = uvs[i]; + vertices[o] = position.x; + vertices[o + 1] = position.y; + vertices[o + 2] = position.z; + vertices[o + 3] = uv.x; + vertices[o + 4] = uv.y; + } + const indicesOffset = this._indicesOffset; + indices[indicesOffset] = vertexCount; + indices[indicesOffset + 1] = vertexCount + 1; + indices[indicesOffset + 2] = vertexCount + 2; + indices[indicesOffset + 3] = vertexCount + 2; + indices[indicesOffset + 4] = vertexCount + 1; + indices[indicesOffset + 5] = vertexCount + 3; + this._vertexOffset += 4 * 9; + this._indicesOffset += 6; + } +} diff --git a/packages/core/src/2d/assembler/ISpriteRenderer.ts b/packages/core/src/2d/assembler/ISpriteRenderer.ts index a72f4e9436..04b50b3fc9 100644 --- a/packages/core/src/2d/assembler/ISpriteRenderer.ts +++ b/packages/core/src/2d/assembler/ISpriteRenderer.ts @@ -1,6 +1,8 @@ import { Color } from "@galacean/engine-math"; import { PrimitiveChunkManager } from "../../RenderPipeline/PrimitiveChunkManager"; import { SubPrimitiveChunk } from "../../RenderPipeline/SubPrimitiveChunk"; +import { SpriteFilledMode } from "../enums/SpriteFilledMode"; +import { SpriteFilledOrigin } from "../enums/SpriteFilledOrigin"; import { SpriteTileMode } from "../enums/SpriteTileMode"; import { Sprite } from "../sprite"; @@ -12,6 +14,10 @@ export interface ISpriteRenderer { color?: Color; tileMode?: SpriteTileMode; tiledAdaptiveThreshold?: number; + filledMode?: SpriteFilledMode; + filledAmount?: number; + filledOrigin?: SpriteFilledOrigin; + filledClockWise?: boolean; _subChunk: SubPrimitiveChunk; _getChunkManager(): PrimitiveChunkManager; } diff --git a/packages/core/src/2d/assembler/SimpleSpriteAssembler.ts b/packages/core/src/2d/assembler/SimpleSpriteAssembler.ts index 563f812106..6e0e07c368 100644 --- a/packages/core/src/2d/assembler/SimpleSpriteAssembler.ts +++ b/packages/core/src/2d/assembler/SimpleSpriteAssembler.ts @@ -66,20 +66,25 @@ export class SimpleSpriteAssembler { } static updateUVs(renderer: ISpriteRenderer): void { + // sprite._uvs 16 个网格点 (column-major, index=column*4+row),4 corner: [0]=LB / [3]=LT / [12]=RB / [15]=RT + // atlasRotated 由 sprite._updateUVs 内部处理,此处直接用结果,无需关心朝向 const spriteUVs = renderer.sprite._getUVs(); - const { x: left, y: bottom } = spriteUVs[0]; - const { x: right, y: top } = spriteUVs[3]; const subChunk = renderer._subChunk; const vertices = subChunk.chunk.vertices; const offset = subChunk.vertexArea.start + 3; - vertices[offset] = left; - vertices[offset + 1] = bottom; - vertices[offset + 9] = right; - vertices[offset + 10] = bottom; - vertices[offset + 18] = left; - vertices[offset + 19] = top; - vertices[offset + 27] = right; - vertices[offset + 28] = top; + const uvLB = spriteUVs[0]; + const uvLT = spriteUVs[3]; + const uvRB = spriteUVs[12]; + const uvRT = spriteUVs[15]; + // SimpleAssembler 的 vertex 顺序:0=LB, 1=RB, 2=LT, 3=RT (按 _rectangleTriangles 的拓扑) + vertices[offset] = uvLB.x; + vertices[offset + 1] = uvLB.y; + vertices[offset + 9] = uvRB.x; + vertices[offset + 10] = uvRB.y; + vertices[offset + 18] = uvLT.x; + vertices[offset + 19] = uvLT.y; + vertices[offset + 27] = uvRT.x; + vertices[offset + 28] = uvRT.y; } static updateColor(renderer: ISpriteRenderer, alpha: number): void { diff --git a/packages/core/src/2d/assembler/SlicedSpriteAssembler.ts b/packages/core/src/2d/assembler/SlicedSpriteAssembler.ts index 31d19d149c..09abce5be3 100644 --- a/packages/core/src/2d/assembler/SlicedSpriteAssembler.ts +++ b/packages/core/src/2d/assembler/SlicedSpriteAssembler.ts @@ -126,14 +126,15 @@ export class SlicedSpriteAssembler { } static updateUVs(renderer: ISpriteRenderer): void { + // 16 UV 网格 (column-major: index = i*4+j, i=column, j=row),与 vertex 索引一一对应 const subChunk = renderer._subChunk; const vertices = subChunk.chunk.vertices; const spriteUVs = renderer.sprite._getUVs(); for (let i = 0, o = subChunk.vertexArea.start + 3; i < 4; i++) { - const rowU = spriteUVs[i].x; for (let j = 0; j < 4; j++, o += 9) { - vertices[o] = rowU; - vertices[o + 1] = spriteUVs[j].y; + const uv = spriteUVs[i * 4 + j]; + vertices[o] = uv.x; + vertices[o + 1] = uv.y; } } } diff --git a/packages/core/src/2d/assembler/TiledSpriteAssembler.ts b/packages/core/src/2d/assembler/TiledSpriteAssembler.ts index bc765c45f9..448d0543a4 100644 --- a/packages/core/src/2d/assembler/TiledSpriteAssembler.ts +++ b/packages/core/src/2d/assembler/TiledSpriteAssembler.ts @@ -188,7 +188,12 @@ export class TiledSpriteAssembler { const spritePositions = sprite._getPositions(); const { x: left, y: bottom } = spritePositions[0]; const { x: right, y: top } = spritePositions[3]; - const [spriteUV0, spriteUV1, spriteUV2, spriteUV3] = sprite._getUVs(); + // 16 UV column-major: [0]=LB(left,bottom), [5]=border-LB(bLeft,bBottom), [10]=border-RT(bRight,bTop), [15]=RT(right,top) + const allUVs = sprite._getUVs(); + const spriteUV0 = allUVs[0]; + const spriteUV1 = allUVs[5]; + const spriteUV2 = allUVs[10]; + const spriteUV3 = allUVs[15]; const expectWidth = sprite.width * referenceResolutionPerUnit; const expectHeight = sprite.height * referenceResolutionPerUnit; const fixedL = expectWidth * border.x; diff --git a/packages/core/src/2d/atlas/SpriteAtlas.ts b/packages/core/src/2d/atlas/SpriteAtlas.ts index 44adadbfdd..93828efe2e 100644 --- a/packages/core/src/2d/atlas/SpriteAtlas.ts +++ b/packages/core/src/2d/atlas/SpriteAtlas.ts @@ -45,7 +45,7 @@ export class SpriteAtlas extends ReferResource { sprite.name === name && outSprites.push(sprite); } } else { - console.warn("The name of the sprite you want to find is not exit in SpriteAtlas."); + console.warn("There is no sprite named " + name + " in the atlas."); } return outSprites; } diff --git a/packages/core/src/2d/enums/SpriteDrawMode.ts b/packages/core/src/2d/enums/SpriteDrawMode.ts index 46bcfd3783..6f35d8c1ef 100644 --- a/packages/core/src/2d/enums/SpriteDrawMode.ts +++ b/packages/core/src/2d/enums/SpriteDrawMode.ts @@ -7,5 +7,7 @@ export enum SpriteDrawMode { /** When modifying the size of the renderer, it scales to fill the range according to the sprite border settings. */ Sliced, /** When modifying the size of the renderer, it will tile to fill the range according to the sprite border settings. */ - Tiled + Tiled, + /** Fill the sprite partially, controlled by fill amount, mode and origin. */ + Filled } diff --git a/packages/core/src/2d/enums/SpriteFilledMode.ts b/packages/core/src/2d/enums/SpriteFilledMode.ts new file mode 100644 index 0000000000..a01cda9e53 --- /dev/null +++ b/packages/core/src/2d/enums/SpriteFilledMode.ts @@ -0,0 +1,15 @@ +/** + * Sprite's filled mode enumeration. + */ +export enum SpriteFilledMode { + /** Fill horizontally. */ + Horizontal, + /** Fill vertically. */ + Vertical, + /** Fill radially over 90 degrees. */ + Radial90, + /** Fill radially over 180 degrees. */ + Radial180, + /** Fill radially over 360 degrees. */ + Radial360 +} diff --git a/packages/core/src/2d/enums/SpriteFilledOrigin.ts b/packages/core/src/2d/enums/SpriteFilledOrigin.ts new file mode 100644 index 0000000000..e9b3193970 --- /dev/null +++ b/packages/core/src/2d/enums/SpriteFilledOrigin.ts @@ -0,0 +1,21 @@ +/** + * Sprite's filled origin enumeration. + */ +export enum SpriteFilledOrigin { + /** Origin at the right. */ + Right, + /** Origin at the top-right. */ + TopRight, + /** Origin at the top. */ + Top, + /** Origin at the top-left. */ + TopLeft, + /** Origin at the left. */ + Left, + /** Origin at the bottom-left. */ + BottomLeft, + /** Origin at the bottom. */ + Bottom, + /** Origin at the bottom-right. */ + BottomRight +} diff --git a/packages/core/src/2d/index.ts b/packages/core/src/2d/index.ts index 47be64ccfc..5481f42b28 100644 --- a/packages/core/src/2d/index.ts +++ b/packages/core/src/2d/index.ts @@ -1,11 +1,14 @@ export type { ISpriteAssembler } from "./assembler/ISpriteAssembler"; export type { ISpriteRenderer } from "./assembler/ISpriteRenderer"; +export { FilledSpriteAssembler } from "./assembler/FilledSpriteAssembler"; export { SimpleSpriteAssembler } from "./assembler/SimpleSpriteAssembler"; export { SlicedSpriteAssembler } from "./assembler/SlicedSpriteAssembler"; export { TiledSpriteAssembler } from "./assembler/TiledSpriteAssembler"; export { SpriteAtlas } from "./atlas/SpriteAtlas"; export { FontStyle } from "./enums/FontStyle"; export { SpriteDrawMode } from "./enums/SpriteDrawMode"; +export { SpriteFilledMode } from "./enums/SpriteFilledMode"; +export { SpriteFilledOrigin } from "./enums/SpriteFilledOrigin"; export { SpriteMaskInteraction } from "./enums/SpriteMaskInteraction"; export { SpriteModifyFlags } from "./enums/SpriteModifyFlags"; export { SpriteTileMode } from "./enums/SpriteTileMode"; diff --git a/packages/core/src/2d/sprite/Sprite.ts b/packages/core/src/2d/sprite/Sprite.ts index 5232001c9a..b7f01f342e 100644 --- a/packages/core/src/2d/sprite/Sprite.ts +++ b/packages/core/src/2d/sprite/Sprite.ts @@ -20,7 +20,16 @@ export class Sprite extends ReferResource { private _customHeight: number = undefined; private _positions: Vector2[] = [new Vector2(), new Vector2(), new Vector2(), new Vector2()]; - private _uvs: Vector2[] = [new Vector2(), new Vector2(), new Vector2(), new Vector2()]; + // 16 UV 顶点构成 4×4 网格(含 9-slice 内边界)。column-major:index = i*4 + j,i=column(0=left..3=right),j=row(0=bottom..3=top)。 + // 与 SlicedAssembler/TiledAssembler 的 vertex 索引图一致:[0]=LB, [3]=LT, [12]=RB, [15]=RT。 + // SimpleAssembler 取 [0]/[3]/[12]/[15] 4 个 corner;Sliced/Tiled 用全 16。 + // prettier-ignore + private _uvs: Vector2[] = [ + new Vector2(), new Vector2(), new Vector2(), new Vector2(), + new Vector2(), new Vector2(), new Vector2(), new Vector2(), + new Vector2(), new Vector2(), new Vector2(), new Vector2(), + new Vector2(), new Vector2(), new Vector2(), new Vector2(), + ]; private _bounds: BoundingBox = new BoundingBox(); private _texture: Texture2D = null; @@ -287,16 +296,18 @@ export class Sprite extends ReferResource { private _calDefaultSize(): void { if (this._texture) { - const { _texture, _atlasRegion, _atlasRegionOffset, _region } = this; - const pixelsPerUnitReciprocal = 1.0 / Engine._pixelsPerUnit; + const { _texture, _atlasRegion, _atlasRegionOffset, _region, _atlasRotated } = this; + const ppuReciprocal = 1.0 / Engine._pixelsPerUnit; + // 先算 atlas 中绝对像素(texture 不一定是方形,必须各自乘对应维度) + const atlasPxW = _texture.width * _atlasRegion.width; + const atlasPxH = _texture.height * _atlasRegion.height; + // atlas 顺时针 pack 90°:原图 W×H 在 atlas 中占 H×W 区域,仅交换 atlasPx 的 W/H + const originWidth = _atlasRotated ? atlasPxH : atlasPxW; + const originHeight = _atlasRotated ? atlasPxW : atlasPxH; this._automaticWidth = - ((_texture.width * _atlasRegion.width) / (1 - _atlasRegionOffset.x - _atlasRegionOffset.z)) * - _region.width * - pixelsPerUnitReciprocal; + (originWidth / (1 - _atlasRegionOffset.x - _atlasRegionOffset.z)) * _region.width * ppuReciprocal; this._automaticHeight = - ((_texture.height * _atlasRegion.height) / (1 - _atlasRegionOffset.y - _atlasRegionOffset.w)) * - _region.height * - pixelsPerUnitReciprocal; + (originHeight / (1 - _atlasRegionOffset.y - _atlasRegionOffset.w)) * _region.height * ppuReciprocal; } else { this._automaticWidth = this._automaticHeight = 0; } @@ -332,34 +343,52 @@ export class Sprite extends ReferResource { } private _updateUVs(): void { - const { _uvs: uv, _atlasRegionOffset: atlasRegionOffset } = this; - const { x: regionX, y: regionY, width: regionW, height: regionH } = this._region; - const regionRight = 1 - regionX - regionW; - const regionBottom = 1 - regionY - regionH; + const { _uvs: uvs, _atlasRotated: atlasRotated, _border: border } = this; + const { x: regionLeft, y: regionTop, width: regionW, height: regionH } = this._region; + const regionRight = 1 - regionLeft - regionW; + const regionBottom = 1 - regionTop - regionH; const { x: atlasRegionX, y: atlasRegionY, width: atlasRegionW, height: atlasRegionH } = this._atlasRegion; - const { x: offsetLeft, y: offsetTop, z: offsetRight, w: offsetBottom } = atlasRegionOffset; + const { x: offsetLeft, y: offsetTop, z: offsetRight, w: offsetBottom } = this._atlasRegionOffset; const realWidth = atlasRegionW / (1 - offsetLeft - offsetRight); const realHeight = atlasRegionH / (1 - offsetTop - offsetBottom); - // Coordinates of the four boundaries. - const left = Math.max(regionX - offsetLeft, 0) * realWidth + atlasRegionX; - const top = Math.max(regionBottom - offsetTop, 0) * realHeight + atlasRegionY; - const right = atlasRegionW + atlasRegionX - Math.max(regionRight - offsetRight, 0) * realWidth; - const bottom = atlasRegionH + atlasRegionY - Math.max(regionY - offsetBottom, 0) * realHeight; - const { x: borderLeft, y: borderBottom, z: borderRight, w: borderTop } = this._border; - // Left-Bottom - uv[0].set(left, bottom); - // Border ( Left-Bottom ) - uv[1].set( - (regionX - offsetLeft + borderLeft * regionW) * realWidth + atlasRegionX, - atlasRegionH + atlasRegionY - (regionY - offsetBottom + borderBottom * regionH) * realHeight - ); - // Border ( Right-Top ) - uv[2].set( - atlasRegionW + atlasRegionX - (regionRight - offsetRight + borderRight * regionW) * realWidth, - (regionBottom - offsetTop + borderTop * regionH) * realHeight + atlasRegionY - ); - // Right-Top - uv[3].set(right, top); + // 4 个外边界 + 4 个 9-slice 内边界 + let left: number, top: number, right: number, bottom: number; + let bLeft: number, bTop: number, bRight: number, bBottom: number; + if (atlasRotated) { + // 原图 region/offset (left/top/right/bottom) 在 atlas 中映射为 (bottom/left/top/right) + left = Math.max(regionBottom - offsetLeft, 0) * realWidth + atlasRegionX; + top = Math.max(regionLeft - offsetTop, 0) * realHeight + atlasRegionY; + right = atlasRegionW + atlasRegionX - Math.max(regionTop - offsetRight, 0) * realWidth; + bottom = atlasRegionH + atlasRegionY - Math.max(regionRight - offsetBottom, 0) * realHeight; + bLeft = (regionBottom - offsetLeft + border.y * regionH) * realWidth + atlasRegionX; + bTop = (regionLeft - offsetTop + border.x * regionW) * realHeight + atlasRegionY; + bRight = atlasRegionW + atlasRegionX - (regionTop - offsetRight + border.w * regionH) * realWidth; + bBottom = atlasRegionH + atlasRegionY - (regionRight - offsetBottom + border.z * regionW) * realHeight; + } else { + left = Math.max(regionLeft - offsetLeft, 0) * realWidth + atlasRegionX; + top = Math.max(regionBottom - offsetTop, 0) * realHeight + atlasRegionY; + right = atlasRegionW + atlasRegionX - Math.max(regionRight - offsetRight, 0) * realWidth; + bottom = atlasRegionH + atlasRegionY - Math.max(regionTop - offsetBottom, 0) * realHeight; + bLeft = (regionLeft - offsetLeft + border.x * regionW) * realWidth + atlasRegionX; + bTop = (regionBottom - offsetTop + border.w * regionH) * realHeight + atlasRegionY; + bRight = atlasRegionW + atlasRegionX - (regionRight - offsetRight + border.z * regionW) * realWidth; + bBottom = atlasRegionH + atlasRegionY - (regionTop - offsetBottom + border.y * regionH) * realHeight; + } + + // 16 UV 网格填充(column-major:index=i*4+j,i=column[0=left..3=right],j=row[0=bottom..3=top]) + // - 非 rotated:column 决定 atlas X (left/bLeft/bRight/right),row 决定 atlas Y (bottom/bBottom/bTop/top) + // - rotated 90° 顺时针 packed:display column 对应 atlas Y 的反向(顶→底),display row 对应 atlas X + if (atlasRotated) { + uvs[0].set(left, top), uvs[1].set(bLeft, top), uvs[2].set(bRight, top), uvs[3].set(right, top); + uvs[4].set(left, bTop), uvs[5].set(bLeft, bTop), uvs[6].set(bRight, bTop), uvs[7].set(right, bTop); + uvs[8].set(left, bBottom), uvs[9].set(bLeft, bBottom), uvs[10].set(bRight, bBottom), uvs[11].set(right, bBottom); + uvs[12].set(left, bottom), uvs[13].set(bLeft, bottom), uvs[14].set(bRight, bottom), uvs[15].set(right, bottom); + } else { + uvs[0].set(left, bottom), uvs[1].set(left, bBottom), uvs[2].set(left, bTop), uvs[3].set(left, top); + uvs[4].set(bLeft, bottom), uvs[5].set(bLeft, bBottom), uvs[6].set(bLeft, bTop), uvs[7].set(bLeft, top); + uvs[8].set(bRight, bottom), uvs[9].set(bRight, bBottom), uvs[10].set(bRight, bTop), uvs[11].set(bRight, top); + uvs[12].set(right, bottom), uvs[13].set(right, bBottom), uvs[14].set(right, bTop), uvs[15].set(right, top); + } this._dirtyUpdateFlag &= ~SpriteUpdateFlags.uvs; } diff --git a/packages/core/src/2d/sprite/SpriteMask.ts b/packages/core/src/2d/sprite/SpriteMask.ts index 141f352d35..1f740081f9 100644 --- a/packages/core/src/2d/sprite/SpriteMask.ts +++ b/packages/core/src/2d/sprite/SpriteMask.ts @@ -1,12 +1,10 @@ import { BoundingBox } from "@galacean/engine-math"; import { Entity } from "../../Entity"; -import { RenderQueueFlags } from "../../RenderPipeline/BasicRenderPipeline"; -import { BatchUtils } from "../../RenderPipeline/BatchUtils"; +import { VertexMergeBatcher } from "../../RenderPipeline/VertexMergeBatcher"; import { PrimitiveChunkManager } from "../../RenderPipeline/PrimitiveChunkManager"; import { RenderContext } from "../../RenderPipeline/RenderContext"; -import { RenderElement } from "../../RenderPipeline/RenderElement"; import { SubPrimitiveChunk } from "../../RenderPipeline/SubPrimitiveChunk"; -import { SubRenderElement } from "../../RenderPipeline/SubRenderElement"; +import { RenderElement } from "../../RenderPipeline/RenderElement"; import { Renderer, RendererUpdateFlags } from "../../Renderer"; import { assignmentClone, ignoreClone } from "../../clone/CloneManager"; import { SpriteMaskLayer } from "../../enums/SpriteMaskLayer"; @@ -181,16 +179,15 @@ export class SpriteMask extends Renderer implements ISpriteRenderer { this.setMaterial(this._engine._basicResources.spriteMaskDefaultMaterial); this.shaderData.setFloat(SpriteMask._alphaCutoffProperty, this._alphaCutoff); this._renderElement = new RenderElement(); - this._renderElement.addSubRenderElement(new SubRenderElement()); this._onSpriteChange = this._onSpriteChange.bind(this); } /** * @internal */ - override _updateTransformShaderData(context: RenderContext, onlyMVP: boolean, batched: boolean): void { + override _updateTransformShaderData(context: RenderContext, onlyMVP: boolean): void { //@todo: Always update world positions to buffer, should opt - super._updateTransformShaderData(context, onlyMVP, true); + this._updateWorldSpaceTransformShaderData(context, onlyMVP); } /** @@ -204,15 +201,15 @@ export class SpriteMask extends Renderer implements ISpriteRenderer { /** * @internal */ - override _canBatch(elementA: SubRenderElement, elementB: SubRenderElement): boolean { - return BatchUtils.canBatchSpriteMask(elementA, elementB); + override _canBatch(preElement: RenderElement, curElement: RenderElement): boolean { + return VertexMergeBatcher.canBatchSpriteMask(preElement, curElement); } /** * @internal */ - override _batch(elementA: SubRenderElement, elementB?: SubRenderElement): void { - BatchUtils.batchFor2D(elementA, elementB); + override _batch(preElement: RenderElement | null, curElement: RenderElement): void { + VertexMergeBatcher.batch(preElement, curElement); } /** @@ -297,14 +294,11 @@ export class SpriteMask extends Renderer implements ISpriteRenderer { } const renderElement = this._renderElement; - const subRenderElement = renderElement.subRenderElements[0]; - renderElement.set(this.priority, this._distanceForSort); - const subChunk = this._subChunk; - subRenderElement.set(this, material, subChunk.chunk.primitive, subChunk.subMesh, this.sprite.texture, subChunk); - subRenderElement.shaderPasses = material.shader.subShaders[0].passes; - subRenderElement.renderQueueFlags = RenderQueueFlags.All; - renderElement.addSubRenderElement(subRenderElement); + renderElement.set(this, material, subChunk.chunk.primitive, subChunk.subMesh, this.sprite.texture, subChunk); + renderElement.priority = this.priority; + renderElement.distanceForSort = this._distanceForSort; + renderElement.subShader = material.shader.subShaders[0]; } /** diff --git a/packages/core/src/2d/sprite/SpriteRenderer.ts b/packages/core/src/2d/sprite/SpriteRenderer.ts index c1b183ee7a..06bd3d3c6c 100644 --- a/packages/core/src/2d/sprite/SpriteRenderer.ts +++ b/packages/core/src/2d/sprite/SpriteRenderer.ts @@ -1,19 +1,22 @@ import { BoundingBox, Color, MathUtil } from "@galacean/engine-math"; import { Entity } from "../../Entity"; -import { BatchUtils } from "../../RenderPipeline/BatchUtils"; +import { VertexMergeBatcher } from "../../RenderPipeline/VertexMergeBatcher"; import { PrimitiveChunkManager } from "../../RenderPipeline/PrimitiveChunkManager"; import { RenderContext } from "../../RenderPipeline/RenderContext"; import { SubPrimitiveChunk } from "../../RenderPipeline/SubPrimitiveChunk"; -import { SubRenderElement } from "../../RenderPipeline/SubRenderElement"; +import { RenderElement } from "../../RenderPipeline/RenderElement"; import { Renderer, RendererUpdateFlags } from "../../Renderer"; import { assignmentClone, deepClone, ignoreClone } from "../../clone/CloneManager"; import { ShaderProperty } from "../../shader/ShaderProperty"; import { ISpriteAssembler } from "../assembler/ISpriteAssembler"; import { ISpriteRenderer } from "../assembler/ISpriteRenderer"; +import { FilledSpriteAssembler } from "../assembler/FilledSpriteAssembler"; import { SimpleSpriteAssembler } from "../assembler/SimpleSpriteAssembler"; import { SlicedSpriteAssembler } from "../assembler/SlicedSpriteAssembler"; import { TiledSpriteAssembler } from "../assembler/TiledSpriteAssembler"; import { SpriteDrawMode } from "../enums/SpriteDrawMode"; +import { SpriteFilledMode } from "../enums/SpriteFilledMode"; +import { SpriteFilledOrigin } from "../enums/SpriteFilledOrigin"; import { SpriteMaskInteraction } from "../enums/SpriteMaskInteraction"; import { SpriteModifyFlags } from "../enums/SpriteModifyFlags"; import { SpriteTileMode } from "../enums/SpriteTileMode"; @@ -39,6 +42,14 @@ export class SpriteRenderer extends Renderer implements ISpriteRenderer { private _tileMode: SpriteTileMode = SpriteTileMode.Continuous; @assignmentClone private _tiledAdaptiveThreshold: number = 0.5; + @assignmentClone + private _filledMode: SpriteFilledMode = SpriteFilledMode.Radial360; + @assignmentClone + private _filledAmount: number = 1; + @assignmentClone + private _filledOrigin: SpriteFilledOrigin = SpriteFilledOrigin.Bottom; + @assignmentClone + private _filledClockWise: boolean = true; @deepClone private _color: Color = new Color(1, 1, 1, 1); @@ -78,6 +89,9 @@ export class SpriteRenderer extends Renderer implements ISpriteRenderer { case SpriteDrawMode.Tiled: this._assembler = TiledSpriteAssembler; break; + case SpriteDrawMode.Filled: + this._assembler = FilledSpriteAssembler; + break; default: break; } @@ -119,6 +133,74 @@ export class SpriteRenderer extends Renderer implements ISpriteRenderer { } } + /** + * The fill amount of the sprite renderer, range from 0 to 1. (Only works in filled mode.) + */ + get filledAmount(): number { + return this._filledAmount; + } + + set filledAmount(value: number) { + value = MathUtil.clamp(value, 0, 1); + if (this._filledAmount !== value) { + this._filledAmount = value; + if (this._drawMode === SpriteDrawMode.Filled) { + this._dirtyUpdateFlag |= SpriteRendererUpdateFlags.WorldVolumeAndUV; + } + } + } + + /** + * The fill mode of the sprite renderer. (Only works in filled mode.) + */ + get filledMode(): SpriteFilledMode { + return this._filledMode; + } + + set filledMode(value: SpriteFilledMode) { + if (this._filledMode !== value) { + this._filledMode = value; + // Reset origin to a valid default for the new mode + this._filledOrigin = + value === SpriteFilledMode.Radial90 ? SpriteFilledOrigin.BottomLeft : SpriteFilledOrigin.Bottom; + if (this._drawMode === SpriteDrawMode.Filled) { + this._dirtyUpdateFlag |= SpriteRendererUpdateFlags.WorldVolumeAndUV; + } + } + } + + /** + * The fill origin of the sprite renderer. (Only works in filled mode.) + */ + get filledOrigin(): SpriteFilledOrigin { + return this._filledOrigin; + } + + set filledOrigin(value: SpriteFilledOrigin) { + if (this._filledOrigin !== value) { + this._filledOrigin = value; + if (this._drawMode === SpriteDrawMode.Filled) { + this._dirtyUpdateFlag |= SpriteRendererUpdateFlags.WorldVolumeAndUV; + } + } + } + + /** + * Whether the fill is clockwise. (Only works in filled radial mode.) + */ + get filledClockWise(): boolean { + return this._filledClockWise; + } + + set filledClockWise(value: boolean) { + if (this._filledClockWise !== value) { + this._filledClockWise = value; + if (this._drawMode === SpriteDrawMode.Filled) { + this._dirtyUpdateFlag |= SpriteRendererUpdateFlags.WorldVolumeAndUV; + } + } + } + /** * The Sprite to render. */ @@ -278,9 +360,9 @@ export class SpriteRenderer extends Renderer implements ISpriteRenderer { /** * @internal */ - override _updateTransformShaderData(context: RenderContext, onlyMVP: boolean, batched: boolean): void { + override _updateTransformShaderData(context: RenderContext, onlyMVP: boolean): void { //@todo: Always update world positions to buffer, should opt - super._updateTransformShaderData(context, onlyMVP, true); + this._updateWorldSpaceTransformShaderData(context, onlyMVP); } /** @@ -295,15 +377,15 @@ export class SpriteRenderer extends Renderer implements ISpriteRenderer { /** * @internal */ - override _canBatch(elementA: SubRenderElement, elementB: SubRenderElement): boolean { - return BatchUtils.canBatchSprite(elementA, elementB); + override _canBatch(preElement: RenderElement, curElement: RenderElement): boolean { + return VertexMergeBatcher.canBatchSprite(preElement, curElement); } /** * @internal */ - override _batch(elementA: SubRenderElement, elementB?: SubRenderElement): void { - BatchUtils.batchFor2D(elementA, elementB); + override _batch(preElement: RenderElement | null, curElement: RenderElement): void { + VertexMergeBatcher.batch(preElement, curElement); } /** @@ -377,11 +459,10 @@ export class SpriteRenderer extends Renderer implements ISpriteRenderer { const camera = context.camera; const engine = camera.engine; const renderElement = engine._renderElementPool.get(); - renderElement.set(this.priority, this._distanceForSort); - const subRenderElement = engine._subRenderElementPool.get(); const subChunk = this._subChunk; - subRenderElement.set(this, material, subChunk.chunk.primitive, subChunk.subMesh, this.sprite.texture, subChunk); - renderElement.addSubRenderElement(subRenderElement); + renderElement.set(this, material, subChunk.chunk.primitive, subChunk.subMesh, this.sprite.texture, subChunk); + renderElement.priority = this.priority; + renderElement.distanceForSort = this._distanceForSort; camera._renderPipeline.pushRenderElement(context, renderElement); } @@ -438,6 +519,9 @@ export class SpriteRenderer extends Renderer implements ISpriteRenderer { case SpriteDrawMode.Tiled: this._dirtyUpdateFlag |= SpriteRendererUpdateFlags.WorldVolumeUVAndColor; break; + case SpriteDrawMode.Filled: + this._dirtyUpdateFlag |= SpriteRendererUpdateFlags.WorldVolumeUVAndColor; + break; } break; case SpriteModifyFlags.border: diff --git a/packages/core/src/2d/text/TextRenderer.ts b/packages/core/src/2d/text/TextRenderer.ts index 143e46a7da..3649180c79 100644 --- a/packages/core/src/2d/text/TextRenderer.ts +++ b/packages/core/src/2d/text/TextRenderer.ts @@ -1,11 +1,11 @@ import { BoundingBox, Color, Vector3 } from "@galacean/engine-math"; import { Engine } from "../../Engine"; import { Entity } from "../../Entity"; -import { BatchUtils } from "../../RenderPipeline/BatchUtils"; +import { VertexMergeBatcher } from "../../RenderPipeline/VertexMergeBatcher"; import { PrimitiveChunkManager } from "../../RenderPipeline/PrimitiveChunkManager"; import { RenderContext } from "../../RenderPipeline/RenderContext"; import { SubPrimitiveChunk } from "../../RenderPipeline/SubPrimitiveChunk"; -import { SubRenderElement } from "../../RenderPipeline/SubRenderElement"; +import { RenderElement } from "../../RenderPipeline/RenderElement"; import { Renderer } from "../../Renderer"; import { TransformModifyFlags } from "../../Transform"; import { assignmentClone, deepClone, ignoreClone } from "../../clone/CloneManager"; @@ -373,23 +373,23 @@ export class TextRenderer extends Renderer implements ITextRenderer { /** * @internal */ - override _updateTransformShaderData(context: RenderContext, onlyMVP: boolean, batched: boolean): void { + override _updateTransformShaderData(context: RenderContext, onlyMVP: boolean): void { //@todo: Always update world positions to buffer, should opt - super._updateTransformShaderData(context, onlyMVP, true); + this._updateWorldSpaceTransformShaderData(context, onlyMVP); } /** * @internal */ - override _canBatch(elementA: SubRenderElement, elementB: SubRenderElement): boolean { - return BatchUtils.canBatchSprite(elementA, elementB); + override _canBatch(preElement: RenderElement, curElement: RenderElement): boolean { + return VertexMergeBatcher.canBatchSprite(preElement, curElement); } /** * @internal */ - override _batch(elementA: SubRenderElement, elementB?: SubRenderElement): void { - BatchUtils.batchFor2D(elementA, elementB); + override _batch(preElement: RenderElement | null, curElement: RenderElement): void { + VertexMergeBatcher.batch(preElement, curElement); } /** @@ -430,20 +430,22 @@ export class TextRenderer extends Renderer implements ITextRenderer { const camera = context.camera; const engine = camera.engine; - const textSubRenderElementPool = engine._textSubRenderElementPool; + const textRenderElementPool = engine._textRenderElementPool; const material = this.getMaterial(); - const renderElement = engine._renderElementPool.get(); - renderElement.set(this.priority, this._distanceForSort); + const priority = this.priority; + const distanceForSort = this._distanceForSort; + const renderPipeline = camera._renderPipeline; const textChunks = this._textChunks; for (let i = 0, n = textChunks.length; i < n; ++i) { const { subChunk, texture } = textChunks[i]; - const subRenderElement = textSubRenderElementPool.get(); - subRenderElement.set(this, material, subChunk.chunk.primitive, subChunk.subMesh, texture, subChunk); - subRenderElement.shaderData ||= new ShaderData(ShaderDataGroup.RenderElement); - subRenderElement.shaderData.setTexture(TextRenderer._textureProperty, texture); - renderElement.addSubRenderElement(subRenderElement); + const renderElement = textRenderElementPool.get(); + renderElement.set(this, material, subChunk.chunk.primitive, subChunk.subMesh, texture, subChunk); + renderElement.shaderData ||= new ShaderData(ShaderDataGroup.RenderElement); + renderElement.shaderData.setTexture(TextRenderer._textureProperty, texture); + renderElement.priority = priority; + renderElement.distanceForSort = distanceForSort; + renderPipeline.pushRenderElement(context, renderElement); } - camera._renderPipeline.pushRenderElement(context, renderElement); } private _resetSubFont(): void { diff --git a/packages/core/src/Camera.ts b/packages/core/src/Camera.ts index 53b689dd84..3faf19a2ef 100644 --- a/packages/core/src/Camera.ts +++ b/packages/core/src/Camera.ts @@ -9,7 +9,7 @@ import { Transform } from "./Transform"; import { UpdateFlagManager } from "./UpdateFlagManager"; import { VirtualCamera } from "./VirtualCamera"; import { GLCapabilityType, Logger } from "./base"; -import { deepClone, ignoreClone } from "./clone/CloneManager"; +import { assignmentClone, deepClone, ignoreClone } from "./clone/CloneManager"; import { AntiAliasing } from "./enums/AntiAliasing"; import { CameraClearFlags } from "./enums/CameraClearFlags"; import { CameraModifyFlags } from "./enums/CameraModifyFlags"; @@ -125,8 +125,10 @@ export class Camera extends Component { @deepClone _virtualCamera: VirtualCamera = new VirtualCamera(); /** @internal */ + @assignmentClone _replacementShader: Shader = null; /** @internal */ + @assignmentClone _replacementSubShaderTag: ShaderTagKey = null; /** @internal */ _replacementFailureStrategy: ReplacementFailureStrategy = null; @@ -934,7 +936,15 @@ export class Camera extends Component { private _getInvViewProjMat(): Matrix { if (this._isInvViewProjDirty.flag) { this._isInvViewProjDirty.flag = false; - Matrix.multiply(this._entity.transform.worldMatrix, this._getInverseProjectionMatrix(), this._invViewProjMat); + const matrix = this._invViewProjMat; + if (this._isCustomViewMatrix) { + Matrix.invert(this.viewMatrix, matrix); + } else { + // Ignore scale, consistent with viewMatrix getter + const transform = this._entity.transform; + Matrix.rotationTranslation(transform.worldRotationQuaternion, transform.worldPosition, matrix); + } + matrix.multiply(this._getInverseProjectionMatrix()); } return this._invViewProjMat; } diff --git a/packages/core/src/ComponentsManager.ts b/packages/core/src/ComponentsManager.ts index e9b9a1cc0d..96924c1a60 100644 --- a/packages/core/src/ComponentsManager.ts +++ b/packages/core/src/ComponentsManager.ts @@ -36,8 +36,6 @@ export class ComponentsManager { // Render private _onUpdateRenderers = new DisorderedArray(); - // Delay dispose active/inActive Pool - private _componentsContainerPool: Component[][] = []; addCamera(camera: Camera) { camera._cameraIndex = this._activeCameras.length; @@ -270,14 +268,6 @@ export class ComponentsManager { ); } - getActiveChangedTempList(): Component[] { - return this._componentsContainerPool.length ? this._componentsContainerPool.pop() : []; - } - - putActiveChangedTempList(componentContainer: Component[]): void { - componentContainer.length = 0; - this._componentsContainerPool.push(componentContainer); - } /** * @internal diff --git a/packages/core/src/Engine.ts b/packages/core/src/Engine.ts index 55b0ea0b4c..ea6b2d3079 100644 --- a/packages/core/src/Engine.ts +++ b/packages/core/src/Engine.ts @@ -15,9 +15,8 @@ import { EngineSettings } from "./EngineSettings"; import { Entity } from "./Entity"; import { BatcherManager } from "./RenderPipeline/BatcherManager"; import { RenderContext } from "./RenderPipeline/RenderContext"; -import { RenderElement } from "./RenderPipeline/RenderElement"; import { RenderTargetPool } from "./RenderPipeline/RenderTargetPool"; -import { SubRenderElement } from "./RenderPipeline/SubRenderElement"; +import { RenderElement } from "./RenderPipeline/RenderElement"; import { Scene } from "./Scene"; import { SceneManager } from "./SceneManager"; import { RenderingStatistics } from "./asset/RenderingStatistics"; @@ -33,7 +32,8 @@ import { Shader } from "./shader/Shader"; import { ShaderMacro } from "./shader/ShaderMacro"; import { ShaderMacroCollection } from "./shader/ShaderMacroCollection"; import { ShaderPool } from "./shader/ShaderPool"; -import { ShaderProgramPool } from "./shader/ShaderProgramPool"; +import { ShaderProgramMap } from "./shader/ShaderProgramMap"; +import { ShaderProgram } from "./shader/ShaderProgram"; import { RenderState } from "./shader/state/RenderState"; import { Texture2D, TextureFormat } from "./texture"; import { UIUtils } from "./ui/UIUtils"; @@ -93,9 +93,7 @@ export class Engine extends EventDispatcher { /* @internal */ _renderElementPool = new ClearableObjectPool(RenderElement); /* @internal */ - _subRenderElementPool = new ClearableObjectPool(SubRenderElement); - /* @internal */ - _textSubRenderElementPool = new ClearableObjectPool(SubRenderElement); + _textRenderElementPool = new ClearableObjectPool(RenderElement); /* @internal */ _charRenderInfoPool = new ReturnableObjectPool(CharRenderInfo, 50); @@ -112,7 +110,7 @@ export class Engine extends EventDispatcher { /* @internal */ _renderCount: number = 0; /* @internal */ - _shaderProgramPools: ShaderProgramPool[] = []; + _shaderProgramMaps: ShaderProgramMap[] = []; /** @internal */ _fontMap: Record = {}; /** @internal */ @@ -329,9 +327,8 @@ export class Engine extends EventDispatcher { const deltaTime = time.deltaTime; this._frameInProcess = true; - this._subRenderElementPool.clear(); - this._textSubRenderElementPool.clear(); this._renderElementPool.clear(); + this._textRenderElementPool.clear(); this.xrManager?._update(); const { inputManager, _physicsInitialized: physicsInitialized } = this; @@ -541,18 +538,18 @@ export class Engine extends EventDispatcher { /** * @internal */ - _getShaderProgramPool(index: number, trackPools?: ShaderProgramPool[]): ShaderProgramPool { - const shaderProgramPools = this._shaderProgramPools; - let pool = shaderProgramPools[index]; - if (!pool) { + _getShaderProgramMap(index: number, trackMaps?: ShaderProgramMap[]): ShaderProgramMap { + const shaderProgramMaps = this._shaderProgramMaps; + let map = shaderProgramMaps[index]; + if (!map) { const length = index + 1; - if (length > shaderProgramPools.length) { - shaderProgramPools.length = length; + if (length > shaderProgramMaps.length) { + shaderProgramMaps.length = length; } - shaderProgramPools[index] = pool = new ShaderProgramPool(this); - trackPools?.push(pool); + shaderProgramMaps[index] = map = new ShaderProgramMap(this); + trackMaps?.push(map); } - return pool; + return map; } /** @@ -674,9 +671,9 @@ export class Engine extends EventDispatcher { private _onDeviceRestored(): void { this._hardwareRenderer.resetState(); this._lastRenderState = new RenderState(); - // Clear shader pools + // Clear shader program maps Shader._clear(this); - this._shaderProgramPools.length = 0; + this._shaderProgramMaps.length = 0; const { resourceManager } = this; // Restore graphic resources @@ -697,9 +694,8 @@ export class Engine extends EventDispatcher { } private _gc(): void { - this._subRenderElementPool.garbageCollection(); - this._textSubRenderElementPool.garbageCollection(); this._renderElementPool.garbageCollection(); + this._textRenderElementPool.garbageCollection(); this._renderContext.garbageCollection(); const scenes = this._sceneManager._scenes.getLoopArray(); for (let i = 0, n = scenes.length; i < n; i++) { diff --git a/packages/core/src/Entity.ts b/packages/core/src/Entity.ts index 08503f5498..35c6fac424 100644 --- a/packages/core/src/Entity.ts +++ b/packages/core/src/Entity.ts @@ -9,7 +9,7 @@ import { Script } from "./Script"; import { Transform } from "./Transform"; import { UpdateFlagManager } from "./UpdateFlagManager"; import { ReferResource } from "./asset/ReferResource"; -import { EngineObject } from "./base"; +import { EngineObject, Logger } from "./base"; import { CloneUtils } from "./clone/CloneUtils"; import { ComponentCloner } from "./clone/ComponentCloner"; import { ActiveChangeFlag } from "./enums/ActiveChangeFlag"; @@ -122,7 +122,7 @@ export class Entity extends EngineObject { private _transform: Transform; private _templateResource: ReferResource; private _parent: Entity = null; - private _activeChangedComponents: Component[]; + private _isActiveChanging: boolean = false; private _modifyFlagManager: UpdateFlagManager; /** @@ -212,16 +212,14 @@ export class Entity extends EngineObject { } set siblingIndex(value: number) { - if (this._siblingIndex === -1) { - throw `The entity ${this.name} is not in the hierarchy`; - } - if (this._isRoot) { this._setSiblingIndex(this._scene._rootEntities, value); - } else { + } else if (this._parent) { const parent = this._parent; this._setSiblingIndex(parent._children, value); parent._dispatchModify(EntityModifyFlags.Child, parent); + } else { + Logger.warn(`The entity ${this.name} is not in the hierarchy`); } } @@ -403,6 +401,11 @@ export class Entity extends EngineObject { for (let i = children.length - 1; i >= 0; i--) { const child = children[i]; child._parent = null; + child._siblingIndex = -1; + // Dispatch `Child` to the old parent before `_processInActive` (which unregisters + // UI listeners via `cleanRootCanvas`), so subscribers such as UICanvas can react + // to the hierarchy change while still attached. + this._dispatchModify(EntityModifyFlags.Child, this); let activeChangeFlag = ActiveChangeFlag.None; child._isActiveInHierarchy && (activeChangeFlag |= ActiveChangeFlag.Hierarchy); @@ -410,6 +413,8 @@ export class Entity extends EngineObject { activeChangeFlag && child._processInActive(activeChangeFlag); Entity._traverseSetOwnerScene(child, null); // Must after child._processInActive(). + + child._setParentChange(); } children.length = 0; } @@ -565,24 +570,24 @@ export class Entity extends EngineObject { * @internal */ _processActive(activeChangeFlag: ActiveChangeFlag): void { - if (this._activeChangedComponents) { + if (this._isActiveChanging) { throw "Note: can't set the 'main inActive entity' active in hierarchy, if the operation is in main inActive entity or it's children script's onDisable Event."; } - this._activeChangedComponents = this._scene._componentsManager.getActiveChangedTempList(); - this._setActiveInHierarchy(this._activeChangedComponents, activeChangeFlag); - this._setActiveComponents(true, activeChangeFlag); + this._isActiveChanging = true; + this._setActiveInHierarchy(activeChangeFlag); + this._isActiveChanging = false; } /** * @internal */ _processInActive(activeChangeFlag: ActiveChangeFlag): void { - if (this._activeChangedComponents) { + if (this._isActiveChanging) { throw "Note: can't set the 'main active entity' inActive in hierarchy, if the operation is in main active entity or it's children script's onEnable Event."; } - this._activeChangedComponents = this._scene._componentsManager.getActiveChangedTempList(); - this._setInActiveInHierarchy(this._activeChangedComponents, activeChangeFlag); - this._setActiveComponents(false, activeChangeFlag); + this._isActiveChanging = true; + this._setInActiveInHierarchy(activeChangeFlag); + this._isActiveChanging = false; } /** @@ -690,42 +695,33 @@ export class Entity extends EngineObject { } } - private _setActiveComponents(isActive: boolean, activeChangeFlag: ActiveChangeFlag): void { - const activeChangedComponents = this._activeChangedComponents; - for (let i = 0, length = activeChangedComponents.length; i < length; ++i) { - activeChangedComponents[i]._setActive(isActive, activeChangeFlag); - } - this._scene._componentsManager.putActiveChangedTempList(activeChangedComponents); - this._activeChangedComponents = null; - } - - private _setActiveInHierarchy(activeChangedComponents: Component[], activeChangeFlag: ActiveChangeFlag): void { + private _setActiveInHierarchy(activeChangeFlag: ActiveChangeFlag): void { activeChangeFlag & ActiveChangeFlag.Hierarchy && (this._isActiveInHierarchy = true); activeChangeFlag & ActiveChangeFlag.Scene && (this._isActiveInScene = true); const components = this._components; for (let i = 0, n = components.length; i < n; i++) { const component = components[i]; - (component.enabled || !component._awoken) && activeChangedComponents.push(component); + (component.enabled || !component._awoken) && component._setActive(true, activeChangeFlag); } const children = this._children; - for (let i = 0, n = children.length; i < n; i++) { + for (let i = children.length - 1; i >= 0; i--) { const child = children[i]; - child.isActive && child._setActiveInHierarchy(activeChangedComponents, activeChangeFlag); + child.isActive && child._setActiveInHierarchy(activeChangeFlag); } } - private _setInActiveInHierarchy(activeChangedComponents: Component[], activeChangeFlag: ActiveChangeFlag): void { + private _setInActiveInHierarchy(activeChangeFlag: ActiveChangeFlag): void { activeChangeFlag & ActiveChangeFlag.Hierarchy && (this._isActiveInHierarchy = false); activeChangeFlag & ActiveChangeFlag.Scene && (this._isActiveInScene = false); const components = this._components; for (let i = 0, n = components.length; i < n; i++) { const component = components[i]; - component.enabled && activeChangedComponents.push(component); + component.enabled && component._setActive(false, activeChangeFlag); } const children = this._children; - for (let i = 0, n = children.length; i < n; i++) { + for (let i = children.length - 1; i >= 0; i--) { const child = children[i]; - child.isActive && child._setInActiveInHierarchy(activeChangedComponents, activeChangeFlag); + child.isActive && child._setInActiveInHierarchy(activeChangeFlag); } } diff --git a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts index dee2231a0a..28049597dd 100644 --- a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts +++ b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts @@ -10,7 +10,7 @@ import { ScalableAmbientObscurancePass } from "../lighting/ambientOcclusion/Scal import { FinalPass } from "../postProcess"; import { Shader } from "../shader/Shader"; import { ShaderMacroCollection } from "../shader/ShaderMacroCollection"; -import { ShaderPass } from "../shader/ShaderPass"; +import { SubShader } from "../shader/SubShader"; import { RenderQueueType } from "../shader/enums/RenderQueueType"; import { RenderState } from "../shader/state/RenderState"; import { CascadedShadowCasterPass } from "../shadow/CascadedShadowCasterPass"; @@ -30,7 +30,6 @@ import { OpaqueTexturePass } from "./OpaqueTexturePass"; import { PipelineUtils } from "./PipelineUtils"; import { ContextRendererUpdateFlag, RenderContext } from "./RenderContext"; import { RenderElement } from "./RenderElement"; -import { SubRenderElement } from "./SubRenderElement"; import { PipelineStage } from "./enums/PipelineStage"; /** * Basic render pipeline. @@ -132,15 +131,17 @@ export class BasicRenderPipeline { this._cascadedShadowCasterPass.onRender(context); } - const batcherManager = engine._batcherManager; cullingResults.reset(); // Depth use camera's view and projection matrix this._cullingResults.setRenderUpdateFlagTrue(ContextRendererUpdateFlag.viewProjectionMatrix); context.applyVirtualCamera(camera._virtualCamera, depthPassEnabled); - this._prepareRender(context); + this._prepareWorldRender(context); - cullingResults.sortBatch(batcherManager); + const batcherManager = engine._batcherManager; + cullingResults.sort(); + this._prepareUIRender(context); + cullingResults.batch(batcherManager); batcherManager.uploadBuffer(); if (depthPassEnabled) { @@ -369,58 +370,53 @@ export class BasicRenderPipeline { * @param renderElement - Render element */ pushRenderElement(context: RenderContext, renderElement: RenderElement): void { - renderElement.renderQueueFlags = RenderQueueFlags.None; - const subRenderElements = renderElement.subRenderElements; - for (let i = 0, n = subRenderElements.length; i < n; ++i) { - const subRenderElement = subRenderElements[i]; - const { material } = subRenderElement; - const { renderStates } = material; - const materialSubShader = material.shader.subShaders[0]; - const replacementShader = context.replacementShader; - if (replacementShader) { - const replacementSubShaders = replacementShader.subShaders; - const { replacementTag } = context; - if (replacementTag) { - let replacementSuccess = false; - for (let j = 0, m = replacementSubShaders.length; j < m; j++) { - const subShader = replacementSubShaders[j]; - if (subShader.getTagValue(replacementTag) === materialSubShader.getTagValue(replacementTag)) { - this.pushRenderElementByType(renderElement, subRenderElement, subShader.passes, renderStates); - replacementSuccess = true; - } + const { material } = renderElement; + const { renderStates } = material; + const materialSubShader = material.shader.subShaders[0]; + const replacementShader = context.replacementShader; + if (replacementShader) { + const replacementSubShaders = replacementShader.subShaders; + const { replacementTag } = context; + if (replacementTag) { + let replacementSuccess = false; + for (let j = 0, m = replacementSubShaders.length; j < m; j++) { + const subShader = replacementSubShaders[j]; + if (subShader.getTagValue(replacementTag) === materialSubShader.getTagValue(replacementTag)) { + this._pushRenderElementByType(renderElement, subShader, renderStates); + replacementSuccess = true; } + } - if ( - !replacementSuccess && - context.replacementFailureStrategy === ReplacementFailureStrategy.KeepOriginalShader - ) { - this.pushRenderElementByType(renderElement, subRenderElement, materialSubShader.passes, renderStates); - } - } else { - this.pushRenderElementByType(renderElement, subRenderElement, replacementSubShaders[0].passes, renderStates); + if ( + !replacementSuccess && + context.replacementFailureStrategy === ReplacementFailureStrategy.KeepOriginalShader + ) { + this._pushRenderElementByType(renderElement, materialSubShader, renderStates); } } else { - this.pushRenderElementByType(renderElement, subRenderElement, materialSubShader.passes, renderStates); + this._pushRenderElementByType(renderElement, replacementSubShaders[0], renderStates); } + } else { + this._pushRenderElementByType(renderElement, materialSubShader, renderStates); } } - private pushRenderElementByType( + private _pushRenderElementByType( renderElement: RenderElement, - subRenderElement: SubRenderElement, - shaderPasses: ReadonlyArray, + subShader: SubShader, renderStates: ReadonlyArray ): void { + const shaderPasses = subShader.passes; const cullingResults = this._cullingResults; + let pushedQueueFlags = RenderQueueFlags.None; for (let i = 0, n = shaderPasses.length; i < n; i++) { - // Get render queue type let renderQueueType: RenderQueueType; const shaderPass = shaderPasses[i]; const renderState = shaderPass._renderState; if (renderState) { renderQueueType = renderState._getRenderQueueByShaderData( shaderPass._renderStateDataMap, - subRenderElement.material.shaderData + renderElement.material.shaderData ); } else { renderQueueType = renderStates[i].renderQueueType; @@ -428,10 +424,9 @@ export class BasicRenderPipeline { const flag = 1 << renderQueueType; - subRenderElement.shaderPasses = shaderPasses; - subRenderElement.renderQueueFlags |= flag; + renderElement.subShader = subShader; - if (renderElement.renderQueueFlags & flag) { + if (pushedQueueFlags & flag) { continue; } @@ -446,7 +441,7 @@ export class BasicRenderPipeline { cullingResults.transparentQueue.pushRenderElement(renderElement); break; } - renderElement.renderQueueFlags |= flag; + pushedQueueFlags |= flag; } } @@ -482,10 +477,10 @@ export class BasicRenderPipeline { rhi.drawPrimitive(mesh._primitive, mesh.subMesh, program); } - private _prepareRender(context: RenderContext): void { + private _prepareWorldRender(context: RenderContext): void { const camera = context.camera; const { engine, enableFrustumCulling, cullingMask, _frustum: frustum } = camera; - const { _renderers: renderers, _canvases: canvases } = camera.scene._componentsManager; + const renderers = camera.scene._componentsManager._renderers; const rendererElements = renderers._elements; for (let i = renderers.length - 1; i >= 0; --i) { @@ -504,7 +499,12 @@ export class BasicRenderPipeline { renderer._prepareRender(context); renderer._renderFrameCount = engine.time.frameCount; } + } + private _prepareUIRender(context: RenderContext): void { + const camera = context.camera; + const { cullingMask } = camera; + const canvases = camera.scene._componentsManager._canvases; const canvasesElements = canvases._elements; for (let i = canvases.length - 1; i >= 0; i--) { const canvas = canvasesElements[i]; @@ -516,7 +516,10 @@ export class BasicRenderPipeline { continue; } canvas._prepareRender(context); - this.pushRenderElement(context, canvas._renderElement); + const canvasElements = canvas._renderElements; + for (let j = 0, m = canvasElements.length; j < m; j++) { + this.pushRenderElement(context, canvasElements[j]); + } } } } diff --git a/packages/core/src/RenderPipeline/BatchUtils.ts b/packages/core/src/RenderPipeline/BatchUtils.ts deleted file mode 100644 index 387c951f93..0000000000 --- a/packages/core/src/RenderPipeline/BatchUtils.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { SpriteMask, SpriteMaskInteraction, SpriteRenderer } from "../2d"; -import { ShaderTagKey } from "../shader"; -import { SubRenderElement } from "./SubRenderElement"; - -/** - * @internal - */ -export class BatchUtils { - protected static _disableBatchTag: ShaderTagKey = ShaderTagKey.getByName("spriteDisableBatching"); - - static canBatchSprite(elementA: SubRenderElement, elementB: SubRenderElement): boolean { - if (elementB.shaderPasses[0].getTagValue(BatchUtils._disableBatchTag) === true) { - return false; - } - if (elementA.subChunk.chunk !== elementB.subChunk.chunk) { - return false; - } - - const rendererA = elementA.component; - const rendererB = elementB.component; - const maskInteractionA = rendererA.maskInteraction; - - // Compare mask, texture and material - return ( - maskInteractionA === rendererB.maskInteraction && - (maskInteractionA === SpriteMaskInteraction.None || rendererA.maskLayer === rendererB.maskLayer) && - elementA.texture === elementB.texture && - elementA.material === elementB.material - ); - } - - static canBatchSpriteMask(elementA: SubRenderElement, elementB: SubRenderElement): boolean { - if (elementA.subChunk.chunk !== elementB.subChunk.chunk) { - return false; - } - - const alphaCutoffProperty = SpriteMask._alphaCutoffProperty; - - // Compare renderer property - return ( - elementA.texture === elementB.texture && - (elementA.component).shaderData.getFloat(alphaCutoffProperty) === - (elementB.component).shaderData.getFloat(alphaCutoffProperty) - ); - } - - static batchFor2D(elementA: SubRenderElement, elementB?: SubRenderElement): void { - const subChunk = elementB ? elementB.subChunk : elementA.subChunk; - const { chunk, indices: subChunkIndices } = subChunk; - - const length = subChunkIndices.length; - let startIndex = chunk.updateIndexLength; - if (elementB) { - elementA.subChunk.subMesh.count += length; - } else { - // Reset subMesh - const subMesh = subChunk.subMesh; - subMesh.start = startIndex; - subMesh.count = length; - } - - const { start, size } = subChunk.vertexArea; - const vertexOffset = start / 9; - const indices = chunk.indices; - for (let i = 0; i < length; ++i) { - indices[startIndex++] = vertexOffset + subChunkIndices[i]; - } - chunk.updateIndexLength += length; - chunk.updateVertexStart = Math.min(chunk.updateVertexStart, start); - chunk.updateVertexEnd = Math.max(chunk.updateVertexEnd, start + size); - } -} diff --git a/packages/core/src/RenderPipeline/BatcherManager.ts b/packages/core/src/RenderPipeline/BatcherManager.ts index 702a4a01e8..05ec1b7e89 100644 --- a/packages/core/src/RenderPipeline/BatcherManager.ts +++ b/packages/core/src/RenderPipeline/BatcherManager.ts @@ -1,8 +1,9 @@ import { Engine } from "../Engine"; import { Renderer } from "../Renderer"; +import { InstanceBuffer } from "./InstanceBuffer"; import { PrimitiveChunkManager } from "./PrimitiveChunkManager"; import { RenderQueue } from "./RenderQueue"; -import { SubRenderElement } from "./SubRenderElement"; +import { RenderElement } from "./RenderElement"; /** * @internal @@ -11,9 +12,14 @@ export class BatcherManager { private _primitiveChunkManager2D: PrimitiveChunkManager; private _primitiveChunkManagerMask: PrimitiveChunkManager; private _primitiveChunkManagerUI: PrimitiveChunkManager; + private _instanceBuffer: InstanceBuffer; constructor(public engine: Engine) {} + get instanceBuffer(): InstanceBuffer { + return (this._instanceBuffer ||= new InstanceBuffer(this.engine)); + } + get primitiveChunkManager2D(): PrimitiveChunkManager { return (this._primitiveChunkManager2D ||= new PrimitiveChunkManager(this.engine)); } @@ -39,47 +45,40 @@ export class BatcherManager { this._primitiveChunkManagerUI.destroy(); this._primitiveChunkManagerUI = null; } + if (this._instanceBuffer) { + this._instanceBuffer.destroy(); + this._instanceBuffer = null; + } } batch(renderQueue: RenderQueue): void { - const { elements, batchedSubElements, renderQueueType } = renderQueue; - let preSubElement: SubRenderElement; + const { elements, batchedElements } = renderQueue; + + let preElement: RenderElement; let preRenderer: Renderer; let preConstructor: Function; for (let i = 0, n = elements.length; i < n; ++i) { - const subElements = elements[i].subRenderElements; - for (let j = 0, m = subElements.length; j < m; ++j) { - const subElement = subElements[j]; - - // Some sub render elements may not belong to the current render queue - if (!(subElement.renderQueueFlags & (1 << renderQueueType))) { - continue; - } - - const renderer = subElement.component; - const constructor = renderer.constructor; - if (preSubElement) { - if (preConstructor === constructor && preRenderer._canBatch(preSubElement, subElement)) { - preRenderer._batch(preSubElement, subElement); - preSubElement.batched = true; - } else { - batchedSubElements.push(preSubElement); - preSubElement = subElement; - preRenderer = renderer; - preConstructor = constructor; - renderer._batch(subElement); - subElement.batched = false; - } + const curElement = elements[i]; + const renderer = curElement.component; + const constructor = renderer.constructor; + if (preElement) { + if (preConstructor === constructor && preRenderer._canBatch(preElement, curElement)) { + preRenderer._batch(preElement, curElement); } else { - preSubElement = subElement; + batchedElements.push(preElement); + preElement = curElement; preRenderer = renderer; preConstructor = constructor; - renderer._batch(subElement); - subElement.batched = false; + renderer._batch(null, curElement); } + } else { + preElement = curElement; + preRenderer = renderer; + preConstructor = constructor; + renderer._batch(null, curElement); } } - preSubElement && batchedSubElements.push(preSubElement); + preElement && batchedElements.push(preElement); } uploadBuffer() { diff --git a/packages/core/src/RenderPipeline/CullingResults.ts b/packages/core/src/RenderPipeline/CullingResults.ts index 673e0694d3..6ff5c298a7 100644 --- a/packages/core/src/RenderPipeline/CullingResults.ts +++ b/packages/core/src/RenderPipeline/CullingResults.ts @@ -30,6 +30,18 @@ export class CullingResults { this.transparentQueue.sortBatch(RenderQueue.compareForTransparent, batcherManager); } + sort() { + this.opaqueQueue.sort(RenderQueue.compareForOpaque); + this.alphaTestQueue.sort(RenderQueue.compareForOpaque); + this.transparentQueue.sort(RenderQueue.compareForTransparent); + } + + batch(batcherManager: BatcherManager): void { + this.opaqueQueue.batch(batcherManager); + this.alphaTestQueue.batch(batcherManager); + this.transparentQueue.batch(batcherManager); + } + setRenderUpdateFlagTrue(rendererUpdateFlag: ContextRendererUpdateFlag): void { this.opaqueQueue.rendererUpdateFlag |= rendererUpdateFlag; this.transparentQueue.rendererUpdateFlag |= rendererUpdateFlag; diff --git a/packages/core/src/RenderPipeline/InstanceBuffer.ts b/packages/core/src/RenderPipeline/InstanceBuffer.ts new file mode 100644 index 0000000000..f62253f78c --- /dev/null +++ b/packages/core/src/RenderPipeline/InstanceBuffer.ts @@ -0,0 +1,86 @@ +import { Engine } from "../Engine"; +import { Buffer } from "../graphic/Buffer"; +import { BufferBindFlag } from "../graphic/enums/BufferBindFlag"; +import { BufferUsage } from "../graphic/enums/BufferUsage"; +import { SetDataOptions } from "../graphic/enums/SetDataOptions"; +import { Renderer } from "../Renderer"; +import { ShaderMacro } from "../shader/ShaderMacro"; +import { InstanceBufferLayout } from "../shaderlib/ShaderFactory"; + +/** + * @internal + * Manages a UBO for GPU instancing, packing per-instance renderer data (ModelMat, Layer, etc.). + */ +export class InstanceBuffer { + static gpuInstanceMacro = ShaderMacro.getByName("RENDERER_GPU_INSTANCE"); + + buffer: Buffer; + + private _engine: Engine; + private _layout: InstanceBufferLayout; + private _data: ArrayBuffer; + private _floatView: Float32Array; + private _intView: Int32Array; + + constructor(engine: Engine) { + this._engine = engine; + } + + /** + * Set UBO layout and allocate buffer if needed. + */ + setLayout(layout: InstanceBufferLayout): void { + this._layout = layout; + const totalBytes = layout.instanceMaxCount * layout.structSize; + // Only reallocate when buffer is too small + if (!this.buffer || totalBytes > this.buffer.byteLength) { + this._data = new ArrayBuffer(totalBytes); + this._floatView = new Float32Array(this._data); + this._intView = new Int32Array(this._data); + this.buffer?.destroy(); + this.buffer = new Buffer(this._engine, BufferBindFlag.ConstantBuffer, totalBytes, BufferUsage.Dynamic); + } + } + + /** + * Pack renderer data into UBO and upload to GPU. + */ + upload(renderers: Renderer[], start: number, count: number): void { + const { instanceFields, structSize } = this._layout; + const elementsPerInstance = structSize / 4; + const { _floatView: floatView, _intView: intView } = this; + const modelMatId = Renderer._worldMatrixProperty._uniqueId; + + for (let i = 0; i < count; i++) { + const renderer = renderers[start + i]; + const propertyValueMap = renderer.shaderData._propertyValueMap; + const baseOffset = i * elementsPerInstance; + + for (let j = 0, n = instanceFields.length; j < n; j++) { + const field = instanceFields[j]; + const fieldOffset = baseOffset + field.offsetInElements; + const propertyId = field.property._uniqueId; + + if (propertyId === modelMatId) { + // Instancing skips _updateTransformShaderData, so worldMatrix is not in propertyValueMap + // Must read from transform getter to trigger lazy update + field.pack(floatView, fieldOffset, renderer.entity.transform.worldMatrix); + } else { + const value = propertyValueMap[propertyId]; + if (value != null) { + field.pack(field.useIntView ? intView : floatView, fieldOffset, value); + } + } + } + } + + this.buffer.setData(floatView, 0, 0, count * elementsPerInstance, SetDataOptions.Discard); + } + + destroy(): void { + this.buffer?.destroy(); + this._data = null; + this._floatView = null; + this._intView = null; + } +} diff --git a/packages/core/src/RenderPipeline/RenderElement.ts b/packages/core/src/RenderPipeline/RenderElement.ts index 582e72f47d..89a67b8fd9 100644 --- a/packages/core/src/RenderPipeline/RenderElement.ts +++ b/packages/core/src/RenderPipeline/RenderElement.ts @@ -1,24 +1,53 @@ +import { Renderer } from "../Renderer"; +import { Primitive, SubMesh } from "../graphic"; +import { Material } from "../material"; +import { ShaderData, SubShader } from "../shader"; +import { Texture2D } from "../texture"; import { IPoolElement } from "../utils/ObjectPool"; -import { RenderQueueFlags } from "./BasicRenderPipeline"; -import { SubRenderElement } from "./SubRenderElement"; +import { SubPrimitiveChunk } from "./SubPrimitiveChunk"; export class RenderElement implements IPoolElement { priority: number; distanceForSort: number; - subRenderElements = Array(); - renderQueueFlags: RenderQueueFlags; + component: Renderer; + primitive: Primitive; + material: Material; + subPrimitive: SubMesh; + subShader: SubShader; + shaderData?: ShaderData; + instancedRenderers: Renderer[] = []; - set(priority: number, distanceForSort: number): void { - this.priority = priority; - this.distanceForSort = distanceForSort; - this.subRenderElements.length = 0; - } + // @todo: maybe should remove later + texture?: Texture2D; + subChunk?: SubPrimitiveChunk; - addSubRenderElement(element: SubRenderElement): void { - this.subRenderElements.push(element); + set( + component: Renderer, + material: Material, + primitive: Primitive, + subPrimitive: SubMesh, + texture?: Texture2D, + subChunk?: SubPrimitiveChunk + ): void { + this.component = component; + this.material = material; + this.primitive = primitive; + this.subPrimitive = subPrimitive; + this.texture = texture; + this.subChunk = subChunk; + this.instancedRenderers.length = 0; } dispose(): void { - this.subRenderElements.length = 0; + this.component = null; + this.material = null; + this.primitive = null; + this.subPrimitive = null; + this.subShader = null; + this.shaderData && (this.shaderData = null); + this.instancedRenderers = null; + + this.texture && (this.texture = null); + this.subChunk && (this.subChunk = null); } } diff --git a/packages/core/src/RenderPipeline/RenderQueue.ts b/packages/core/src/RenderPipeline/RenderQueue.ts index 3558679996..f9ee9fb0a4 100644 --- a/packages/core/src/RenderPipeline/RenderQueue.ts +++ b/packages/core/src/RenderPipeline/RenderQueue.ts @@ -3,10 +3,11 @@ import { BasicResources, RenderStateElementMap } from "../BasicResources"; import { Utils } from "../Utils"; import { RenderQueueType, Shader } from "../shader"; import { ShaderMacroCollection } from "../shader/ShaderMacroCollection"; +import { ConstantBufferBindingPoint } from "../shader/enums/ConstantBufferBindingPoint"; import { BatcherManager } from "./BatcherManager"; +import { InstanceBuffer } from "./InstanceBuffer"; import { ContextRendererUpdateFlag, RenderContext } from "./RenderContext"; import { RenderElement } from "./RenderElement"; -import { SubRenderElement } from "./SubRenderElement"; import { RenderQueueMaskType } from "./enums/RenderQueueMaskType"; /** @@ -14,7 +15,11 @@ import { RenderQueueMaskType } from "./enums/RenderQueueMaskType"; */ export class RenderQueue { static compareForOpaque(a: RenderElement, b: RenderElement): number { - return a.priority - b.priority || a.distanceForSort - b.distanceForSort; + return ( + a.priority - b.priority || + a.material.instanceId - b.material.instanceId || + a.primitive.instanceId - b.primitive.instanceId + ); } static compareForTransparent(a: RenderElement, b: RenderElement): number { @@ -22,7 +27,7 @@ export class RenderQueue { } readonly elements = new Array(); - readonly batchedSubElements = new Array(); + readonly batchedElements = new Array(); rendererUpdateFlag = ContextRendererUpdateFlag.None; constructor(public renderQueueType: RenderQueueType) {} @@ -36,6 +41,10 @@ export class RenderQueue { this.batch(batcherManager); } + sort(compareFunc: Function): void { + Utils._quickSort(this.elements, 0, this.elements.length, compareFunc); + } + batch(batcherManager: BatcherManager): void { batcherManager.batch(this); } @@ -45,8 +54,8 @@ export class RenderQueue { pipelineStageTagValue: string, maskType: RenderQueueMaskType = RenderQueueMaskType.No ): void { - const batchedSubElements = this.batchedSubElements; - const length = batchedSubElements.length; + const batchedElements = this.batchedElements; + const length = batchedElements.length; if (length === 0) { return; } @@ -57,34 +66,33 @@ export class RenderQueue { const rhi = engine._hardwareRenderer; const pipelineStageKey = RenderContext.pipelineStageKey; const renderQueueType = this.renderQueueType; + const needMaskType = maskType !== RenderQueueMaskType.No; for (let i = 0; i < length; i++) { - const subElement = batchedSubElements[i]; - const { component: renderer, batched, material } = subElement; - - // @todo: Can optimize update view projection matrix updated - if ( - this.rendererUpdateFlag & ContextRendererUpdateFlag.WorldViewMatrix || - renderer._batchedTransformShaderData != batched - ) { - // Update world matrix and view matrix and model matrix - renderer._updateTransformShaderData(context, false, batched); - renderer._batchedTransformShaderData = batched; - } else if (this.rendererUpdateFlag & ContextRendererUpdateFlag.ProjectionMatrix) { - // Only projection matrix need updated - renderer._updateTransformShaderData(context, true, batched); + const curElement = batchedElements[i]; + const { component, material } = curElement; + const isInstanced = curElement.instancedRenderers.length > 0; + + // Update transform shader data + // Instancing packs per-renderer transforms into the instance UBO at draw time, so skip here + if (!isInstanced) { + if (this.rendererUpdateFlag & ContextRendererUpdateFlag.WorldViewMatrix) { + component._updateTransformShaderData(context, false); + } else if (this.rendererUpdateFlag & ContextRendererUpdateFlag.ProjectionMatrix) { + component._updateTransformShaderData(context, true); + } } - const maskInteraction = renderer._maskInteraction; + // Resolve mask render states + const maskInteraction = component._maskInteraction; const needMaskInteraction = maskInteraction !== SpriteMaskInteraction.None; - const needMaskType = maskType !== RenderQueueMaskType.No; let customStates: RenderStateElementMap = null; if (needMaskType) { customStates = BasicResources.getMaskTypeRenderStates(maskType); } else { if (needMaskInteraction) { - maskManager.drawMask(context, pipelineStageTagValue, subElement.component._maskLayer); + maskManager.drawMask(context, pipelineStageTagValue, component._maskLayer); customStates = BasicResources.getMaskInteractionRenderStates(maskInteraction); } else { maskManager.isReadStencil(material) && maskManager.clearMask(context, pipelineStageTagValue); @@ -92,21 +100,27 @@ export class RenderQueue { maskManager.isStencilWritten(material) && (maskManager.hasStencilWritten = true); } - const compileMacros = Shader._compileMacros; - const { primitive, shaderPasses, shaderData: renderElementShaderData } = subElement; - const { shaderData: rendererData, instanceId: rendererId } = renderer; + const { shaderData: renderElementShaderData } = curElement; + const shaderPasses = curElement.subShader.passes; + const { shaderData: rendererData, instanceId: rendererId } = component; const { shaderData: materialData, instanceId: materialId, renderStates } = material; - // Union render global macro and material self macro - ShaderMacroCollection.unionCollection(renderer._globalShaderMacro, materialData._macroCollection, compileMacros); + // Build compile macros + const compileMacros = Shader._compileMacros; + ShaderMacroCollection.unionCollection(component._globalShaderMacro, materialData._macroCollection, compileMacros); ShaderMacroCollection.unionCollection(compileMacros, engine._macroCollection, compileMacros); + if (isInstanced) { + compileMacros.enable(InstanceBuffer.gpuInstanceMacro); + } + for (let j = 0, m = shaderPasses.length; j < m; j++) { const shaderPass = shaderPasses[j]; if (shaderPass.getTagValue(pipelineStageKey) !== pipelineStageTagValue) { continue; } + // Pick render state and filter by queue type let renderState = shaderPass._renderState; if (needMaskType) { // Mask don't care render queue type @@ -134,18 +148,23 @@ export class RenderQueue { const switchProgram = program.bind(); const switchRenderCount = renderCount !== program._uploadRenderCount; + // Upload uniforms (cache-aware per block) if (switchRenderCount) { program.groupingOtherUniformBlock(); program.uploadAll(program.sceneUniformBlock, sceneData); program.uploadAll(program.cameraUniformBlock, cameraData); - program.uploadAll(program.rendererUniformBlock, rendererData); + if (isInstanced) { + program._uploadRendererId = -1; + } else { + program.uploadAll(program.rendererUniformBlock, rendererData); + program._uploadRendererId = rendererId; + } program.uploadAll(program.materialUniformBlock, materialData); renderElementShaderData && program.uploadAll(program.renderElementUniformBlock, renderElementShaderData); - // UnGroup textures should upload default value, texture uint maybe change by logic of texture bind. + // UnGroup textures should upload default value, texture uint maybe change by logic of texture bind program.uploadUnGroupTextures(); program._uploadSceneId = sceneId; program._uploadCameraId = cameraId; - program._uploadRendererId = rendererId; program._uploadMaterialId = materialId; program._uploadRenderCount = renderCount; } else { @@ -163,11 +182,13 @@ export class RenderQueue { program.uploadTextures(program.cameraUniformBlock, cameraData); } - if (program._uploadRendererId !== rendererId) { - program.uploadAll(program.rendererUniformBlock, rendererData); - program._uploadRendererId = rendererId; - } else if (switchProgram) { - program.uploadTextures(program.rendererUniformBlock, rendererData); + if (!isInstanced) { + if (program._uploadRendererId !== rendererId) { + program.uploadAll(program.rendererUniformBlock, rendererData); + program._uploadRendererId = rendererId; + } else if (switchProgram) { + program.uploadTextures(program.rendererUniformBlock, rendererData); + } } if (program._uploadMaterialId !== materialId) { @@ -179,20 +200,41 @@ export class RenderQueue { renderElementShaderData && program.uploadAll(program.renderElementUniformBlock, renderElementShaderData); - // We only consider switchProgram case, because UnGroup texture's value is always default. + // We only consider switchProgram case, because UnGroup texture's value is always default if (switchProgram) { program.uploadUnGroupTextures(); } } + // Apply render state renderState._applyStates( engine, - renderer._isFrontFaceInvert(), + component._isFrontFaceInvert(), shaderPass._renderStateDataMap, material.shaderData, customStates ); - rhi.drawPrimitive(primitive, subElement.subPrimitive, program); + + // Draw + const layout = program._instanceLayout; + if (isInstanced && layout) { + const { primitive, subPrimitive, instancedRenderers } = curElement; + const totalCount = instancedRenderers.length; + const maxCount = layout.instanceMaxCount; + const instanceBuffer = engine._batcherManager.instanceBuffer; + + instanceBuffer.setLayout(layout); + rhi.bindUniformBufferBase(ConstantBufferBindingPoint.RendererInstance, instanceBuffer.buffer._platformBuffer); + for (let start = 0; start < totalCount; start += maxCount) { + const count = Math.min(maxCount, totalCount - start); + instanceBuffer.upload(instancedRenderers, start, count); + primitive.instanceCount = count; + rhi.drawPrimitive(primitive, subPrimitive, program); + } + primitive.instanceCount = 0; + } else { + rhi.drawPrimitive(curElement.primitive, curElement.subPrimitive, program); + } } } @@ -201,7 +243,7 @@ export class RenderQueue { clear(): void { this.elements.length = 0; - this.batchedSubElements.length = 0; + this.batchedElements.length = 0; } destroy(): void {} diff --git a/packages/core/src/RenderPipeline/SubRenderElement.ts b/packages/core/src/RenderPipeline/SubRenderElement.ts deleted file mode 100644 index f8c86c114d..0000000000 --- a/packages/core/src/RenderPipeline/SubRenderElement.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Renderer } from "../Renderer"; -import { Primitive, SubMesh } from "../graphic"; -import { Material } from "../material"; -import { ShaderData, ShaderPass } from "../shader"; -import { Texture2D } from "../texture"; -import { IPoolElement } from "../utils/ObjectPool"; -import { RenderQueueFlags } from "./BasicRenderPipeline"; -import { SubPrimitiveChunk } from "./SubPrimitiveChunk"; - -export class SubRenderElement implements IPoolElement { - component: Renderer; - primitive: Primitive; - material: Material; - subPrimitive: SubMesh; - shaderPasses: ReadonlyArray; - shaderData?: ShaderData; - batched: boolean; - renderQueueFlags: RenderQueueFlags; - - // @todo: maybe should remove later - texture?: Texture2D; - subChunk?: SubPrimitiveChunk; - - set( - component: Renderer, - material: Material, - primitive: Primitive, - subPrimitive: SubMesh, - texture?: Texture2D, - subChunk?: SubPrimitiveChunk - ): void { - this.component = component; - this.material = material; - this.primitive = primitive; - this.subPrimitive = subPrimitive; - this.texture = texture; - this.subChunk = subChunk; - } - - dispose(): void { - this.component = null; - this.material = null; - this.primitive = null; - this.subPrimitive = null; - this.shaderPasses = null; - this.shaderData && (this.shaderData = null); - - this.texture && (this.texture = null); - this.subChunk && (this.subChunk = null); - } -} diff --git a/packages/core/src/RenderPipeline/VertexMergeBatcher.ts b/packages/core/src/RenderPipeline/VertexMergeBatcher.ts new file mode 100644 index 0000000000..c337ec21eb --- /dev/null +++ b/packages/core/src/RenderPipeline/VertexMergeBatcher.ts @@ -0,0 +1,67 @@ +import { SpriteMask, SpriteMaskInteraction, SpriteRenderer } from "../2d"; +import { ShaderTagKey } from "../shader"; +import { RenderElement } from "./RenderElement"; + +/** + * @internal + */ +export class VertexMergeBatcher { + protected static _disableBatchTag: ShaderTagKey = ShaderTagKey.getByName("spriteDisableBatching"); + + static canBatchSprite(preElement: RenderElement, curElement: RenderElement): boolean { + const preRenderer = preElement.component; + const renderer = curElement.component; + const maskInteraction = preRenderer.maskInteraction; + + // Order: cheap reference checks → mask state → tag lookup (rare opt-out) + return ( + preElement.subChunk.chunk === curElement.subChunk.chunk && + preElement.texture === curElement.texture && + preElement.material === curElement.material && + maskInteraction === renderer.maskInteraction && + (maskInteraction === SpriteMaskInteraction.None || preRenderer.maskLayer === renderer.maskLayer) && + curElement.subShader.passes[0].getTagValue(VertexMergeBatcher._disableBatchTag) !== true + ); + } + + static canBatchSpriteMask(preElement: RenderElement, curElement: RenderElement): boolean { + if (preElement.subChunk.chunk !== curElement.subChunk.chunk) { + return false; + } + + const alphaCutoffProperty = SpriteMask._alphaCutoffProperty; + + // Compare renderer property + return ( + preElement.texture === curElement.texture && + (preElement.component).shaderData.getFloat(alphaCutoffProperty) === + (curElement.component).shaderData.getFloat(alphaCutoffProperty) + ); + } + + static batch(preElement: RenderElement | null, curElement: RenderElement): void { + const subChunk = curElement.subChunk; + const { chunk, indices: subChunkIndices } = subChunk; + + const length = subChunkIndices.length; + let startIndex = chunk.updateIndexLength; + if (preElement) { + preElement.subChunk.subMesh.count += length; + } else { + // Reset subMesh + const subMesh = subChunk.subMesh; + subMesh.start = startIndex; + subMesh.count = length; + } + + const { start, size } = subChunk.vertexArea; + const vertexOffset = start / 9; + const indices = chunk.indices; + for (let i = 0; i < length; ++i) { + indices[startIndex++] = vertexOffset + subChunkIndices[i]; + } + chunk.updateIndexLength += length; + chunk.updateVertexStart = Math.min(chunk.updateVertexStart, start); + chunk.updateVertexEnd = Math.max(chunk.updateVertexEnd, start + size); + } +} diff --git a/packages/core/src/RenderPipeline/index.ts b/packages/core/src/RenderPipeline/index.ts index 7161b57757..29431e2740 100644 --- a/packages/core/src/RenderPipeline/index.ts +++ b/packages/core/src/RenderPipeline/index.ts @@ -1,5 +1,5 @@ export { BasicRenderPipeline, RenderQueueFlags } from "./BasicRenderPipeline"; -export { BatchUtils } from "./BatchUtils"; +export { VertexMergeBatcher } from "./VertexMergeBatcher"; export { Blitter } from "./Blitter"; export { RenderQueue } from "./RenderQueue"; export { PipelineStage } from "./enums/PipelineStage"; diff --git a/packages/core/src/Renderer.ts b/packages/core/src/Renderer.ts index ab9f743c0c..5af1e71750 100644 --- a/packages/core/src/Renderer.ts +++ b/packages/core/src/Renderer.ts @@ -5,7 +5,7 @@ import { Component } from "./Component"; import { DependentMode, dependentComponents } from "./ComponentsDependencies"; import { Entity } from "./Entity"; import { RenderContext } from "./RenderPipeline/RenderContext"; -import { SubRenderElement } from "./RenderPipeline/SubRenderElement"; +import { RenderElement } from "./RenderPipeline/RenderElement"; import { Transform, TransformModifyFlags } from "./Transform"; import { assignmentClone, deepClone, ignoreClone } from "./clone/CloneManager"; import { SpriteMaskLayer } from "./enums/SpriteMaskLayer"; @@ -23,14 +23,15 @@ import { ShaderDataGroup } from "./shader/enums/ShaderDataGroup"; export class Renderer extends Component { private static _tempVector0 = new Vector3(); + /** @internal */ + static _worldMatrixProperty = ShaderProperty.getByName("renderer_ModelMat"); + /** @internal */ + static _rendererLayerProperty = ShaderProperty.getByName("renderer_Layer"); + private static _receiveShadowMacro = ShaderMacro.getByName("RENDERER_IS_RECEIVE_SHADOWS"); - private static _localMatrixProperty = ShaderProperty.getByName("renderer_LocalMat"); - private static _worldMatrixProperty = ShaderProperty.getByName("renderer_ModelMat"); private static _mvMatrixProperty = ShaderProperty.getByName("renderer_MVMat"); private static _mvpMatrixProperty = ShaderProperty.getByName("renderer_MVPMat"); - private static _mvInvMatrixProperty = ShaderProperty.getByName("renderer_MVInvMat"); private static _normalMatrixProperty = ShaderProperty.getByName("renderer_NormalMat"); - private static _rendererLayerProperty = ShaderProperty.getByName("renderer_Layer"); /** @internal */ @ignoreClone @@ -49,9 +50,6 @@ export class Renderer extends Component { /** @internal */ @assignmentClone _maskInteraction: SpriteMaskInteraction = SpriteMaskInteraction.None; - /** @internal */ - @ignoreClone - _batchedTransformShaderData: boolean = false; @assignmentClone _maskLayer: SpriteMaskLayer = SpriteMaskLayer.Layer0; @@ -74,8 +72,6 @@ export class Renderer extends Component { @ignoreClone private _mvpMatrix: Matrix = new Matrix(); @ignoreClone - private _mvInvMatrix: Matrix = new Matrix(); - @ignoreClone private _normalMatrix: Matrix = new Matrix(); @ignoreClone private _materialsInstanced: boolean[] = []; @@ -384,7 +380,6 @@ export class Renderer extends Component { this._shaderData = null; this._mvMatrix = null; this._mvpMatrix = null; - this._mvInvMatrix = null; this._normalMatrix = null; this._materialsInstanced = null; this._rendererLayer = null; @@ -393,74 +388,66 @@ export class Renderer extends Component { /** * @internal */ - _updateTransformShaderData(context: RenderContext, onlyMVP: boolean, batched: boolean): void { + _updateTransformShaderData(context: RenderContext, onlyMVP: boolean): void { const worldMatrix = this._transformEntity.transform.worldMatrix; + const { shaderData } = this; if (onlyMVP) { - this._updateProjectionRelatedShaderData(context, worldMatrix, batched); + const mvpMatrix = this._mvpMatrix; + Matrix.multiply(context.viewProjectionMatrix, worldMatrix, mvpMatrix); + shaderData.setMatrix(Renderer._mvpMatrixProperty, mvpMatrix); } else { - this._updateWorldViewRelatedShaderData(context, worldMatrix, batched); + const mvMatrix = this._mvMatrix; + const normalMatrix = this._normalMatrix; + + Matrix.multiply(context.viewMatrix, worldMatrix, mvMatrix); + Matrix.invert(worldMatrix, normalMatrix); + normalMatrix.transpose(); + + shaderData.setMatrix(Renderer._worldMatrixProperty, worldMatrix); + shaderData.setMatrix(Renderer._mvMatrixProperty, mvMatrix); + shaderData.setMatrix(Renderer._normalMatrixProperty, normalMatrix); + + const mvpMatrix = this._mvpMatrix; + Matrix.multiply(context.viewProjectionMatrix, worldMatrix, mvpMatrix); + shaderData.setMatrix(Renderer._mvpMatrixProperty, mvpMatrix); } } /** * @internal */ - _canBatch(elementA: SubRenderElement, elementB: SubRenderElement): boolean { + _canBatch(preElement: RenderElement, curElement: RenderElement): boolean { return false; } /** * @internal */ - _batch(elementA: SubRenderElement, elementB?: SubRenderElement): void {} + _batch(preElement: RenderElement | null, curElement: RenderElement): void {} /** - * Update once per frame per renderer, not influenced by batched. + * Update once per frame per renderer. */ protected _update(context: RenderContext): void { const { layer } = this.entity; this._rendererLayer.set(layer & 65535, (layer >>> 16) & 65535, 0, 0); } - protected _updateWorldViewRelatedShaderData(context: RenderContext, worldMatrix: Matrix, batched: boolean): void { - const { shaderData, _mvInvMatrix: mvInvMatrix } = this; - if (batched) { + /** + * Update transform shader data for world-space vertices (2D renderers). + * Vertices are already in world space, so model matrix is identity. + */ + protected _updateWorldSpaceTransformShaderData(context: RenderContext, onlyMVP: boolean): void { + const { shaderData } = this; + if (onlyMVP) { + shaderData.setMatrix(Renderer._mvpMatrixProperty, context.viewProjectionMatrix); + } else { // @ts-ignore const identityMatrix = Matrix._identity; - - Matrix.invert(context.viewMatrix, mvInvMatrix); - - shaderData.setMatrix(Renderer._localMatrixProperty, identityMatrix); shaderData.setMatrix(Renderer._worldMatrixProperty, identityMatrix); shaderData.setMatrix(Renderer._mvMatrixProperty, context.viewMatrix); - shaderData.setMatrix(Renderer._mvInvMatrixProperty, mvInvMatrix); shaderData.setMatrix(Renderer._normalMatrixProperty, identityMatrix); - } else { - const mvMatrix = this._mvMatrix; - const normalMatrix = this._normalMatrix; - - Matrix.multiply(context.viewMatrix, worldMatrix, mvMatrix); - Matrix.invert(mvMatrix, mvInvMatrix); - Matrix.invert(worldMatrix, normalMatrix); - normalMatrix.transpose(); - - shaderData.setMatrix(Renderer._localMatrixProperty, this._transformEntity.transform.localMatrix); - shaderData.setMatrix(Renderer._worldMatrixProperty, worldMatrix); - shaderData.setMatrix(Renderer._mvMatrixProperty, mvMatrix); - shaderData.setMatrix(Renderer._mvInvMatrixProperty, mvInvMatrix); - shaderData.setMatrix(Renderer._normalMatrixProperty, normalMatrix); - } - - this._updateProjectionRelatedShaderData(context, worldMatrix, batched); - } - - protected _updateProjectionRelatedShaderData(context: RenderContext, worldMatrix: Matrix, batched: boolean): void { - if (batched) { - this.shaderData.setMatrix(Renderer._mvpMatrixProperty, context.viewProjectionMatrix); - } else { - const mvpMatrix = this._mvpMatrix; - Matrix.multiply(context.viewProjectionMatrix, worldMatrix, mvpMatrix); - this.shaderData.setMatrix(Renderer._mvpMatrixProperty, mvpMatrix); + shaderData.setMatrix(Renderer._mvpMatrixProperty, context.viewProjectionMatrix); } } diff --git a/packages/core/src/SceneManager.ts b/packages/core/src/SceneManager.ts index 92de60d66b..1fa51ba265 100644 --- a/packages/core/src/SceneManager.ts +++ b/packages/core/src/SceneManager.ts @@ -91,10 +91,21 @@ export class SceneManager { * @returns scene promise */ loadScene(url: string, destroyOldScene: boolean = true): AssetPromise { - const scenePromise = this.engine.resourceManager.load({ url, type: AssetType.Scene }); + const resourceManager = this.engine.resourceManager; + // Evict the Scene asset cache for managed scenes about to be destroyed, so a fresh Scene + // instance is created by the loader instead of returning the same instance we're about to + // destroy (self-destroy would leave the active scene in a zombie state). + if (destroyOldScene) { + const realPath = resourceManager._virtualPathResourceMap[url]?.path ?? url; + const cached = resourceManager.getFromCache(realPath); + if (cached && this._scenes.indexOf(cached) !== -1) { + resourceManager._deleteAsset(cached); + } + } + const scenePromise = resourceManager.load({ url, type: AssetType.Scene }); scenePromise.then((scene: Scene) => { if (destroyOldScene) { - const scenes = this._scenes.getArray(); + const scenes = this._scenes.getLoopArray(); for (let i = 0, n = scenes.length; i < n; i++) { scenes[i].destroy(); } diff --git a/packages/core/src/Signal.ts b/packages/core/src/Signal.ts index a18b86cf5a..e337e03d9d 100644 --- a/packages/core/src/Signal.ts +++ b/packages/core/src/Signal.ts @@ -20,9 +20,11 @@ export class Signal { on(fn: (...args: T) => void, target?: any): void; /** * Add a structured binding listener. Structured bindings support clone remapping. + * The target method will be invoked as `method(...signalArgs, ...args)` — + * runtime signal arguments come first, bound arguments are appended. * @param target - The target component * @param methodName - The method name to invoke on the target - * @param args - Pre-resolved arguments + * @param args - Pre-resolved arguments appended after the runtime signal arguments */ on(target: Component, methodName: string, ...args: any[]): void; on(fnOrTarget: ((...args: T) => void) | Component, targetOrMethodName?: any, ...args: any[]): void { @@ -37,9 +39,11 @@ export class Signal { once(fn: (...args: T) => void, target?: any): void; /** * Add a one-time structured binding listener. + * The target method will be invoked as `method(...signalArgs, ...args)` — + * runtime signal arguments come first, bound arguments are appended. * @param target - The target component * @param methodName - The method name to invoke on the target - * @param args - Pre-resolved arguments + * @param args - Pre-resolved arguments appended after the runtime signal arguments */ once(target: Component, methodName: string, ...args: any[]): void; once(fnOrTarget: ((...args: T) => void) | Component, targetOrMethodName?: any, ...args: any[]): void { @@ -171,7 +175,7 @@ export class Signal { const methodName = targetOrMethodName as string; const fn = args.length > 0 - ? (...signalArgs: any[]) => (target as any)[methodName](...args, ...signalArgs) + ? (...signalArgs: any[]) => (target as any)[methodName](...signalArgs, ...args) : (...signalArgs: any[]) => (target as any)[methodName](...signalArgs); this._listeners.push({ fn: fn as (...args: T) => void, diff --git a/packages/core/src/Transform.ts b/packages/core/src/Transform.ts index f822474dcc..fe9fc720b1 100644 --- a/packages/core/src/Transform.ts +++ b/packages/core/src/Transform.ts @@ -563,7 +563,26 @@ export class Transform extends Component { */ _parentChange(): void { this._isParentDirty = true; - this._updateAllWorldFlag(TransformModifyFlags.WmWpWeWqWsWus); + // Reparent invalidates the world state of the entire subtree: + // 1) `_updateAllWorldFlag` has an early-exit that skips propagation when + // self's world dirty flags are already set — invalid after reparent. + // 2) Descendants may have cached a stale `_parentTransformCache` (e.g. if + // `_getParentTransform` was ever called while their ancestor chain was + // partially constructed during clone/instantiate). Force them to + // re-resolve the parent transform on next access. + this._propagateReparentDirty(TransformModifyFlags.WmWpWeWqWsWus); + } + + private _propagateReparentDirty(flags: TransformModifyFlags): void { + this._worldAssociatedChange(flags); + const children = this._entity._children; + for (let i = 0, n = children.length; i < n; i++) { + const transform = children[i].transform; + if (transform) { + transform._isParentDirty = true; + transform._propagateReparentDirty(flags); + } + } } /** diff --git a/packages/core/src/animation/Animator.ts b/packages/core/src/animation/Animator.ts index 180c2d1356..c25c30e3c8 100644 --- a/packages/core/src/animation/Animator.ts +++ b/packages/core/src/animation/Animator.ts @@ -218,13 +218,31 @@ export class Animator extends Component { * @param stateName - The state name * @param layerIndex - The layer index(default -1). If layer is -1, find the first state with the given state name */ - findAnimatorState(stateName: string, layerIndex: number = -1): AnimatorState { - return this._getAnimatorStateInfo(stateName, layerIndex).state; + /** + * Find the per-instance play data for a state by name. + * The returned object's `speed` is per-instance and safe to modify without affecting other Animator instances. + * @param stateName - The state name + * @param layerIndex - The layer index (default -1, searches all layers) + * @returns Per-instance AnimatorStatePlayData, or null if not found + */ + findAnimatorState(stateName: string, layerIndex: number = -1): AnimatorStatePlayData { + const { state, layerIndex: foundLayer } = this._getAnimatorStateInfo(stateName, layerIndex); + if (!state || foundLayer < 0) return null; + const layerData = this._animatorLayersData[foundLayer]; + if (!layerData) return null; + // Check srcPlayData and destPlayData for the matching state + if (layerData.srcPlayData.state === state) return layerData.srcPlayData; + if (layerData.destPlayData.state === state) return layerData.destPlayData; + // State exists in controller but not currently playing — return srcPlayData initialized with the state + return layerData.srcPlayData; } /** * Get the layer by name. * @param name - The layer's name. + * @todo Return per-instance layer data (like AnimatorStatePlayData for states) instead of shared asset. + * Currently returns the shared AnimatorControllerLayer — modifying `weight` affects all instances. + * Should follow Unity's pattern: Animator.SetLayerWeight/GetLayerWeight (per-instance). */ findLayerByName(name: string): AnimatorControllerLayer { return this._animatorController?._layersMap[name]; @@ -616,7 +634,7 @@ export class Animator extends Component { const { srcPlayData } = layerData; const { state } = srcPlayData; - const playSpeed = state.speed * this.speed; + const playSpeed = srcPlayData.speed * this.speed; const playDeltaTime = playSpeed * deltaTime; srcPlayData.updateOrientation(playDeltaTime); @@ -883,7 +901,7 @@ export class Animator extends Component { return; } - const playSpeed = state.speed * this.speed; + const playSpeed = destPlayData.speed * this.speed; const playDeltaTime = playSpeed * deltaTime; destPlayData.updateOrientation(playDeltaTime); @@ -989,7 +1007,7 @@ export class Animator extends Component { ): void { const playData = layerData.srcPlayData; const { state } = playData; - const actualSpeed = state.speed * this.speed; + const actualSpeed = playData.speed * this.speed; const actualDeltaTime = actualSpeed * deltaTime; playData.updateOrientation(actualDeltaTime); diff --git a/packages/core/src/animation/index.ts b/packages/core/src/animation/index.ts index b829ffde54..bd201a871f 100644 --- a/packages/core/src/animation/index.ts +++ b/packages/core/src/animation/index.ts @@ -11,6 +11,7 @@ export { Animator } from "./Animator"; export { AnimatorController } from "./AnimatorController"; export { AnimatorControllerLayer } from "./AnimatorControllerLayer"; export { AnimatorState } from "./AnimatorState"; +export { AnimatorStatePlayData } from "./internal/AnimatorStatePlayData"; export { AnimatorStateMachine } from "./AnimatorStateMachine"; export { AnimatorStateTransition } from "./AnimatorStateTransition"; export { AnimatorConditionMode } from "./enums/AnimatorConditionMode"; diff --git a/packages/core/src/animation/internal/AnimatorStatePlayData.ts b/packages/core/src/animation/internal/AnimatorStatePlayData.ts index 7d10fc2324..5cfa2fd3eb 100644 --- a/packages/core/src/animation/internal/AnimatorStatePlayData.ts +++ b/packages/core/src/animation/internal/AnimatorStatePlayData.ts @@ -1,20 +1,63 @@ +import { AnimationClip } from "../AnimationClip"; import { AnimatorState } from "../AnimatorState"; +import { AnimatorStateTransition } from "../AnimatorStateTransition"; import { AnimatorStatePlayState } from "../enums/AnimatorStatePlayState"; import { WrapMode } from "../enums/WrapMode"; +import { StateMachineScript } from "../StateMachineScript"; import { AnimatorStateData } from "./AnimatorStateData"; /** - * @internal + * Per-instance runtime data for an AnimatorState. + * Proxies read-only properties from the shared AnimatorState asset, + * while providing per-instance mutable properties (e.g. speed). */ export class AnimatorStatePlayData { + /** @internal */ state: AnimatorState; + /** @internal */ stateData: AnimatorStateData; + /** @internal */ playedTime: number; playState: AnimatorStatePlayState; + /** @internal */ clipTime: number; + /** @internal */ currentEventIndex: number; + /** @internal */ isForward = true; + /** @internal */ offsetFrameTime: number; + /** Per-instance speed. Initialized from AnimatorState.speed, safe to modify without affecting other instances. */ + speed: number = 1.0; + + // ── Proxy properties from AnimatorState (read-only) ── + + /** The name of the state. */ + get name(): string { + return this.state.name; + } + + /** The clip played by this state. */ + get clip(): AnimationClip { + return this.state.clip; + } + + /** The wrap mode. */ + get wrapMode(): WrapMode { + return this.state.wrapMode; + } + + /** The transitions going out of this state. */ + get transitions(): Readonly { + return this.state.transitions; + } + + /** + * Add a state machine script to the underlying AnimatorState. + */ + addStateMachineScript(scriptType: new () => T): T { + return this.state.addStateMachineScript(scriptType); + } private _changedOrientation = false; @@ -27,6 +70,7 @@ export class AnimatorStatePlayData { this.clipTime = state.clipStartTime * state.clip.length; this.currentEventIndex = 0; this.isForward = true; + this.speed = state.speed; this.state._transitionCollection.needResetCurrentCheckIndex = true; } diff --git a/packages/core/src/asset/ResourceManager.ts b/packages/core/src/asset/ResourceManager.ts index 0395b2b29b..b83a9360c4 100644 --- a/packages/core/src/asset/ResourceManager.ts +++ b/packages/core/src/asset/ResourceManager.ts @@ -58,7 +58,7 @@ export class ResourceManager { * Create a ResourceManager. * @param engine - Engine to which the current ResourceManager belongs */ - constructor(public readonly engine: Engine) {} + constructor(public readonly engine: Engine) { } /** * Load the asset asynchronously by asset item information. @@ -340,7 +340,12 @@ export class ResourceManager { } private _assignDefaultOptions(assetInfo: LoadItem): LoadItem { - assetInfo.type = assetInfo.type ?? ResourceManager._getTypeByUrl(assetInfo.url); + const remoteConfig = this._virtualPathResourceMap[assetInfo.url]; + if (remoteConfig) { + assetInfo.type = remoteConfig.type; + } else { + assetInfo.type = assetInfo.type ?? ResourceManager._getTypeByUrl(assetInfo.url); + } if (assetInfo.type === undefined) { throw `asset type should be specified: ${assetInfo.url}`; } @@ -621,7 +626,7 @@ export class ResourceManager { * @param extNames - Name of file extension */ export function resourceLoader(assetType: string, extNames: string[], useCache: boolean = true) { - return >(Target: { new (useCache: boolean): T }) => { + return >(Target: { new(useCache: boolean): T }) => { const loader = new Target(useCache); ResourceManager._addLoader(assetType, loader, extNames); }; @@ -632,18 +637,18 @@ const reEscapeChar = /\\(\\)?/g; const rePropName = RegExp( // Match anything that isn't a dot or bracket. "[^.[\\]]+" + - "|" + - // Or match property names within brackets. - "\\[(?:" + - // Match a non-string expression. - "([^\"'][^[]*)" + - "|" + - // Or match strings (supports escaping characters). - "([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2" + - ")\\]" + - "|" + - // Or match "" as the space between consecutive dots or empty brackets. - "(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))", + "|" + + // Or match property names within brackets. + "\\[(?:" + + // Match a non-string expression. + "([^\"'][^[]*)" + + "|" + + // Or match strings (supports escaping characters). + "([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2" + + ")\\]" + + "|" + + // Or match "" as the space between consecutive dots or empty brackets. + "(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))", "g" ); diff --git a/packages/core/src/audio/AudioManager.ts b/packages/core/src/audio/AudioManager.ts index ad93f5ed59..b1c4c5651b 100644 --- a/packages/core/src/audio/AudioManager.ts +++ b/packages/core/src/audio/AudioManager.ts @@ -1,3 +1,9 @@ +type ResumableAudioSource = { + _resumePendingPlayback(): void; + _suspendPlaybackForInterruption(): boolean; + _resumeInterruptedPlayback(): void; +}; + /** * Audio Manager for managing global audio context and settings. */ @@ -7,15 +13,22 @@ export class AudioManager { private static _context: AudioContext; private static _gainNode: GainNode; - private static _resumePromise: Promise = null; private static _needsUserGestureResume = false; + private static _pendingSources = new Set(); + private static _playingSources = new Set(); + private static _interruptedSources = new Set(); + private static _foregroundRestoreDelay = 300; + private static _foregroundRestoreTimer: number | undefined; + private static _hidden = false; + private static _eventsBound = false; /** * Suspend the audio context. * @returns A promise that resolves when the audio context is suspended */ static suspend(): Promise { - return AudioManager._context.suspend(); + AudioManager._suspendActiveSourcesForInterruption(); + return AudioManager._context?.suspend() ?? Promise.resolve(); } /** @@ -24,14 +37,48 @@ export class AudioManager { * @returns A promise that resolves when the audio context is resumed */ static resume(): Promise { - return (AudioManager._resumePromise ??= AudioManager._context - .resume() - .then(() => { - AudioManager._needsUserGestureResume = false; - }) - .finally(() => { - AudioManager._resumePromise = null; - })); + const context = AudioManager._context; + if (!context) { + return Promise.resolve(); + } + if (context.state === "running") { + AudioManager._clearForegroundRestore(); + AudioManager._needsUserGestureResume = false; + AudioManager._resumePendingSources(); + AudioManager._resumeInterruptedSources(); + return Promise.resolve(); + } + return context.resume().then(() => { + AudioManager._clearForegroundRestore(); + AudioManager._needsUserGestureResume = false; + AudioManager._resumePendingSources(); + AudioManager._resumeInterruptedSources(); + }); + } + + /** @internal */ + static _registerPendingSource(source: ResumableAudioSource): void { + AudioManager._pendingSources.add(source); + } + + /** @internal */ + static _unregisterPendingSource(source: ResumableAudioSource): void { + AudioManager._pendingSources.delete(source); + } + + /** @internal */ + static _registerPlayingSource(source: ResumableAudioSource): void { + AudioManager._playingSources.add(source); + } + + /** @internal */ + static _unregisterPlayingSource(source: ResumableAudioSource): void { + AudioManager._playingSources.delete(source); + } + + /** @internal */ + static _unregisterInterruptedSource(source: ResumableAudioSource): void { + AudioManager._interruptedSources.delete(source); } /** @@ -41,11 +88,12 @@ export class AudioManager { let context = AudioManager._context; if (!context) { AudioManager._context = context = new window.AudioContext(); - document.addEventListener("visibilitychange", AudioManager._onVisibilityChange); - // iOS Safari requires user gesture to resume AudioContext - document.addEventListener("touchstart", AudioManager._resumeAfterInterruption, { passive: true }); - document.addEventListener("touchend", AudioManager._resumeAfterInterruption, { passive: true }); - document.addEventListener("click", AudioManager._resumeAfterInterruption); + context.onstatechange = AudioManager._onContextStateChange; + if (!AudioManager._eventsBound) { + AudioManager._eventsBound = true; + AudioManager._bindLifecycleEvents(); + AudioManager._bindGestureEvents(); + } } return context; } @@ -70,22 +118,153 @@ export class AudioManager { return AudioManager.getContext().state === "running"; } - private static _onVisibilityChange(): void { - if (!document.hidden && AudioManager._playingCount > 0 && !AudioManager.isAudioContextRunning()) { - // iOS WKWebView WebKit bug(Triggered in LingGuang App): AudioContext may be in a "zombie" state where - // state reports "suspended" but resume() alone won't restart audio rendering. - // Calling suspend() first forces a clean internal state reset before user gesture triggers resume. - // Related: https://bugs.webkit.org/show_bug.cgi?id=263627 - AudioManager.suspend(); - AudioManager._needsUserGestureResume = true; + private static _onContextStateChange(): void { + if (AudioManager._context?.state === "running") { + if (AudioManager._hidden || AudioManager._needsUserGestureResume) { + return; + } + AudioManager._needsUserGestureResume = false; + AudioManager._resumePendingSources(); + AudioManager._resumeInterruptedSources(); + } + } + + private static _resumePendingSources(): void { + if (!AudioManager._pendingSources.size || !AudioManager.isAudioContextRunning()) { + return; + } + + const pendingSources = Array.from(AudioManager._pendingSources); + AudioManager._pendingSources.clear(); + + for (let i = 0, n = pendingSources.length; i < n; i++) { + pendingSources[i]._resumePendingPlayback(); + } + } + + private static _suspendActiveSourcesForInterruption(): void { + if (!AudioManager._playingSources.size) { + return; + } + + const playingSources = Array.from(AudioManager._playingSources); + for (let i = 0, n = playingSources.length; i < n; i++) { + const source = playingSources[i]; + if (source._suspendPlaybackForInterruption()) { + AudioManager._interruptedSources.add(source); + } + } + } + + private static _resumeInterruptedSources(): void { + if (!AudioManager._interruptedSources.size || !AudioManager.isAudioContextRunning()) { + return; + } + + const interruptedSources = Array.from(AudioManager._interruptedSources); + AudioManager._interruptedSources.clear(); + + for (let i = 0, n = interruptedSources.length; i < n; i++) { + interruptedSources[i]._resumeInterruptedPlayback(); + } + } + + private static _bindLifecycleEvents(): void { + const hiddenProp = AudioManager._getHiddenProp(); + const visibilityEvents = [ + "visibilitychange", + "mozvisibilitychange", + "msvisibilitychange", + "webkitvisibilitychange", + "qbrowserVisibilityChange" + ]; + + for (let i = 0, n = visibilityEvents.length; i < n; i++) { + document.addEventListener(visibilityEvents[i], (event) => { + const hidden = hiddenProp ? Boolean((document as any)[hiddenProp] || (event as any)?.hidden) : document.hidden; + hidden ? AudioManager._onHidden() : AudioManager._onShown(); + }); + } + + window.addEventListener("pagehide", AudioManager._onHidden); + window.addEventListener("pageshow", AudioManager._onShown); + document.addEventListener("pagehide", AudioManager._onHidden); + document.addEventListener("pageshow", AudioManager._onShown); + } + + private static _bindGestureEvents(): void { + const gestureEvents = ["pointerdown", "pointerup", "touchstart", "touchend", "mouseup", "click"]; + for (let i = 0, n = gestureEvents.length; i < n; i++) { + document.addEventListener(gestureEvents[i], AudioManager._resumeAfterInterruption, { passive: true }); + } + } + + private static _getHiddenProp(): string { + const doc = document as any; + if (typeof doc.hidden !== "undefined") return "hidden"; + if (typeof doc.mozHidden !== "undefined") return "mozHidden"; + if (typeof doc.msHidden !== "undefined") return "msHidden"; + if (typeof doc.webkitHidden !== "undefined") return "webkitHidden"; + return ""; + } + + private static _hasResumeWork(): boolean { + return ( + AudioManager._needsUserGestureResume || + AudioManager._pendingSources.size > 0 || + AudioManager._interruptedSources.size > 0 + ); + } + + private static _onHidden(): void { + if (AudioManager._hidden) { + return; + } + AudioManager._hidden = true; + AudioManager._clearForegroundRestore(); + AudioManager.suspend().catch(() => {}); + } + + private static _onShown(): void { + if (!AudioManager._hidden) { + return; + } + AudioManager._hidden = false; + + if (AudioManager._hasResumeWork()) { + AudioManager._prepareGestureResume(); + AudioManager._scheduleForegroundRestore(); } } private static _resumeAfterInterruption(): void { - if (AudioManager._needsUserGestureResume) { + if (AudioManager._hasResumeWork()) { AudioManager.resume().catch((e) => { console.warn("Failed to resume AudioContext:", e); }); } } + + private static _scheduleForegroundRestore(): void { + AudioManager._clearForegroundRestore(); + AudioManager._foregroundRestoreTimer = window.setTimeout(() => { + AudioManager._foregroundRestoreTimer = undefined; + AudioManager.resume().catch(() => AudioManager._prepareGestureResume()); + }, AudioManager._foregroundRestoreDelay); + } + + private static _clearForegroundRestore(): void { + if (AudioManager._foregroundRestoreTimer === undefined) { + return; + } + window.clearTimeout(AudioManager._foregroundRestoreTimer); + AudioManager._foregroundRestoreTimer = undefined; + } + + private static _prepareGestureResume(): Promise { + // iOS WKWebView may report a resumable state while rendering is still frozen. + // Force a clean context edge, then let a gesture or foreground retry restore sources. + AudioManager._needsUserGestureResume = true; + return AudioManager.suspend().catch(() => {}); + } } diff --git a/packages/core/src/audio/AudioSource.ts b/packages/core/src/audio/AudioSource.ts index 29a3ed8bc1..3dacf53ec3 100644 --- a/packages/core/src/audio/AudioSource.ts +++ b/packages/core/src/audio/AudioSource.ts @@ -159,27 +159,11 @@ export class AudioSource extends Component { if (AudioManager.isAudioContextRunning()) { this._startPlayback(); } else { - // iOS Safari requires resume() to be called within the same user gesture callback that triggers playback. - // Document-level events won't work - must call resume() directly here in play(). this._pendingPlay = true; - AudioManager.resume().then( - () => { - // Check if cancelled by stop()/pause() - if (!this._pendingPlay) { - return; - } - this._pendingPlay = false; - // Check if still valid to play after async resume - if (this._destroyed || !this.enabled || !this._clip) { - return; - } - this._startPlayback(); - }, - (e) => { - this._pendingPlay = false; - console.warn("Failed to resume AudioContext:", e); - } - ); + AudioManager._registerPendingSource(this); + AudioManager.resume().catch((e) => { + console.warn("Failed to resume AudioContext:", e); + }); } } @@ -187,23 +171,27 @@ export class AudioSource extends Component { * Stops playing the clip. */ stop(): void { - this._pendingPlay = false; + this._cancelPendingPlayback(); + AudioManager._unregisterInterruptedSource(this); if (this._isPlaying) { this._clearSourceNode(); this._isPlaying = false; - this._pausedTime = -1; - this._playTime = -1; AudioManager._playingCount--; + AudioManager._unregisterPlayingSource(this); } + + this._pausedTime = -1; + this._playTime = -1; } /** * Pauses playing the clip. */ pause(): void { - this._pendingPlay = false; + this._cancelPendingPlayback(); + AudioManager._unregisterInterruptedSource(this); if (this._isPlaying) { this._clearSourceNode(); @@ -211,6 +199,7 @@ export class AudioSource extends Component { this._pausedTime = AudioManager.getContext().currentTime; this._isPlaying = false; AudioManager._playingCount--; + AudioManager._unregisterPlayingSource(this); } } @@ -250,34 +239,120 @@ export class AudioSource extends Component { this.stop(); } + /** @internal */ + _resumePendingPlayback(): void { + if (!this._pendingPlay) { + return; + } + + this._pendingPlay = false; + + if (this._destroyed || !this.enabled || !this._clip?._getAudioSource()) { + return; + } + + this._startPlayback(); + } + + /** @internal */ + _suspendPlaybackForInterruption(): boolean { + if (!this._isPlaying) { + return false; + } + + const pausedTime = AudioManager.getContext().currentTime; + this._clearSourceNode(); + + this._pausedTime = pausedTime; + this._isPlaying = false; + AudioManager._playingCount--; + AudioManager._unregisterPlayingSource(this); + + return true; + } + + /** @internal */ + _resumeInterruptedPlayback(): void { + if ( + this._destroyed || + !this.enabled || + this._isPlaying || + this._pendingPlay || + !this._clip?._getAudioSource() || + this._playTime < 0 + ) { + return; + } + + if (AudioManager.isAudioContextRunning()) { + this._startPlayback(); + } else { + this._pendingPlay = true; + AudioManager._registerPendingSource(this); + } + } + private _startPlayback(): void { const startTime = this._pausedTime > 0 ? this._pausedTime - this._playTime : 0; - this._initSourceNode(startTime); + if (!this._initSourceNode(startTime)) { + this._pausedTime = -1; + this._playTime = -1; + return; + } this._playTime = AudioManager.getContext().currentTime - startTime; this._pausedTime = -1; this._isPlaying = true; AudioManager._playingCount++; + AudioManager._registerPlayingSource(this); } - private _initSourceNode(startTime: number): void { + private _initSourceNode(startTime: number): boolean { const context = AudioManager.getContext(); const sourceNode = context.createBufferSource(); + const audioBuffer = this._clip._getAudioSource(); + const duration = audioBuffer.duration; + let offset = Math.max(0, startTime); + + if (duration > 0) { + if (this._loop) { + offset %= duration; + } else if (offset >= duration) { + return false; + } + } - sourceNode.buffer = this._clip._getAudioSource(); + sourceNode.buffer = audioBuffer; sourceNode.playbackRate.value = this._playbackRate; sourceNode.loop = this._loop; sourceNode.onended = this._onPlayEnd; this._sourceNode = sourceNode; sourceNode.connect(this._gainNode); - sourceNode.start(0, startTime); + sourceNode.start(0, offset); + return true; } private _clearSourceNode(): void { - this._sourceNode.stop(); - this._sourceNode.disconnect(); - this._sourceNode.onended = null; + const sourceNode = this._sourceNode; + if (!sourceNode) { + return; + } + + sourceNode.onended = null; + try { + sourceNode.stop(); + } catch {} + sourceNode.disconnect(); this._sourceNode = null; } + + private _cancelPendingPlayback(): void { + if (!this._pendingPlay) { + return; + } + + this._pendingPlay = false; + AudioManager._unregisterPendingSource(this); + } } diff --git a/packages/core/src/clone/CloneManager.ts b/packages/core/src/clone/CloneManager.ts index be46462982..b6f94ce248 100644 --- a/packages/core/src/clone/CloneManager.ts +++ b/packages/core/src/clone/CloneManager.ts @@ -105,21 +105,46 @@ export class CloneManager { ): void { const sourceProperty = source[k]; - // Remappable references (Entity/Component) are always remapped, regardless of clone decorator + // 1. Remappable references (Entity/Component) are always remapped, highest priority if (sourceProperty instanceof Object && (sourceProperty)._remap) { target[k] = (sourceProperty)._remap(srcRoot, targetRoot); return; } + // 2. Explicit ignore if (cloneMode === CloneMode.Ignore) return; - // Primitives, undecorated, or @assignmentClone: direct assign - if (!(sourceProperty instanceof Object) || cloneMode === undefined || cloneMode === CloneMode.Assignment) { + // 3. Primitives / null / undefined - direct assign + if (!(sourceProperty instanceof Object)) { target[k] = sourceProperty; return; } - // @shallowClone / @deepClone: deep copy complex objects + // 4. Determine effective clone mode + let effectiveCloneMode: CloneMode = cloneMode; + if (effectiveCloneMode === undefined) { + // Undecorated: infer from runtime type + effectiveCloneMode = CloneManager._inferCloneMode(sourceProperty, target[k]); + } else if (effectiveCloneMode !== CloneMode.Assignment) { + // Decorated Shallow/Deep: upgrade to Deep if target already has independent same-type instance. + // Assignment is never upgraded — it means the user explicitly wants a reference copy. + const targetProperty = target[k]; + if ( + targetProperty && + targetProperty !== sourceProperty && + targetProperty.constructor === sourceProperty.constructor + ) { + effectiveCloneMode = CloneMode.Deep; + } + } + + // 5. Assignment - direct reference copy + if (effectiveCloneMode === CloneMode.Assignment) { + target[k] = sourceProperty; + return; + } + + // 6. Shallow/Deep clone for complex types const type = sourceProperty.constructor; switch (type) { case Uint8Array: @@ -137,6 +162,37 @@ export class CloneManager { targetPropertyT.set(sourceProperty); } break; + case Map: + let targetPropertyM = >target[k]; + if (targetPropertyM == null) { + target[k] = targetPropertyM = new Map(); + } else { + targetPropertyM.clear(); + } + (>sourceProperty).forEach((value, key) => { + if (key instanceof Object && (key)._remap) { + key = (key)._remap(srcRoot, targetRoot); + } + if (value instanceof Object && (value)._remap) { + value = (value)._remap(srcRoot, targetRoot); + } + targetPropertyM.set(key, value); + }); + break; + case Set: + let targetPropertyS = >target[k]; + if (targetPropertyS == null) { + target[k] = targetPropertyS = new Set(); + } else { + targetPropertyS.clear(); + } + (>sourceProperty).forEach((value) => { + if (value instanceof Object && (value)._remap) { + value = (value)._remap(srcRoot, targetRoot); + } + targetPropertyS.add(value); + }); + break; case Array: let targetPropertyA = >target[k]; const length = (>sourceProperty).length; @@ -150,7 +206,7 @@ export class CloneManager { >sourceProperty, targetPropertyA, i, - cloneMode, + cloneMode, // Pass original mode: decorated → children inherit, undecorated → children infer independently srcRoot, targetRoot, deepInstanceMap @@ -158,25 +214,27 @@ export class CloneManager { } break; default: - let targetProperty = target[k]; - // If the target property is undefined, create new instance and keep reference sharing like the source - if (!targetProperty) { - targetProperty = deepInstanceMap.get(sourceProperty); - if (!targetProperty) { - targetProperty = new sourceProperty.constructor(); - deepInstanceMap.set(sourceProperty, targetProperty); - } - target[k] = targetProperty; + // Check if we've already visited this source object (cycle detection) + if (deepInstanceMap.has(sourceProperty)) { + target[k] = deepInstanceMap.get(sourceProperty); + return; + } + + let targetPropertyD = target[k]; + if (!targetPropertyD) { + targetPropertyD = new sourceProperty.constructor(); + target[k] = targetPropertyD; } + deepInstanceMap.set(sourceProperty, targetPropertyD); if ((sourceProperty).copyFrom) { - (targetProperty).copyFrom(sourceProperty); + (targetPropertyD).copyFrom(sourceProperty); } else { const cloneModes = CloneManager.getCloneMode(sourceProperty.constructor); for (let k in sourceProperty) { CloneManager.cloneProperty( sourceProperty, - targetProperty, + targetPropertyD, k, cloneModes[k], srcRoot, @@ -184,12 +242,46 @@ export class CloneManager { deepInstanceMap ); } - (sourceProperty)._cloneTo?.(targetProperty, srcRoot, targetRoot); + (sourceProperty)._cloneTo?.(targetPropertyD, srcRoot, targetRoot); } break; } } + /** + * Infer the appropriate clone mode for an undecorated property based on its runtime type. + * This enables user custom scripts to get correct clone behavior without decorators. + */ + private static _inferCloneMode(sourceProperty: Object, targetProperty: any): CloneMode { + // If target already has an independent instance of the same type, + // deep clone to preserve isolation (e.g., constructor-created objects) + if ( + targetProperty && + targetProperty !== sourceProperty && + targetProperty.constructor === sourceProperty.constructor + ) { + return CloneMode.Deep; + } + + // Arrays need recursive processing (may contain Entity/Component refs) + if (Array.isArray(sourceProperty)) return CloneMode.Deep; + + // TypedArrays - copy data + if (ArrayBuffer.isView(sourceProperty)) return CloneMode.Deep; + + // Maps and Sets - create independent copies + if (sourceProperty instanceof Map || sourceProperty instanceof Set) return CloneMode.Deep; + + // Value types with copyFrom (math types like Vector3, Color, etc.) + if ((sourceProperty).copyFrom) return CloneMode.Deep; + + // Plain objects - deep clone (may contain Entity/Component refs) + if (sourceProperty.constructor === Object) return CloneMode.Deep; + + // Other class instances (engine resources like Material, Texture) - shared reference + return CloneMode.Assignment; + } + static deepCloneObject(source: Object, target: Object, deepInstanceMap: Map): void { for (let k in source) { CloneManager.cloneProperty(source, target, k, CloneMode.Deep, null, null, deepInstanceMap); diff --git a/packages/core/src/graphic/TransformFeedbackShader.ts b/packages/core/src/graphic/TransformFeedbackShader.ts index c200e41597..64ffd7d114 100644 --- a/packages/core/src/graphic/TransformFeedbackShader.ts +++ b/packages/core/src/graphic/TransformFeedbackShader.ts @@ -28,16 +28,17 @@ export class TransformFeedbackShader { * Get or compile a shader program for the given engine and macro combination. */ getProgram(engine: Engine, macroCollection: ShaderMacroCollection): ShaderProgram | null { - const pool = engine._getShaderProgramPool(this._id); + const map = engine._getShaderProgramMap(this._id); - let program = pool.get(macroCollection); + let program = map.get(macroCollection); if (program) return program; const { vertexSource, fragmentSource } = ShaderFactory.compilePlatformSource( engine, macroCollection, this.vertexSource, - this.fragmentSource + this.fragmentSource, + false ); program = new ShaderProgram(engine, vertexSource, fragmentSource, this.feedbackVaryings); @@ -47,7 +48,7 @@ export class TransformFeedbackShader { return null; } - pool.cache(program); + map.cache(program); return program; } } diff --git a/packages/core/src/graphic/enums/BufferBindFlag.ts b/packages/core/src/graphic/enums/BufferBindFlag.ts index 152b9d2e54..4616d1eaff 100644 --- a/packages/core/src/graphic/enums/BufferBindFlag.ts +++ b/packages/core/src/graphic/enums/BufferBindFlag.ts @@ -5,5 +5,7 @@ export enum BufferBindFlag { /** Vertex buffer binding flag. */ VertexBuffer, /** Index buffer binding flag. */ - IndexBuffer + IndexBuffer, + /** Constant buffer binding flag (WebGL2 only). */ + ConstantBuffer } diff --git a/packages/core/src/mesh/MeshRenderer.ts b/packages/core/src/mesh/MeshRenderer.ts index e08e51ac4c..7eaf45be7b 100644 --- a/packages/core/src/mesh/MeshRenderer.ts +++ b/packages/core/src/mesh/MeshRenderer.ts @@ -1,6 +1,7 @@ import { BoundingBox } from "@galacean/engine-math"; import { Entity } from "../Entity"; import { RenderContext } from "../RenderPipeline/RenderContext"; +import { RenderElement } from "../RenderPipeline/RenderElement"; import { Renderer, RendererUpdateFlags } from "../Renderer"; import { Logger } from "../base/Logger"; import { ignoreClone } from "../clone/CloneManager"; @@ -151,9 +152,10 @@ export class MeshRenderer extends Renderer { const { _materials: materials, _engine: engine } = this; const subMeshes = mesh.subMeshes; - const renderElement = engine._renderElementPool.get(); - renderElement.set(this.priority, this._distanceForSort); - const subRenderElementPool = engine._subRenderElementPool; + const priority = this.priority; + const distanceForSort = this._distanceForSort; + const renderElementPool = engine._renderElementPool; + const renderPipeline = context.camera._renderPipeline; for (let i = 0, n = subMeshes.length; i < n; i++) { let material = materials[i]; if (!material) { @@ -163,11 +165,38 @@ export class MeshRenderer extends Renderer { material = this.engine._basicResources.meshMagentaMaterial; } - const subRenderElement = subRenderElementPool.get(); - subRenderElement.set(this, material, mesh._primitive, subMeshes[i]); - renderElement.addSubRenderElement(subRenderElement); + const renderElement = renderElementPool.get(); + renderElement.set(this, material, mesh._primitive, subMeshes[i]); + renderElement.priority = priority; + renderElement.distanceForSort = distanceForSort; + renderPipeline.pushRenderElement(context, renderElement); } - context.camera._renderPipeline.pushRenderElement(context, renderElement); + } + + /** + * @internal + */ + override _canBatch(preElement: RenderElement, curElement: RenderElement): boolean { + if (!this._engine._hardwareRenderer.isWebGL2) return false; + return ( + preElement.primitive === curElement.primitive && + preElement.subPrimitive === curElement.subPrimitive && + preElement.material === curElement.material && + this._isFrontFaceInvert() === (curElement.component)._isFrontFaceInvert() && + this.shaderData._macroCollection.isEqual(curElement.component.shaderData._macroCollection) + ); + } + + /** + * @internal + */ + override _batch(preElement: RenderElement | null, curElement: RenderElement): void { + if (!preElement) return; + const renderers = preElement.instancedRenderers; + if (renderers.length === 0) { + renderers.push(preElement.component); + } + renderers.push(curElement.component); } private _setMesh(mesh: Mesh): void { diff --git a/packages/core/src/mesh/ModelMesh.ts b/packages/core/src/mesh/ModelMesh.ts index 27b92ced49..8ee92c4825 100644 --- a/packages/core/src/mesh/ModelMesh.ts +++ b/packages/core/src/mesh/ModelMesh.ts @@ -925,7 +925,7 @@ export class ModelMesh extends Mesh { return null; } if (!buffer.readable) { - throw "Not allowed to access data while vertex buffer readable is false."; + throw new Error("Not allowed to access data while vertex buffer readable is false."); } const vertexCount = this.vertexCount; diff --git a/packages/core/src/mesh/Skin.ts b/packages/core/src/mesh/Skin.ts index 7a9b3444b0..18489805c5 100644 --- a/packages/core/src/mesh/Skin.ts +++ b/packages/core/src/mesh/Skin.ts @@ -15,7 +15,7 @@ export class Skin extends EngineObject { inverseBindMatrices = new Array(); /** @internal */ - @ignoreClone + @deepClone _skinMatrices: Float32Array; /** @internal */ @ignoreClone diff --git a/packages/core/src/mesh/SkinnedMeshRenderer.ts b/packages/core/src/mesh/SkinnedMeshRenderer.ts index d8e83e16bb..4d7f726184 100644 --- a/packages/core/src/mesh/SkinnedMeshRenderer.ts +++ b/packages/core/src/mesh/SkinnedMeshRenderer.ts @@ -1,6 +1,7 @@ import { BoundingBox, Vector2 } from "@galacean/engine-math"; import { Entity } from "../Entity"; import { RenderContext } from "../RenderPipeline/RenderContext"; +import { RenderElement } from "../RenderPipeline/RenderElement"; import { RendererUpdateFlags } from "../Renderer"; import { Logger } from "../base/Logger"; import { deepClone, ignoreClone } from "../clone/CloneManager"; @@ -120,6 +121,13 @@ export class SkinnedMeshRenderer extends MeshRenderer { localBounds.max._onValueChanged = this._onLocalBoundsChanged; } + /** + * @internal + */ + override _canBatch(_preElement: RenderElement, _curElement: RenderElement): boolean { + return false; + } + /** * @internal */ diff --git a/packages/core/src/particle/ParticleGenerator.ts b/packages/core/src/particle/ParticleGenerator.ts index d180c7f929..75c50b5cf6 100644 --- a/packages/core/src/particle/ParticleGenerator.ts +++ b/packages/core/src/particle/ParticleGenerator.ts @@ -112,6 +112,7 @@ export class ParticleGenerator { @ignoreClone _subPrimitive = new SubMesh(0, 0, MeshTopology.Triangles); /** @internal */ + @ignoreClone readonly _renderer: ParticleRenderer; /** @internal */ diff --git a/packages/core/src/particle/ParticleRenderer.ts b/packages/core/src/particle/ParticleRenderer.ts index 633e166989..ed6e4a7275 100644 --- a/packages/core/src/particle/ParticleRenderer.ts +++ b/packages/core/src/particle/ParticleRenderer.ts @@ -5,7 +5,7 @@ import { Renderer, RendererUpdateFlags } from "../Renderer"; import { TransformModifyFlags } from "../Transform"; import { GLCapabilityType } from "../base/Constant"; import { Logger } from "../base/Logger"; -import { deepClone, ignoreClone, shallowClone } from "../clone/CloneManager"; +import { assignmentClone, deepClone, ignoreClone, shallowClone } from "../clone/CloneManager"; import { ModelMesh } from "../mesh/ModelMesh"; import { ShaderMacro } from "../shader/ShaderMacro"; import { ShaderProperty } from "../shader/ShaderProperty"; @@ -47,7 +47,9 @@ export class ParticleRenderer extends Renderer { @ignoreClone _transformedBounds = new BoundingBox(); + @assignmentClone private _renderMode: ParticleRenderMode; + @assignmentClone private _currentRenderModeMacro: ShaderMacro; private _mesh: ModelMesh; private _supportInstancedArrays: boolean; @@ -174,9 +176,9 @@ export class ParticleRenderer extends Renderer { /** * @internal */ - override _updateTransformShaderData(context: RenderContext, onlyMVP: boolean, batched: boolean): void { + override _updateTransformShaderData(context: RenderContext, onlyMVP: boolean): void { //@todo: Don't need to update transform shader data, temp solution - super._updateTransformShaderData(context, onlyMVP, true); + this._updateWorldSpaceTransformShaderData(context, onlyMVP); } protected override _updateBounds(worldBounds: BoundingBox): void { const { generator } = this; @@ -251,13 +253,29 @@ export class ParticleRenderer extends Renderer { const engine = this._engine; const renderElement = engine._renderElementPool.get(); - renderElement.set(this.priority, this._distanceForSort); - const subRenderElement = engine._subRenderElementPool.get(); - subRenderElement.set(this, material, generator._primitive, generator._subPrimitive); - renderElement.addSubRenderElement(subRenderElement); + renderElement.set(this, material, generator._primitive, generator._subPrimitive); + renderElement.priority = this.priority; + renderElement.distanceForSort = this._distanceForSort; context.camera._renderPipeline.pushRenderElement(context, renderElement); } + /** + * @internal + */ + override _cloneTo(target: ParticleRenderer): void { + super._cloneTo(target); + + // ShaderData internals (_macroCollection, _propertyValueMap) are @ignoreClone, + // so the cloned shaderData only has the constructor-set Billboard macro. + // Must re-apply the source's shaderData state. + this.shaderData.cloneTo(target.shaderData); + + // Rebuild GPU resources to match cloned renderMode/mesh/maxParticles. + const gen = target.generator; + gen._reorganizeGeometryBuffers(); + gen._resizeInstanceBuffer(true, gen.main.maxParticles); + } + protected override _onDestroy(): void { const mesh = this._mesh; if (mesh) { diff --git a/packages/core/src/physics/PhysicsScene.ts b/packages/core/src/physics/PhysicsScene.ts index b1f96d77dd..ce6bf2e4e8 100644 --- a/packages/core/src/physics/PhysicsScene.ts +++ b/packages/core/src/physics/PhysicsScene.ts @@ -835,7 +835,7 @@ export class PhysicsScene { if (!shape) { return false; } - return shape.collider.entity.layer & mask && shape.isSceneQuery; + return shape.collider.collisionLayer & mask && shape.isSceneQuery; }; } diff --git a/packages/core/src/shader/Shader.ts b/packages/core/src/shader/Shader.ts index bbdbc23de4..80de735c90 100644 --- a/packages/core/src/shader/Shader.ts +++ b/packages/core/src/shader/Shader.ts @@ -210,12 +210,12 @@ export class Shader implements IReferable { const passes = subShaders[i].passes; for (let j = 0, m = passes.length; j < m; j++) { const pass = passes[j]; - const passShaderProgramPools = pass._shaderProgramPools; - for (let k = passShaderProgramPools.length - 1; k >= 0; k--) { - const shaderProgramPool = passShaderProgramPools[k]; - if (shaderProgramPool.engine !== engine) continue; - shaderProgramPool._destroy(); - passShaderProgramPools.splice(k, 1); + const passShaderProgramMaps = pass._shaderProgramMaps; + for (let k = passShaderProgramMaps.length - 1; k >= 0; k--) { + const map = passShaderProgramMaps[k]; + if (map.engine !== engine) continue; + map.destroy(); + passShaderProgramMaps.splice(k, 1); } } } diff --git a/packages/core/src/shader/ShaderBlockProperty.ts b/packages/core/src/shader/ShaderBlockProperty.ts new file mode 100644 index 0000000000..fd47b4cecc --- /dev/null +++ b/packages/core/src/shader/ShaderBlockProperty.ts @@ -0,0 +1,28 @@ +/** + * @internal + * Shader block property, used to identify uniform blocks by id. + */ +export class ShaderBlockProperty { + private static _counter = 0; + private static _nameMap: Record = Object.create(null); + + /** + * Get shader block property by name. + * @param name - Name of the uniform block + * @returns Shader block property + */ + static getByName(name: string): ShaderBlockProperty { + const nameMap = ShaderBlockProperty._nameMap; + return (nameMap[name] ??= new ShaderBlockProperty(name)); + } + + /** Uniform block name. */ + readonly name: string; + /** @internal */ + readonly _uniqueId: number; + + private constructor(name: string) { + this.name = name; + this._uniqueId = ShaderBlockProperty._counter++; + } +} diff --git a/packages/core/src/shader/ShaderData.ts b/packages/core/src/shader/ShaderData.ts index 72a2f096f0..f2a8a7ccd5 100644 --- a/packages/core/src/shader/ShaderData.ts +++ b/packages/core/src/shader/ShaderData.ts @@ -607,7 +607,11 @@ export class ShaderData implements IReferable, IClone { cloneTo(target: ShaderData): void { CloneManager.deepCloneObject(this._macroCollection, target._macroCollection, new Map()); - Object.assign(target._macroMap, this._macroMap); + const targetMacroMap = target._macroMap; + for (const key in targetMacroMap) { + delete targetMacroMap[key]; + } + Object.assign(targetMacroMap, this._macroMap); const referCount = target._getReferCount(); const propertyValueMap = this._propertyValueMap; const targetPropertyValueMap = target._propertyValueMap; diff --git a/packages/core/src/shader/ShaderMacroCollection.ts b/packages/core/src/shader/ShaderMacroCollection.ts index 749abc22ee..3efb98b77c 100644 --- a/packages/core/src/shader/ShaderMacroCollection.ts +++ b/packages/core/src/shader/ShaderMacroCollection.ts @@ -158,6 +158,20 @@ export class ShaderMacroCollection { return (this._mask[index] & macro._maskValue) !== 0; } + /** + * Whether this macro collection is equal to another. + * @param other - macro collection to compare + */ + isEqual(other: ShaderMacroCollection): boolean { + if (this._length !== other._length) return false; + const mask = this._mask; + const otherMask = other._mask; + for (let i = 0, n = this._length; i < n; i++) { + if (mask[i] !== otherMask[i]) return false; + } + return true; + } + /** * Clear this macro collection. */ diff --git a/packages/core/src/shader/ShaderPass.ts b/packages/core/src/shader/ShaderPass.ts index 8c11182df7..6dc63f0220 100644 --- a/packages/core/src/shader/ShaderPass.ts +++ b/packages/core/src/shader/ShaderPass.ts @@ -1,13 +1,14 @@ import { Engine } from "../Engine"; +import { InstanceBuffer } from "../RenderPipeline/InstanceBuffer"; import { PipelineStage } from "../RenderPipeline/enums/PipelineStage"; import { GLCapabilityType } from "../base/Constant"; -import { ShaderFactory } from "../shaderlib"; +import { ShaderFactory, InstanceBufferLayout } from "../shaderlib/ShaderFactory"; import { Shader } from "./Shader"; import { ShaderMacro } from "./ShaderMacro"; import { ShaderMacroCollection } from "./ShaderMacroCollection"; import { ShaderPart } from "./ShaderPart"; +import { ShaderProgramMap } from "./ShaderProgramMap"; import { ShaderProgram } from "./ShaderProgram"; -import { ShaderProgramPool } from "./ShaderProgramPool"; import { ShaderProperty } from "./ShaderProperty"; import { ShaderLanguage } from "./enums/ShaderLanguage"; import { RenderState } from "./state/RenderState"; @@ -47,7 +48,7 @@ export class ShaderPass extends ShaderPart { /** @internal */ _renderStateDataMap: Record = {}; /** @internal */ - _shaderProgramPools: ShaderProgramPool[] = []; + _shaderProgramMaps: ShaderProgramMap[] = []; private _vertexSource: string; private _fragmentSource: string; @@ -110,15 +111,15 @@ export class ShaderPass extends ShaderPart { * @internal */ _getShaderProgram(engine: Engine, macroCollection: ShaderMacroCollection): ShaderProgram { - const shaderProgramPool = engine._getShaderProgramPool(this._shaderPassId, this._shaderProgramPools); - let shaderProgram = shaderProgramPool.get(macroCollection); + const shaderProgramMap = engine._getShaderProgramMap(this._shaderPassId, this._shaderProgramMaps); + let shaderProgram = shaderProgramMap.get(macroCollection); if (shaderProgram) { return shaderProgram; } - shaderProgram = this._getCanonicalShaderProgram(engine, macroCollection); + shaderProgram = this._compileShaderProgram(engine, macroCollection); - shaderProgramPool.cache(shaderProgram); + shaderProgramMap.cache(shaderProgram); return shaderProgram; } @@ -126,32 +127,46 @@ export class ShaderPass extends ShaderPart { * @internal */ _destroy(): void { - const shaderProgramPools = this._shaderProgramPools; - for (let i = 0, n = shaderProgramPools.length; i < n; i++) { - const shaderProgramPool = shaderProgramPools[i]; - shaderProgramPool._destroy(); - delete shaderProgramPool.engine._shaderProgramPools[this._shaderPassId]; + const shaderProgramMaps = this._shaderProgramMaps; + for (let i = 0, n = shaderProgramMaps.length; i < n; i++) { + const map = shaderProgramMaps[i]; + map.destroy(); + delete map.engine._shaderProgramMaps[this._shaderPassId]; } - // Clear array storing multiple engine shader program pools - shaderProgramPools.length = 0; + shaderProgramMaps.length = 0; } - private _getCanonicalShaderProgram(engine: Engine, macroCollection: ShaderMacroCollection): ShaderProgram { - if (this._platformTarget != undefined) { - return this._getShaderLabProgram(engine, macroCollection); - } + private _compileShaderProgram(engine: Engine, macroCollection: ShaderMacroCollection): ShaderProgram { + const isGPUInstance = macroCollection.isEnable(InstanceBuffer.gpuInstanceMacro); + const { vertexSource, fragmentSource, instanceLayout } = + this._platformTarget != undefined + ? this._compileShaderLabSource(engine, macroCollection, isGPUInstance) + : this._compilePlatformSource(engine, macroCollection, isGPUInstance); + + const program = new ShaderProgram(engine, vertexSource, fragmentSource); + program._instanceLayout = instanceLayout; + return program; + } - const { vertexSource, fragmentSource } = ShaderFactory.compilePlatformSource( + private _compilePlatformSource( + engine: Engine, + macroCollection: ShaderMacroCollection, + isGPUInstance: boolean + ): { vertexSource: string; fragmentSource: string; instanceLayout: InstanceBufferLayout | null } { + return ShaderFactory.compilePlatformSource( engine, macroCollection, this._vertexSource, - this._fragmentSource + this._fragmentSource, + isGPUInstance ); - - return new ShaderProgram(engine, vertexSource, fragmentSource); } - private _getShaderLabProgram(engine: Engine, macroCollection: ShaderMacroCollection): ShaderProgram { + private _compileShaderLabSource( + engine: Engine, + macroCollection: ShaderMacroCollection, + isGPUInstance: boolean + ): { vertexSource: string; fragmentSource: string; instanceLayout: InstanceBufferLayout | null } { const isWebGL2: boolean = engine._hardwareRenderer.isWebGL2; const shaderMacroList = new Array(); ShaderMacro._getMacrosElements(macroCollection, shaderMacroList); @@ -169,6 +184,14 @@ export class ShaderPass extends ShaderPart { noIncludeVertex = Shader._shaderLab._parseMacros(noIncludeVertex, shaderMacroList); noIncludeFrag = Shader._shaderLab._parseMacros(noIncludeFrag, shaderMacroList); + let instanceLayout: InstanceBufferLayout | null = null; + if (isGPUInstance) { + const injected = ShaderFactory.injectInstanceUBO(engine, noIncludeVertex, noIncludeFrag); + noIncludeVertex = injected.vertexSource; + noIncludeFrag = injected.fragmentSource; + instanceLayout = injected.instanceLayout; + } + if (isWebGL2 && this._platformTarget === ShaderLanguage.GLSLES100) { noIncludeVertex = ShaderFactory.convertTo300(noIncludeVertex); noIncludeFrag = ShaderFactory.convertTo300(noIncludeFrag, true); @@ -176,15 +199,16 @@ export class ShaderPass extends ShaderPart { const versionStr = isWebGL2 ? "#version 300 es" : "#version 100"; - const vertexSource = ` ${versionStr} + return { + vertexSource: ` ${versionStr} ${noIncludeVertex} - `; - const fragmentSource = ` ${versionStr} - ${isWebGL2 ? "" : ShaderFactory._shaderExtension} + `, + fragmentSource: ` ${versionStr} + ${isWebGL2 ? "" : ShaderFactory.shaderExtension} ${precisionStr} ${noIncludeFrag} - `; - - return new ShaderProgram(engine, vertexSource, fragmentSource); + `, + instanceLayout + }; } } diff --git a/packages/core/src/shader/ShaderProgram.ts b/packages/core/src/shader/ShaderProgram.ts index 22151e5f77..9548548db6 100644 --- a/packages/core/src/shader/ShaderProgram.ts +++ b/packages/core/src/shader/ShaderProgram.ts @@ -7,7 +7,9 @@ import { ShaderData } from "./ShaderData"; import { ShaderProperty } from "./ShaderProperty"; import { ShaderUniform } from "./ShaderUniform"; import { ShaderUniformBlock } from "./ShaderUniformBlock"; +import { ShaderBlockProperty } from "./ShaderBlockProperty"; import { ShaderDataGroup } from "./enums/ShaderDataGroup"; +import { InstanceBufferLayout, ShaderFactory } from "../shaderlib/ShaderFactory"; /** * Shader program, corresponding to the GPU shader program. @@ -52,7 +54,11 @@ export class ShaderProgram { /** @internal */ _uploadMaterialId: number = -1; + /** @internal */ + _instanceLayout: InstanceBufferLayout | null = null; + attributeLocation: Record = Object.create(null); + uniformBlockIds: number[] = []; // @todo: move to RHI. private _isValid: boolean; @@ -339,6 +345,9 @@ export class ShaderProgram { } const location = gl.getUniformLocation(program, name); + // UBO members have no individual location, skip them + if (location === null) return; + shaderUniform.name = name; shaderUniform.propertyId = ShaderProperty.getByName(name)._uniqueId; shaderUniform.location = location; @@ -412,9 +421,33 @@ export class ShaderProgram { shaderUniform.cacheValue = new Vector4(0, 0, 0); } break; + case gl.FLOAT_MAT2: + shaderUniform.applyFunc = shaderUniform.uploadMat2; + break; + case gl.FLOAT_MAT3: + shaderUniform.applyFunc = shaderUniform.uploadMat3; + break; case gl.FLOAT_MAT4: shaderUniform.applyFunc = isArray ? shaderUniform.uploadMat4v : shaderUniform.uploadMat4; break; + case (gl).FLOAT_MAT2x3: + shaderUniform.applyFunc = shaderUniform.uploadMat2x3; + break; + case (gl).FLOAT_MAT2x4: + shaderUniform.applyFunc = shaderUniform.uploadMat2x4; + break; + case (gl).FLOAT_MAT3x2: + shaderUniform.applyFunc = shaderUniform.uploadMat3x2; + break; + case (gl).FLOAT_MAT3x4: + shaderUniform.applyFunc = shaderUniform.uploadMat3x4; + break; + case (gl).FLOAT_MAT4x2: + shaderUniform.applyFunc = shaderUniform.uploadMat4x2; + break; + case (gl).FLOAT_MAT4x3: + shaderUniform.applyFunc = shaderUniform.uploadMat4x3; + break; case gl.SAMPLER_2D: case gl.SAMPLER_CUBE: case (gl).UNSIGNED_INT_SAMPLER_2D: @@ -476,6 +509,21 @@ export class ShaderProgram { attributeInfos.forEach(({ name }) => { this.attributeLocation[name] = gl.getAttribLocation(program, name); }); + + // Record uniform block indices and bind binding points (WebGL2 only) + if (this._engine._hardwareRenderer.isWebGL2) { + const gl2 = gl; + const bindingMap = ShaderFactory.uniformBlockBindingMap; + const blockCount = gl2.getProgramParameter(program, gl2.ACTIVE_UNIFORM_BLOCKS) ?? 0; + for (let i = 0; i < blockCount; i++) { + const id = ShaderBlockProperty.getByName(gl2.getActiveUniformBlockName(program, i))._uniqueId; + this.uniformBlockIds[i] = id; + const bindingPoint = bindingMap[id]; + if (bindingPoint !== undefined) { + gl2.uniformBlockBinding(program, i, bindingPoint); + } + } + } } private _getUniformInfos(): WebGLActiveInfo[] { diff --git a/packages/core/src/shader/ShaderProgramPool.ts b/packages/core/src/shader/ShaderProgramMap.ts similarity index 56% rename from packages/core/src/shader/ShaderProgramPool.ts rename to packages/core/src/shader/ShaderProgramMap.ts index 3b43a07afa..5673708863 100644 --- a/packages/core/src/shader/ShaderProgramPool.ts +++ b/packages/core/src/shader/ShaderProgramMap.ts @@ -2,23 +2,26 @@ import { Engine } from "../Engine"; import { ShaderMacroCollection } from "./ShaderMacroCollection"; import { ShaderProgram } from "./ShaderProgram"; +type Tree = { + [key: number]: Tree | ShaderProgram; +}; + /** - * Shader program pool. + * Map keyed by ShaderMacroCollection bitmask, caching ShaderProgram instances. * @internal */ -export class ShaderProgramPool { +export class ShaderProgramMap { + engine: Engine; + private _cacheHierarchyDepth: number = 1; - private _cacheMap: Tree = Object.create(null); + private _cacheMap: Tree = Object.create(null); private _lastQueryMap: Record; private _lastQueryKey: number; - constructor(public engine: Engine) {} + constructor(engine: Engine) { + this.engine = engine; + } - /** - * Get shader program by macro collection. - * @param macros - macro collection - * @returns shader program - */ get(macros: ShaderMacroCollection): ShaderProgram | null { let cacheMap = this._cacheMap; const maskLength = macros._length; @@ -33,41 +36,31 @@ export class ShaderProgramPool { const maxEndIndex = this._cacheHierarchyDepth - 1; for (let i = 0; i < maxEndIndex; i++) { const subMask = endIndex < i ? 0 : mask[i]; - let subCacheShaders = >cacheMap[subMask]; - subCacheShaders || (cacheMap[subMask] = subCacheShaders = Object.create(null)); - cacheMap = subCacheShaders; + let subCache = cacheMap[subMask]; + subCache || (cacheMap[subMask] = subCache = Object.create(null)); + cacheMap = subCache; } const cacheKey = endIndex < maxEndIndex ? 0 : mask[maxEndIndex]; - const shader = (>cacheMap)[cacheKey]; - if (!shader) { + const value = (>cacheMap)[cacheKey]; + if (!value) { this._lastQueryKey = cacheKey; this._lastQueryMap = >cacheMap; } - return shader; + return value; } - /** - * Cache the shader program. - * - * @remarks - * The method must return an empty value after calling get() to run normally. - * - * @param shaderProgram - shader program - */ - cache(shaderProgram: ShaderProgram): void { - this._lastQueryMap[this._lastQueryKey] = shaderProgram; + cache(value: ShaderProgram): void { + this._lastQueryMap[this._lastQueryKey] = value; } - /** - * @internal - */ - _destroy(): void { - this._recursiveDestroy(0, this._cacheMap); + destroy(): void { + this._recursiveForEach(0, this._cacheMap); this._cacheMap = Object.create(null); + this._cacheHierarchyDepth = 1; } - private _recursiveDestroy(hierarchy: number, cacheMap: Tree): void { + private _recursiveForEach(hierarchy: number, cacheMap: Tree): void { if (hierarchy === this._cacheHierarchyDepth - 1) { for (let k in cacheMap) { (cacheMap[k]).destroy(); @@ -76,35 +69,30 @@ export class ShaderProgramPool { } ++hierarchy; for (let k in cacheMap) { - this._recursiveDestroy(hierarchy, >cacheMap[k]); + this._recursiveForEach(hierarchy, cacheMap[k]); } } private _resizeCacheMapHierarchy( - cacheMap: Tree, + cacheMap: Tree, hierarchy: number, currentHierarchy: number, increaseHierarchy: number ): void { - // Only expand but not shrink if (hierarchy == currentHierarchy - 1) { for (let k in cacheMap) { - const shader = cacheMap[k]; + const value = cacheMap[k]; let subCacheMap = cacheMap; for (let i = 0; i < increaseHierarchy; i++) { subCacheMap[i == 0 ? k : 0] = subCacheMap = Object.create(null); } - subCacheMap[0] = shader; + subCacheMap[0] = value; } } else { hierarchy++; for (let k in cacheMap) { - this._resizeCacheMapHierarchy(>cacheMap[k], hierarchy, currentHierarchy, increaseHierarchy); + this._resizeCacheMapHierarchy(cacheMap[k], hierarchy, currentHierarchy, increaseHierarchy); } } } } - -type Tree = { - [key: number]: Tree | T; -}; diff --git a/packages/core/src/shader/ShaderUniform.ts b/packages/core/src/shader/ShaderUniform.ts index 07017a4abc..90d9233c1b 100644 --- a/packages/core/src/shader/ShaderUniform.ts +++ b/packages/core/src/shader/ShaderUniform.ts @@ -237,6 +237,14 @@ export class ShaderUniform { this._gl.uniform4iv(shaderUniform.location, value); } + uploadMat2(shaderUniform: ShaderUniform, value: Float32Array): void { + this._gl.uniformMatrix2fv(shaderUniform.location, false, value); + } + + uploadMat3(shaderUniform: ShaderUniform, value: Float32Array): void { + this._gl.uniformMatrix3fv(shaderUniform.location, false, value); + } + uploadMat4(shaderUniform: ShaderUniform, value: Matrix): void { this._gl.uniformMatrix4fv(shaderUniform.location, false, value.elements); } @@ -245,6 +253,30 @@ export class ShaderUniform { this._gl.uniformMatrix4fv(shaderUniform.location, false, value); } + uploadMat2x3(shaderUniform: ShaderUniform, value: Float32Array): void { + (this._gl).uniformMatrix2x3fv(shaderUniform.location, false, value); + } + + uploadMat2x4(shaderUniform: ShaderUniform, value: Float32Array): void { + (this._gl).uniformMatrix2x4fv(shaderUniform.location, false, value); + } + + uploadMat3x2(shaderUniform: ShaderUniform, value: Float32Array): void { + (this._gl).uniformMatrix3x2fv(shaderUniform.location, false, value); + } + + uploadMat3x4(shaderUniform: ShaderUniform, value: Float32Array): void { + (this._gl).uniformMatrix3x4fv(shaderUniform.location, false, value); + } + + uploadMat4x2(shaderUniform: ShaderUniform, value: Float32Array): void { + (this._gl).uniformMatrix4x2fv(shaderUniform.location, false, value); + } + + uploadMat4x3(shaderUniform: ShaderUniform, value: Float32Array): void { + (this._gl).uniformMatrix4x3fv(shaderUniform.location, false, value); + } + uploadTexture(shaderUniform: ShaderUniform, value: Texture): void { const rhi = this._rhi; rhi.activeTexture(shaderUniform.textureIndex as GLenum); diff --git a/packages/core/src/shader/enums/ConstantBufferBindingPoint.ts b/packages/core/src/shader/enums/ConstantBufferBindingPoint.ts new file mode 100644 index 0000000000..595d159924 --- /dev/null +++ b/packages/core/src/shader/enums/ConstantBufferBindingPoint.ts @@ -0,0 +1,7 @@ +/** + * @internal + * Constant buffer binding point allocation. + */ +export enum ConstantBufferBindingPoint { + RendererInstance = 0 +} diff --git a/packages/core/src/shaderlib/ShaderFactory.ts b/packages/core/src/shaderlib/ShaderFactory.ts index e314e4409d..678eb1b55b 100644 --- a/packages/core/src/shaderlib/ShaderFactory.ts +++ b/packages/core/src/shaderlib/ShaderFactory.ts @@ -1,13 +1,28 @@ +import { Matrix, Vector2, Vector3, Vector4 } from "@galacean/engine-math"; import { GLCapabilityType } from "../base/Constant"; import { Logger } from "../base/Logger"; import { Engine } from "../Engine"; +import { Renderer } from "../Renderer"; +import { ShaderDataGroup } from "../shader/enums/ShaderDataGroup"; import { ShaderMacro } from "../shader/ShaderMacro"; import { ShaderMacroCollection } from "../shader/ShaderMacroCollection"; +import { ShaderProperty } from "../shader/ShaderProperty"; +import { ShaderBlockProperty } from "../shader/ShaderBlockProperty"; +import { ConstantBufferBindingPoint } from "../shader/enums/ConstantBufferBindingPoint"; import { ShaderLib } from "./ShaderLib"; +/** + * @internal + */ export class ShaderFactory { - /** @internal */ - static readonly _shaderExtension = [ + static readonly RENDERER_INSTANCE_BLOCK_NAME = "RendererInstanceData"; + + static readonly uniformBlockBindingMap: Record = { + [ShaderBlockProperty.getByName(ShaderFactory.RENDERER_INSTANCE_BLOCK_NAME)._uniqueId]: + ConstantBufferBindingPoint.RendererInstance + }; + + static readonly shaderExtension = [ "GL_EXT_shader_texture_lod", "GL_OES_standard_derivatives", "GL_EXT_draw_buffers", @@ -16,35 +31,127 @@ export class ShaderFactory { .map((e) => `#extension ${e} : enable\n`) .join(""); - private static readonly _has300OutInFragReg = /\bout\s+(?:\w+\s+)?(?:vec4)\s+(?:\w+)\s*;/; // [layout(location = 0)] out [highp] vec4 [color]; + private static readonly _std140TypeInfoMap: Record = { + float: { size: 4, align: 4 }, + int: { size: 4, align: 4 }, + uint: { size: 4, align: 4 }, + vec2: { size: 8, align: 8 }, + ivec2: { size: 8, align: 8 }, + vec3: { size: 12, align: 16 }, + ivec3: { size: 12, align: 16 }, + vec4: { size: 16, align: 16 }, + ivec4: { size: 16, align: 16 }, + mat4: { size: 64, align: 16 }, + mat3x4: { size: 48, align: 16 } + }; + + private static readonly _has300OutInFragReg = /\bout\s+(?:\w+\s+)?vec4\s+\w+\s*;/; + + private static readonly _precisionStr = ` +#ifdef GL_FRAGMENT_PRECISION_HIGH + precision highp float; + precision highp int; +#else + precision mediump float; + precision mediump int; +#endif +`; + + private static readonly _derivedDefines = `\ +#define renderer_MVMat (camera_ViewMat * renderer_ModelMat) +#define renderer_MVPMat (camera_VPMat * renderer_ModelMat) +#define renderer_NormalMat mat4(transpose(inverse(mat3(renderer_ModelMat))))`; + + // Built-in renderer uniforms. value=true means derived (remove but not added to UBO) + private static readonly _builtinRendererUniforms: Record = { + renderer_ModelMat: false, + renderer_Layer: false, + renderer_MVMat: true, + renderer_MVPMat: true, + renderer_NormalMat: true + }; + + private static readonly _uboUniformRegex = + /^[ \t]*uniform\s+(?:(?:lowp|mediump|highp)\s+)?(\w+)\s+(\w+)\s*(\[.+?\])?\s*;/gm; + + private static _packFuncMap: Record = (() => { + const packScalar = (v: Float32Array | Int32Array, o: number, val: number) => { + v[o] = val; + }; + const packVec2 = (v: Float32Array | Int32Array, o: number, val: Vector2) => { + v[o] = val.x; + v[o + 1] = val.y; + }; + const packVec3 = (v: Float32Array | Int32Array, o: number, val: Vector3) => { + v[o] = val.x; + v[o + 1] = val.y; + v[o + 2] = val.z; + }; + const packVec4 = (v: Float32Array | Int32Array, o: number, val: Vector4) => { + v[o] = val.x; + v[o + 1] = val.y; + v[o + 2] = val.z; + v[o + 3] = val.w; + }; + return { + float: packScalar, + int: packScalar, + uint: packScalar, + vec2: packVec2, + ivec2: packVec2, + vec3: packVec3, + ivec3: packVec3, + vec4: packVec4, + ivec4: packVec4, + mat4: (v: Float32Array | Int32Array, o: number, val: Matrix) => { + const e = val.elements; + for (let k = 0; k < 16; k++) v[o + k] = e[k]; + }, + // Affine mat4 stored as mat3x4: write 3 transposed rows (row3 is always 0,0,0,1) + mat3x4: (v: Float32Array | Int32Array, o: number, val: Matrix) => { + const e = val.elements; + // Row 0 + v[o] = e[0]; + v[o + 1] = e[4]; + v[o + 2] = e[8]; + v[o + 3] = e[12]; + // Row 1 + v[o + 4] = e[1]; + v[o + 5] = e[5]; + v[o + 6] = e[9]; + v[o + 7] = e[13]; + // Row 2 + v[o + 8] = e[2]; + v[o + 9] = e[6]; + v[o + 10] = e[10]; + v[o + 11] = e[14]; + } + }; + })(); static parseCustomMacros(macros: ShaderMacro[]) { return macros.map((m) => `#define ${m.value ? m.name + ` ` + m.value : m.name}\n`).join(""); } /** - * @internal * Compile vertex and fragment source with standard macros, includes, and version header. - * @param engine - Engine instance - * @param macroCollection - Current macro collection - * @param vertexSource - Raw vertex shader source (may contain #include) - * @param fragmentSource - Raw fragment shader source - * @returns Compiled { vertexSource, fragmentSource } ready for ShaderProgram */ static compilePlatformSource( engine: Engine, macroCollection: ShaderMacroCollection, vertexSource: string, - fragmentSource: string - ): { vertexSource: string; fragmentSource: string } { - const isWebGL2 = engine._hardwareRenderer.isWebGL2; + fragmentSource: string, + isGPUInstance: boolean + ): { vertexSource: string; fragmentSource: string; instanceLayout: InstanceBufferLayout | null } { + const rhi = engine._hardwareRenderer; + const isWebGL2 = rhi.isWebGL2; const shaderMacroList = new Array(); ShaderMacro._getMacrosElements(macroCollection, shaderMacroList); shaderMacroList.push(ShaderMacro.getByName(isWebGL2 ? "GRAPHICS_API_WEBGL2" : "GRAPHICS_API_WEBGL1")); - if (engine._hardwareRenderer.canIUse(GLCapabilityType.shaderTextureLod)) { + if (rhi.canIUse(GLCapabilityType.shaderTextureLod)) { shaderMacroList.push(ShaderMacro.getByName("HAS_TEX_LOD")); } - if (engine._hardwareRenderer.canIUse(GLCapabilityType.standardDerivatives)) { + if (rhi.canIUse(GLCapabilityType.standardDerivatives)) { shaderMacroList.push(ShaderMacro.getByName("HAS_DERIVATIVES")); } @@ -55,28 +162,82 @@ export class ShaderFactory { noIncludeVertex = macroStr + noIncludeVertex; noIncludeFrag = macroStr + noIncludeFrag; + let instanceLayout: InstanceBufferLayout | null = null; + if (isGPUInstance) { + const activeMacros = new Set(); + for (let i = 0, len = shaderMacroList.length; i < len; i++) activeMacros.add(shaderMacroList[i].name); + const injected = ShaderFactory.injectInstanceUBO(engine, noIncludeVertex, noIncludeFrag, activeMacros); + noIncludeVertex = injected.vertexSource; + noIncludeFrag = injected.fragmentSource; + instanceLayout = injected.instanceLayout; + } + if (isWebGL2) { noIncludeVertex = ShaderFactory.convertTo300(noIncludeVertex); noIncludeFrag = ShaderFactory.convertTo300(noIncludeFrag, true); } const versionStr = isWebGL2 ? "#version 300 es" : "#version 100"; - const precisionStr = ` -#ifdef GL_FRAGMENT_PRECISION_HIGH - precision highp float; - precision highp int; -#else - precision mediump float; - precision mediump int; -#endif -`; return { vertexSource: `${versionStr}\nprecision highp float;\n${noIncludeVertex}`, - fragmentSource: `${versionStr}\n${isWebGL2 ? "" : ShaderFactory._shaderExtension}${precisionStr}${noIncludeFrag}` + fragmentSource: `${versionStr}\n${isWebGL2 ? "" : ShaderFactory.shaderExtension}${ShaderFactory._precisionStr}${noIncludeFrag}`, + instanceLayout }; } + /** + * Scan VS/FS for renderer-group `uniform` declarations, replace them with a shared + * std140 UBO (instanced array), and emit `#define` remapping so original uniform + * names resolve to `rendererData[instanceID].field`. + */ + static injectInstanceUBO( + engine: Engine, + vertexSource: string, + fragmentSource: string, + activeMacros?: Set + ): { vertexSource: string; fragmentSource: string; instanceLayout: InstanceBufferLayout | null } { + // 1. Scan & strip renderer uniforms from both stages, collect into fieldMap + const fieldMap: Record = Object.create(null); + if (activeMacros) { + vertexSource = ShaderFactory._scanInstanceUniformsWithMacros(vertexSource, fieldMap, activeMacros); + fragmentSource = ShaderFactory._scanInstanceUniformsWithMacros(fragmentSource, fieldMap, activeMacros); + } else { + vertexSource = ShaderFactory._scanInstanceUniforms(vertexSource, fieldMap); + fragmentSource = ShaderFactory._scanInstanceUniforms(fragmentSource, fieldMap); + } + + // Fast empty check without allocating an array + let hasField = false; + for (const _ in fieldMap) { + hasField = true; + break; + } + if (!hasField) return { vertexSource, fragmentSource, instanceLayout: null }; + + // 2. Compute std140 layout (field offsets, struct size, max instance count) + const instanceLayout = ShaderFactory._buildLayout(engine, fieldMap); + + // 3. Generate GLSL UBO block and inject into both stages + const { instanceFields } = instanceLayout; + const uboDecl = ShaderFactory._buildUBODeclaration(instanceLayout); + const fieldDefinesVS = ShaderFactory._buildFieldDefines(instanceFields, "gl_InstanceID"); + const fieldDefinesFS = ShaderFactory._buildFieldDefines(instanceFields, "v_instanceID"); + const derivedDefines = ShaderFactory._derivedDefines; + + const vsBlock = `${uboDecl}flat out int v_instanceID;\n${fieldDefinesVS}\n${derivedDefines}\n`; + const fsBlock = `${uboDecl}flat in int v_instanceID;\n${fieldDefinesFS}\n${derivedDefines}\n`; + + vertexSource = vsBlock + vertexSource; + vertexSource = vertexSource.replace( + /void\s+main\s*\(\s*\)\s*\{/, + "void main() {\n v_instanceID = gl_InstanceID;" + ); + fragmentSource = fsBlock + fragmentSource; + + return { vertexSource, fragmentSource, instanceLayout }; + } + static registerInclude(includeName: string, includeSource: string) { if (ShaderLib[includeName]) { throw `The "${includeName}" shader include already exist`; @@ -93,25 +254,21 @@ export class ShaderFactory { * since `ShaderLab` use the same parsing function but different syntax for `#include` --- `/^[ \t]*#include +"([\w\d.]+)"/gm` */ static parseIncludes(src: string, regex = /^[ \t]*#include +<([\w\d.]+)>/gm) { - function replace(match, slice) { - var replace = ShaderLib[slice]; - - if (replace === undefined) { + return src.replace(regex, (match, slice) => { + const replacement = ShaderLib[slice]; + if (replacement === undefined) { Logger.error(`Shader slice "${match.trim()}" not founded.`); return ""; } - - return ShaderFactory.parseIncludes(replace, regex); - } - - return src.replace(regex, replace); + return ShaderFactory.parseIncludes(replacement, regex); + }); } /** * Convert lower GLSL version to GLSL 300 es. * @param shader - code * @param isFrag - Whether it is a fragment shader. - * */ + */ static convertTo300(shader: string, isFrag?: boolean) { shader = shader.replace(/\bvarying\b/g, isFrag ? "in" : "out"); shader = shader.replace(/\btexture(2D|Cube)\b/g, "texture"); @@ -124,7 +281,7 @@ export class ShaderFactory { if (isFrag) { shader = shader.replace(/\bgl_FragDepthEXT\b/g, "gl_FragDepth"); - if (!ShaderFactory._has300Output(shader)) { + if (!ShaderFactory._has300OutInFragReg.test(shader)) { const isMRT = /\bgl_FragData\[.+?\]/g.test(shader); if (isMRT) { shader = shader.replace(/\bgl_FragColor\b/g, "gl_FragData[0]"); @@ -142,8 +299,162 @@ export class ShaderFactory { return shader; } - private static _has300Output(fragmentShader: string): boolean { - return ShaderFactory._has300OutInFragReg.test(fragmentShader); + private static _scanInstanceUniforms(source: string, fieldMap: Record): string { + const builtinUniforms = ShaderFactory._builtinRendererUniforms; + return source.replace(ShaderFactory._uboUniformRegex, (match, type, name, arraySize) => { + if (type.includes("sampler")) return match; + const isDerived = builtinUniforms[name]; + if (isDerived === undefined && ShaderProperty._getShaderPropertyGroup(name) !== ShaderDataGroup.Renderer) + return match; + if (isDerived) return ""; + // Array uniforms not supported in instancing UBO, keep as regular uniform + if (arraySize) { + Logger.error(`GPU Instancing does not support array uniform "${name}${arraySize}"`); + return match; + } + // ModelMat is affine, store as mat3x4 (3 columns) to save 16 bytes per instance + fieldMap[ShaderProperty.getByName(name)._uniqueId] = + type === "mat4" && name === "renderer_ModelMat" ? "mat3x4" : type; + return ""; + }); + } + + // Matches preprocessor directives at line start. Only `#ifdef / #ifndef / #else / #endif` are + // supported; `#if` with expressions is not recognized (such blocks are treated as always-active). + private static readonly _ifdefRegex = /^[ \t]*#ifdef\s+(\w+)/; + private static readonly _ifndefRegex = /^[ \t]*#ifndef\s+(\w+)/; + private static readonly _elseRegex = /^[ \t]*#else\b/; + private static readonly _endifRegex = /^[ \t]*#endif\b/; + + /** + * Scan with preprocessor awareness, for raw GLSL paths where `#ifdef` blocks are not yet + * expanded. Uniforms inside inactive branches are skipped. + */ + private static _scanInstanceUniformsWithMacros( + source: string, + fieldMap: Record, + activeMacros: Set + ): string { + // Preprocessor branch stack: each frame tracks whether current branch is active + const branchStack: boolean[] = [true]; + const lines = source.split("\n"); + + for (let i = 0, n = lines.length; i < n; i++) { + const line = lines[i]; + + let m = line.match(ShaderFactory._ifdefRegex); + if (m) { + const parentActive = branchStack[branchStack.length - 1]; + branchStack.push(parentActive && activeMacros.has(m[1])); + continue; + } + m = line.match(ShaderFactory._ifndefRegex); + if (m) { + const parentActive = branchStack[branchStack.length - 1]; + branchStack.push(parentActive && !activeMacros.has(m[1])); + continue; + } + if (ShaderFactory._elseRegex.test(line)) { + const parentActive = branchStack.length >= 2 ? branchStack[branchStack.length - 2] : true; + const currentActive = branchStack[branchStack.length - 1]; + branchStack[branchStack.length - 1] = parentActive && !currentActive; + continue; + } + if (ShaderFactory._endifRegex.test(line)) { + if (branchStack.length > 1) branchStack.pop(); + continue; + } + if (!branchStack[branchStack.length - 1]) continue; + + lines[i] = ShaderFactory._scanInstanceUniforms(line, fieldMap); + } + + return lines.join("\n"); + } + + private static _buildLayout(engine: Engine, fieldMap: Record): InstanceBufferLayout { + const maxUBOSize = engine._hardwareRenderer.maxUniformBlockSize; + const std140Map = ShaderFactory._std140TypeInfoMap; + const instanceFields: InstanceFieldInfo[] = []; + let currentOffset = 0; + + const packFuncMap = ShaderFactory._packFuncMap; + const addField = (id: number): void => { + const type = fieldMap[id]; + const info = std140Map[type]; + if (!info) return; + currentOffset = Math.ceil(currentOffset / info.align) * info.align; + instanceFields.push({ + property: ShaderProperty._propertyIdMap[id], + type, + offset: currentOffset, + offsetInElements: currentOffset / 4, + useIntView: type[0] === "i" || type[0] === "u", + pack: packFuncMap[type] + }); + currentOffset += info.size; + }; + + // Priority fields first + const modelMatId = Renderer._worldMatrixProperty._uniqueId; + const layerId = Renderer._rendererLayerProperty._uniqueId; + if (modelMatId in fieldMap) { + addField(modelMatId); + delete fieldMap[modelMatId]; + } + if (layerId in fieldMap) { + addField(layerId); + delete fieldMap[layerId]; + } + + // Remaining fields sorted by id + const keys: number[] = []; + for (const k in fieldMap) keys.push(+k); + keys.sort((a, b) => a - b); + for (let i = 0; i < keys.length; i++) addField(keys[i]); + + const structSize = Math.ceil(currentOffset / 16) * 16; + const instanceMaxCount = Math.floor(maxUBOSize / structSize); + + return { instanceFields, instanceMaxCount, structSize }; + } + + private static _buildUBODeclaration(layout: InstanceBufferLayout): string { + const { instanceFields, instanceMaxCount } = layout; + const structLines: string[] = []; + for (let i = 0; i < instanceFields.length; i++) { + const { type, property } = instanceFields[i]; + structLines.push(` ${type} ${property.name};`); + } + return ( + `#define INSTANCE_MAX_COUNT ${instanceMaxCount}\n` + + `struct RendererInstanceStruct {\n${structLines.join("\n")}\n};\n` + + `layout(std140) uniform ${ShaderFactory.RENDERER_INSTANCE_BLOCK_NAME} {\n` + + ` RendererInstanceStruct rendererData[INSTANCE_MAX_COUNT];\n};\n` + ); + } + + private static _buildFieldDefines(fields: InstanceFieldInfo[], idExpr: string): string { + const accessor = `rendererData[${idExpr}]`; + const lines: string[] = []; + for (let i = 0; i < fields.length; i++) { + const { type, property } = fields[i]; + const n = property.name; + if (type === "mat3x4") { + // mat3x4 stores 3 transposed rows; reconstruct column-major mat4 with row3=(0,0,0,1) + const m = `${accessor}.${n}`; + lines.push( + `#define ${n} mat4(` + + `vec4(${m}[0].x,${m}[1].x,${m}[2].x,0.0),` + + `vec4(${m}[0].y,${m}[1].y,${m}[2].y,0.0),` + + `vec4(${m}[0].z,${m}[1].z,${m}[2].z,0.0),` + + `vec4(${m}[0].w,${m}[1].w,${m}[2].w,1.0))` + ); + } else { + lines.push(`#define ${n} ${accessor}.${n}`); + } + } + return lines.join("\n"); } private static _replaceMRTShader(shader: string, result: string[]): string { @@ -166,3 +477,24 @@ export class ShaderFactory { return shader; } } + +export interface InstanceFieldInfo { + property: ShaderProperty; + type: string; + offset: number; + /** offset / 4, precomputed to avoid repeated division in upload loop */ + offsetInElements: number; + useIntView: boolean; + pack: InstancePackFunc; +} + +/** + * @internal + */ +export interface InstanceBufferLayout { + instanceFields: InstanceFieldInfo[]; + instanceMaxCount: number; + structSize: number; +} + +type InstancePackFunc = (view: Float32Array | Int32Array, offset: number, value: any) => void; diff --git a/packages/core/src/shaderlib/extra/depthOnly.vs.glsl b/packages/core/src/shaderlib/extra/depthOnly.vs.glsl index 06ea2dc057..ecaea3e6ce 100644 --- a/packages/core/src/shaderlib/extra/depthOnly.vs.glsl +++ b/packages/core/src/shaderlib/extra/depthOnly.vs.glsl @@ -2,8 +2,6 @@ #include #include #include -uniform mat4 camera_VPMat; - void main() { diff --git a/packages/core/src/shaderlib/extra/shadow-map.vs.glsl b/packages/core/src/shaderlib/extra/shadow-map.vs.glsl index fae6a4b849..2da9dc1092 100644 --- a/packages/core/src/shaderlib/extra/shadow-map.vs.glsl +++ b/packages/core/src/shaderlib/extra/shadow-map.vs.glsl @@ -3,7 +3,6 @@ #include #include #include -uniform mat4 camera_VPMat; uniform vec2 scene_ShadowBias; // x: depth bias, y: normal bias uniform vec3 scene_LightDirection; @@ -26,7 +25,7 @@ void main() { #include #include #include - + vec4 positionWS = renderer_ModelMat * position; positionWS.xyz = applyShadowBias(positionWS.xyz); diff --git a/packages/core/src/shaderlib/extra/skybox.vs.glsl b/packages/core/src/shaderlib/extra/skybox.vs.glsl index 54c7185dd8..de9692f754 100644 --- a/packages/core/src/shaderlib/extra/skybox.vs.glsl +++ b/packages/core/src/shaderlib/extra/skybox.vs.glsl @@ -1,7 +1,5 @@ #include -uniform mat4 camera_VPMat; - varying vec3 v_cubeUV; uniform float material_Rotation; diff --git a/packages/core/src/shaderlib/normal_vert.glsl b/packages/core/src/shaderlib/normal_vert.glsl index 096a4595d1..906be70ef7 100644 --- a/packages/core/src/shaderlib/normal_vert.glsl +++ b/packages/core/src/shaderlib/normal_vert.glsl @@ -1,9 +1,10 @@ #ifndef MATERIAL_OMIT_NORMAL #ifdef RENDERER_HAS_NORMAL - v_normal = normalize( mat3(renderer_NormalMat) * normal ); + mat3 normalMat = mat3(renderer_NormalMat); + v_normal = normalize( normalMat * normal ); #if defined(RENDERER_HAS_TANGENT) && ( defined(MATERIAL_HAS_NORMALTEXTURE) || defined(MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE) || defined(MATERIAL_ENABLE_ANISOTROPY) ) - vec3 tangentW = normalize( mat3(renderer_NormalMat) * tangent.xyz ); + vec3 tangentW = normalize( normalMat * tangent.xyz ); vec3 bitangentW = cross( v_normal, tangentW ) * tangent.w; v_TBN = mat3( tangentW, bitangentW, v_normal ); diff --git a/packages/core/src/shaderlib/transform_declare.glsl b/packages/core/src/shaderlib/transform_declare.glsl index 00e1d5edba..86048dcbde 100644 --- a/packages/core/src/shaderlib/transform_declare.glsl +++ b/packages/core/src/shaderlib/transform_declare.glsl @@ -1,7 +1,8 @@ -uniform mat4 renderer_LocalMat; -uniform mat4 renderer_ModelMat; uniform mat4 camera_ViewMat; uniform mat4 camera_ProjMat; +uniform mat4 camera_VPMat; + +uniform mat4 renderer_ModelMat; uniform mat4 renderer_MVMat; uniform mat4 renderer_MVPMat; uniform mat4 renderer_NormalMat; \ No newline at end of file diff --git a/packages/core/src/trail/TrailRenderer.ts b/packages/core/src/trail/TrailRenderer.ts index b8d97f4365..6485d658ca 100644 --- a/packages/core/src/trail/TrailRenderer.ts +++ b/packages/core/src/trail/TrailRenderer.ts @@ -1,7 +1,6 @@ import { BoundingBox, Color, Vector2, Vector3, Vector4 } from "@galacean/engine-math"; import { Entity } from "../Entity"; import { RenderContext } from "../RenderPipeline/RenderContext"; -import { RenderElement } from "../RenderPipeline/RenderElement"; import { Renderer, RendererUpdateFlags } from "../Renderer"; import { deepClone, ignoreClone } from "../clone/CloneManager"; import { Buffer } from "../graphic/Buffer"; @@ -232,8 +231,9 @@ export class TrailRenderer extends Renderer { const { _firstActiveElement: firstActive, _firstFreeElement: firstFree } = this; - const renderElement = this._engine._renderElementPool.get(); - renderElement.set(this.priority, this._distanceForSort); + const priority = this.priority; + const distanceForSort = this._distanceForSort; + const renderPipeline = context.camera._renderPipeline; // spansBoundary: active points cross buffer end // wrapped: spansBoundary AND point 0 has been written (need bridge + second segment) @@ -241,13 +241,19 @@ export class TrailRenderer extends Renderer { const wrapped = spansBoundary && firstFree > 0; const mainCount = (spansBoundary ? this._currentPointCapacity - firstActive + (wrapped ? 1 : 0) : firstFree - firstActive) * 2; - this._addSubRenderElement(renderElement, material, this._mainSubPrimitive, firstActive * 2, mainCount); + this._addRenderElement( + context, + material, + this._mainSubPrimitive, + firstActive * 2, + mainCount, + priority, + distanceForSort + ); if (wrapped) { - this._addSubRenderElement(renderElement, material, this._wrapSubPrimitive, 0, firstFree * 2); + this._addRenderElement(context, material, this._wrapSubPrimitive, 0, firstFree * 2, priority, distanceForSort); } - - context.camera._renderPipeline.pushRenderElement(context, renderElement); } protected override _updateBounds(worldBounds: BoundingBox): void { @@ -588,18 +594,22 @@ export class TrailRenderer extends Renderer { this._bufferResized = false; } - private _addSubRenderElement( - renderElement: RenderElement, + private _addRenderElement( + context: RenderContext, material: Material, subPrimitive: SubPrimitive, start: number, - count: number + count: number, + priority: number, + distanceForSort: number ): void { subPrimitive.start = start; subPrimitive.count = count; - const subRenderElement = this._engine._subRenderElementPool.get(); - subRenderElement.set(this, material, this._primitive, subPrimitive); - renderElement.addSubRenderElement(subRenderElement); + const renderElement = this._engine._renderElementPool.get(); + renderElement.set(this, material, this._primitive, subPrimitive); + renderElement.priority = priority; + renderElement.distanceForSort = distanceForSort; + context.camera._renderPipeline.pushRenderElement(context, renderElement); } @ignoreClone diff --git a/packages/core/src/ui/IUICanvas.ts b/packages/core/src/ui/IUICanvas.ts index 3139b6dba8..e90e209aa2 100644 --- a/packages/core/src/ui/IUICanvas.ts +++ b/packages/core/src/ui/IUICanvas.ts @@ -10,7 +10,7 @@ export interface IUICanvas { entity: Entity; sortOrder: number; _canvasIndex: number; - _renderElement: RenderElement; + _renderElements: RenderElement[]; _canRender(camera: Camera): boolean; _prepareRender(renderContext: RenderContext): void; } diff --git a/packages/core/src/ui/UIUtils.ts b/packages/core/src/ui/UIUtils.ts index c57c8bdf1f..a6f7822a03 100644 --- a/packages/core/src/ui/UIUtils.ts +++ b/packages/core/src/ui/UIUtils.ts @@ -44,7 +44,10 @@ export class UIUtils { renderContext.applyVirtualCamera(virtualCamera, false); uiRenderQueue.rendererUpdateFlag |= ContextRendererUpdateFlag.ProjectionMatrix; uiCanvas._prepareRender(renderContext); - uiRenderQueue.pushRenderElement(uiCanvas._renderElement); + const curElements = uiCanvas._renderElements; + for (let j = 0, m = curElements.length; j < m; j++) { + uiRenderQueue.pushRenderElement(curElements[j]); + } uiRenderQueue.batch(batcherManager); batcherManager.uploadBuffer(); uiRenderQueue.render(renderContext, "Forward"); diff --git a/packages/design/package.json b/packages/design/package.json index 86e73a7c33..373541de5a 100644 --- a/packages/design/package.json +++ b/packages/design/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-design", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" diff --git a/packages/design/src/renderingHardwareInterface/IHardwareRenderer.ts b/packages/design/src/renderingHardwareInterface/IHardwareRenderer.ts index bccb92bf65..193ef7a558 100644 --- a/packages/design/src/renderingHardwareInterface/IHardwareRenderer.ts +++ b/packages/design/src/renderingHardwareInterface/IHardwareRenderer.ts @@ -2,6 +2,8 @@ * Hardware graphics API renderer. */ export interface IHardwareRenderer { + readonly maxUniformBlockSize: number; + // todo: implements [key: string]: any; } diff --git a/packages/galacean/package.json b/packages/galacean/package.json index a2bf568984..de2435f362 100644 --- a/packages/galacean/package.json +++ b/packages/galacean/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" diff --git a/packages/loader/package.json b/packages/loader/package.json index 61e5825838..4c22a84ca4 100644 --- a/packages/loader/package.json +++ b/packages/loader/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-loader", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" diff --git a/packages/loader/src/AudioLoader.ts b/packages/loader/src/AudioLoader.ts index 24c2b788c9..7233fb8e0f 100644 --- a/packages/loader/src/AudioLoader.ts +++ b/packages/loader/src/AudioLoader.ts @@ -9,7 +9,7 @@ import { ResourceManager, resourceLoader } from "@galacean/engine-core"; -@resourceLoader(AssetType.Audio, ["mp3", "ogg", "wav"]) +@resourceLoader(AssetType.Audio, ["mp3", "ogg", "wav", "audio"]) class AudioLoader extends Loader { load(item: LoadItem, resourceManager: ResourceManager): AssetPromise { return new AssetPromise((resolve, reject) => { diff --git a/packages/loader/src/SpriteAtlasLoader.ts b/packages/loader/src/SpriteAtlasLoader.ts index 0bada4b334..c5a1d6a550 100644 --- a/packages/loader/src/SpriteAtlasLoader.ts +++ b/packages/loader/src/SpriteAtlasLoader.ts @@ -102,7 +102,7 @@ class SpriteAtlasLoader extends Loader { const { x: offsetLeft, y: offsetTop, z: offsetRight, w: offsetBottom } = atlasRegionOffset; sprite.atlasRegionOffset.set(offsetLeft * invW, offsetTop * invH, offsetRight * invW, offsetBottom * invH); } - config.atlasRotated && (sprite.atlasRotated = true); + sprite.atlasRotated = config.atlasRotated ?? false; } width === undefined || (sprite.width = width); height === undefined || (sprite.height = height); diff --git a/packages/loader/src/gltf/parser/GLTFParserContext.ts b/packages/loader/src/gltf/parser/GLTFParserContext.ts index 83f9f65124..b549da5ca2 100644 --- a/packages/loader/src/gltf/parser/GLTFParserContext.ts +++ b/packages/loader/src/gltf/parser/GLTFParserContext.ts @@ -116,13 +116,13 @@ export class GLTFParserContext { return AssetPromise.all([ this.get(GLTFParserType.Validator), + this.get(GLTFParserType.Scene), this.get(GLTFParserType.Texture), this.get(GLTFParserType.Material), this.get(GLTFParserType.Mesh), this.get(GLTFParserType.Skin), this.get(GLTFParserType.Animation), - this.get(GLTFParserType.AnimatorController), - this.get(GLTFParserType.Scene) + this.get(GLTFParserType.AnimatorController) ]).then(() => { const glTFResource = this.glTFResource; const animatorController = glTFResource.animatorController; diff --git a/packages/loader/src/gltf/parser/GLTFSceneParser.ts b/packages/loader/src/gltf/parser/GLTFSceneParser.ts index 6517356c97..b74424d2e6 100644 --- a/packages/loader/src/gltf/parser/GLTFSceneParser.ts +++ b/packages/loader/src/gltf/parser/GLTFSceneParser.ts @@ -31,18 +31,14 @@ export class GLTFSceneParser extends GLTFParser { const sceneNodes = sceneInfo.nodes || []; let sceneRoot: Entity; - if (sceneNodes.length === 1) { - sceneRoot = context.get(GLTFParserType.Entity, sceneNodes[0]); - } else { - sceneRoot = new Entity(engine, "GLTF_ROOT"); - // @ts-ignore - sceneRoot._markAsTemplate(glTFResource); - for (let i = 0; i < sceneNodes.length; i++) { - const childEntity = context.get(GLTFParserType.Entity, sceneNodes[i]); - sceneRoot.addChild(childEntity); - } + sceneRoot = new Entity(engine, "GLTF_ROOT"); + // @ts-ignore + sceneRoot._markAsTemplate(glTFResource); + for (let i = 0; i < sceneNodes.length; i++) { + sceneRoot.addChild(context.get(GLTFParserType.Entity, sceneNodes[i])); } + (glTFResource._sceneRoots ||= [])[index] = sceneRoot; if (isDefaultScene) { glTFResource._defaultSceneRoot = sceneRoot; } diff --git a/packages/loader/src/gltf/parser/GLTFSkinParser.ts b/packages/loader/src/gltf/parser/GLTFSkinParser.ts index 7c1580e4ca..978dd4780e 100644 --- a/packages/loader/src/gltf/parser/GLTFSkinParser.ts +++ b/packages/loader/src/gltf/parser/GLTFSkinParser.ts @@ -39,7 +39,7 @@ export class GLTFSkinParser extends GLTFParser { const rootBone = entities[skeleton]; skin.rootBone = rootBone; } else { - const rootBone = this._findSkeletonRootBone(joints, entities); + const rootBone = this._findSceneRootBone(context, joints, entities) ?? this._findSkeletonRootBone(joints, entities); if (rootBone) { skin.rootBone = rootBone; } else { @@ -53,6 +53,49 @@ export class GLTFSkinParser extends GLTFParser { return AssetPromise.resolve(skinPromise); } + private _findSceneRootBone(context: GLTFParserContext, joints: number[], entities: Entity[]): Entity | null { + const { glTF, glTFResource } = context; + const scenes = glTF.scenes; + const sceneRoots = glTFResource._sceneRoots; + + if (!scenes?.length || !sceneRoots?.length) { + return null; + } + + for (let i = 0, n = scenes.length; i < n; i++) { + const sceneNodes = scenes[i].nodes ?? []; + if (sceneNodes.length <= 1) { + continue; + } + + const sceneRoot = sceneRoots[i]; + if (!sceneRoot) { + continue; + } + + const sceneRootChildren = new Set(sceneNodes.map((nodeIndex) => entities[nodeIndex])); + let allJointsUnderSceneRoot = true; + + for (let j = 0, m = joints.length; j < m; j++) { + let entity = entities[joints[j]]; + while (entity?.parent) { + entity = entity.parent; + } + + if (!sceneRootChildren.has(entity)) { + allJointsUnderSceneRoot = false; + break; + } + } + + if (allJointsUnderSceneRoot) { + return sceneRoot; + } + } + + return null; + } + private _findSkeletonRootBone(joints: number[], entities: Entity[]): Entity { const paths = >{}; for (const index of joints) { diff --git a/packages/loader/src/resource-deserialize/resources/parser/ReflectionParser.ts b/packages/loader/src/resource-deserialize/resources/parser/ReflectionParser.ts index e79ea06864..fe92bbcf6a 100644 --- a/packages/loader/src/resource-deserialize/resources/parser/ReflectionParser.ts +++ b/packages/loader/src/resource-deserialize/resources/parser/ReflectionParser.ts @@ -125,7 +125,14 @@ export class ReflectionParser { if (!entity) return Promise.resolve(null); const type = Loader.getClass(value.componentType); if (!type) return Promise.resolve(null); - return Promise.resolve(entity.getComponents(type, [])[value.componentIndex] ?? null); + // Try direct components first, fallback to children search (for GLB clone entities + // where the component lives on a child entity inside the clone) + const direct = entity.getComponents(type, []); + const result = direct[value.componentIndex]; + if (result) return Promise.resolve(result); + const includeChildren: any[] = []; + entity.getComponentsIncludeChildren(type, includeChildren); + return Promise.resolve(includeChildren[value.componentIndex] ?? null); } else if (ReflectionParser._isEntityRef(value)) { return Promise.resolve(this._resolveEntityByPath(value.entityPath)); } else if (ReflectionParser._isSignalRef(value)) { diff --git a/packages/math/package.json b/packages/math/package.json index 42a52983a1..d197caf7e2 100644 --- a/packages/math/package.json +++ b/packages/math/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-math", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" diff --git a/packages/physics-lite/package.json b/packages/physics-lite/package.json index 30c4065480..4296c0d9d4 100644 --- a/packages/physics-lite/package.json +++ b/packages/physics-lite/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-physics-lite", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" diff --git a/packages/physics-physx/libs/physx.release.js b/packages/physics-physx/libs/physx.release.js index 426e4ca185..f816e9dce3 100644 --- a/packages/physics-physx/libs/physx.release.js +++ b/packages/physics-physx/libs/physx.release.js @@ -1,2 +1,2 @@ -var PHYSX=(()=>{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["P"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return "https://mdn.alipayobjects.com/rms/afts/file/A*RkDQSaUOhxsAAAAAgCAAAAgAehQnAQ/physx.release.wasm"}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var __abort_js=()=>abort("");var createNamedFunction=(name,func)=>Object.defineProperty(func,"name",{value:name});var emval_freelist=[];var emval_handles=[0,1,,1,null,1,true,1,false,1];var BindingError=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};var throwBindingError=message=>{throw new BindingError(message)};var Emval={toValue:handle=>{if(!handle){throwBindingError(`Cannot use deleted val. handle = ${handle}`)}return emval_handles[handle]},toHandle:value=>{switch(value){case undefined:return 2;case null:return 4;case true:return 6;case false:return 8;default:{const handle=emval_freelist.pop()||emval_handles.length;emval_handles[handle]=value;emval_handles[handle+1]=1;return handle}}}};class PureVirtualError extends Error{}var AsciiToString=ptr=>{var str="";while(1){var ch=HEAPU8[ptr++];if(!ch)return str;str+=String.fromCharCode(ch)}};var registeredInstances={};var getBasestPointer=(class_,ptr)=>{if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr};var registerInheritedInstance=(class_,ptr,instance)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){throwBindingError(`Tried to register registered instance: ${ptr}`)}else{registeredInstances[ptr]=instance}};var registeredTypes={};var getTypeName=type=>{var ptr=___getTypeName(type);var rv=AsciiToString(ptr);_free(ptr);return rv};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`)}return impl};var unregisterInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){delete registeredInstances[ptr]}else{throwBindingError(`Tried to unregister unregistered instance: ${ptr}`)}};var detachFinalizer=handle=>{};var finalizationRegistry=false;var runDestructor=$$=>{if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}};var releaseClassHandle=$$=>{$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}};var attachFinalizer=handle=>{if(!globalThis.FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$};finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)};var __embind_create_inheriting_constructor=(constructorName,wrapperType,properties)=>{constructorName=AsciiToString(constructorName);wrapperType=requireRegisteredType(wrapperType,"wrapper");properties=Emval.toValue(properties);var registeredClass=wrapperType.registeredClass;var wrapperPrototype=registeredClass.instancePrototype;var baseClass=registeredClass.baseClass;var baseClassPrototype=baseClass.instancePrototype;var baseConstructor=registeredClass.baseClass.constructor;var ctor=createNamedFunction(constructorName,function(...args){for(var name of registeredClass.baseClass.pureVirtualFunctions){if(this[name]===baseClassPrototype[name]){throw new PureVirtualError(`Pure virtual function ${name} must be implemented in JavaScript`)}}Object.defineProperty(this,"__parent",{value:wrapperPrototype});this["__construct"](...args)});wrapperPrototype["__construct"]=function __construct(...args){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __construct")}var inner=baseConstructor["implement"](this,...args);detachFinalizer(inner);var $$=inner.$$;inner["notifyOnDestruction"]();$$.preservePointerOnDelete=true;Object.defineProperties(this,{$$:{value:$$}});attachFinalizer(this);registerInheritedInstance(registeredClass,$$.ptr,this)};wrapperPrototype["__destruct"]=function __destruct(){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __destruct")}detachFinalizer(this);unregisterInheritedInstance(registeredClass,this.$$.ptr)};ctor.prototype=Object.create(wrapperPrototype);Object.assign(ctor.prototype,properties);return Emval.toHandle(ctor)};var structRegistrations={};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function readPointer(pointer){return this.fromWireType(HEAPU32[pointer>>2])}var awaitingDependencies={};var typeDependencies={};var InternalError=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};var throwInternalError=message=>{throw new InternalError(message)};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(type=>typeDependencies[type]=dependentTypes);function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}}if(0===unregisteredTypes.length){onComplete(typeConverters)}};var __embind_finalize_value_object=structType=>{var reg=structRegistrations[structType];delete structRegistrations[structType];var rawConstructor=reg.rawConstructor;var rawDestructor=reg.rawDestructor;var fieldRecords=reg.fields;var fieldTypes=fieldRecords.map(field=>field.getterReturnType).concat(fieldRecords.map(field=>field.setterArgumentType));whenDependentTypesAreResolved([structType],fieldTypes,fieldTypes=>{var fields={};for(var[i,field]of fieldRecords.entries()){const getterReturnType=fieldTypes[i];const getter=field.getter;const getterContext=field.getterContext;const setterArgumentType=fieldTypes[i+fieldRecords.length];const setter=field.setter;const setterContext=field.setterContext;fields[field.fieldName]={read:ptr=>getterReturnType.fromWireType(getter(getterContext,ptr)),write:(ptr,o)=>{var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,o));runDestructors(destructors)},optional:getterReturnType.optional}}return[{name:reg.name,fromWireType:ptr=>{var rv={};for(var i in fields){rv[i]=fields[i].read(ptr)}rawDestructor(ptr);return rv},toWireType:(destructors,o)=>{for(var fieldName in fields){if(!(fieldName in o)&&!fields[fieldName].optional){throw new TypeError(`Missing field: "${fieldName}"`)}}var ptr=rawConstructor();for(fieldName in fields){fields[fieldName].write(ptr,o[fieldName])}if(destructors!==null){destructors.push(rawDestructor,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction:rawDestructor}]})};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){return sharedRegisterType(rawType,registeredInstance,options)}var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>HEAP8[pointer]:pointer=>HEAPU8[pointer];case 2:return signed?pointer=>HEAP16[pointer>>1]:pointer=>HEAPU16[pointer>>1];case 4:return signed?pointer=>HEAP32[pointer>>2]:pointer=>HEAPU32[pointer>>2];case 8:return signed?pointer=>HEAP64[pointer>>3]:pointer=>HEAPU64[pointer>>3];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_bigint=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0n;let fromWireType=value=>value;if(isUnsignedType){const bitSize=size*8;fromWireType=value=>BigInt.asUintN(bitSize,value);maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>{if(typeof value=="number"){value=BigInt(value)}return value},readValueFromPointer:integerReadValueFromPointer(name,size,!isUnsignedType),destructorFunction:null})};var __embind_register_bool=(rawType,name,trueValue,falseValue)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:function(wt){return!!wt},toWireType:function(destructors,o){return o?trueValue:falseValue},readValueFromPointer:function(pointer){return this.fromWireType(HEAPU8[pointer])},destructorFunction:null})};var shallowCopyInternalPointer=o=>({count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType});var throwInstanceAlreadyDeleted=obj=>{function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")};var deletionQueue=[];var flushPendingDeletes=()=>{while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}};var delayFunction;var init_ClassHandle=()=>{let proto=ClassHandle.prototype;Object.assign(proto,{isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;other.$$=other.$$;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right},clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}},delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}},isDeleted(){return!this.$$.ptr},deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}});const symbolDispose=Symbol.dispose;if(symbolDispose){proto[symbolDispose]=proto["delete"]}};function ClassHandle(){}var registeredPointers={};var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(...args){if(!proto[methodName].overloadTable.hasOwnProperty(args.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[args.length].apply(this,args)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module[name].overloadTable.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}var upcastPointer=(ptr,ptrClass,desiredClass)=>{while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr};var embindRepr=v=>{if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}};function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle||!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(()=>clonedHandle["delete"]()));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupported sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}var downcastPointer=(ptr,ptrClass,desiredClass)=>{if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)};var getInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]};var makeClassHandle=(prototype,record)=>{if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record,writable:true}}))};function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}var init_RegisteredPointer=()=>{Object.assign(RegisteredPointer.prototype,{getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr},destructor(ptr){this.rawDestructor?.(ptr)},readValueFromPointer:readPointer,fromWireType:RegisteredPointer_fromWireType})};function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this.toWireType=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this.toWireType=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this.toWireType=genericPointerToWireType}}var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistent public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var wasmTableMirror=[];var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var embind__requireFunction=(signature,rawFunction,isAsync=false)=>{signature=AsciiToString(signature);function makeDynCaller(){var rtn=getWasmTableEntry(rawFunction);return rtn}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};class UnboundTypeError extends Error{}var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};var __embind_register_class=(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor)=>{name=AsciiToString(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);upcast&&=embind__requireFunction(upcastSignature,upcast);downcast&&=embind__requireFunction(downcastSignature,downcast);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],base=>{base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(name,function(...args){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError(`Use 'new' to construct ${name}`)}if(undefined===registeredClass.constructor_body){throw new BindingError(`${name} has no accessible constructor`)}var body=registeredClass.constructor_body[args.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,args)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){registeredClass.baseClass.__derivedClasses??=[];registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})};function usesDestructorStack(argTypes){for(var i=1;i{var array=[];for(var i=0;i>2])}return array};var getFunctionName=signature=>{signature=signature.trim();const argsIndex=signature.indexOf("(");if(argsIndex===-1)return signature;return signature.slice(0,argsIndex)};var __embind_register_class_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}var proto=classType.registeredClass.constructor;if(undefined===proto[methodName]){unboundTypesHandler.argCount=argCount-1;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-1]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));var func=craftInvokerFunction(humanName,invokerArgsArray,null,rawInvoker,fn,isAsync);if(undefined===proto[methodName].overloadTable){func.argCount=argCount-1;proto[methodName]=func}else{proto[methodName].overloadTable[argCount-1]=func}if(classType.registeredClass.__derivedClasses){for(const derivedClass of classType.registeredClass.__derivedClasses){if(!derivedClass.constructor.hasOwnProperty(methodName)){derivedClass.constructor[methodName]=func}}}return[]});return[]})};var __embind_register_class_constructor=(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`constructor ${classType.name}`;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`)}classType.registeredClass.constructor_body[argCount-1]=()=>{throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`,rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{argTypes.splice(1,0,null);classType.registeredClass.constructor_body[argCount-1]=craftInvokerFunction(humanName,argTypes,null,invoker,rawConstructor);return[]});return[]})};var __embind_register_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context,isAsync);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]});return[]})};var validateThis=(this_,classType,humanName)=>{if(!(this_ instanceof Object)){throwBindingError(`${humanName} with invalid "this": ${this_}`)}if(!(this_ instanceof classType.registeredClass.constructor)){throwBindingError(`${humanName} incompatible with "this" of type ${this_.constructor.name}`)}if(!this_.$$.ptr){throwBindingError(`cannot call emscripten binding method ${humanName} on deleted object`)}return upcastPointer(this_.$$.ptr,this_.$$.ptrType.registeredClass,classType.registeredClass)};var __embind_register_class_property=(classType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{fieldName=AsciiToString(fieldName);getter=embind__requireFunction(getterSignature,getter);whenDependentTypesAreResolved([],[classType],classType=>{classType=classType[0];var humanName=`${classType.name}.${fieldName}`;var desc={get(){throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])},enumerable:true,configurable:true};if(setter){desc.set=()=>throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])}else{desc.set=v=>throwBindingError(humanName+" is a read-only property")}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);whenDependentTypesAreResolved([],setter?[getterReturnType,setterArgumentType]:[getterReturnType],types=>{var getterReturnType=types[0];var desc={get(){var ptr=validateThis(this,classType,humanName+" getter");return getterReturnType.fromWireType(getter(getterContext,ptr))},enumerable:true};if(setter){setter=embind__requireFunction(setterSignature,setter);var setterArgumentType=types[1];desc.set=function(v){var ptr=validateThis(this,classType,humanName+" setter");var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,v));runDestructors(destructors)}}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);return[]});return[]})};var __embind_register_constant=(name,type,value)=>{name=AsciiToString(name);whenDependentTypesAreResolved([],[type],type=>{type=type[0];Module[name]=type.fromWireType(value);return[]})};var __emval_decref=handle=>{if(handle>9&&0===--emval_handles[handle+1]){emval_handles[handle]=undefined;emval_freelist.push(handle)}};var EmValType={name:"emscripten::val",fromWireType:handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},toWireType:(destructors,value)=>Emval.toHandle(value),readValueFromPointer:readPointer,destructorFunction:null};var __embind_register_emval=rawType=>registerType(rawType,EmValType);var enumReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?function(pointer){return this.fromWireType(HEAP8[pointer])}:function(pointer){return this.fromWireType(HEAPU8[pointer])};case 2:return signed?function(pointer){return this.fromWireType(HEAP16[pointer>>1])}:function(pointer){return this.fromWireType(HEAPU16[pointer>>1])};case 4:return signed?function(pointer){return this.fromWireType(HEAP32[pointer>>2])}:function(pointer){return this.fromWireType(HEAPU32[pointer>>2])};default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};function getEnumValueType(rawValueType){return rawValueType===0?"object":rawValueType===1?"number":"string"}var __embind_register_enum=(rawType,name,size,isSigned,rawValueType)=>{name=AsciiToString(name);const valueType=getEnumValueType(rawValueType);switch(valueType){case"object":{function ctor(){}ctor.values={};registerType(rawType,{name,constructor:ctor,valueType,fromWireType:function(c){return this.constructor.values[c]},toWireType:(destructors,c)=>c.value,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor);break}case"number":{var keysMap={};registerType(rawType,{name,keysMap,valueType,fromWireType:c=>c,toWireType:(destructors,c)=>c,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}case"string":{var valuesMap={};var reverseMap={};var keysMap={};registerType(rawType,{name,valuesMap,reverseMap,keysMap,valueType,fromWireType:function(c){return this.reverseMap[c]},toWireType:function(destructors,c){return this.valuesMap[c]},readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}}};var __embind_register_enum_value=(rawEnumType,name,enumValue)=>{var enumType=requireRegisteredType(rawEnumType,"enum");name=AsciiToString(name);switch(enumType.valueType){case"object":{var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(`${enumType.name}_${name}`,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value;break}case"number":{enumType.keysMap[name]=enumValue;break}case"string":{enumType.valuesMap[name]=enumValue;enumType.reverseMap[enumValue]=name;enumType.keysMap[name]=name;break}}};var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this.fromWireType(HEAPF32[pointer>>2])};case 8:return function(pointer){return this.fromWireType(HEAPF64[pointer>>3])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=(rawType,name,size)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:value=>value,toWireType:(destructors,value)=>value,readValueFromPointer:floatReadValueFromPointer(name,size),destructorFunction:null})};var __embind_register_function=(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=AsciiToString(name);name=getFunctionName(name);rawInvoker=embind__requireFunction(signature,rawInvoker,isAsync);exposePublicSymbol(name,function(){throwUnboundTypeError(`Cannot call ${name} due to unbound types`,argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn,isAsync),argCount-1);return[]})};var __embind_register_integer=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0;let fromWireType=value=>value;if(isUnsignedType){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift;maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>value,readValueFromPointer:integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})};var installIndexedIterator=(proto,sizeMethodName,getMethodName)=>{const makeIterator=(size,getValue)=>{let index=0;return{next(){if(index>=size){return{done:true}}const current=index;index++;const value=getValue(current);return{value,done:false}},[Symbol.iterator](){return this}}};if(!proto[Symbol.iterator]){proto[Symbol.iterator]=function(){const size=this[sizeMethodName]();return makeIterator(size,i=>this[getMethodName](i))}}};var __embind_register_iterable=(rawClassType,rawElementType,sizeMethodName,getMethodName)=>{sizeMethodName=AsciiToString(sizeMethodName);getMethodName=AsciiToString(getMethodName);whenDependentTypesAreResolved([],[rawClassType,rawElementType],types=>{const classType=types[0];installIndexedIterator(classType.registeredClass.instancePrototype,sizeMethodName,getMethodName);return[]})};var __embind_register_memory_view=(rawType,dataTypeIndex,name)=>{var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=HEAPU32[handle>>2];var data=HEAPU32[handle+4>>2];return new TA(HEAP8.buffer,data,size)}name=AsciiToString(name);registerType(rawType,{name,fromWireType:decodeMemoryView,readValueFromPointer:decodeMemoryView},{ignoreDuplicateRegistrations:true})};var EmValOptionalType=Object.assign({optional:true},EmValType);var __embind_register_optional=(rawOptionalType,rawType)=>{registerType(rawOptionalType,EmValOptionalType)};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var UTF8Decoder=globalThis.TextDecoder&&new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var __embind_register_std_string=(rawType,name)=>{name=AsciiToString(name);var stdStringIsUTF8=true;registerType(rawType,{name,fromWireType(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){str=UTF8ToString(payload,length,true)}else{str="";for(var i=0;i>2]=length;if(valueIsOfTypeString){if(stdStringIsUTF8){stringToUTF8(value,ptr,length+1)}else{for(var i=0;i255){_free(base);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}}else{HEAPU8.set(value,ptr)}if(destructors!==null){destructors.push(_free,base)}return base},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var UTF16Decoder=globalThis.TextDecoder?new TextDecoder("utf-16le"):undefined;var UTF16ToString=(ptr,maxBytesToRead,ignoreNul)=>{var idx=ptr>>1;var endIdx=findStringEnd(HEAPU16,idx,maxBytesToRead/2,ignoreNul);if(endIdx-idx>16&&UTF16Decoder)return UTF16Decoder.decode(HEAPU16.subarray(idx,endIdx));var str="";for(var i=idx;i{maxBytesToWrite??=2147483647;if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead,ignoreNul)=>{var str="";var startIdx=ptr>>2;for(var i=0;!(i>=maxBytesToRead/4);i++){var utf32=HEAPU32[startIdx+i];if(!utf32&&!ignoreNul)break;str+=String.fromCodePoint(utf32)}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i65535){i++}HEAP32[outPtr>>2]=codePoint;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i65535){i++}len+=4}return len};var __embind_register_std_wstring=(rawType,charSize,name)=>{name=AsciiToString(name);var decodeString,encodeString,lengthBytesUTF;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16}else{decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32}registerType(rawType,{name,fromWireType:value=>{var length=HEAPU32[value>>2];var str=decodeString(value+4,length*charSize,true);_free(value);return str},toWireType:(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length/charSize;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var __embind_register_value_object=(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor)=>{structRegistrations[rawType]={name:AsciiToString(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}};var __embind_register_value_object_field=(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{structRegistrations[structType].fields.push({fieldName:AsciiToString(fieldName),getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext,setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext})};var __embind_register_void=(rawType,name)=>{name=AsciiToString(name);registerType(rawType,{isVoid:true,name,fromWireType:()=>undefined,toWireType:(destructors,o)=>undefined})};var runtimeKeepaliveCounter=0;var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var emval_methodCallers=[];var emval_addMethodCaller=caller=>{var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id};var emval_lookupTypes=(argCount,argTypes)=>{var a=new Array(argCount);for(var i=0;i>2],`parameter ${i}`)}return a};var emval_returnValue=(toReturnWire,destructorsRef,handle)=>{var destructors=[];var result=toReturnWire(destructors,handle);if(destructors.length){HEAPU32[destructorsRef>>2]=Emval.toHandle(destructors)}return result};var emval_symbols={};var getStringOrSymbol=address=>{var symbol=emval_symbols[address];if(symbol===undefined){return AsciiToString(address)}return symbol};var __emval_create_invoker=(argCount,argTypesPtr,kind)=>{var GenericWireTypeSize=8;var[retType,...argTypes]=emval_lookupTypes(argCount,argTypesPtr);var toReturnWire=retType.toWireType.bind(retType);var argFromPtr=argTypes.map(type=>type.readValueFromPointer.bind(type));argCount--;var argN=new Array(argCount);var invokerFunction=(handle,methodName,destructorsRef,args)=>{var offset=0;for(var i=0;it.name)}) => ${retType.name}>`;return emval_addMethodCaller(createNamedFunction(functionName,invokerFunction))};var __emval_invoke=(caller,handle,methodName,destructorsRef,args)=>emval_methodCallers[caller](handle,methodName,destructorsRef,args);var __emval_new_cstring=v=>Emval.toHandle(getStringOrSymbol(v));var __emval_new_object=()=>Emval.toHandle({});var __emval_run_destructors=handle=>{var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)};var __emval_set_property=(handle,key,value)=>{handle=Emval.toValue(handle);key=Emval.toValue(key);value=Emval.toValue(value);handle[key]=value};var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{return func()}catch(e){handleException(e)}finally{maybeExit()}};var _emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()))},timeout_ms);timers[which]={id,timeout_ms};return 0};var _emscripten_date_now=()=>Date.now();var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var printCharBuffers=[null,[],[]];var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer));buffer.length=0}else{buffer.push(curr)}};var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0};init_ClassHandle();init_RegisteredPointer();{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}var ___getTypeName,_free,_malloc,__emscripten_timeout,memory,__indirect_function_table,wasmMemory,wasmTable;function assignWasmExports(wasmExports){___getTypeName=wasmExports["Q"];_free=Module["_free"]=wasmExports["R"];_malloc=Module["_malloc"]=wasmExports["S"];__emscripten_timeout=wasmExports["U"];memory=wasmMemory=wasmExports["O"];__indirect_function_table=wasmTable=wasmExports["T"]}var wasmImports={J:__abort_js,x:__embind_create_inheriting_constructor,s:__embind_finalize_value_object,z:__embind_register_bigint,A:__embind_register_bool,b:__embind_register_class,p:__embind_register_class_class_function,e:__embind_register_class_constructor,a:__embind_register_class_function,d:__embind_register_class_property,K:__embind_register_constant,M:__embind_register_emval,l:__embind_register_enum,f:__embind_register_enum_value,y:__embind_register_float,g:__embind_register_function,o:__embind_register_integer,q:__embind_register_iterable,h:__embind_register_memory_view,r:__embind_register_optional,N:__embind_register_std_string,u:__embind_register_std_wstring,t:__embind_register_value_object,m:__embind_register_value_object_field,B:__embind_register_void,D:__emscripten_runtime_keepalive_clear,k:__emval_create_invoker,n:__emval_decref,j:__emval_invoke,v:__emval_new_cstring,L:__emval_new_object,i:__emval_run_destructors,w:__emval_set_property,E:__setitimer_js,I:_emscripten_date_now,c:_emscripten_get_now,F:_emscripten_resize_heap,G:_exit,H:_fd_write,C:_proc_exit};function run(){preRun();function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})} +var PHYSX=(()=>{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["P"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("physx.release.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var __abort_js=()=>abort("");var createNamedFunction=(name,func)=>Object.defineProperty(func,"name",{value:name});var emval_freelist=[];var emval_handles=[0,1,,1,null,1,true,1,false,1];var BindingError=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};var throwBindingError=message=>{throw new BindingError(message)};var Emval={toValue:handle=>{if(!handle){throwBindingError(`Cannot use deleted val. handle = ${handle}`)}return emval_handles[handle]},toHandle:value=>{switch(value){case undefined:return 2;case null:return 4;case true:return 6;case false:return 8;default:{const handle=emval_freelist.pop()||emval_handles.length;emval_handles[handle]=value;emval_handles[handle+1]=1;return handle}}}};class PureVirtualError extends Error{}var AsciiToString=ptr=>{var str="";while(1){var ch=HEAPU8[ptr++];if(!ch)return str;str+=String.fromCharCode(ch)}};var registeredInstances={};var getBasestPointer=(class_,ptr)=>{if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr};var registerInheritedInstance=(class_,ptr,instance)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){throwBindingError(`Tried to register registered instance: ${ptr}`)}else{registeredInstances[ptr]=instance}};var registeredTypes={};var getTypeName=type=>{var ptr=___getTypeName(type);var rv=AsciiToString(ptr);_free(ptr);return rv};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`)}return impl};var unregisterInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){delete registeredInstances[ptr]}else{throwBindingError(`Tried to unregister unregistered instance: ${ptr}`)}};var detachFinalizer=handle=>{};var finalizationRegistry=false;var runDestructor=$$=>{if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}};var releaseClassHandle=$$=>{$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}};var attachFinalizer=handle=>{if(!globalThis.FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$};finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)};var __embind_create_inheriting_constructor=(constructorName,wrapperType,properties)=>{constructorName=AsciiToString(constructorName);wrapperType=requireRegisteredType(wrapperType,"wrapper");properties=Emval.toValue(properties);var registeredClass=wrapperType.registeredClass;var wrapperPrototype=registeredClass.instancePrototype;var baseClass=registeredClass.baseClass;var baseClassPrototype=baseClass.instancePrototype;var baseConstructor=registeredClass.baseClass.constructor;var ctor=createNamedFunction(constructorName,function(...args){for(var name of registeredClass.baseClass.pureVirtualFunctions){if(this[name]===baseClassPrototype[name]){throw new PureVirtualError(`Pure virtual function ${name} must be implemented in JavaScript`)}}Object.defineProperty(this,"__parent",{value:wrapperPrototype});this["__construct"](...args)});wrapperPrototype["__construct"]=function __construct(...args){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __construct")}var inner=baseConstructor["implement"](this,...args);detachFinalizer(inner);var $$=inner.$$;inner["notifyOnDestruction"]();$$.preservePointerOnDelete=true;Object.defineProperties(this,{$$:{value:$$}});attachFinalizer(this);registerInheritedInstance(registeredClass,$$.ptr,this)};wrapperPrototype["__destruct"]=function __destruct(){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __destruct")}detachFinalizer(this);unregisterInheritedInstance(registeredClass,this.$$.ptr)};ctor.prototype=Object.create(wrapperPrototype);Object.assign(ctor.prototype,properties);return Emval.toHandle(ctor)};var structRegistrations={};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function readPointer(pointer){return this.fromWireType(HEAPU32[pointer>>2])}var awaitingDependencies={};var typeDependencies={};var InternalError=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};var throwInternalError=message=>{throw new InternalError(message)};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(type=>typeDependencies[type]=dependentTypes);function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}}if(0===unregisteredTypes.length){onComplete(typeConverters)}};var __embind_finalize_value_object=structType=>{var reg=structRegistrations[structType];delete structRegistrations[structType];var rawConstructor=reg.rawConstructor;var rawDestructor=reg.rawDestructor;var fieldRecords=reg.fields;var fieldTypes=fieldRecords.map(field=>field.getterReturnType).concat(fieldRecords.map(field=>field.setterArgumentType));whenDependentTypesAreResolved([structType],fieldTypes,fieldTypes=>{var fields={};for(var[i,field]of fieldRecords.entries()){const getterReturnType=fieldTypes[i];const getter=field.getter;const getterContext=field.getterContext;const setterArgumentType=fieldTypes[i+fieldRecords.length];const setter=field.setter;const setterContext=field.setterContext;fields[field.fieldName]={read:ptr=>getterReturnType.fromWireType(getter(getterContext,ptr)),write:(ptr,o)=>{var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,o));runDestructors(destructors)},optional:getterReturnType.optional}}return[{name:reg.name,fromWireType:ptr=>{var rv={};for(var i in fields){rv[i]=fields[i].read(ptr)}rawDestructor(ptr);return rv},toWireType:(destructors,o)=>{for(var fieldName in fields){if(!(fieldName in o)&&!fields[fieldName].optional){throw new TypeError(`Missing field: "${fieldName}"`)}}var ptr=rawConstructor();for(fieldName in fields){fields[fieldName].write(ptr,o[fieldName])}if(destructors!==null){destructors.push(rawDestructor,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction:rawDestructor}]})};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){return sharedRegisterType(rawType,registeredInstance,options)}var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>HEAP8[pointer]:pointer=>HEAPU8[pointer];case 2:return signed?pointer=>HEAP16[pointer>>1]:pointer=>HEAPU16[pointer>>1];case 4:return signed?pointer=>HEAP32[pointer>>2]:pointer=>HEAPU32[pointer>>2];case 8:return signed?pointer=>HEAP64[pointer>>3]:pointer=>HEAPU64[pointer>>3];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_bigint=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0n;let fromWireType=value=>value;if(isUnsignedType){const bitSize=size*8;fromWireType=value=>BigInt.asUintN(bitSize,value);maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>{if(typeof value=="number"){value=BigInt(value)}return value},readValueFromPointer:integerReadValueFromPointer(name,size,!isUnsignedType),destructorFunction:null})};var __embind_register_bool=(rawType,name,trueValue,falseValue)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:function(wt){return!!wt},toWireType:function(destructors,o){return o?trueValue:falseValue},readValueFromPointer:function(pointer){return this.fromWireType(HEAPU8[pointer])},destructorFunction:null})};var shallowCopyInternalPointer=o=>({count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType});var throwInstanceAlreadyDeleted=obj=>{function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")};var deletionQueue=[];var flushPendingDeletes=()=>{while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}};var delayFunction;var init_ClassHandle=()=>{let proto=ClassHandle.prototype;Object.assign(proto,{isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;other.$$=other.$$;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right},clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}},delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}},isDeleted(){return!this.$$.ptr},deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}});const symbolDispose=Symbol.dispose;if(symbolDispose){proto[symbolDispose]=proto["delete"]}};function ClassHandle(){}var registeredPointers={};var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(...args){if(!proto[methodName].overloadTable.hasOwnProperty(args.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[args.length].apply(this,args)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module[name].overloadTable.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}var upcastPointer=(ptr,ptrClass,desiredClass)=>{while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr};var embindRepr=v=>{if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}};function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle||!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(()=>clonedHandle["delete"]()));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupported sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}var downcastPointer=(ptr,ptrClass,desiredClass)=>{if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)};var getInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]};var makeClassHandle=(prototype,record)=>{if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record,writable:true}}))};function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}var init_RegisteredPointer=()=>{Object.assign(RegisteredPointer.prototype,{getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr},destructor(ptr){this.rawDestructor?.(ptr)},readValueFromPointer:readPointer,fromWireType:RegisteredPointer_fromWireType})};function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this.toWireType=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this.toWireType=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this.toWireType=genericPointerToWireType}}var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistent public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var wasmTableMirror=[];var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var embind__requireFunction=(signature,rawFunction,isAsync=false)=>{signature=AsciiToString(signature);function makeDynCaller(){var rtn=getWasmTableEntry(rawFunction);return rtn}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};class UnboundTypeError extends Error{}var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};var __embind_register_class=(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor)=>{name=AsciiToString(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);upcast&&=embind__requireFunction(upcastSignature,upcast);downcast&&=embind__requireFunction(downcastSignature,downcast);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],base=>{base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(name,function(...args){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError(`Use 'new' to construct ${name}`)}if(undefined===registeredClass.constructor_body){throw new BindingError(`${name} has no accessible constructor`)}var body=registeredClass.constructor_body[args.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,args)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){registeredClass.baseClass.__derivedClasses??=[];registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})};function usesDestructorStack(argTypes){for(var i=1;i{var array=[];for(var i=0;i>2])}return array};var getFunctionName=signature=>{signature=signature.trim();const argsIndex=signature.indexOf("(");if(argsIndex===-1)return signature;return signature.slice(0,argsIndex)};var __embind_register_class_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}var proto=classType.registeredClass.constructor;if(undefined===proto[methodName]){unboundTypesHandler.argCount=argCount-1;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-1]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));var func=craftInvokerFunction(humanName,invokerArgsArray,null,rawInvoker,fn,isAsync);if(undefined===proto[methodName].overloadTable){func.argCount=argCount-1;proto[methodName]=func}else{proto[methodName].overloadTable[argCount-1]=func}if(classType.registeredClass.__derivedClasses){for(const derivedClass of classType.registeredClass.__derivedClasses){if(!derivedClass.constructor.hasOwnProperty(methodName)){derivedClass.constructor[methodName]=func}}}return[]});return[]})};var __embind_register_class_constructor=(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`constructor ${classType.name}`;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`)}classType.registeredClass.constructor_body[argCount-1]=()=>{throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`,rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{argTypes.splice(1,0,null);classType.registeredClass.constructor_body[argCount-1]=craftInvokerFunction(humanName,argTypes,null,invoker,rawConstructor);return[]});return[]})};var __embind_register_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context,isAsync);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]});return[]})};var validateThis=(this_,classType,humanName)=>{if(!(this_ instanceof Object)){throwBindingError(`${humanName} with invalid "this": ${this_}`)}if(!(this_ instanceof classType.registeredClass.constructor)){throwBindingError(`${humanName} incompatible with "this" of type ${this_.constructor.name}`)}if(!this_.$$.ptr){throwBindingError(`cannot call emscripten binding method ${humanName} on deleted object`)}return upcastPointer(this_.$$.ptr,this_.$$.ptrType.registeredClass,classType.registeredClass)};var __embind_register_class_property=(classType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{fieldName=AsciiToString(fieldName);getter=embind__requireFunction(getterSignature,getter);whenDependentTypesAreResolved([],[classType],classType=>{classType=classType[0];var humanName=`${classType.name}.${fieldName}`;var desc={get(){throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])},enumerable:true,configurable:true};if(setter){desc.set=()=>throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])}else{desc.set=v=>throwBindingError(humanName+" is a read-only property")}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);whenDependentTypesAreResolved([],setter?[getterReturnType,setterArgumentType]:[getterReturnType],types=>{var getterReturnType=types[0];var desc={get(){var ptr=validateThis(this,classType,humanName+" getter");return getterReturnType.fromWireType(getter(getterContext,ptr))},enumerable:true};if(setter){setter=embind__requireFunction(setterSignature,setter);var setterArgumentType=types[1];desc.set=function(v){var ptr=validateThis(this,classType,humanName+" setter");var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,v));runDestructors(destructors)}}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);return[]});return[]})};var __embind_register_constant=(name,type,value)=>{name=AsciiToString(name);whenDependentTypesAreResolved([],[type],type=>{type=type[0];Module[name]=type.fromWireType(value);return[]})};var __emval_decref=handle=>{if(handle>9&&0===--emval_handles[handle+1]){emval_handles[handle]=undefined;emval_freelist.push(handle)}};var EmValType={name:"emscripten::val",fromWireType:handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},toWireType:(destructors,value)=>Emval.toHandle(value),readValueFromPointer:readPointer,destructorFunction:null};var __embind_register_emval=rawType=>registerType(rawType,EmValType);var enumReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?function(pointer){return this.fromWireType(HEAP8[pointer])}:function(pointer){return this.fromWireType(HEAPU8[pointer])};case 2:return signed?function(pointer){return this.fromWireType(HEAP16[pointer>>1])}:function(pointer){return this.fromWireType(HEAPU16[pointer>>1])};case 4:return signed?function(pointer){return this.fromWireType(HEAP32[pointer>>2])}:function(pointer){return this.fromWireType(HEAPU32[pointer>>2])};default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};function getEnumValueType(rawValueType){return rawValueType===0?"object":rawValueType===1?"number":"string"}var __embind_register_enum=(rawType,name,size,isSigned,rawValueType)=>{name=AsciiToString(name);const valueType=getEnumValueType(rawValueType);switch(valueType){case"object":{function ctor(){}ctor.values={};registerType(rawType,{name,constructor:ctor,valueType,fromWireType:function(c){return this.constructor.values[c]},toWireType:(destructors,c)=>c.value,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor);break}case"number":{var keysMap={};registerType(rawType,{name,keysMap,valueType,fromWireType:c=>c,toWireType:(destructors,c)=>c,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}case"string":{var valuesMap={};var reverseMap={};var keysMap={};registerType(rawType,{name,valuesMap,reverseMap,keysMap,valueType,fromWireType:function(c){return this.reverseMap[c]},toWireType:function(destructors,c){return this.valuesMap[c]},readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}}};var __embind_register_enum_value=(rawEnumType,name,enumValue)=>{var enumType=requireRegisteredType(rawEnumType,"enum");name=AsciiToString(name);switch(enumType.valueType){case"object":{var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(`${enumType.name}_${name}`,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value;break}case"number":{enumType.keysMap[name]=enumValue;break}case"string":{enumType.valuesMap[name]=enumValue;enumType.reverseMap[enumValue]=name;enumType.keysMap[name]=name;break}}};var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this.fromWireType(HEAPF32[pointer>>2])};case 8:return function(pointer){return this.fromWireType(HEAPF64[pointer>>3])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=(rawType,name,size)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:value=>value,toWireType:(destructors,value)=>value,readValueFromPointer:floatReadValueFromPointer(name,size),destructorFunction:null})};var __embind_register_function=(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=AsciiToString(name);name=getFunctionName(name);rawInvoker=embind__requireFunction(signature,rawInvoker,isAsync);exposePublicSymbol(name,function(){throwUnboundTypeError(`Cannot call ${name} due to unbound types`,argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn,isAsync),argCount-1);return[]})};var __embind_register_integer=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0;let fromWireType=value=>value;if(isUnsignedType){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift;maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>value,readValueFromPointer:integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})};var installIndexedIterator=(proto,sizeMethodName,getMethodName)=>{const makeIterator=(size,getValue)=>{let index=0;return{next(){if(index>=size){return{done:true}}const current=index;index++;const value=getValue(current);return{value,done:false}},[Symbol.iterator](){return this}}};if(!proto[Symbol.iterator]){proto[Symbol.iterator]=function(){const size=this[sizeMethodName]();return makeIterator(size,i=>this[getMethodName](i))}}};var __embind_register_iterable=(rawClassType,rawElementType,sizeMethodName,getMethodName)=>{sizeMethodName=AsciiToString(sizeMethodName);getMethodName=AsciiToString(getMethodName);whenDependentTypesAreResolved([],[rawClassType,rawElementType],types=>{const classType=types[0];installIndexedIterator(classType.registeredClass.instancePrototype,sizeMethodName,getMethodName);return[]})};var __embind_register_memory_view=(rawType,dataTypeIndex,name)=>{var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=HEAPU32[handle>>2];var data=HEAPU32[handle+4>>2];return new TA(HEAP8.buffer,data,size)}name=AsciiToString(name);registerType(rawType,{name,fromWireType:decodeMemoryView,readValueFromPointer:decodeMemoryView},{ignoreDuplicateRegistrations:true})};var EmValOptionalType=Object.assign({optional:true},EmValType);var __embind_register_optional=(rawOptionalType,rawType)=>{registerType(rawOptionalType,EmValOptionalType)};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var UTF8Decoder=globalThis.TextDecoder&&new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var __embind_register_std_string=(rawType,name)=>{name=AsciiToString(name);var stdStringIsUTF8=true;registerType(rawType,{name,fromWireType(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){str=UTF8ToString(payload,length,true)}else{str="";for(var i=0;i>2]=length;if(valueIsOfTypeString){if(stdStringIsUTF8){stringToUTF8(value,ptr,length+1)}else{for(var i=0;i255){_free(base);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}}else{HEAPU8.set(value,ptr)}if(destructors!==null){destructors.push(_free,base)}return base},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var UTF16Decoder=globalThis.TextDecoder?new TextDecoder("utf-16le"):undefined;var UTF16ToString=(ptr,maxBytesToRead,ignoreNul)=>{var idx=ptr>>1;var endIdx=findStringEnd(HEAPU16,idx,maxBytesToRead/2,ignoreNul);if(endIdx-idx>16&&UTF16Decoder)return UTF16Decoder.decode(HEAPU16.subarray(idx,endIdx));var str="";for(var i=idx;i{maxBytesToWrite??=2147483647;if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead,ignoreNul)=>{var str="";var startIdx=ptr>>2;for(var i=0;!(i>=maxBytesToRead/4);i++){var utf32=HEAPU32[startIdx+i];if(!utf32&&!ignoreNul)break;str+=String.fromCodePoint(utf32)}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i65535){i++}HEAP32[outPtr>>2]=codePoint;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i65535){i++}len+=4}return len};var __embind_register_std_wstring=(rawType,charSize,name)=>{name=AsciiToString(name);var decodeString,encodeString,lengthBytesUTF;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16}else{decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32}registerType(rawType,{name,fromWireType:value=>{var length=HEAPU32[value>>2];var str=decodeString(value+4,length*charSize,true);_free(value);return str},toWireType:(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length/charSize;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var __embind_register_value_object=(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor)=>{structRegistrations[rawType]={name:AsciiToString(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}};var __embind_register_value_object_field=(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{structRegistrations[structType].fields.push({fieldName:AsciiToString(fieldName),getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext,setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext})};var __embind_register_void=(rawType,name)=>{name=AsciiToString(name);registerType(rawType,{isVoid:true,name,fromWireType:()=>undefined,toWireType:(destructors,o)=>undefined})};var runtimeKeepaliveCounter=0;var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var emval_methodCallers=[];var emval_addMethodCaller=caller=>{var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id};var emval_lookupTypes=(argCount,argTypes)=>{var a=new Array(argCount);for(var i=0;i>2],`parameter ${i}`)}return a};var emval_returnValue=(toReturnWire,destructorsRef,handle)=>{var destructors=[];var result=toReturnWire(destructors,handle);if(destructors.length){HEAPU32[destructorsRef>>2]=Emval.toHandle(destructors)}return result};var emval_symbols={};var getStringOrSymbol=address=>{var symbol=emval_symbols[address];if(symbol===undefined){return AsciiToString(address)}return symbol};var __emval_create_invoker=(argCount,argTypesPtr,kind)=>{var GenericWireTypeSize=8;var[retType,...argTypes]=emval_lookupTypes(argCount,argTypesPtr);var toReturnWire=retType.toWireType.bind(retType);var argFromPtr=argTypes.map(type=>type.readValueFromPointer.bind(type));argCount--;var argN=new Array(argCount);var invokerFunction=(handle,methodName,destructorsRef,args)=>{var offset=0;for(var i=0;it.name)}) => ${retType.name}>`;return emval_addMethodCaller(createNamedFunction(functionName,invokerFunction))};var __emval_invoke=(caller,handle,methodName,destructorsRef,args)=>emval_methodCallers[caller](handle,methodName,destructorsRef,args);var __emval_new_cstring=v=>Emval.toHandle(getStringOrSymbol(v));var __emval_new_object=()=>Emval.toHandle({});var __emval_run_destructors=handle=>{var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)};var __emval_set_property=(handle,key,value)=>{handle=Emval.toValue(handle);key=Emval.toValue(key);value=Emval.toValue(value);handle[key]=value};var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{return func()}catch(e){handleException(e)}finally{maybeExit()}};var _emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()))},timeout_ms);timers[which]={id,timeout_ms};return 0};var _emscripten_date_now=()=>Date.now();var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var printCharBuffers=[null,[],[]];var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer));buffer.length=0}else{buffer.push(curr)}};var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0};init_ClassHandle();init_RegisteredPointer();{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}var ___getTypeName,_free,_malloc,__emscripten_timeout,memory,__indirect_function_table,wasmMemory,wasmTable;function assignWasmExports(wasmExports){___getTypeName=wasmExports["Q"];_free=Module["_free"]=wasmExports["R"];_malloc=Module["_malloc"]=wasmExports["S"];__emscripten_timeout=wasmExports["U"];memory=wasmMemory=wasmExports["O"];__indirect_function_table=wasmTable=wasmExports["T"]}var wasmImports={J:__abort_js,x:__embind_create_inheriting_constructor,s:__embind_finalize_value_object,z:__embind_register_bigint,A:__embind_register_bool,b:__embind_register_class,p:__embind_register_class_class_function,e:__embind_register_class_constructor,a:__embind_register_class_function,d:__embind_register_class_property,K:__embind_register_constant,M:__embind_register_emval,l:__embind_register_enum,f:__embind_register_enum_value,y:__embind_register_float,g:__embind_register_function,o:__embind_register_integer,q:__embind_register_iterable,h:__embind_register_memory_view,r:__embind_register_optional,N:__embind_register_std_string,u:__embind_register_std_wstring,t:__embind_register_value_object,m:__embind_register_value_object_field,B:__embind_register_void,D:__emscripten_runtime_keepalive_clear,k:__emval_create_invoker,n:__emval_decref,j:__emval_invoke,v:__emval_new_cstring,L:__emval_new_object,i:__emval_run_destructors,w:__emval_set_property,E:__setitimer_js,I:_emscripten_date_now,c:_emscripten_get_now,F:_emscripten_resize_heap,G:_exit,H:_fd_write,C:_proc_exit};function run(){preRun();function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})} ;return moduleRtn}})();if(typeof exports==="object"&&typeof module==="object"){module.exports=PHYSX;module.exports.default=PHYSX}else if(typeof define==="function"&&define["amd"])define([],()=>PHYSX); diff --git a/packages/physics-physx/libs/physx.release.simd.js b/packages/physics-physx/libs/physx.release.simd.js index bdb1d70990..45843d369b 100644 --- a/packages/physics-physx/libs/physx.release.simd.js +++ b/packages/physics-physx/libs/physx.release.simd.js @@ -1,2 +1,2 @@ -var PHYSX=(()=>{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["P"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return "https://mdn.alipayobjects.com/rms/afts/file/A*6vi1SJaSJ6IAAAAAgDAAAAgAehQnAQ/physx.release.simd.wasm"}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var __abort_js=()=>abort("");var createNamedFunction=(name,func)=>Object.defineProperty(func,"name",{value:name});var emval_freelist=[];var emval_handles=[0,1,,1,null,1,true,1,false,1];var BindingError=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};var throwBindingError=message=>{throw new BindingError(message)};var Emval={toValue:handle=>{if(!handle){throwBindingError(`Cannot use deleted val. handle = ${handle}`)}return emval_handles[handle]},toHandle:value=>{switch(value){case undefined:return 2;case null:return 4;case true:return 6;case false:return 8;default:{const handle=emval_freelist.pop()||emval_handles.length;emval_handles[handle]=value;emval_handles[handle+1]=1;return handle}}}};class PureVirtualError extends Error{}var AsciiToString=ptr=>{var str="";while(1){var ch=HEAPU8[ptr++];if(!ch)return str;str+=String.fromCharCode(ch)}};var registeredInstances={};var getBasestPointer=(class_,ptr)=>{if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr};var registerInheritedInstance=(class_,ptr,instance)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){throwBindingError(`Tried to register registered instance: ${ptr}`)}else{registeredInstances[ptr]=instance}};var registeredTypes={};var getTypeName=type=>{var ptr=___getTypeName(type);var rv=AsciiToString(ptr);_free(ptr);return rv};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`)}return impl};var unregisterInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){delete registeredInstances[ptr]}else{throwBindingError(`Tried to unregister unregistered instance: ${ptr}`)}};var detachFinalizer=handle=>{};var finalizationRegistry=false;var runDestructor=$$=>{if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}};var releaseClassHandle=$$=>{$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}};var attachFinalizer=handle=>{if(!globalThis.FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$};finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)};var __embind_create_inheriting_constructor=(constructorName,wrapperType,properties)=>{constructorName=AsciiToString(constructorName);wrapperType=requireRegisteredType(wrapperType,"wrapper");properties=Emval.toValue(properties);var registeredClass=wrapperType.registeredClass;var wrapperPrototype=registeredClass.instancePrototype;var baseClass=registeredClass.baseClass;var baseClassPrototype=baseClass.instancePrototype;var baseConstructor=registeredClass.baseClass.constructor;var ctor=createNamedFunction(constructorName,function(...args){for(var name of registeredClass.baseClass.pureVirtualFunctions){if(this[name]===baseClassPrototype[name]){throw new PureVirtualError(`Pure virtual function ${name} must be implemented in JavaScript`)}}Object.defineProperty(this,"__parent",{value:wrapperPrototype});this["__construct"](...args)});wrapperPrototype["__construct"]=function __construct(...args){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __construct")}var inner=baseConstructor["implement"](this,...args);detachFinalizer(inner);var $$=inner.$$;inner["notifyOnDestruction"]();$$.preservePointerOnDelete=true;Object.defineProperties(this,{$$:{value:$$}});attachFinalizer(this);registerInheritedInstance(registeredClass,$$.ptr,this)};wrapperPrototype["__destruct"]=function __destruct(){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __destruct")}detachFinalizer(this);unregisterInheritedInstance(registeredClass,this.$$.ptr)};ctor.prototype=Object.create(wrapperPrototype);Object.assign(ctor.prototype,properties);return Emval.toHandle(ctor)};var structRegistrations={};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function readPointer(pointer){return this.fromWireType(HEAPU32[pointer>>2])}var awaitingDependencies={};var typeDependencies={};var InternalError=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};var throwInternalError=message=>{throw new InternalError(message)};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(type=>typeDependencies[type]=dependentTypes);function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}}if(0===unregisteredTypes.length){onComplete(typeConverters)}};var __embind_finalize_value_object=structType=>{var reg=structRegistrations[structType];delete structRegistrations[structType];var rawConstructor=reg.rawConstructor;var rawDestructor=reg.rawDestructor;var fieldRecords=reg.fields;var fieldTypes=fieldRecords.map(field=>field.getterReturnType).concat(fieldRecords.map(field=>field.setterArgumentType));whenDependentTypesAreResolved([structType],fieldTypes,fieldTypes=>{var fields={};for(var[i,field]of fieldRecords.entries()){const getterReturnType=fieldTypes[i];const getter=field.getter;const getterContext=field.getterContext;const setterArgumentType=fieldTypes[i+fieldRecords.length];const setter=field.setter;const setterContext=field.setterContext;fields[field.fieldName]={read:ptr=>getterReturnType.fromWireType(getter(getterContext,ptr)),write:(ptr,o)=>{var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,o));runDestructors(destructors)},optional:getterReturnType.optional}}return[{name:reg.name,fromWireType:ptr=>{var rv={};for(var i in fields){rv[i]=fields[i].read(ptr)}rawDestructor(ptr);return rv},toWireType:(destructors,o)=>{for(var fieldName in fields){if(!(fieldName in o)&&!fields[fieldName].optional){throw new TypeError(`Missing field: "${fieldName}"`)}}var ptr=rawConstructor();for(fieldName in fields){fields[fieldName].write(ptr,o[fieldName])}if(destructors!==null){destructors.push(rawDestructor,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction:rawDestructor}]})};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){return sharedRegisterType(rawType,registeredInstance,options)}var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>HEAP8[pointer]:pointer=>HEAPU8[pointer];case 2:return signed?pointer=>HEAP16[pointer>>1]:pointer=>HEAPU16[pointer>>1];case 4:return signed?pointer=>HEAP32[pointer>>2]:pointer=>HEAPU32[pointer>>2];case 8:return signed?pointer=>HEAP64[pointer>>3]:pointer=>HEAPU64[pointer>>3];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_bigint=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0n;let fromWireType=value=>value;if(isUnsignedType){const bitSize=size*8;fromWireType=value=>BigInt.asUintN(bitSize,value);maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>{if(typeof value=="number"){value=BigInt(value)}return value},readValueFromPointer:integerReadValueFromPointer(name,size,!isUnsignedType),destructorFunction:null})};var __embind_register_bool=(rawType,name,trueValue,falseValue)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:function(wt){return!!wt},toWireType:function(destructors,o){return o?trueValue:falseValue},readValueFromPointer:function(pointer){return this.fromWireType(HEAPU8[pointer])},destructorFunction:null})};var shallowCopyInternalPointer=o=>({count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType});var throwInstanceAlreadyDeleted=obj=>{function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")};var deletionQueue=[];var flushPendingDeletes=()=>{while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}};var delayFunction;var init_ClassHandle=()=>{let proto=ClassHandle.prototype;Object.assign(proto,{isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;other.$$=other.$$;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right},clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}},delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}},isDeleted(){return!this.$$.ptr},deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}});const symbolDispose=Symbol.dispose;if(symbolDispose){proto[symbolDispose]=proto["delete"]}};function ClassHandle(){}var registeredPointers={};var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(...args){if(!proto[methodName].overloadTable.hasOwnProperty(args.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[args.length].apply(this,args)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module[name].overloadTable.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}var upcastPointer=(ptr,ptrClass,desiredClass)=>{while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr};var embindRepr=v=>{if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}};function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle||!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(()=>clonedHandle["delete"]()));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupported sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}var downcastPointer=(ptr,ptrClass,desiredClass)=>{if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)};var getInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]};var makeClassHandle=(prototype,record)=>{if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record,writable:true}}))};function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}var init_RegisteredPointer=()=>{Object.assign(RegisteredPointer.prototype,{getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr},destructor(ptr){this.rawDestructor?.(ptr)},readValueFromPointer:readPointer,fromWireType:RegisteredPointer_fromWireType})};function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this.toWireType=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this.toWireType=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this.toWireType=genericPointerToWireType}}var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistent public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var wasmTableMirror=[];var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var embind__requireFunction=(signature,rawFunction,isAsync=false)=>{signature=AsciiToString(signature);function makeDynCaller(){var rtn=getWasmTableEntry(rawFunction);return rtn}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};class UnboundTypeError extends Error{}var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};var __embind_register_class=(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor)=>{name=AsciiToString(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);upcast&&=embind__requireFunction(upcastSignature,upcast);downcast&&=embind__requireFunction(downcastSignature,downcast);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],base=>{base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(name,function(...args){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError(`Use 'new' to construct ${name}`)}if(undefined===registeredClass.constructor_body){throw new BindingError(`${name} has no accessible constructor`)}var body=registeredClass.constructor_body[args.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,args)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){registeredClass.baseClass.__derivedClasses??=[];registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})};function usesDestructorStack(argTypes){for(var i=1;i{var array=[];for(var i=0;i>2])}return array};var getFunctionName=signature=>{signature=signature.trim();const argsIndex=signature.indexOf("(");if(argsIndex===-1)return signature;return signature.slice(0,argsIndex)};var __embind_register_class_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}var proto=classType.registeredClass.constructor;if(undefined===proto[methodName]){unboundTypesHandler.argCount=argCount-1;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-1]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));var func=craftInvokerFunction(humanName,invokerArgsArray,null,rawInvoker,fn,isAsync);if(undefined===proto[methodName].overloadTable){func.argCount=argCount-1;proto[methodName]=func}else{proto[methodName].overloadTable[argCount-1]=func}if(classType.registeredClass.__derivedClasses){for(const derivedClass of classType.registeredClass.__derivedClasses){if(!derivedClass.constructor.hasOwnProperty(methodName)){derivedClass.constructor[methodName]=func}}}return[]});return[]})};var __embind_register_class_constructor=(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`constructor ${classType.name}`;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`)}classType.registeredClass.constructor_body[argCount-1]=()=>{throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`,rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{argTypes.splice(1,0,null);classType.registeredClass.constructor_body[argCount-1]=craftInvokerFunction(humanName,argTypes,null,invoker,rawConstructor);return[]});return[]})};var __embind_register_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context,isAsync);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]});return[]})};var validateThis=(this_,classType,humanName)=>{if(!(this_ instanceof Object)){throwBindingError(`${humanName} with invalid "this": ${this_}`)}if(!(this_ instanceof classType.registeredClass.constructor)){throwBindingError(`${humanName} incompatible with "this" of type ${this_.constructor.name}`)}if(!this_.$$.ptr){throwBindingError(`cannot call emscripten binding method ${humanName} on deleted object`)}return upcastPointer(this_.$$.ptr,this_.$$.ptrType.registeredClass,classType.registeredClass)};var __embind_register_class_property=(classType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{fieldName=AsciiToString(fieldName);getter=embind__requireFunction(getterSignature,getter);whenDependentTypesAreResolved([],[classType],classType=>{classType=classType[0];var humanName=`${classType.name}.${fieldName}`;var desc={get(){throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])},enumerable:true,configurable:true};if(setter){desc.set=()=>throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])}else{desc.set=v=>throwBindingError(humanName+" is a read-only property")}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);whenDependentTypesAreResolved([],setter?[getterReturnType,setterArgumentType]:[getterReturnType],types=>{var getterReturnType=types[0];var desc={get(){var ptr=validateThis(this,classType,humanName+" getter");return getterReturnType.fromWireType(getter(getterContext,ptr))},enumerable:true};if(setter){setter=embind__requireFunction(setterSignature,setter);var setterArgumentType=types[1];desc.set=function(v){var ptr=validateThis(this,classType,humanName+" setter");var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,v));runDestructors(destructors)}}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);return[]});return[]})};var __embind_register_constant=(name,type,value)=>{name=AsciiToString(name);whenDependentTypesAreResolved([],[type],type=>{type=type[0];Module[name]=type.fromWireType(value);return[]})};var __emval_decref=handle=>{if(handle>9&&0===--emval_handles[handle+1]){emval_handles[handle]=undefined;emval_freelist.push(handle)}};var EmValType={name:"emscripten::val",fromWireType:handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},toWireType:(destructors,value)=>Emval.toHandle(value),readValueFromPointer:readPointer,destructorFunction:null};var __embind_register_emval=rawType=>registerType(rawType,EmValType);var enumReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?function(pointer){return this.fromWireType(HEAP8[pointer])}:function(pointer){return this.fromWireType(HEAPU8[pointer])};case 2:return signed?function(pointer){return this.fromWireType(HEAP16[pointer>>1])}:function(pointer){return this.fromWireType(HEAPU16[pointer>>1])};case 4:return signed?function(pointer){return this.fromWireType(HEAP32[pointer>>2])}:function(pointer){return this.fromWireType(HEAPU32[pointer>>2])};default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};function getEnumValueType(rawValueType){return rawValueType===0?"object":rawValueType===1?"number":"string"}var __embind_register_enum=(rawType,name,size,isSigned,rawValueType)=>{name=AsciiToString(name);const valueType=getEnumValueType(rawValueType);switch(valueType){case"object":{function ctor(){}ctor.values={};registerType(rawType,{name,constructor:ctor,valueType,fromWireType:function(c){return this.constructor.values[c]},toWireType:(destructors,c)=>c.value,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor);break}case"number":{var keysMap={};registerType(rawType,{name,keysMap,valueType,fromWireType:c=>c,toWireType:(destructors,c)=>c,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}case"string":{var valuesMap={};var reverseMap={};var keysMap={};registerType(rawType,{name,valuesMap,reverseMap,keysMap,valueType,fromWireType:function(c){return this.reverseMap[c]},toWireType:function(destructors,c){return this.valuesMap[c]},readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}}};var __embind_register_enum_value=(rawEnumType,name,enumValue)=>{var enumType=requireRegisteredType(rawEnumType,"enum");name=AsciiToString(name);switch(enumType.valueType){case"object":{var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(`${enumType.name}_${name}`,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value;break}case"number":{enumType.keysMap[name]=enumValue;break}case"string":{enumType.valuesMap[name]=enumValue;enumType.reverseMap[enumValue]=name;enumType.keysMap[name]=name;break}}};var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this.fromWireType(HEAPF32[pointer>>2])};case 8:return function(pointer){return this.fromWireType(HEAPF64[pointer>>3])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=(rawType,name,size)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:value=>value,toWireType:(destructors,value)=>value,readValueFromPointer:floatReadValueFromPointer(name,size),destructorFunction:null})};var __embind_register_function=(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=AsciiToString(name);name=getFunctionName(name);rawInvoker=embind__requireFunction(signature,rawInvoker,isAsync);exposePublicSymbol(name,function(){throwUnboundTypeError(`Cannot call ${name} due to unbound types`,argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn,isAsync),argCount-1);return[]})};var __embind_register_integer=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0;let fromWireType=value=>value;if(isUnsignedType){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift;maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>value,readValueFromPointer:integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})};var installIndexedIterator=(proto,sizeMethodName,getMethodName)=>{const makeIterator=(size,getValue)=>{let index=0;return{next(){if(index>=size){return{done:true}}const current=index;index++;const value=getValue(current);return{value,done:false}},[Symbol.iterator](){return this}}};if(!proto[Symbol.iterator]){proto[Symbol.iterator]=function(){const size=this[sizeMethodName]();return makeIterator(size,i=>this[getMethodName](i))}}};var __embind_register_iterable=(rawClassType,rawElementType,sizeMethodName,getMethodName)=>{sizeMethodName=AsciiToString(sizeMethodName);getMethodName=AsciiToString(getMethodName);whenDependentTypesAreResolved([],[rawClassType,rawElementType],types=>{const classType=types[0];installIndexedIterator(classType.registeredClass.instancePrototype,sizeMethodName,getMethodName);return[]})};var __embind_register_memory_view=(rawType,dataTypeIndex,name)=>{var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=HEAPU32[handle>>2];var data=HEAPU32[handle+4>>2];return new TA(HEAP8.buffer,data,size)}name=AsciiToString(name);registerType(rawType,{name,fromWireType:decodeMemoryView,readValueFromPointer:decodeMemoryView},{ignoreDuplicateRegistrations:true})};var EmValOptionalType=Object.assign({optional:true},EmValType);var __embind_register_optional=(rawOptionalType,rawType)=>{registerType(rawOptionalType,EmValOptionalType)};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var UTF8Decoder=globalThis.TextDecoder&&new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var __embind_register_std_string=(rawType,name)=>{name=AsciiToString(name);var stdStringIsUTF8=true;registerType(rawType,{name,fromWireType(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){str=UTF8ToString(payload,length,true)}else{str="";for(var i=0;i>2]=length;if(valueIsOfTypeString){if(stdStringIsUTF8){stringToUTF8(value,ptr,length+1)}else{for(var i=0;i255){_free(base);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}}else{HEAPU8.set(value,ptr)}if(destructors!==null){destructors.push(_free,base)}return base},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var UTF16Decoder=globalThis.TextDecoder?new TextDecoder("utf-16le"):undefined;var UTF16ToString=(ptr,maxBytesToRead,ignoreNul)=>{var idx=ptr>>1;var endIdx=findStringEnd(HEAPU16,idx,maxBytesToRead/2,ignoreNul);if(endIdx-idx>16&&UTF16Decoder)return UTF16Decoder.decode(HEAPU16.subarray(idx,endIdx));var str="";for(var i=idx;i{maxBytesToWrite??=2147483647;if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead,ignoreNul)=>{var str="";var startIdx=ptr>>2;for(var i=0;!(i>=maxBytesToRead/4);i++){var utf32=HEAPU32[startIdx+i];if(!utf32&&!ignoreNul)break;str+=String.fromCodePoint(utf32)}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i65535){i++}HEAP32[outPtr>>2]=codePoint;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i65535){i++}len+=4}return len};var __embind_register_std_wstring=(rawType,charSize,name)=>{name=AsciiToString(name);var decodeString,encodeString,lengthBytesUTF;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16}else{decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32}registerType(rawType,{name,fromWireType:value=>{var length=HEAPU32[value>>2];var str=decodeString(value+4,length*charSize,true);_free(value);return str},toWireType:(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length/charSize;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var __embind_register_value_object=(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor)=>{structRegistrations[rawType]={name:AsciiToString(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}};var __embind_register_value_object_field=(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{structRegistrations[structType].fields.push({fieldName:AsciiToString(fieldName),getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext,setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext})};var __embind_register_void=(rawType,name)=>{name=AsciiToString(name);registerType(rawType,{isVoid:true,name,fromWireType:()=>undefined,toWireType:(destructors,o)=>undefined})};var runtimeKeepaliveCounter=0;var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var emval_methodCallers=[];var emval_addMethodCaller=caller=>{var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id};var emval_lookupTypes=(argCount,argTypes)=>{var a=new Array(argCount);for(var i=0;i>2],`parameter ${i}`)}return a};var emval_returnValue=(toReturnWire,destructorsRef,handle)=>{var destructors=[];var result=toReturnWire(destructors,handle);if(destructors.length){HEAPU32[destructorsRef>>2]=Emval.toHandle(destructors)}return result};var emval_symbols={};var getStringOrSymbol=address=>{var symbol=emval_symbols[address];if(symbol===undefined){return AsciiToString(address)}return symbol};var __emval_create_invoker=(argCount,argTypesPtr,kind)=>{var GenericWireTypeSize=8;var[retType,...argTypes]=emval_lookupTypes(argCount,argTypesPtr);var toReturnWire=retType.toWireType.bind(retType);var argFromPtr=argTypes.map(type=>type.readValueFromPointer.bind(type));argCount--;var argN=new Array(argCount);var invokerFunction=(handle,methodName,destructorsRef,args)=>{var offset=0;for(var i=0;it.name)}) => ${retType.name}>`;return emval_addMethodCaller(createNamedFunction(functionName,invokerFunction))};var __emval_invoke=(caller,handle,methodName,destructorsRef,args)=>emval_methodCallers[caller](handle,methodName,destructorsRef,args);var __emval_new_cstring=v=>Emval.toHandle(getStringOrSymbol(v));var __emval_new_object=()=>Emval.toHandle({});var __emval_run_destructors=handle=>{var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)};var __emval_set_property=(handle,key,value)=>{handle=Emval.toValue(handle);key=Emval.toValue(key);value=Emval.toValue(value);handle[key]=value};var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{return func()}catch(e){handleException(e)}finally{maybeExit()}};var _emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()))},timeout_ms);timers[which]={id,timeout_ms};return 0};var _emscripten_date_now=()=>Date.now();var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var printCharBuffers=[null,[],[]];var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer));buffer.length=0}else{buffer.push(curr)}};var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0};init_ClassHandle();init_RegisteredPointer();{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}var ___getTypeName,_free,_malloc,__emscripten_timeout,memory,__indirect_function_table,wasmMemory,wasmTable;function assignWasmExports(wasmExports){___getTypeName=wasmExports["Q"];_free=Module["_free"]=wasmExports["R"];_malloc=Module["_malloc"]=wasmExports["S"];__emscripten_timeout=wasmExports["U"];memory=wasmMemory=wasmExports["O"];__indirect_function_table=wasmTable=wasmExports["T"]}var wasmImports={J:__abort_js,x:__embind_create_inheriting_constructor,s:__embind_finalize_value_object,z:__embind_register_bigint,A:__embind_register_bool,b:__embind_register_class,p:__embind_register_class_class_function,e:__embind_register_class_constructor,a:__embind_register_class_function,d:__embind_register_class_property,K:__embind_register_constant,M:__embind_register_emval,l:__embind_register_enum,f:__embind_register_enum_value,y:__embind_register_float,g:__embind_register_function,o:__embind_register_integer,q:__embind_register_iterable,h:__embind_register_memory_view,r:__embind_register_optional,N:__embind_register_std_string,u:__embind_register_std_wstring,t:__embind_register_value_object,m:__embind_register_value_object_field,B:__embind_register_void,D:__emscripten_runtime_keepalive_clear,k:__emval_create_invoker,n:__emval_decref,j:__emval_invoke,v:__emval_new_cstring,L:__emval_new_object,i:__emval_run_destructors,w:__emval_set_property,E:__setitimer_js,I:_emscripten_date_now,c:_emscripten_get_now,F:_emscripten_resize_heap,G:_exit,H:_fd_write,C:_proc_exit};function run(){preRun();function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})} +var PHYSX=(()=>{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["P"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("physx.release.simd.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var __abort_js=()=>abort("");var createNamedFunction=(name,func)=>Object.defineProperty(func,"name",{value:name});var emval_freelist=[];var emval_handles=[0,1,,1,null,1,true,1,false,1];var BindingError=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};var throwBindingError=message=>{throw new BindingError(message)};var Emval={toValue:handle=>{if(!handle){throwBindingError(`Cannot use deleted val. handle = ${handle}`)}return emval_handles[handle]},toHandle:value=>{switch(value){case undefined:return 2;case null:return 4;case true:return 6;case false:return 8;default:{const handle=emval_freelist.pop()||emval_handles.length;emval_handles[handle]=value;emval_handles[handle+1]=1;return handle}}}};class PureVirtualError extends Error{}var AsciiToString=ptr=>{var str="";while(1){var ch=HEAPU8[ptr++];if(!ch)return str;str+=String.fromCharCode(ch)}};var registeredInstances={};var getBasestPointer=(class_,ptr)=>{if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr};var registerInheritedInstance=(class_,ptr,instance)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){throwBindingError(`Tried to register registered instance: ${ptr}`)}else{registeredInstances[ptr]=instance}};var registeredTypes={};var getTypeName=type=>{var ptr=___getTypeName(type);var rv=AsciiToString(ptr);_free(ptr);return rv};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`)}return impl};var unregisterInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){delete registeredInstances[ptr]}else{throwBindingError(`Tried to unregister unregistered instance: ${ptr}`)}};var detachFinalizer=handle=>{};var finalizationRegistry=false;var runDestructor=$$=>{if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}};var releaseClassHandle=$$=>{$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}};var attachFinalizer=handle=>{if(!globalThis.FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$};finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)};var __embind_create_inheriting_constructor=(constructorName,wrapperType,properties)=>{constructorName=AsciiToString(constructorName);wrapperType=requireRegisteredType(wrapperType,"wrapper");properties=Emval.toValue(properties);var registeredClass=wrapperType.registeredClass;var wrapperPrototype=registeredClass.instancePrototype;var baseClass=registeredClass.baseClass;var baseClassPrototype=baseClass.instancePrototype;var baseConstructor=registeredClass.baseClass.constructor;var ctor=createNamedFunction(constructorName,function(...args){for(var name of registeredClass.baseClass.pureVirtualFunctions){if(this[name]===baseClassPrototype[name]){throw new PureVirtualError(`Pure virtual function ${name} must be implemented in JavaScript`)}}Object.defineProperty(this,"__parent",{value:wrapperPrototype});this["__construct"](...args)});wrapperPrototype["__construct"]=function __construct(...args){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __construct")}var inner=baseConstructor["implement"](this,...args);detachFinalizer(inner);var $$=inner.$$;inner["notifyOnDestruction"]();$$.preservePointerOnDelete=true;Object.defineProperties(this,{$$:{value:$$}});attachFinalizer(this);registerInheritedInstance(registeredClass,$$.ptr,this)};wrapperPrototype["__destruct"]=function __destruct(){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __destruct")}detachFinalizer(this);unregisterInheritedInstance(registeredClass,this.$$.ptr)};ctor.prototype=Object.create(wrapperPrototype);Object.assign(ctor.prototype,properties);return Emval.toHandle(ctor)};var structRegistrations={};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function readPointer(pointer){return this.fromWireType(HEAPU32[pointer>>2])}var awaitingDependencies={};var typeDependencies={};var InternalError=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};var throwInternalError=message=>{throw new InternalError(message)};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(type=>typeDependencies[type]=dependentTypes);function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}}if(0===unregisteredTypes.length){onComplete(typeConverters)}};var __embind_finalize_value_object=structType=>{var reg=structRegistrations[structType];delete structRegistrations[structType];var rawConstructor=reg.rawConstructor;var rawDestructor=reg.rawDestructor;var fieldRecords=reg.fields;var fieldTypes=fieldRecords.map(field=>field.getterReturnType).concat(fieldRecords.map(field=>field.setterArgumentType));whenDependentTypesAreResolved([structType],fieldTypes,fieldTypes=>{var fields={};for(var[i,field]of fieldRecords.entries()){const getterReturnType=fieldTypes[i];const getter=field.getter;const getterContext=field.getterContext;const setterArgumentType=fieldTypes[i+fieldRecords.length];const setter=field.setter;const setterContext=field.setterContext;fields[field.fieldName]={read:ptr=>getterReturnType.fromWireType(getter(getterContext,ptr)),write:(ptr,o)=>{var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,o));runDestructors(destructors)},optional:getterReturnType.optional}}return[{name:reg.name,fromWireType:ptr=>{var rv={};for(var i in fields){rv[i]=fields[i].read(ptr)}rawDestructor(ptr);return rv},toWireType:(destructors,o)=>{for(var fieldName in fields){if(!(fieldName in o)&&!fields[fieldName].optional){throw new TypeError(`Missing field: "${fieldName}"`)}}var ptr=rawConstructor();for(fieldName in fields){fields[fieldName].write(ptr,o[fieldName])}if(destructors!==null){destructors.push(rawDestructor,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction:rawDestructor}]})};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){return sharedRegisterType(rawType,registeredInstance,options)}var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>HEAP8[pointer]:pointer=>HEAPU8[pointer];case 2:return signed?pointer=>HEAP16[pointer>>1]:pointer=>HEAPU16[pointer>>1];case 4:return signed?pointer=>HEAP32[pointer>>2]:pointer=>HEAPU32[pointer>>2];case 8:return signed?pointer=>HEAP64[pointer>>3]:pointer=>HEAPU64[pointer>>3];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_bigint=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0n;let fromWireType=value=>value;if(isUnsignedType){const bitSize=size*8;fromWireType=value=>BigInt.asUintN(bitSize,value);maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>{if(typeof value=="number"){value=BigInt(value)}return value},readValueFromPointer:integerReadValueFromPointer(name,size,!isUnsignedType),destructorFunction:null})};var __embind_register_bool=(rawType,name,trueValue,falseValue)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:function(wt){return!!wt},toWireType:function(destructors,o){return o?trueValue:falseValue},readValueFromPointer:function(pointer){return this.fromWireType(HEAPU8[pointer])},destructorFunction:null})};var shallowCopyInternalPointer=o=>({count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType});var throwInstanceAlreadyDeleted=obj=>{function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")};var deletionQueue=[];var flushPendingDeletes=()=>{while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}};var delayFunction;var init_ClassHandle=()=>{let proto=ClassHandle.prototype;Object.assign(proto,{isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;other.$$=other.$$;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right},clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}},delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}},isDeleted(){return!this.$$.ptr},deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}});const symbolDispose=Symbol.dispose;if(symbolDispose){proto[symbolDispose]=proto["delete"]}};function ClassHandle(){}var registeredPointers={};var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(...args){if(!proto[methodName].overloadTable.hasOwnProperty(args.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[args.length].apply(this,args)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module[name].overloadTable.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}var upcastPointer=(ptr,ptrClass,desiredClass)=>{while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr};var embindRepr=v=>{if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}};function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle||!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(()=>clonedHandle["delete"]()));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupported sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}var downcastPointer=(ptr,ptrClass,desiredClass)=>{if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)};var getInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]};var makeClassHandle=(prototype,record)=>{if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record,writable:true}}))};function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}var init_RegisteredPointer=()=>{Object.assign(RegisteredPointer.prototype,{getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr},destructor(ptr){this.rawDestructor?.(ptr)},readValueFromPointer:readPointer,fromWireType:RegisteredPointer_fromWireType})};function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this.toWireType=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this.toWireType=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this.toWireType=genericPointerToWireType}}var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistent public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var wasmTableMirror=[];var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var embind__requireFunction=(signature,rawFunction,isAsync=false)=>{signature=AsciiToString(signature);function makeDynCaller(){var rtn=getWasmTableEntry(rawFunction);return rtn}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};class UnboundTypeError extends Error{}var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};var __embind_register_class=(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor)=>{name=AsciiToString(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);upcast&&=embind__requireFunction(upcastSignature,upcast);downcast&&=embind__requireFunction(downcastSignature,downcast);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],base=>{base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(name,function(...args){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError(`Use 'new' to construct ${name}`)}if(undefined===registeredClass.constructor_body){throw new BindingError(`${name} has no accessible constructor`)}var body=registeredClass.constructor_body[args.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,args)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){registeredClass.baseClass.__derivedClasses??=[];registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})};function usesDestructorStack(argTypes){for(var i=1;i{var array=[];for(var i=0;i>2])}return array};var getFunctionName=signature=>{signature=signature.trim();const argsIndex=signature.indexOf("(");if(argsIndex===-1)return signature;return signature.slice(0,argsIndex)};var __embind_register_class_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}var proto=classType.registeredClass.constructor;if(undefined===proto[methodName]){unboundTypesHandler.argCount=argCount-1;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-1]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));var func=craftInvokerFunction(humanName,invokerArgsArray,null,rawInvoker,fn,isAsync);if(undefined===proto[methodName].overloadTable){func.argCount=argCount-1;proto[methodName]=func}else{proto[methodName].overloadTable[argCount-1]=func}if(classType.registeredClass.__derivedClasses){for(const derivedClass of classType.registeredClass.__derivedClasses){if(!derivedClass.constructor.hasOwnProperty(methodName)){derivedClass.constructor[methodName]=func}}}return[]});return[]})};var __embind_register_class_constructor=(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`constructor ${classType.name}`;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`)}classType.registeredClass.constructor_body[argCount-1]=()=>{throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`,rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{argTypes.splice(1,0,null);classType.registeredClass.constructor_body[argCount-1]=craftInvokerFunction(humanName,argTypes,null,invoker,rawConstructor);return[]});return[]})};var __embind_register_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual,isAsync,isNonnullReturn)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=AsciiToString(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker,isAsync);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context,isAsync);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]});return[]})};var validateThis=(this_,classType,humanName)=>{if(!(this_ instanceof Object)){throwBindingError(`${humanName} with invalid "this": ${this_}`)}if(!(this_ instanceof classType.registeredClass.constructor)){throwBindingError(`${humanName} incompatible with "this" of type ${this_.constructor.name}`)}if(!this_.$$.ptr){throwBindingError(`cannot call emscripten binding method ${humanName} on deleted object`)}return upcastPointer(this_.$$.ptr,this_.$$.ptrType.registeredClass,classType.registeredClass)};var __embind_register_class_property=(classType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{fieldName=AsciiToString(fieldName);getter=embind__requireFunction(getterSignature,getter);whenDependentTypesAreResolved([],[classType],classType=>{classType=classType[0];var humanName=`${classType.name}.${fieldName}`;var desc={get(){throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])},enumerable:true,configurable:true};if(setter){desc.set=()=>throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])}else{desc.set=v=>throwBindingError(humanName+" is a read-only property")}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);whenDependentTypesAreResolved([],setter?[getterReturnType,setterArgumentType]:[getterReturnType],types=>{var getterReturnType=types[0];var desc={get(){var ptr=validateThis(this,classType,humanName+" getter");return getterReturnType.fromWireType(getter(getterContext,ptr))},enumerable:true};if(setter){setter=embind__requireFunction(setterSignature,setter);var setterArgumentType=types[1];desc.set=function(v){var ptr=validateThis(this,classType,humanName+" setter");var destructors=[];setter(setterContext,ptr,setterArgumentType.toWireType(destructors,v));runDestructors(destructors)}}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);return[]});return[]})};var __embind_register_constant=(name,type,value)=>{name=AsciiToString(name);whenDependentTypesAreResolved([],[type],type=>{type=type[0];Module[name]=type.fromWireType(value);return[]})};var __emval_decref=handle=>{if(handle>9&&0===--emval_handles[handle+1]){emval_handles[handle]=undefined;emval_freelist.push(handle)}};var EmValType={name:"emscripten::val",fromWireType:handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},toWireType:(destructors,value)=>Emval.toHandle(value),readValueFromPointer:readPointer,destructorFunction:null};var __embind_register_emval=rawType=>registerType(rawType,EmValType);var enumReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?function(pointer){return this.fromWireType(HEAP8[pointer])}:function(pointer){return this.fromWireType(HEAPU8[pointer])};case 2:return signed?function(pointer){return this.fromWireType(HEAP16[pointer>>1])}:function(pointer){return this.fromWireType(HEAPU16[pointer>>1])};case 4:return signed?function(pointer){return this.fromWireType(HEAP32[pointer>>2])}:function(pointer){return this.fromWireType(HEAPU32[pointer>>2])};default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};function getEnumValueType(rawValueType){return rawValueType===0?"object":rawValueType===1?"number":"string"}var __embind_register_enum=(rawType,name,size,isSigned,rawValueType)=>{name=AsciiToString(name);const valueType=getEnumValueType(rawValueType);switch(valueType){case"object":{function ctor(){}ctor.values={};registerType(rawType,{name,constructor:ctor,valueType,fromWireType:function(c){return this.constructor.values[c]},toWireType:(destructors,c)=>c.value,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor);break}case"number":{var keysMap={};registerType(rawType,{name,keysMap,valueType,fromWireType:c=>c,toWireType:(destructors,c)=>c,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}case"string":{var valuesMap={};var reverseMap={};var keysMap={};registerType(rawType,{name,valuesMap,reverseMap,keysMap,valueType,fromWireType:function(c){return this.reverseMap[c]},toWireType:function(destructors,c){return this.valuesMap[c]},readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,keysMap);delete Module[name].argCount;break}}};var __embind_register_enum_value=(rawEnumType,name,enumValue)=>{var enumType=requireRegisteredType(rawEnumType,"enum");name=AsciiToString(name);switch(enumType.valueType){case"object":{var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(`${enumType.name}_${name}`,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value;break}case"number":{enumType.keysMap[name]=enumValue;break}case"string":{enumType.valuesMap[name]=enumValue;enumType.reverseMap[enumValue]=name;enumType.keysMap[name]=name;break}}};var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this.fromWireType(HEAPF32[pointer>>2])};case 8:return function(pointer){return this.fromWireType(HEAPF64[pointer>>3])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=(rawType,name,size)=>{name=AsciiToString(name);registerType(rawType,{name,fromWireType:value=>value,toWireType:(destructors,value)=>value,readValueFromPointer:floatReadValueFromPointer(name,size),destructorFunction:null})};var __embind_register_function=(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn,isAsync,isNonnullReturn)=>{var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=AsciiToString(name);name=getFunctionName(name);rawInvoker=embind__requireFunction(signature,rawInvoker,isAsync);exposePublicSymbol(name,function(){throwUnboundTypeError(`Cannot call ${name} due to unbound types`,argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn,isAsync),argCount-1);return[]})};var __embind_register_integer=(primitiveType,name,size,minRange,maxRange)=>{name=AsciiToString(name);const isUnsignedType=minRange===0;let fromWireType=value=>value;if(isUnsignedType){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift;maxRange=fromWireType(maxRange)}registerType(primitiveType,{name,fromWireType,toWireType:(destructors,value)=>value,readValueFromPointer:integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})};var installIndexedIterator=(proto,sizeMethodName,getMethodName)=>{const makeIterator=(size,getValue)=>{let index=0;return{next(){if(index>=size){return{done:true}}const current=index;index++;const value=getValue(current);return{value,done:false}},[Symbol.iterator](){return this}}};if(!proto[Symbol.iterator]){proto[Symbol.iterator]=function(){const size=this[sizeMethodName]();return makeIterator(size,i=>this[getMethodName](i))}}};var __embind_register_iterable=(rawClassType,rawElementType,sizeMethodName,getMethodName)=>{sizeMethodName=AsciiToString(sizeMethodName);getMethodName=AsciiToString(getMethodName);whenDependentTypesAreResolved([],[rawClassType,rawElementType],types=>{const classType=types[0];installIndexedIterator(classType.registeredClass.instancePrototype,sizeMethodName,getMethodName);return[]})};var __embind_register_memory_view=(rawType,dataTypeIndex,name)=>{var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=HEAPU32[handle>>2];var data=HEAPU32[handle+4>>2];return new TA(HEAP8.buffer,data,size)}name=AsciiToString(name);registerType(rawType,{name,fromWireType:decodeMemoryView,readValueFromPointer:decodeMemoryView},{ignoreDuplicateRegistrations:true})};var EmValOptionalType=Object.assign({optional:true},EmValType);var __embind_register_optional=(rawOptionalType,rawType)=>{registerType(rawOptionalType,EmValOptionalType)};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var UTF8Decoder=globalThis.TextDecoder&&new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var __embind_register_std_string=(rawType,name)=>{name=AsciiToString(name);var stdStringIsUTF8=true;registerType(rawType,{name,fromWireType(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){str=UTF8ToString(payload,length,true)}else{str="";for(var i=0;i>2]=length;if(valueIsOfTypeString){if(stdStringIsUTF8){stringToUTF8(value,ptr,length+1)}else{for(var i=0;i255){_free(base);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}}else{HEAPU8.set(value,ptr)}if(destructors!==null){destructors.push(_free,base)}return base},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var UTF16Decoder=globalThis.TextDecoder?new TextDecoder("utf-16le"):undefined;var UTF16ToString=(ptr,maxBytesToRead,ignoreNul)=>{var idx=ptr>>1;var endIdx=findStringEnd(HEAPU16,idx,maxBytesToRead/2,ignoreNul);if(endIdx-idx>16&&UTF16Decoder)return UTF16Decoder.decode(HEAPU16.subarray(idx,endIdx));var str="";for(var i=idx;i{maxBytesToWrite??=2147483647;if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead,ignoreNul)=>{var str="";var startIdx=ptr>>2;for(var i=0;!(i>=maxBytesToRead/4);i++){var utf32=HEAPU32[startIdx+i];if(!utf32&&!ignoreNul)break;str+=String.fromCodePoint(utf32)}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i65535){i++}HEAP32[outPtr>>2]=codePoint;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i65535){i++}len+=4}return len};var __embind_register_std_wstring=(rawType,charSize,name)=>{name=AsciiToString(name);var decodeString,encodeString,lengthBytesUTF;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16}else{decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32}registerType(rawType,{name,fromWireType:value=>{var length=HEAPU32[value>>2];var str=decodeString(value+4,length*charSize,true);_free(value);return str},toWireType:(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length/charSize;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var __embind_register_value_object=(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor)=>{structRegistrations[rawType]={name:AsciiToString(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}};var __embind_register_value_object_field=(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{structRegistrations[structType].fields.push({fieldName:AsciiToString(fieldName),getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext,setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext})};var __embind_register_void=(rawType,name)=>{name=AsciiToString(name);registerType(rawType,{isVoid:true,name,fromWireType:()=>undefined,toWireType:(destructors,o)=>undefined})};var runtimeKeepaliveCounter=0;var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var emval_methodCallers=[];var emval_addMethodCaller=caller=>{var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id};var emval_lookupTypes=(argCount,argTypes)=>{var a=new Array(argCount);for(var i=0;i>2],`parameter ${i}`)}return a};var emval_returnValue=(toReturnWire,destructorsRef,handle)=>{var destructors=[];var result=toReturnWire(destructors,handle);if(destructors.length){HEAPU32[destructorsRef>>2]=Emval.toHandle(destructors)}return result};var emval_symbols={};var getStringOrSymbol=address=>{var symbol=emval_symbols[address];if(symbol===undefined){return AsciiToString(address)}return symbol};var __emval_create_invoker=(argCount,argTypesPtr,kind)=>{var GenericWireTypeSize=8;var[retType,...argTypes]=emval_lookupTypes(argCount,argTypesPtr);var toReturnWire=retType.toWireType.bind(retType);var argFromPtr=argTypes.map(type=>type.readValueFromPointer.bind(type));argCount--;var argN=new Array(argCount);var invokerFunction=(handle,methodName,destructorsRef,args)=>{var offset=0;for(var i=0;it.name)}) => ${retType.name}>`;return emval_addMethodCaller(createNamedFunction(functionName,invokerFunction))};var __emval_invoke=(caller,handle,methodName,destructorsRef,args)=>emval_methodCallers[caller](handle,methodName,destructorsRef,args);var __emval_new_cstring=v=>Emval.toHandle(getStringOrSymbol(v));var __emval_new_object=()=>Emval.toHandle({});var __emval_run_destructors=handle=>{var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)};var __emval_set_property=(handle,key,value)=>{handle=Emval.toValue(handle);key=Emval.toValue(key);value=Emval.toValue(value);handle[key]=value};var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{return func()}catch(e){handleException(e)}finally{maybeExit()}};var _emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()))},timeout_ms);timers[which]={id,timeout_ms};return 0};var _emscripten_date_now=()=>Date.now();var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var printCharBuffers=[null,[],[]];var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer));buffer.length=0}else{buffer.push(curr)}};var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0};init_ClassHandle();init_RegisteredPointer();{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}var ___getTypeName,_free,_malloc,__emscripten_timeout,memory,__indirect_function_table,wasmMemory,wasmTable;function assignWasmExports(wasmExports){___getTypeName=wasmExports["Q"];_free=Module["_free"]=wasmExports["R"];_malloc=Module["_malloc"]=wasmExports["S"];__emscripten_timeout=wasmExports["U"];memory=wasmMemory=wasmExports["O"];__indirect_function_table=wasmTable=wasmExports["T"]}var wasmImports={J:__abort_js,x:__embind_create_inheriting_constructor,s:__embind_finalize_value_object,z:__embind_register_bigint,A:__embind_register_bool,b:__embind_register_class,p:__embind_register_class_class_function,e:__embind_register_class_constructor,a:__embind_register_class_function,d:__embind_register_class_property,K:__embind_register_constant,M:__embind_register_emval,l:__embind_register_enum,f:__embind_register_enum_value,y:__embind_register_float,g:__embind_register_function,o:__embind_register_integer,q:__embind_register_iterable,h:__embind_register_memory_view,r:__embind_register_optional,N:__embind_register_std_string,u:__embind_register_std_wstring,t:__embind_register_value_object,m:__embind_register_value_object_field,B:__embind_register_void,D:__emscripten_runtime_keepalive_clear,k:__emval_create_invoker,n:__emval_decref,j:__emval_invoke,v:__emval_new_cstring,L:__emval_new_object,i:__emval_run_destructors,w:__emval_set_property,E:__setitimer_js,I:_emscripten_date_now,c:_emscripten_get_now,F:_emscripten_resize_heap,G:_exit,H:_fd_write,C:_proc_exit};function run(){preRun();function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})} ;return moduleRtn}})();if(typeof exports==="object"&&typeof module==="object"){module.exports=PHYSX;module.exports.default=PHYSX}else if(typeof define==="function"&&define["amd"])define([],()=>PHYSX); diff --git a/packages/physics-physx/libs/physx.release.simd.wasm b/packages/physics-physx/libs/physx.release.simd.wasm index 91e5bab34b..f52b48110a 100755 Binary files a/packages/physics-physx/libs/physx.release.simd.wasm and b/packages/physics-physx/libs/physx.release.simd.wasm differ diff --git a/packages/physics-physx/libs/physx.release.wasm b/packages/physics-physx/libs/physx.release.wasm index d9e03eee6a..3efb26a288 100755 Binary files a/packages/physics-physx/libs/physx.release.wasm and b/packages/physics-physx/libs/physx.release.wasm differ diff --git a/packages/physics-physx/package.json b/packages/physics-physx/package.json index 3cdabdd9a9..c7710f0e7e 100644 --- a/packages/physics-physx/package.json +++ b/packages/physics-physx/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-physics-physx", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" diff --git a/packages/physics-physx/src/PhysXPhysics.ts b/packages/physics-physx/src/PhysXPhysics.ts index 77ca0b6157..6c5d788aa1 100644 --- a/packages/physics-physx/src/PhysXPhysics.ts +++ b/packages/physics-physx/src/PhysXPhysics.ts @@ -67,10 +67,10 @@ export class PhysXPhysics implements IPhysics { this._runTimeMode = runtimeMode; this._wasmSIMDModeUrl = runtimeUrls?.wasmSIMDModeUrl ?? - "https://mdn.alipayobjects.com/rms/afts/file/A*FHYHS4_ZL5UAAAAAQ4AAAAgAehQnAQ/physx.release.simd.js"; + "https://mdn.alipayobjects.com/rms/afts/file/A*iHrYQKBrgTAAAAAAQ4AAAAgAehQnAQ/physx.release.simd.js"; this._wasmModeUrl = runtimeUrls?.wasmModeUrl ?? - "https://mdn.alipayobjects.com/rms/afts/file/A*2fv0RLMK1d0AAAAAQ4AAAAgAehQnAQ/physx.release.js"; + "https://mdn.alipayobjects.com/rms/afts/file/A*DFuvR6Mv5C0AAAAAQ4AAAAgAehQnAQ/physx.release.js"; } /** diff --git a/packages/physics-physx/src/PhysXPhysicsScene.ts b/packages/physics-physx/src/PhysXPhysicsScene.ts index a56a1fabce..b42c51c8a8 100644 --- a/packages/physics-physx/src/PhysXPhysicsScene.ts +++ b/packages/physics-physx/src/PhysXPhysicsScene.ts @@ -50,7 +50,9 @@ export class PhysXPhysicsScene implements IPhysicsScene { this._pxRaycastHit = new physX.PxRaycastHit(); this._pxFilterData = new physX.PxQueryFilterData(); - this._pxFilterData.flags = new physX.PxQueryFlags(QueryFlag.STATIC | QueryFlag.DYNAMIC | QueryFlag.PRE_FILTER); + this._pxFilterData.flags = new physX.PxQueryFlags( + QueryFlag.STATIC | QueryFlag.DYNAMIC | QueryFlag.PRE_FILTER | QueryFlag.POST_FILTER + ); const triggerCallback = { onContactBegin: (collision) => { @@ -214,6 +216,12 @@ export class PhysXPhysicsScene implements IPhysicsScene { } else { return 0; // eNONE } + }, + postFilter: (filterData, distance) => { + if (distance <= 0) { + return 0; // eNONE — skip initial overlap + } + return 2; // eBLOCK } }; @@ -452,6 +460,12 @@ export class PhysXPhysicsScene implements IPhysicsScene { } else { return 0; // eNONE } + }, + postFilter: (filterData, distance) => { + if (distance <= 0) { + return 0; // eNONE — skip initial overlap + } + return 2; // eBLOCK } }; diff --git a/packages/rhi-webgl/package.json b/packages/rhi-webgl/package.json index 9d22c1e383..5e49b49847 100644 --- a/packages/rhi-webgl/package.json +++ b/packages/rhi-webgl/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-rhi-webgl", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "repository": { "url": "https://github.com/galacean/engine.git" }, diff --git a/packages/rhi-webgl/src/GLBuffer.ts b/packages/rhi-webgl/src/GLBuffer.ts index 87f635dba9..aea7b38842 100644 --- a/packages/rhi-webgl/src/GLBuffer.ts +++ b/packages/rhi-webgl/src/GLBuffer.ts @@ -21,7 +21,18 @@ export class GLBuffer implements IPlatformBuffer { const gl = rhi.gl; const glBuffer = gl.createBuffer(); const glBufferUsage = this._getGLBufferUsage(gl, bufferUsage); - const glBindTarget = type === BufferBindFlag.VertexBuffer ? gl.ARRAY_BUFFER : gl.ELEMENT_ARRAY_BUFFER; + let glBindTarget: number; + switch (type) { + case BufferBindFlag.VertexBuffer: + glBindTarget = gl.ARRAY_BUFFER; + break; + case BufferBindFlag.IndexBuffer: + glBindTarget = gl.ELEMENT_ARRAY_BUFFER; + break; + case BufferBindFlag.ConstantBuffer: + glBindTarget = (gl).UNIFORM_BUFFER; + break; + } this._gl = gl; this._glBuffer = glBuffer; this._glBufferUsage = glBufferUsage; diff --git a/packages/rhi-webgl/src/GLPrimitive.ts b/packages/rhi-webgl/src/GLPrimitive.ts index fa7d89f1e8..b679bc4699 100644 --- a/packages/rhi-webgl/src/GLPrimitive.ts +++ b/packages/rhi-webgl/src/GLPrimitive.ts @@ -118,6 +118,7 @@ export class GLPrimitive implements IPlatformPrimitive { const element = attributes[name]; if (element) { + if(!vertexBufferBindings[element.bindingIndex]) continue; const { buffer, stride } = vertexBufferBindings[element.bindingIndex]; vbo = buffer._platformBuffer._glBuffer; // prevent binding the vbo which already bound at the last loop, e.g. a buffer with multiple attributes. diff --git a/packages/rhi-webgl/src/WebGLGraphicDevice.ts b/packages/rhi-webgl/src/WebGLGraphicDevice.ts index c937742f36..7394b0409a 100644 --- a/packages/rhi-webgl/src/WebGLGraphicDevice.ts +++ b/packages/rhi-webgl/src/WebGLGraphicDevice.ts @@ -89,6 +89,8 @@ export interface WebGLGraphicDeviceOptions { * WebGL graphic device, including WebGL1.0 and WebGL2.0. */ export class WebGLGraphicDevice implements IHardwareRenderer { + maxUniformBlockSize: number; + /** @internal */ _readFrameBuffer: WebGLFramebuffer = null; /** @internal */ @@ -280,6 +282,20 @@ export class WebGLGraphicDevice implements IHardwareRenderer { return new GLTransformFeedbackPrimitive(this._gl); } + bindUniformBufferBase(bindingPoint: number, buffer: IPlatformBuffer): void { + const gl = this._gl; + gl.bindBufferBase(gl.UNIFORM_BUFFER, bindingPoint, (buffer)._glBuffer); + } + + bindUniformBlock(program: WebGLProgram, blockName: string, bindingPoint: number): number { + const gl = this._gl; + const blockIndex = gl.getUniformBlockIndex(program, blockName); + if (blockIndex !== gl.INVALID_INDEX) { + gl.uniformBlockBinding(program, blockIndex, bindingPoint); + } + return blockIndex; + } + /** * Enable GL_RASTERIZER_DISCARD (WebGL2 only). */ @@ -623,6 +639,11 @@ export class WebGLGraphicDevice implements IHardwareRenderer { if (debugRenderInfo != null) { this._renderer = gl.getParameter(debugRenderInfo.UNMASKED_RENDERER_WEBGL); } + if (this._isWebGL2) { + this.maxUniformBlockSize = (gl).getParameter( + (gl).MAX_UNIFORM_BLOCK_SIZE + ); + } } destroy(): void { diff --git a/packages/shader-lab/package.json b/packages/shader-lab/package.json index c6220b9a53..256e0eed35 100644 --- a/packages/shader-lab/package.json +++ b/packages/shader-lab/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-shaderlab", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" diff --git a/packages/shader-lab/src/Preprocessor.ts b/packages/shader-lab/src/Preprocessor.ts index 17e907da73..8f3e1abb27 100644 --- a/packages/shader-lab/src/Preprocessor.ts +++ b/packages/shader-lab/src/Preprocessor.ts @@ -5,6 +5,7 @@ import { ShaderLib } from "@galacean/engine"; export enum MacroValueType { Number, // 1, 1.1 Symbol, // variable name + MemberAccess, // member access, e.g. input.v_uv, v.rgb FunctionCall, // function call, e.g. clamp(a, 0.0, 1.0) Other // shaderLab does not check this } @@ -27,6 +28,7 @@ export class Preprocessor { private static readonly _macroRegex = /^\s*#define\s+(\w+)[ ]*(\(([^)]*)\))?[ ]+(\(?\w+\)?.*?)(?:\/\/.*|\/\*.*?\*\/)?\s*$/gm; private static readonly _symbolReg = /^[a-zA-Z_][a-zA-Z0-9_]*$/; + private static readonly _memberAccessReg = /^([a-zA-Z_][a-zA-Z0-9_]*)(\.[a-zA-Z_][a-zA-Z0-9_]*)+$/; private static readonly _funcCallReg = /^([a-zA-Z_][a-zA-Z0-9_]*)\s*\((.*)\)$/; private static readonly _macroDefineIncludeMap = new Map(); @@ -61,6 +63,10 @@ export class Preprocessor { const referencedName = valueType === MacroValueType.FunctionCall ? info.functionCallName : info.value; if (info.params.indexOf(referencedName) !== -1) continue; if (out.indexOf(referencedName) === -1) out.push(referencedName); + } else if (valueType === MacroValueType.MemberAccess) { + // Extract root symbol: "input.v_uv" → "input" + const rootName = info.value.substring(0, info.value.indexOf(".")); + if (out.indexOf(rootName) === -1) out.push(rootName); } else if (valueType === MacroValueType.Other) { // #if _VERBOSE Logger.warn( @@ -110,6 +116,8 @@ export class Preprocessor { valueType = MacroValueType.Number; } else if (this._symbolReg.test(value)) { valueType = MacroValueType.Symbol; + } else if (this._memberAccessReg.test(value)) { + valueType = MacroValueType.MemberAccess; } else { const callMatch = this._funcCallReg.exec(value); if (callMatch) { diff --git a/packages/shader-lab/src/codeGen/CodeGenVisitor.ts b/packages/shader-lab/src/codeGen/CodeGenVisitor.ts index 35beaa1d98..f4d560c987 100644 --- a/packages/shader-lab/src/codeGen/CodeGenVisitor.ts +++ b/packages/shader-lab/src/codeGen/CodeGenVisitor.ts @@ -31,13 +31,19 @@ export abstract class CodeGenVisitor { protected static _tmpArrayPool = new ReturnableObjectPool(TempArray, 10); + protected static readonly _memberAccessReg = /\b(\w+)\.(\w+)\b/g; + defaultCodeGen(children: NodeChild[]) { const pool = CodeGenVisitor._tmpArrayPool; let ret = pool.get(); ret.dispose(); for (const child of children) { if (child instanceof BaseToken) { - ret.array.push(child.lexeme); + if (child.type === Keyword.MACRO_DEFINE_EXPRESSION) { + ret.array.push(this._transformMacroDefineValue(child.lexeme)); + } else { + ret.array.push(child.lexeme); + } } else { ret.array.push(child.codeGen(this)); } @@ -46,6 +52,32 @@ export abstract class CodeGenVisitor { return ret.array.join(" "); } + protected _transformMacroDefineValue( + lexeme: string, + overrideMap?: Record + ): string { + const context = VisitorContext.context; + const structVarMap = overrideMap ?? context._structVarMap; + if (!structVarMap) return lexeme; + + const spaceIdx = lexeme.indexOf(" "); + if (spaceIdx === -1) return lexeme; + + const macroName = lexeme.substring(0, spaceIdx); + let value = lexeme.substring(spaceIdx); + + const reg = CodeGenVisitor._memberAccessReg; + reg.lastIndex = 0; + value = value.replace(reg, (match, varName, propName) => { + const role = structVarMap[varName]; + if (!role) return match; + context.referenceStructPropByName(role, propName); + return propName; + }); + + return macroName + value; + } + visitPostfixExpression(node: ASTNode.PostfixExpression): string { const children = node.children; const derivationLength = children.length; @@ -212,7 +244,19 @@ export abstract class CodeGenVisitor { const children = node.children; const fullType = children[0]; if (fullType instanceof ASTNode.FullySpecifiedType && fullType.typeSpecifier.isCustom) { - VisitorContext.context.referenceGlobal(fullType.type, ESymbolType.STRUCT); + const context = VisitorContext.context; + const typeLexeme = fullType.typeSpecifier.lexeme; + const role = context.getStructRole(typeLexeme); + if (role) { + // Global variable of a varying/attribute/mrt struct type (e.g. "Varyings o;"). + // Don't output as uniform; register the variable in struct var maps instead. + const ident = children[1]; + if (ident instanceof BaseToken) { + context.registerStructVar(ident.lexeme, role); + } + return ""; + } + context.referenceGlobal(fullType.type, ESymbolType.STRUCT); } return `uniform ${this.defaultCodeGen(children)}`; } @@ -351,6 +395,8 @@ export abstract class CodeGenVisitor { const fnName = fnNode.protoType.ident.lexeme; const context = VisitorContext.context; + this._collectStructVars(fnNode, context); + if (fnName == context.stageEntry) { const statements = fnNode.statements.codeGen(this); return `void main() ${statements}`; @@ -359,6 +405,74 @@ export abstract class CodeGenVisitor { } } + private _collectStructVars(fnNode: ASTNode.FunctionDefinition, context: VisitorContext): void { + const map = context._structVarMap; + // Clear previous function's mappings + for (const key in map) delete map[key]; + + // Collect from function parameters + const paramList = fnNode.protoType.parameterList; + if (paramList) { + for (const param of paramList) { + if (param.ident && param.typeInfo && typeof param.typeInfo.type === "string") { + const role = context.getStructRole(param.typeInfo.typeLexeme); + if (role) map[param.ident.lexeme] = role; + } + } + } + + // Collect from local variable declarations in function body + this._collectStructVarsFromNode(fnNode.statements, context, map); + } + + private _collectStructVarsFromNode( + node: TreeNode, + context: VisitorContext, + map: Record + ): void { + const children = node.children; + for (let i = 0; i < children.length; i++) { + const child = children[i]; + if (child instanceof ASTNode.InitDeclaratorList) { + const typeLexeme = child.typeInfo?.typeLexeme; + if (typeLexeme) { + const role = context.getStructRole(typeLexeme); + if (role) { + // Extract variable name from SingleDeclaration or comma-separated identifiers + this._extractVarNamesFromInitDeclaratorList(child, map, role); + } + } + } else if (child instanceof TreeNode) { + this._collectStructVarsFromNode(child, context, map); + } + } + } + + protected _extractVarNamesFromInitDeclaratorList( + node: ASTNode.InitDeclaratorList, + map: Record, + role: "varying" | "attribute" | "mrt" + ): void { + const children = node.children; + if (children.length === 1) { + // SingleDeclaration: type ident + const singleDecl = children[0] as ASTNode.SingleDeclaration; + const identChildren = singleDecl.children; + if (identChildren.length >= 2 && identChildren[1] instanceof BaseToken) { + map[identChildren[1].lexeme] = role; + } + } else if (children.length >= 3) { + // InitDeclaratorList , ident ... + const initDeclList = children[0]; + if (initDeclList instanceof ASTNode.InitDeclaratorList) { + this._extractVarNamesFromInitDeclaratorList(initDeclList, map, role); + } + if (children[2] instanceof BaseToken) { + map[children[2].lexeme] = role; + } + } + } + protected _reportError(loc: ShaderRange | ShaderPosition, message: string): void { // #if _VERBOSE this.errors.push(new GSError(GSErrorName.CompilationError, message, loc, ShaderLab._processingPassText)); diff --git a/packages/shader-lab/src/codeGen/GLES100.ts b/packages/shader-lab/src/codeGen/GLES100.ts index 995dccdeec..2c2e0faa93 100644 --- a/packages/shader-lab/src/codeGen/GLES100.ts +++ b/packages/shader-lab/src/codeGen/GLES100.ts @@ -47,7 +47,7 @@ export class GLES100Visitor extends GLESVisitor { return ""; } const expression = node.children[1] as ASTNode.Expression; - return `gl_FragColor = ${expression.codeGen(this)}`; + return `gl_FragColor = ${expression.codeGen(this)};`; } return super.visitJumpStatement(node); } diff --git a/packages/shader-lab/src/codeGen/GLESVisitor.ts b/packages/shader-lab/src/codeGen/GLESVisitor.ts index fbf611729f..d7596ae9ab 100644 --- a/packages/shader-lab/src/codeGen/GLESVisitor.ts +++ b/packages/shader-lab/src/codeGen/GLESVisitor.ts @@ -5,6 +5,7 @@ import { Keyword } from "../common/enums/Keyword"; import { ASTNode, TreeNode } from "../parser/AST"; import { ShaderData } from "../parser/ShaderInfo"; import { ESymbolType, FnSymbol, StructSymbol, SymbolInfo } from "../parser/symbolTable"; +import { NodeChild } from "../parser/types"; import { CodeGenVisitor } from "./CodeGenVisitor"; import { ICodeSegment } from "./types"; import { VisitorContext } from "./VisitorContext"; @@ -37,10 +38,15 @@ export abstract class GLESVisitor extends CodeGenVisitor { this.reset(); const shaderData = node.shaderData; - VisitorContext.context._passSymbolTable = shaderData.symbolTable; + const context = VisitorContext.context; + context._passSymbolTable = shaderData.symbolTable; const outerGlobalMacroDeclarations = shaderData.getOuterGlobalMacroDeclarations(); + // Build combined _globalStructVarMap from both entry functions before per-stage processing. + // This must happen here because vertex runs first and doesn't yet know fragment's variables. + this._buildGlobalStructVarMap(vertexEntry, fragmentEntry, shaderData, outerGlobalMacroDeclarations, context); + return { vertex: this._vertexMain(vertexEntry, shaderData, outerGlobalMacroDeclarations), fragment: this._fragmentMain(fragmentEntry, shaderData, outerGlobalMacroDeclarations) @@ -109,6 +115,9 @@ export abstract class GLESVisitor extends CodeGenVisitor { } }); + // Pre-register global #define member access references for this stage + this._registerGlobalMacroReferences(outerGlobalMacroDeclarations, context); + const globalCodeArray = this._globalCodeArray; VisitorContext.context.referenceGlobal(entry, ESymbolType.FN); @@ -173,6 +182,9 @@ export abstract class GLESVisitor extends CodeGenVisitor { } }); + // Pre-register global #define member access references for this stage + this._registerGlobalMacroReferences(outerGlobalMacroStatements, context); + const globalCodeArray = this._globalCodeArray; VisitorContext.context.referenceGlobal(entry, ESymbolType.FN); @@ -193,10 +205,178 @@ export abstract class GLESVisitor extends CodeGenVisitor { return globalCode; } + /** + * Build _globalStructVarMap from both entry functions before per-stage processing. + * Classifies struct types by their position in function signatures: + * - vertex param[0] → attribute, vertex return type → varying + * - fragment param[0] → varying, fragment return type → mrt + */ + private _buildGlobalStructVarMap( + vertexEntry: string, + fragmentEntry: string, + data: ShaderData, + globalMacros: ASTNode.GlobalDeclaration[], + context: VisitorContext + ): void { + const map = context._globalStructVarMap; + const lookupSymbol = GLESVisitor._lookupSymbol; + const { symbolTable } = data; + + // Map struct type names to roles based on function signature positions + const structTypeRoles: Record = Object.create(null); + + // Vertex entry: param[0] type → attribute, return type → varying + lookupSymbol.set(vertexEntry, ESymbolType.FN); + const vertexFns = symbolTable.getSymbols(lookupSymbol, true, []); + for (const fn of vertexFns) { + const proto = fn.astNode.protoType; + const param0 = proto.parameterList?.[0]; + if (param0 && typeof param0.typeInfo.type === "string") { + structTypeRoles[param0.typeInfo.typeLexeme] = "attribute"; + } + if (typeof proto.returnType.type === "string") { + structTypeRoles[proto.returnType.type] = "varying"; + } + } + + // Fragment entry: param[0] type → varying, return type → mrt + lookupSymbol.set(fragmentEntry, ESymbolType.FN); + const fragmentFns = symbolTable.getSymbols(lookupSymbol, true, []); + for (const fn of fragmentFns) { + const proto = fn.astNode.protoType; + const param0 = proto.parameterList?.[0]; + if (param0 && typeof param0.typeInfo.type === "string") { + structTypeRoles[param0.typeInfo.typeLexeme] = "varying"; + } + if (typeof proto.returnType.type === "string") { + structTypeRoles[proto.returnType.type] = "mrt"; + } + } + + // Scan all entry functions' params and local vars, classify by structTypeRoles + for (const fn of [...vertexFns, ...fragmentFns]) { + const fnNode = fn.astNode; + const paramList = fnNode.protoType.parameterList; + if (paramList) { + for (const param of paramList) { + if (param.ident && param.typeInfo && typeof param.typeInfo.type === "string") { + const role = structTypeRoles[param.typeInfo.typeLexeme]; + if (role) map[param.ident.lexeme] = role; + } + } + } + this._collectStructVarsFromBody(fnNode.statements, structTypeRoles, map); + } + + // Also scan global macros for root variable names that might be global struct variables. + // e.g. #define VSOutput_worldPos o.v_worldPos → root "o" → look up in symbol table + let hasRoles = false; + for (const _ in structTypeRoles) { + hasRoles = true; + break; + } + if (hasRoles) { + const checked = new Set(); + const symOut: SymbolInfo[] = []; + this._forEachMacroMemberAccess(globalMacros, (rootName) => { + if (map[rootName] || checked.has(rootName)) return; + checked.add(rootName); + lookupSymbol.set(rootName, ESymbolType.VAR); + symbolTable.getSymbols(lookupSymbol, true, symOut); + for (const sym of symOut) { + if (sym.dataType) { + const role = structTypeRoles[sym.dataType.typeLexeme]; + if (role) { + map[rootName] = role; + break; + } + } + } + }); + } + } + + private _collectStructVarsFromBody( + node: TreeNode, + structTypeRoles: Record, + map: Record + ): void { + const children = node.children; + for (let i = 0; i < children.length; i++) { + const child = children[i]; + if (child instanceof ASTNode.InitDeclaratorList) { + const typeLexeme = child.typeInfo?.typeLexeme; + if (typeLexeme) { + const role = structTypeRoles[typeLexeme]; + if (role) { + this._extractVarNamesFromInitDeclaratorList(child, map, role); + } + } + } else if (child instanceof TreeNode) { + this._collectStructVarsFromBody(child, structTypeRoles, map); + } + } + } + + /** + * Pre-register attribute/varying/mrt references from global #define member access patterns, + * so that declarations are emitted by _getCustomStruct for the current stage. + */ + private _registerGlobalMacroReferences(globalMacros: ASTNode.GlobalDeclaration[], context: VisitorContext): void { + const map = context._globalStructVarMap; + let hasEntries = false; + for (const _ in map) { + hasEntries = true; + break; + } + if (!hasEntries) return; + this._forEachMacroMemberAccess(globalMacros, (rootName, propName) => { + const role = map[rootName]; + if (role) context.referenceStructPropByName(role, propName); + }); + } + + /** + * Traverse global macro declarations, extracting member access patterns (e.g. "o.v_uv") + * and invoking the callback with (rootName, propName) for each match. + */ + private _forEachMacroMemberAccess( + macros: ASTNode.GlobalDeclaration[], + callback: (rootName: string, propName: string) => void + ): void { + const reg = CodeGenVisitor._memberAccessReg; + for (const macro of macros) { + this._walkMacroChildren(macro.children, reg, callback); + } + } + + private _walkMacroChildren( + children: NodeChild[], + reg: RegExp, + callback: (rootName: string, propName: string) => void + ): void { + for (const child of children) { + if (child instanceof BaseToken && child.type === Keyword.MACRO_DEFINE_EXPRESSION) { + const spaceIdx = child.lexeme.indexOf(" "); + if (spaceIdx === -1) continue; + const value = child.lexeme.substring(spaceIdx); + reg.lastIndex = 0; + let match: RegExpExecArray | null; + while ((match = reg.exec(value)) !== null) { + callback(match[1], match[2]); + } + } else if (child instanceof TreeNode) { + this._walkMacroChildren(child.children, reg, callback); + } + } + } + private _getGlobalSymbol(out: ICodeSegment[]): void { - const { _referencedGlobals } = VisitorContext.context; + const context = VisitorContext.context; + const { _referencedGlobals } = context; - const lastLength = Object.keys(_referencedGlobals).length; + let lastLength = 0; + for (const _ in _referencedGlobals) lastLength++; if (lastLength === 0) return; for (const ident in _referencedGlobals) { @@ -206,7 +386,9 @@ export abstract class GLESVisitor extends CodeGenVisitor { const symbols = _referencedGlobals[ident]; for (let i = 0; i < symbols.length; i++) { const sm = symbols[i]; - const text = sm.astNode.codeGen(this) + (sm.type === ESymbolType.VAR ? ";" : ""); + const codeGenResult = sm.astNode.codeGen(this); + if (!codeGenResult) continue; + const text = codeGenResult + (sm.type === ESymbolType.VAR ? ";" : ""); if (!sm.isInMacroBranch) { out.push({ text, @@ -216,7 +398,9 @@ export abstract class GLESVisitor extends CodeGenVisitor { } } - if (Object.keys(_referencedGlobals).length !== lastLength) { + let newLength = 0; + for (const _ in _referencedGlobals) newLength++; + if (newLength !== lastLength) { this._getGlobalSymbol(out); } } @@ -233,6 +417,7 @@ export abstract class GLESVisitor extends CodeGenVisitor { private _getGlobalMacroDeclarations(macros: ASTNode.GlobalDeclaration[], out: ICodeSegment[]): void { const context = VisitorContext.context; + const globalMap = context._globalStructVarMap; const referencedGlobals = context._referencedGlobals; const referencedGlobalMacroASTs = context._referencedGlobalMacroASTs; referencedGlobalMacroASTs.length = 0; @@ -253,7 +438,12 @@ export abstract class GLESVisitor extends CodeGenVisitor { let result: ICodeSegment[] = []; result.push( ...macro.macroExpressions.map((item) => ({ - text: item instanceof BaseToken ? item.lexeme : item.codeGen(this), + text: + item instanceof BaseToken + ? item.type === Keyword.MACRO_DEFINE_EXPRESSION + ? this._transformMacroDefineValue(item.lexeme, globalMap) + : item.lexeme + : item.codeGen(this), index: item.location.start.index })) ); @@ -264,6 +454,8 @@ export abstract class GLESVisitor extends CodeGenVisitor { .sort((a, b) => a.index - b.index) .map((item) => item.text) .join("\n"); + } else if (child instanceof BaseToken && child.type === Keyword.MACRO_DEFINE_EXPRESSION) { + text = this._transformMacroDefineValue(child.lexeme, globalMap); } else { text = macro.codeGen(this); } diff --git a/packages/shader-lab/src/codeGen/VisitorContext.ts b/packages/shader-lab/src/codeGen/VisitorContext.ts index 25211f008a..1c1972c0db 100644 --- a/packages/shader-lab/src/codeGen/VisitorContext.ts +++ b/packages/shader-lab/src/codeGen/VisitorContext.ts @@ -38,6 +38,10 @@ export class VisitorContext { _referencedMRTList: Record; _referencedGlobals: Record; _referencedGlobalMacroASTs: TreeNode[] = []; + /** Maps variable names to their struct role for function-body #define value transformation. */ + _structVarMap: Record; + /** Combined mapping from all entry functions for global #define transformation. */ + _globalStructVarMap: Record; _passSymbolTable: SymbolTable; @@ -56,6 +60,36 @@ export class VisitorContext { this._referencedMRTList = Object.create(null); this._referencedGlobals = Object.create(null); this._referencedGlobalMacroASTs.length = 0; + this._structVarMap = Object.create(null); + if (resetAll) { + this._globalStructVarMap = Object.create(null); + } + } + + getStructRole(typeLexeme: string): "varying" | "attribute" | "mrt" | undefined { + if (this.isAttributeStruct(typeLexeme)) return "attribute"; + if (this.isVaryingStruct(typeLexeme)) return "varying"; + if (this.isMRTStruct(typeLexeme)) return "mrt"; + } + + registerStructVar(varName: string, role: "varying" | "attribute" | "mrt"): void { + this._structVarMap[varName] = role; + this._globalStructVarMap[varName] = role; + } + + referenceStructPropByName(role: "varying" | "attribute" | "mrt", propName: string): void { + const list = role === "varying" ? this.varyingList : role === "attribute" ? this.attributeList : this.mrtList; + const refList = + role === "varying" + ? this._referencedVaryingList + : role === "attribute" + ? this._referencedAttributeList + : this._referencedMRTList; + if (refList[propName]) return; + const props = list.filter((item) => item.ident.lexeme === propName); + if (props.length) { + refList[propName] = props; + } } isAttributeStruct(type: string) { diff --git a/packages/shader-lab/src/macroProcessor/MacroParser.ts b/packages/shader-lab/src/macroProcessor/MacroParser.ts index d845102e1a..a2ed90c504 100644 --- a/packages/shader-lab/src/macroProcessor/MacroParser.ts +++ b/packages/shader-lab/src/macroProcessor/MacroParser.ts @@ -355,7 +355,7 @@ export class MacroParser { scanner.advance(1); scanner.skipSpace(false); const parenExpr = this._parseParenthesisExpression(scanner); - if ((operator === "!" && typeof parenExpr !== "boolean") || (operator !== "!" && typeof parenExpr !== "number")) { + if (operator !== "!" && typeof parenExpr !== "number") { this._reportError(opPos, "invalid operator.", scanner.source, scanner.file); } diff --git a/packages/shader-lab/src/parser/AST.ts b/packages/shader-lab/src/parser/AST.ts index 4c90c01444..243944df8f 100644 --- a/packages/shader-lab/src/parser/AST.ts +++ b/packages/shader-lab/src/parser/AST.ts @@ -4,7 +4,7 @@ import { ETokenType, GalaceanDataType, ShaderRange, TokenType, TypeAny } from ". import { BaseToken } from "../common/BaseToken"; import { Keyword } from "../common/enums/Keyword"; import { ParserUtils } from "../ParserUtils"; -import { Preprocessor } from "../Preprocessor"; +import { MacroValueType, Preprocessor } from "../Preprocessor"; import { ShaderLabUtils } from "../ShaderLabUtils"; import { BuiltinFunction, BuiltinVariable, NonGenericGalaceanType } from "./builtin"; import { NoneTerminal } from "./GrammarSymbol"; @@ -1424,7 +1424,12 @@ export namespace ASTNode { sa.reportWarning(this.location, `Please sure the identifier "${name}" will be declared before used.`); // #endif } else { - this.typeInfo = symbols[0].dataType?.type; + // For member access macros (e.g. #define FRAG_UV v.v_uv), the referenceSymbolNames + // contains the root variable ("v") whose type is the struct ("Varyings"), not the + // member type ("vec2"). Skip type inference in this case — keep TypeAny. + if (child instanceof BaseToken || !this._isMemberAccessMacro(sa, child)) { + this.typeInfo = symbols[0].dataType?.type; + } const currentScopeSymbol = sa.symbolTableStack.scope.getSymbol(lookupSymbol, true); if (currentScopeSymbol) { if ( @@ -1443,6 +1448,12 @@ export namespace ASTNode { } } + private _isMemberAccessMacro(sa: SemanticAnalyzer, child: MacroCallSymbol | MacroCallFunction): boolean { + const macroName = child.macroName; + const infos = sa.macroDefineList[macroName]; + return infos?.some((info) => info.valueType === MacroValueType.MemberAccess) ?? false; + } + override codeGen(visitor: CodeGenVisitor): string { return this.setCache(visitor.visitVariableIdentifier(this)); } diff --git a/packages/shader-lab/src/parser/builtin/functions.ts b/packages/shader-lab/src/parser/builtin/functions.ts index 46c0d49d29..859951641c 100644 --- a/packages/shader-lab/src/parser/builtin/functions.ts +++ b/packages/shader-lab/src/parser/builtin/functions.ts @@ -26,6 +26,39 @@ function isGenericType(t: BuiltinType) { return t >= EGenType.GenType && t <= EGenType.GSampler2DArray; } +/** + * Resolve a generic return type from the actual type of a generic parameter. + * + * For GVec4 return type, maps sampler variants to the correct vec4 type: + * sampler2D/sampler3D/samplerCube → vec4 + * isampler2D/isampler3D/... → ivec4 + * usampler2D/usampler3D/... → uvec4 + * + * For all other generic return types (GenType etc.), passes through the actual param type directly. + */ +function resolveGenericReturnType( + genericReturnType: EGenType, + actualParamType: NonGenericGalaceanType +): NonGenericGalaceanType { + if (genericReturnType === EGenType.GVec4) { + switch (actualParamType) { + case Keyword.I_SAMPLER2D: + case Keyword.I_SAMPLER3D: + case Keyword.I_SAMPLER_CUBE: + case Keyword.I_SAMPLER2D_ARRAY: + return Keyword.IVEC4; + case Keyword.U_SAMPLER2D: + case Keyword.U_SAMPLER3D: + case Keyword.U_SAMPLER_CUBE: + case Keyword.U_SAMPLER2D_ARRAY: + return Keyword.UVEC4; + default: + return Keyword.VEC4; + } + } + return actualParamType; +} + const BuiltinFunctionTable: Map = new Map(); export class BuiltinFunction { @@ -78,12 +111,14 @@ export class BuiltinFunction { const argLength = fnArgs.length; if (argLength !== parameterTypes.length) continue; // Try to match generic parameter type. - let returnType = TypeAny; + let resolvedReturnType: NonGenericGalaceanType = TypeAny; let found = true; for (let i = 0; i < argLength; i++) { const curFnArg = fnArgs[i]; if (isGenericType(curFnArg)) { - if (returnType === TypeAny) returnType = parameterTypes[i]; + if (resolvedReturnType === TypeAny) { + resolvedReturnType = resolveGenericReturnType(fn._returnType as EGenType, parameterTypes[i]); + } } else { if (curFnArg !== parameterTypes[i] && parameterTypes[i] !== TypeAny) { found = false; @@ -92,7 +127,9 @@ export class BuiltinFunction { } } if (found) { - fn._realReturnType = returnType; + fn._realReturnType = isGenericType(fn._returnType) + ? resolvedReturnType + : (fn._returnType as NonGenericGalaceanType); return fn; } } @@ -300,13 +337,14 @@ BuiltinFunction._create("textureLod", EGenType.GVec4, EGenType.GSampler3D, Keywo BuiltinFunction._create("textureLod", EGenType.GVec4, EGenType.GSamplerCube, Keyword.VEC3, Keyword.FLOAT); BuiltinFunction._create("textureLod", Keyword.FLOAT, Keyword.SAMPLER2D_SHADOW, Keyword.VEC3, Keyword.FLOAT); BuiltinFunction._create("textureLod", EGenType.GVec4, EGenType.GSampler2DArray, Keyword.VEC3, Keyword.FLOAT); +BuiltinFunction._create("texture2DLod", Keyword.VEC4, Keyword.SAMPLER2D, Keyword.VEC2, Keyword.FLOAT); BuiltinFunction._create("texture2DLodEXT", EGenType.GVec4, EGenType.GSampler2D, Keyword.VEC2, Keyword.FLOAT); BuiltinFunction._create("texture2DLodEXT", EGenType.GVec4, EGenType.GSampler3D, Keyword.VEC3, Keyword.FLOAT); -BuiltinFunction._create("textureCube", Keyword.SAMPLER_CUBE, Keyword.VEC3); -BuiltinFunction._create("textureCube", Keyword.SAMPLER_CUBE, Keyword.VEC3, Keyword.FLOAT); +BuiltinFunction._create("textureCube", Keyword.VEC4, Keyword.SAMPLER_CUBE, Keyword.VEC3); +BuiltinFunction._create("textureCube", Keyword.VEC4, Keyword.SAMPLER_CUBE, Keyword.VEC3, Keyword.FLOAT); BuiltinFunction._create("textureCube", EGenType.GVec4, EGenType.GSamplerCube, Keyword.VEC3, Keyword.FLOAT); -BuiltinFunction._create("textureCubeLod", Keyword.SAMPLER_CUBE, Keyword.VEC3, Keyword.FLOAT); +BuiltinFunction._create("textureCubeLod", Keyword.VEC4, Keyword.SAMPLER_CUBE, Keyword.VEC3, Keyword.FLOAT); BuiltinFunction._create("textureCubeLodEXT", EGenType.GVec4, EGenType.GSamplerCube, Keyword.VEC3, Keyword.FLOAT); BuiltinFunction._create( diff --git a/packages/shader/package.json b/packages/shader/package.json index e7e7eff423..c9f1a8bbe1 100644 --- a/packages/shader/package.json +++ b/packages/shader/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-shader", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" diff --git a/packages/shader/src/shaders/Transform.glsl b/packages/shader/src/shaders/Transform.glsl index b5d1a52a68..1af76a0f0e 100644 --- a/packages/shader/src/shaders/Transform.glsl +++ b/packages/shader/src/shaders/Transform.glsl @@ -1,16 +1,17 @@ #ifndef TRANSFORM_INCLUDED #define TRANSFORM_INCLUDED -mat4 renderer_LocalMat; -mat4 renderer_ModelMat; mat4 camera_ViewMat; mat4 camera_ProjMat; -mat4 renderer_MVMat; -mat4 renderer_MVPMat; -mat4 renderer_NormalMat; +mat4 camera_VPMat; vec3 camera_Position; -vec3 camera_Forward; +vec3 camera_Forward; vec4 camera_ProjectionParams; -#endif \ No newline at end of file +mat4 renderer_ModelMat; +mat4 renderer_MVMat; +mat4 renderer_MVPMat; +mat4 renderer_NormalMat; + +#endif diff --git a/packages/shader/src/shaders/shadingPBR/VertexPBR.glsl b/packages/shader/src/shaders/shadingPBR/VertexPBR.glsl index 134f2405f2..c9e964d6ec 100644 --- a/packages/shader/src/shaders/shadingPBR/VertexPBR.glsl +++ b/packages/shader/src/shaders/shadingPBR/VertexPBR.glsl @@ -69,10 +69,11 @@ VertexInputs getVertexInputs(Attributes attributes){ // TBN world space #ifdef RENDERER_HAS_NORMAL - inputs.normalWS = normalize( mat3(renderer_NormalMat) * normal ); + mat3 normalMat = mat3(renderer_NormalMat); + inputs.normalWS = normalize( normalMat * normal ); #ifdef RENDERER_HAS_TANGENT - vec3 tangentWS = normalize( mat3(renderer_NormalMat) * tangent.xyz ); + vec3 tangentWS = normalize( normalMat * tangent.xyz ); vec3 bitangentWS = cross( inputs.normalWS, tangentWS ) * tangent.w; inputs.tangentWS = tangentWS; @@ -85,7 +86,7 @@ VertexInputs getVertexInputs(Attributes attributes){ vec4 positionWS = renderer_ModelMat * position; inputs.positionWS = positionWS.xyz / positionWS.w; - #if SCENE_FOG_MODE != 0 + #if SCENE_FOG_MODE != 0 vec4 positionVS = renderer_MVMat * position; inputs.positionVS = positionVS.xyz / positionVS.w; #endif diff --git a/packages/ui/package.json b/packages/ui/package.json index 4b51ee5bc2..e3b8aa207b 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-ui", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" diff --git a/packages/ui/src/component/UICanvas.ts b/packages/ui/src/component/UICanvas.ts index 9e5b33c405..f4bf699135 100644 --- a/packages/ui/src/component/UICanvas.ts +++ b/packages/ui/src/component/UICanvas.ts @@ -62,7 +62,7 @@ export class UICanvas extends Component implements IElement { _isRootCanvas: boolean = false; /** @internal */ @ignoreClone - _renderElement: any; + _renderElements: any[] = []; /** @internal */ @ignoreClone _sortDistance: number = 0; @@ -307,11 +307,10 @@ export class UICanvas extends Component implements IElement { const { engine, _realRenderMode: mode } = this; const { enableFrustumCulling, cullingMask, _frustum: frustum } = context.camera; const { frameCount } = engine.time; - // @ts-ignore - const renderElement = (this._renderElement = engine._renderElementPool.get()); + const renderElements = this._renderElements; + renderElements.length = 0; const virtualCamera = context.virtualCamera; this._updateSortDistance(virtualCamera.isOrthographic, virtualCamera.position, virtualCamera.forward); - renderElement.set(this.sortOrder, this._sortDistance); const { width, height } = engine.canvas; const renderers = this._getRenderers(); for (let i = 0, n = renderers.length; i < n; i++) { diff --git a/packages/ui/src/component/UIRenderer.ts b/packages/ui/src/component/UIRenderer.ts index 59a2fc434c..676a4b241c 100644 --- a/packages/ui/src/component/UIRenderer.ts +++ b/packages/ui/src/component/UIRenderer.ts @@ -1,5 +1,5 @@ import { - BatchUtils, + VertexMergeBatcher, Color, DependentMode, Entity, @@ -71,7 +71,7 @@ export class UIRenderer extends Renderer implements IGraphics { _subChunk; @assignmentClone - private _raycastEnabled: boolean = true; + private _raycastEnabled: boolean = false; @deepClone protected _color: Color = new Color(1, 1, 1, 1); @@ -113,19 +113,19 @@ export class UIRenderer extends Renderer implements IGraphics { } // @ts-ignore - override _canBatch(elementA, elementB): boolean { - return BatchUtils.canBatchSprite(elementA, elementB); + override _canBatch(preElement, curElement): boolean { + return VertexMergeBatcher.canBatchSprite(preElement, curElement); } // @ts-ignore - override _batch(elementA, elementB?): void { - BatchUtils.batchFor2D(elementA, elementB); + override _batch(preElement, curElement): void { + VertexMergeBatcher.batch(preElement, curElement); } // @ts-ignore - override _updateTransformShaderData(context, onlyMVP: boolean, batched: boolean): void { + override _updateTransformShaderData(context, onlyMVP: boolean): void { // @ts-ignore - super._updateTransformShaderData(context, onlyMVP, true); + this._updateWorldSpaceTransformShaderData(context, onlyMVP); } // @ts-ignore diff --git a/packages/ui/src/component/UITransform.ts b/packages/ui/src/component/UITransform.ts index 9144373472..28e0087575 100644 --- a/packages/ui/src/component/UITransform.ts +++ b/packages/ui/src/component/UITransform.ts @@ -251,7 +251,49 @@ export class UITransform extends Transform { */ _parentChange(): void { this._isParentDirty = true; - this._updateWorldFlagWithParentRectChange(TransformModifyFlags.WmWpWeWqWsWus); + // Reparent invalidates the world state of the entire subtree: + // 1) `_updateWorldFlagWithParentRectChange` has an early-exit that skips + // propagation when self's world dirty flags are already all set — + // invalid after reparent. + // 2) Descendants may have cached a stale `_parentTransformCache` + // (e.g. `_getParentTransform` called while ancestor chain was partially + // constructed during clone/instantiate). Force them to re-resolve on + // next access. + this._propagateReparentDirtyUI(TransformModifyFlags.WmWpWeWqWsWus); + } + + private _propagateReparentDirtyUI(flags: number): void { + let selfChange = false; + const { _horizontalAlignment: horizontalAlignment, _verticalAlignment: verticalAlignment } = this; + if (horizontalAlignment || verticalAlignment) { + if ( + horizontalAlignment === HorizontalAlignmentMode.LeftAndRight || + verticalAlignment === VerticalAlignmentMode.TopAndBottom + ) { + this._updateSizeByAlignment(); + this._updateRectBySizeAndPivot(); + selfChange = true; + } + this._updatePositionByAlignment(); + this._setDirtyFlagTrue(TransformModifyFlags.LocalMatrix); + flags |= TransformModifyFlags.WmWp; + } + this._worldAssociatedChange(flags); + const children = this.entity.children; + for (let i = 0, n = children.length; i < n; i++) { + const transform = children[i].transform as any; + if (!transform) continue; + transform._isParentDirty = true; + if (typeof transform._propagateReparentDirtyUI === "function") { + transform._propagateReparentDirtyUI(flags); + } else if (typeof transform._propagateReparentDirty === "function") { + transform._propagateReparentDirty(flags); + } + } + if (selfChange) { + // @ts-ignore + this._entity._updateFlagManager.dispatch(UITransformModifyFlags.Size); + } } // @ts-ignore diff --git a/packages/ui/src/component/advanced/Image.ts b/packages/ui/src/component/advanced/Image.ts index b8ca6ffe55..bac5457c86 100644 --- a/packages/ui/src/component/advanced/Image.ts +++ b/packages/ui/src/component/advanced/Image.ts @@ -1,15 +1,17 @@ import { BoundingBox, Entity, + FilledSpriteAssembler, ISpriteAssembler, ISpriteRenderer, MathUtil, - RenderQueueFlags, RendererUpdateFlags, SimpleSpriteAssembler, SlicedSpriteAssembler, Sprite, SpriteDrawMode, + SpriteFilledMode, + SpriteFilledOrigin, SpriteModifyFlags, SpriteTileMode, TiledSpriteAssembler, @@ -21,6 +23,16 @@ import { RootCanvasModifyFlags } from "../UICanvas"; import { UIRenderer, UIRendererUpdateFlags } from "../UIRenderer"; import { UITransform, UITransformModifyFlags } from "../UITransform"; +/** + * Determines how the Image element's size is controlled relative to the sprite. + */ +export enum SpriteSizeMode { + /** The image size is controlled manually via UITransform (default, existing behavior). */ + Custom = 0, + /** The image size is automatically set to the sprite's natural dimensions when the sprite changes. */ + Automatic = 1 +} + /** * UI element that renders an image. */ @@ -35,6 +47,16 @@ export class Image extends UIRenderer implements ISpriteRenderer { private _tileMode: SpriteTileMode = SpriteTileMode.Continuous; @assignmentClone private _tiledAdaptiveThreshold: number = 0.5; + @assignmentClone + private _filledMode: SpriteFilledMode = SpriteFilledMode.Radial360; + @assignmentClone + private _filledAmount: number = 1; + @assignmentClone + private _filledOrigin: SpriteFilledOrigin = SpriteFilledOrigin.Bottom; + @assignmentClone + private _filledClockWise: boolean = true; + @assignmentClone + private _sizeMode: SpriteSizeMode = SpriteSizeMode.Custom; /** * The draw mode of the image. @@ -56,6 +78,9 @@ export class Image extends UIRenderer implements ISpriteRenderer { case SpriteDrawMode.Tiled: this._assembler = TiledSpriteAssembler; break; + case SpriteDrawMode.Filled: + this._assembler = FilledSpriteAssembler; + break; default: break; } @@ -64,6 +89,23 @@ export class Image extends UIRenderer implements ISpriteRenderer { } } + /** + * The size mode of the image. When set to `Automatic`, the UITransform size + * is automatically synchronized to the sprite's natural dimensions. + */ + get sizeMode(): SpriteSizeMode { + return this._sizeMode; + } + + set sizeMode(value: SpriteSizeMode) { + if (this._sizeMode !== value) { + this._sizeMode = value; + if (value === SpriteSizeMode.Automatic && this._sprite) { + this._applySpriteSize(); + } + } + } + /** * The tiling mode of the image. (Only works in tiled mode.) */ @@ -97,6 +139,73 @@ export class Image extends UIRenderer implements ISpriteRenderer { } } + /** + * The fill amount of the image, range from 0 to 1. (Only works in filled mode.) + */ + get filledAmount(): number { + return this._filledAmount; + } + + set filledAmount(value: number) { + value = MathUtil.clamp(value, 0, 1); + if (this._filledAmount !== value) { + this._filledAmount = value; + if (this._drawMode === SpriteDrawMode.Filled) { + this._dirtyUpdateFlag |= ImageUpdateFlags.WorldVolumeAndUV; + } + } + } + + /** + * The fill mode of the image. (Only works in filled mode.) + */ + get filledMode(): SpriteFilledMode { + return this._filledMode; + } + + set filledMode(value: SpriteFilledMode) { + if (this._filledMode !== value) { + this._filledMode = value; + this._filledOrigin = + value === SpriteFilledMode.Radial90 ? SpriteFilledOrigin.BottomLeft : SpriteFilledOrigin.Bottom; + if (this._drawMode === SpriteDrawMode.Filled) { + this._dirtyUpdateFlag |= ImageUpdateFlags.WorldVolumeAndUV; + } + } + } + + /** + * The fill origin of the image. (Only works in filled mode.) + */ + get filledOrigin(): SpriteFilledOrigin { + return this._filledOrigin; + } + + set filledOrigin(value: SpriteFilledOrigin) { + if (this._filledOrigin !== value) { + this._filledOrigin = value; + if (this._drawMode === SpriteDrawMode.Filled) { + this._dirtyUpdateFlag |= ImageUpdateFlags.WorldVolumeAndUV; + } + } + } + + /** + * Whether the fill is clockwise. (Only works in filled radial mode.) + */ + get filledClockWise(): boolean { + return this._filledClockWise; + } + + set filledClockWise(value: boolean) { + if (this._filledClockWise !== value) { + this._filledClockWise = value; + if (this._drawMode === SpriteDrawMode.Filled) { + this._dirtyUpdateFlag |= ImageUpdateFlags.WorldVolumeAndUV; + } + } + } + /** * The Sprite to render. */ @@ -122,6 +231,9 @@ export class Image extends UIRenderer implements ISpriteRenderer { this.shaderData.setTexture(UIRenderer._textureProperty, null); } this._sprite = value; + if (this._sizeMode === SpriteSizeMode.Automatic && value) { + this._applySpriteSize(); + } } } @@ -236,16 +348,16 @@ export class Image extends UIRenderer implements ISpriteRenderer { } this._dirtyUpdateFlag = dirtyUpdateFlag; - // Init sub render element. const { engine } = context.camera; - const subRenderElement = engine._subRenderElementPool.get(); + const renderElement = engine._renderElementPool.get(); const subChunk = this._subChunk; - subRenderElement.set(this, material, subChunk.chunk.primitive, subChunk.subMesh, this.sprite.texture, subChunk); + renderElement.set(this, material, subChunk.chunk.primitive, subChunk.subMesh, this.sprite.texture, subChunk); if (canvas._realRenderMode === CanvasRenderMode.ScreenSpaceOverlay) { - subRenderElement.shaderPasses = material.shader.subShaders[0].passes; - subRenderElement.renderQueueFlags = RenderQueueFlags.All; + renderElement.subShader = material.shader.subShaders[0]; } - canvas._renderElement.addSubRenderElement(subRenderElement); + renderElement.priority = canvas.sortOrder; + renderElement.distanceForSort = canvas._sortDistance; + canvas._renderElements.push(renderElement); } @ignoreClone @@ -274,6 +386,9 @@ export class Image extends UIRenderer implements ISpriteRenderer { this.shaderData.setTexture(UIRenderer._textureProperty, this.sprite.texture); break; case SpriteModifyFlags.size: + if (this._sizeMode === SpriteSizeMode.Automatic) { + this._applySpriteSize(); + } switch (this._drawMode) { case SpriteDrawMode.Sliced: this._dirtyUpdateFlag |= RendererUpdateFlags.WorldVolume; @@ -281,6 +396,9 @@ export class Image extends UIRenderer implements ISpriteRenderer { case SpriteDrawMode.Tiled: this._dirtyUpdateFlag |= ImageUpdateFlags.WorldVolumeUVAndColor; break; + case SpriteDrawMode.Filled: + this._dirtyUpdateFlag |= ImageUpdateFlags.WorldVolumeUVAndColor; + break; default: break; } @@ -309,6 +427,13 @@ export class Image extends UIRenderer implements ISpriteRenderer { break; } } + + private _applySpriteSize(): void { + const sprite = this._sprite; + if (sprite) { + (this._transformEntity.transform).size.set(sprite.width, sprite.height); + } + } } /** diff --git a/packages/ui/src/component/advanced/Text.ts b/packages/ui/src/component/advanced/Text.ts index 0eb5edeb93..6f20830716 100644 --- a/packages/ui/src/component/advanced/Text.ts +++ b/packages/ui/src/component/advanced/Text.ts @@ -7,7 +7,6 @@ import { FontStyle, ITextRenderer, OverflowMode, - RenderQueueFlags, RendererUpdateFlags, ShaderData, ShaderDataGroup, @@ -350,23 +349,26 @@ export class Text extends UIRenderer implements ITextRenderer { } const engine = context.camera.engine; - const textSubRenderElementPool = engine._textSubRenderElementPool; + const textRenderElementPool = engine._textRenderElementPool; const material = this.getMaterial(); - const renderElement = canvas._renderElement; + const renderElements = canvas._renderElements; + const priority = canvas.sortOrder; + const distanceForSort = canvas._sortDistance; const textChunks = this._textChunks; const isOverlay = canvas._realRenderMode === CanvasRenderMode.ScreenSpaceOverlay; for (let i = 0, n = textChunks.length; i < n; ++i) { const { subChunk, texture } = textChunks[i]; - const subRenderElement = textSubRenderElementPool.get(); - subRenderElement.set(this, material, subChunk.chunk.primitive, subChunk.subMesh, texture, subChunk); + const renderElement = textRenderElementPool.get(); + renderElement.set(this, material, subChunk.chunk.primitive, subChunk.subMesh, texture, subChunk); // @ts-ignore - subRenderElement.shaderData ||= new ShaderData(ShaderDataGroup.RenderElement); - subRenderElement.shaderData.setTexture(Text._textTextureProperty, texture); + renderElement.shaderData ||= new ShaderData(ShaderDataGroup.RenderElement); + renderElement.shaderData.setTexture(Text._textTextureProperty, texture); if (isOverlay) { - subRenderElement.shaderPasses = material.shader.subShaders[0].passes; - subRenderElement.renderQueueFlags = RenderQueueFlags.All; + renderElement.subShader = material.shader.subShaders[0]; } - renderElement.addSubRenderElement(subRenderElement); + renderElement.priority = priority; + renderElement.distanceForSort = distanceForSort; + renderElements.push(renderElement); } } diff --git a/packages/ui/src/component/index.ts b/packages/ui/src/component/index.ts index 1f89431265..fc93806fb6 100644 --- a/packages/ui/src/component/index.ts +++ b/packages/ui/src/component/index.ts @@ -3,7 +3,7 @@ export { UIGroup } from "./UIGroup"; export { UIRenderer } from "./UIRenderer"; export { UITransform } from "./UITransform"; export { Button } from "./advanced/Button"; -export { Image } from "./advanced/Image"; +export { Image, SpriteSizeMode } from "./advanced/Image"; export { Text } from "./advanced/Text"; export { ColorTransition } from "./interactive/transition/ColorTransition"; export { ScaleTransition } from "./interactive/transition/ScaleTransition"; diff --git a/packages/xr-webxr/package.json b/packages/xr-webxr/package.json index 9663c2321f..920f0f8044 100644 --- a/packages/xr-webxr/package.json +++ b/packages/xr-webxr/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-xr-webxr", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" diff --git a/packages/xr/package.json b/packages/xr/package.json index ec2e3cc79e..cb7ddc5400 100644 --- a/packages/xr/package.json +++ b/packages/xr/package.json @@ -1,6 +1,6 @@ { "name": "@galacean/engine-xr", - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ed565e145b..f6dbf1d371 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,11 +45,11 @@ importers: specifier: latest version: 0.5.22 '@typescript-eslint/eslint-plugin': - specifier: ^6.1.0 - version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3) + specifier: ^8.58.1 + version: 8.58.1(@typescript-eslint/parser@8.58.1(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3) '@typescript-eslint/parser': - specifier: ^6.1.0 - version: 6.21.0(eslint@8.57.1)(typescript@5.6.3) + specifier: ^8.58.1 + version: 8.58.1(eslint@8.57.1)(typescript@5.6.3) '@vitest/coverage-v8': specifier: 2.1.3 version: 2.1.3(@vitest/browser@2.1.3(@types/node@18.19.64)(@vitest/spy@2.1.3)(typescript@5.6.3)(vite@5.4.11(@types/node@18.19.64)(sass@1.81.0)(terser@5.44.1))(vitest@2.1.3))(vitest@2.1.3(@types/node@18.19.64)(@vitest/browser@2.1.3)(msw@2.6.5(@types/node@18.19.64)(typescript@5.6.3))(sass@1.81.0)(terser@5.44.1)) @@ -63,7 +63,7 @@ importers: specifier: ^13 version: 13.6.9 eslint: - specifier: ^8.44.0 + specifier: ^8.57.1 version: 8.57.1 eslint-config-prettier: specifier: ^8.8.0 @@ -78,8 +78,8 @@ importers: specifier: ^8.0.0 version: 8.0.3 lint-staged: - specifier: ^10.5.3 - version: 10.5.4 + specifier: ^16.4.0 + version: 16.4.0 nyc: specifier: ^15.1.0 version: 15.1.0 @@ -188,6 +188,9 @@ importers: '@galacean/engine-toolkit': specifier: latest version: 1.5.3(@galacean/engine-ui@packages+ui)(@galacean/engine@packages+galacean) + '@galacean/engine-toolkit-stats': + specifier: latest + version: 1.6.0(@galacean/engine@packages+galacean) '@galacean/engine-ui': specifier: workspace:* version: link:../packages/ui @@ -804,10 +807,20 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/regexpp@4.12.1': resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint/eslintrc@2.1.4': resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -935,6 +948,11 @@ packages: peerDependencies: '@galacean/engine': ^1.5.0 + '@galacean/engine-toolkit-stats@1.6.0': + resolution: {integrity: sha512-63LLxTWg15xR000jbtEONnK6lBBMylvl5m+3VqqC7b09YAuMWlm9CuPfaM8dlbctOYT6nmPu9bpQiq3JfdgtWg==} + peerDependencies: + '@galacean/engine': '>=1.6.0-0' + '@galacean/engine-toolkit@1.3.9': resolution: {integrity: sha512-sxE7QfzH61O9Q1wtwnjIEjcg3n0ZZVz9B6CyqBLOWyWgWsZmefcjZLnnH4HIkvc5ZLNA+gMuJ1ekmwJgfkck+g==} @@ -1481,9 +1499,6 @@ packages: '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/keyv@3.1.4': resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} @@ -1508,9 +1523,6 @@ packages: '@types/responselike@1.0.3': resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} - '@types/semver@7.5.8': - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - '@types/statuses@2.0.5': resolution: {integrity: sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==} @@ -1520,63 +1532,64 @@ packages: '@types/webxr@0.5.22': resolution: {integrity: sha512-Vr6Stjv5jPRqH690f5I5GLjVk8GSsoQSYJ2FVd/3jJF7KaqfwPi3ehfBS96mlQ2kPCwZaX6U0rG2+NGHBKkA/A==} - '@typescript-eslint/eslint-plugin@6.21.0': - resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/eslint-plugin@8.58.1': + resolution: {integrity: sha512-eSkwoemjo76bdXl2MYqtxg51HNwUSkWfODUOQ3PaTLZGh9uIWWFZIjyjaJnex7wXDu+TRx+ATsnSxdN9YWfRTQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + '@typescript-eslint/parser': ^8.58.1 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@6.21.0': - resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/parser@8.58.1': + resolution: {integrity: sha512-gGkiNMPqerb2cJSVcruigx9eHBlLG14fSdPdqMoOcBfh+vvn4iCq2C8MzUB89PrxOXk0y3GZ1yIWb9aOzL93bw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@6.21.0': - resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/project-service@8.58.1': + resolution: {integrity: sha512-gfQ8fk6cxhtptek+/8ZIqw8YrRW5048Gug8Ts5IYcMLCw18iUgrZAEY/D7s4hkI0FxEfGakKuPK/XUMPzPxi5g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@6.21.0': - resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/scope-manager@8.58.1': + resolution: {integrity: sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.58.1': + resolution: {integrity: sha512-JAr2hOIct2Q+qk3G+8YFfqkqi7sC86uNryT+2i5HzMa2MPjw4qNFvtjnw1IiA1rP7QhNKVe21mSSLaSjwA1Olw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@6.21.0': - resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/type-utils@8.58.1': + resolution: {integrity: sha512-HUFxvTJVroT+0rXVJC7eD5zol6ID+Sn5npVPWoFuHGg9Ncq5Q4EYstqR+UOqaNRFXi5TYkpXXkLhoCHe3G0+7w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/typescript-estree@6.21.0': - resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/types@8.58.1': + resolution: {integrity: sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.58.1': + resolution: {integrity: sha512-w4w7WR7GHOjqqPnvAYbazq+Y5oS68b9CzasGtnd6jIeOIeKUzYzupGTB2T4LTPSv4d+WPeccbxuneTFHYgAAWg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@6.21.0': - resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/utils@8.58.1': + resolution: {integrity: sha512-Ln8R0tmWC7pTtLOzgJzYTXSCjJ9rDNHAqTaVONF4FEi2qwce8mD9iSOxOpLFFvWp/wBFlew0mjM1L1ihYWfBdQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@6.21.0': - resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} - engines: {node: ^16.0.0 || >=18.0.0} + '@typescript-eslint/visitor-keys@8.58.1': + resolution: {integrity: sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -1694,14 +1707,14 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} + ansi-escapes@7.3.0: + resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} + engines: {node: '>=18'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1710,6 +1723,10 @@ packages: resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} engines: {node: '>=12'} + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -1722,6 +1739,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -1748,10 +1769,6 @@ packages: array-ify@1.0.0: resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} - array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - arrify@1.0.1: resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} engines: {node: '>=0.10.0'} @@ -1760,10 +1777,6 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - at-least-node@1.0.0: resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} engines: {node: '>= 4.0.0'} @@ -1771,6 +1784,10 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -1785,6 +1802,10 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@5.0.5: + resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + engines: {node: 18 || 20 || >=22} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -1882,13 +1903,13 @@ packages: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} - cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} - cli-truncate@2.1.0: - resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} - engines: {node: '>=8'} + cli-truncate@5.2.0: + resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} + engines: {node: '>=20'} cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} @@ -1914,13 +1935,13 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + commander@14.0.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} + engines: {node: '>=20'} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - commander@6.2.1: - resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} - engines: {node: '>= 6'} - commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} @@ -2017,6 +2038,15 @@ packages: supports-color: optional: true + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decamelize-keys@1.1.1: resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} engines: {node: '>=0.10.0'} @@ -2029,9 +2059,6 @@ packages: resolution: {integrity: sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==} engines: {node: '>=4'} - dedent@0.7.0: - resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} - deep-eql@5.0.2: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} @@ -2080,10 +2107,6 @@ packages: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} @@ -2113,6 +2136,9 @@ packages: engines: {node: '>= 8.6'} hasBin: true + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2126,14 +2152,14 @@ packages: end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - enquirer@2.4.1: - resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} - engines: {node: '>=8.6'} - env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -2322,6 +2348,10 @@ packages: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + eslint@8.57.1: resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2365,9 +2395,8 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - execa@4.1.0: - resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} - engines: {node: '>=10'} + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} execa@8.0.1: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} @@ -2387,10 +2416,6 @@ packages: fast-diff@1.3.0: resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -2411,6 +2436,15 @@ packages: picomatch: optional: true + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -2489,13 +2523,14 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + engines: {node: '>=18'} + get-intrinsic@1.2.4: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} - get-own-enumerable-property-symbols@3.0.2: - resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} - get-package-type@0.1.0: resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} engines: {node: '>=8.0.0'} @@ -2568,10 +2603,6 @@ packages: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} - globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} @@ -2632,10 +2663,6 @@ packages: http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - human-signals@1.1.1: - resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} - engines: {node: '>=8.12.0'} - human-signals@5.0.0: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} @@ -2649,6 +2676,10 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + immutable@5.0.2: resolution: {integrity: sha512-1NU7hWZDkV7hJ4PJ9dur9gTNQ4ePNPN4k9/0YhwjzykTi/+3Q5pF93YU5QoVj8BuOnhLgaY8gs0U2pj4kSYVcw==} @@ -2693,6 +2724,10 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-fullwidth-code-point@5.1.0: + resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} + engines: {node: '>=18'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -2707,10 +2742,6 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-obj@1.0.1: - resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==} - engines: {node: '>=0.10.0'} - is-obj@2.0.0: resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} engines: {node: '>=8'} @@ -2726,10 +2757,6 @@ packages: is-reference@1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} - is-regexp@1.0.0: - resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==} - engines: {node: '>=0.10.0'} - is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -2745,10 +2772,6 @@ packages: is-typedarray@1.0.0: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} @@ -2875,18 +2898,14 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lint-staged@10.5.4: - resolution: {integrity: sha512-EechC3DdFic/TdOPgj/RB3FicqE6932LTHCUm0Y2fsD9KGlLB+RwJl2q1IYBIvEsKzDOgn0D4gll+YxG5RsrKg==} + lint-staged@16.4.0: + resolution: {integrity: sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==} + engines: {node: '>=20.17'} hasBin: true - listr2@3.14.0: - resolution: {integrity: sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==} - engines: {node: '>=10.0.0'} - peerDependencies: - enquirer: '>= 2.3.0 < 3' - peerDependenciesMeta: - enquirer: - optional: true + listr2@9.0.5: + resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} + engines: {node: '>=20.0.0'} locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} @@ -2905,13 +2924,9 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - - log-update@4.0.0: - resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} - engines: {node: '>=10'} + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} loupe@3.1.2: resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} @@ -2977,10 +2992,6 @@ packages: merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -2990,14 +3001,14 @@ packages: engines: {node: '>=4.0.0'} hasBin: true - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + mimic-response@1.0.1: resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} engines: {node: '>=4'} @@ -3006,13 +3017,13 @@ packages: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -3119,10 +3130,6 @@ packages: resolution: {integrity: sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==} engines: {node: '>=4'} - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - npm-run-path@5.3.0: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -3151,14 +3158,14 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - onetime@6.0.0: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + opener@1.5.2: resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} hasBin: true @@ -3194,10 +3201,6 @@ packages: resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} engines: {node: '>=8'} - p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} - p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -3279,6 +3282,10 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + pify@3.0.0: resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} engines: {node: '>=4'} @@ -3300,9 +3307,6 @@ packages: engines: {node: '>=18'} hasBin: true - please-upgrade-node@3.2.0: - resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==} - postcss@8.4.49: resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} @@ -3446,9 +3450,9 @@ packages: responselike@1.0.2: resolution: {integrity: sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==} - restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} @@ -3514,9 +3518,6 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} - safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -3549,6 +3550,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + serialize-error@7.0.1: resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} engines: {node: '>=10'} @@ -3593,17 +3599,13 @@ packages: resolution: {integrity: sha512-pEjMUbwJ5Pl/6Vn6FsamXHXItJXSRftcibixDmNCWbWhic0hzHrwkMZo0IZ7fMRH9KxcWDFSkzhccB4285PutA==} engines: {node: '>=4.2'} - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - - slice-ansi@3.0.0: - resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} - engines: {node: '>=8'} + slice-ansi@7.1.2: + resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} + engines: {node: '>=18'} - slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} + slice-ansi@8.0.0: + resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} + engines: {node: '>=20'} source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} @@ -3658,10 +3660,6 @@ packages: strict-event-emitter@0.5.1: resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} - string-argv@0.3.1: - resolution: {integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==} - engines: {node: '>=0.6.19'} - string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -3674,16 +3672,20 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string-width@8.2.0: + resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==} + engines: {node: '>=20'} + string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - stringify-object@3.3.0: - resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==} - engines: {node: '>=4'} - strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -3692,14 +3694,14 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + strip-bom@4.0.0: resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} engines: {node: '>=8'} - strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} @@ -3764,10 +3766,18 @@ packages: tinyexec@0.3.1: resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} + tinyexec@1.1.1: + resolution: {integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==} + engines: {node: '>=18'} + tinyglobby@0.2.10: resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} engines: {node: '>=12.0.0'} + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + engines: {node: '>=12.0.0'} + tinypool@1.0.2: resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -3800,11 +3810,11 @@ packages: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} engines: {node: '>=8'} - ts-api-utils@1.4.0: - resolution: {integrity: sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==} - engines: {node: '>=16'} + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} peerDependencies: - typescript: '>=4.2.0' + typescript: '>=4.8.4' ts-node@10.9.2: resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} @@ -4092,6 +4102,10 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -4127,6 +4141,11 @@ packages: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} + yaml@2.8.3: + resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} + engines: {node: '>= 14.6'} + hasBin: true + yargs-parser@18.1.3: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} @@ -4539,8 +4558,15 @@ snapshots: eslint: 8.57.1 eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.9.1(eslint@8.57.1)': + dependencies: + eslint: 8.57.1 + eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.12.1': {} + '@eslint-community/regexpp@4.12.2': {} + '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 @@ -4662,6 +4688,10 @@ snapshots: dependencies: '@galacean/engine': link:packages/galacean + '@galacean/engine-toolkit-stats@1.6.0(@galacean/engine@packages+galacean)': + dependencies: + '@galacean/engine': link:packages/galacean + '@galacean/engine-toolkit@1.3.9(@galacean/engine@packages+galacean)': dependencies: '@galacean/engine-toolkit-auxiliary-lines': 1.3.9(@galacean/engine@packages+galacean) @@ -5149,8 +5179,6 @@ snapshots: '@types/estree@1.0.6': {} - '@types/json-schema@7.0.15': {} - '@types/keyv@3.1.4': dependencies: '@types/node': 18.19.64 @@ -5175,99 +5203,102 @@ snapshots: dependencies: '@types/node': 18.19.64 - '@types/semver@7.5.8': {} - '@types/statuses@2.0.5': {} '@types/tough-cookie@4.0.5': {} '@types/webxr@0.5.22': {} - '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3)': + '@typescript-eslint/eslint-plugin@8.58.1(@typescript-eslint/parser@8.58.1(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3)': dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.7 + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.58.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.58.1 + '@typescript-eslint/type-utils': 8.58.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/utils': 8.58.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.58.1 eslint: 8.57.1 - graphemer: 1.4.0 - ignore: 5.3.2 + ignore: 7.0.5 natural-compare: 1.4.0 - semver: 7.6.3 - ts-api-utils: 1.4.0(typescript@5.6.3) - optionalDependencies: + ts-api-utils: 2.5.0(typescript@5.6.3) typescript: 5.6.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.6.3)': + '@typescript-eslint/parser@8.58.1(eslint@8.57.1)(typescript@5.6.3)': dependencies: - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.6.3) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.7 + '@typescript-eslint/scope-manager': 8.58.1 + '@typescript-eslint/types': 8.58.1 + '@typescript-eslint/typescript-estree': 8.58.1(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.58.1 + debug: 4.4.3 eslint: 8.57.1 - optionalDependencies: typescript: 5.6.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@6.21.0': + '@typescript-eslint/project-service@8.58.1(typescript@5.6.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.58.1(typescript@5.6.3) + '@typescript-eslint/types': 8.58.1 + debug: 4.4.3 + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.58.1': dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 + '@typescript-eslint/types': 8.58.1 + '@typescript-eslint/visitor-keys': 8.58.1 - '@typescript-eslint/type-utils@6.21.0(eslint@8.57.1)(typescript@5.6.3)': + '@typescript-eslint/tsconfig-utils@8.58.1(typescript@5.6.3)': dependencies: - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.6.3) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.6.3) - debug: 4.3.7 + typescript: 5.6.3 + + '@typescript-eslint/type-utils@8.58.1(eslint@8.57.1)(typescript@5.6.3)': + dependencies: + '@typescript-eslint/types': 8.58.1 + '@typescript-eslint/typescript-estree': 8.58.1(typescript@5.6.3) + '@typescript-eslint/utils': 8.58.1(eslint@8.57.1)(typescript@5.6.3) + debug: 4.4.3 eslint: 8.57.1 - ts-api-utils: 1.4.0(typescript@5.6.3) - optionalDependencies: + ts-api-utils: 2.5.0(typescript@5.6.3) typescript: 5.6.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@6.21.0': {} + '@typescript-eslint/types@8.58.1': {} - '@typescript-eslint/typescript-estree@6.21.0(typescript@5.6.3)': + '@typescript-eslint/typescript-estree@8.58.1(typescript@5.6.3)': dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.7 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.6.3 - ts-api-utils: 1.4.0(typescript@5.6.3) - optionalDependencies: + '@typescript-eslint/project-service': 8.58.1(typescript@5.6.3) + '@typescript-eslint/tsconfig-utils': 8.58.1(typescript@5.6.3) + '@typescript-eslint/types': 8.58.1 + '@typescript-eslint/visitor-keys': 8.58.1 + debug: 4.4.3 + minimatch: 10.2.5 + semver: 7.7.4 + tinyglobby: 0.2.16 + ts-api-utils: 2.5.0(typescript@5.6.3) typescript: 5.6.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@6.21.0(eslint@8.57.1)(typescript@5.6.3)': + '@typescript-eslint/utils@8.58.1(eslint@8.57.1)(typescript@5.6.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.6.3) + '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) + '@typescript-eslint/scope-manager': 8.58.1 + '@typescript-eslint/types': 8.58.1 + '@typescript-eslint/typescript-estree': 8.58.1(typescript@5.6.3) eslint: 8.57.1 - semver: 7.6.3 + typescript: 5.6.3 transitivePeerDependencies: - supports-color - - typescript - '@typescript-eslint/visitor-keys@6.21.0': + '@typescript-eslint/visitor-keys@8.58.1': dependencies: - '@typescript-eslint/types': 6.21.0 - eslint-visitor-keys: 3.4.3 + '@typescript-eslint/types': 8.58.1 + eslint-visitor-keys: 5.0.1 '@ungap/structured-clone@1.2.0': {} @@ -5455,16 +5486,20 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ansi-colors@4.1.3: {} - ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 + ansi-escapes@7.3.0: + dependencies: + environment: 1.1.0 + ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} + ansi-regex@6.2.2: {} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 @@ -5473,6 +5508,8 @@ snapshots: ansi-styles@6.2.1: {} + ansi-styles@6.2.3: {} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 @@ -5498,18 +5535,16 @@ snapshots: array-ify@1.0.0: {} - array-union@2.1.0: {} - arrify@1.0.1: {} assertion-error@2.0.1: {} - astral-regex@2.0.0: {} - at-least-node@1.0.0: {} balanced-match@1.0.2: {} + balanced-match@4.0.4: {} + binary-extensions@2.3.0: {} boolean@3.2.0: @@ -5524,6 +5559,10 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.5: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -5649,14 +5688,14 @@ snapshots: clean-stack@2.2.0: {} - cli-cursor@3.1.0: + cli-cursor@5.0.0: dependencies: - restore-cursor: 3.1.0 + restore-cursor: 5.1.0 - cli-truncate@2.1.0: + cli-truncate@5.2.0: dependencies: - slice-ansi: 3.0.0 - string-width: 4.2.3 + slice-ansi: 8.0.0 + string-width: 8.2.0 cli-width@4.1.0: {} @@ -5684,11 +5723,11 @@ snapshots: colorette@2.0.20: {} + commander@14.0.3: {} + commander@2.20.3: optional: true - commander@6.2.1: {} - commondir@1.0.1: {} compare-func@2.0.0: @@ -5785,6 +5824,10 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.4.3: + dependencies: + ms: 2.1.3 + decamelize-keys@1.1.1: dependencies: decamelize: 1.2.0 @@ -5796,8 +5839,6 @@ snapshots: dependencies: mimic-response: 1.0.1 - dedent@0.7.0: {} - deep-eql@5.0.2: {} deep-is@0.1.4: {} @@ -5838,10 +5879,6 @@ snapshots: diff@4.0.2: {} - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 - doctrine@3.0.0: dependencies: esutils: 2.0.3 @@ -5868,6 +5905,8 @@ snapshots: transitivePeerDependencies: - supports-color + emoji-regex@10.6.0: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -5879,13 +5918,10 @@ snapshots: dependencies: once: 1.4.0 - enquirer@2.4.1: - dependencies: - ansi-colors: 4.1.3 - strip-ansi: 6.0.1 - env-paths@2.2.1: {} + environment@1.1.0: {} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -6062,6 +6098,8 @@ snapshots: eslint-visitor-keys@3.4.3: {} + eslint-visitor-keys@5.0.1: {} + eslint@8.57.1: dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) @@ -6135,17 +6173,7 @@ snapshots: esutils@2.0.3: {} - execa@4.1.0: - dependencies: - cross-spawn: 7.0.5 - get-stream: 5.2.0 - human-signals: 1.1.1 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 + eventemitter3@5.0.4: {} execa@8.0.1: dependencies: @@ -6174,14 +6202,6 @@ snapshots: fast-diff@1.3.0: {} - fast-glob@3.3.2: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - fast-json-stable-stringify@2.1.0: {} fast-levenshtein@2.0.6: {} @@ -6198,6 +6218,10 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -6279,6 +6303,8 @@ snapshots: get-caller-file@2.0.5: {} + get-east-asian-width@1.5.0: {} + get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 @@ -6288,8 +6314,6 @@ snapshots: hasown: 2.0.2 optional: true - get-own-enumerable-property-symbols@3.0.2: {} - get-package-type@0.1.0: {} get-stdin@8.0.0: {} @@ -6387,15 +6411,6 @@ snapshots: gopd: 1.0.1 optional: true - globby@11.1.0: - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.2 - merge2: 1.4.1 - slash: 3.0.0 - gopd@1.0.1: dependencies: get-intrinsic: 1.2.4 @@ -6459,14 +6474,14 @@ snapshots: http-cache-semantics@4.1.1: {} - human-signals@1.1.1: {} - human-signals@5.0.0: {} husky@8.0.3: {} ignore@5.3.2: {} + ignore@7.0.5: {} + immutable@5.0.2: {} import-fresh@3.3.0: @@ -6501,6 +6516,10 @@ snapshots: is-fullwidth-code-point@3.0.0: {} + is-fullwidth-code-point@5.1.0: + dependencies: + get-east-asian-width: 1.5.0 + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -6511,8 +6530,6 @@ snapshots: is-number@7.0.0: {} - is-obj@1.0.1: {} - is-obj@2.0.0: {} is-path-inside@3.0.3: {} @@ -6523,8 +6540,6 @@ snapshots: dependencies: '@types/estree': 1.0.6 - is-regexp@1.0.0: {} - is-stream@2.0.1: {} is-stream@3.0.0: {} @@ -6535,8 +6550,6 @@ snapshots: is-typedarray@1.0.0: {} - is-unicode-supported@0.1.0: {} - is-windows@1.0.2: {} isarray@1.0.0: {} @@ -6671,38 +6684,23 @@ snapshots: lines-and-columns@1.2.4: {} - lint-staged@10.5.4: + lint-staged@16.4.0: dependencies: - chalk: 4.1.2 - cli-truncate: 2.1.0 - commander: 6.2.1 - cosmiconfig: 7.1.0 - debug: 4.3.7 - dedent: 0.7.0 - enquirer: 2.4.1 - execa: 4.1.0 - listr2: 3.14.0(enquirer@2.4.1) - log-symbols: 4.1.0 - micromatch: 4.0.8 - normalize-path: 3.0.0 - please-upgrade-node: 3.2.0 - string-argv: 0.3.1 - stringify-object: 3.3.0 - transitivePeerDependencies: - - supports-color + commander: 14.0.3 + listr2: 9.0.5 + picomatch: 4.0.4 + string-argv: 0.3.2 + tinyexec: 1.1.1 + yaml: 2.8.3 - listr2@3.14.0(enquirer@2.4.1): + listr2@9.0.5: dependencies: - cli-truncate: 2.1.0 + cli-truncate: 5.2.0 colorette: 2.0.20 - log-update: 4.0.0 - p-map: 4.0.0 + eventemitter3: 5.0.4 + log-update: 6.1.0 rfdc: 1.4.1 - rxjs: 7.8.1 - through: 2.3.8 - wrap-ansi: 7.0.0 - optionalDependencies: - enquirer: 2.4.1 + wrap-ansi: 9.0.2 locate-path@5.0.0: dependencies: @@ -6718,17 +6716,13 @@ snapshots: lodash@4.17.21: {} - log-symbols@4.1.0: - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - - log-update@4.0.0: + log-update@6.1.0: dependencies: - ansi-escapes: 4.3.2 - cli-cursor: 3.1.0 - slice-ansi: 4.0.0 - wrap-ansi: 6.2.0 + ansi-escapes: 7.3.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.2 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.2 loupe@3.1.2: {} @@ -6797,30 +6791,29 @@ snapshots: merge-stream@2.0.0: {} - merge2@1.4.1: {} - micromatch@4.0.8: dependencies: braces: 3.0.3 picomatch: 2.3.1 + optional: true mime@2.6.0: {} - mimic-fn@2.1.0: {} - mimic-fn@4.0.0: {} + mimic-function@5.0.1: {} + mimic-response@1.0.1: {} min-indent@1.0.1: {} - minimatch@3.1.2: + minimatch@10.2.5: dependencies: - brace-expansion: 1.1.11 + brace-expansion: 5.0.5 - minimatch@9.0.3: + minimatch@3.1.2: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 1.1.11 minimatch@9.0.5: dependencies: @@ -6934,10 +6927,6 @@ snapshots: pify: 3.0.0 optional: true - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 - npm-run-path@5.3.0: dependencies: path-key: 4.0.0 @@ -6994,14 +6983,14 @@ snapshots: dependencies: wrappy: 1.0.2 - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - onetime@6.0.0: dependencies: mimic-fn: 4.0.0 + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + opener@1.5.2: {} optionator@0.9.4: @@ -7037,10 +7026,6 @@ snapshots: dependencies: aggregate-error: 3.1.0 - p-map@4.0.0: - dependencies: - aggregate-error: 3.1.0 - p-try@2.2.0: {} package-hash@4.0.0: @@ -7100,6 +7085,8 @@ snapshots: picomatch@4.0.2: {} + picomatch@4.0.4: {} + pify@3.0.0: optional: true @@ -7121,10 +7108,6 @@ snapshots: optionalDependencies: fsevents: 2.3.2 - please-upgrade-node@3.2.0: - dependencies: - semver-compare: 1.0.0 - postcss@8.4.49: dependencies: nanoid: 3.3.7 @@ -7261,10 +7244,10 @@ snapshots: dependencies: lowercase-keys: 1.0.1 - restore-cursor@3.1.0: + restore-cursor@5.1.0: dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 + onetime: 7.0.0 + signal-exit: 4.1.0 reusify@1.0.4: {} @@ -7355,10 +7338,6 @@ snapshots: dependencies: queue-microtask: 1.2.3 - rxjs@7.8.1: - dependencies: - tslib: 2.8.1 - safe-buffer@5.1.2: {} safe-buffer@5.2.1: {} @@ -7371,7 +7350,8 @@ snapshots: optionalDependencies: '@parcel/watcher': 2.5.0 - semver-compare@1.0.0: {} + semver-compare@1.0.0: + optional: true semver@5.7.2: {} @@ -7381,6 +7361,8 @@ snapshots: semver@7.6.3: {} + semver@7.7.4: {} + serialize-error@7.0.1: dependencies: type-fest: 0.13.1 @@ -7416,19 +7398,15 @@ snapshots: skip-regex@1.0.2: {} - slash@3.0.0: {} - - slice-ansi@3.0.0: + slice-ansi@7.1.2: dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.1.0 - slice-ansi@4.0.0: + slice-ansi@8.0.0: dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 source-map-js@1.2.1: {} @@ -7482,8 +7460,6 @@ snapshots: strict-event-emitter@0.5.1: {} - string-argv@0.3.1: {} - string-argv@0.3.2: {} string-width@4.2.3: @@ -7498,6 +7474,17 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.0 + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.5.0 + strip-ansi: 7.1.0 + + string-width@8.2.0: + dependencies: + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 + string_decoder@1.1.1: dependencies: safe-buffer: 5.1.2 @@ -7506,12 +7493,6 @@ snapshots: dependencies: safe-buffer: 5.2.1 - stringify-object@3.3.0: - dependencies: - get-own-enumerable-property-symbols: 3.0.2 - is-obj: 1.0.1 - is-regexp: 1.0.0 - strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -7520,9 +7501,11 @@ snapshots: dependencies: ansi-regex: 6.1.0 - strip-bom@4.0.0: {} + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 - strip-final-newline@2.0.0: {} + strip-bom@4.0.0: {} strip-final-newline@3.0.0: {} @@ -7592,11 +7575,18 @@ snapshots: tinyexec@0.3.1: {} + tinyexec@1.1.1: {} + tinyglobby@0.2.10: dependencies: fdir: 6.4.2(picomatch@4.0.2) picomatch: 4.0.2 + tinyglobby@0.2.16: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + tinypool@1.0.2: {} tinyrainbow@1.2.0: {} @@ -7620,7 +7610,7 @@ snapshots: trim-newlines@3.0.1: {} - ts-api-utils@1.4.0(typescript@5.6.3): + ts-api-utils@2.5.0(typescript@5.6.3): dependencies: typescript: 5.6.3 @@ -7738,7 +7728,7 @@ snapshots: vite-node@2.1.5(@types/node@18.19.64)(sass@1.81.0)(terser@5.44.1): dependencies: cac: 6.7.14 - debug: 4.3.7 + debug: 4.4.3 es-module-lexer: 1.5.4 pathe: 1.1.2 vite: 5.4.11(@types/node@18.19.64)(sass@1.81.0)(terser@5.44.1) @@ -7831,7 +7821,7 @@ snapshots: '@vitest/spy': 2.1.5 '@vitest/utils': 2.1.5 chai: 5.1.2 - debug: 4.3.7 + debug: 4.4.3 expect-type: 1.1.0 magic-string: 0.30.12 pathe: 1.1.2 @@ -7892,6 +7882,12 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.0 + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 + wrappy@1.0.2: {} write-file-atomic@3.0.3: @@ -7913,6 +7909,8 @@ snapshots: yaml@1.10.2: {} + yaml@2.8.3: {} + yargs-parser@18.1.3: dependencies: camelcase: 5.3.1 diff --git a/tests/package.json b/tests/package.json index bcf0debcb4..72ef5992b1 100644 --- a/tests/package.json +++ b/tests/package.json @@ -1,7 +1,7 @@ { "name": "@galacean/engine-tests", "private": true, - "version": "2.0.0-alpha.24", + "version": "0.0.0-experimental-2.0-game.6", "license": "MIT", "main": "dist/main.js", "module": "dist/module.js", diff --git a/tests/src/core/Animator.test.ts b/tests/src/core/Animator.test.ts index c37d476a92..6cb74ea8e2 100644 --- a/tests/src/core/Animator.test.ts +++ b/tests/src/core/Animator.test.ts @@ -307,7 +307,7 @@ describe("Animator test", function () { const additiveLayer = new AnimatorControllerLayer("additiveLayer"); additiveLayer.stateMachine = animatorStateMachine; const mask = AnimatorLayerMask.createByEntity(animator.entity); - mask.setPathMaskActive("_rootJoint/b_Root_00/b_Hip_01/b_Spine01_02/b_Spine02_03/b_Neck_04", false, true); + mask.setPathMaskActive("root/_rootJoint/b_Root_00/b_Hip_01/b_Spine01_02/b_Spine02_03/b_Neck_04", false, true); additiveLayer.mask = mask; additiveLayer.blendingMode = AnimatorLayerBlendingMode.Additive; animatorController.addLayer(additiveLayer); @@ -319,12 +319,12 @@ describe("Animator test", function () { animator.play("Walk", 0); animator.play("Run", 1); - const parentEntity = animator.entity.findByPath("_rootJoint/b_Root_00/b_Hip_01/b_Spine01_02/b_Spine02_03/"); + const parentEntity = animator.entity.findByPath("root/_rootJoint/b_Root_00/b_Hip_01/b_Spine01_02/b_Spine02_03/"); const targetEntity = animator.entity.findByPath( - "_rootJoint/b_Root_00/b_Hip_01/b_Spine01_02/b_Spine02_03/b_Neck_04" + "root/_rootJoint/b_Root_00/b_Hip_01/b_Spine01_02/b_Spine02_03/b_Neck_04" ); const childEntity = animator.entity.findByPath( - "_rootJoint/b_Root_00/b_Hip_01/b_Spine01_02/b_Spine02_03/b_Neck_04/b_Head_05" + "root/_rootJoint/b_Root_00/b_Hip_01/b_Spine01_02/b_Spine02_03/b_Neck_04/b_Head_05" ); let layerData = animator["_animatorLayersData"][1]; @@ -338,7 +338,7 @@ describe("Animator test", function () { expect(childLayerCurveOwner.isActive).to.eq(false); animator.animatorController.removeLayer(1); - mask.removePathMask("_rootJoint/b_Root_00/b_Hip_01/b_Spine01_02/b_Spine02_03/b_Neck_04/b_Head_05"); + mask.removePathMask("root/_rootJoint/b_Root_00/b_Hip_01/b_Spine01_02/b_Spine02_03/b_Neck_04/b_Head_05"); animator.animatorController.addLayer(additiveLayer); animator.play("Run", 1); layerData = animator["_animatorLayersData"][1]; @@ -1046,6 +1046,48 @@ describe("Animator test", function () { expect(animator.entity.clone().getComponent(Animator).animatorController).to.eq(animator.animatorController); }); + it("samples self-name-prefixed curve paths on wrapped roots", () => { + const wrappedRoot = new Entity(engine, "GLTF_ROOT"); + const hips = new Entity(engine, "mixamorig:Hips"); + const spine = new Entity(engine, "mixamorig:Spine"); + hips.parent = wrappedRoot; + spine.parent = hips; + + const clip = new AnimationClip("idle"); + const hipsCurve = new AnimationFloatCurve(); + const spineCurve = new AnimationFloatCurve(); + const hipsStart = new Keyframe(); + const hipsEnd = new Keyframe(); + hipsStart.time = 0; + hipsStart.value = 0; + hipsEnd.time = 0.1; + hipsEnd.value = 1; + hipsCurve.addKey(hipsStart); + hipsCurve.addKey(hipsEnd); + + const spineStart = new Keyframe(); + const spineEnd = new Keyframe(); + spineStart.time = 0; + spineStart.value = 0; + spineEnd.time = 0.1; + spineEnd.value = 1; + spineCurve.addKey(spineStart); + spineCurve.addKey(spineEnd); + + clip.addCurveBinding("mixamorig:Hips", Transform, "position.x", hipsCurve); + clip.addCurveBinding("mixamorig:Hips/mixamorig:Spine", Transform, "position.y", spineCurve); + + expect(wrappedRoot.findByPath("mixamorig:Hips")).to.eq(hips); + expect(wrappedRoot.findByPath("mixamorig:Hips/mixamorig:Spine")).to.eq(spine); + + // @ts-ignore + clip._sampleAnimation(wrappedRoot, 0.1); + + expect(wrappedRoot.transform.position.x).to.eq(0); + expect(hips.transform.position.x).to.eq(1); + expect(spine.transform.position.y).to.eq(1); + }); + it("anyState transition interrupts crossFade", () => { const { animatorController } = animator; animatorController.addParameter("interrupt", false); diff --git a/tests/src/core/AnimatorHang.test.ts b/tests/src/core/AnimatorHang.test.ts new file mode 100644 index 0000000000..99a8a5ba14 --- /dev/null +++ b/tests/src/core/AnimatorHang.test.ts @@ -0,0 +1,20 @@ +import { Animator, Camera } from "@galacean/engine-core"; +import "@galacean/engine-loader"; +import type { GLTFResource } from "@galacean/engine-loader"; +import { WebGLEngine } from "@galacean/engine-rhi-webgl"; +import { describe, expect, it } from "vitest"; +import { glbResource } from "./model/fox"; +const canvasDOM = document.createElement("canvas"); +canvasDOM.width = 1024; +canvasDOM.height = 1024; +describe("Canvas 1024 test", async function () { + const engine = await WebGLEngine.create({ canvas: canvasDOM }); + const scene = engine.sceneManager.activeScene; + const rootEntity = scene.createRootEntity(); + rootEntity.addComponent(Camera); + const resource = await engine.resourceManager.load(glbResource); + const defaultSceneRoot = resource.defaultSceneRoot; + rootEntity.addChild(defaultSceneRoot); + const animator = defaultSceneRoot.getComponent(Animator); + it("loaded", () => { expect(animator).not.eq(null); }); +}); diff --git a/tests/src/core/Camera.test.ts b/tests/src/core/Camera.test.ts index 52ae7890d1..5f77077f7f 100644 --- a/tests/src/core/Camera.test.ts +++ b/tests/src/core/Camera.test.ts @@ -245,10 +245,64 @@ describe("camera test", function () { expect(Math.abs(ray.direction.z)).not.eq(Infinity); }); + it("screenPointToRay should ignore inherited scale from parent entity", () => { + // Simulate UICanvas scenario: camera is a child of a scaled parent entity + const scene = engine.sceneManager.scenes[0]; + const parentEntity = scene.createRootEntity("scaledParent"); + parentEntity.transform.setScale(1.5, 1.5, 1.5); + parentEntity.transform.setPosition(100, 200, 0); + + const childEntity = parentEntity.createChild("cameraChild"); + childEntity.transform.setPosition(0, 0, 500); + const scaledCamera = childEntity.addComponent(Camera); + scaledCamera.isOrthographic = true; + scaledCamera.orthographicSize = 5; + scaledCamera.nearClipPlane = 0.1; + scaledCamera.farClipPlane = 1000; + + // A camera without inherited scale at the same world position/rotation for comparison + const refEntity = scene.createRootEntity("refCamera"); + refEntity.transform.setWorldPosition( + childEntity.transform.worldPosition.x, + childEntity.transform.worldPosition.y, + childEntity.transform.worldPosition.z + ); + const refCamera = refEntity.addComponent(Camera); + refCamera.isOrthographic = true; + refCamera.orthographicSize = 5; + refCamera.nearClipPlane = 0.1; + refCamera.farClipPlane = 1000; + + // Both cameras should produce the same ray for the same screen point + const screenPoint = new Vector2(128, 128); + const rayScaled = scaledCamera.screenPointToRay(screenPoint, new Ray()); + const rayRef = refCamera.screenPointToRay(screenPoint, new Ray()); + + expect(rayScaled.origin.x).to.be.closeTo(rayRef.origin.x, 0.001); + expect(rayScaled.origin.y).to.be.closeTo(rayRef.origin.y, 0.001); + expect(rayScaled.direction.x).to.be.closeTo(rayRef.direction.x, 0.001); + expect(rayScaled.direction.y).to.be.closeTo(rayRef.direction.y, 0.001); + expect(rayScaled.direction.z).to.be.closeTo(rayRef.direction.z, 0.001); + + // Round-trip: worldToViewportPoint -> viewportToWorldPoint should be accurate + const worldPoint = new Vector3(105, 210, 0); + const viewportPoint = scaledCamera.worldToViewportPoint(worldPoint, new Vector3()); + const recoveredPoint = scaledCamera.viewportToWorldPoint(viewportPoint, new Vector3()); + expect(recoveredPoint.x).to.be.closeTo(worldPoint.x, 0.01); + expect(recoveredPoint.y).to.be.closeTo(worldPoint.y, 0.01); + expect(recoveredPoint.z).to.be.closeTo(worldPoint.z, 0.01); + + // Clean up + scaledCamera.destroy(); + refCamera.destroy(); + parentEntity.destroy(); + refEntity.destroy(); + }); + /* Attention: - Below methods will change the default view of current Camera. - If executed in advance, it will affect the expected results of other test cases, + Below methods will change the default view of current Camera. + If executed in advance, it will affect the expected results of other test cases, so it should be placed at the end of the test case execution. */ it("projection matrix", () => { diff --git a/tests/src/core/CloneUtils.test.ts b/tests/src/core/CloneUtils.test.ts index 7d7195f323..80ffbe27dd 100644 --- a/tests/src/core/CloneUtils.test.ts +++ b/tests/src/core/CloneUtils.test.ts @@ -87,6 +87,26 @@ class NestedObjectScript extends Script { config: { target: Entity; label: string } = { target: null, label: "" }; } +/** Script with UNDECORATED array of entities (no @deepClone) */ +class UndecoratedArrayScript extends Script { + entities: Entity[] = []; +} + +/** Script with UNDECORATED nested object containing entity refs */ +class UndecoratedObjectScript extends Script { + config: { target: Entity; label: string } = { target: null, label: "" }; +} + +/** Script with UNDECORATED nested array of arrays containing entities */ +class NestedArrayScript extends Script { + groups: Entity[][] = []; +} + +/** Script with UNDECORATED Map containing entity values */ +class MapRefScript extends Script { + entityMap: Map = new Map(); +} + /** Script for testing multiple same-type components on one entity */ class CounterScript extends Script { value: number = 0; @@ -244,7 +264,9 @@ describe("Clone remap", async () => { expect(clonedScript.speed).eq(42); expect(clonedScript.name2).eq("test"); expect(clonedScript.flag).eq(true); - expect(clonedScript.data).eq(obj); + // Plain objects are now deep cloned (independent copy) for undecorated properties + expect(clonedScript.data).not.eq(obj); + expect((clonedScript.data).x).eq(1); rootEntity.destroy(); }); @@ -873,4 +895,142 @@ describe("Clone remap", async () => { rootEntity.destroy(); }); }); + + describe("Undecorated array auto clone + remap (type inference)", () => { + it("undecorated entity array should create new array and remap elements", () => { + const rootEntity = scene.createRootEntity("root"); + const parent = rootEntity.createChild("parent"); + const childA = parent.createChild("childA"); + const childB = parent.createChild("childB"); + const script = parent.addComponent(UndecoratedArrayScript); + script.entities = [childA, childB]; + + const cloned = parent.clone(); + const cs = cloned.getComponent(UndecoratedArrayScript); + + expect(cs.entities).not.eq(script.entities); + expect(cs.entities.length).eq(2); + expect(cs.entities[0]).not.eq(childA); + expect(cs.entities[1]).not.eq(childB); + expect(cs.entities[0]).eq(cloned.children[0]); + expect(cs.entities[1]).eq(cloned.children[1]); + + rootEntity.destroy(); + }); + + it("undecorated entity array with external ref keeps original", () => { + const rootEntity = scene.createRootEntity("root"); + const parent = rootEntity.createChild("parent"); + const child = parent.createChild("child"); + const external = rootEntity.createChild("external"); + const script = parent.addComponent(UndecoratedArrayScript); + script.entities = [child, external]; + + const cloned = parent.clone(); + const cs = cloned.getComponent(UndecoratedArrayScript); + + expect(cs.entities[0]).eq(cloned.children[0]); + expect(cs.entities[1]).eq(external); + + rootEntity.destroy(); + }); + + it("undecorated empty array stays empty with independent reference", () => { + const rootEntity = scene.createRootEntity("root"); + const parent = rootEntity.createChild("parent"); + const script = parent.addComponent(UndecoratedArrayScript); + script.entities = []; + + const cloned = parent.clone(); + const cs = cloned.getComponent(UndecoratedArrayScript); + + expect(cs.entities).not.eq(script.entities); + expect(cs.entities.length).eq(0); + + rootEntity.destroy(); + }); + }); + + describe("Undecorated nested object auto clone + remap (type inference)", () => { + it("undecorated object with entity ref should deep clone and remap", () => { + const rootEntity = scene.createRootEntity("root"); + const parent = rootEntity.createChild("parent"); + const child = parent.createChild("child"); + const script = parent.addComponent(UndecoratedObjectScript); + script.config = { target: child, label: "hello" }; + + const cloned = parent.clone(); + const cs = cloned.getComponent(UndecoratedObjectScript); + + expect(cs.config).not.eq(script.config); + expect(cs.config.label).eq("hello"); + expect(cs.config.target).not.eq(child); + expect(cs.config.target).eq(cloned.children[0]); + + rootEntity.destroy(); + }); + + it("undecorated object with external entity ref keeps original", () => { + const rootEntity = scene.createRootEntity("root"); + const parent = rootEntity.createChild("parent"); + const external = rootEntity.createChild("external"); + const script = parent.addComponent(UndecoratedObjectScript); + script.config = { target: external, label: "ext" }; + + const cloned = parent.clone(); + const cs = cloned.getComponent(UndecoratedObjectScript); + + expect(cs.config.target).eq(external); + expect(cs.config.label).eq("ext"); + + rootEntity.destroy(); + }); + }); + + describe("Nested array of arrays with entity refs (type inference)", () => { + it("undecorated nested entity arrays should recursively clone and remap", () => { + const rootEntity = scene.createRootEntity("root"); + const parent = rootEntity.createChild("parent"); + const childA = parent.createChild("childA"); + const childB = parent.createChild("childB"); + const childC = parent.createChild("childC"); + const script = parent.addComponent(NestedArrayScript); + script.groups = [[childA, childB], [childC]]; + + const cloned = parent.clone(); + const cs = cloned.getComponent(NestedArrayScript); + + expect(cs.groups).not.eq(script.groups); + expect(cs.groups.length).eq(2); + expect(cs.groups[0]).not.eq(script.groups[0]); + expect(cs.groups[1]).not.eq(script.groups[1]); + expect(cs.groups[0][0]).eq(cloned.children[0]); + expect(cs.groups[0][1]).eq(cloned.children[1]); + expect(cs.groups[1][0]).eq(cloned.children[2]); + + rootEntity.destroy(); + }); + }); + + describe("Map with entity values (type inference)", () => { + it("undecorated Map should create new Map and remap entity values", () => { + const rootEntity = scene.createRootEntity("root"); + const parent = rootEntity.createChild("parent"); + const child = parent.createChild("child"); + const external = rootEntity.createChild("external"); + const script = parent.addComponent(MapRefScript); + script.entityMap.set("internal", child); + script.entityMap.set("external", external); + + const cloned = parent.clone(); + const cs = cloned.getComponent(MapRefScript); + + expect(cs.entityMap).not.eq(script.entityMap); + expect(cs.entityMap.size).eq(2); + expect(cs.entityMap.get("internal")).eq(cloned.children[0]); + expect(cs.entityMap.get("external")).eq(external); + + rootEntity.destroy(); + }); + }); }); diff --git a/tests/src/core/Entity.test.ts b/tests/src/core/Entity.test.ts index 2fe8f908ad..212ee84286 100644 --- a/tests/src/core/Entity.test.ts +++ b/tests/src/core/Entity.test.ts @@ -320,6 +320,19 @@ describe("Entity", async () => { expect(parent.findByPath("child/grandson")).eq(grandson2); }); + it("findByPath accepts self-name prefix", () => { + const parent = new Entity(engine, "parent"); + parent.parent = scene.getRootEntity(); + const child = new Entity(engine, "child"); + child.parent = parent; + const grandson = new Entity(engine, "grandson"); + grandson.parent = child; + + expect(parent.findByPath("parent")).eq(parent); + expect(parent.findByPath("parent/child")).eq(child); + expect(parent.findByPath("parent/child/grandson")).eq(grandson); + }); + it("clearChildren", () => { const parent = new Entity(engine, "parent"); @@ -328,8 +341,29 @@ describe("Entity", async () => { child.parent = parent; const child2 = new Entity(engine, "child2"); child2.parent = parent; + + const parentModifyCount = [0, 0, 0]; + const childModifyCount = [0, 0, 0]; + const child2ModifyCount = [0, 0, 0]; + // @ts-ignore + parent._registerModifyListener((flag: EntityModifyFlags) => ++parentModifyCount[flag]); + // @ts-ignore + child._registerModifyListener((flag: EntityModifyFlags) => ++childModifyCount[flag]); + // @ts-ignore + child2._registerModifyListener((flag: EntityModifyFlags) => ++child2ModifyCount[flag]); + parent.clearChildren(); expect(parent.children.length).eq(0); + + // Parent should receive a single `Child` modify event for the whole clear so + // listeners (e.g. UICanvas) can invalidate their cached state. + expect(parentModifyCount[EntityModifyFlags.Child]).eq(1); + // Each detached child should receive a `Parent` modify event. + expect(childModifyCount[EntityModifyFlags.Parent]).eq(1); + expect(child2ModifyCount[EntityModifyFlags.Parent]).eq(1); + // Sibling index must be reset so the entity is treated as lonely afterwards. + expect(child.siblingIndex).eq(-1); + expect(child2.siblingIndex).eq(-1); }); it("sibling index", () => { const root = scene.createRootEntity(); @@ -681,4 +715,4 @@ describe("Entity", async () => { expect(script.onDestroy).toHaveBeenCalledTimes(1); }); }); -}); \ No newline at end of file +}); diff --git a/tests/src/core/ShaderData.test.ts b/tests/src/core/ShaderData.test.ts new file mode 100644 index 0000000000..6903c67150 --- /dev/null +++ b/tests/src/core/ShaderData.test.ts @@ -0,0 +1,184 @@ +import { CloneManager, ShaderData, ShaderDataGroup, ShaderMacro } from "@galacean/engine-core"; +import { CloneMode } from "@galacean/engine-core/src/clone/enums/CloneMode"; +import { describe, expect, it } from "vitest"; + +describe("ShaderData", () => { + describe("Macro operations", () => { + it("enableMacro and disableMacro", () => { + const shaderData = new ShaderData(ShaderDataGroup.Renderer); + const macro = ShaderMacro.getByName("TEST_ENABLE_DISABLE"); + + shaderData.enableMacro("TEST_ENABLE_DISABLE"); + expect(shaderData._macroCollection.isEnable(macro)).to.be.true; + + const macros = shaderData.getMacros() as ShaderMacro[]; + expect(macros).to.have.lengthOf(1); + expect(macros[0]).to.equal(macro); + + shaderData.disableMacro("TEST_ENABLE_DISABLE"); + expect(shaderData._macroCollection.isEnable(macro)).to.be.false; + expect(shaderData.getMacros() as ShaderMacro[]).to.have.lengthOf(0); + }); + + it("enableMacro with value replaces same-name macro", () => { + const shaderData = new ShaderData(ShaderDataGroup.Renderer); + + shaderData.enableMacro("TEST_VALUE_MACRO", "1"); + const macro1 = ShaderMacro.getByName("TEST_VALUE_MACRO", "1"); + expect(shaderData._macroCollection.isEnable(macro1)).to.be.true; + + shaderData.enableMacro("TEST_VALUE_MACRO", "2"); + const macro2 = ShaderMacro.getByName("TEST_VALUE_MACRO", "2"); + expect(shaderData._macroCollection.isEnable(macro1)).to.be.false; + expect(shaderData._macroCollection.isEnable(macro2)).to.be.true; + expect(shaderData.getMacros() as ShaderMacro[]).to.have.lengthOf(1); + }); + }); + + describe("cloneTo", () => { + it("should produce identical macros in target", () => { + const source = new ShaderData(ShaderDataGroup.Renderer); + source.enableMacro("CLONE_MACRO_A"); + source.enableMacro("CLONE_MACRO_B"); + + const target = new ShaderData(ShaderDataGroup.Renderer); + source.cloneTo(target); + + const macroA = ShaderMacro.getByName("CLONE_MACRO_A"); + const macroB = ShaderMacro.getByName("CLONE_MACRO_B"); + expect(target._macroCollection.isEnable(macroA)).to.be.true; + expect(target._macroCollection.isEnable(macroB)).to.be.true; + + const targetMacros = target.getMacros() as ShaderMacro[]; + expect(targetMacros).to.have.lengthOf(2); + }); + + it("should clear stale macros in target before cloning", () => { + const source = new ShaderData(ShaderDataGroup.Renderer); + source.enableMacro("SOURCE_ONLY_MACRO"); + + const target = new ShaderData(ShaderDataGroup.Renderer); + target.enableMacro("TARGET_STALE_MACRO"); + + source.cloneTo(target); + + const staleMacro = ShaderMacro.getByName("TARGET_STALE_MACRO"); + const sourceMacro = ShaderMacro.getByName("SOURCE_ONLY_MACRO"); + + expect(target._macroCollection.isEnable(staleMacro)).to.be.false; + const targetMacros = target.getMacros() as ShaderMacro[]; + expect(targetMacros).to.have.lengthOf(1); + expect(targetMacros[0]).to.equal(sourceMacro); + + const macroMap = (target as any)._macroMap; + for (const key in macroMap) { + expect(Number(key)).to.equal(macroMap[key]._nameId); + } + }); + + it("should not have duplicate macros with same name under different keys", () => { + const target = new ShaderData(ShaderDataGroup.Renderer); + target.enableMacro("MACRO_X"); + target.enableMacro("MACRO_Y"); + target.enableMacro("MACRO_Z"); + + const source = new ShaderData(ShaderDataGroup.Renderer); + source.enableMacro("MACRO_Y"); + + source.cloneTo(target); + + const targetMacros = target.getMacros() as ShaderMacro[]; + expect(targetMacros).to.have.lengthOf(1); + expect(targetMacros[0].name).to.equal("MACRO_Y"); + + const names = targetMacros.map((m) => m.name); + const uniqueNames = [...new Set(names)]; + expect(names.length).to.equal(uniqueNames.length); + }); + + it("clone() should produce a clean independent copy", () => { + const source = new ShaderData(ShaderDataGroup.Renderer); + source.enableMacro("CLONE_INDEPENDENT_A"); + source.enableMacro("CLONE_INDEPENDENT_B"); + + const cloned = source.clone(); + + const macroA = ShaderMacro.getByName("CLONE_INDEPENDENT_A"); + const macroB = ShaderMacro.getByName("CLONE_INDEPENDENT_B"); + expect(cloned._macroCollection.isEnable(macroA)).to.be.true; + expect(cloned._macroCollection.isEnable(macroB)).to.be.true; + + source.disableMacro("CLONE_INDEPENDENT_A"); + expect(cloned._macroCollection.isEnable(macroA)).to.be.true; + }); + }); + + describe("CloneManager", () => { + it("default cloneMode deep-clones same-constructor objects", () => { + const sourceObj = { name: "B", id: 2 }; + const targetObj = { name: "A", id: 1 }; + const source = { _field: sourceObj }; + const target = { _field: targetObj }; + + CloneManager.cloneProperty(source, target, "_field", undefined, null, null, new Map()); + + expect(target._field).to.equal(targetObj); + expect(targetObj.name).to.equal("B"); + expect(targetObj.id).to.equal(2); + }); + + it("CloneMode.Assignment prevents singleton corruption", () => { + const macroA = ShaderMacro.getByName("SINGLETON_FIX_A"); + const macroB = ShaderMacro.getByName("SINGLETON_FIX_B"); + + const source = { _macro: macroB }; + const target = { _macro: macroA }; + + CloneManager.cloneProperty(source, target, "_macro", CloneMode.Assignment, null, null, new Map()); + + expect(macroA.name).to.equal("SINGLETON_FIX_A"); + expect(macroA._nameId).to.not.equal(macroB._nameId); + expect(target._macro).to.equal(macroB); + }); + + it("should not infinite loop on circular references", () => { + // Simulate AnimatorState ↔ AnimatorStateTransition cycle: + // State has transitions array, each Transition has destinationState pointing back to a State + class FakeState { + transitions: FakeTransition[] = []; + } + class FakeTransition { + destinationState: FakeState = null; + } + + // Build circular graph: stateA → transitionAB → stateB → transitionBA → stateA + const srcStateA = new FakeState(); + const srcStateB = new FakeState(); + const srcTransAB = new FakeTransition(); + const srcTransBA = new FakeTransition(); + srcTransAB.destinationState = srcStateB; + srcTransBA.destinationState = srcStateA; + srcStateA.transitions = [srcTransAB]; + srcStateB.transitions = [srcTransBA]; + + // Target has its own independent state graph + const tgtStateA = new FakeState(); + const tgtStateB = new FakeState(); + const tgtTransAB = new FakeTransition(); + const tgtTransBA = new FakeTransition(); + tgtTransAB.destinationState = tgtStateB; + tgtTransBA.destinationState = tgtStateA; + tgtStateA.transitions = [tgtTransAB]; + tgtStateB.transitions = [tgtTransBA]; + + const source = { state: srcStateA }; + const target = { state: tgtStateA }; + + // This must not hang — should complete within milliseconds + CloneManager.cloneProperty(source, target, "state", CloneMode.Deep, null, null, new Map()); + + // After clone, target's state graph should reflect source's data + expect(target.state.transitions).to.have.lengthOf(1); + }); + }); +}); diff --git a/tests/src/core/Transform.test.ts b/tests/src/core/Transform.test.ts index 58ffe3f4a8..dc14acbf42 100644 --- a/tests/src/core/Transform.test.ts +++ b/tests/src/core/Transform.test.ts @@ -1,4 +1,4 @@ -import { deepClone, Entity, Scene, Transform } from "@galacean/engine-core"; +import { deepClone, Entity, Scene, Transform, TransformModifyFlags } from "@galacean/engine-core"; import { Vector2, Vector3 } from "@galacean/engine-math"; import { WebGLEngine } from "@galacean/engine-rhi-webgl"; import { beforeAll, describe, expect, it } from "vitest"; @@ -74,6 +74,108 @@ describe("Transform test", function () { expect(parent.transform.instanceId).eq(child.transform._getParentTransform()?.instanceId); }); + it("Reparent propagates world matrix dirty to deep descendants after clone", () => { + // Build source hierarchy: source -> middle -> inner (with local offset) + const source = new Entity(engine, "source"); + const srcMiddle = source.createChild("middle"); + const srcInner = srcMiddle.createChild("inner"); + srcInner.transform.setPosition(10, 20, 30); + + // Clone (equivalent to PrefabResource.instantiate) + const clone = source.clone(); + const cloneMiddle = clone.findByName("middle")!; + const cloneInner = cloneMiddle.findByName("inner")!; + + // Access cloneInner.worldMatrix before adding clone to a positioned parent. + const worldBeforeReparent = cloneInner.transform.worldMatrix; + expect(worldBeforeReparent.elements[12]).to.equal(10); + expect(worldBeforeReparent.elements[13]).to.equal(20); + expect(worldBeforeReparent.elements[14]).to.equal(30); + + // Reparent the clone under a positioned root — same as `table.addChild(levelNode)`. + const root = scene.createRootEntity("reparent-root"); + root.transform.setPosition(1000, 2000, 3000); + root.addChild(clone); + + // cloneInner.worldMatrix must reflect root's offset (deep descendant of moved subtree). + const worldAfterReparent = cloneInner.transform.worldMatrix; + expect(worldAfterReparent.elements[12]).to.equal(1010); + expect(worldAfterReparent.elements[13]).to.equal(2020); + expect(worldAfterReparent.elements[14]).to.equal(3030); + }); + + it("Reparent invalidates descendant world caches even when parent has all world flags set (engine dirty-flag bug)", () => { + // Reproduces a Galacean 2.0-alpha.24 engine bug observed in Screw game: + // Transform._parentChange() calls _updateAllWorldFlag which early-exits + // if `this` already has all target world dirty flags set. This skips + // propagation to descendants. After reparent, a descendant whose + // WorldMatrix flag was previously cleared keeps returning stale cache. + const parent = new Entity(engine, "parent"); + const child = parent.createChild("child"); + child.transform.setPosition(10, 20, 30); + + // 1) Access child.worldMatrix to CLEAR child's WorldMatrix dirty flag. + // The access also clears parent's WorldMatrix flag (chain compute). + const cached = child.transform.worldMatrix; + expect(cached.elements[12]).to.equal(10); + + // 2) Force parent into the failure state: + // "all world dirty flags set" (as if never accessed) — simulates the + // post-clone / lifecycle state where PARENT's world hasn't been read + // but a DESCENDANT's world was. + // @ts-ignore - white-box access for precise engine bug reproduction + parent.transform._dirtyFlag |= TransformModifyFlags.WmWpWeWqWsWus; + + // Sanity: child's WorldMatrix is CLEAR, parent has ALL world flags SET. + // @ts-ignore + expect(child.transform._dirtyFlag & TransformModifyFlags.WorldMatrix).to.equal(0); + // @ts-ignore + expect(parent.transform._dirtyFlag & TransformModifyFlags.WmWpWeWqWsWus).to.equal(TransformModifyFlags.WmWpWeWqWsWus); + + // 3) Reparent `parent` under a positioned root (triggers _parentChange on parent). + const root = scene.createRootEntity("reparent-root"); + root.transform.setPosition(1000, 2000, 3000); + root.addChild(parent); + + // 4) Child's worldMatrix MUST now reflect root's offset. + // Under the bug: early-exit in _updateAllWorldFlag skips propagation → child's + // WorldMatrix flag stays CLEAR → getter returns stale cached (10, 20, 30). + const afterReparent = child.transform.worldMatrix; + expect(afterReparent.elements[12]).to.equal(1010); + expect(afterReparent.elements[13]).to.equal(2020); + expect(afterReparent.elements[14]).to.equal(3030); + }); + + it("Reparent re-resolves descendant parent cache even when cached as null", () => { + // Reproduces the second half of the Galacean 2.0-alpha.24 bug: a descendant + // whose `_parentTransformCache` was resolved to `null` (because + // `_getParentTransform` was called while its ancestor chain was partially + // constructed) keeps returning identity worldMatrix even after the + // ancestor chain is fully wired up. + const parent = new Entity(engine, "parent"); + const child = parent.createChild("child"); + child.transform.setPosition(10, 20, 30); + + // Force child's parent cache to null with `_isParentDirty = false` — + // simulates the state observed in Screw where layer-001 had + // `_parentTransformCache = null, _isParentDirty = false` after clone. + // @ts-ignore + child.transform._parentTransformCache = null; + // @ts-ignore + child.transform._isParentDirty = false; + + // Add parent under a positioned root. If _parentChange on parent fails to + // invalidate child's parent cache, child.worldMatrix returns identity. + const root = scene.createRootEntity("cache-null-root"); + root.transform.setPosition(500, 600, 700); + root.addChild(parent); + + const after = child.transform.worldMatrix; + expect(after.elements[12]).to.equal(510); // 500 + 10 + expect(after.elements[13]).to.equal(620); // 600 + 20 + expect(after.elements[14]).to.equal(730); // 700 + 30 + }); + it("Subclasses of Transform", () => { // Create by constructor const entity0 = new Entity(engine, "entity"); diff --git a/tests/src/core/audio/AudioSourcePendingPlayback.test.ts b/tests/src/core/audio/AudioSourcePendingPlayback.test.ts new file mode 100644 index 0000000000..5e7e4645a1 --- /dev/null +++ b/tests/src/core/audio/AudioSourcePendingPlayback.test.ts @@ -0,0 +1,358 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { AudioManager, AudioSource } from "@galacean/engine-core"; + +class MockGainNode { + gain = { + setValueAtTime: vi.fn() + }; + + connect = vi.fn(); +} + +class MockBufferSourceNode { + buffer: unknown = null; + loop = false; + onended: (() => void) | null = null; + playbackRate = { + value: 1 + }; + + connect = vi.fn(); + disconnect = vi.fn(); + start = vi.fn(); + stop = vi.fn(); +} + +class MockAudioContext { + static shouldResumeSucceed = true; + static resumeResultQueue: Array | Error> | null = null; + + currentTime = 0; + destination = {}; + onstatechange: (() => void) | null = null; + state: AudioContextState = "suspended"; + + createBufferSource(): AudioBufferSourceNode { + return new MockBufferSourceNode() as unknown as AudioBufferSourceNode; + } + + createGain(): GainNode { + return new MockGainNode() as unknown as GainNode; + } + + resume(): Promise { + const queuedResult = MockAudioContext.resumeResultQueue?.shift(); + if (queuedResult instanceof Promise) { + return queuedResult; + } + if (queuedResult instanceof Error) { + return Promise.reject(queuedResult); + } + if (!MockAudioContext.shouldResumeSucceed) { + return Promise.reject(new Error("autoplay blocked")); + } + this.state = "running"; + this.onstatechange?.(); + return Promise.resolve(); + } + + suspend(): Promise { + this.state = "suspended"; + this.onstatechange?.(); + return Promise.resolve(); + } +} + +async function flushAsync(): Promise { + await Promise.resolve(); + await Promise.resolve(); +} + +function createAudioSource(): AudioSource { + const audioSource = new AudioSource({ + _isActiveInHierarchy: true, + _isActiveInScene: true, + _removeComponent() {}, + engine: {} + } as any); + + audioSource.clip = { + _addReferCount() {}, + _getAudioSource() { + return {}; + } + } as any; + + return audioSource; +} + +describe("AudioSource pending playback", () => { + beforeEach(() => { + (window as any).AudioContext = MockAudioContext; + (AudioManager as any)._context = null; + (AudioManager as any)._gainNode = null; + (AudioManager as any)._needsUserGestureResume = false; + (AudioManager as any)._pendingSources = new Set(); + (AudioManager as any)._playingSources = new Set(); + (AudioManager as any)._interruptedSources = new Set(); + (AudioManager as any)._foregroundRestoreTimer = undefined; + (AudioManager as any)._hidden = false; + MockAudioContext.shouldResumeSucceed = true; + MockAudioContext.resumeResultQueue = null; + AudioManager._playingCount = 0; + }); + + afterEach(() => { + vi.useRealTimers(); + vi.restoreAllMocks(); + document.replaceChildren(); + }); + + it("replays pending playback on the next user gesture after autoplay blocking", async () => { + const audioSource = createAudioSource(); + + vi.spyOn(console, "warn").mockImplementation(() => {}); + MockAudioContext.shouldResumeSucceed = false; + + audioSource.play(); + await flushAsync(); + + expect((audioSource as any)._pendingPlay).to.be.true; + expect((AudioManager as any)._pendingSources.size).to.equal(1); + expect((AudioManager as any)._needsUserGestureResume).to.be.false; + expect(audioSource.isPlaying).to.be.false; + + MockAudioContext.shouldResumeSucceed = true; + document.dispatchEvent(new Event("click")); + await flushAsync(); + + expect(audioSource.isPlaying).to.be.true; + expect((audioSource as any)._pendingPlay).to.be.false; + expect((AudioManager as any)._pendingSources.size).to.equal(0); + expect((AudioManager as any)._needsUserGestureResume).to.be.false; + }); + + it("cancels pending playback before the unlocking gesture arrives", async () => { + const audioSource = createAudioSource(); + + vi.spyOn(console, "warn").mockImplementation(() => {}); + MockAudioContext.shouldResumeSucceed = false; + + audioSource.play(); + await flushAsync(); + + audioSource.stop(); + expect((audioSource as any)._pendingPlay).to.be.false; + expect((AudioManager as any)._pendingSources.size).to.equal(0); + + MockAudioContext.shouldResumeSucceed = true; + document.dispatchEvent(new Event("click")); + await flushAsync(); + + expect(audioSource.isPlaying).to.be.false; + expect((audioSource as any)._pendingPlay).to.be.false; + }); + + it("keeps resume a no-op until a context already exists", async () => { + expect((AudioManager as any)._context).to.be.null; + + await AudioManager.resume(); + + expect((AudioManager as any)._context).to.be.null; + }); + + it("does not resume foreground audio before a hide event", async () => { + createAudioSource(); + const context = (AudioManager as any)._context as MockAudioContext; + + vi.spyOn(document, "hidden", "get").mockReturnValue(false); + const resumeSpy = vi.spyOn(context, "resume"); + const suspendSpy = vi.spyOn(AudioManager, "suspend"); + + context.state = "suspended"; + AudioManager._playingCount = 1; + + document.dispatchEvent(new Event("visibilitychange")); + await flushAsync(); + + expect(resumeSpy).not.toHaveBeenCalled(); + expect(suspendSpy).not.toHaveBeenCalled(); + expect((AudioManager as any)._needsUserGestureResume).to.be.false; + }); + + it("recreates interrupted source nodes from a foreground gesture", async () => { + const audioSource = createAudioSource(); + const context = (AudioManager as any)._context as MockAudioContext; + + context.state = "running"; + audioSource.play(); + + const firstSourceNode = (audioSource as any)._sourceNode as MockBufferSourceNode; + expect(audioSource.isPlaying).to.be.true; + expect(AudioManager._playingCount).to.equal(1); + + const hiddenSpy = vi.spyOn(document, "hidden", "get").mockReturnValue(true); + document.dispatchEvent(new Event("visibilitychange")); + await flushAsync(); + + expect(firstSourceNode.stop).toHaveBeenCalledTimes(1); + expect(audioSource.isPlaying).to.be.false; + expect(AudioManager._playingCount).to.equal(0); + expect((AudioManager as any)._interruptedSources.size).to.equal(1); + + hiddenSpy.mockReturnValue(false); + document.dispatchEvent(new Event("visibilitychange")); + await flushAsync(); + + expect(audioSource.isPlaying).to.be.false; + expect((AudioManager as any)._interruptedSources.size).to.equal(1); + expect((AudioManager as any)._needsUserGestureResume).to.be.true; + + document.dispatchEvent(new Event("touchend")); + await flushAsync(); + + expect(audioSource.isPlaying).to.be.true; + expect(AudioManager._playingCount).to.equal(1); + expect((AudioManager as any)._interruptedSources.size).to.equal(0); + expect((audioSource as any)._sourceNode).not.to.equal(firstSourceNode); + }); + + it("recovers interrupted source nodes from foreground retry after the restore delay", async () => { + vi.useFakeTimers(); + const audioSource = createAudioSource(); + const context = (AudioManager as any)._context as MockAudioContext; + + context.state = "running"; + audioSource.play(); + + const hiddenSpy = vi.spyOn(document, "hidden", "get").mockReturnValue(true); + document.dispatchEvent(new Event("visibilitychange")); + await flushAsync(); + + hiddenSpy.mockReturnValue(false); + document.dispatchEvent(new Event("visibilitychange")); + await flushAsync(); + + expect(audioSource.isPlaying).to.be.false; + + await vi.advanceTimersByTimeAsync(299); + await flushAsync(); + + expect(audioSource.isPlaying).to.be.false; + + await vi.advanceTimersByTimeAsync(1); + await flushAsync(); + + expect(audioSource.isPlaying).to.be.true; + expect((AudioManager as any)._interruptedSources.size).to.equal(0); + }); + + it("handles document pagehide/pageshow and mouseup recovery", async () => { + const audioSource = createAudioSource(); + const context = (AudioManager as any)._context as MockAudioContext; + + context.state = "running"; + audioSource.play(); + + document.dispatchEvent(new Event("pagehide")); + await flushAsync(); + + expect(audioSource.isPlaying).to.be.false; + expect((AudioManager as any)._interruptedSources.size).to.equal(1); + + document.dispatchEvent(new Event("pageshow")); + await flushAsync(); + + expect(audioSource.isPlaying).to.be.false; + expect((AudioManager as any)._needsUserGestureResume).to.be.true; + + document.dispatchEvent(new Event("mouseup")); + await flushAsync(); + + expect(audioSource.isPlaying).to.be.true; + expect((AudioManager as any)._interruptedSources.size).to.equal(0); + }); + + it("keeps gesture recovery when foreground resume fails", async () => { + vi.useFakeTimers(); + const audioSource = createAudioSource(); + const context = (AudioManager as any)._context as MockAudioContext; + + vi.spyOn(console, "warn").mockImplementation(() => {}); + const hiddenSpy = vi.spyOn(document, "hidden", "get").mockReturnValue(true); + const resumeSpy = vi.spyOn(context, "resume"); + const suspendSpy = vi.spyOn(AudioManager, "suspend"); + + context.state = "running"; + audioSource.play(); + + document.dispatchEvent(new Event("visibilitychange")); + await flushAsync(); + + MockAudioContext.shouldResumeSucceed = false; + hiddenSpy.mockReturnValue(false); + document.dispatchEvent(new Event("visibilitychange")); + await flushAsync(); + + expect(resumeSpy).not.toHaveBeenCalled(); + expect(suspendSpy).toHaveBeenCalledTimes(2); + expect((AudioManager as any)._needsUserGestureResume).to.be.true; + + await vi.advanceTimersByTimeAsync(299); + await flushAsync(); + + expect(resumeSpy).not.toHaveBeenCalled(); + expect(suspendSpy).toHaveBeenCalledTimes(2); + expect((AudioManager as any)._needsUserGestureResume).to.be.true; + + await vi.advanceTimersByTimeAsync(1); + await flushAsync(); + + expect(resumeSpy).toHaveBeenCalledTimes(1); + expect(suspendSpy).toHaveBeenCalledTimes(3); + expect((AudioManager as any)._needsUserGestureResume).to.be.true; + + document.dispatchEvent(new Event("click")); + await flushAsync(); + + expect(resumeSpy).toHaveBeenCalledTimes(2); + expect((AudioManager as any)._needsUserGestureResume).to.be.true; + + MockAudioContext.shouldResumeSucceed = true; + document.dispatchEvent(new Event("click")); + await flushAsync(); + + expect(resumeSpy).toHaveBeenCalledTimes(3); + expect(context.state).to.equal("running"); + expect((AudioManager as any)._needsUserGestureResume).to.be.false; + }); + + it("retries context.resume inside a later user gesture even if an earlier resume is still pending", async () => { + createAudioSource(); + const context = (AudioManager as any)._context as MockAudioContext; + const firstResume = new Promise(() => {}); + + MockAudioContext.resumeResultQueue = [firstResume]; + const resumeSpy = vi.spyOn(context, "resume"); + + AudioManager.resume().catch(() => {}); + await flushAsync(); + + expect(resumeSpy).toHaveBeenCalledTimes(1); + + MockAudioContext.resumeResultQueue = [ + Promise.resolve().then(() => { + context.state = "running"; + context.onstatechange?.(); + }) + ]; + (AudioManager as any)._needsUserGestureResume = true; + + document.dispatchEvent(new Event("click")); + await flushAsync(); + + expect(resumeSpy).toHaveBeenCalledTimes(2); + expect(context.state).to.equal("running"); + expect((AudioManager as any)._needsUserGestureResume).to.be.false; + }); +}); diff --git a/tests/src/core/physics/PhysicsScene.test.ts b/tests/src/core/physics/PhysicsScene.test.ts index 406306a4b6..fb28579400 100644 --- a/tests/src/core/physics/PhysicsScene.test.ts +++ b/tests/src/core/physics/PhysicsScene.test.ts @@ -508,6 +508,7 @@ describe("Physics Test", () => { rootEntityCharacter.transform.position = new Vector3(0, 0, 0); const characterController = rootEntityCharacter.addComponent(CharacterController); + characterController.collisionLayer = Layer.Layer3; const boxShape2 = new BoxColliderShape(); boxShape2.size.set(1, 1, 1); boxShape2.position = new Vector3(0, 0, 0); diff --git a/tests/src/loader/GLTFLoader.test.ts b/tests/src/loader/GLTFLoader.test.ts index 7b35b7b330..3c8aa822a7 100644 --- a/tests/src/loader/GLTFLoader.test.ts +++ b/tests/src/loader/GLTFLoader.test.ts @@ -39,6 +39,60 @@ beforeAll(async function () { @registerGLTFParser(GLTFParserType.Schema) class GLTFCustomJSONParser extends GLTFParser { parse(context: GLTFParserContext) { + if (context.glTFResource.url.endsWith("testSkinRoot.gltf")) { + context.buffers = [new ArrayBuffer(128)]; + return Promise.resolve({ + asset: { + version: "2.0" + }, + scene: 0, + scenes: [ + { + nodes: [0, 1] + } + ], + nodes: [ + { + name: "Character_Man" + }, + { + name: "mixamorig:Hips", + children: [2] + }, + { + name: "mixamorig:Spine" + } + ], + skins: [ + { + inverseBindMatrices: 0, + joints: [1, 2] + } + ], + accessors: [ + { + bufferView: 0, + byteOffset: 0, + componentType: 5126, + count: 2, + type: "MAT4" + } + ], + bufferViews: [ + { + buffer: 0, + byteOffset: 0, + byteLength: 128 + } + ], + buffers: [ + { + byteLength: 128 + } + ] + }); + } + const glTF = { buffers: [ { @@ -481,6 +535,17 @@ describe("glTF Loader test", function () { expect(renderer).to.exist; expect(renderer.blendShapeWeights).to.deep.include([1, 1]); }); + + it("single-root animation root channel should bind to the root node path", async () => { + const glTFResource: GLTFResource = await engine.resourceManager.load({ + type: AssetType.GLTF, + url: "mock/path/testA.gltf" + }); + + const clip = glTFResource.animations?.[0]; + expect(clip).to.exist; + expect(clip.curveBindings[0].relativePath).to.equal("entity1"); + }); }); describe("glTF instance test", function () { @@ -517,6 +582,33 @@ describe("glTF instance test", function () { }); }); +describe("glTF scene root structure", function () { + it("Single root scene should have GLTF_ROOT container", async () => { + const glTFResource: GLTFResource = await engine.resourceManager.load({ + type: AssetType.GLTF, + url: "mock/path/testRoot.gltf" + }); + const { defaultSceneRoot } = glTFResource; + + // Should always create GLTF_ROOT container, even for single-root scenes + expect(defaultSceneRoot.name).to.equal("GLTF_ROOT"); + expect(defaultSceneRoot.children.length).to.equal(1); + expect(defaultSceneRoot.children[0].name).to.equal("entity1"); + }); + + it("Multi-root skins without skeleton should use the scene wrapper as rootBone", async () => { + const glTFResource: GLTFResource = await engine.resourceManager.load({ + type: AssetType.GLTF, + url: "mock/path/testSkinRoot.gltf" + }); + const { defaultSceneRoot, skins } = glTFResource; + + expect(defaultSceneRoot.name).to.equal("GLTF_ROOT"); + expect(defaultSceneRoot.children.length).to.equal(2); + expect(skins[0].rootBone).to.equal(defaultSceneRoot); + }); +}); + describe("glTF instance test", function () { it("GLTFResource destroy directly", async () => { const glTFResource: GLTFResource = await engine.resourceManager.load({ diff --git a/tests/src/loader/StrippedEntity.test.ts b/tests/src/loader/StrippedEntity.test.ts new file mode 100644 index 0000000000..6f078d1d17 --- /dev/null +++ b/tests/src/loader/StrippedEntity.test.ts @@ -0,0 +1,277 @@ +/** + * Tests stripped entities that proxy internal prefab-instance entities. + * + * A stripped entity can resolve to an entity inside a nested prefab instance and + * serve as the parent for newly added entities. + */ +import { expect, beforeAll, afterAll, describe, it } from "vitest"; +import { WebGLEngine } from "@galacean/engine-rhi-webgl"; +import type { IHierarchyFile } from "@galacean/engine-loader"; +import { Vector3 } from "@galacean/engine-math"; +import { PrefabParser } from "../../../packages/loader/src/prefab/PrefabParser"; + +let engine: WebGLEngine; + +function getResourceObjectPool(): Record { + return (engine.resourceManager as unknown as { _objectPool: Record })._objectPool; +} + +function cachePrefab(url: string, prefab: unknown): void { + getResourceObjectPool()[url] = prefab; +} + +function removeCachedPrefab(url: string): void { + delete getResourceObjectPool()[url]; +} + +beforeAll(async () => { + const canvas = document.createElement("canvas"); + canvas.width = 256; + canvas.height = 256; + engine = await WebGLEngine.create({ canvas }); +}); + +afterAll(() => { + engine?.destroy(); +}); + +describe("IStrippedEntity as addedEntities mechanism", () => { + it("keeps nested prefab children after instantiation", async () => { + const nestedPrefabData: IHierarchyFile = { + entities: [ + { id: "0", name: "nestedRoot", components: [], children: ["1", "2"] }, + { id: "1", name: "boneHand", parent: "0", components: [] }, + { id: "2", name: "otherChild", parent: "0", components: [] } + ] + }; + const nestedPrefab = await PrefabParser.parse(engine, "sanity.prefab", nestedPrefabData); + const inst = nestedPrefab.instantiate(); + const names = inst.children.map((c) => c.name); + expect(names).toContain("boneHand"); + expect(names).toContain("otherChild"); + inst.destroy(); + }); + + it("should attach new child entity under an internal entity of a nested prefab", async () => { + // Nested prefab: + // root + // - boneHand (proxied by the stripped entity) + // - otherChild + const nestedPrefabData: IHierarchyFile = { + entities: [ + { id: "0", name: "nestedRoot", components: [], children: ["1", "2"] }, + { id: "1", name: "boneHand", parent: "0", components: [] }, + { id: "2", name: "otherChild", parent: "0", components: [] } + ] + }; + const nestedPrefab = await PrefabParser.parse(engine, "char.prefab", nestedPrefabData); + cachePrefab("char.prefab", nestedPrefab); + + // Outer prefab: + // - IRefEntity instantiating the nested prefab (only direct child of outerRoot) + // - IStrippedEntity proxying to boneHand, not in outerRoot.children + // - weaponslot listed in stripped entity's children + const outerPrefabData: IHierarchyFile = { + entities: [ + { + id: "outerRoot", + name: "Character", + components: [], + children: ["charInst"] + }, + { + id: "charInst", + name: "char", + parent: "outerRoot", + components: [], + assetUrl: "char.prefab", + isClone: true, + modifications: [], + removedEntities: [], + removedComponents: [] + } as any, + { + // Do not set `name`: _applyEntityData would override the internal entity's name. + strippedId: "boneHandle", + prefabInstanceId: "charInst", + prefabSource: { assetId: "", entityId: "0" }, + components: [], + children: ["weaponslot"] + } as any, + { + id: "weaponslot", + name: "weaponslot1", + parent: "boneHandle", + components: [], + position: { x: 0.5, y: 0.25, z: 0 } + } + ] + }; + + const outerPrefab = await PrefabParser.parse(engine, "outer.prefab", outerPrefabData); + const root = outerPrefab.instantiate(); + + const charInst = root.children.find((c) => c.name === "char"); + expect(charInst, "char instance should be a child of outerRoot").not.toBeUndefined(); + + const boneHand = charInst!.children.find((c) => c.name === "boneHand"); + expect(boneHand, "boneHand should exist inside nested prefab").not.toBeUndefined(); + + const weaponslot = boneHand!.children.find((c) => c.name === "weaponslot1"); + expect(weaponslot, "weaponslot1 should be attached as child of boneHand via stripped entity").not.toBeUndefined(); + expect(weaponslot!.transform.position.x).toBeCloseTo(0.5, 5); + expect(weaponslot!.transform.position.y).toBeCloseTo(0.25, 5); + expect(weaponslot!.transform.position.z).toBeCloseTo(0, 5); + + root.destroy(); + removeCachedPrefab("char.prefab"); + }); + + it("should support multiple stripped entities targeting different internal entities (LeftHand / RightHand socket case)", async () => { + // Nested prefab: root -> [LeftHand, RightHand] + const nestedPrefabData: IHierarchyFile = { + entities: [ + { id: "0", name: "nestedRoot", components: [], children: ["1", "2"] }, + { id: "1", name: "LeftHand", parent: "0", components: [] }, + { id: "2", name: "RightHand", parent: "0", components: [] } + ] + }; + const nestedPrefab = await PrefabParser.parse(engine, "body.prefab", nestedPrefabData); + cachePrefab("body.prefab", nestedPrefab); + + // entityId is the path string generated by _generateInstanceContext: + // nestedRoot = "" + // nestedRoot.children[0] = LeftHand -> "0" + // nestedRoot.children[1] = RightHand -> "1" + const outerPrefabData: IHierarchyFile = { + entities: [ + { + id: "outerRoot", + name: "Player", + components: [], + children: ["bodyInst"] + }, + { + id: "bodyInst", + name: "body", + parent: "outerRoot", + components: [], + assetUrl: "body.prefab", + isClone: true, + modifications: [], + removedEntities: [], + removedComponents: [] + } as any, + { + strippedId: "lhHandle", + prefabInstanceId: "bodyInst", + prefabSource: { assetId: "", entityId: "0" }, + components: [], + children: ["ws1"] + } as any, + { + strippedId: "rhHandle", + prefabInstanceId: "bodyInst", + prefabSource: { assetId: "", entityId: "1" }, + components: [], + children: ["ws2", "ws3"] + } as any, + { id: "ws1", name: "weaponslot1", parent: "lhHandle", components: [] }, + { id: "ws2", name: "weaponslot2", parent: "rhHandle", components: [] }, + { id: "ws3", name: "weaponslot3", parent: "rhHandle", components: [] } + ] + }; + + const outerPrefab = await PrefabParser.parse(engine, "player.prefab", outerPrefabData); + const root = outerPrefab.instantiate(); + const bodyInst = root.children.find((c) => c.name === "body")!; + const leftHand = bodyInst.children.find((c) => c.name === "LeftHand")!; + const rightHand = bodyInst.children.find((c) => c.name === "RightHand")!; + + const slot1 = leftHand.children.find((c) => c.name === "weaponslot1"); + const slot2 = rightHand.children.find((c) => c.name === "weaponslot2"); + const slot3 = rightHand.children.find((c) => c.name === "weaponslot3"); + + expect(slot1, "weaponslot1 under LeftHand").not.toBeUndefined(); + expect(slot2, "weaponslot2 under RightHand").not.toBeUndefined(); + expect(slot3, "weaponslot3 under RightHand").not.toBeUndefined(); + + // No new entities should remain as direct children of outerRoot after reparenting + expect(root.children.find((c) => c.name === "weaponslot1")).toBeUndefined(); + expect(root.children.find((c) => c.name === "lh-proxy")).toBeUndefined(); + + root.destroy(); + removeCachedPrefab("body.prefab"); + }); + + it("should propagate internal entity transform changes to the attached child (bone-drives-weapon behavior)", async () => { + // When an internal entity moves, the child attached through the stripped + // entity follows through normal hierarchy transforms. + const nestedPrefabData: IHierarchyFile = { + entities: [ + { id: "0", name: "nestedRoot", components: [], children: ["1"] }, + { id: "1", name: "bone", parent: "0", components: [] } + ] + }; + const nestedPrefab = await PrefabParser.parse(engine, "skel.prefab", nestedPrefabData); + cachePrefab("skel.prefab", nestedPrefab); + + const outerPrefabData: IHierarchyFile = { + entities: [ + { + id: "outerRoot", + name: "Actor", + components: [], + children: ["skelInst"] + }, + { + id: "skelInst", + name: "skel", + parent: "outerRoot", + components: [], + assetUrl: "skel.prefab", + isClone: true, + modifications: [], + removedEntities: [], + removedComponents: [] + } as any, + { + strippedId: "boneHandle", + prefabInstanceId: "skelInst", + prefabSource: { assetId: "", entityId: "0" }, + components: [], + children: ["weapon"] + } as any, + { + id: "weapon", + name: "weapon", + parent: "boneHandle", + components: [], + position: { x: 1, y: 0, z: 0 } + } + ] + }; + + const outerPrefab = await PrefabParser.parse(engine, "actor.prefab", outerPrefabData); + const root = outerPrefab.instantiate(); + const bone = root.children.find((c) => c.name === "skel")!.children.find((c) => c.name === "bone")!; + const weapon = bone.children.find((c) => c.name === "weapon")!; + + // Initial: bone at origin, weapon world position = (1, 0, 0) + const worldPos = new Vector3(); + worldPos.copyFrom(weapon.transform.worldPosition); + expect(worldPos.x).toBeCloseTo(1, 5); + expect(worldPos.y).toBeCloseTo(0, 5); + expect(worldPos.z).toBeCloseTo(0, 5); + + // Simulate transform animation: move bone to (10, 5, -3) + bone.transform.setPosition(10, 5, -3); + worldPos.copyFrom(weapon.transform.worldPosition); + expect(worldPos.x).toBeCloseTo(11, 5); // 10 + 1 + expect(worldPos.y).toBeCloseTo(5, 5); // 5 + 0 + expect(worldPos.z).toBeCloseTo(-3, 5); // -3 + 0 + + root.destroy(); + removeCachedPrefab("skel.prefab"); + }); +}); diff --git a/tests/src/shader-lab/ShaderLab.test.ts b/tests/src/shader-lab/ShaderLab.test.ts index e998533e5e..b1d5085044 100644 --- a/tests/src/shader-lab/ShaderLab.test.ts +++ b/tests/src/shader-lab/ShaderLab.test.ts @@ -247,8 +247,128 @@ describe("ShaderLab", async () => { glslValidate(engine, shaderSource, shaderLabRelease); }); + it("macro-negate-number (!0, !1 in #if expressions)", async () => { + const shaderSource = await readFile("./shaders/macro-negate-number.shader"); + glslValidate(engine, shaderSource, shaderLabVerbose); + glslValidate(engine, shaderSource, shaderLabRelease); + }); + it("mrt-struct", async () => { const shaderSource = await readFile("./shaders/mrt-struct.shader"); glslValidate(engine, shaderSource, shaderLabRelease); }); + + it("texture-generic (GVec4 → vec4 resolve)", async () => { + const shaderSource = await readFile("./shaders/texture-generic.shader"); + glslValidate(engine, shaderSource, shaderLabRelease); + }); + + it("generic-return-type (builtin generic return as arg to user function)", async () => { + const shaderSource = await readFile("./shaders/generic-return-type.shader"); + glslValidate(engine, shaderSource, shaderLabRelease); + }); + + it("define-struct-access-global (global #define with struct member access)", async () => { + const shaderSource = await readFile("./shaders/define-struct-access-global.shader"); + glslValidate(engine, shaderSource, shaderLabRelease); + + const shader = shaderLabVerbose._parseShaderSource(shaderSource); + const passSource = shader.subShaders[0].passes[0]; + const { vertex, fragment } = shaderLabVerbose._parseShaderPass( + passSource.contents, + passSource.vertexEntry, + passSource.fragmentEntry, + 0, + "" + )!; + + const expectedVert = await readFile("./expected/define-struct-access-global.vert.glsl"); + const expectedFrag = await readFile("./expected/define-struct-access-global.frag.glsl"); + expect(vertex).to.equal(expectedVert); + expect(fragment).to.equal(expectedFrag); + }); + + it("define-struct-access (function-body #define with struct member access)", async () => { + const shaderSource = await readFile("./shaders/define-struct-access.shader"); + glslValidate(engine, shaderSource, shaderLabRelease); + + const shader = shaderLabVerbose._parseShaderSource(shaderSource); + const passSource = shader.subShaders[0].passes[0]; + const { vertex, fragment } = shaderLabVerbose._parseShaderPass( + passSource.contents, + passSource.vertexEntry, + passSource.fragmentEntry, + 0, + "" + )!; + + const expectedVert = await readFile("./expected/define-struct-access.vert.glsl"); + const expectedFrag = await readFile("./expected/define-struct-access.frag.glsl"); + expect(vertex).to.equal(expectedVert); + expect(fragment).to.equal(expectedFrag); + }); + + it("macro-member-access-builtin-arg (Cocos FSInput pattern: member access macro as builtin fn arg)", async () => { + const shaderSource = await readFile("./shaders/macro-member-access-builtin-arg.shader"); + glslValidate(engine, shaderSource, shaderLabRelease); + + // Also verify verbose mode (semantic analysis) succeeds — this was the original bug: + // member access macros like #define FSInput_worldNormal v.v_normal.xyz resolved to + // struct type "Varyings" instead of TypeAny, causing builtin overload matching to fail. + const shader = shaderLabVerbose._parseShaderSource(shaderSource); + const passSource = shader.subShaders[0].passes[0]; + const { vertex, fragment } = shaderLabVerbose._parseShaderPass( + passSource.contents, + passSource.vertexEntry, + passSource.fragmentEntry, + 0, + "" + )!; + + expect(vertex).to.be.a("string").and.not.empty; + expect(fragment).to.be.a("string").and.not.empty; + + // Verify key builtins are present in output (macros expanded correctly) + expect(fragment).to.contain("normalize"); + expect(fragment).to.contain("dot"); + expect(fragment).to.contain("texture2D"); + }); + + it("global-varying-var (Cocos VSOutput pattern: global Varyings var with #define macros)", async () => { + const shaderSource = await readFile("./shaders/global-varying-var.shader"); + glslValidate(engine, shaderSource, shaderLabRelease); + + // Verify verbose mode: global "Varyings o;" should not produce "uniform Varyings o;" + // and should not duplicate varying declarations. + const shader = shaderLabVerbose._parseShaderSource(shaderSource); + const passSource = shader.subShaders[0].passes[0]; + const { vertex, fragment } = shaderLabVerbose._parseShaderPass( + passSource.contents, + passSource.vertexEntry, + passSource.fragmentEntry, + 0, + "" + )!; + + expect(vertex).to.be.a("string").and.not.empty; + expect(fragment).to.be.a("string").and.not.empty; + + // No "uniform Varyings o;" in output + expect(vertex).to.not.contain("uniform Varyings"); + expect(fragment).to.not.contain("uniform Varyings"); + + // Macros should be transformed: "o.v_worldPos" → "v_worldPos" + expect(vertex).to.contain("#define VSOutput_worldPos v_worldPos"); + expect(vertex).to.contain("#define VSOutput_worldNormal v_normal.xyz"); + + // No duplicate varying declarations + const varyingMatches = vertex.match(/varying vec3 v_worldPos/g); + expect(varyingMatches).to.have.lengthOf(1); + }); + + it("frag-return-vec4 (Cocos pattern: fragment entry returns vec4 instead of void)", async () => { + const shaderSource = await readFile("./shaders/frag-return-vec4.shader"); + glslValidate(engine, shaderSource, shaderLabRelease); + glslValidate(engine, shaderSource, shaderLabVerbose); + }); }); diff --git a/tests/src/shader-lab/ShaderValidate.ts b/tests/src/shader-lab/ShaderValidate.ts index da6d83407b..7689c721bd 100644 --- a/tests/src/shader-lab/ShaderValidate.ts +++ b/tests/src/shader-lab/ShaderValidate.ts @@ -65,7 +65,7 @@ export function glslValidate( }); // @ts-ignore - const shaderProgram = shaderPass._getCanonicalShaderProgram(engine, macroMockCollection); + const shaderProgram = shaderPass._compileShaderProgram(engine, macroMockCollection); expect(shaderProgram.isValid).to.be.true; }); }); diff --git a/tests/src/shader-lab/expected/define-struct-access-global.frag.glsl b/tests/src/shader-lab/expected/define-struct-access-global.frag.glsl new file mode 100644 index 0000000000..e766b6e6a1 --- /dev/null +++ b/tests/src/shader-lab/expected/define-struct-access-global.frag.glsl @@ -0,0 +1,10 @@ +varying vec2 v_uv; + +uniform sampler2D u_texture; +#define ATTR_POS POSITION + +#define VARYING_UV v_uv + +#define FRAG_UV v_uv + +void main() { gl_FragColor = texture2D ( u_texture , FRAG_UV ) ; } \ No newline at end of file diff --git a/tests/src/shader-lab/expected/define-struct-access-global.vert.glsl b/tests/src/shader-lab/expected/define-struct-access-global.vert.glsl new file mode 100644 index 0000000000..782ad3ee52 --- /dev/null +++ b/tests/src/shader-lab/expected/define-struct-access-global.vert.glsl @@ -0,0 +1,16 @@ +uniform mat4 renderer_MVPMat; +attribute vec4 POSITION; +attribute vec2 TEXCOORD_0; + +varying vec2 v_uv; + +#define ATTR_POS POSITION + +#define VARYING_UV v_uv + +#define FRAG_UV v_uv + +void main() { +gl_Position = renderer_MVPMat * ATTR_POS ; +VARYING_UV = TEXCOORD_0 ; + } \ No newline at end of file diff --git a/tests/src/shader-lab/expected/define-struct-access.frag.glsl b/tests/src/shader-lab/expected/define-struct-access.frag.glsl new file mode 100644 index 0000000000..2c8ba502ac --- /dev/null +++ b/tests/src/shader-lab/expected/define-struct-access.frag.glsl @@ -0,0 +1,11 @@ +varying vec2 v_uv; +varying vec3 v_normal; + +uniform sampler2D u_texture; +uniform vec3 u_lightDir; +void main() { #define FRAG_UV v_uv + +#define FRAG_NORMAL v_normal + +float NdotL = dot ( FRAG_NORMAL , u_lightDir ) ; +gl_FragColor = texture2D ( u_texture , FRAG_UV ) * NdotL ; } \ No newline at end of file diff --git a/tests/src/shader-lab/expected/define-struct-access.vert.glsl b/tests/src/shader-lab/expected/define-struct-access.vert.glsl new file mode 100644 index 0000000000..1ee6d28522 --- /dev/null +++ b/tests/src/shader-lab/expected/define-struct-access.vert.glsl @@ -0,0 +1,18 @@ +uniform mat4 renderer_MVPMat; +attribute vec4 POSITION; +attribute vec2 TEXCOORD_0; + +varying vec2 v_uv; +varying vec3 v_normal; + +void main() { +#define ATTR_POS POSITION + +#define VARYING_UV v_uv + +#define VARYING_NORMAL v_normal + +gl_Position = renderer_MVPMat * ATTR_POS ; +VARYING_UV = TEXCOORD_0 ; +VARYING_NORMAL = vec3 ( 0.0 , 1.0 , 0.0 ) ; + } \ No newline at end of file diff --git a/tests/src/shader-lab/shaders/define-struct-access-global.shader b/tests/src/shader-lab/shaders/define-struct-access-global.shader new file mode 100644 index 0000000000..a8abffe570 --- /dev/null +++ b/tests/src/shader-lab/shaders/define-struct-access-global.shader @@ -0,0 +1,31 @@ +Shader "define-struct-access-global-test" { + SubShader "Default" { + Pass "Forward" { + mat4 renderer_MVPMat; + + struct Attributes { vec4 POSITION; vec2 TEXCOORD_0; }; + struct Varyings { vec2 v_uv; }; + + VertexShader = vert; + FragmentShader = frag; + + sampler2D u_texture; + + // Global #define referencing entry function parameter names + #define ATTR_POS attr.POSITION + #define VARYING_UV o.v_uv + #define FRAG_UV v.v_uv + + Varyings vert(Attributes attr) { + Varyings o; + gl_Position = renderer_MVPMat * ATTR_POS; + VARYING_UV = attr.TEXCOORD_0; + return o; + } + + void frag(Varyings v) { + gl_FragColor = texture2D(u_texture, FRAG_UV); + } + } + } +} diff --git a/tests/src/shader-lab/shaders/define-struct-access.shader b/tests/src/shader-lab/shaders/define-struct-access.shader new file mode 100644 index 0000000000..a28171dc40 --- /dev/null +++ b/tests/src/shader-lab/shaders/define-struct-access.shader @@ -0,0 +1,34 @@ +Shader "define-struct-access-test" { + SubShader "Default" { + Pass "Forward" { + mat4 renderer_MVPMat; + + struct Attributes { vec4 POSITION; vec2 TEXCOORD_0; }; + struct Varyings { vec2 v_uv; vec3 v_normal; }; + + VertexShader = vert; + FragmentShader = frag; + + sampler2D u_texture; + vec3 u_lightDir; + + Varyings vert(Attributes attr) { + Varyings o; + #define ATTR_POS attr.POSITION + #define VARYING_UV o.v_uv + #define VARYING_NORMAL o.v_normal + gl_Position = renderer_MVPMat * ATTR_POS; + VARYING_UV = attr.TEXCOORD_0; + VARYING_NORMAL = vec3(0.0, 1.0, 0.0); + return o; + } + + void frag(Varyings v) { + #define FRAG_UV v.v_uv + #define FRAG_NORMAL v.v_normal + float NdotL = dot(FRAG_NORMAL, u_lightDir); + gl_FragColor = texture2D(u_texture, FRAG_UV) * NdotL; + } + } + } +} diff --git a/tests/src/shader-lab/shaders/frag-return-vec4.shader b/tests/src/shader-lab/shaders/frag-return-vec4.shader new file mode 100644 index 0000000000..9b3ea3d4ca --- /dev/null +++ b/tests/src/shader-lab/shaders/frag-return-vec4.shader @@ -0,0 +1,41 @@ +Shader "frag-return-vec4-test" { + SubShader "Default" { + Pass "Forward" { + mat4 renderer_MVPMat; + + struct Attributes { vec3 POSITION; vec3 NORMAL; vec2 TEXCOORD_0; }; + struct Varyings { vec3 v_worldPos; vec4 v_normal; vec2 v_uv; }; + + VertexShader = vert; + FragmentShader = frag; + + sampler2D u_texture; + vec3 u_lightDir; + + vec3 SRGBToLinear(vec3 gamma) { return gamma * gamma; } + vec3 LinearToSRGB(vec3 linear) { return sqrt(linear); } + + vec4 SurfacesFragmentModifyBaseColorAndTransparency(Varyings input) { + vec4 color = texture2D(u_texture, input.v_uv); + color.rgb = SRGBToLinear(color.rgb); + return color; + } + + Varyings vert(Attributes attr) { + Varyings o; + vec4 pos = renderer_MVPMat * vec4(attr.POSITION, 1.0); + o.v_worldPos = pos.xyz; + o.v_normal = vec4(attr.NORMAL, 1.0); + o.v_uv = attr.TEXCOORD_0; + gl_Position = pos; + return o; + } + + vec4 frag(Varyings input) { + vec4 color = SurfacesFragmentModifyBaseColorAndTransparency(input); + color.rgb = LinearToSRGB(color.rgb); + return color; + } + } + } +} diff --git a/tests/src/shader-lab/shaders/generic-return-type.shader b/tests/src/shader-lab/shaders/generic-return-type.shader new file mode 100644 index 0000000000..72e96b7f3d --- /dev/null +++ b/tests/src/shader-lab/shaders/generic-return-type.shader @@ -0,0 +1,52 @@ +Shader "generic-return-type-test" { + SubShader "Default" { + Pass "Forward" { + mat4 renderer_MVPMat; + + struct Attributes { vec4 POSITION; }; + struct Varyings { vec2 uv; vec3 worldNormal; vec3 worldTangent; }; + + VertexShader = vert; + FragmentShader = frag; + + // Test: user-defined function with concrete parameter types + vec3 CalculateNormalFromTangentSpace(vec3 normalFromTangentSpace, float normalStrength, vec3 normal, vec3 tangent, float mirrorNormal) { + vec3 binormal = cross(normal, tangent) * mirrorNormal; + return (normalFromTangentSpace.x * normalStrength) * normalize(tangent) + + (normalFromTangentSpace.y * normalStrength) * normalize(binormal) + + normalFromTangentSpace.z * normalize(normal); + } + + sampler2D u_normalMap; + vec4 u_scaleAndStrength; + + Varyings vert(Attributes attr) { + Varyings o; + gl_Position = renderer_MVPMat * attr.POSITION; + o.uv = attr.POSITION.xy; + o.worldNormal = attr.POSITION.xyz; + o.worldTangent = attr.POSITION.xyz; + return o; + } + + void frag(Varyings v) { + vec3 normal = v.worldNormal; + + // Test: builtin generic functions (normalize) on swizzled values, + // passed as arguments to a user-defined function. + // normalize(vec3) should not produce EGenType.GenType (200) as return type, + // it should produce TypeAny so overload matching succeeds. + vec3 nmmp = texture(u_normalMap, v.uv).xyz - vec3(0.5); + normal = CalculateNormalFromTangentSpace( + nmmp, + u_scaleAndStrength.w, + normalize(normal.xyz), + normalize(v.worldTangent), + 1.0 + ); + + gl_FragColor = vec4(normalize(normal), 1.0); + } + } + } +} diff --git a/tests/src/shader-lab/shaders/global-varying-var.shader b/tests/src/shader-lab/shaders/global-varying-var.shader new file mode 100644 index 0000000000..bd6a5cf477 --- /dev/null +++ b/tests/src/shader-lab/shaders/global-varying-var.shader @@ -0,0 +1,42 @@ +Shader "global-varying-var-test" { + SubShader "Default" { + Pass "Forward" { + mat4 renderer_MVPMat; + + struct Attributes { vec3 POSITION; vec3 NORMAL; vec2 TEXCOORD_0; }; + struct Varyings { vec3 v_worldPos; vec4 v_normal; vec2 v_uv; vec4 v_shadowBiasAndProbeId; }; + + VertexShader = vert; + FragmentShader = frag; + + sampler2D u_texture; + vec3 u_lightDir; + + #define VSOutput_worldPos o.v_worldPos + #define VSOutput_worldNormal o.v_normal.xyz + #define VSOutput_faceSideSign o.v_normal.w + #define VSOutput_texcoord o.v_uv + #define VSOutput_shadowBias o.v_shadowBiasAndProbeId.xy + + Varyings o; + + Varyings vert(Attributes input) { + mat4 matWorld = renderer_MVPMat; + vec4 pos = matWorld * vec4(input.POSITION, 1.0); + VSOutput_worldPos = pos.xyz; + VSOutput_worldNormal = input.NORMAL; + VSOutput_faceSideSign = 1.0; + VSOutput_texcoord = input.TEXCOORD_0; + VSOutput_shadowBias = vec2(0.0, 0.0); + gl_Position = pos; + return o; + } + + void frag(Varyings v) { + vec3 N = normalize(v.v_normal.xyz); + float NdotL = dot(N, u_lightDir); + gl_FragColor = texture2D(u_texture, v.v_uv) * NdotL; + } + } + } +} diff --git a/tests/src/shader-lab/shaders/macro-member-access-builtin-arg.shader b/tests/src/shader-lab/shaders/macro-member-access-builtin-arg.shader new file mode 100644 index 0000000000..70ae36f3bc --- /dev/null +++ b/tests/src/shader-lab/shaders/macro-member-access-builtin-arg.shader @@ -0,0 +1,49 @@ +Shader "macro-member-access-builtin-arg-test" { + SubShader "Default" { + Pass "Forward" { + mat4 renderer_MVPMat; + + struct Attributes { vec4 POSITION; vec3 NORMAL; vec2 TEXCOORD_0; }; + struct Varyings { vec2 v_uv; vec4 v_normal; vec3 v_worldPos; }; + + VertexShader = vert; + FragmentShader = frag; + + sampler2D u_texture; + vec3 u_lightDir; + vec3 u_cameraPos; + + // Cocos-style FSInput macros: member access used as builtin function args + #define FSInput_worldNormal v.v_normal.xyz + #define FSInput_faceSideSign v.v_normal.w + #define FSInput_worldPos v.v_worldPos + #define FSInput_texcoord v.v_uv + + Varyings vert(Attributes attr) { + Varyings o; + gl_Position = renderer_MVPMat * attr.POSITION; + o.v_uv = attr.TEXCOORD_0; + o.v_normal = vec4(attr.NORMAL, 1.0); + o.v_worldPos = attr.POSITION.xyz; + return o; + } + + void frag(Varyings v) { + // normalize() with member access macro as arg + vec3 N = normalize(FSInput_worldNormal); + + // dot() with member access macro as arg + float NdotL = dot(N, u_lightDir); + + // texture2D() with member access macro as arg + vec4 albedo = texture2D(u_texture, FSInput_texcoord); + + // mix() with member access macro and scalar macro + vec3 viewDir = normalize(u_cameraPos - FSInput_worldPos); + float rim = 1.0 - dot(N, viewDir); + + gl_FragColor = albedo * NdotL + vec4(vec3(rim), 0.0); + } + } + } +} diff --git a/tests/src/shader-lab/shaders/macro-negate-number.shader b/tests/src/shader-lab/shaders/macro-negate-number.shader new file mode 100644 index 0000000000..a224605393 --- /dev/null +++ b/tests/src/shader-lab/shaders/macro-negate-number.shader @@ -0,0 +1,41 @@ +Shader "macro-negate-number-test" { + SubShader "default" { + Pass "default" { + struct a2v { + vec4 POSITION; + }; + + mat4 renderer_MVPMat; + + #define SCENE_FOG_MODE 1 + + VertexShader = vert; + FragmentShader = frag; + + void vert(a2v v) { + gl_Position = renderer_MVPMat * v.POSITION; + } + + void frag() { + vec4 color = vec4(1.0); + + // Test: !0 should evaluate to true (like C preprocessor) + #if SCENE_FOG_MODE != 4 && (!0 || SCENE_FOG_MODE) + color = vec4(0.0, 1.0, 0.0, 1.0); + #endif + + // Test: !1 should evaluate to false + #if !1 + color = vec4(1.0, 0.0, 0.0, 1.0); + #endif + + // Test: !0 alone + #if !0 + color = vec4(0.0, 0.0, 1.0, 1.0); + #endif + + gl_FragColor = color; + } + } + } +} diff --git a/tests/src/shader-lab/shaders/texture-generic.shader b/tests/src/shader-lab/shaders/texture-generic.shader new file mode 100644 index 0000000000..a27789175c --- /dev/null +++ b/tests/src/shader-lab/shaders/texture-generic.shader @@ -0,0 +1,94 @@ +Shader "texture-generic-test" { + SubShader "Default" { + Pass "Forward" { + mat4 renderer_MVPMat; + + struct Attributes { vec4 POSITION; }; + struct Varyings { vec2 uv; }; + + VertexShader = vert; + FragmentShader = frag; + + // Test: user-defined function taking vec4, called with texture() return value. + // texture(sampler2D, vec2) returns GVec4 which must resolve to vec4. + float decode32(vec4 rgba) { + rgba = rgba * 255.0; + float Sign = 1.0 - step(128.0, rgba[3] + 0.5) * 2.0; + float Exponent = 2.0 * mod(float(int(rgba[3] + 0.5)), 128.0) + step(128.0, rgba[2] + 0.5) - 127.0; + float Mantissa = mod(float(int(rgba[2] + 0.5)), 128.0) * 65536.0 + rgba[1] * 256.0 + rgba[0] + 8388608.0; + return Sign * exp2(Exponent - 23.0) * Mantissa; + } + + sampler2D u_texture; + + // Test: texture() result passed to user function (GVec4 → vec4 resolve) + mat4 getJointMatrix(float i) { + float x = 4.0 * i; + vec4 v1 = vec4( + decode32(texture(u_texture, vec2((x + 0.5) / 1024.0, 0.5))), + decode32(texture(u_texture, vec2((x + 1.5) / 1024.0, 0.5))), + decode32(texture(u_texture, vec2((x + 2.5) / 1024.0, 0.5))), + decode32(texture(u_texture, vec2((x + 3.5) / 1024.0, 0.5))) + ); + return mat4(v1, v1, v1, vec4(0.0, 0.0, 0.0, 1.0)); + } + + // Test: texture() result used directly in arithmetic (GVec4 → vec4) + vec4 sampleAndScale(sampler2D tex, vec2 coord, float scale) { + vec4 color = texture(tex, coord); + return color * scale; + } + + // Test: textureLod also returns GVec4 + vec4 sampleLod(sampler2D tex, vec2 coord, float lod) { + vec4 color = textureLod(tex, coord, lod); + return color; + } + + // Test: texture2DLod (ES 1.0 function, concrete types) + vec4 sampleLod2D(sampler2D tex, vec2 coord, float lod) { + return texture2DLod(tex, coord, lod); + } + + // Test: texture2DLod result passed to user function + float decodeLod2D(sampler2D tex, vec2 coord) { + return decode32(texture2DLod(tex, coord, 0.0)); + } + + // Test: texture() with samplerCube (GVec4 → vec4 resolve via GSamplerCube) + samplerCube u_cubeMap; + vec4 sampleCube(samplerCube tex, vec3 dir) { + return texture(tex, dir); + } + + // Test: textureLod with samplerCube (GVec4 → vec4 resolve via GSamplerCube) + vec4 sampleCubeLod(samplerCube tex, vec3 dir, float lod) { + return textureLod(tex, dir, lod); + } + + // Test: texture(samplerCube) result passed to user function (vec4 param matching) + float decodeCube(vec4 rgba) { + return rgba.r + rgba.g; + } + float sampleAndDecode(samplerCube tex, vec3 dir) { + return decodeCube(texture(tex, dir)); + } + + Varyings vert(Attributes attr) { + Varyings o; + gl_Position = renderer_MVPMat * attr.POSITION; + o.uv = attr.POSITION.xy; + return o; + } + + void frag(Varyings v) { + vec4 sampled = sampleAndScale(u_texture, v.uv, 1.0); + vec4 lodSampled = sampleLod(u_texture, v.uv, 0.0); + vec4 cubeSampled = sampleCube(u_cubeMap, vec3(v.uv, 1.0)); + vec4 cubeLodSampled = sampleCubeLod(u_cubeMap, vec3(v.uv, 1.0), 0.0); + float decoded = sampleAndDecode(u_cubeMap, vec3(v.uv, 1.0)); + gl_FragColor = sampled + lodSampled + cubeSampled + cubeLodSampled + vec4(decoded); + } + } + } +} diff --git a/tests/src/ui/UIEvent.test.ts b/tests/src/ui/UIEvent.test.ts index d2057a26cb..dc49457ba1 100644 --- a/tests/src/ui/UIEvent.test.ts +++ b/tests/src/ui/UIEvent.test.ts @@ -74,17 +74,20 @@ describe("UIEvent", async () => { // Add Image const imageEntity1 = canvasEntity.createChild("Image1"); - imageEntity1.addComponent(Image); + const image1 = imageEntity1.addComponent(Image); + image1.raycastEnabled = true; (imageEntity1.transform).size.set(300, 300); const script1 = imageEntity1.addComponent(TestScript); const imageEntity2 = imageEntity1.createChild("Image2"); - imageEntity2.addComponent(Image); + const image2 = imageEntity2.addComponent(Image); + image2.raycastEnabled = true; (imageEntity2.transform).size.set(200, 200); const script2 = imageEntity2.addComponent(TestScript); const imageEntity3 = imageEntity2.createChild("Image3"); const image3 = imageEntity3.addComponent(Image); + image3.raycastEnabled = true; (imageEntity3.transform).size.set(100, 100); const script3 = imageEntity3.addComponent(TestScript); @@ -93,6 +96,7 @@ describe("UIEvent", async () => { const { _pointerManager: pointerManager } = inputManager; const { _target: target } = pointerManager; const { left, top } = target.getBoundingClientRect(); + target.dispatchEvent(generatePointerEvent("pointerdown", 2, left + 2, top + 2)); engine.update(); diff --git a/tests/vitest.config.ts b/tests/vitest.config.ts index 91a68ffbca..e11fe737fa 100644 --- a/tests/vitest.config.ts +++ b/tests/vitest.config.ts @@ -1,9 +1,18 @@ +import glsl from "../rollup-plugin-glsl"; import { defineProject } from "vitest/config"; export default defineProject({ server: { port: 51204 }, + plugins: [ + glsl({ + include: [/\.(glsl|gs)$/] + }) + ], + resolve: { + mainFields: ["debug", "module", "main"] + }, optimizeDeps: { exclude: [ "@galacean/engine",