diff --git a/applications/asset_server/Dockerfile b/applications/asset_server/Dockerfile index 44f54352a..6bfd6b95c 100644 --- a/applications/asset_server/Dockerfile +++ b/applications/asset_server/Dockerfile @@ -5,56 +5,39 @@ FROM alpine:3.9 # ---------------------------------------------------------------------------------------------------------------- # Base OS libs. # ---------------------------------------------------------------------------------------------------------------- -RUN apk update && apk upgrade && apk --no-cache add bash bash-completion nodejs nodejs-npm curl gzip postgresql-dev \ - && apk add --update alpine-sdk wget coreutils +RUN apk update && apk upgrade && apk add --update --no-cache \ + bash bash-completion nodejs nodejs-npm curl gzip postgresql-dev alpine-sdk wget coreutils # ---------------------------------------------------------------------------------------------------------------- # __ __ -# |__) |__| |__) -# | | | | +# |__) |__| |__) Not currently needed ever? {php7-apcu} +# | | | | Not currently needed DB drivers/libs: {php7-sqlite3 php7-mysqli php7-pdo_dblib php7-pdo_odbc} # ---------------------------------------------------------------------------------------------------------------- -RUN apk --no-cache add php7 php7-fpm php7-mysqli php7-json php7-openssl php7-curl php7-zlib php7-xml \ - php7-phar php7-intl php7-dom php7-xmlreader php7-ctype php7-mbstring php7-gd php7-common php7-doc php7-ftp \ - php7-cgi php7-dev php7-iconv php7-zip php7-session php7-pdo php7-pgsql php7-pdo_pgsql php7-tokenizer +RUN apk add --no-cache \ + php7 php7-dev php7-fpm php7-json php7-openssl php7-curl php7-zlib php7-xml php7-phar php7-intl php7-dom \ + php7-xmlreader php7-xmlrpc php7-ctype php7-mbstring php7-gd php7-common php7-doc php7-ftp php7-cgi php7-iconv \ + php7-zip php7-session php7-pdo php7-pgsql php7-pdo_pgsql php7-opcache php7-mcrypt php7-soap php7-gmp \ + php7-tokenizer php7-gettext php7-bz2 RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer -# ---------------------------------------------------------------------------------------------------------------- -# __ -# / ` __|__ __|__ -# \__, | | -# ---------------------------------------------------------------------------------------------------------------- -#RUN apk add --no-cache libc-dev \ -# && apk add --no-cache libressl-dev \ -# && apk add --no-cache gcc \ -# && apk add --no-cache zlib-dev \ -# && apk add --no-cache jpeg-dev \ -# && apk add --no-cache boost-dev \ -# && apk add --no-cache musl-dev \ -# && apk add --no-cache cmake \ -# && apk add --no-cache libev-dev \ -# && apk add --no-cache linux-headers \ -# && apk add --no-cache libtool \ -# && apk add --no-cache libsodium-dev \ -# && apk add --no-cache utomake - -RUN rm /var/cache/apk/* - RUN echo $'[PHP] \n\ +zend.multibyte=On \n\ engine=On \n\ short_open_tag=Off \n\ +asp_tags=Off \n\ precision=14 \n\ -output_buffering=4096 \n\ +output_buffering=Off \n\ zlib.output_compression=Off \n\ implicit_flush=Off \n\ serialize_precision=-1 \n\ -realpath_cache_size=4096k \n\ +realpath_cache_size=4M \n\ realpath_cache_ttl=600 \n\ zend.enable_gc=On \n\ expose_php=Off \n\ -max_execution_time=30 \n\ +max_execution_time=600 \n\ max_input_time=60 \n\ -memory_limit=256M \n\ +memory_limit=512M \n\ error_reporting=E_ALL & ~E_DEPRECATED & ~E_STRICT \n\ display_errors=On \n\ display_startup_errors=On \n\ @@ -68,12 +51,12 @@ variables_order="S" \n\ request_order="GP" \n\ register_argc_argv=On \n\ auto_globals_jit=On \n\ -enable_post_data_reading=Off \n\ -post_max_size=8M \n\ +enable_post_data_reading=On \n\ +post_max_size=64M \n\ include_path = ".:/usr/share/php7" \n\ enable_dl = Off \n\ file_uploads=On \n\ -upload_max_filesize=2M \n\ +upload_max_filesize=100M \n\ max_file_uploads=20 \n\ allow_url_fopen=On \n\ allow_url_include=Off \n\ @@ -99,7 +82,7 @@ pgsql.allow_persistent=On \n\ pgsql.auto_reset_persistent=On \n\ pgsql.max_persistent=-1 \n\ pgsql.max_links=-1 \n\ -pgsql.ignore_notice=1 \n\ +pgsql.ignore_notice=0 \n\ pgsql.log_notice=1 \n\ [bcmath] \n\ bcmath.scale=0 \n\ @@ -112,13 +95,13 @@ session.name=PHPSESSID \n\ session.auto_start=-1\n\ session.serialize_handler = php \n\ session.gc_probability=1 \n\ -session.gc_divisor=1000 \n\ +session.gc_divisor=100 \n\ session.gc_maxlifetime=1440 \n\ -session.cache_limiter=nocache \n\ +session.cache_limiter=public \n\ session.cache_expire=180 \n\ session.use_trans_sid=0 \n\ [Assertion] \n\ -zend.assertions=-1 \n\ +zend.assertions=1 \n\ [Tidy] \n\ tidy.clean_output=Off \n\ [soap] \n\ @@ -131,15 +114,66 @@ ldap.max_links=-1 \n\ [opcache] \n\ opcache.enable=1 \n\ opcache.enable_cli=1 \n\ -opcache.file_cache_only=1 \n\ -opcache.file_cache=/tmp/php-opcache \n\ +opcache.optimization_level=15 \n\ +opcache.opt_debug_level=0x20000 \n\ +opcache.max_file_size=0 \n\ +opcache.huge_code_pages=1 \n\ +opcache.file_cache_consistency_checks=1 \n\ +opcache.validate_permission=0 \n\ +opcache.file_cache_only=0 \n\ +opcache.file_cache=/quasar_source/var/opcache \n\ opcache.validate_timestamps=1 \n\ +opcache.enable_file_override=1 \n\ opcache.revalidate_freq=0 \n\ -op.cache.revalidate_path=1 \n\ -opcache.max_accelerated_files=20000 \n\ -opcache.memory_consumption=192 \n\ -opcache.max_wasted_percentage=10 \n\ +opcache.revalidate_path=1 \n\ +opcache.max_accelerated_files=50000 \n\ +opcache.memory_consumption=64 \n\ +opcache.max_wasted_percentage=15 \n\ opcache.interned_strings_buffer=16 \n\ -opcache.fast_shutdown=1\n' > /etc/php7/php.ini +opcache.fast_shutdown=1 \n\ +' > /etc/php7/php.ini + +RUN wget https://get.symfony.com/cli/installer -O - | bash +RUN mv /root/.symfony/bin/symfony /usr/local/bin/symfony +ENV PATH="$HOME/.symfony/bin:$PATH" + +# ---------------------------------------------------------------------------------------------------------------- +# __ +# / ` __|__ __|__ +# \__, | | +# ---------------------------------------------------------------------------------------------------------------- +#RUN apk add --no-cache libc-dev \ +# && apk add --no-cache libressl-dev \ +# && apk add --no-cache gcc \ +# && apk add --no-cache zlib-dev \ +# && apk add --no-cache jpeg-dev \ +# && apk add --no-cache boost-dev \ +# && apk add --no-cache musl-dev \ +# && apk add --no-cache cmake \ +# && apk add --no-cache libev-dev \ +# && apk add --no-cache linux-headers \ +# && apk add --no-cache libtool \ +# && apk add --no-cache libsodium-dev \ +# && apk add --no-cache utomake + +RUN rm /var/cache/apk/* + +RUN apk add --no-cache shadow && adduser -S _www -u 1000 && groupadd _www + + +#https://stackoverflow.com/questions/49955097/how-do-i-add-a-user-when-im-using-alpine-as-a-base-image +#ENV USER=docker +#ENV UID=12345 +#ENV GID=23456 +#RUN addgroup --gid "$GID" "$USER" \ +# && adduser \ +# --disabled-password \ +# --gecos "" \ +# --home "$(pwd)" \ +# --ingroup "$USER" \ +# --no-create-home \ +# --uid "$UID" \ +# "$USER" + CMD ["bash", "/quasar_source/applications/asset_server/src/asset_server.sh"] diff --git a/applications/asset_server/code_manager/.env.dist b/applications/asset_server/code_manager/.env.dist deleted file mode 100644 index 494111bb6..000000000 --- a/applications/asset_server/code_manager/.env.dist +++ /dev/null @@ -1,3 +0,0 @@ -KERNEL_CLASS='CodeManager\Kernel' -APP_SECRET='s$cretf0rt3st' -SYMFONY_DEPRECATIONS_HELPER=999999 diff --git a/applications/asset_server/code_manager/.env.test b/applications/asset_server/code_manager/.env.test deleted file mode 100644 index 494111bb6..000000000 --- a/applications/asset_server/code_manager/.env.test +++ /dev/null @@ -1,3 +0,0 @@ -KERNEL_CLASS='CodeManager\Kernel' -APP_SECRET='s$cretf0rt3st' -SYMFONY_DEPRECATIONS_HELPER=999999 diff --git a/applications/asset_server/code_manager/.gitignore b/applications/asset_server/code_manager/.gitignore index 683670f64..5f00bbee3 100644 --- a/applications/asset_server/code_manager/.gitignore +++ b/applications/asset_server/code_manager/.gitignore @@ -11,3 +11,7 @@ .phpunit /phpunit.xml ###< symfony/phpunit-bridge ### + +###> symfony/web-server-bundle ### +/.web-server-pid +###< symfony/web-server-bundle ### diff --git a/applications/asset_server/code_manager/composer.json b/applications/asset_server/code_manager/composer.json index 397415e8d..f7623fe99 100644 --- a/applications/asset_server/code_manager/composer.json +++ b/applications/asset_server/code_manager/composer.json @@ -21,13 +21,17 @@ "symfony/orm-pack" : "^1.0", "symfony/phpunit-bridge" : "4.*", "symfony/process" : "4.*", - "symfony/yaml" : "4.*" + "symfony/yaml" : "4.*", + "symfony/web-server-bundle": "4.2.*" }, "config": { "preferred-install": { "*": "dist" }, - "sort-packages": false + "sort-packages": false, + "optimize-autoloader": true, + "classmap-authoritative": true, + "apcu-autoloader": false }, "autoload": { "psr-4": { @@ -37,9 +41,7 @@ }, "autoload-dev": { "psr-4": { - "CodeManager\\": "src/", - "CodeManager\\Tests\\": "tests/", - "QuasarSource\\": "./../../../libraries/php/" + "CodeManager\\Tests\\": "tests/" } }, "replace": { diff --git a/applications/asset_server/code_manager/config/bootstrap.php b/applications/asset_server/code_manager/config/bootstrap.php index 6ee0dca99..9ca46b060 100644 --- a/applications/asset_server/code_manager/config/bootstrap.php +++ b/applications/asset_server/code_manager/config/bootstrap.php @@ -1,21 +1,15 @@ =1.2) -if (is_array($env = @include dirname(__DIR__).'/.env.local.php')) { - $_ENV += $env; -} else if (!class_exists(Dotenv::class)) { - throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.'); -} else { - // load all the .env files - (new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env'); -} - +# ----------------------------------- {A U T O G E N E R A T E D C O D E}:{0x0} ------------------------------------ +$_ENV += [ + 'APP_ENV' => 'dev', + 'KERNEL_CLASS' => 'CodeManager\Kernel', + 'APP_SECRET' => 's$cretf0rt3st', + 'SYMFONY_DEPRECATIONS_HELPER' => '999999', + 'YES' => 'HELLO!', +]; +# --------------------------------------------------- {E N D}:{0x0} ---------------------------------------------------- $_SERVER += $_ENV; -$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; +$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; $_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV']; $_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0'; diff --git a/applications/asset_server/code_manager/config/bundles.php b/applications/asset_server/code_manager/config/bundles.php index 8754ce8dd..aea8d0b49 100644 --- a/applications/asset_server/code_manager/config/bundles.php +++ b/applications/asset_server/code_manager/config/bundles.php @@ -1,8 +1,9 @@ - ['all' => true], Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true], Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], + Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true], ]; diff --git a/applications/asset_server/code_manager/config/packages/dev/monolog.yaml b/applications/asset_server/code_manager/config/packages/dev/monolog.yaml index 71554587c..a8f20ee67 100644 --- a/applications/asset_server/code_manager/config/packages/dev/monolog.yaml +++ b/applications/asset_server/code_manager/config/packages/dev/monolog.yaml @@ -5,7 +5,19 @@ monolog: path: "%kernel.logs_dir%/%kernel.environment%.log" level: debug channels: ["!event"] + nested: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: debug console: type: console process_psr_3_messages: false - channels: ["!event", "!doctrine", "!console"] + channels: ["!event", "!doctrine", "!console"] #["!event", "!doctrine", "!console"] + deprecation: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.deprecations.log" + deprecation_filter: + type: filter + handler: deprecation + max_level: info + channels: ["php"] \ No newline at end of file diff --git a/applications/asset_server/code_manager/config/routes.yaml b/applications/asset_server/code_manager/config/routes.yaml index 0f2d8fec7..e69de29bb 100644 --- a/applications/asset_server/code_manager/config/routes.yaml +++ b/applications/asset_server/code_manager/config/routes.yaml @@ -1,8 +0,0 @@ -qa_test: - path: /qa_test - controller: CodeManager\Controller\QAController::test_response - -run_unit_tests: - path: /run_unit_tests - controller: CodeManager\Controller\QAController::run_unit_tests - diff --git a/applications/asset_server/code_manager/php/index.php b/applications/asset_server/code_manager/php/index.php new file mode 100644 index 000000000..139589835 --- /dev/null +++ b/applications/asset_server/code_manager/php/index.php @@ -0,0 +1,21 @@ +handle($request); +$response->send(); +$kernel->terminate($request, $response); diff --git a/applications/asset_server/code_manager/php/test.php b/applications/asset_server/code_manager/php/test.php new file mode 100644 index 000000000..fbb6c32cf --- /dev/null +++ b/applications/asset_server/code_manager/php/test.php @@ -0,0 +1,6 @@ +0?1:+t}),"name"in Function.prototype==!1&&Object.defineProperty(Function.prototype,"name",{get:function(){return this.toString().match(/^\s*function\s*([^\(\s]*)/)[1]}}),void 0===Object.assign&&(Object.assign=function(t){if(null==t)throw new TypeError("Cannot convert undefined or null to object");for(var e=Object(t),n=1;n>8&255]+t[e>>16&255]+t[e>>24&255]+"-"+t[255&n]+t[n>>8&255]+"-"+t[n>>16&15|64]+t[n>>24&255]+"-"+t[63&i|128]+t[i>>8&255]+"-"+t[i>>16&255]+t[i>>24&255]+t[255&r]+t[r>>8&255]+t[r>>16&255]+t[r>>24&255]).toUpperCase()}}(),clamp:function(t,e,n){return Math.max(e,Math.min(n,t))},euclideanModulo:function(t,e){return(t%e+e)%e},mapLinear:function(t,e,n,i,r){return i+(t-e)*(r-i)/(n-e)},lerp:function(t,e,n){return(1-n)*t+n*e},smoothstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*(3-2*t)},smootherstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*t*(t*(6*t-15)+10)},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},degToRad:function(t){return t*Ee.DEG2RAD},radToDeg:function(t){return t*Ee.RAD2DEG},isPowerOfTwo:function(t){return 0==(t&t-1)&&0!==t},ceilPowerOfTwo:function(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))},floorPowerOfTwo:function(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))}};function Te(t,e){this.x=t||0,this.y=e||0}function Ae(t,e,n,i){this._x=t||0,this._y=e||0,this._z=n||0,this._w=void 0!==i?i:1}function Le(t,e,n){this.x=t||0,this.y=e||0,this.z=n||0}function Pe(){this.elements=[1,0,0,0,1,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.")}Object.defineProperties(Te.prototype,{width:{get:function(){return this.x},set:function(t){this.x=t}},height:{get:function(){return this.y},set:function(t){this.y=t}}}),Object.assign(Te.prototype,{isVector2:!0,set:function(t,e){return this.x=t,this.y=e,this},setScalar:function(t){return this.x=t,this.y=t,this},setX:function(t){return this.x=t,this},setY:function(t){return this.y=t,this},setComponent:function(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this},getComponent:function(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}},clone:function(){return new this.constructor(this.x,this.y)},copy:function(t){return this.x=t.x,this.y=t.y,this},add:function(t,e){return void 0!==e?(console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this)},addScalar:function(t){return this.x+=t,this.y+=t,this},addVectors:function(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this},addScaledVector:function(t,e){return this.x+=t.x*e,this.y+=t.y*e,this},sub:function(t,e){return void 0!==e?(console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this)},subScalar:function(t){return this.x-=t,this.y-=t,this},subVectors:function(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this},multiply:function(t){return this.x*=t.x,this.y*=t.y,this},multiplyScalar:function(t){return this.x*=t,this.y*=t,this},divide:function(t){return this.x/=t.x,this.y/=t.y,this},divideScalar:function(t){return this.multiplyScalar(1/t)},applyMatrix3:function(t){var e=this.x,n=this.y,i=t.elements;return this.x=i[0]*e+i[3]*n+i[6],this.y=i[1]*e+i[4]*n+i[7],this},min:function(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this},max:function(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this},clamp:function(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this},clampScalar:function(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this},clampLength:function(t,e){var n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this},negate:function(){return this.x=-this.x,this.y=-this.y,this},dot:function(t){return this.x*t.x+this.y*t.y},cross:function(t){return this.x*t.y-this.y*t.x},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)},normalize:function(){return this.divideScalar(this.length()||1)},angle:function(){var t=Math.atan2(this.y,this.x);return t<0&&(t+=2*Math.PI),t},distanceTo:function(t){return Math.sqrt(this.distanceToSquared(t))},distanceToSquared:function(t){var e=this.x-t.x,n=this.y-t.y;return e*e+n*n},manhattanDistanceTo:function(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)},setLength:function(t){return this.normalize().multiplyScalar(t)},lerp:function(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this},lerpVectors:function(t,e,n){return this.subVectors(e,t).multiplyScalar(n).add(t)},equals:function(t){return t.x===this.x&&t.y===this.y},fromArray:function(t,e){return void 0===e&&(e=0),this.x=t[e],this.y=t[e+1],this},toArray:function(t,e){return void 0===t&&(t=[]),void 0===e&&(e=0),t[e]=this.x,t[e+1]=this.y,t},fromBufferAttribute:function(t,e,n){return void 0!==n&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute()."),this.x=t.getX(e),this.y=t.getY(e),this},rotateAround:function(t,e){var n=Math.cos(e),i=Math.sin(e),r=this.x-t.x,a=this.y-t.y;return this.x=r*n-a*i+t.x,this.y=r*i+a*n+t.y,this}}),Object.assign(Ae,{slerp:function(t,e,n,i){return n.copy(t).slerp(e,i)},slerpFlat:function(t,e,n,i,r,a,o){var s=n[i+0],c=n[i+1],h=n[i+2],l=n[i+3],u=r[a+0],p=r[a+1],d=r[a+2],f=r[a+3];if(l!==f||s!==u||c!==p||h!==d){var m=1-o,g=s*u+c*p+h*d+l*f,v=g>=0?1:-1,y=1-g*g;if(y>Number.EPSILON){var x=Math.sqrt(y),b=Math.atan2(x,g*v);m=Math.sin(m*b)/x,o=Math.sin(o*b)/x}var w=o*v;if(s=s*m+u*w,c=c*m+p*w,h=h*m+d*w,l=l*m+f*w,m===1-o){var _=1/Math.sqrt(s*s+c*c+h*h+l*l);s*=_,c*=_,h*=_,l*=_}}t[e]=s,t[e+1]=c,t[e+2]=h,t[e+3]=l}}),Object.defineProperties(Ae.prototype,{x:{get:function(){return this._x},set:function(t){this._x=t,this.onChangeCallback()}},y:{get:function(){return this._y},set:function(t){this._y=t,this.onChangeCallback()}},z:{get:function(){return this._z},set:function(t){this._z=t,this.onChangeCallback()}},w:{get:function(){return this._w},set:function(t){this._w=t,this.onChangeCallback()}}}),Object.assign(Ae.prototype,{isQuaternion:!0,set:function(t,e,n,i){return this._x=t,this._y=e,this._z=n,this._w=i,this.onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._w)},copy:function(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this.onChangeCallback(),this},setFromEuler:function(t,e){if(!t||!t.isEuler)throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");var n=t._x,i=t._y,r=t._z,a=t.order,o=Math.cos,s=Math.sin,c=o(n/2),h=o(i/2),l=o(r/2),u=s(n/2),p=s(i/2),d=s(r/2);return"XYZ"===a?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"YXZ"===a?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"ZXY"===a?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"ZYX"===a?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"YZX"===a?(this._x=u*h*l+c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l-u*p*d):"XZY"===a&&(this._x=u*h*l-c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l+u*p*d),!1!==e&&this.onChangeCallback(),this},setFromAxisAngle:function(t,e){var n=e/2,i=Math.sin(n);return this._x=t.x*i,this._y=t.y*i,this._z=t.z*i,this._w=Math.cos(n),this.onChangeCallback(),this},setFromRotationMatrix:function(t){var e,n=t.elements,i=n[0],r=n[4],a=n[8],o=n[1],s=n[5],c=n[9],h=n[2],l=n[6],u=n[10],p=i+s+u;return p>0?(e=.5/Math.sqrt(p+1),this._w=.25/e,this._x=(l-c)*e,this._y=(a-h)*e,this._z=(o-r)*e):i>s&&i>u?(e=2*Math.sqrt(1+i-s-u),this._w=(l-c)/e,this._x=.25*e,this._y=(r+o)/e,this._z=(a+h)/e):s>u?(e=2*Math.sqrt(1+s-i-u),this._w=(a-h)/e,this._x=(r+o)/e,this._y=.25*e,this._z=(c+l)/e):(e=2*Math.sqrt(1+u-i-s),this._w=(o-r)/e,this._x=(a+h)/e,this._y=(c+l)/e,this._z=.25*e),this.onChangeCallback(),this},setFromUnitVectors:function(t,e){var n=t.dot(e)+1;return n<1e-6?(n=0,Math.abs(t.x)>Math.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=n):(this._x=0,this._y=-t.z,this._z=t.y,this._w=n)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=n),this.normalize()},angleTo:function(t){return 2*Math.acos(Math.abs(Ee.clamp(this.dot(t),-1,1)))},rotateTowards:function(t,e){var n=this.angleTo(t);if(0===n)return this;var i=Math.min(1,e/n);return this.slerp(t,i),this},inverse:function(){return this.conjugate()},conjugate:function(){return this._x*=-1,this._y*=-1,this._z*=-1,this.onChangeCallback(),this},dot:function(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w},lengthSq:function(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w},length:function(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)},normalize:function(){var t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this.onChangeCallback(),this},multiply:function(t,e){return void 0!==e?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(t,e)):this.multiplyQuaternions(this,t)},premultiply:function(t){return this.multiplyQuaternions(t,this)},multiplyQuaternions:function(t,e){var n=t._x,i=t._y,r=t._z,a=t._w,o=e._x,s=e._y,c=e._z,h=e._w;return this._x=n*h+a*o+i*c-r*s,this._y=i*h+a*s+r*o-n*c,this._z=r*h+a*c+n*s-i*o,this._w=a*h-n*o-i*s-r*c,this.onChangeCallback(),this},slerp:function(t,e){if(0===e)return this;if(1===e)return this.copy(t);var n=this._x,i=this._y,r=this._z,a=this._w,o=a*t._w+n*t._x+i*t._y+r*t._z;if(o<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,o=-o):this.copy(t),o>=1)return this._w=a,this._x=n,this._y=i,this._z=r,this;var s=1-o*o;if(s<=Number.EPSILON){var c=1-e;return this._w=c*a+e*this._w,this._x=c*n+e*this._x,this._y=c*i+e*this._y,this._z=c*r+e*this._z,this.normalize()}var h=Math.sqrt(s),l=Math.atan2(h,o),u=Math.sin((1-e)*l)/h,p=Math.sin(e*l)/h;return this._w=a*u+this._w*p,this._x=n*u+this._x*p,this._y=i*u+this._y*p,this._z=r*u+this._z*p,this.onChangeCallback(),this},equals:function(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w},fromArray:function(t,e){return void 0===e&&(e=0),this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this.onChangeCallback(),this},toArray:function(t,e){return void 0===t&&(t=[]),void 0===e&&(e=0),t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t},onChange:function(t){return this.onChangeCallback=t,this},onChangeCallback:function(){}}),Object.assign(Le.prototype,{isVector3:!0,set:function(t,e,n){return this.x=t,this.y=e,this.z=n,this},setScalar:function(t){return this.x=t,this.y=t,this.z=t,this},setX:function(t){return this.x=t,this},setY:function(t){return this.y=t,this},setZ:function(t){return this.z=t,this},setComponent:function(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this},getComponent:function(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}},clone:function(){return new this.constructor(this.x,this.y,this.z)},copy:function(t){return this.x=t.x,this.y=t.y,this.z=t.z,this},add:function(t,e){return void 0!==e?(console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this.z+=t.z,this)},addScalar:function(t){return this.x+=t,this.y+=t,this.z+=t,this},addVectors:function(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this},addScaledVector:function(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this},sub:function(t,e){return void 0!==e?(console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this.z-=t.z,this)},subScalar:function(t){return this.x-=t,this.y-=t,this.z-=t,this},subVectors:function(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this},multiply:function(t,e){return void 0!==e?(console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(t,e)):(this.x*=t.x,this.y*=t.y,this.z*=t.z,this)},multiplyScalar:function(t){return this.x*=t,this.y*=t,this.z*=t,this},multiplyVectors:function(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this},applyEuler:(a=new Ae,function(t){return t&&t.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(a.setFromEuler(t))}),applyAxisAngle:function(){var t=new Ae;return function(e,n){return this.applyQuaternion(t.setFromAxisAngle(e,n))}}(),applyMatrix3:function(t){var e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[3]*n+r[6]*i,this.y=r[1]*e+r[4]*n+r[7]*i,this.z=r[2]*e+r[5]*n+r[8]*i,this},applyMatrix4:function(t){var e=this.x,n=this.y,i=this.z,r=t.elements,a=1/(r[3]*e+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*e+r[4]*n+r[8]*i+r[12])*a,this.y=(r[1]*e+r[5]*n+r[9]*i+r[13])*a,this.z=(r[2]*e+r[6]*n+r[10]*i+r[14])*a,this},applyQuaternion:function(t){var e=this.x,n=this.y,i=this.z,r=t.x,a=t.y,o=t.z,s=t.w,c=s*e+a*i-o*n,h=s*n+o*e-r*i,l=s*i+r*n-a*e,u=-r*e-a*n-o*i;return this.x=c*s+u*-r+h*-o-l*-a,this.y=h*s+u*-a+l*-r-c*-o,this.z=l*s+u*-o+c*-a-h*-r,this},project:function(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)},unproject:function(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)},transformDirection:function(t){var e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[4]*n+r[8]*i,this.y=r[1]*e+r[5]*n+r[9]*i,this.z=r[2]*e+r[6]*n+r[10]*i,this.normalize()},divide:function(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this},divideScalar:function(t){return this.multiplyScalar(1/t)},min:function(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this},max:function(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this},clamp:function(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this},clampScalar:function(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this.z=Math.max(t,Math.min(e,this.z)),this},clampLength:function(t,e){var n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this},dot:function(t){return this.x*t.x+this.y*t.y+this.z*t.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(t){return this.normalize().multiplyScalar(t)},lerp:function(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this},lerpVectors:function(t,e,n){return this.subVectors(e,t).multiplyScalar(n).add(t)},cross:function(t,e){return void 0!==e?(console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(t,e)):this.crossVectors(this,t)},crossVectors:function(t,e){var n=t.x,i=t.y,r=t.z,a=e.x,o=e.y,s=e.z;return this.x=i*s-r*o,this.y=r*a-n*s,this.z=n*o-i*a,this},projectOnVector:function(t){var e=t.dot(this)/t.lengthSq();return this.copy(t).multiplyScalar(e)},projectOnPlane:(r=new Le,function(t){return r.copy(this).projectOnVector(t),this.sub(r)}),reflect:function(){var t=new Le;return function(e){return this.sub(t.copy(e).multiplyScalar(2*this.dot(e)))}}(),angleTo:function(t){var e=this.dot(t)/Math.sqrt(this.lengthSq()*t.lengthSq());return Math.acos(Ee.clamp(e,-1,1))},distanceTo:function(t){return Math.sqrt(this.distanceToSquared(t))},distanceToSquared:function(t){var e=this.x-t.x,n=this.y-t.y,i=this.z-t.z;return e*e+n*n+i*i},manhattanDistanceTo:function(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)},setFromSpherical:function(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)},setFromSphericalCoords:function(t,e,n){var i=Math.sin(e)*t;return this.x=i*Math.sin(n),this.y=Math.cos(e)*t,this.z=i*Math.cos(n),this},setFromCylindrical:function(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)},setFromCylindricalCoords:function(t,e,n){return this.x=t*Math.sin(e),this.y=n,this.z=t*Math.cos(e),this},setFromMatrixPosition:function(t){var e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this},setFromMatrixScale:function(t){var e=this.setFromMatrixColumn(t,0).length(),n=this.setFromMatrixColumn(t,1).length(),i=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=n,this.z=i,this},setFromMatrixColumn:function(t,e){return this.fromArray(t.elements,4*e)},equals:function(t){return t.x===this.x&&t.y===this.y&&t.z===this.z},fromArray:function(t,e){return void 0===e&&(e=0),this.x=t[e],this.y=t[e+1],this.z=t[e+2],this},toArray:function(t,e){return void 0===t&&(t=[]),void 0===e&&(e=0),t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t},fromBufferAttribute:function(t,e,n){return void 0!==n&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute()."),this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}}),Object.assign(Pe.prototype,{isMatrix3:!0,set:function(t,e,n,i,r,a,o,s,c){var h=this.elements;return h[0]=t,h[1]=i,h[2]=o,h[3]=e,h[4]=r,h[5]=s,h[6]=n,h[7]=a,h[8]=c,this},identity:function(){return this.set(1,0,0,0,1,0,0,0,1),this},clone:function(){return(new this.constructor).fromArray(this.elements)},copy:function(t){var e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],this},setFromMatrix4:function(t){var e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this},applyToBufferAttribute:function(){var t=new Le;return function(e){for(var n=0,i=e.count;n2048||e.height>2048?e.toDataURL("image/jpeg",.6):e.toDataURL("image/png")}},We=0;function qe(t,e,n,i,r,a,o,s,c,h){Object.defineProperty(this,"id",{value:We++}),this.uuid=Ee.generateUUID(),this.name="",this.image=void 0!==t?t:qe.DEFAULT_IMAGE,this.mipmaps=[],this.mapping=void 0!==e?e:qe.DEFAULT_MAPPING,this.wrapS=void 0!==n?n:pt,this.wrapT=void 0!==i?i:pt,this.magFilter=void 0!==r?r:vt,this.minFilter=void 0!==a?a:xt,this.anisotropy=void 0!==c?c:1,this.format=void 0!==o?o:Dt,this.type=void 0!==s?s:bt,this.offset=new Te(0,0),this.repeat=new Te(1,1),this.center=new Te(0,0),this.rotation=0,this.matrixAutoUpdate=!0,this.matrix=new Pe,this.generateMipmaps=!0,this.premultiplyAlpha=!1,this.flipY=!0,this.unpackAlignment=4,this.encoding=void 0!==h?h:fe,this.version=0,this.onUpdate=null}function Xe(t,e,n,i){this.x=t||0,this.y=e||0,this.z=n||0,this.w=void 0!==i?i:1}function Ye(t,e,n){this.width=t,this.height=e,this.scissor=new Xe(0,0,t,e),this.scissorTest=!1,this.viewport=new Xe(0,0,t,e),n=n||{},this.texture=new qe(void 0,void 0,n.wrapS,n.wrapT,n.magFilter,n.minFilter,n.format,n.type,n.anisotropy,n.encoding),this.texture.generateMipmaps=void 0!==n.generateMipmaps&&n.generateMipmaps,this.texture.minFilter=void 0!==n.minFilter?n.minFilter:vt,this.depthBuffer=void 0===n.depthBuffer||n.depthBuffer,this.stencilBuffer=void 0===n.stencilBuffer||n.stencilBuffer,this.depthTexture=void 0!==n.depthTexture?n.depthTexture:null}function Je(t,e,n){Ye.call(this,t,e,n),this.samples=4}function Ze(t,e,n){Ye.call(this,t,e,n)}function Qe(t,e,n,i,r,a,o,s,c,h,l,u){qe.call(this,null,a,o,s,c,h,i,r,l,u),this.image={data:t,width:e,height:n},this.magFilter=void 0!==c?c:ft,this.minFilter=void 0!==h?h:ft,this.generateMipmaps=!1,this.flipY=!1,this.unpackAlignment=1}function Ke(t,e){this.min=void 0!==t?t:new Le(1/0,1/0,1/0),this.max=void 0!==e?e:new Le(-1/0,-1/0,-1/0)}function $e(t,e){this.center=void 0!==t?t:new Le,this.radius=void 0!==e?e:0}function tn(t,e){this.normal=void 0!==t?t:new Le(1,0,0),this.constant=void 0!==e?e:0}function en(t,e,n,i,r,a){this.planes=[void 0!==t?t:new tn,void 0!==e?e:new tn,void 0!==n?n:new tn,void 0!==i?i:new tn,void 0!==r?r:new tn,void 0!==a?a:new tn]}function nn(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.")}qe.DEFAULT_IMAGE=void 0,qe.DEFAULT_MAPPING=300,qe.prototype=Object.assign(Object.create(i.prototype),{constructor:qe,isTexture:!0,updateMatrix:function(){this.matrix.setUvTransform(this.offset.x,this.offset.y,this.repeat.x,this.repeat.y,this.rotation,this.center.x,this.center.y)},clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.name=t.name,this.image=t.image,this.mipmaps=t.mipmaps.slice(0),this.mapping=t.mapping,this.wrapS=t.wrapS,this.wrapT=t.wrapT,this.magFilter=t.magFilter,this.minFilter=t.minFilter,this.anisotropy=t.anisotropy,this.format=t.format,this.type=t.type,this.offset.copy(t.offset),this.repeat.copy(t.repeat),this.center.copy(t.center),this.rotation=t.rotation,this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrix.copy(t.matrix),this.generateMipmaps=t.generateMipmaps,this.premultiplyAlpha=t.premultiplyAlpha,this.flipY=t.flipY,this.unpackAlignment=t.unpackAlignment,this.encoding=t.encoding,this},toJSON:function(t){var e=void 0===t||"string"==typeof t;if(!e&&void 0!==t.textures[this.uuid])return t.textures[this.uuid];var n={metadata:{version:4.5,type:"Texture",generator:"Texture.toJSON"},uuid:this.uuid,name:this.name,mapping:this.mapping,repeat:[this.repeat.x,this.repeat.y],offset:[this.offset.x,this.offset.y],center:[this.center.x,this.center.y],rotation:this.rotation,wrap:[this.wrapS,this.wrapT],format:this.format,type:this.type,encoding:this.encoding,minFilter:this.minFilter,magFilter:this.magFilter,anisotropy:this.anisotropy,flipY:this.flipY,premultiplyAlpha:this.premultiplyAlpha,unpackAlignment:this.unpackAlignment};if(void 0!==this.image){var i=this.image;if(void 0===i.uuid&&(i.uuid=Ee.generateUUID()),!e&&void 0===t.images[i.uuid]){var r;if(Array.isArray(i)){r=[];for(var a=0,o=i.length;a1)switch(this.wrapS){case ut:t.x=t.x-Math.floor(t.x);break;case pt:t.x=t.x<0?0:1;break;case dt:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y<0||t.y>1)switch(this.wrapT){case ut:t.y=t.y-Math.floor(t.y);break;case pt:t.y=t.y<0?0:1;break;case dt:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&&(t.y=1-t.y),t}}),Object.defineProperty(qe.prototype,"needsUpdate",{set:function(t){!0===t&&this.version++}}),Object.assign(Xe.prototype,{isVector4:!0,set:function(t,e,n,i){return this.x=t,this.y=e,this.z=n,this.w=i,this},setScalar:function(t){return this.x=t,this.y=t,this.z=t,this.w=t,this},setX:function(t){return this.x=t,this},setY:function(t){return this.y=t,this},setZ:function(t){return this.z=t,this},setW:function(t){return this.w=t,this},setComponent:function(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this},getComponent:function(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}},clone:function(){return new this.constructor(this.x,this.y,this.z,this.w)},copy:function(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this},add:function(t,e){return void 0!==e?(console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this)},addScalar:function(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this},addVectors:function(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this},addScaledVector:function(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this},sub:function(t,e){return void 0!==e?(console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this)},subScalar:function(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this},subVectors:function(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this},multiplyScalar:function(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this},applyMatrix4:function(t){var e=this.x,n=this.y,i=this.z,r=this.w,a=t.elements;return this.x=a[0]*e+a[4]*n+a[8]*i+a[12]*r,this.y=a[1]*e+a[5]*n+a[9]*i+a[13]*r,this.z=a[2]*e+a[6]*n+a[10]*i+a[14]*r,this.w=a[3]*e+a[7]*n+a[11]*i+a[15]*r,this},divideScalar:function(t){return this.multiplyScalar(1/t)},setAxisAngleFromQuaternion:function(t){this.w=2*Math.acos(t.w);var e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this},setAxisAngleFromRotationMatrix:function(t){var e,n,i,r,a=t.elements,o=a[0],s=a[4],c=a[8],h=a[1],l=a[5],u=a[9],p=a[2],d=a[6],f=a[10];if(Math.abs(s-h)<.01&&Math.abs(c-p)<.01&&Math.abs(u-d)<.01){if(Math.abs(s+h)<.1&&Math.abs(c+p)<.1&&Math.abs(u+d)<.1&&Math.abs(o+l+f-3)<.1)return this.set(1,0,0,0),this;e=Math.PI;var m=(o+1)/2,g=(l+1)/2,v=(f+1)/2,y=(s+h)/4,x=(c+p)/4,b=(u+d)/4;return m>g&&m>v?m<.01?(n=0,i=.707106781,r=.707106781):(i=y/(n=Math.sqrt(m)),r=x/n):g>v?g<.01?(n=.707106781,i=0,r=.707106781):(n=y/(i=Math.sqrt(g)),r=b/i):v<.01?(n=.707106781,i=.707106781,r=0):(n=x/(r=Math.sqrt(v)),i=b/r),this.set(n,i,r,e),this}var w=Math.sqrt((d-u)*(d-u)+(c-p)*(c-p)+(h-s)*(h-s));return Math.abs(w)<.001&&(w=1),this.x=(d-u)/w,this.y=(c-p)/w,this.z=(h-s)/w,this.w=Math.acos((o+l+f-1)/2),this},min:function(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this.w=Math.min(this.w,t.w),this},max:function(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this.w=Math.max(this.w,t.w),this},clamp:function(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this.w=Math.max(t.w,Math.min(e.w,this.w)),this},clampScalar:function(t,e){return void 0===Re&&(Re=new Xe,Ce=new Xe),Re.set(t,t,t,t),Ce.set(e,e,e,e),this.clamp(Re,Ce)},clampLength:function(t,e){var n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this.w=Math.floor(this.w),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this.w=Math.ceil(this.w),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this.w=Math.round(this.w),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this.w=this.w<0?Math.ceil(this.w):Math.floor(this.w),this},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this.w=-this.w,this},dot:function(t){return this.x*t.x+this.y*t.y+this.z*t.z+this.w*t.w},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(t){return this.normalize().multiplyScalar(t)},lerp:function(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this.w+=(t.w-this.w)*e,this},lerpVectors:function(t,e,n){return this.subVectors(e,t).multiplyScalar(n).add(t)},equals:function(t){return t.x===this.x&&t.y===this.y&&t.z===this.z&&t.w===this.w},fromArray:function(t,e){return void 0===e&&(e=0),this.x=t[e],this.y=t[e+1],this.z=t[e+2],this.w=t[e+3],this},toArray:function(t,e){return void 0===t&&(t=[]),void 0===e&&(e=0),t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t[e+3]=this.w,t},fromBufferAttribute:function(t,e,n){return void 0!==n&&console.warn("THREE.Vector4: offset has been removed from .fromBufferAttribute()."),this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this.w=t.getW(e),this}}),Ye.prototype=Object.assign(Object.create(i.prototype),{constructor:Ye,isWebGLRenderTarget:!0,setSize:function(t,e){this.width===t&&this.height===e||(this.width=t,this.height=e,this.dispose()),this.viewport.set(0,0,t,e),this.scissor.set(0,0,t,e)},clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.width=t.width,this.height=t.height,this.viewport.copy(t.viewport),this.texture=t.texture.clone(),this.depthBuffer=t.depthBuffer,this.stencilBuffer=t.stencilBuffer,this.depthTexture=t.depthTexture,this},dispose:function(){this.dispatchEvent({type:"dispose"})}}),Je.prototype=Object.assign(Object.create(Ye.prototype),{constructor:Je,isWebGLMultisampleRenderTarget:!0,copy:function(t){return Ye.prototype.copy.call(this,t),this.samples=t.samples,this}}),Ze.prototype=Object.create(Ye.prototype),Ze.prototype.constructor=Ze,Ze.prototype.isWebGLRenderTargetCube=!0,Qe.prototype=Object.create(qe.prototype),Qe.prototype.constructor=Qe,Qe.prototype.isDataTexture=!0,Object.assign(Ke.prototype,{isBox3:!0,set:function(t,e){return this.min.copy(t),this.max.copy(e),this},setFromArray:function(t){for(var e=1/0,n=1/0,i=1/0,r=-1/0,a=-1/0,o=-1/0,s=0,c=t.length;sr&&(r=h),l>a&&(a=l),u>o&&(o=u)}return this.min.set(e,n,i),this.max.set(r,a,o),this},setFromBufferAttribute:function(t){for(var e=1/0,n=1/0,i=1/0,r=-1/0,a=-1/0,o=-1/0,s=0,c=t.count;sr&&(r=h),l>a&&(a=l),u>o&&(o=u)}return this.min.set(e,n,i),this.max.set(r,a,o),this},setFromPoints:function(t){this.makeEmpty();for(var e=0,n=t.length;ethis.max.x||t.ythis.max.y||t.zthis.max.z)},containsBox:function(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z},getParameter:function(t,e){return void 0===e&&(console.warn("THREE.Box3: .getParameter() target is now required"),e=new Le),e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))},intersectsBox:function(t){return!(t.max.xthis.max.x||t.max.ythis.max.y||t.max.zthis.max.z)},intersectsSphere:(Ie=new Le,function(t){return this.clampPoint(t.center,Ie),Ie.distanceToSquared(t.center)<=t.radius*t.radius}),intersectsPlane:function(t){var e,n;return t.normal.x>0?(e=t.normal.x*this.min.x,n=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,n=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,n+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,n+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,n+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,n+=t.normal.z*this.min.z),e<=-t.constant&&n>=-t.constant},intersectsTriangle:function(){var t=new Le,e=new Le,n=new Le,i=new Le,r=new Le,a=new Le,o=new Le,s=new Le,c=new Le,h=new Le;function l(i){var r,a;for(r=0,a=i.length-3;r<=a;r+=3){o.fromArray(i,r);var s=c.x*Math.abs(o.x)+c.y*Math.abs(o.y)+c.z*Math.abs(o.z),h=t.dot(o),l=e.dot(o),u=n.dot(o);if(Math.max(-Math.max(h,l,u),Math.min(h,l,u))>s)return!1}return!0}return function(o){if(this.isEmpty())return!1;this.getCenter(s),c.subVectors(this.max,s),t.subVectors(o.a,s),e.subVectors(o.b,s),n.subVectors(o.c,s),i.subVectors(e,t),r.subVectors(n,e),a.subVectors(t,n);var u=[0,-i.z,i.y,0,-r.z,r.y,0,-a.z,a.y,i.z,0,-i.x,r.z,0,-r.x,a.z,0,-a.x,-i.y,i.x,0,-r.y,r.x,0,-a.y,a.x,0];return!!l(u)&&(!!l(u=[1,0,0,0,1,0,0,0,1])&&(h.crossVectors(i,r),l(u=[h.x,h.y,h.z])))}}(),clampPoint:function(t,e){return void 0===e&&(console.warn("THREE.Box3: .clampPoint() target is now required"),e=new Le),e.copy(t).clamp(this.min,this.max)},distanceToPoint:function(){var t=new Le;return function(e){return t.copy(e).clamp(this.min,this.max).sub(e).length()}}(),getBoundingSphere:function(){var t=new Le;return function(e){return void 0===e&&console.error("THREE.Box3: .getBoundingSphere() target is now required"),this.getCenter(e.center),e.radius=.5*this.getSize(t).length(),e}}(),intersect:function(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this},union:function(t){return this.min.min(t.min),this.max.max(t.max),this},applyMatrix4:(Oe=[new Le,new Le,new Le,new Le,new Le,new Le,new Le,new Le],function(t){return this.isEmpty()?this:(Oe[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),Oe[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),Oe[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),Oe[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),Oe[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),Oe[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),Oe[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),Oe[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(Oe),this)}),translate:function(t){return this.min.add(t),this.max.add(t),this},equals:function(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}),Object.assign($e.prototype,{set:function(t,e){return this.center.copy(t),this.radius=e,this},setFromPoints:(De=new Ke,function(t,e){var n=this.center;void 0!==e?n.copy(e):De.setFromPoints(t).getCenter(n);for(var i=0,r=0,a=t.length;rthis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e},getBoundingBox:function(t){return void 0===t&&(console.warn("THREE.Sphere: .getBoundingBox() target is now required"),t=new Ke),t.set(this.center,this.center),t.expandByScalar(this.radius),t},applyMatrix4:function(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this},translate:function(t){return this.center.add(t),this},equals:function(t){return t.center.equals(this.center)&&t.radius===this.radius}}),Object.assign(tn.prototype,{set:function(t,e){return this.normal.copy(t),this.constant=e,this},setComponents:function(t,e,n,i){return this.normal.set(t,e,n),this.constant=i,this},setFromNormalAndCoplanarPoint:function(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this},setFromCoplanarPoints:function(){var t=new Le,e=new Le;return function(n,i,r){var a=t.subVectors(r,i).cross(e.subVectors(n,i)).normalize();return this.setFromNormalAndCoplanarPoint(a,n),this}}(),clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.normal.copy(t.normal),this.constant=t.constant,this},normalize:function(){var t=1/this.normal.length();return this.normal.multiplyScalar(t),this.constant*=t,this},negate:function(){return this.constant*=-1,this.normal.negate(),this},distanceToPoint:function(t){return this.normal.dot(t)+this.constant},distanceToSphere:function(t){return this.distanceToPoint(t.center)-t.radius},projectPoint:function(t,e){return void 0===e&&(console.warn("THREE.Plane: .projectPoint() target is now required"),e=new Le),e.copy(this.normal).multiplyScalar(-this.distanceToPoint(t)).add(t)},intersectLine:function(){var t=new Le;return function(e,n){void 0===n&&(console.warn("THREE.Plane: .intersectLine() target is now required"),n=new Le);var i=e.delta(t),r=this.normal.dot(i);if(0===r)return 0===this.distanceToPoint(e.start)?n.copy(e.start):void 0;var a=-(e.start.dot(this.normal)+this.constant)/r;return a<0||a>1?void 0:n.copy(i).multiplyScalar(a).add(e.start)}}(),intersectsLine:function(t){var e=this.distanceToPoint(t.start),n=this.distanceToPoint(t.end);return e<0&&n>0||n<0&&e>0},intersectsBox:function(t){return t.intersectsPlane(this)},intersectsSphere:function(t){return t.intersectsPlane(this)},coplanarPoint:function(t){return void 0===t&&(console.warn("THREE.Plane: .coplanarPoint() target is now required"),t=new Le),t.copy(this.normal).multiplyScalar(-this.constant)},applyMatrix4:function(){var t=new Le,e=new Pe;return function(n,i){var r=i||e.getNormalMatrix(n),a=this.coplanarPoint(t).applyMatrix4(n),o=this.normal.applyMatrix3(r).normalize();return this.constant=-a.dot(o),this}}(),translate:function(t){return this.constant-=t.dot(this.normal),this},equals:function(t){return t.normal.equals(this.normal)&&t.constant===this.constant}}),Object.assign(en.prototype,{set:function(t,e,n,i,r,a){var o=this.planes;return o[0].copy(t),o[1].copy(e),o[2].copy(n),o[3].copy(i),o[4].copy(r),o[5].copy(a),this},clone:function(){return(new this.constructor).copy(this)},copy:function(t){for(var e=this.planes,n=0;n<6;n++)e[n].copy(t.planes[n]);return this},setFromMatrix:function(t){var e=this.planes,n=t.elements,i=n[0],r=n[1],a=n[2],o=n[3],s=n[4],c=n[5],h=n[6],l=n[7],u=n[8],p=n[9],d=n[10],f=n[11],m=n[12],g=n[13],v=n[14],y=n[15];return e[0].setComponents(o-i,l-s,f-u,y-m).normalize(),e[1].setComponents(o+i,l+s,f+u,y+m).normalize(),e[2].setComponents(o+r,l+c,f+p,y+g).normalize(),e[3].setComponents(o-r,l-c,f-p,y-g).normalize(),e[4].setComponents(o-a,l-h,f-d,y-v).normalize(),e[5].setComponents(o+a,l+h,f+d,y+v).normalize(),this},intersectsObject:(ze=new $e,function(t){var e=t.geometry;return null===e.boundingSphere&&e.computeBoundingSphere(),ze.copy(e.boundingSphere).applyMatrix4(t.matrixWorld),this.intersectsSphere(ze)}),intersectsSprite:function(){var t=new $e;return function(e){return t.center.set(0,0,0),t.radius=.7071067811865476,t.applyMatrix4(e.matrixWorld),this.intersectsSphere(t)}}(),intersectsSphere:function(t){for(var e=this.planes,n=t.center,i=-t.radius,r=0;r<6;r++){if(e[r].distanceToPoint(n)0?t.max.x:t.min.x,Ne.y=i.normal.y>0?t.max.y:t.min.y,Ne.z=i.normal.z>0?t.max.z:t.min.z,i.distanceToPoint(Ne)<0)return!1}return!0}),containsPoint:function(t){for(var e=this.planes,n=0;n<6;n++)if(e[n].distanceToPoint(t)<0)return!1;return!0}}),Object.assign(nn.prototype,{isMatrix4:!0,set:function(t,e,n,i,r,a,o,s,c,h,l,u,p,d,f,m){var g=this.elements;return g[0]=t,g[4]=e,g[8]=n,g[12]=i,g[1]=r,g[5]=a,g[9]=o,g[13]=s,g[2]=c,g[6]=h,g[10]=l,g[14]=u,g[3]=p,g[7]=d,g[11]=f,g[15]=m,this},identity:function(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this},clone:function(){return(new nn).fromArray(this.elements)},copy:function(t){var e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],e[9]=n[9],e[10]=n[10],e[11]=n[11],e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15],this},copyPosition:function(t){var e=this.elements,n=t.elements;return e[12]=n[12],e[13]=n[13],e[14]=n[14],this},extractBasis:function(t,e,n){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this},makeBasis:function(t,e,n){return this.set(t.x,e.x,n.x,0,t.y,e.y,n.y,0,t.z,e.z,n.z,0,0,0,0,1),this},extractRotation:function(){var t=new Le;return function(e){var n=this.elements,i=e.elements,r=1/t.setFromMatrixColumn(e,0).length(),a=1/t.setFromMatrixColumn(e,1).length(),o=1/t.setFromMatrixColumn(e,2).length();return n[0]=i[0]*r,n[1]=i[1]*r,n[2]=i[2]*r,n[3]=0,n[4]=i[4]*a,n[5]=i[5]*a,n[6]=i[6]*a,n[7]=0,n[8]=i[8]*o,n[9]=i[9]*o,n[10]=i[10]*o,n[11]=0,n[12]=0,n[13]=0,n[14]=0,n[15]=1,this}}(),makeRotationFromEuler:function(t){t&&t.isEuler||console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");var e=this.elements,n=t.x,i=t.y,r=t.z,a=Math.cos(n),o=Math.sin(n),s=Math.cos(i),c=Math.sin(i),h=Math.cos(r),l=Math.sin(r);if("XYZ"===t.order){var u=a*h,p=a*l,d=o*h,f=o*l;e[0]=s*h,e[4]=-s*l,e[8]=c,e[1]=p+d*c,e[5]=u-f*c,e[9]=-o*s,e[2]=f-u*c,e[6]=d+p*c,e[10]=a*s}else if("YXZ"===t.order){var m=s*h,g=s*l,v=c*h,y=c*l;e[0]=m+y*o,e[4]=v*o-g,e[8]=a*c,e[1]=a*l,e[5]=a*h,e[9]=-o,e[2]=g*o-v,e[6]=y+m*o,e[10]=a*s}else if("ZXY"===t.order){m=s*h,g=s*l,v=c*h,y=c*l;e[0]=m-y*o,e[4]=-a*l,e[8]=v+g*o,e[1]=g+v*o,e[5]=a*h,e[9]=y-m*o,e[2]=-a*c,e[6]=o,e[10]=a*s}else if("ZYX"===t.order){u=a*h,p=a*l,d=o*h,f=o*l;e[0]=s*h,e[4]=d*c-p,e[8]=u*c+f,e[1]=s*l,e[5]=f*c+u,e[9]=p*c-d,e[2]=-c,e[6]=o*s,e[10]=a*s}else if("YZX"===t.order){var x=a*s,b=a*c,w=o*s,_=o*c;e[0]=s*h,e[4]=_-x*l,e[8]=w*l+b,e[1]=l,e[5]=a*h,e[9]=-o*h,e[2]=-c*h,e[6]=b*l+w,e[10]=x-_*l}else if("XZY"===t.order){x=a*s,b=a*c,w=o*s,_=o*c;e[0]=s*h,e[4]=-l,e[8]=c*h,e[1]=x*l+_,e[5]=a*h,e[9]=b*l-w,e[2]=w*l-b,e[6]=o*h,e[10]=_*l+x}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this},makeRotationFromQuaternion:(ke=new Le(0,0,0),Ve=new Le(1,1,1),function(t){return this.compose(ke,t,Ve)}),lookAt:(Ge=new Le,Fe=new Le,He=new Le,function(t,e,n){var i=this.elements;return He.subVectors(t,e),0===He.lengthSq()&&(He.z=1),He.normalize(),Ge.crossVectors(n,He),0===Ge.lengthSq()&&(1===Math.abs(n.z)?He.x+=1e-4:He.z+=1e-4,He.normalize(),Ge.crossVectors(n,He)),Ge.normalize(),Fe.crossVectors(He,Ge),i[0]=Ge.x,i[4]=Fe.x,i[8]=He.x,i[1]=Ge.y,i[5]=Fe.y,i[9]=He.y,i[2]=Ge.z,i[6]=Fe.z,i[10]=He.z,this}),multiply:function(t,e){return void 0!==e?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(t,e)):this.multiplyMatrices(this,t)},premultiply:function(t){return this.multiplyMatrices(t,this)},multiplyMatrices:function(t,e){var n=t.elements,i=e.elements,r=this.elements,a=n[0],o=n[4],s=n[8],c=n[12],h=n[1],l=n[5],u=n[9],p=n[13],d=n[2],f=n[6],m=n[10],g=n[14],v=n[3],y=n[7],x=n[11],b=n[15],w=i[0],_=i[4],M=i[8],S=i[12],E=i[1],T=i[5],A=i[9],L=i[13],P=i[2],R=i[6],C=i[10],O=i[14],I=i[3],D=i[7],N=i[11],z=i[15];return r[0]=a*w+o*E+s*P+c*I,r[4]=a*_+o*T+s*R+c*D,r[8]=a*M+o*A+s*C+c*N,r[12]=a*S+o*L+s*O+c*z,r[1]=h*w+l*E+u*P+p*I,r[5]=h*_+l*T+u*R+p*D,r[9]=h*M+l*A+u*C+p*N,r[13]=h*S+l*L+u*O+p*z,r[2]=d*w+f*E+m*P+g*I,r[6]=d*_+f*T+m*R+g*D,r[10]=d*M+f*A+m*C+g*N,r[14]=d*S+f*L+m*O+g*z,r[3]=v*w+y*E+x*P+b*I,r[7]=v*_+y*T+x*R+b*D,r[11]=v*M+y*A+x*C+b*N,r[15]=v*S+y*L+x*O+b*z,this},multiplyScalar:function(t){var e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this},applyToBufferAttribute:function(){var t=new Le;return function(e){for(var n=0,i=e.count;n 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n#else\n\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t}\n\treturn 1.0;\n#endif\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\treturn specularColor * brdf.x + brdf.y;\n}\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tvec3 F = F_Schlick( specularColor, dotNV );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\tvec3 FssEss = F * brdf.x + brdf.y;\n\tfloat Ess = brdf.x + brdf.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG ) && ! defined( MATCAP )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG ) && ! defined( MATCAP )\n\tvarying vec3 vViewPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG ) && ! defined( MATCAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif",color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif",common:"#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV( sampler2D envMap, vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = normalMatrix * objectTangent;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",encodings_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",encodings_pars_fragment:"\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * value.a * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = cLogLuvM * value.rgb;\n\tXp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) );\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract( Le );\n\tvResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 );\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;\n\treturn vec4( max( vRGB, 0.0 ), 1.0 );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_pars_fragment:"#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent ));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tfogDepth = -mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float fogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif",lights_pars_begin:"uniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in GeometricContext geometry ) {\n\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef ENVMAP_TYPE_CUBE_UV\n\t\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#endif\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\tfloat clearCoatInv = 1.0 - clearCoatDHR;\n\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec3 singleScattering = vec3( 0.0 );\n\t\tvec3 multiScattering = vec3( 0.0 );\n\t\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\n\t\tvec3 diffuse = material.diffuseColor;\n\t\treflectedLight.indirectSpecular += clearCoatInv * radiance * singleScattering;\n\t\treflectedLight.indirectDiffuse += multiScattering * cosineWeightedIrradiance;\n\t\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n\t#else\n\t\treflectedLight.indirectSpecular += clearCoatInv * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#endif\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearCoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), maxMipLevel );\n\t#ifndef STANDARD\n\t\tclearCoatRadiance += getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), maxMipLevel );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, irradiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif",map_particle_pars_fragment:"#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif",normal_fragment_begin:"#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\tbitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t#endif\n\t#endif\n#endif",normal_fragment_maps:"#ifdef USE_NORMALMAP\n\t#ifdef OBJECTSPACE_NORMALMAP\n\t\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\t#ifdef FLIP_SIDED\n\t\t\tnormal = - normal;\n\t\t#endif\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t#endif\n\t\tnormal = normalize( normalMatrix * normal );\n\t#else\n\t\t#ifdef USE_TANGENT\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\t\tmapN.xy = normalScale * mapN.xy;\n\t\t\tnormal = normalize( vTBN * mapN );\n\t\t#else\n\t\t\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n\t\t#endif\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\t#ifdef OBJECTSPACE_NORMALMAP\n\t\tuniform mat3 normalMatrix;\n\t#else\n\t\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\t\tvec2 st0 = dFdx( vUv.st );\n\t\t\tvec2 st1 = dFdy( vUv.st );\n\t\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\n\t\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\t\tvec3 N = normalize( surf_norm );\n\t\t\tmat3 tsn = mat3( S, T, N );\n\t\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\t\tmapN.xy *= normalScale;\n\t\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\treturn normalize( tsn * mapN );\n\t\t}\n\t#endif\n#endif",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#if defined( DITHERING )\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( ( color * ( 2.51 * color + 0.03 ) ) / ( color * ( 2.43 * color + 0.59 ) + 0.14 ) );\n}",uv_pars_fragment:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif",uv_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif",background_frag:"uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\t#else\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t\tmatcapColor = matcapTexelToLinear( matcapColor );\n\t#else\n\t\tvec4 matcapColor = vec4( 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifndef FLAT_SHADED\n\t\tvNormal = normalize( transformedNormal );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_frag:"#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}",normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}",shadow_vert:"#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}"};function an(t){var e={};for(var n in t)for(var i in e[n]={},t[n]){var r=t[n][i];r&&(r.isColor||r.isMatrix3||r.isMatrix4||r.isVector2||r.isVector3||r.isVector4||r.isTexture)?e[n][i]=r.clone():Array.isArray(r)?e[n][i]=r.slice():e[n][i]=r}return e}function on(t){for(var e={},n=0;n>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,this},setRGB:function(t,e,n){return this.r=t,this.g=e,this.b=n,this},setHSL:function(){function t(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+6*(e-t)*(2/3-n):t}return function(e,n,i){if(e=Ee.euclideanModulo(e,1),n=Ee.clamp(n,0,1),i=Ee.clamp(i,0,1),0===n)this.r=this.g=this.b=i;else{var r=i<=.5?i*(1+n):i+n-i*n,a=2*i-r;this.r=t(a,r,e+1/3),this.g=t(a,r,e),this.b=t(a,r,e-1/3)}return this}}(),setStyle:function(t){function e(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}var n;if(n=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(t)){var i,r=n[1],a=n[2];switch(r){case"rgb":case"rgba":if(i=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a))return this.r=Math.min(255,parseInt(i[1],10))/255,this.g=Math.min(255,parseInt(i[2],10))/255,this.b=Math.min(255,parseInt(i[3],10))/255,e(i[5]),this;if(i=/^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a))return this.r=Math.min(100,parseInt(i[1],10))/100,this.g=Math.min(100,parseInt(i[2],10))/100,this.b=Math.min(100,parseInt(i[3],10))/100,e(i[5]),this;break;case"hsl":case"hsla":if(i=/^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a)){var o=parseFloat(i[1])/360,s=parseInt(i[2],10)/100,c=parseInt(i[3],10)/100;return e(i[5]),this.setHSL(o,s,c)}}}else if(n=/^\#([A-Fa-f0-9]+)$/.exec(t)){var h,l=(h=n[1]).length;if(3===l)return this.r=parseInt(h.charAt(0)+h.charAt(0),16)/255,this.g=parseInt(h.charAt(1)+h.charAt(1),16)/255,this.b=parseInt(h.charAt(2)+h.charAt(2),16)/255,this;if(6===l)return this.r=parseInt(h.charAt(0)+h.charAt(1),16)/255,this.g=parseInt(h.charAt(2)+h.charAt(3),16)/255,this.b=parseInt(h.charAt(4)+h.charAt(5),16)/255,this}t&&t.length>0&&(void 0!==(h=ln[t])?this.setHex(h):console.warn("THREE.Color: Unknown color "+t));return this},clone:function(){return new this.constructor(this.r,this.g,this.b)},copy:function(t){return this.r=t.r,this.g=t.g,this.b=t.b,this},copyGammaToLinear:function(t,e){return void 0===e&&(e=2),this.r=Math.pow(t.r,e),this.g=Math.pow(t.g,e),this.b=Math.pow(t.b,e),this},copyLinearToGamma:function(t,e){void 0===e&&(e=2);var n=e>0?1/e:1;return this.r=Math.pow(t.r,n),this.g=Math.pow(t.g,n),this.b=Math.pow(t.b,n),this},convertGammaToLinear:function(t){return this.copyGammaToLinear(this,t),this},convertLinearToGamma:function(t){return this.copyLinearToGamma(this,t),this},copySRGBToLinear:function(){function t(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}return function(e){return this.r=t(e.r),this.g=t(e.g),this.b=t(e.b),this}}(),copyLinearToSRGB:function(){function t(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}return function(e){return this.r=t(e.r),this.g=t(e.g),this.b=t(e.b),this}}(),convertSRGBToLinear:function(){return this.copySRGBToLinear(this),this},convertLinearToSRGB:function(){return this.copyLinearToSRGB(this),this},getHex:function(){return 255*this.r<<16^255*this.g<<8^255*this.b<<0},getHexString:function(){return("000000"+this.getHex().toString(16)).slice(-6)},getHSL:function(t){void 0===t&&(console.warn("THREE.Color: .getHSL() target is now required"),t={h:0,s:0,l:0});var e,n,i=this.r,r=this.g,a=this.b,o=Math.max(i,r,a),s=Math.min(i,r,a),c=(s+o)/2;if(s===o)e=0,n=0;else{var h=o-s;switch(n=c<=.5?h/(o+s):h/(2-o-s),o){case i:e=(r-a)/h+(r1){for(var e=0;e1){for(var e=0;e0){i.children=[];for(s=0;s0&&(n.geometries=u),p.length>0&&(n.materials=p),d.length>0&&(n.textures=d),f.length>0&&(n.images=f),o.length>0&&(n.shapes=o)}return n.object=i,n;function m(t){var e=[];for(var n in t){var i=t[n];delete i.metadata,e.push(i)}return e}},clone:function(t){return(new this.constructor).copy(this,t)},copy:function(t,e){if(void 0===e&&(e=!0),this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(var n=0;ne&&(e=t[n]);return e}Pn.prototype=Object.assign(Object.create(i.prototype),{constructor:Pn,isGeometry:!0,applyMatrix:function(t){for(var e=(new Pe).getNormalMatrix(t),n=0,i=this.vertices.length;n0)for(h=0;h0&&(this.normalsNeedUpdate=!0)},computeFlatVertexNormals:function(){var t,e,n;for(this.computeFaceNormals(),t=0,e=this.faces.length;t0&&(this.normalsNeedUpdate=!0)},computeMorphNormals:function(){var t,e,n,i,r;for(n=0,i=this.faces.length;n=0;n--){var f=p[n];for(this.faces.splice(f,1),o=0,s=this.faceVertexUvs.length;o0,g=d.vertexNormals.length>0,v=1!==d.color.r||1!==d.color.g||1!==d.color.b,y=d.vertexColors.length>0,x=0;if(x=M(x,0,0),x=M(x,1,!0),x=M(x,2,!1),x=M(x,3,f),x=M(x,4,m),x=M(x,5,g),x=M(x,6,v),x=M(x,7,y),o.push(x),o.push(d.a,d.b,d.c),o.push(d.materialIndex),f){var b=this.faceVertexUvs[0][r];o.push(T(b[0]),T(b[1]),T(b[2]))}if(m&&o.push(S(d.normal)),g){var w=d.vertexNormals;o.push(S(w[0]),S(w[1]),S(w[2]))}if(v&&o.push(E(d.color)),y){var _=d.vertexColors;o.push(E(_[0]),E(_[1]),E(_[2]))}}function M(t,e,n){return n?t|1<0&&(t.data.colors=h),u.length>0&&(t.data.uvs=[u]),t.data.faces=o,t},clone:function(){return(new Pn).copy(this)},copy:function(t){var e,n,i,r,a,o;this.vertices=[],this.colors=[],this.faces=[],this.faceVertexUvs=[[]],this.morphTargets=[],this.morphNormals=[],this.skinWeights=[],this.skinIndices=[],this.lineDistances=[],this.boundingBox=null,this.boundingSphere=null,this.name=t.name;var s=t.vertices;for(e=0,n=s.length;e0,o=r[1]&&r[1].length>0,s=t.morphTargets,c=s.length;if(c>0){e=[];for(var h=0;h0){l=[];for(h=0;h0&&0===n.length&&console.error("THREE.DirectGeometry: Faceless geometries are not supported.");for(h=0;h0?1:-1,h.push(P.x,P.y,P.z),l.push(y/m),l.push(1-x/g),A+=1}}for(x=0;x65535?Bn:Nn)(t,1):this.index=t},addAttribute:function(t,e){return e&&e.isBufferAttribute||e&&e.isInterleavedBufferAttribute?"index"===t?(console.warn("THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute."),this.setIndex(e),this):(this.attributes[t]=e,this):(console.warn("THREE.BufferGeometry: .addAttribute() now expects ( name, attribute )."),this.addAttribute(t,new Rn(arguments[1],arguments[2])))},getAttribute:function(t){return this.attributes[t]},removeAttribute:function(t){return delete this.attributes[t],this},addGroup:function(t,e,n){this.groups.push({start:t,count:e,materialIndex:void 0!==n?n:0})},clearGroups:function(){this.groups=[]},setDrawRange:function(t,e){this.drawRange.start=t,this.drawRange.count=e},applyMatrix:function(t){var e=this.attributes.position;void 0!==e&&(t.applyToBufferAttribute(e),e.needsUpdate=!0);var n=this.attributes.normal;void 0!==n&&((new Pe).getNormalMatrix(t).applyToBufferAttribute(n),n.needsUpdate=!0);var i=this.attributes.tangent;void 0!==i&&((new Pe).getNormalMatrix(t).applyToBufferAttribute(i),i.needsUpdate=!0);return null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this},rotateX:function(){var t=new nn;return function(e){return t.makeRotationX(e),this.applyMatrix(t),this}}(),rotateY:function(){var t=new nn;return function(e){return t.makeRotationY(e),this.applyMatrix(t),this}}(),rotateZ:function(){var t=new nn;return function(e){return t.makeRotationZ(e),this.applyMatrix(t),this}}(),translate:function(){var t=new nn;return function(e,n,i){return t.makeTranslation(e,n,i),this.applyMatrix(t),this}}(),scale:function(){var t=new nn;return function(e,n,i){return t.makeScale(e,n,i),this.applyMatrix(t),this}}(),lookAt:function(){var t=new En;return function(e){t.lookAt(e),t.updateMatrix(),this.applyMatrix(t.matrix)}}(),center:function(){var t=new Le;return function(){return this.computeBoundingBox(),this.boundingBox.getCenter(t).negate(),this.translate(t.x,t.y,t.z),this}}(),setFromObject:function(t){var e=t.geometry;if(t.isPoints||t.isLine){var n=new Un(3*e.vertices.length,3),i=new Un(3*e.colors.length,3);if(this.addAttribute("position",n.copyVector3sArray(e.vertices)),this.addAttribute("color",i.copyColorsArray(e.colors)),e.lineDistances&&e.lineDistances.length===e.vertices.length){var r=new Un(e.lineDistances.length,1);this.addAttribute("lineDistance",r.copyArray(e.lineDistances))}null!==e.boundingSphere&&(this.boundingSphere=e.boundingSphere.clone()),null!==e.boundingBox&&(this.boundingBox=e.boundingBox.clone())}else t.isMesh&&e&&e.isGeometry&&this.fromGeometry(e);return this},setFromPoints:function(t){for(var e=[],n=0,i=t.length;n0){var n=new Float32Array(3*t.normals.length);this.addAttribute("normal",new Rn(n,3).copyVector3sArray(t.normals))}if(t.colors.length>0){var i=new Float32Array(3*t.colors.length);this.addAttribute("color",new Rn(i,3).copyColorsArray(t.colors))}if(t.uvs.length>0){var r=new Float32Array(2*t.uvs.length);this.addAttribute("uv",new Rn(r,2).copyVector2sArray(t.uvs))}if(t.uvs2.length>0){var a=new Float32Array(2*t.uvs2.length);this.addAttribute("uv2",new Rn(a,2).copyVector2sArray(t.uvs2))}for(var o in this.groups=t.groups,t.morphTargets){for(var s=[],c=t.morphTargets[o],h=0,l=c.length;h0){var d=new Un(4*t.skinIndices.length,4);this.addAttribute("skinIndex",d.copyVector4sArray(t.skinIndices))}if(t.skinWeights.length>0){var f=new Un(4*t.skinWeights.length,4);this.addAttribute("skinWeight",f.copyVector4sArray(t.skinWeights))}return null!==t.boundingSphere&&(this.boundingSphere=t.boundingSphere.clone()),null!==t.boundingBox&&(this.boundingBox=t.boundingBox.clone()),this},computeBoundingBox:function(){var t=new Ke;return function(){null===this.boundingBox&&(this.boundingBox=new Ke);var e=this.attributes.position,n=this.morphAttributes.position;if(void 0!==e){if(this.boundingBox.setFromBufferAttribute(e),n)for(var i=0,r=n.length;i0&&(t.userData=this.userData),void 0!==this.parameters){var e=this.parameters;for(var n in e)void 0!==e[n]&&(t[n]=e[n]);return t}t.data={attributes:{}};var i=this.index;null!==i&&(t.data.index={type:i.array.constructor.name,array:Array.prototype.slice.call(i.array)});var r=this.attributes;for(var n in r){var a={itemSize:(p=r[n]).itemSize,type:p.array.constructor.name,array:Array.prototype.slice.call(p.array),normalized:p.normalized};""!==p.name&&(a.name=p.name),t.data.attributes[n]=a}var o={},s=!1;for(var n in this.morphAttributes){for(var c=this.morphAttributes[n],h=[],l=0,u=c.length;l0&&(o[n]=h,s=!0)}s&&(t.data.morphAttributes=o);var d=this.groups;d.length>0&&(t.data.groups=JSON.parse(JSON.stringify(d)));var f=this.boundingSphere;return null!==f&&(t.data.boundingSphere={center:f.center.toArray(),radius:f.radius}),t},clone:function(){return(new Vn).copy(this)},copy:function(t){var e,n,i;this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.name=t.name;var r=t.index;null!==r&&this.setIndex(r.clone());var a=t.attributes;for(e in a){var o=a[e];this.addAttribute(e,o.clone())}var s=t.morphAttributes;for(e in s){var c=[],h=s[e];for(n=0,i=h.length;n0&&(n.alphaTest=this.alphaTest),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(n.wireframe=this.wireframe),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.morphTargets&&(n.morphTargets=!0),!0===this.skinning&&(n.skinning=!0),!1===this.visible&&(n.visible=!1),"{}"!==JSON.stringify(this.userData)&&(n.userData=this.userData),e){var r=i(t.textures),a=i(t.images);r.length>0&&(n.textures=r),a.length>0&&(n.images=a)}return n},clone:function(){return(new this.constructor).copy(this)},copy:function(t){this.name=t.name,this.fog=t.fog,this.lights=t.lights,this.blending=t.blending,this.side=t.side,this.flatShading=t.flatShading,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.premultipliedAlpha=t.premultipliedAlpha,this.visible=t.visible,this.userData=JSON.parse(JSON.stringify(t.userData)),this.clipShadows=t.clipShadows,this.clipIntersection=t.clipIntersection;var e=t.clippingPlanes,n=null;if(null!==e){var i=e.length;n=new Array(i);for(var r=0;r!==i;++r)n[r]=e[r].clone()}return this.clippingPlanes=n,this.shadowSide=t.shadowSide,this},dispose:function(){this.dispatchEvent({type:"dispose"})}});var Zn,Qn,Kn,$n,ti,ei,ni,ii,ri,ai,oi,si,ci="void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",hi="void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";function li(t){Jn.call(this),this.type="ShaderMaterial",this.defines={},this.uniforms={},this.vertexShader=ci,this.fragmentShader=hi,this.linewidth=1,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.lights=!1,this.clipping=!1,this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.extensions={derivatives:!1,fragDepth:!1,drawBuffers:!1,shaderTextureLOD:!1},this.defaultAttributeValues={color:[1,1,1],uv:[0,0],uv2:[0,0]},this.index0AttributeName=void 0,this.uniformsNeedUpdate=!1,void 0!==t&&(void 0!==t.attributes&&console.error("THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead."),this.setValues(t))}function ui(t,e){this.origin=void 0!==t?t:new Le,this.direction=void 0!==e?e:new Le}function pi(t,e,n){this.a=void 0!==t?t:new Le,this.b=void 0!==e?e:new Le,this.c=void 0!==n?n:new Le}function di(t){Jn.call(this),this.type="MeshBasicMaterial",this.color=new un(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=J,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.skinning=!1,this.morphTargets=!1,this.lights=!1,this.setValues(t)}function fi(t,e){En.call(this),this.type="Mesh",this.geometry=void 0!==t?t:new Vn,this.material=void 0!==e?e:new di({color:16777215*Math.random()}),this.drawMode=ue,this.updateMorphTargets()}function mi(t,e,n,i){var r,a,o=new un(0),s=0,c=null,h=0;function l(t,n){e.buffers.color.setClear(t.r,t.g,t.b,n,i)}return{getClearColor:function(){return o},setClearColor:function(t,e){o.set(t),l(o,s=void 0!==e?e:1)},getClearAlpha:function(){return s},setClearAlpha:function(t){l(o,s=t)},render:function(e,i,u,p){var m=i.background,g=t.vr,v=g.getSession&&g.getSession();if(v&&"additive"===v.environmentBlendMode&&(m=null),null===m?(l(o,s),c=null,h=0):m&&m.isColor&&(l(m,1),p=!0,c=null,h=0),(t.autoClear||p)&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),m&&(m.isCubeTexture||m.isWebGLRenderTargetCube)){void 0===a&&((a=new fi(new Wn(1,1,1),new li({type:"BackgroundCubeMaterial",uniforms:an(fn.cube.uniforms),vertexShader:fn.cube.vertexShader,fragmentShader:fn.cube.fragmentShader,side:f,depthTest:!1,depthWrite:!1,fog:!1}))).geometry.removeAttribute("normal"),a.geometry.removeAttribute("uv"),a.onBeforeRender=function(t,e,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(a.material,"map",{get:function(){return this.uniforms.tCube.value}}),n.update(a));var y=m.isWebGLRenderTargetCube?m.texture:m;a.material.uniforms.tCube.value=y,a.material.uniforms.tFlip.value=m.isWebGLRenderTargetCube?1:-1,c===m&&h===y.version||(a.material.needsUpdate=!0,c=m,h=y.version),e.unshift(a,a.geometry,a.material,0,0,null)}else m&&m.isTexture&&(void 0===r&&((r=new fi(new Xn(2,2),new li({type:"BackgroundMaterial",uniforms:an(fn.background.uniforms),vertexShader:fn.background.vertexShader,fragmentShader:fn.background.fragmentShader,side:d,depthTest:!1,depthWrite:!1,fog:!1}))).geometry.removeAttribute("normal"),Object.defineProperty(r.material,"map",{get:function(){return this.uniforms.t2D.value}}),n.update(r)),r.material.uniforms.t2D.value=m,!0===m.matrixAutoUpdate&&m.updateMatrix(),r.material.uniforms.uvTransform.value.copy(m.matrix),c===m&&h===m.version||(r.material.needsUpdate=!0,c=m,h=m.version),e.unshift(r,r.geometry,r.material,0,0,null))}}}function gi(t,e,n,i){var r;this.setMode=function(t){r=t},this.render=function(e,i){t.drawArrays(r,e,i),n.update(i,r)},this.renderInstances=function(a,o,s){var c;if(i.isWebGL2)c=t;else if(null===(c=e.get("ANGLE_instanced_arrays")))return void console.error("THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.");c[i.isWebGL2?"drawArraysInstanced":"drawArraysInstancedANGLE"](r,o,s,a.maxInstancedCount),n.update(s,r,a.maxInstancedCount)}}function vi(t,e,n){var i;function r(e){if("highp"===e){if(t.getShaderPrecisionFormat(35633,36338).precision>0&&t.getShaderPrecisionFormat(35632,36338).precision>0)return"highp";e="mediump"}return"mediump"===e&&t.getShaderPrecisionFormat(35633,36337).precision>0&&t.getShaderPrecisionFormat(35632,36337).precision>0?"mediump":"lowp"}var a="undefined"!=typeof WebGL2RenderingContext&&t instanceof WebGL2RenderingContext,o=void 0!==n.precision?n.precision:"highp",s=r(o);s!==o&&(console.warn("THREE.WebGLRenderer:",o,"not supported, using",s,"instead."),o=s);var c=!0===n.logarithmicDepthBuffer,h=t.getParameter(34930),l=t.getParameter(35660),u=t.getParameter(3379),p=t.getParameter(34076),d=t.getParameter(34921),f=t.getParameter(36347),m=t.getParameter(36348),g=t.getParameter(36349),v=l>0,y=a||!!e.get("OES_texture_float");return{isWebGL2:a,getMaxAnisotropy:function(){if(void 0!==i)return i;var n=e.get("EXT_texture_filter_anisotropic");return i=null!==n?t.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT):0},getMaxPrecision:r,precision:o,logarithmicDepthBuffer:c,maxTextures:h,maxVertexTextures:l,maxTextureSize:u,maxCubemapSize:p,maxAttributes:d,maxVertexUniforms:f,maxVaryings:m,maxFragmentUniforms:g,vertexTextures:v,floatFragmentTextures:y,floatVertexTextures:v&&y,maxSamples:a?t.getParameter(36183):0}}function yi(){var t=this,e=null,n=0,i=!1,r=!1,a=new tn,o=new Pe,s={value:null,needsUpdate:!1};function c(){s.value!==e&&(s.value=e,s.needsUpdate=n>0),t.numPlanes=n,t.numIntersection=0}function h(e,n,i,r){var c=null!==e?e.length:0,h=null;if(0!==c){if(h=s.value,!0!==r||null===h){var l=i+4*c,u=n.matrixWorldInverse;o.getNormalMatrix(u),(null===h||h.length65535?Bn:Nn)(a,1),e.update(n,34963),r[t.id]=n,n}}}function wi(t,e,n,i){var r,a,o;this.setMode=function(t){r=t},this.setIndex=function(t){a=t.type,o=t.bytesPerElement},this.render=function(e,i){t.drawElements(r,i,a,e*o),n.update(i,r)},this.renderInstances=function(s,c,h){var l;if(i.isWebGL2)l=t;else if(null===(l=e.get("ANGLE_instanced_arrays")))return void console.error("THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.");l[i.isWebGL2?"drawElementsInstanced":"drawElementsInstancedANGLE"](r,h,a,c*o,s.maxInstancedCount),n.update(h,r,s.maxInstancedCount)}}function _i(t){var e={frame:0,calls:0,triangles:0,points:0,lines:0};return{memory:{geometries:0,textures:0},render:e,programs:null,autoReset:!0,reset:function(){e.frame++,e.calls=0,e.triangles=0,e.points=0,e.lines=0},update:function(t,n,i){switch(i=i||1,e.calls++,n){case 4:e.triangles+=i*(t/3);break;case 5:case 6:e.triangles+=i*(t-2);break;case 1:e.lines+=i*(t/2);break;case 3:e.lines+=i*(t-1);break;case 2:e.lines+=i*t;break;case 0:e.points+=i*t;break;default:console.error("THREE.WebGLInfo: Unknown draw mode:",n)}}}}function Mi(t,e){return Math.abs(e[1])-Math.abs(t[1])}function Si(t){var e={},n=new Float32Array(8);return{update:function(i,r,a,o){var s=i.morphTargetInfluences,c=s.length,h=e[r.id];if(void 0===h){h=[];for(var l=0;l0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader;var r={};for(var a in this.extensions)!0===this.extensions[a]&&(r[a]=!0);return Object.keys(r).length>0&&(e.extensions=r),e},Object.assign(ui.prototype,{set:function(t,e){return this.origin.copy(t),this.direction.copy(e),this},clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this},at:function(t,e){return void 0===e&&(console.warn("THREE.Ray: .at() target is now required"),e=new Le),e.copy(this.direction).multiplyScalar(t).add(this.origin)},lookAt:function(t){return this.direction.copy(t).sub(this.origin).normalize(),this},recast:function(){var t=new Le;return function(e){return this.origin.copy(this.at(e,t)),this}}(),closestPointToPoint:function(t,e){void 0===e&&(console.warn("THREE.Ray: .closestPointToPoint() target is now required"),e=new Le),e.subVectors(t,this.origin);var n=e.dot(this.direction);return n<0?e.copy(this.origin):e.copy(this.direction).multiplyScalar(n).add(this.origin)},distanceToPoint:function(t){return Math.sqrt(this.distanceSqToPoint(t))},distanceSqToPoint:function(){var t=new Le;return function(e){var n=t.subVectors(e,this.origin).dot(this.direction);return n<0?this.origin.distanceToSquared(e):(t.copy(this.direction).multiplyScalar(n).add(this.origin),t.distanceToSquared(e))}}(),distanceSqToSegment:(Qn=new Le,Kn=new Le,$n=new Le,function(t,e,n,i){Qn.copy(t).add(e).multiplyScalar(.5),Kn.copy(e).sub(t).normalize(),$n.copy(this.origin).sub(Qn);var r,a,o,s,c=.5*t.distanceTo(e),h=-this.direction.dot(Kn),l=$n.dot(this.direction),u=-$n.dot(Kn),p=$n.lengthSq(),d=Math.abs(1-h*h);if(d>0)if(a=h*l-u,s=c*d,(r=h*u-l)>=0)if(a>=-s)if(a<=s){var f=1/d;o=(r*=f)*(r+h*(a*=f)+2*l)+a*(h*r+a+2*u)+p}else a=c,o=-(r=Math.max(0,-(h*a+l)))*r+a*(a+2*u)+p;else a=-c,o=-(r=Math.max(0,-(h*a+l)))*r+a*(a+2*u)+p;else a<=-s?o=-(r=Math.max(0,-(-h*c+l)))*r+(a=r>0?-c:Math.min(Math.max(-c,-u),c))*(a+2*u)+p:a<=s?(r=0,o=(a=Math.min(Math.max(-c,-u),c))*(a+2*u)+p):o=-(r=Math.max(0,-(h*c+l)))*r+(a=r>0?c:Math.min(Math.max(-c,-u),c))*(a+2*u)+p;else a=h>0?-c:c,o=-(r=Math.max(0,-(h*a+l)))*r+a*(a+2*u)+p;return n&&n.copy(this.direction).multiplyScalar(r).add(this.origin),i&&i.copy(Kn).multiplyScalar(a).add(Qn),o}),intersectSphere:function(){var t=new Le;return function(e,n){t.subVectors(e.center,this.origin);var i=t.dot(this.direction),r=t.dot(t)-i*i,a=e.radius*e.radius;if(r>a)return null;var o=Math.sqrt(a-r),s=i-o,c=i+o;return s<0&&c<0?null:s<0?this.at(c,n):this.at(s,n)}}(),intersectsSphere:function(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius},distanceToPlane:function(t){var e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;var n=-(this.origin.dot(t.normal)+t.constant)/e;return n>=0?n:null},intersectPlane:function(t,e){var n=this.distanceToPlane(t);return null===n?null:this.at(n,e)},intersectsPlane:function(t){var e=t.distanceToPoint(this.origin);return 0===e||t.normal.dot(this.direction)*e<0},intersectBox:function(t,e){var n,i,r,a,o,s,c=1/this.direction.x,h=1/this.direction.y,l=1/this.direction.z,u=this.origin;return c>=0?(n=(t.min.x-u.x)*c,i=(t.max.x-u.x)*c):(n=(t.max.x-u.x)*c,i=(t.min.x-u.x)*c),h>=0?(r=(t.min.y-u.y)*h,a=(t.max.y-u.y)*h):(r=(t.max.y-u.y)*h,a=(t.min.y-u.y)*h),n>a||r>i?null:((r>n||n!=n)&&(n=r),(a=0?(o=(t.min.z-u.z)*l,s=(t.max.z-u.z)*l):(o=(t.max.z-u.z)*l,s=(t.min.z-u.z)*l),n>s||o>i?null:((o>n||n!=n)&&(n=o),(s=0?n:i,e)))},intersectsBox:(Zn=new Le,function(t){return null!==this.intersectBox(t,Zn)}),intersectTriangle:function(){var t=new Le,e=new Le,n=new Le,i=new Le;return function(r,a,o,s,c){e.subVectors(a,r),n.subVectors(o,r),i.crossVectors(e,n);var h,l=this.direction.dot(i);if(l>0){if(s)return null;h=1}else{if(!(l<0))return null;h=-1,l=-l}t.subVectors(this.origin,r);var u=h*this.direction.dot(n.crossVectors(t,n));if(u<0)return null;var p=h*this.direction.dot(e.cross(t));if(p<0)return null;if(u+p>l)return null;var d=-h*t.dot(i);return d<0?null:this.at(d/l,c)}}(),applyMatrix4:function(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this},equals:function(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}}),Object.assign(pi,{getNormal:(ei=new Le,function(t,e,n,i){void 0===i&&(console.warn("THREE.Triangle: .getNormal() target is now required"),i=new Le),i.subVectors(n,e),ei.subVectors(t,e),i.cross(ei);var r=i.lengthSq();return r>0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}),getBarycoord:function(){var t=new Le,e=new Le,n=new Le;return function(i,r,a,o,s){t.subVectors(o,r),e.subVectors(a,r),n.subVectors(i,r);var c=t.dot(t),h=t.dot(e),l=t.dot(n),u=e.dot(e),p=e.dot(n),d=c*u-h*h;if(void 0===s&&(console.warn("THREE.Triangle: .getBarycoord() target is now required"),s=new Le),0===d)return s.set(-2,-1,-1);var f=1/d,m=(u*l-h*p)*f,g=(c*p-h*l)*f;return s.set(1-m-g,g,m)}}(),containsPoint:function(){var t=new Le;return function(e,n,i,r){return pi.getBarycoord(e,n,i,r,t),t.x>=0&&t.y>=0&&t.x+t.y<=1}}(),getUV:(ti=new Le,function(t,e,n,i,r,a,o,s){return this.getBarycoord(t,e,n,i,ti),s.set(0,0),s.addScaledVector(r,ti.x),s.addScaledVector(a,ti.y),s.addScaledVector(o,ti.z),s})}),Object.assign(pi.prototype,{set:function(t,e,n){return this.a.copy(t),this.b.copy(e),this.c.copy(n),this},setFromPointsAndIndices:function(t,e,n,i){return this.a.copy(t[e]),this.b.copy(t[n]),this.c.copy(t[i]),this},clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this},getArea:function(){var t=new Le,e=new Le;return function(){return t.subVectors(this.c,this.b),e.subVectors(this.a,this.b),.5*t.cross(e).length()}}(),getMidpoint:function(t){return void 0===t&&(console.warn("THREE.Triangle: .getMidpoint() target is now required"),t=new Le),t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},getNormal:function(t){return pi.getNormal(this.a,this.b,this.c,t)},getPlane:function(t){return void 0===t&&(console.warn("THREE.Triangle: .getPlane() target is now required"),t=new Le),t.setFromCoplanarPoints(this.a,this.b,this.c)},getBarycoord:function(t,e){return pi.getBarycoord(t,this.a,this.b,this.c,e)},containsPoint:function(t){return pi.containsPoint(t,this.a,this.b,this.c)},getUV:function(t,e,n,i,r){return pi.getUV(t,this.a,this.b,this.c,e,n,i,r)},intersectsBox:function(t){return t.intersectsTriangle(this)},closestPointToPoint:(ni=new Le,ii=new Le,ri=new Le,ai=new Le,oi=new Le,si=new Le,function(t,e){void 0===e&&(console.warn("THREE.Triangle: .closestPointToPoint() target is now required"),e=new Le);var n,i,r=this.a,a=this.b,o=this.c;ni.subVectors(a,r),ii.subVectors(o,r),ai.subVectors(t,r);var s=ni.dot(ai),c=ii.dot(ai);if(s<=0&&c<=0)return e.copy(r);oi.subVectors(t,a);var h=ni.dot(oi),l=ii.dot(oi);if(h>=0&&l<=h)return e.copy(a);var u=s*l-h*c;if(u<=0&&s>=0&&h<=0)return n=s/(s-h),e.copy(r).addScaledVector(ni,n);si.subVectors(t,o);var p=ni.dot(si),d=ii.dot(si);if(d>=0&&p<=d)return e.copy(o);var f=p*c-s*d;if(f<=0&&c>=0&&d<=0)return i=c/(c-d),e.copy(r).addScaledVector(ii,i);var m=h*d-p*l;if(m<=0&&l-h>=0&&p-d>=0)return ri.subVectors(o,a),i=(l-h)/(l-h+(p-d)),e.copy(a).addScaledVector(ri,i);var g=1/(m+f+u);return n=f*g,i=u*g,e.copy(r).addScaledVector(ni,n).addScaledVector(ii,i)}),equals:function(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}),di.prototype=Object.create(Jn.prototype),di.prototype.constructor=di,di.prototype.isMeshBasicMaterial=!0,di.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this},fi.prototype=Object.assign(Object.create(En.prototype),{constructor:fi,isMesh:!0,setDrawMode:function(t){this.drawMode=t},copy:function(t){return En.prototype.copy.call(this,t),this.drawMode=t.drawMode,void 0!==t.morphTargetInfluences&&(this.morphTargetInfluences=t.morphTargetInfluences.slice()),void 0!==t.morphTargetDictionary&&(this.morphTargetDictionary=Object.assign({},t.morphTargetDictionary)),this},updateMorphTargets:function(){var t,e,n,i=this.geometry;if(i.isBufferGeometry){var r=i.morphAttributes,a=Object.keys(r);if(a.length>0){var o=r[a[0]];if(void 0!==o)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},t=0,e=o.length;t0&&console.error("THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.")}},raycast:function(){var t=new nn,e=new ui,n=new $e,i=new Le,r=new Le,a=new Le,o=new Le,s=new Le,c=new Le,h=new Le,l=new Le,u=new Le,p=new Te,d=new Te,g=new Te,v=new Le,y=new Le;function x(t,e,n,i,r,a,o,s){if(null===(e.side===f?i.intersectTriangle(o,a,r,!0,s):i.intersectTriangle(r,a,o,e.side!==m,s)))return null;y.copy(s),y.applyMatrix4(t.matrixWorld);var c=n.ray.origin.distanceTo(y);return cn.far?null:{distance:c,point:y.clone(),object:t}}function b(t,e,n,f,m,y,b,w,_,M){i.fromBufferAttribute(m,w),r.fromBufferAttribute(m,_),a.fromBufferAttribute(m,M);var S=t.morphTargetInfluences;if(e.morphTargets&&y&&S){h.set(0,0,0),l.set(0,0,0),u.set(0,0,0);for(var E=0,T=y.length;E0&&(I=B);for(var U=0,G=z.length;U0)return t;var r=e*n,a=Ii[r];if(void 0===a&&(a=new Float32Array(r),Ii[r]=a),0!==e){i.toArray(a,0);for(var o=1,s=0;o!==e;++o)s+=n,t[o].toArray(a,s)}return a}function Gi(t,e){if(t.length!==e.length)return!1;for(var n=0,i=t.length;n/gm,function(t,e){var n=rn[e];if(void 0===n)throw new Error("Can not resolve #include <"+e+">");return Lr(n)})}function Pr(t){return t.replace(/#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,function(t,e,n,i){for(var r="",a=parseInt(e);a0?t.gammaFactor:1,S=o.isWebGL2?"":function(t,e,n){return[(t=t||{}).derivatives||e.envMapCubeUV||e.bumpMap||e.normalMap&&!e.objectSpaceNormalMap||e.flatShading?"#extension GL_OES_standard_derivatives : enable":"",(t.fragDepth||e.logarithmicDepthBuffer)&&n.get("EXT_frag_depth")?"#extension GL_EXT_frag_depth : enable":"",t.drawBuffers&&n.get("WEBGL_draw_buffers")?"#extension GL_EXT_draw_buffers : require":"",(t.shaderTextureLOD||e.envMap)&&n.get("EXT_shader_texture_lod")?"#extension GL_EXT_shader_texture_lod : enable":""].filter(Er).join("\n")}(i.extensions,a,e),E=function(t){var e=[];for(var n in t){var i=t[n];!1!==i&&e.push("#define "+n+" "+i)}return e.join("\n")}(h),T=c.createProgram();if(i.isRawShaderMaterial?((y=[E].filter(Er).join("\n")).length>0&&(y+="\n"),(x=[S,E].filter(Er).join("\n")).length>0&&(x+="\n")):(y=["precision "+a.precision+" float;","precision "+a.precision+" int;","#define SHADER_NAME "+r.name,E,a.supportsVertexTextures?"#define VERTEX_TEXTURES":"","#define GAMMA_FACTOR "+M,"#define MAX_BONES "+a.maxBones,a.useFog&&a.fog?"#define USE_FOG":"",a.useFog&&a.fogExp?"#define FOG_EXP2":"",a.map?"#define USE_MAP":"",a.envMap?"#define USE_ENVMAP":"",a.envMap?"#define "+g:"",a.lightMap?"#define USE_LIGHTMAP":"",a.aoMap?"#define USE_AOMAP":"",a.emissiveMap?"#define USE_EMISSIVEMAP":"",a.bumpMap?"#define USE_BUMPMAP":"",a.normalMap?"#define USE_NORMALMAP":"",a.normalMap&&a.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",a.displacementMap&&a.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",a.specularMap?"#define USE_SPECULARMAP":"",a.roughnessMap?"#define USE_ROUGHNESSMAP":"",a.metalnessMap?"#define USE_METALNESSMAP":"",a.alphaMap?"#define USE_ALPHAMAP":"",a.vertexTangents?"#define USE_TANGENT":"",a.vertexColors?"#define USE_COLOR":"",a.flatShading?"#define FLAT_SHADED":"",a.skinning?"#define USE_SKINNING":"",a.useVertexTexture?"#define BONE_TEXTURE":"",a.morphTargets?"#define USE_MORPHTARGETS":"",a.morphNormals&&!1===a.flatShading?"#define USE_MORPHNORMALS":"",a.doubleSided?"#define DOUBLE_SIDED":"",a.flipSided?"#define FLIP_SIDED":"",a.shadowMapEnabled?"#define USE_SHADOWMAP":"",a.shadowMapEnabled?"#define "+f:"",a.sizeAttenuation?"#define USE_SIZEATTENUATION":"",a.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",a.logarithmicDepthBuffer&&(o.isWebGL2||e.get("EXT_frag_depth"))?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#ifdef USE_COLOR","\tattribute vec3 color;","#endif","#ifdef USE_MORPHTARGETS","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(Er).join("\n"),x=[S,"precision "+a.precision+" float;","precision "+a.precision+" int;","#define SHADER_NAME "+r.name,E,a.alphaTest?"#define ALPHATEST "+a.alphaTest+(a.alphaTest%1?"":".0"):"","#define GAMMA_FACTOR "+M,a.useFog&&a.fog?"#define USE_FOG":"",a.useFog&&a.fogExp?"#define FOG_EXP2":"",a.map?"#define USE_MAP":"",a.matcap?"#define USE_MATCAP":"",a.envMap?"#define USE_ENVMAP":"",a.envMap?"#define "+m:"",a.envMap?"#define "+g:"",a.envMap?"#define "+v:"",a.lightMap?"#define USE_LIGHTMAP":"",a.aoMap?"#define USE_AOMAP":"",a.emissiveMap?"#define USE_EMISSIVEMAP":"",a.bumpMap?"#define USE_BUMPMAP":"",a.normalMap?"#define USE_NORMALMAP":"",a.normalMap&&a.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",a.specularMap?"#define USE_SPECULARMAP":"",a.roughnessMap?"#define USE_ROUGHNESSMAP":"",a.metalnessMap?"#define USE_METALNESSMAP":"",a.alphaMap?"#define USE_ALPHAMAP":"",a.vertexTangents?"#define USE_TANGENT":"",a.vertexColors?"#define USE_COLOR":"",a.gradientMap?"#define USE_GRADIENTMAP":"",a.flatShading?"#define FLAT_SHADED":"",a.doubleSided?"#define DOUBLE_SIDED":"",a.flipSided?"#define FLIP_SIDED":"",a.shadowMapEnabled?"#define USE_SHADOWMAP":"",a.shadowMapEnabled?"#define "+f:"",a.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",a.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",a.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",a.logarithmicDepthBuffer&&(o.isWebGL2||e.get("EXT_frag_depth"))?"#define USE_LOGDEPTHBUF_EXT":"",a.envMap&&(o.isWebGL2||e.get("EXT_shader_texture_lod"))?"#define TEXTURE_LOD_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;",a.toneMapping!==K?"#define TONE_MAPPING":"",a.toneMapping!==K?rn.tonemapping_pars_fragment:"",a.toneMapping!==K?Sr("toneMapping",a.toneMapping):"",a.dithering?"#define DITHERING":"",a.outputEncoding||a.mapEncoding||a.matcapEncoding||a.envMapEncoding||a.emissiveMapEncoding?rn.encodings_pars_fragment:"",a.mapEncoding?Mr("mapTexelToLinear",a.mapEncoding):"",a.matcapEncoding?Mr("matcapTexelToLinear",a.matcapEncoding):"",a.envMapEncoding?Mr("envMapTexelToLinear",a.envMapEncoding):"",a.emissiveMapEncoding?Mr("emissiveMapTexelToLinear",a.emissiveMapEncoding):"",a.outputEncoding?(b="linearToOutputTexel",w=a.outputEncoding,_=_r(w),"vec4 "+b+"( vec4 value ) { return LinearTo"+_[0]+_[1]+"; }"):"",a.depthPacking?"#define DEPTH_PACKING "+i.depthPacking:"","\n"].filter(Er).join("\n")),l=Ar(l=Tr(l=Lr(l),a),a),d=Ar(d=Tr(d=Lr(d),a),a),l=Pr(l),d=Pr(d),o.isWebGL2&&!i.isRawShaderMaterial){var A=!1,L=/^\s*#version\s+300\s+es\s*\n/;i.isShaderMaterial&&null!==l.match(L)&&null!==d.match(L)&&(A=!0,l=l.replace(L,""),d=d.replace(L,"")),y=["#version 300 es\n","#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+y,x=["#version 300 es\n","#define varying in",A?"":"out highp vec4 pc_fragColor;",A?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+x}var P,R,C=x+d,O=br(c,35633,y+l,t.debug.checkShaderErrors),I=br(c,35632,C,t.debug.checkShaderErrors);if(c.attachShader(T,O),c.attachShader(T,I),void 0!==i.index0AttributeName?c.bindAttribLocation(T,0,i.index0AttributeName):!0===a.morphTargets&&c.bindAttribLocation(T,0,"position"),c.linkProgram(T),t.debug.checkShaderErrors){var D=c.getProgramInfoLog(T).trim(),N=c.getShaderInfoLog(O).trim(),z=c.getShaderInfoLog(I).trim(),B=!0,U=!0;!1===c.getProgramParameter(T,35714)?(B=!1,console.error("THREE.WebGLProgram: shader error: ",c.getError(),"35715",c.getProgramParameter(T,35715),"gl.getProgramInfoLog",D,N,z)):""!==D?console.warn("THREE.WebGLProgram: gl.getProgramInfoLog()",D):""!==N&&""!==z||(U=!1),U&&(this.diagnostics={runnable:B,material:i,programLog:D,vertexShader:{log:N,prefix:y},fragmentShader:{log:z,prefix:x}})}return c.deleteShader(O),c.deleteShader(I),this.getUniforms=function(){return void 0===P&&(P=new xr(c,T,s)),P},this.getAttributes=function(){return void 0===R&&(R=function(t,e){for(var n={},i=t.getProgramParameter(e,35721),r=0;r0,maxBones:p,useVertexTexture:n.floatVertexTextures,morphTargets:e.morphTargets,morphNormals:e.morphNormals,maxMorphTargets:t.maxMorphTargets,maxMorphNormals:t.maxMorphNormals,numDirLights:i.directional.length,numPointLights:i.point.length,numSpotLights:i.spot.length,numRectAreaLights:i.rectArea.length,numHemiLights:i.hemi.length,numClippingPlanes:c,numClipIntersection:h,dithering:e.dithering,shadowMapEnabled:t.shadowMap.enabled&&l.receiveShadow&&r.length>0,shadowMapType:t.shadowMap.type,toneMapping:t.toneMapping,physicallyCorrectLights:t.physicallyCorrectLights,premultipliedAlpha:e.premultipliedAlpha,alphaTest:e.alphaTest,doubleSided:e.side===m,flipSided:e.side===f,depthPacking:void 0!==e.depthPacking&&e.depthPacking}},this.getProgramCode=function(e,n){var i=[];if(n.shaderID?i.push(n.shaderID):(i.push(e.fragmentShader),i.push(e.vertexShader)),void 0!==e.defines)for(var r in e.defines)i.push(r),i.push(e.defines[r]);for(var a=0;a1&&n.sort(Ir),i.length>1&&i.sort(Dr)}}}function zr(){var t={};function e(n){var i=n.target;i.removeEventListener("dispose",e),delete t[i.id]}return{get:function(n,i){var r,a=t[n.id];return void 0===a?(r=new Nr,t[n.id]={},t[n.id][i.id]=r,n.addEventListener("dispose",e)):void 0===(r=a[i.id])&&(r=new Nr,a[i.id]=r),r},dispose:function(){t={}}}}function Br(){var t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];var n;switch(e.type){case"DirectionalLight":n={direction:new Le,color:new un,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new Te};break;case"SpotLight":n={position:new Le,direction:new Le,color:new un,distance:0,coneCos:0,penumbraCos:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new Te};break;case"PointLight":n={position:new Le,color:new un,distance:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new Te,shadowCameraNear:1,shadowCameraFar:1e3};break;case"HemisphereLight":n={direction:new Le,skyColor:new un,groundColor:new un};break;case"RectAreaLight":n={color:new un,position:new Le,halfWidth:new Le,halfHeight:new Le}}return t[e.id]=n,n}}}var Ur=0;function Gr(){for(var t=new Br,e={id:Ur++,hash:{stateID:-1,directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,shadowsLength:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],point:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]},n=0;n<9;n++)e.probe.push(new Le);var i=new Le,r=new nn,a=new nn;return{setup:function(n,o,s){for(var c=0,h=0,l=0,u=0;u<9;u++)e.probe[u].set(0,0,0);for(var p=0,d=0,f=0,m=0,g=0,v=s.matrixWorldInverse,y=(u=0,n.length);u0:s&&s.isGeometry&&(d=s.morphTargets&&s.morphTargets.length>0)),e.isSkinnedMesh&&!1===n.skinning&&console.warn("THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:",e);var f=e.isSkinnedMesh&&n.skinning,m=0;d&&(m|=h),f&&(m|=l),c=u[m]}if(t.localClippingEnabled&&!0===n.clipShadows&&0!==n.clippingPlanes.length){var x=c.uuid,w=n.uuid,_=y[x];void 0===_&&(_={},y[x]=_);var M=_[w];void 0===M&&(M=c.clone(),_[w]=M),c=M}return c.visible=n.visible,c.wireframe=n.wireframe,c.side=null!=n.shadowSide?n.shadowSide:b[n.side],c.clipShadows=n.clipShadows,c.clippingPlanes=n.clippingPlanes,c.clipIntersection=n.clipIntersection,c.wireframeLinewidth=n.wireframeLinewidth,c.linewidth=n.linewidth,i&&c.isMeshDistanceMaterial&&(c.referencePosition.copy(r),c.nearDistance=a,c.farDistance=o),c}function C(n,r,a,o){if(!1!==n.visible){if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&n.castShadow&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(a.matrixWorldInverse,n.matrixWorld);var s=e.update(n),h=n.material;if(Array.isArray(h))for(var l=s.groups,u=0,p=l.length;u=1):-1!==Q.indexOf("OpenGL ES")&&(Z=parseFloat(/^OpenGL\ ES\ ([0-9])/.exec(Q)[1]),J=Z>=2);var K=null,$={},tt=new Xe,et=new Xe;function nt(e,n,i){var r=new Uint8Array(4),a=t.createTexture();t.bindTexture(e,a),t.texParameteri(e,10241,9728),t.texParameteri(e,10240,9728);for(var o=0;oi||t.height>i)&&(r=i/Math.max(t.width,t.height)),r<1||!0===e){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){var a=e?Ee.floorPowerOfTwo:Math.floor,o=a(r*t.width),c=a(r*t.height);void 0===s&&(s=l(o,c));var h=n?l(o,c):s;return h.width=o,h.height=c,h.getContext("2d").drawImage(t,0,0,o,c),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+t.width+"x"+t.height+") to ("+o+"x"+c+")."),h}return"data"in t&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+t.width+"x"+t.height+")."),t}return t}function p(t){return Ee.isPowerOfTwo(t.width)&&Ee.isPowerOfTwo(t.height)}function d(t,e){return t.generateMipmaps&&e&&t.minFilter!==ft&&t.minFilter!==vt}function f(e,n,r,a){t.generateMipmap(e),i.get(n).__maxMipLevel=Math.log(Math.max(r,a))*Math.LOG2E}function m(t,n){if(!r.isWebGL2)return t;var i=t;return 6403===t&&(5126===n&&(i=33326),5131===n&&(i=33325),5121===n&&(i=33321)),6407===t&&(5126===n&&(i=34837),5131===n&&(i=34843),5121===n&&(i=32849)),6408===t&&(5126===n&&(i=34836),5131===n&&(i=34842),5121===n&&(i=32856)),33325===i||33326===i||34842===i||34836===i?e.get("EXT_color_buffer_float"):34843!==i&&34837!==i||console.warn("THREE.WebGLRenderer: Floating point textures with RGB format not supported. Please use RGBA instead."),i}function g(t){return t===ft||t===mt||t===gt?9728:9729}function v(e){var n=e.target;n.removeEventListener("dispose",v),function(e){var n=i.get(e);if(void 0===n.__webglInit)return;t.deleteTexture(n.__webglTexture),i.remove(e)}(n),n.isVideoTexture&&delete c[n.id],o.memory.textures--}function y(e){var n=e.target;n.removeEventListener("dispose",y),function(e){var n=i.get(e),r=i.get(e.texture);if(!e)return;void 0!==r.__webglTexture&&t.deleteTexture(r.__webglTexture);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLRenderTargetCube)for(var a=0;a<6;a++)t.deleteFramebuffer(n.__webglFramebuffer[a]),n.__webglDepthbuffer&&t.deleteRenderbuffer(n.__webglDepthbuffer[a]);else t.deleteFramebuffer(n.__webglFramebuffer),n.__webglDepthbuffer&&t.deleteRenderbuffer(n.__webglDepthbuffer);i.remove(e.texture),i.remove(e)}(n),o.memory.textures--}var x=0;function b(t,e){var r=i.get(t);if(t.isVideoTexture&&function(t){var e=t.id,n=o.render.frame;c[e]!==n&&(c[e]=n,t.update())}(t),t.version>0&&r.__version!==t.version){var a=t.image;if(void 0===a)console.warn("THREE.WebGLRenderer: Texture marked for update but image is undefined");else{if(!1!==a.complete)return void E(r,t,e);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.activeTexture(33984+e),n.bindTexture(3553,r.__webglTexture)}function w(e,o){var s=i.get(e);if(6===e.image.length)if(e.version>0&&s.__version!==e.version){S(s,e),n.activeTexture(33984+o),n.bindTexture(34067,s.__webglTexture),t.pixelStorei(37440,e.flipY);for(var c=e&&e.isCompressedTexture,h=e.image[0]&&e.image[0].isDataTexture,l=[],g=0;g<6;g++)l[g]=c||h?h?e.image[g].image:e.image[g]:u(e.image[g],!1,!0,r.maxCubemapSize);var v=l[0],y=p(v)||r.isWebGL2,x=a.convert(e.format),b=a.convert(e.type),w=m(x,b);M(34067,e,y);for(g=0;g<6;g++)if(c)for(var _,E=l[g].mipmaps,T=0,A=E.length;T-1?n.compressedTexImage2D(34069+g,T,w,_.width,_.height,0,_.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()"):n.texImage2D(34069+g,T,w,_.width,_.height,0,x,b,_.data);else h?n.texImage2D(34069+g,0,w,l[g].width,l[g].height,0,x,b,l[g].data):n.texImage2D(34069+g,0,w,x,b,l[g]);s.__maxMipLevel=c?E.length-1:0,d(e,y)&&f(34067,e,v.width,v.height),s.__version=e.version,e.onUpdate&&e.onUpdate(e)}else n.activeTexture(33984+o),n.bindTexture(34067,s.__webglTexture)}function _(t,e){n.activeTexture(33984+e),n.bindTexture(34067,i.get(t).__webglTexture)}function M(n,o,s){var c;if(s?(t.texParameteri(n,10242,a.convert(o.wrapS)),t.texParameteri(n,10243,a.convert(o.wrapT)),32879!==n&&35866!==n||t.texParameteri(n,32882,a.convert(o.wrapR)),t.texParameteri(n,10240,a.convert(o.magFilter)),t.texParameteri(n,10241,a.convert(o.minFilter))):(t.texParameteri(n,10242,33071),t.texParameteri(n,10243,33071),32879!==n&&35866!==n||t.texParameteri(n,32882,33071),o.wrapS===pt&&o.wrapT===pt||console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping."),t.texParameteri(n,10240,g(o.magFilter)),t.texParameteri(n,10241,g(o.minFilter)),o.minFilter!==ft&&o.minFilter!==vt&&console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.")),c=e.get("EXT_texture_filter_anisotropic")){if(o.type===Tt&&null===e.get("OES_texture_float_linear"))return;if(o.type===At&&null===(r.isWebGL2||e.get("OES_texture_half_float_linear")))return;(o.anisotropy>1||i.get(o).__currentAnisotropy)&&(t.texParameterf(n,c.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(o.anisotropy,r.getMaxAnisotropy())),i.get(o).__currentAnisotropy=o.anisotropy)}}function S(e,n){void 0===e.__webglInit&&(e.__webglInit=!0,n.addEventListener("dispose",v),e.__webglTexture=t.createTexture(),o.memory.textures++)}function E(e,i,o){var s=3553;i.isDataTexture2DArray&&(s=35866),i.isDataTexture3D&&(s=32879),S(e,i),n.activeTexture(33984+o),n.bindTexture(s,e.__webglTexture),t.pixelStorei(37440,i.flipY),t.pixelStorei(37441,i.premultiplyAlpha),t.pixelStorei(3317,i.unpackAlignment);var c=function(t){return!r.isWebGL2&&(t.wrapS!==pt||t.wrapT!==pt||t.minFilter!==ft&&t.minFilter!==vt)}(i)&&!1===p(i.image),h=u(i.image,c,!1,r.maxTextureSize),l=p(h)||r.isWebGL2,g=a.convert(i.format),v=a.convert(i.type),y=m(g,v);M(s,i,l);var x,b=i.mipmaps;if(i.isDepthTexture){if(y=6402,i.type===Tt){if(!r.isWebGL2)throw new Error("Float Depth Texture only supported in WebGL2.0");y=36012}else r.isWebGL2&&(y=33189);i.format===Bt&&6402===y&&i.type!==Mt&&i.type!==Et&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),i.type=Mt,v=a.convert(i.type)),i.format===Ut&&(y=34041,i.type!==Ct&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),i.type=Ct,v=a.convert(i.type))),n.texImage2D(3553,0,y,h.width,h.height,0,g,v,null)}else if(i.isDataTexture)if(b.length>0&&l){for(var w=0,_=b.length;w<_;w++)x=b[w],n.texImage2D(3553,w,y,x.width,x.height,0,g,v,x.data);i.generateMipmaps=!1,e.__maxMipLevel=b.length-1}else n.texImage2D(3553,0,y,h.width,h.height,0,g,v,h.data),e.__maxMipLevel=0;else if(i.isCompressedTexture){for(w=0,_=b.length;w<_;w++)x=b[w],i.format!==Dt&&i.format!==It?n.getCompressedTextureFormats().indexOf(g)>-1?n.compressedTexImage2D(3553,w,y,x.width,x.height,0,x.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()"):n.texImage2D(3553,w,y,x.width,x.height,0,g,v,x.data);e.__maxMipLevel=b.length-1}else if(i.isDataTexture2DArray)n.texImage3D(35866,0,y,h.width,h.height,h.depth,0,g,v,h.data),e.__maxMipLevel=0;else if(i.isDataTexture3D)n.texImage3D(32879,0,y,h.width,h.height,h.depth,0,g,v,h.data),e.__maxMipLevel=0;else if(b.length>0&&l){for(w=0,_=b.length;w<_;w++)x=b[w],n.texImage2D(3553,w,y,g,v,x);i.generateMipmaps=!1,e.__maxMipLevel=b.length-1}else n.texImage2D(3553,0,y,g,v,h),e.__maxMipLevel=0;d(i,l)&&f(3553,i,h.width,h.height),e.__version=i.version,i.onUpdate&&i.onUpdate(i)}function T(e,r,o,s){var c=a.convert(r.texture.format),h=a.convert(r.texture.type),l=m(c,h);n.texImage2D(s,0,l,r.width,r.height,0,c,h,null),t.bindFramebuffer(36160,e),t.framebufferTexture2D(36160,o,s,i.get(r.texture).__webglTexture,0),t.bindFramebuffer(36160,null)}function A(e,n,i){if(t.bindRenderbuffer(36161,e),n.depthBuffer&&!n.stencilBuffer){if(i){var r=P(n);t.renderbufferStorageMultisample(36161,r,33189,n.width,n.height)}else t.renderbufferStorage(36161,33189,n.width,n.height);t.framebufferRenderbuffer(36160,36096,36161,e)}else if(n.depthBuffer&&n.stencilBuffer){if(i){r=P(n);t.renderbufferStorageMultisample(36161,r,34041,n.width,n.height)}else t.renderbufferStorage(36161,34041,n.width,n.height);t.framebufferRenderbuffer(36160,33306,36161,e)}else{var o=m(a.convert(n.texture.format),a.convert(n.texture.type));if(i){r=P(n);t.renderbufferStorageMultisample(36161,r,o,n.width,n.height)}else t.renderbufferStorage(36161,o,n.width,n.height)}t.bindRenderbuffer(36161,null)}function L(e){var n=i.get(e),r=!0===e.isWebGLRenderTargetCube;if(e.depthTexture){if(r)throw new Error("target.depthTexture not supported in Cube render targets");!function(e,n){if(n&&n.isWebGLRenderTargetCube)throw new Error("Depth Texture with cube render targets is not supported");if(t.bindFramebuffer(36160,e),!n.depthTexture||!n.depthTexture.isDepthTexture)throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");i.get(n.depthTexture).__webglTexture&&n.depthTexture.image.width===n.width&&n.depthTexture.image.height===n.height||(n.depthTexture.image.width=n.width,n.depthTexture.image.height=n.height,n.depthTexture.needsUpdate=!0),b(n.depthTexture,0);var r=i.get(n.depthTexture).__webglTexture;if(n.depthTexture.format===Bt)t.framebufferTexture2D(36160,36096,3553,r,0);else{if(n.depthTexture.format!==Ut)throw new Error("Unknown depthTexture format");t.framebufferTexture2D(36160,33306,3553,r,0)}}(n.__webglFramebuffer,e)}else if(r){n.__webglDepthbuffer=[];for(var a=0;a<6;a++)t.bindFramebuffer(36160,n.__webglFramebuffer[a]),n.__webglDepthbuffer[a]=t.createRenderbuffer(),A(n.__webglDepthbuffer[a],e)}else t.bindFramebuffer(36160,n.__webglFramebuffer),n.__webglDepthbuffer=t.createRenderbuffer(),A(n.__webglDepthbuffer,e);t.bindFramebuffer(36160,null)}function P(t){return r.isWebGL2&&t.isWebGLMultisampleRenderTarget?Math.min(r.maxSamples,t.samples):0}var R=!1,C=!1;this.allocateTextureUnit=function(){var t=x;return t>=r.maxTextures&&console.warn("THREE.WebGLTextures: Trying to use "+t+" texture units while this GPU supports only "+r.maxTextures),x+=1,t},this.resetTextureUnits=function(){x=0},this.setTexture2D=b,this.setTexture2DArray=function(t,e){var r=i.get(t);t.version>0&&r.__version!==t.version?E(r,t,e):(n.activeTexture(33984+e),n.bindTexture(35866,r.__webglTexture))},this.setTexture3D=function(t,e){var r=i.get(t);t.version>0&&r.__version!==t.version?E(r,t,e):(n.activeTexture(33984+e),n.bindTexture(32879,r.__webglTexture))},this.setTextureCube=w,this.setTextureCubeDynamic=_,this.setupRenderTarget=function(e){var s=i.get(e),c=i.get(e.texture);e.addEventListener("dispose",y),c.__webglTexture=t.createTexture(),o.memory.textures++;var h=!0===e.isWebGLRenderTargetCube,l=!0===e.isWebGLMultisampleRenderTarget,u=p(e)||r.isWebGL2;if(h){s.__webglFramebuffer=[];for(var g=0;g<6;g++)s.__webglFramebuffer[g]=t.createFramebuffer()}else if(s.__webglFramebuffer=t.createFramebuffer(),l)if(r.isWebGL2){s.__webglMultisampledFramebuffer=t.createFramebuffer(),s.__webglColorRenderbuffer=t.createRenderbuffer(),t.bindRenderbuffer(36161,s.__webglColorRenderbuffer);var v=m(a.convert(e.texture.format),a.convert(e.texture.type)),x=P(e);t.renderbufferStorageMultisample(36161,x,v,e.width,e.height),t.bindFramebuffer(36160,s.__webglMultisampledFramebuffer),t.framebufferRenderbuffer(36160,36064,36161,s.__webglColorRenderbuffer),t.bindRenderbuffer(36161,null),e.depthBuffer&&(s.__webglDepthRenderbuffer=t.createRenderbuffer(),A(s.__webglDepthRenderbuffer,e,!0)),t.bindFramebuffer(36160,null)}else console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.");if(h){for(n.bindTexture(34067,c.__webglTexture),M(34067,e.texture,u),g=0;g<6;g++)T(s.__webglFramebuffer[g],e,36064,34069+g);d(e.texture,u)&&f(34067,e.texture,e.width,e.height),n.bindTexture(34067,null)}else n.bindTexture(3553,c.__webglTexture),M(3553,e.texture,u),T(s.__webglFramebuffer,e,36064,3553),d(e.texture,u)&&f(3553,e.texture,e.width,e.height),n.bindTexture(3553,null);e.depthBuffer&&L(e)},this.updateRenderTargetMipmap=function(t){var e=t.texture;if(d(e,p(t)||r.isWebGL2)){var a=t.isWebGLRenderTargetCube?34067:3553,o=i.get(e).__webglTexture;n.bindTexture(a,o),f(a,e,t.width,t.height),n.bindTexture(a,null)}},this.updateMultisampleRenderTarget=function(e){if(e.isWebGLMultisampleRenderTarget)if(r.isWebGL2){var n=i.get(e);t.bindFramebuffer(36008,n.__webglMultisampledFramebuffer),t.bindFramebuffer(36009,n.__webglFramebuffer);var a=e.width,o=e.height,s=16384;e.depthBuffer&&(s|=256),e.stencilBuffer&&(s|=1024),t.blitFramebuffer(0,0,a,o,0,0,a,o,s,9728)}else console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.")},this.safeSetTexture2D=function(t,e){t&&t.isWebGLRenderTarget&&(!1===R&&(console.warn("THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead."),R=!0),t=t.texture),b(t,e)},this.safeSetTextureCube=function(t,e){t&&t.isWebGLRenderTargetCube&&(!1===C&&(console.warn("THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead."),C=!0),t=t.texture),t&&t.isCubeTexture||Array.isArray(t.image)&&6===t.image.length?w(t,e):_(t,e)}}function Xr(t,e,n){return{convert:function(t){var i;if(t===ut)return 10497;if(t===pt)return 33071;if(t===dt)return 33648;if(t===ft)return 9728;if(t===mt)return 9984;if(t===gt)return 9986;if(t===vt)return 9729;if(t===yt)return 9985;if(t===xt)return 9987;if(t===bt)return 5121;if(t===Lt)return 32819;if(t===Pt)return 32820;if(t===Rt)return 33635;if(t===wt)return 5120;if(t===_t)return 5122;if(t===Mt)return 5123;if(t===St)return 5124;if(t===Et)return 5125;if(t===Tt)return 5126;if(t===At){if(n.isWebGL2)return 5131;if(null!==(i=e.get("OES_texture_half_float")))return i.HALF_FLOAT_OES}if(t===Ot)return 6406;if(t===It)return 6407;if(t===Dt)return 6408;if(t===Nt)return 6409;if(t===zt)return 6410;if(t===Bt)return 6402;if(t===Ut)return 34041;if(t===Gt)return 6403;if(t===E)return 32774;if(t===T)return 32778;if(t===A)return 32779;if(t===R)return 0;if(t===C)return 1;if(t===O)return 768;if(t===I)return 769;if(t===D)return 770;if(t===N)return 771;if(t===z)return 772;if(t===B)return 773;if(t===U)return 774;if(t===G)return 775;if(t===F)return 776;if((t===Ft||t===Ht||t===kt||t===Vt)&&null!==(i=e.get("WEBGL_compressed_texture_s3tc"))){if(t===Ft)return i.COMPRESSED_RGB_S3TC_DXT1_EXT;if(t===Ht)return i.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(t===kt)return i.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(t===Vt)return i.COMPRESSED_RGBA_S3TC_DXT5_EXT}if((t===jt||t===Wt||t===qt||t===Xt)&&null!==(i=e.get("WEBGL_compressed_texture_pvrtc"))){if(t===jt)return i.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(t===Wt)return i.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(t===qt)return i.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(t===Xt)return i.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}if(t===Yt&&null!==(i=e.get("WEBGL_compressed_texture_etc1")))return i.COMPRESSED_RGB_ETC1_WEBGL;if((t===Jt||t===Zt||t===Qt||t===Kt||t===$t||t===te||t===ee||t===ne||t===ie||t===re||t===ae||t===oe||t===se||t===ce)&&null!==(i=e.get("WEBGL_compressed_texture_astc")))return t;if(t===L||t===P){if(n.isWebGL2){if(t===L)return 32775;if(t===P)return 32776}if(null!==(i=e.get("EXT_blend_minmax"))){if(t===L)return i.MIN_EXT;if(t===P)return i.MAX_EXT}}if(t===Ct){if(n.isWebGL2)return 34042;if(null!==(i=e.get("WEBGL_depth_texture")))return i.UNSIGNED_INT_24_8_WEBGL}return 0}}}function Yr(){En.call(this),this.type="Group"}function Jr(){En.call(this),this.type="Camera",this.matrixWorldInverse=new nn,this.projectionMatrix=new nn,this.projectionMatrixInverse=new nn}function Zr(t,e,n,i){Jr.call(this),this.type="PerspectiveCamera",this.fov=void 0!==t?t:50,this.zoom=1,this.near=void 0!==n?n:.1,this.far=void 0!==i?i:2e3,this.focus=10,this.aspect=void 0!==e?e:1,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}function Qr(t){Zr.call(this),this.cameras=t||[]}kr.prototype=Object.create(Jn.prototype),kr.prototype.constructor=kr,kr.prototype.isMeshDepthMaterial=!0,kr.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.depthPacking=t.depthPacking,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this},Vr.prototype=Object.create(Jn.prototype),Vr.prototype.constructor=Vr,Vr.prototype.isMeshDistanceMaterial=!0,Vr.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.referencePosition.copy(t.referencePosition),this.nearDistance=t.nearDistance,this.farDistance=t.farDistance,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this},Yr.prototype=Object.assign(Object.create(En.prototype),{constructor:Yr,isGroup:!0}),Jr.prototype=Object.assign(Object.create(En.prototype),{constructor:Jr,isCamera:!0,copy:function(t,e){return En.prototype.copy.call(this,t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this},getWorldDirection:function(t){void 0===t&&(console.warn("THREE.Camera: .getWorldDirection() target is now required"),t=new Le),this.updateMatrixWorld(!0);var e=this.matrixWorld.elements;return t.set(-e[8],-e[9],-e[10]).normalize()},updateMatrixWorld:function(t){En.prototype.updateMatrixWorld.call(this,t),this.matrixWorldInverse.getInverse(this.matrixWorld)},clone:function(){return(new this.constructor).copy(this)}}),Zr.prototype=Object.assign(Object.create(Jr.prototype),{constructor:Zr,isPerspectiveCamera:!0,copy:function(t,e){return Jr.prototype.copy.call(this,t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this},setFocalLength:function(t){var e=.5*this.getFilmHeight()/t;this.fov=2*Ee.RAD2DEG*Math.atan(e),this.updateProjectionMatrix()},getFocalLength:function(){var t=Math.tan(.5*Ee.DEG2RAD*this.fov);return.5*this.getFilmHeight()/t},getEffectiveFOV:function(){return 2*Ee.RAD2DEG*Math.atan(Math.tan(.5*Ee.DEG2RAD*this.fov)/this.zoom)},getFilmWidth:function(){return this.filmGauge*Math.min(this.aspect,1)},getFilmHeight:function(){return this.filmGauge/Math.max(this.aspect,1)},setViewOffset:function(t,e,n,i,r,a){this.aspect=t/e,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()},clearViewOffset:function(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()},updateProjectionMatrix:function(){var t=this.near,e=t*Math.tan(.5*Ee.DEG2RAD*this.fov)/this.zoom,n=2*e,i=this.aspect*n,r=-.5*i,a=this.view;if(null!==this.view&&this.view.enabled){var o=a.fullWidth,s=a.fullHeight;r+=a.offsetX*i/o,e-=a.offsetY*n/s,i*=a.width/o,n*=a.height/s}var c=this.filmOffset;0!==c&&(r+=t*c/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,e,e-n,t,this.far),this.projectionMatrixInverse.getInverse(this.projectionMatrix)},toJSON:function(t){var e=En.prototype.toJSON.call(this,t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}),Qr.prototype=Object.assign(Object.create(Zr.prototype),{constructor:Qr,isArrayCamera:!0});var Kr,$r,ta,ea,na,ia,ra=new Le,aa=new Le;function oa(t,e,n){ra.setFromMatrixPosition(e.matrixWorld),aa.setFromMatrixPosition(n.matrixWorld);var i=ra.distanceTo(aa),r=e.projectionMatrix.elements,a=n.projectionMatrix.elements,o=r[14]/(r[10]-1),s=r[14]/(r[10]+1),c=(r[9]+1)/r[5],h=(r[9]-1)/r[5],l=(r[8]-1)/r[0],u=(a[8]+1)/a[0],p=o*l,d=o*u,f=i/(-l+u),m=f*-l;e.matrixWorld.decompose(t.position,t.quaternion,t.scale),t.translateX(m),t.translateZ(f),t.matrixWorld.compose(t.position,t.quaternion,t.scale),t.matrixWorldInverse.getInverse(t.matrixWorld);var g=o+f,v=s+f,y=p-m,x=d+(i-m),b=c*s/v*g,w=h*s/v*g;t.projectionMatrix.makePerspective(y,x,b,w,g,v)}function sa(t){var e=this,n=null,i=null,r=null,a=[],o=new nn,s=new nn,c=1,h="stage";"undefined"!=typeof window&&"VRFrameData"in window&&(i=new window.VRFrameData,window.addEventListener("vrdisplaypresentchange",x,!1));var l=new nn,u=new Ae,p=new Le,d=new Zr;d.bounds=new Xe(0,0,.5,1),d.layers.enable(1);var f=new Zr;f.bounds=new Xe(.5,0,.5,1),f.layers.enable(2);var m=new Qr([d,f]);function g(){return null!==n&&!0===n.isPresenting}m.layers.enable(1),m.layers.enable(2);var v,y=new Te;function x(){if(g()){var i=n.getEyeParameters("left"),r=i.renderWidth*c,a=i.renderHeight*c;v=t.getPixelRatio(),t.getSize(y),t.setDrawingBufferSize(2*r,a,1),_.start()}else e.enabled&&t.setDrawingBufferSize(y.width,y.height,v),_.stop()}var b=[];function w(t){for(var e=navigator.getGamepads&&navigator.getGamepads(),n=0,i=0,r=e.length;n=0){var c=i[o];if(void 0!==c){var h=c.normalized,l=c.itemSize,u=w.get(c);if(void 0===u)continue;var p=u.buffer,f=u.type,y=u.bytesPerElement;if(c.isInterleavedBufferAttribute){var x=c.data,b=x.stride,_=c.offset;x&&x.isInstancedInterleavedBuffer?(v.enableAttributeAndDivisor(s,x.meshPerAttribute),void 0===n.maxInstancedCount&&(n.maxInstancedCount=x.meshPerAttribute*x.count)):v.enableAttribute(s),d.bindBuffer(34962,p),d.vertexAttribPointer(s,l,f,h,b*y,_*y)}else c.isInstancedBufferAttribute?(v.enableAttributeAndDivisor(s,c.meshPerAttribute),void 0===n.maxInstancedCount&&(n.maxInstancedCount=c.meshPerAttribute*c.count)):v.enableAttribute(s),d.bindBuffer(34962,p),d.vertexAttribPointer(s,l,f,h,0,0)}else if(void 0!==a){var M=a[o];if(void 0!==M)switch(M.length){case 2:d.vertexAttrib2fv(s,M);break;case 3:d.vertexAttrib3fv(s,M);break;case 4:d.vertexAttrib4fv(s,M);break;default:d.vertexAttrib1fv(s,M)}}}}v.disableUnusedAttributes()}(i,s,n),null!==l&&d.bindBuffer(34963,h.buffer));var y=1/0;null!==l?y=l.count:void 0!==u&&(y=u.count);var x=n.drawRange.start*p,b=n.drawRange.count*p,M=null!==a?a.start*p:0,S=null!==a?a.count*p:1/0,E=Math.max(x,M),T=Math.min(y,x+b,M+S)-1,A=Math.max(0,T-E+1);if(0!==A){if(r.isMesh)if(!0===i.wireframe)v.setLineWidth(i.wireframeLinewidth*it()),f.setMode(1);else switch(r.drawMode){case ue:f.setMode(4);break;case pe:f.setMode(5);break;case de:f.setMode(6)}else if(r.isLine){var C=i.linewidth;void 0===C&&(C=1),v.setLineWidth(C*it()),r.isLineSegments?f.setMode(1):r.isLineLoop?f.setMode(2):f.setMode(3)}else r.isPoints?f.setMode(0):r.isSprite&&f.setMode(4);n&&n.isInstancedBufferGeometry?n.maxInstancedCount>0&&f.renderInstances(n,E,A):f.render(E,A)}},this.compile=function(t,e){(p=T.get(t,e)).init(),t.traverse(function(t){t.isLight&&(p.pushLight(t),t.castShadow&&p.pushShadow(t))}),p.setupLights(e),t.traverse(function(e){if(e.material)if(Array.isArray(e.material))for(var n=0;n=0&&t.numSupportedMorphTargets++}if(t.morphNormals){t.numSupportedMorphNormals=0;for(m=0;m=0&&t.numSupportedMorphNormals++}var g=i.shader.uniforms;(t.isShaderMaterial||t.isRawShaderMaterial)&&!0!==t.clipping||(i.numClippingPlanes=Q.numPlanes,i.numIntersection=Q.numIntersection,g.clippingPlanes=Q.uniform),i.fog=e,void 0===o&&(i.lightsHash=o={}),o.stateID=s.stateID,o.directionalLength=s.directionalLength,o.pointLength=s.pointLength,o.spotLength=s.spotLength,o.rectAreaLength=s.rectAreaLength,o.hemiLength=s.hemiLength,o.shadowsLength=s.shadowsLength,t.lights&&(g.ambientLightColor.value=r.state.ambient,g.lightProbe.value=r.state.probe,g.directionalLights.value=r.state.directional,g.spotLights.value=r.state.spot,g.rectAreaLights.value=r.state.rectArea,g.pointLights.value=r.state.point,g.hemisphereLights.value=r.state.hemi,g.directionalShadowMap.value=r.state.directionalShadowMap,g.directionalShadowMatrix.value=r.state.directionalShadowMatrix,g.spotShadowMap.value=r.state.spotShadowMap,g.spotShadowMatrix.value=r.state.spotShadowMatrix,g.pointShadowMap.value=r.state.pointShadowMap,g.pointShadowMatrix.value=r.state.pointShadowMatrix);var v=i.program.getUniforms(),y=xr.seqWithValue(v.seq,g);i.uniformsList=y}function vt(t,e,n,i){b.resetTextureUnits();var r=x.get(n),a=p.state.lights,o=r.lightsHash,s=a.state.hash;if(K&&(tt||t!==G)){var c=t===G&&n.id===B;Q.setState(n.clippingPlanes,n.clipIntersection,n.clipShadows,t,r,c)}!1===n.needsUpdate&&(void 0===r.program?n.needsUpdate=!0:n.fog&&r.fog!==e?n.needsUpdate=!0:(!n.lights||o.stateID===s.stateID&&o.directionalLength===s.directionalLength&&o.pointLength===s.pointLength&&o.spotLength===s.spotLength&&o.rectAreaLength===s.rectAreaLength&&o.hemiLength===s.hemiLength&&o.shadowsLength===s.shadowsLength)&&(void 0===r.numClippingPlanes||r.numClippingPlanes===Q.numPlanes&&r.numIntersection===Q.numIntersection)||(n.needsUpdate=!0)),n.needsUpdate&&(gt(n,e,i),n.needsUpdate=!1);var h,l,u=!1,m=!1,y=!1,w=r.program,_=w.getUniforms(),M=r.shader.uniforms;if(v.useProgram(w.program)&&(u=!0,m=!0,y=!0),n.id!==B&&(B=n.id,m=!0),u||G!==t){if(_.setValue(d,"projectionMatrix",t.projectionMatrix),g.logarithmicDepthBuffer&&_.setValue(d,"logDepthBufFC",2/(Math.log(t.far+1)/Math.LN2)),G!==t&&(G=t,m=!0,y=!0),n.isShaderMaterial||n.isMeshPhongMaterial||n.isMeshStandardMaterial||n.envMap){var S=_.map.cameraPosition;void 0!==S&&S.setValue(d,nt.setFromMatrixPosition(t.matrixWorld))}(n.isMeshPhongMaterial||n.isMeshLambertMaterial||n.isMeshBasicMaterial||n.isMeshStandardMaterial||n.isShaderMaterial||n.skinning)&&_.setValue(d,"viewMatrix",t.matrixWorldInverse)}if(n.skinning){_.setOptional(d,i,"bindMatrix"),_.setOptional(d,i,"bindMatrixInverse");var E=i.skeleton;if(E){var T=E.bones;if(g.floatVertexTextures){if(void 0===E.boneTexture){var A=Math.sqrt(4*T.length);A=Ee.ceilPowerOfTwo(A),A=Math.max(A,4);var L=new Float32Array(A*A*4);L.set(E.boneMatrices);var P=new Qe(L,A,A,Dt,Tt);P.needsUpdate=!0,E.boneMatrices=L,E.boneTexture=P,E.boneTextureSize=A}_.setValue(d,"boneTexture",E.boneTexture,b),_.setValue(d,"boneTextureSize",E.boneTextureSize)}else _.setOptional(d,E,"boneMatrices")}}return m&&(_.setValue(d,"toneMappingExposure",O.toneMappingExposure),_.setValue(d,"toneMappingWhitePoint",O.toneMappingWhitePoint),n.lights&&(l=y,(h=M).ambientLightColor.needsUpdate=l,h.lightProbe.needsUpdate=l,h.directionalLights.needsUpdate=l,h.pointLights.needsUpdate=l,h.spotLights.needsUpdate=l,h.rectAreaLights.needsUpdate=l,h.hemisphereLights.needsUpdate=l),e&&n.fog&&function(t,e){t.fogColor.value.copy(e.color),e.isFog?(t.fogNear.value=e.near,t.fogFar.value=e.far):e.isFogExp2&&(t.fogDensity.value=e.density)}(M,e),n.isMeshBasicMaterial?yt(M,n):n.isMeshLambertMaterial?(yt(M,n),function(t,e){e.emissiveMap&&(t.emissiveMap.value=e.emissiveMap)}(M,n)):n.isMeshPhongMaterial?(yt(M,n),n.isMeshToonMaterial?function(t,e){xt(t,e),e.gradientMap&&(t.gradientMap.value=e.gradientMap)}(M,n):xt(M,n)):n.isMeshStandardMaterial?(yt(M,n),n.isMeshPhysicalMaterial?function(t,e){wt(t,e),t.reflectivity.value=e.reflectivity,t.clearCoat.value=e.clearCoat,t.clearCoatRoughness.value=e.clearCoatRoughness}(M,n):wt(M,n)):n.isMeshMatcapMaterial?(yt(M,n),function(t,e){e.matcap&&(t.matcap.value=e.matcap);e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,e.side===f&&(t.bumpScale.value*=-1));e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),e.side===f&&t.normalScale.value.negate());e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(M,n)):n.isMeshDepthMaterial?(yt(M,n),function(t,e){e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(M,n)):n.isMeshDistanceMaterial?(yt(M,n),function(t,e){e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias);t.referencePosition.value.copy(e.referencePosition),t.nearDistance.value=e.nearDistance,t.farDistance.value=e.farDistance}(M,n)):n.isMeshNormalMaterial?(yt(M,n),function(t,e){e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,e.side===f&&(t.bumpScale.value*=-1));e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),e.side===f&&t.normalScale.value.negate());e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(M,n)):n.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity}(M,n),n.isLineDashedMaterial&&function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(M,n)):n.isPointsMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*q,t.scale.value=.5*W,t.map.value=e.map,null!==e.map&&(!0===e.map.matrixAutoUpdate&&e.map.updateMatrix(),t.uvTransform.value.copy(e.map.matrix))}(M,n):n.isSpriteMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.rotation.value=e.rotation,t.map.value=e.map,null!==e.map&&(!0===e.map.matrixAutoUpdate&&e.map.updateMatrix(),t.uvTransform.value.copy(e.map.matrix))}(M,n):n.isShadowMaterial&&(M.color.value.copy(n.color),M.opacity.value=n.opacity),void 0!==M.ltc_1&&(M.ltc_1.value=dn.LTC_1),void 0!==M.ltc_2&&(M.ltc_2.value=dn.LTC_2),xr.upload(d,r.uniformsList,M,b)),n.isShaderMaterial&&!0===n.uniformsNeedUpdate&&(xr.upload(d,r.uniformsList,M,b),n.uniformsNeedUpdate=!1),n.isSpriteMaterial&&_.setValue(d,"center",i.center),_.setValue(d,"modelViewMatrix",i.modelViewMatrix),_.setValue(d,"normalMatrix",i.normalMatrix),_.setValue(d,"modelMatrix",i.matrixWorld),w}function yt(t,e){var n;t.opacity.value=e.opacity,e.color&&t.diffuse.value.copy(e.color),e.emissive&&t.emissive.value.copy(e.emissive).multiplyScalar(e.emissiveIntensity),e.map&&(t.map.value=e.map),e.alphaMap&&(t.alphaMap.value=e.alphaMap),e.specularMap&&(t.specularMap.value=e.specularMap),e.envMap&&(t.envMap.value=e.envMap,t.flipEnvMap.value=e.envMap.isCubeTexture?-1:1,t.reflectivity.value=e.reflectivity,t.refractionRatio.value=e.refractionRatio,t.maxMipLevel.value=x.get(e.envMap).__maxMipLevel),e.lightMap&&(t.lightMap.value=e.lightMap,t.lightMapIntensity.value=e.lightMapIntensity),e.aoMap&&(t.aoMap.value=e.aoMap,t.aoMapIntensity.value=e.aoMapIntensity),e.map?n=e.map:e.specularMap?n=e.specularMap:e.displacementMap?n=e.displacementMap:e.normalMap?n=e.normalMap:e.bumpMap?n=e.bumpMap:e.roughnessMap?n=e.roughnessMap:e.metalnessMap?n=e.metalnessMap:e.alphaMap?n=e.alphaMap:e.emissiveMap&&(n=e.emissiveMap),void 0!==n&&(n.isWebGLRenderTarget&&(n=n.texture),!0===n.matrixAutoUpdate&&n.updateMatrix(),t.uvTransform.value.copy(n.matrix))}function xt(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4),e.emissiveMap&&(t.emissiveMap.value=e.emissiveMap),e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,e.side===f&&(t.bumpScale.value*=-1)),e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),e.side===f&&t.normalScale.value.negate()),e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}function wt(t,e){t.roughness.value=e.roughness,t.metalness.value=e.metalness,e.roughnessMap&&(t.roughnessMap.value=e.roughnessMap),e.metalnessMap&&(t.metalnessMap.value=e.metalnessMap),e.emissiveMap&&(t.emissiveMap.value=e.emissiveMap),e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,e.side===f&&(t.bumpScale.value*=-1)),e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),e.side===f&&t.normalScale.value.negate()),e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias),e.envMap&&(t.envMapIntensity.value=e.envMapIntensity)}dt.setAnimationLoop(function(t){ot.isPresenting()||pt&&pt(t)}),"undefined"!=typeof window&&dt.setContext(window),this.setAnimationLoop=function(t){pt=t,ot.setAnimationLoop(t),dt.start()},this.render=function(t,e){var n,i;if(void 0!==arguments[2]&&(console.warn("THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead."),n=arguments[2]),void 0!==arguments[3]&&(console.warn("THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead."),i=arguments[3]),e&&e.isCamera){if(!I){U.geometry=null,U.program=null,U.wireframe=!1,B=-1,G=null,!0===t.autoUpdate&&t.updateMatrixWorld(),null===e.parent&&e.updateMatrixWorld(),ot.enabled&&(e=ot.getCamera(e)),(p=T.get(t,e)).init(),t.onBeforeRender(O,t,e,n||N),et.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),Z.setFromMatrix(et),tt=this.localClippingEnabled,K=Q.init(this.clippingPlanes,tt,e),(u=E.get(t,e)).init(),function t(e,n,i,r){if(!1===e.visible)return;var a=e.layers.test(n.layers);if(a)if(e.isGroup)i=e.renderOrder;else if(e.isLight)p.pushLight(e),e.castShadow&&p.pushShadow(e);else if(e.isSprite){if(!e.frustumCulled||Z.intersectsSprite(e)){r&&nt.setFromMatrixPosition(e.matrixWorld).applyMatrix4(et);var o=M.update(e),s=e.material;s.visible&&u.push(e,o,s,i,nt.z,null)}}else if(e.isImmediateRenderObject)r&&nt.setFromMatrixPosition(e.matrixWorld).applyMatrix4(et),u.push(e,null,e.material,i,nt.z,null);else if((e.isMesh||e.isLine||e.isPoints)&&(e.isSkinnedMesh&&e.skeleton.update(),!e.frustumCulled||Z.intersectsObject(e))){r&&nt.setFromMatrixPosition(e.matrixWorld).applyMatrix4(et);var o=M.update(e),s=e.material;if(Array.isArray(s))for(var c=o.groups,h=0,l=c.length;h=0&&e<=t.width-i&&n>=0&&n<=t.height-r&&d.readPixels(e,n,i,r,C.convert(h),C.convert(l),a):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{s&&d.bindFramebuffer(36160,z)}}}else console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.")},this.copyFramebufferToTexture=function(t,e,n){var i=e.image.width,r=e.image.height,a=C.convert(e.format);b.setTexture2D(e,0),d.copyTexImage2D(3553,n||0,a,t.x,t.y,i,r,0)},this.copyTextureToTexture=function(t,e,n,i){var r=e.image.width,a=e.image.height,o=C.convert(n.format),s=C.convert(n.type);b.setTexture2D(n,0),e.isDataTexture?d.texSubImage2D(3553,i||0,t.x,t.y,r,a,o,s,e.image.data):d.texSubImage2D(3553,i||0,t.x,t.y,o,s,e.image)}}function la(t,e){this.name="",this.color=new un(t),this.density=void 0!==e?e:25e-5}function ua(t,e,n){this.name="",this.color=new un(t),this.near=void 0!==e?e:1,this.far=void 0!==n?n:1e3}function pa(){En.call(this),this.type="Scene",this.background=null,this.fog=null,this.overrideMaterial=null,this.autoUpdate=!0}function da(t,e){this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.dynamic=!1,this.updateRange={offset:0,count:-1},this.version=0}function fa(t,e,n,i){this.data=t,this.itemSize=e,this.offset=n,this.normalized=!0===i}function ma(t){Jn.call(this),this.type="SpriteMaterial",this.color=new un(16777215),this.map=null,this.rotation=0,this.sizeAttenuation=!0,this.lights=!1,this.transparent=!0,this.setValues(t)}function ga(t){if(En.call(this),this.type="Sprite",void 0===Kr){Kr=new Vn;var e=new da(new Float32Array([-.5,-.5,0,0,0,.5,-.5,0,1,0,.5,.5,0,1,1,-.5,.5,0,0,1]),5);Kr.setIndex([0,1,2,0,2,3]),Kr.addAttribute("position",new fa(e,3,0,!1)),Kr.addAttribute("uv",new fa(e,2,3,!1))}this.geometry=Kr,this.material=void 0!==t?t:new ma,this.center=new Te(.5,.5)}function va(){En.call(this),this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]}})}function ya(t,e){t&&t.isGeometry&&console.error("THREE.SkinnedMesh no longer supports THREE.Geometry. Use THREE.BufferGeometry instead."),fi.call(this,t,e),this.type="SkinnedMesh",this.bindMode="attached",this.bindMatrix=new nn,this.bindMatrixInverse=new nn}function xa(t,e){if(t=t||[],this.bones=t.slice(0),this.boneMatrices=new Float32Array(16*this.bones.length),void 0===e)this.calculateInverses();else if(this.bones.length===e.length)this.boneInverses=e.slice(0);else{console.warn("THREE.Skeleton boneInverses is the wrong length."),this.boneInverses=[];for(var n=0,i=this.bones.length;n=0?(t(g-1e-5,m,u),p.subVectors(l,u)):(t(g+1e-5,m,u),p.subVectors(u,l)),m-1e-5>=0?(t(g,m-1e-5,u),d.subVectors(l,u)):(t(g,m+1e-5,u),d.subVectors(u,l)),h.crossVectors(p,d).normalize(),s.push(h.x,h.y,h.z),c.push(g,m)}}for(i=0;i.9&&o<.1&&(e<.2&&(a[t+0]+=1),n<.2&&(a[t+2]+=1),i<.2&&(a[t+4]+=1))}}()}(),this.addAttribute("position",new Un(r,3)),this.addAttribute("normal",new Un(r.slice(),3)),this.addAttribute("uv",new Un(a,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}function za(t,e){Pn.call(this),this.type="TetrahedronGeometry",this.parameters={radius:t,detail:e},this.fromBufferGeometry(new Ba(t,e)),this.mergeVertices()}function Ba(t,e){Na.call(this,[1,1,1,-1,-1,1,-1,1,-1,1,-1,-1],[2,1,0,0,3,2,1,3,0,2,3,1],t,e),this.type="TetrahedronBufferGeometry",this.parameters={radius:t,detail:e}}function Ua(t,e){Pn.call(this),this.type="OctahedronGeometry",this.parameters={radius:t,detail:e},this.fromBufferGeometry(new Ga(t,e)),this.mergeVertices()}function Ga(t,e){Na.call(this,[1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1],[0,2,4,0,4,3,0,3,5,0,5,2,1,2,5,1,5,3,1,3,4,1,4,2],t,e),this.type="OctahedronBufferGeometry",this.parameters={radius:t,detail:e}}function Fa(t,e){Pn.call(this),this.type="IcosahedronGeometry",this.parameters={radius:t,detail:e},this.fromBufferGeometry(new Ha(t,e)),this.mergeVertices()}function Ha(t,e){var n=(1+Math.sqrt(5))/2,i=[-1,n,0,1,n,0,-1,-n,0,1,-n,0,0,-1,n,0,1,n,0,-1,-n,0,1,-n,n,0,-1,n,0,1,-n,0,-1,-n,0,1];Na.call(this,i,[0,11,5,0,5,1,0,1,7,0,7,10,0,10,11,1,5,9,5,11,4,11,10,2,10,7,6,7,1,8,3,9,4,3,4,2,3,2,6,3,6,8,3,8,9,4,9,5,2,4,11,6,2,10,8,6,7,9,8,1],t,e),this.type="IcosahedronBufferGeometry",this.parameters={radius:t,detail:e}}function ka(t,e){Pn.call(this),this.type="DodecahedronGeometry",this.parameters={radius:t,detail:e},this.fromBufferGeometry(new Va(t,e)),this.mergeVertices()}function Va(t,e){var n=(1+Math.sqrt(5))/2,i=1/n,r=[-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-i,-n,0,-i,n,0,i,-n,0,i,n,-i,-n,0,-i,n,0,i,-n,0,i,n,0,-n,0,-i,n,0,-i,-n,0,i,n,0,i];Na.call(this,r,[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type="DodecahedronBufferGeometry",this.parameters={radius:t,detail:e}}function ja(t,e,n,i,r,a){Pn.call(this),this.type="TubeGeometry",this.parameters={path:t,tubularSegments:e,radius:n,radialSegments:i,closed:r},void 0!==a&&console.warn("THREE.TubeGeometry: taper has been removed.");var o=new Wa(t,e,n,i,r);this.tangents=o.tangents,this.normals=o.normals,this.binormals=o.binormals,this.fromBufferGeometry(o),this.mergeVertices()}function Wa(t,e,n,i,r){Vn.call(this),this.type="TubeBufferGeometry",this.parameters={path:t,tubularSegments:e,radius:n,radialSegments:i,closed:r},e=e||64,n=n||1,i=i||8,r=r||!1;var a=t.computeFrenetFrames(e,r);this.tangents=a.tangents,this.normals=a.normals,this.binormals=a.binormals;var o,s,c=new Le,h=new Le,l=new Te,u=new Le,p=[],d=[],f=[],m=[];function g(r){u=t.getPointAt(r/e,u);var o=a.normals[r],l=a.binormals[r];for(s=0;s<=i;s++){var f=s/i*Math.PI*2,m=Math.sin(f),g=-Math.cos(f);h.x=g*o.x+m*l.x,h.y=g*o.y+m*l.y,h.z=g*o.z+m*l.z,h.normalize(),d.push(h.x,h.y,h.z),c.x=u.x+n*h.x,c.y=u.y+n*h.y,c.z=u.z+n*h.z,p.push(c.x,c.y,c.z)}}!function(){for(o=0;oi.far||r.push({distance:y,point:t.clone(),uv:pi.getUV(t,o,s,c,h,l,u,new Te),face:null,object:this})}}}(),clone:function(){return new this.constructor(this.material).copy(this)},copy:function(t){return En.prototype.copy.call(this,t),void 0!==t.center&&this.center.copy(t.center),this}}),va.prototype=Object.assign(Object.create(En.prototype),{constructor:va,isLOD:!0,copy:function(t){En.prototype.copy.call(this,t,!1);for(var e=t.levels,n=0,i=e.length;n1){t.setFromMatrixPosition(n.matrixWorld),e.setFromMatrixPosition(this.matrixWorld);var r=t.distanceTo(e);i[0].object.visible=!0;for(var a=1,o=i.length;a=i[a].distance;a++)i[a-1].object.visible=!1,i[a].object.visible=!0;for(;ah))d.applyMatrix4(this.matrixWorld),(S=i.ray.origin.distanceTo(d))i.far||r.push({distance:S,point:p.clone().applyMatrix4(this.matrixWorld),index:y,face:null,faceIndex:null,object:this})}else for(y=0,x=g.length/3-1;yh))d.applyMatrix4(this.matrixWorld),(S=i.ray.origin.distanceTo(d))i.far||r.push({distance:S,point:p.clone().applyMatrix4(this.matrixWorld),index:y,face:null,faceIndex:null,object:this})}}else if(o.isGeometry){var _=o.vertices,M=_.length;for(y=0;yh))d.applyMatrix4(this.matrixWorld),(S=i.ray.origin.distanceTo(d))i.far||r.push({distance:S,point:p.clone().applyMatrix4(this.matrixWorld),index:y,face:null,faceIndex:null,object:this})}}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),Ma.prototype=Object.assign(Object.create(_a.prototype),{constructor:Ma,isLineSegments:!0,computeLineDistances:function(){var t=new Le,e=new Le;return function(){var n=this.geometry;if(n.isBufferGeometry)if(null===n.index){for(var i=n.attributes.position,r=[],a=0,o=i.count;ai.far)return;r.push({distance:c,distanceToRay:Math.sqrt(o),point:p.clone(),index:n,face:null,object:a})}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),Aa.prototype=Object.assign(Object.create(qe.prototype),{constructor:Aa,isVideoTexture:!0,update:function(){var t=this.image;t.readyState>=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}),La.prototype=Object.create(qe.prototype),La.prototype.constructor=La,La.prototype.isCompressedTexture=!0,Pa.prototype=Object.create(qe.prototype),Pa.prototype.constructor=Pa,Pa.prototype.isCanvasTexture=!0,Ra.prototype=Object.create(qe.prototype),Ra.prototype.constructor=Ra,Ra.prototype.isDepthTexture=!0,Ca.prototype=Object.create(Vn.prototype),Ca.prototype.constructor=Ca,Oa.prototype=Object.create(Pn.prototype),Oa.prototype.constructor=Oa,Ia.prototype=Object.create(Vn.prototype),Ia.prototype.constructor=Ia,Da.prototype=Object.create(Pn.prototype),Da.prototype.constructor=Da,Na.prototype=Object.create(Vn.prototype),Na.prototype.constructor=Na,za.prototype=Object.create(Pn.prototype),za.prototype.constructor=za,Ba.prototype=Object.create(Na.prototype),Ba.prototype.constructor=Ba,Ua.prototype=Object.create(Pn.prototype),Ua.prototype.constructor=Ua,Ga.prototype=Object.create(Na.prototype),Ga.prototype.constructor=Ga,Fa.prototype=Object.create(Pn.prototype),Fa.prototype.constructor=Fa,Ha.prototype=Object.create(Na.prototype),Ha.prototype.constructor=Ha,ka.prototype=Object.create(Pn.prototype),ka.prototype.constructor=ka,Va.prototype=Object.create(Na.prototype),Va.prototype.constructor=Va,ja.prototype=Object.create(Pn.prototype),ja.prototype.constructor=ja,Wa.prototype=Object.create(Vn.prototype),Wa.prototype.constructor=Wa,Wa.prototype.toJSON=function(){var t=Vn.prototype.toJSON.call(this);return t.path=this.parameters.path.toJSON(),t},qa.prototype=Object.create(Pn.prototype),qa.prototype.constructor=qa,Xa.prototype=Object.create(Vn.prototype),Xa.prototype.constructor=Xa,Ya.prototype=Object.create(Pn.prototype),Ya.prototype.constructor=Ya,Ja.prototype=Object.create(Vn.prototype),Ja.prototype.constructor=Ja;var Za=function(t,e,n){n=n||2;var i,r,a,o,s,c,h,l=e&&e.length,u=l?e[0]*n:t.length,p=Qa(t,0,u,n,!0),d=[];if(!p)return d;if(l&&(p=function(t,e,n,i){var r,a,o,s,c,h=[];for(r=0,a=e.length;r80*n){i=a=t[0],r=o=t[1];for(var f=n;fa&&(a=s),c>o&&(o=c);h=0!==(h=Math.max(a-i,o-r))?1/h:0}return $a(p,d,n,i,r,h),d};function Qa(t,e,n,i,r){var a,o;if(r===function(t,e,n,i){for(var r=0,a=e,o=n-i;a0)for(a=e;a=e;a-=i)o=go(a,t[a],t[a+1],o);return o&&uo(o,o.next)&&(vo(o),o=o.next),o}function Ka(t,e){if(!t)return t;e||(e=t);var n,i=t;do{if(n=!1,i.steiner||!uo(i,i.next)&&0!==lo(i.prev,i,i.next))i=i.next;else{if(vo(i),(i=e=i.prev)===i.next)break;n=!0}}while(n||i!==e);return e}function $a(t,e,n,i,r,a,o){if(t){!o&&a&&function(t,e,n,i){var r=t;do{null===r.z&&(r.z=oo(r.x,r.y,e,n,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){var e,n,i,r,a,o,s,c,h=1;do{for(n=t,t=null,a=null,o=0;n;){for(o++,i=n,s=0,e=0;e0||c>0&&i;)0!==s&&(0===c||!i||n.z<=i.z)?(r=n,n=n.nextZ,s--):(r=i,i=i.nextZ,c--),a?a.nextZ=r:t=r,r.prevZ=a,a=r;n=i}a.nextZ=null,h*=2}while(o>1)}(r)}(t,i,r,a);for(var s,c,h=t;t.prev!==t.next;)if(s=t.prev,c=t.next,a?eo(t,i,r,a):to(t))e.push(s.i/n),e.push(t.i/n),e.push(c.i/n),vo(t),t=c.next,h=c.next;else if((t=c)===h){o?1===o?$a(t=no(t,e,n),e,n,i,r,a,2):2===o&&io(t,e,n,i,r,a):$a(Ka(t),e,n,i,r,a,1);break}}}function to(t){var e=t.prev,n=t,i=t.next;if(lo(e,n,i)>=0)return!1;for(var r=t.next.next;r!==t.prev;){if(co(e.x,e.y,n.x,n.y,i.x,i.y,r.x,r.y)&&lo(r.prev,r,r.next)>=0)return!1;r=r.next}return!0}function eo(t,e,n,i){var r=t.prev,a=t,o=t.next;if(lo(r,a,o)>=0)return!1;for(var s=r.xa.x?r.x>o.x?r.x:o.x:a.x>o.x?a.x:o.x,l=r.y>a.y?r.y>o.y?r.y:o.y:a.y>o.y?a.y:o.y,u=oo(s,c,e,n,i),p=oo(h,l,e,n,i),d=t.nextZ;d&&d.z<=p;){if(d!==t.prev&&d!==t.next&&co(r.x,r.y,a.x,a.y,o.x,o.y,d.x,d.y)&&lo(d.prev,d,d.next)>=0)return!1;d=d.nextZ}for(d=t.prevZ;d&&d.z>=u;){if(d!==t.prev&&d!==t.next&&co(r.x,r.y,a.x,a.y,o.x,o.y,d.x,d.y)&&lo(d.prev,d,d.next)>=0)return!1;d=d.prevZ}return!0}function no(t,e,n){var i=t;do{var r=i.prev,a=i.next.next;!uo(r,a)&&po(r,i,i.next,a)&&fo(r,a)&&fo(a,r)&&(e.push(r.i/n),e.push(i.i/n),e.push(a.i/n),vo(i),vo(i.next),i=t=a),i=i.next}while(i!==t);return i}function io(t,e,n,i,r,a){var o=t;do{for(var s=o.next.next;s!==o.prev;){if(o.i!==s.i&&ho(o,s)){var c=mo(o,s);return o=Ka(o,o.next),c=Ka(c,c.next),$a(o,e,n,i,r,a),void $a(c,e,n,i,r,a)}s=s.next}o=o.next}while(o!==t)}function ro(t,e){return t.x-e.x}function ao(t,e){if(e=function(t,e){var n,i=e,r=t.x,a=t.y,o=-1/0;do{if(a<=i.y&&a>=i.next.y&&i.next.y!==i.y){var s=i.x+(a-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(s<=r&&s>o){if(o=s,s===r){if(a===i.y)return i;if(a===i.next.y)return i.next}n=i.x=i.x&&i.x>=l&&r!==i.x&&co(an.x)&&fo(i,t)&&(n=i,p=c),i=i.next;return n}(t,e)){var n=mo(e,t);Ka(n,n.next)}}function oo(t,e,n,i,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-n)*r)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-i)*r)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function so(t){var e=t,n=t;do{e.x=0&&(t-o)*(i-s)-(n-o)*(e-s)>=0&&(n-o)*(a-s)-(r-o)*(i-s)>=0}function ho(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){var n=t;do{if(n.i!==t.i&&n.next.i!==t.i&&n.i!==e.i&&n.next.i!==e.i&&po(n,n.next,t,e))return!0;n=n.next}while(n!==t);return!1}(t,e)&&fo(t,e)&&fo(e,t)&&function(t,e){var n=t,i=!1,r=(t.x+e.x)/2,a=(t.y+e.y)/2;do{n.y>a!=n.next.y>a&&n.next.y!==n.y&&r<(n.next.x-n.x)*(a-n.y)/(n.next.y-n.y)+n.x&&(i=!i),n=n.next}while(n!==t);return i}(t,e)}function lo(t,e,n){return(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y)}function uo(t,e){return t.x===e.x&&t.y===e.y}function po(t,e,n,i){return!!(uo(t,e)&&uo(n,i)||uo(t,i)&&uo(n,e))||lo(t,e,n)>0!=lo(t,e,i)>0&&lo(n,i,t)>0!=lo(n,i,e)>0}function fo(t,e){return lo(t.prev,t,t.next)<0?lo(t,e,t.next)>=0&&lo(t,t.prev,e)>=0:lo(t,e,t.prev)<0||lo(t,t.next,e)<0}function mo(t,e){var n=new yo(t.i,t.x,t.y),i=new yo(e.i,e.x,e.y),r=t.next,a=e.prev;return t.next=e,e.prev=t,n.next=r,r.prev=n,i.next=n,n.prev=i,a.next=i,i.prev=a,i}function go(t,e,n,i){var r=new yo(t,e,n);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function vo(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function yo(t,e,n){this.i=t,this.x=e,this.y=n,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}var xo={area:function(t){for(var e=t.length,n=0,i=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function wo(t,e){for(var n=0;nNumber.EPSILON){var p=Math.sqrt(l),d=Math.sqrt(c*c+h*h),f=e.x-s/p,m=e.y+o/p,g=((n.x-h/d-f)*h-(n.y+c/d-m)*c)/(o*h-s*c),v=(i=f+o*g-t.x)*i+(r=m+s*g-t.y)*r;if(v<=2)return new Te(i,r);a=Math.sqrt(v/2)}else{var y=!1;o>Number.EPSILON?c>Number.EPSILON&&(y=!0):o<-Number.EPSILON?c<-Number.EPSILON&&(y=!0):Math.sign(s)===Math.sign(h)&&(y=!0),y?(i=-s,r=o,a=Math.sqrt(l)):(i=o,r=s,a=Math.sqrt(l/2))}return new Te(i/a,r/a)}for(var F=[],H=0,k=P.length,V=k-1,j=H+1;H=0;C--){for(I=C/d,D=l*Math.cos(I*Math.PI/2),O=u*Math.sin(I*Math.PI/2)+p,H=0,k=P.length;H=0;){n=H,(i=H-1)<0&&(i=t.length-1);var r=0,a=s+2*d;for(r=0;r0)&&f.push(_,M,E),(c!==n-1||h0&&v(!0),e>0&&v(!1)),this.setIndex(h),this.addAttribute("position",new Un(l,3)),this.addAttribute("normal",new Un(u,3)),this.addAttribute("uv",new Un(p,2))}function Fo(t,e,n,i,r,a,o){Uo.call(this,0,t,e,n,i,r,a,o),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:n,heightSegments:i,openEnded:r,thetaStart:a,thetaLength:o}}function Ho(t,e,n,i,r,a,o){Go.call(this,0,t,e,n,i,r,a,o),this.type="ConeBufferGeometry",this.parameters={radius:t,height:e,radialSegments:n,heightSegments:i,openEnded:r,thetaStart:a,thetaLength:o}}function ko(t,e,n,i){Pn.call(this),this.type="CircleGeometry",this.parameters={radius:t,segments:e,thetaStart:n,thetaLength:i},this.fromBufferGeometry(new Vo(t,e,n,i)),this.mergeVertices()}function Vo(t,e,n,i){Vn.call(this),this.type="CircleBufferGeometry",this.parameters={radius:t,segments:e,thetaStart:n,thetaLength:i},t=t||1,e=void 0!==e?Math.max(3,e):8,n=void 0!==n?n:0,i=void 0!==i?i:2*Math.PI;var r,a,o=[],s=[],c=[],h=[],l=new Le,u=new Te;for(s.push(0,0,0),c.push(0,0,1),h.push(.5,.5),a=0,r=3;a<=e;a++,r+=3){var p=n+a/e*i;l.x=t*Math.cos(p),l.y=t*Math.sin(p),s.push(l.x,l.y,l.z),c.push(0,0,1),u.x=(s[r]/t+1)/2,u.y=(s[r+1]/t+1)/2,h.push(u.x,u.y)}for(r=1;r<=e;r++)o.push(r,r+1,0);this.setIndex(o),this.addAttribute("position",new Un(s,3)),this.addAttribute("normal",new Un(c,3)),this.addAttribute("uv",new Un(h,2))}To.prototype=Object.create(Pn.prototype),To.prototype.constructor=To,Ao.prototype=Object.create(Mo.prototype),Ao.prototype.constructor=Ao,Lo.prototype=Object.create(Pn.prototype),Lo.prototype.constructor=Lo,Po.prototype=Object.create(Vn.prototype),Po.prototype.constructor=Po,Ro.prototype=Object.create(Pn.prototype),Ro.prototype.constructor=Ro,Co.prototype=Object.create(Vn.prototype),Co.prototype.constructor=Co,Oo.prototype=Object.create(Pn.prototype),Oo.prototype.constructor=Oo,Io.prototype=Object.create(Vn.prototype),Io.prototype.constructor=Io,Do.prototype=Object.create(Pn.prototype),Do.prototype.constructor=Do,Do.prototype.toJSON=function(){var t=Pn.prototype.toJSON.call(this);return zo(this.parameters.shapes,t)},No.prototype=Object.create(Vn.prototype),No.prototype.constructor=No,No.prototype.toJSON=function(){var t=Vn.prototype.toJSON.call(this);return zo(this.parameters.shapes,t)},Bo.prototype=Object.create(Vn.prototype),Bo.prototype.constructor=Bo,Uo.prototype=Object.create(Pn.prototype),Uo.prototype.constructor=Uo,Go.prototype=Object.create(Vn.prototype),Go.prototype.constructor=Go,Fo.prototype=Object.create(Uo.prototype),Fo.prototype.constructor=Fo,Ho.prototype=Object.create(Go.prototype),Ho.prototype.constructor=Ho,ko.prototype=Object.create(Pn.prototype),ko.prototype.constructor=ko,Vo.prototype=Object.create(Vn.prototype),Vo.prototype.constructor=Vo;var jo=Object.freeze({WireframeGeometry:Ca,ParametricGeometry:Oa,ParametricBufferGeometry:Ia,TetrahedronGeometry:za,TetrahedronBufferGeometry:Ba,OctahedronGeometry:Ua,OctahedronBufferGeometry:Ga,IcosahedronGeometry:Fa,IcosahedronBufferGeometry:Ha,DodecahedronGeometry:ka,DodecahedronBufferGeometry:Va,PolyhedronGeometry:Da,PolyhedronBufferGeometry:Na,TubeGeometry:ja,TubeBufferGeometry:Wa,TorusKnotGeometry:qa,TorusKnotBufferGeometry:Xa,TorusGeometry:Ya,TorusBufferGeometry:Ja,TextGeometry:To,TextBufferGeometry:Ao,SphereGeometry:Lo,SphereBufferGeometry:Po,RingGeometry:Ro,RingBufferGeometry:Co,PlaneGeometry:qn,PlaneBufferGeometry:Xn,LatheGeometry:Oo,LatheBufferGeometry:Io,ShapeGeometry:Do,ShapeBufferGeometry:No,ExtrudeGeometry:_o,ExtrudeBufferGeometry:Mo,EdgesGeometry:Bo,ConeGeometry:Fo,ConeBufferGeometry:Ho,CylinderGeometry:Uo,CylinderBufferGeometry:Go,CircleGeometry:ko,CircleBufferGeometry:Vo,BoxGeometry:jn,BoxBufferGeometry:Wn});function Wo(t){Jn.call(this),this.type="ShadowMaterial",this.color=new un(0),this.transparent=!0,this.setValues(t)}function qo(t){li.call(this,t),this.type="RawShaderMaterial"}function Xo(t){Jn.call(this),this.defines={STANDARD:""},this.type="MeshStandardMaterial",this.color=new un(16777215),this.roughness=.5,this.metalness=.5,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new un(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=Me,this.normalScale=new Te(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.roughnessMap=null,this.metalnessMap=null,this.alphaMap=null,this.envMap=null,this.envMapIntensity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.setValues(t)}function Yo(t){Xo.call(this),this.defines={PHYSICAL:""},this.type="MeshPhysicalMaterial",this.reflectivity=.5,this.clearCoat=0,this.clearCoatRoughness=0,this.setValues(t)}function Jo(t){Jn.call(this),this.type="MeshPhongMaterial",this.color=new un(16777215),this.specular=new un(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new un(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=Me,this.normalScale=new Te(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=J,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.setValues(t)}function Zo(t){Jo.call(this),this.defines={TOON:""},this.type="MeshToonMaterial",this.gradientMap=null,this.setValues(t)}function Qo(t){Jn.call(this),this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=Me,this.normalScale=new Te(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.lights=!1,this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.setValues(t)}function Ko(t){Jn.call(this),this.type="MeshLambertMaterial",this.color=new un(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new un(0),this.emissiveIntensity=1,this.emissiveMap=null,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=J,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.setValues(t)}function $o(t){Jn.call(this),this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new un(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=Me,this.normalScale=new Te(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.lights=!1,this.setValues(t)}function ts(t){wa.call(this),this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}Wo.prototype=Object.create(Jn.prototype),Wo.prototype.constructor=Wo,Wo.prototype.isShadowMaterial=!0,Wo.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.color.copy(t.color),this},qo.prototype=Object.create(li.prototype),qo.prototype.constructor=qo,qo.prototype.isRawShaderMaterial=!0,Xo.prototype=Object.create(Jn.prototype),Xo.prototype.constructor=Xo,Xo.prototype.isMeshStandardMaterial=!0,Xo.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.defines={STANDARD:""},this.color.copy(t.color),this.roughness=t.roughness,this.metalness=t.metalness,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.roughnessMap=t.roughnessMap,this.metalnessMap=t.metalnessMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.envMapIntensity=t.envMapIntensity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.morphNormals=t.morphNormals,this},Yo.prototype=Object.create(Xo.prototype),Yo.prototype.constructor=Yo,Yo.prototype.isMeshPhysicalMaterial=!0,Yo.prototype.copy=function(t){return Xo.prototype.copy.call(this,t),this.defines={PHYSICAL:""},this.reflectivity=t.reflectivity,this.clearCoat=t.clearCoat,this.clearCoatRoughness=t.clearCoatRoughness,this},Jo.prototype=Object.create(Jn.prototype),Jo.prototype.constructor=Jo,Jo.prototype.isMeshPhongMaterial=!0,Jo.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.morphNormals=t.morphNormals,this},Zo.prototype=Object.create(Jo.prototype),Zo.prototype.constructor=Zo,Zo.prototype.isMeshToonMaterial=!0,Zo.prototype.copy=function(t){return Jo.prototype.copy.call(this,t),this.gradientMap=t.gradientMap,this},Qo.prototype=Object.create(Jn.prototype),Qo.prototype.constructor=Qo,Qo.prototype.isMeshNormalMaterial=!0,Qo.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.morphNormals=t.morphNormals,this},Ko.prototype=Object.create(Jn.prototype),Ko.prototype.constructor=Ko,Ko.prototype.isMeshLambertMaterial=!0,Ko.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.morphNormals=t.morphNormals,this},$o.prototype=Object.create(Jn.prototype),$o.prototype.constructor=$o,$o.prototype.isMeshMatcapMaterial=!0,$o.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.defines={MATCAP:""},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.morphNormals=t.morphNormals,this},ts.prototype=Object.create(wa.prototype),ts.prototype.constructor=ts,ts.prototype.isLineDashedMaterial=!0,ts.prototype.copy=function(t){return wa.prototype.copy.call(this,t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this};var es=Object.freeze({ShadowMaterial:Wo,SpriteMaterial:ma,RawShaderMaterial:qo,ShaderMaterial:li,PointsMaterial:Ea,MeshPhysicalMaterial:Yo,MeshStandardMaterial:Xo,MeshPhongMaterial:Jo,MeshToonMaterial:Zo,MeshNormalMaterial:Qo,MeshLambertMaterial:Ko,MeshDepthMaterial:kr,MeshDistanceMaterial:Vr,MeshBasicMaterial:di,MeshMatcapMaterial:$o,LineDashedMaterial:ts,LineBasicMaterial:wa,Material:Jn}),ns={arraySlice:function(t,e,n){return ns.isTypedArray(t)?new t.constructor(t.subarray(e,void 0!==n?n:t.length)):t.slice(e,n)},convertArray:function(t,e,n){return!t||!n&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)},isTypedArray:function(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)},getKeyframeOrder:function(t){for(var e=t.length,n=new Array(e),i=0;i!==e;++i)n[i]=i;return n.sort(function(e,n){return t[e]-t[n]}),n},sortedArray:function(t,e,n){for(var i=t.length,r=new t.constructor(i),a=0,o=0;o!==i;++a)for(var s=n[a]*e,c=0;c!==e;++c)r[o++]=t[s+c];return r},flattenJSON:function(t,e,n,i){for(var r=1,a=t[0];void 0!==a&&void 0===a[i];)a=t[r++];if(void 0!==a){var o=a[i];if(void 0!==o)if(Array.isArray(o))do{void 0!==(o=a[i])&&(e.push(a.time),n.push.apply(n,o)),a=t[r++]}while(void 0!==a);else if(void 0!==o.toArray)do{void 0!==(o=a[i])&&(e.push(a.time),o.toArray(n,n.length)),a=t[r++]}while(void 0!==a);else do{void 0!==(o=a[i])&&(e.push(a.time),n.push(o)),a=t[r++]}while(void 0!==a)}}};function is(t,e,n,i){this.parameterPositions=t,this._cachedIndex=0,this.resultBuffer=void 0!==i?i:new e.constructor(n),this.sampleValues=e,this.valueSize=n}function rs(t,e,n,i){is.call(this,t,e,n,i),this._weightPrev=-0,this._offsetPrev=-0,this._weightNext=-0,this._offsetNext=-0}function as(t,e,n,i){is.call(this,t,e,n,i)}function os(t,e,n,i){is.call(this,t,e,n,i)}function ss(t,e,n,i){if(void 0===t)throw new Error("THREE.KeyframeTrack: track name is undefined");if(void 0===e||0===e.length)throw new Error("THREE.KeyframeTrack: no keyframes in track named "+t);this.name=t,this.times=ns.convertArray(e,this.TimeBufferType),this.values=ns.convertArray(n,this.ValueBufferType),this.setInterpolation(i||this.DefaultInterpolation)}function cs(t,e,n){ss.call(this,t,e,n)}function hs(t,e,n,i){ss.call(this,t,e,n,i)}function ls(t,e,n,i){ss.call(this,t,e,n,i)}function us(t,e,n,i){is.call(this,t,e,n,i)}function ps(t,e,n,i){ss.call(this,t,e,n,i)}function ds(t,e,n,i){ss.call(this,t,e,n,i)}function fs(t,e,n,i){ss.call(this,t,e,n,i)}function ms(t,e,n){this.name=t,this.tracks=n,this.duration=void 0!==e?e:-1,this.uuid=Ee.generateUUID(),this.duration<0&&this.resetDuration()}function gs(t){if(void 0===t.type)throw new Error("THREE.KeyframeTrack: track type undefined, can not parse");var e=function(t){switch(t.toLowerCase()){case"scalar":case"double":case"float":case"number":case"integer":return ls;case"vector":case"vector2":case"vector3":case"vector4":return fs;case"color":return hs;case"quaternion":return ps;case"bool":case"boolean":return cs;case"string":return ds}throw new Error("THREE.KeyframeTrack: Unsupported typeName: "+t)}(t.type);if(void 0===t.times){var n=[],i=[];ns.flattenJSON(t.keys,n,i,"value"),t.times=n,t.values=i}return void 0!==e.parse?e.parse(t):new e(t.name,t.times,t.values,t.interpolation)}Object.assign(is.prototype,{evaluate:function(t){var e=this.parameterPositions,n=this._cachedIndex,i=e[n],r=e[n-1];t:{e:{var a;n:{i:if(!(t=r)break t;var s=e[1];t=(r=e[--n-1]))break e}a=n,n=0}for(;n>>1;t0?1:+t}),"name"in Function.prototype==!1&&Object.defineProperty(Function.prototype,"name",{get:function(){return this.toString().match(/^\s*function\s*([^\(\s]*)/)[1]}}),void 0===Object.assign&&(Object.assign=function(t){if(null==t)throw new TypeError("Cannot convert undefined or null to object");for(var e=Object(t),n=1;n>8&255]+t[e>>16&255]+t[e>>24&255]+"-"+t[255&n]+t[n>>8&255]+"-"+t[n>>16&15|64]+t[n>>24&255]+"-"+t[63&i|128]+t[i>>8&255]+"-"+t[i>>16&255]+t[i>>24&255]+t[255&r]+t[r>>8&255]+t[r>>16&255]+t[r>>24&255]).toUpperCase()}}(),clamp:function(t,e,n){return Math.max(e,Math.min(n,t))},euclideanModulo:function(t,e){return(t%e+e)%e},mapLinear:function(t,e,n,i,r){return i+(t-e)*(r-i)/(n-e)},lerp:function(t,e,n){return(1-n)*t+n*e},smoothstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*(3-2*t)},smootherstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*t*(t*(6*t-15)+10)},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},degToRad:function(t){return t*Te.DEG2RAD},radToDeg:function(t){return t*Te.RAD2DEG},isPowerOfTwo:function(t){return 0==(t&t-1)&&0!==t},ceilPowerOfTwo:function(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))},floorPowerOfTwo:function(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))}};function Ee(t,e){this.x=t||0,this.y=e||0}function Ae(t,e,n,i){this._x=t||0,this._y=e||0,this._z=n||0,this._w=void 0!==i?i:1}function Le(t,e,n){this.x=t||0,this.y=e||0,this.z=n||0}function Pe(){this.elements=[1,0,0,0,1,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.")}Object.defineProperties(Ee.prototype,{width:{get:function(){return this.x},set:function(t){this.x=t}},height:{get:function(){return this.y},set:function(t){this.y=t}}}),Object.assign(Ee.prototype,{isVector2:!0,set:function(t,e){return this.x=t,this.y=e,this},setScalar:function(t){return this.x=t,this.y=t,this},setX:function(t){return this.x=t,this},setY:function(t){return this.y=t,this},setComponent:function(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this},getComponent:function(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}},clone:function(){return new this.constructor(this.x,this.y)},copy:function(t){return this.x=t.x,this.y=t.y,this},add:function(t,e){return void 0!==e?(console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this)},addScalar:function(t){return this.x+=t,this.y+=t,this},addVectors:function(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this},addScaledVector:function(t,e){return this.x+=t.x*e,this.y+=t.y*e,this},sub:function(t,e){return void 0!==e?(console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this)},subScalar:function(t){return this.x-=t,this.y-=t,this},subVectors:function(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this},multiply:function(t){return this.x*=t.x,this.y*=t.y,this},multiplyScalar:function(t){return this.x*=t,this.y*=t,this},divide:function(t){return this.x/=t.x,this.y/=t.y,this},divideScalar:function(t){return this.multiplyScalar(1/t)},applyMatrix3:function(t){var e=this.x,n=this.y,i=t.elements;return this.x=i[0]*e+i[3]*n+i[6],this.y=i[1]*e+i[4]*n+i[7],this},min:function(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this},max:function(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this},clamp:function(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this},clampScalar:function(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this},clampLength:function(t,e){var n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this},negate:function(){return this.x=-this.x,this.y=-this.y,this},dot:function(t){return this.x*t.x+this.y*t.y},cross:function(t){return this.x*t.y-this.y*t.x},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)},normalize:function(){return this.divideScalar(this.length()||1)},angle:function(){var t=Math.atan2(this.y,this.x);return t<0&&(t+=2*Math.PI),t},distanceTo:function(t){return Math.sqrt(this.distanceToSquared(t))},distanceToSquared:function(t){var e=this.x-t.x,n=this.y-t.y;return e*e+n*n},manhattanDistanceTo:function(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)},setLength:function(t){return this.normalize().multiplyScalar(t)},lerp:function(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this},lerpVectors:function(t,e,n){return this.subVectors(e,t).multiplyScalar(n).add(t)},equals:function(t){return t.x===this.x&&t.y===this.y},fromArray:function(t,e){return void 0===e&&(e=0),this.x=t[e],this.y=t[e+1],this},toArray:function(t,e){return void 0===t&&(t=[]),void 0===e&&(e=0),t[e]=this.x,t[e+1]=this.y,t},fromBufferAttribute:function(t,e,n){return void 0!==n&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute()."),this.x=t.getX(e),this.y=t.getY(e),this},rotateAround:function(t,e){var n=Math.cos(e),i=Math.sin(e),r=this.x-t.x,a=this.y-t.y;return this.x=r*n-a*i+t.x,this.y=r*i+a*n+t.y,this}}),Object.assign(Ae,{slerp:function(t,e,n,i){return n.copy(t).slerp(e,i)},slerpFlat:function(t,e,n,i,r,a,o){var s=n[i+0],c=n[i+1],h=n[i+2],l=n[i+3],u=r[a+0],p=r[a+1],d=r[a+2],f=r[a+3];if(l!==f||s!==u||c!==p||h!==d){var m=1-o,g=s*u+c*p+h*d+l*f,v=g>=0?1:-1,y=1-g*g;if(y>Number.EPSILON){var x=Math.sqrt(y),b=Math.atan2(x,g*v);m=Math.sin(m*b)/x,o=Math.sin(o*b)/x}var w=o*v;if(s=s*m+u*w,c=c*m+p*w,h=h*m+d*w,l=l*m+f*w,m===1-o){var _=1/Math.sqrt(s*s+c*c+h*h+l*l);s*=_,c*=_,h*=_,l*=_}}t[e]=s,t[e+1]=c,t[e+2]=h,t[e+3]=l}}),Object.defineProperties(Ae.prototype,{x:{get:function(){return this._x},set:function(t){this._x=t,this.onChangeCallback()}},y:{get:function(){return this._y},set:function(t){this._y=t,this.onChangeCallback()}},z:{get:function(){return this._z},set:function(t){this._z=t,this.onChangeCallback()}},w:{get:function(){return this._w},set:function(t){this._w=t,this.onChangeCallback()}}}),Object.assign(Ae.prototype,{isQuaternion:!0,set:function(t,e,n,i){return this._x=t,this._y=e,this._z=n,this._w=i,this.onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._w)},copy:function(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this.onChangeCallback(),this},setFromEuler:function(t,e){if(!t||!t.isEuler)throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");var n=t._x,i=t._y,r=t._z,a=t.order,o=Math.cos,s=Math.sin,c=o(n/2),h=o(i/2),l=o(r/2),u=s(n/2),p=s(i/2),d=s(r/2);return"XYZ"===a?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"YXZ"===a?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"ZXY"===a?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"ZYX"===a?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"YZX"===a?(this._x=u*h*l+c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l-u*p*d):"XZY"===a&&(this._x=u*h*l-c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l+u*p*d),!1!==e&&this.onChangeCallback(),this},setFromAxisAngle:function(t,e){var n=e/2,i=Math.sin(n);return this._x=t.x*i,this._y=t.y*i,this._z=t.z*i,this._w=Math.cos(n),this.onChangeCallback(),this},setFromRotationMatrix:function(t){var e,n=t.elements,i=n[0],r=n[4],a=n[8],o=n[1],s=n[5],c=n[9],h=n[2],l=n[6],u=n[10],p=i+s+u;return p>0?(e=.5/Math.sqrt(p+1),this._w=.25/e,this._x=(l-c)*e,this._y=(a-h)*e,this._z=(o-r)*e):i>s&&i>u?(e=2*Math.sqrt(1+i-s-u),this._w=(l-c)/e,this._x=.25*e,this._y=(r+o)/e,this._z=(a+h)/e):s>u?(e=2*Math.sqrt(1+s-i-u),this._w=(a-h)/e,this._x=(r+o)/e,this._y=.25*e,this._z=(c+l)/e):(e=2*Math.sqrt(1+u-i-s),this._w=(o-r)/e,this._x=(a+h)/e,this._y=(c+l)/e,this._z=.25*e),this.onChangeCallback(),this},setFromUnitVectors:function(t,e){var n=t.dot(e)+1;return n<1e-6?(n=0,Math.abs(t.x)>Math.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=n):(this._x=0,this._y=-t.z,this._z=t.y,this._w=n)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=n),this.normalize()},angleTo:function(t){return 2*Math.acos(Math.abs(Te.clamp(this.dot(t),-1,1)))},rotateTowards:function(t,e){var n=this.angleTo(t);if(0===n)return this;var i=Math.min(1,e/n);return this.slerp(t,i),this},inverse:function(){return this.conjugate()},conjugate:function(){return this._x*=-1,this._y*=-1,this._z*=-1,this.onChangeCallback(),this},dot:function(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w},lengthSq:function(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w},length:function(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)},normalize:function(){var t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this.onChangeCallback(),this},multiply:function(t,e){return void 0!==e?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(t,e)):this.multiplyQuaternions(this,t)},premultiply:function(t){return this.multiplyQuaternions(t,this)},multiplyQuaternions:function(t,e){var n=t._x,i=t._y,r=t._z,a=t._w,o=e._x,s=e._y,c=e._z,h=e._w;return this._x=n*h+a*o+i*c-r*s,this._y=i*h+a*s+r*o-n*c,this._z=r*h+a*c+n*s-i*o,this._w=a*h-n*o-i*s-r*c,this.onChangeCallback(),this},slerp:function(t,e){if(0===e)return this;if(1===e)return this.copy(t);var n=this._x,i=this._y,r=this._z,a=this._w,o=a*t._w+n*t._x+i*t._y+r*t._z;if(o<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,o=-o):this.copy(t),o>=1)return this._w=a,this._x=n,this._y=i,this._z=r,this;var s=1-o*o;if(s<=Number.EPSILON){var c=1-e;return this._w=c*a+e*this._w,this._x=c*n+e*this._x,this._y=c*i+e*this._y,this._z=c*r+e*this._z,this.normalize()}var h=Math.sqrt(s),l=Math.atan2(h,o),u=Math.sin((1-e)*l)/h,p=Math.sin(e*l)/h;return this._w=a*u+this._w*p,this._x=n*u+this._x*p,this._y=i*u+this._y*p,this._z=r*u+this._z*p,this.onChangeCallback(),this},equals:function(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w},fromArray:function(t,e){return void 0===e&&(e=0),this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this.onChangeCallback(),this},toArray:function(t,e){return void 0===t&&(t=[]),void 0===e&&(e=0),t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t},onChange:function(t){return this.onChangeCallback=t,this},onChangeCallback:function(){}}),Object.assign(Le.prototype,{isVector3:!0,set:function(t,e,n){return this.x=t,this.y=e,this.z=n,this},setScalar:function(t){return this.x=t,this.y=t,this.z=t,this},setX:function(t){return this.x=t,this},setY:function(t){return this.y=t,this},setZ:function(t){return this.z=t,this},setComponent:function(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this},getComponent:function(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}},clone:function(){return new this.constructor(this.x,this.y,this.z)},copy:function(t){return this.x=t.x,this.y=t.y,this.z=t.z,this},add:function(t,e){return void 0!==e?(console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this.z+=t.z,this)},addScalar:function(t){return this.x+=t,this.y+=t,this.z+=t,this},addVectors:function(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this},addScaledVector:function(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this},sub:function(t,e){return void 0!==e?(console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this.z-=t.z,this)},subScalar:function(t){return this.x-=t,this.y-=t,this.z-=t,this},subVectors:function(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this},multiply:function(t,e){return void 0!==e?(console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(t,e)):(this.x*=t.x,this.y*=t.y,this.z*=t.z,this)},multiplyScalar:function(t){return this.x*=t,this.y*=t,this.z*=t,this},multiplyVectors:function(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this},applyEuler:(a=new Ae,function(t){return t&&t.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(a.setFromEuler(t))}),applyAxisAngle:function(){var t=new Ae;return function(e,n){return this.applyQuaternion(t.setFromAxisAngle(e,n))}}(),applyMatrix3:function(t){var e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[3]*n+r[6]*i,this.y=r[1]*e+r[4]*n+r[7]*i,this.z=r[2]*e+r[5]*n+r[8]*i,this},applyMatrix4:function(t){var e=this.x,n=this.y,i=this.z,r=t.elements,a=1/(r[3]*e+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*e+r[4]*n+r[8]*i+r[12])*a,this.y=(r[1]*e+r[5]*n+r[9]*i+r[13])*a,this.z=(r[2]*e+r[6]*n+r[10]*i+r[14])*a,this},applyQuaternion:function(t){var e=this.x,n=this.y,i=this.z,r=t.x,a=t.y,o=t.z,s=t.w,c=s*e+a*i-o*n,h=s*n+o*e-r*i,l=s*i+r*n-a*e,u=-r*e-a*n-o*i;return this.x=c*s+u*-r+h*-o-l*-a,this.y=h*s+u*-a+l*-r-c*-o,this.z=l*s+u*-o+c*-a-h*-r,this},project:function(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)},unproject:function(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)},transformDirection:function(t){var e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[4]*n+r[8]*i,this.y=r[1]*e+r[5]*n+r[9]*i,this.z=r[2]*e+r[6]*n+r[10]*i,this.normalize()},divide:function(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this},divideScalar:function(t){return this.multiplyScalar(1/t)},min:function(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this},max:function(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this},clamp:function(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this},clampScalar:function(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this.z=Math.max(t,Math.min(e,this.z)),this},clampLength:function(t,e){var n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this},dot:function(t){return this.x*t.x+this.y*t.y+this.z*t.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(t){return this.normalize().multiplyScalar(t)},lerp:function(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this},lerpVectors:function(t,e,n){return this.subVectors(e,t).multiplyScalar(n).add(t)},cross:function(t,e){return void 0!==e?(console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(t,e)):this.crossVectors(this,t)},crossVectors:function(t,e){var n=t.x,i=t.y,r=t.z,a=e.x,o=e.y,s=e.z;return this.x=i*s-r*o,this.y=r*a-n*s,this.z=n*o-i*a,this},projectOnVector:function(t){var e=t.dot(this)/t.lengthSq();return this.copy(t).multiplyScalar(e)},projectOnPlane:(r=new Le,function(t){return r.copy(this).projectOnVector(t),this.sub(r)}),reflect:function(){var t=new Le;return function(e){return this.sub(t.copy(e).multiplyScalar(2*this.dot(e)))}}(),angleTo:function(t){var e=this.dot(t)/Math.sqrt(this.lengthSq()*t.lengthSq());return Math.acos(Te.clamp(e,-1,1))},distanceTo:function(t){return Math.sqrt(this.distanceToSquared(t))},distanceToSquared:function(t){var e=this.x-t.x,n=this.y-t.y,i=this.z-t.z;return e*e+n*n+i*i},manhattanDistanceTo:function(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)},setFromSpherical:function(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)},setFromSphericalCoords:function(t,e,n){var i=Math.sin(e)*t;return this.x=i*Math.sin(n),this.y=Math.cos(e)*t,this.z=i*Math.cos(n),this},setFromCylindrical:function(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)},setFromCylindricalCoords:function(t,e,n){return this.x=t*Math.sin(e),this.y=n,this.z=t*Math.cos(e),this},setFromMatrixPosition:function(t){var e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this},setFromMatrixScale:function(t){var e=this.setFromMatrixColumn(t,0).length(),n=this.setFromMatrixColumn(t,1).length(),i=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=n,this.z=i,this},setFromMatrixColumn:function(t,e){return this.fromArray(t.elements,4*e)},equals:function(t){return t.x===this.x&&t.y===this.y&&t.z===this.z},fromArray:function(t,e){return void 0===e&&(e=0),this.x=t[e],this.y=t[e+1],this.z=t[e+2],this},toArray:function(t,e){return void 0===t&&(t=[]),void 0===e&&(e=0),t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t},fromBufferAttribute:function(t,e,n){return void 0!==n&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute()."),this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}}),Object.assign(Pe.prototype,{isMatrix3:!0,set:function(t,e,n,i,r,a,o,s,c){var h=this.elements;return h[0]=t,h[1]=i,h[2]=o,h[3]=e,h[4]=r,h[5]=s,h[6]=n,h[7]=a,h[8]=c,this},identity:function(){return this.set(1,0,0,0,1,0,0,0,1),this},clone:function(){return(new this.constructor).fromArray(this.elements)},copy:function(t){var e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],this},setFromMatrix4:function(t){var e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this},applyToBufferAttribute:function(){var t=new Le;return function(e){for(var n=0,i=e.count;n2048||e.height>2048?e.toDataURL("image/jpeg",.6):e.toDataURL("image/png")}},We=0;function qe(t,e,n,i,r,a,o,s,c,h){Object.defineProperty(this,"id",{value:We++}),this.uuid=Te.generateUUID(),this.name="",this.image=void 0!==t?t:qe.DEFAULT_IMAGE,this.mipmaps=[],this.mapping=void 0!==e?e:qe.DEFAULT_MAPPING,this.wrapS=void 0!==n?n:pt,this.wrapT=void 0!==i?i:pt,this.magFilter=void 0!==r?r:vt,this.minFilter=void 0!==a?a:xt,this.anisotropy=void 0!==c?c:1,this.format=void 0!==o?o:Dt,this.type=void 0!==s?s:bt,this.offset=new Ee(0,0),this.repeat=new Ee(1,1),this.center=new Ee(0,0),this.rotation=0,this.matrixAutoUpdate=!0,this.matrix=new Pe,this.generateMipmaps=!0,this.premultiplyAlpha=!1,this.flipY=!0,this.unpackAlignment=4,this.encoding=void 0!==h?h:fe,this.version=0,this.onUpdate=null}function Xe(t,e,n,i){this.x=t||0,this.y=e||0,this.z=n||0,this.w=void 0!==i?i:1}function Ye(t,e,n){this.width=t,this.height=e,this.scissor=new Xe(0,0,t,e),this.scissorTest=!1,this.viewport=new Xe(0,0,t,e),n=n||{},this.texture=new qe(void 0,void 0,n.wrapS,n.wrapT,n.magFilter,n.minFilter,n.format,n.type,n.anisotropy,n.encoding),this.texture.generateMipmaps=void 0!==n.generateMipmaps&&n.generateMipmaps,this.texture.minFilter=void 0!==n.minFilter?n.minFilter:vt,this.depthBuffer=void 0===n.depthBuffer||n.depthBuffer,this.stencilBuffer=void 0===n.stencilBuffer||n.stencilBuffer,this.depthTexture=void 0!==n.depthTexture?n.depthTexture:null}function Je(t,e,n){Ye.call(this,t,e,n),this.samples=4}function Ze(t,e,n){Ye.call(this,t,e,n)}function Qe(t,e,n,i,r,a,o,s,c,h,l,u){qe.call(this,null,a,o,s,c,h,i,r,l,u),this.image={data:t,width:e,height:n},this.magFilter=void 0!==c?c:ft,this.minFilter=void 0!==h?h:ft,this.generateMipmaps=!1,this.flipY=!1,this.unpackAlignment=1}function Ke(t,e){this.min=void 0!==t?t:new Le(1/0,1/0,1/0),this.max=void 0!==e?e:new Le(-1/0,-1/0,-1/0)}function $e(t,e){this.center=void 0!==t?t:new Le,this.radius=void 0!==e?e:0}function tn(t,e){this.normal=void 0!==t?t:new Le(1,0,0),this.constant=void 0!==e?e:0}function en(t,e,n,i,r,a){this.planes=[void 0!==t?t:new tn,void 0!==e?e:new tn,void 0!==n?n:new tn,void 0!==i?i:new tn,void 0!==r?r:new tn,void 0!==a?a:new tn]}function nn(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.")}qe.DEFAULT_IMAGE=void 0,qe.DEFAULT_MAPPING=300,qe.prototype=Object.assign(Object.create(i.prototype),{constructor:qe,isTexture:!0,updateMatrix:function(){this.matrix.setUvTransform(this.offset.x,this.offset.y,this.repeat.x,this.repeat.y,this.rotation,this.center.x,this.center.y)},clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.name=t.name,this.image=t.image,this.mipmaps=t.mipmaps.slice(0),this.mapping=t.mapping,this.wrapS=t.wrapS,this.wrapT=t.wrapT,this.magFilter=t.magFilter,this.minFilter=t.minFilter,this.anisotropy=t.anisotropy,this.format=t.format,this.type=t.type,this.offset.copy(t.offset),this.repeat.copy(t.repeat),this.center.copy(t.center),this.rotation=t.rotation,this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrix.copy(t.matrix),this.generateMipmaps=t.generateMipmaps,this.premultiplyAlpha=t.premultiplyAlpha,this.flipY=t.flipY,this.unpackAlignment=t.unpackAlignment,this.encoding=t.encoding,this},toJSON:function(t){var e=void 0===t||"string"==typeof t;if(!e&&void 0!==t.textures[this.uuid])return t.textures[this.uuid];var n={metadata:{version:4.5,type:"Texture",generator:"Texture.toJSON"},uuid:this.uuid,name:this.name,mapping:this.mapping,repeat:[this.repeat.x,this.repeat.y],offset:[this.offset.x,this.offset.y],center:[this.center.x,this.center.y],rotation:this.rotation,wrap:[this.wrapS,this.wrapT],format:this.format,type:this.type,encoding:this.encoding,minFilter:this.minFilter,magFilter:this.magFilter,anisotropy:this.anisotropy,flipY:this.flipY,premultiplyAlpha:this.premultiplyAlpha,unpackAlignment:this.unpackAlignment};if(void 0!==this.image){var i=this.image;if(void 0===i.uuid&&(i.uuid=Te.generateUUID()),!e&&void 0===t.images[i.uuid]){var r;if(Array.isArray(i)){r=[];for(var a=0,o=i.length;a1)switch(this.wrapS){case ut:t.x=t.x-Math.floor(t.x);break;case pt:t.x=t.x<0?0:1;break;case dt:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y<0||t.y>1)switch(this.wrapT){case ut:t.y=t.y-Math.floor(t.y);break;case pt:t.y=t.y<0?0:1;break;case dt:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&&(t.y=1-t.y),t}}),Object.defineProperty(qe.prototype,"needsUpdate",{set:function(t){!0===t&&this.version++}}),Object.assign(Xe.prototype,{isVector4:!0,set:function(t,e,n,i){return this.x=t,this.y=e,this.z=n,this.w=i,this},setScalar:function(t){return this.x=t,this.y=t,this.z=t,this.w=t,this},setX:function(t){return this.x=t,this},setY:function(t){return this.y=t,this},setZ:function(t){return this.z=t,this},setW:function(t){return this.w=t,this},setComponent:function(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this},getComponent:function(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}},clone:function(){return new this.constructor(this.x,this.y,this.z,this.w)},copy:function(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this},add:function(t,e){return void 0!==e?(console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this)},addScalar:function(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this},addVectors:function(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this},addScaledVector:function(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this},sub:function(t,e){return void 0!==e?(console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this)},subScalar:function(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this},subVectors:function(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this},multiplyScalar:function(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this},applyMatrix4:function(t){var e=this.x,n=this.y,i=this.z,r=this.w,a=t.elements;return this.x=a[0]*e+a[4]*n+a[8]*i+a[12]*r,this.y=a[1]*e+a[5]*n+a[9]*i+a[13]*r,this.z=a[2]*e+a[6]*n+a[10]*i+a[14]*r,this.w=a[3]*e+a[7]*n+a[11]*i+a[15]*r,this},divideScalar:function(t){return this.multiplyScalar(1/t)},setAxisAngleFromQuaternion:function(t){this.w=2*Math.acos(t.w);var e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this},setAxisAngleFromRotationMatrix:function(t){var e,n,i,r,a=t.elements,o=a[0],s=a[4],c=a[8],h=a[1],l=a[5],u=a[9],p=a[2],d=a[6],f=a[10];if(Math.abs(s-h)<.01&&Math.abs(c-p)<.01&&Math.abs(u-d)<.01){if(Math.abs(s+h)<.1&&Math.abs(c+p)<.1&&Math.abs(u+d)<.1&&Math.abs(o+l+f-3)<.1)return this.set(1,0,0,0),this;e=Math.PI;var m=(o+1)/2,g=(l+1)/2,v=(f+1)/2,y=(s+h)/4,x=(c+p)/4,b=(u+d)/4;return m>g&&m>v?m<.01?(n=0,i=.707106781,r=.707106781):(i=y/(n=Math.sqrt(m)),r=x/n):g>v?g<.01?(n=.707106781,i=0,r=.707106781):(n=y/(i=Math.sqrt(g)),r=b/i):v<.01?(n=.707106781,i=.707106781,r=0):(n=x/(r=Math.sqrt(v)),i=b/r),this.set(n,i,r,e),this}var w=Math.sqrt((d-u)*(d-u)+(c-p)*(c-p)+(h-s)*(h-s));return Math.abs(w)<.001&&(w=1),this.x=(d-u)/w,this.y=(c-p)/w,this.z=(h-s)/w,this.w=Math.acos((o+l+f-1)/2),this},min:function(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this.w=Math.min(this.w,t.w),this},max:function(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this.w=Math.max(this.w,t.w),this},clamp:function(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this.w=Math.max(t.w,Math.min(e.w,this.w)),this},clampScalar:function(t,e){return void 0===Re&&(Re=new Xe,Ce=new Xe),Re.set(t,t,t,t),Ce.set(e,e,e,e),this.clamp(Re,Ce)},clampLength:function(t,e){var n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this.w=Math.floor(this.w),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this.w=Math.ceil(this.w),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this.w=Math.round(this.w),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this.w=this.w<0?Math.ceil(this.w):Math.floor(this.w),this},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this.w=-this.w,this},dot:function(t){return this.x*t.x+this.y*t.y+this.z*t.z+this.w*t.w},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(t){return this.normalize().multiplyScalar(t)},lerp:function(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this.w+=(t.w-this.w)*e,this},lerpVectors:function(t,e,n){return this.subVectors(e,t).multiplyScalar(n).add(t)},equals:function(t){return t.x===this.x&&t.y===this.y&&t.z===this.z&&t.w===this.w},fromArray:function(t,e){return void 0===e&&(e=0),this.x=t[e],this.y=t[e+1],this.z=t[e+2],this.w=t[e+3],this},toArray:function(t,e){return void 0===t&&(t=[]),void 0===e&&(e=0),t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t[e+3]=this.w,t},fromBufferAttribute:function(t,e,n){return void 0!==n&&console.warn("THREE.Vector4: offset has been removed from .fromBufferAttribute()."),this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this.w=t.getW(e),this}}),Ye.prototype=Object.assign(Object.create(i.prototype),{constructor:Ye,isWebGLRenderTarget:!0,setSize:function(t,e){this.width===t&&this.height===e||(this.width=t,this.height=e,this.dispose()),this.viewport.set(0,0,t,e),this.scissor.set(0,0,t,e)},clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.width=t.width,this.height=t.height,this.viewport.copy(t.viewport),this.texture=t.texture.clone(),this.depthBuffer=t.depthBuffer,this.stencilBuffer=t.stencilBuffer,this.depthTexture=t.depthTexture,this},dispose:function(){this.dispatchEvent({type:"dispose"})}}),Je.prototype=Object.assign(Object.create(Ye.prototype),{constructor:Je,isWebGLMultisampleRenderTarget:!0,copy:function(t){return Ye.prototype.copy.call(this,t),this.samples=t.samples,this}}),Ze.prototype=Object.create(Ye.prototype),Ze.prototype.constructor=Ze,Ze.prototype.isWebGLRenderTargetCube=!0,Qe.prototype=Object.create(qe.prototype),Qe.prototype.constructor=Qe,Qe.prototype.isDataTexture=!0,Object.assign(Ke.prototype,{isBox3:!0,set:function(t,e){return this.min.copy(t),this.max.copy(e),this},setFromArray:function(t){for(var e=1/0,n=1/0,i=1/0,r=-1/0,a=-1/0,o=-1/0,s=0,c=t.length;sr&&(r=h),l>a&&(a=l),u>o&&(o=u)}return this.min.set(e,n,i),this.max.set(r,a,o),this},setFromBufferAttribute:function(t){for(var e=1/0,n=1/0,i=1/0,r=-1/0,a=-1/0,o=-1/0,s=0,c=t.count;sr&&(r=h),l>a&&(a=l),u>o&&(o=u)}return this.min.set(e,n,i),this.max.set(r,a,o),this},setFromPoints:function(t){this.makeEmpty();for(var e=0,n=t.length;ethis.max.x||t.ythis.max.y||t.zthis.max.z)},containsBox:function(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z},getParameter:function(t,e){return void 0===e&&(console.warn("THREE.Box3: .getParameter() target is now required"),e=new Le),e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))},intersectsBox:function(t){return!(t.max.xthis.max.x||t.max.ythis.max.y||t.max.zthis.max.z)},intersectsSphere:(Ie=new Le,function(t){return this.clampPoint(t.center,Ie),Ie.distanceToSquared(t.center)<=t.radius*t.radius}),intersectsPlane:function(t){var e,n;return t.normal.x>0?(e=t.normal.x*this.min.x,n=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,n=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,n+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,n+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,n+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,n+=t.normal.z*this.min.z),e<=-t.constant&&n>=-t.constant},intersectsTriangle:function(){var t=new Le,e=new Le,n=new Le,i=new Le,r=new Le,a=new Le,o=new Le,s=new Le,c=new Le,h=new Le;function l(i){var r,a;for(r=0,a=i.length-3;r<=a;r+=3){o.fromArray(i,r);var s=c.x*Math.abs(o.x)+c.y*Math.abs(o.y)+c.z*Math.abs(o.z),h=t.dot(o),l=e.dot(o),u=n.dot(o);if(Math.max(-Math.max(h,l,u),Math.min(h,l,u))>s)return!1}return!0}return function(o){if(this.isEmpty())return!1;this.getCenter(s),c.subVectors(this.max,s),t.subVectors(o.a,s),e.subVectors(o.b,s),n.subVectors(o.c,s),i.subVectors(e,t),r.subVectors(n,e),a.subVectors(t,n);var u=[0,-i.z,i.y,0,-r.z,r.y,0,-a.z,a.y,i.z,0,-i.x,r.z,0,-r.x,a.z,0,-a.x,-i.y,i.x,0,-r.y,r.x,0,-a.y,a.x,0];return!!l(u)&&(!!l(u=[1,0,0,0,1,0,0,0,1])&&(h.crossVectors(i,r),l(u=[h.x,h.y,h.z])))}}(),clampPoint:function(t,e){return void 0===e&&(console.warn("THREE.Box3: .clampPoint() target is now required"),e=new Le),e.copy(t).clamp(this.min,this.max)},distanceToPoint:function(){var t=new Le;return function(e){return t.copy(e).clamp(this.min,this.max).sub(e).length()}}(),getBoundingSphere:function(){var t=new Le;return function(e){return void 0===e&&console.error("THREE.Box3: .getBoundingSphere() target is now required"),this.getCenter(e.center),e.radius=.5*this.getSize(t).length(),e}}(),intersect:function(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this},union:function(t){return this.min.min(t.min),this.max.max(t.max),this},applyMatrix4:(Oe=[new Le,new Le,new Le,new Le,new Le,new Le,new Le,new Le],function(t){return this.isEmpty()?this:(Oe[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),Oe[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),Oe[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),Oe[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),Oe[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),Oe[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),Oe[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),Oe[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(Oe),this)}),translate:function(t){return this.min.add(t),this.max.add(t),this},equals:function(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}),Object.assign($e.prototype,{set:function(t,e){return this.center.copy(t),this.radius=e,this},setFromPoints:(De=new Ke,function(t,e){var n=this.center;void 0!==e?n.copy(e):De.setFromPoints(t).getCenter(n);for(var i=0,r=0,a=t.length;rthis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e},getBoundingBox:function(t){return void 0===t&&(console.warn("THREE.Sphere: .getBoundingBox() target is now required"),t=new Ke),t.set(this.center,this.center),t.expandByScalar(this.radius),t},applyMatrix4:function(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this},translate:function(t){return this.center.add(t),this},equals:function(t){return t.center.equals(this.center)&&t.radius===this.radius}}),Object.assign(tn.prototype,{set:function(t,e){return this.normal.copy(t),this.constant=e,this},setComponents:function(t,e,n,i){return this.normal.set(t,e,n),this.constant=i,this},setFromNormalAndCoplanarPoint:function(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this},setFromCoplanarPoints:function(){var t=new Le,e=new Le;return function(n,i,r){var a=t.subVectors(r,i).cross(e.subVectors(n,i)).normalize();return this.setFromNormalAndCoplanarPoint(a,n),this}}(),clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.normal.copy(t.normal),this.constant=t.constant,this},normalize:function(){var t=1/this.normal.length();return this.normal.multiplyScalar(t),this.constant*=t,this},negate:function(){return this.constant*=-1,this.normal.negate(),this},distanceToPoint:function(t){return this.normal.dot(t)+this.constant},distanceToSphere:function(t){return this.distanceToPoint(t.center)-t.radius},projectPoint:function(t,e){return void 0===e&&(console.warn("THREE.Plane: .projectPoint() target is now required"),e=new Le),e.copy(this.normal).multiplyScalar(-this.distanceToPoint(t)).add(t)},intersectLine:function(){var t=new Le;return function(e,n){void 0===n&&(console.warn("THREE.Plane: .intersectLine() target is now required"),n=new Le);var i=e.delta(t),r=this.normal.dot(i);if(0===r)return 0===this.distanceToPoint(e.start)?n.copy(e.start):void 0;var a=-(e.start.dot(this.normal)+this.constant)/r;return a<0||a>1?void 0:n.copy(i).multiplyScalar(a).add(e.start)}}(),intersectsLine:function(t){var e=this.distanceToPoint(t.start),n=this.distanceToPoint(t.end);return e<0&&n>0||n<0&&e>0},intersectsBox:function(t){return t.intersectsPlane(this)},intersectsSphere:function(t){return t.intersectsPlane(this)},coplanarPoint:function(t){return void 0===t&&(console.warn("THREE.Plane: .coplanarPoint() target is now required"),t=new Le),t.copy(this.normal).multiplyScalar(-this.constant)},applyMatrix4:function(){var t=new Le,e=new Pe;return function(n,i){var r=i||e.getNormalMatrix(n),a=this.coplanarPoint(t).applyMatrix4(n),o=this.normal.applyMatrix3(r).normalize();return this.constant=-a.dot(o),this}}(),translate:function(t){return this.constant-=t.dot(this.normal),this},equals:function(t){return t.normal.equals(this.normal)&&t.constant===this.constant}}),Object.assign(en.prototype,{set:function(t,e,n,i,r,a){var o=this.planes;return o[0].copy(t),o[1].copy(e),o[2].copy(n),o[3].copy(i),o[4].copy(r),o[5].copy(a),this},clone:function(){return(new this.constructor).copy(this)},copy:function(t){for(var e=this.planes,n=0;n<6;n++)e[n].copy(t.planes[n]);return this},setFromMatrix:function(t){var e=this.planes,n=t.elements,i=n[0],r=n[1],a=n[2],o=n[3],s=n[4],c=n[5],h=n[6],l=n[7],u=n[8],p=n[9],d=n[10],f=n[11],m=n[12],g=n[13],v=n[14],y=n[15];return e[0].setComponents(o-i,l-s,f-u,y-m).normalize(),e[1].setComponents(o+i,l+s,f+u,y+m).normalize(),e[2].setComponents(o+r,l+c,f+p,y+g).normalize(),e[3].setComponents(o-r,l-c,f-p,y-g).normalize(),e[4].setComponents(o-a,l-h,f-d,y-v).normalize(),e[5].setComponents(o+a,l+h,f+d,y+v).normalize(),this},intersectsObject:(ze=new $e,function(t){var e=t.geometry;return null===e.boundingSphere&&e.computeBoundingSphere(),ze.copy(e.boundingSphere).applyMatrix4(t.matrixWorld),this.intersectsSphere(ze)}),intersectsSprite:function(){var t=new $e;return function(e){return t.center.set(0,0,0),t.radius=.7071067811865476,t.applyMatrix4(e.matrixWorld),this.intersectsSphere(t)}}(),intersectsSphere:function(t){for(var e=this.planes,n=t.center,i=-t.radius,r=0;r<6;r++){if(e[r].distanceToPoint(n)0?t.max.x:t.min.x,Ne.y=i.normal.y>0?t.max.y:t.min.y,Ne.z=i.normal.z>0?t.max.z:t.min.z,i.distanceToPoint(Ne)<0)return!1}return!0}),containsPoint:function(t){for(var e=this.planes,n=0;n<6;n++)if(e[n].distanceToPoint(t)<0)return!1;return!0}}),Object.assign(nn.prototype,{isMatrix4:!0,set:function(t,e,n,i,r,a,o,s,c,h,l,u,p,d,f,m){var g=this.elements;return g[0]=t,g[4]=e,g[8]=n,g[12]=i,g[1]=r,g[5]=a,g[9]=o,g[13]=s,g[2]=c,g[6]=h,g[10]=l,g[14]=u,g[3]=p,g[7]=d,g[11]=f,g[15]=m,this},identity:function(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this},clone:function(){return(new nn).fromArray(this.elements)},copy:function(t){var e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],e[9]=n[9],e[10]=n[10],e[11]=n[11],e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15],this},copyPosition:function(t){var e=this.elements,n=t.elements;return e[12]=n[12],e[13]=n[13],e[14]=n[14],this},extractBasis:function(t,e,n){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this},makeBasis:function(t,e,n){return this.set(t.x,e.x,n.x,0,t.y,e.y,n.y,0,t.z,e.z,n.z,0,0,0,0,1),this},extractRotation:function(){var t=new Le;return function(e){var n=this.elements,i=e.elements,r=1/t.setFromMatrixColumn(e,0).length(),a=1/t.setFromMatrixColumn(e,1).length(),o=1/t.setFromMatrixColumn(e,2).length();return n[0]=i[0]*r,n[1]=i[1]*r,n[2]=i[2]*r,n[3]=0,n[4]=i[4]*a,n[5]=i[5]*a,n[6]=i[6]*a,n[7]=0,n[8]=i[8]*o,n[9]=i[9]*o,n[10]=i[10]*o,n[11]=0,n[12]=0,n[13]=0,n[14]=0,n[15]=1,this}}(),makeRotationFromEuler:function(t){t&&t.isEuler||console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");var e=this.elements,n=t.x,i=t.y,r=t.z,a=Math.cos(n),o=Math.sin(n),s=Math.cos(i),c=Math.sin(i),h=Math.cos(r),l=Math.sin(r);if("XYZ"===t.order){var u=a*h,p=a*l,d=o*h,f=o*l;e[0]=s*h,e[4]=-s*l,e[8]=c,e[1]=p+d*c,e[5]=u-f*c,e[9]=-o*s,e[2]=f-u*c,e[6]=d+p*c,e[10]=a*s}else if("YXZ"===t.order){var m=s*h,g=s*l,v=c*h,y=c*l;e[0]=m+y*o,e[4]=v*o-g,e[8]=a*c,e[1]=a*l,e[5]=a*h,e[9]=-o,e[2]=g*o-v,e[6]=y+m*o,e[10]=a*s}else if("ZXY"===t.order){m=s*h,g=s*l,v=c*h,y=c*l;e[0]=m-y*o,e[4]=-a*l,e[8]=v+g*o,e[1]=g+v*o,e[5]=a*h,e[9]=y-m*o,e[2]=-a*c,e[6]=o,e[10]=a*s}else if("ZYX"===t.order){u=a*h,p=a*l,d=o*h,f=o*l;e[0]=s*h,e[4]=d*c-p,e[8]=u*c+f,e[1]=s*l,e[5]=f*c+u,e[9]=p*c-d,e[2]=-c,e[6]=o*s,e[10]=a*s}else if("YZX"===t.order){var x=a*s,b=a*c,w=o*s,_=o*c;e[0]=s*h,e[4]=_-x*l,e[8]=w*l+b,e[1]=l,e[5]=a*h,e[9]=-o*h,e[2]=-c*h,e[6]=b*l+w,e[10]=x-_*l}else if("XZY"===t.order){x=a*s,b=a*c,w=o*s,_=o*c;e[0]=s*h,e[4]=-l,e[8]=c*h,e[1]=x*l+_,e[5]=a*h,e[9]=b*l-w,e[2]=w*l-b,e[6]=o*h,e[10]=_*l+x}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this},makeRotationFromQuaternion:(ke=new Le(0,0,0),Ve=new Le(1,1,1),function(t){return this.compose(ke,t,Ve)}),lookAt:(Ge=new Le,Fe=new Le,He=new Le,function(t,e,n){var i=this.elements;return He.subVectors(t,e),0===He.lengthSq()&&(He.z=1),He.normalize(),Ge.crossVectors(n,He),0===Ge.lengthSq()&&(1===Math.abs(n.z)?He.x+=1e-4:He.z+=1e-4,He.normalize(),Ge.crossVectors(n,He)),Ge.normalize(),Fe.crossVectors(He,Ge),i[0]=Ge.x,i[4]=Fe.x,i[8]=He.x,i[1]=Ge.y,i[5]=Fe.y,i[9]=He.y,i[2]=Ge.z,i[6]=Fe.z,i[10]=He.z,this}),multiply:function(t,e){return void 0!==e?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(t,e)):this.multiplyMatrices(this,t)},premultiply:function(t){return this.multiplyMatrices(t,this)},multiplyMatrices:function(t,e){var n=t.elements,i=e.elements,r=this.elements,a=n[0],o=n[4],s=n[8],c=n[12],h=n[1],l=n[5],u=n[9],p=n[13],d=n[2],f=n[6],m=n[10],g=n[14],v=n[3],y=n[7],x=n[11],b=n[15],w=i[0],_=i[4],M=i[8],S=i[12],T=i[1],E=i[5],A=i[9],L=i[13],P=i[2],R=i[6],C=i[10],O=i[14],I=i[3],D=i[7],N=i[11],z=i[15];return r[0]=a*w+o*T+s*P+c*I,r[4]=a*_+o*E+s*R+c*D,r[8]=a*M+o*A+s*C+c*N,r[12]=a*S+o*L+s*O+c*z,r[1]=h*w+l*T+u*P+p*I,r[5]=h*_+l*E+u*R+p*D,r[9]=h*M+l*A+u*C+p*N,r[13]=h*S+l*L+u*O+p*z,r[2]=d*w+f*T+m*P+g*I,r[6]=d*_+f*E+m*R+g*D,r[10]=d*M+f*A+m*C+g*N,r[14]=d*S+f*L+m*O+g*z,r[3]=v*w+y*T+x*P+b*I,r[7]=v*_+y*E+x*R+b*D,r[11]=v*M+y*A+x*C+b*N,r[15]=v*S+y*L+x*O+b*z,this},multiplyScalar:function(t){var e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this},applyToBufferAttribute:function(){var t=new Le;return function(e){for(var n=0,i=e.count;n 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n#else\n\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t}\n\treturn 1.0;\n#endif\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\treturn specularColor * brdf.x + brdf.y;\n}\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tvec3 F = F_Schlick( specularColor, dotNV );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\tvec3 FssEss = F * brdf.x + brdf.y;\n\tfloat Ess = brdf.x + brdf.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG ) && ! defined( MATCAP )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG ) && ! defined( MATCAP )\n\tvarying vec3 vViewPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG ) && ! defined( MATCAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif",color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif",common:"#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV( sampler2D envMap, vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = normalMatrix * objectTangent;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",encodings_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",encodings_pars_fragment:"\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * value.a * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = cLogLuvM * value.rgb;\n\tXp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) );\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract( Le );\n\tvResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 );\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;\n\treturn vec4( max( vRGB, 0.0 ), 1.0 );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_pars_fragment:"#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent ));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tfogDepth = -mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float fogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif",lights_pars_begin:"uniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in GeometricContext geometry ) {\n\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef ENVMAP_TYPE_CUBE_UV\n\t\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#endif\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\tfloat clearCoatInv = 1.0 - clearCoatDHR;\n\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec3 singleScattering = vec3( 0.0 );\n\t\tvec3 multiScattering = vec3( 0.0 );\n\t\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\n\t\tvec3 diffuse = material.diffuseColor;\n\t\treflectedLight.indirectSpecular += clearCoatInv * radiance * singleScattering;\n\t\treflectedLight.indirectDiffuse += multiScattering * cosineWeightedIrradiance;\n\t\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n\t#else\n\t\treflectedLight.indirectSpecular += clearCoatInv * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#endif\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearCoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), maxMipLevel );\n\t#ifndef STANDARD\n\t\tclearCoatRadiance += getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), maxMipLevel );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, irradiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif",map_particle_pars_fragment:"#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif",normal_fragment_begin:"#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\tbitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t#endif\n\t#endif\n#endif",normal_fragment_maps:"#ifdef USE_NORMALMAP\n\t#ifdef OBJECTSPACE_NORMALMAP\n\t\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\t#ifdef FLIP_SIDED\n\t\t\tnormal = - normal;\n\t\t#endif\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t#endif\n\t\tnormal = normalize( normalMatrix * normal );\n\t#else\n\t\t#ifdef USE_TANGENT\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\t\tmapN.xy = normalScale * mapN.xy;\n\t\t\tnormal = normalize( vTBN * mapN );\n\t\t#else\n\t\t\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n\t\t#endif\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\t#ifdef OBJECTSPACE_NORMALMAP\n\t\tuniform mat3 normalMatrix;\n\t#else\n\t\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\t\tvec2 st0 = dFdx( vUv.st );\n\t\t\tvec2 st1 = dFdy( vUv.st );\n\t\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\n\t\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\t\tvec3 N = normalize( surf_norm );\n\t\t\tmat3 tsn = mat3( S, T, N );\n\t\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\t\tmapN.xy *= normalScale;\n\t\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\treturn normalize( tsn * mapN );\n\t\t}\n\t#endif\n#endif",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#if defined( DITHERING )\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( ( color * ( 2.51 * color + 0.03 ) ) / ( color * ( 2.43 * color + 0.59 ) + 0.14 ) );\n}",uv_pars_fragment:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif",uv_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif",background_frag:"uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\t#else\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t\tmatcapColor = matcapTexelToLinear( matcapColor );\n\t#else\n\t\tvec4 matcapColor = vec4( 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifndef FLAT_SHADED\n\t\tvNormal = normalize( transformedNormal );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_frag:"#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}",normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}",shadow_vert:"#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}"};function an(t){var e={};for(var n in t)for(var i in e[n]={},t[n]){var r=t[n][i];r&&(r.isColor||r.isMatrix3||r.isMatrix4||r.isVector2||r.isVector3||r.isVector4||r.isTexture)?e[n][i]=r.clone():Array.isArray(r)?e[n][i]=r.slice():e[n][i]=r}return e}function on(t){for(var e={},n=0;n>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,this},setRGB:function(t,e,n){return this.r=t,this.g=e,this.b=n,this},setHSL:function(){function t(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+6*(e-t)*(2/3-n):t}return function(e,n,i){if(e=Te.euclideanModulo(e,1),n=Te.clamp(n,0,1),i=Te.clamp(i,0,1),0===n)this.r=this.g=this.b=i;else{var r=i<=.5?i*(1+n):i+n-i*n,a=2*i-r;this.r=t(a,r,e+1/3),this.g=t(a,r,e),this.b=t(a,r,e-1/3)}return this}}(),setStyle:function(t){function e(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}var n;if(n=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(t)){var i,r=n[1],a=n[2];switch(r){case"rgb":case"rgba":if(i=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a))return this.r=Math.min(255,parseInt(i[1],10))/255,this.g=Math.min(255,parseInt(i[2],10))/255,this.b=Math.min(255,parseInt(i[3],10))/255,e(i[5]),this;if(i=/^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a))return this.r=Math.min(100,parseInt(i[1],10))/100,this.g=Math.min(100,parseInt(i[2],10))/100,this.b=Math.min(100,parseInt(i[3],10))/100,e(i[5]),this;break;case"hsl":case"hsla":if(i=/^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a)){var o=parseFloat(i[1])/360,s=parseInt(i[2],10)/100,c=parseInt(i[3],10)/100;return e(i[5]),this.setHSL(o,s,c)}}}else if(n=/^\#([A-Fa-f0-9]+)$/.exec(t)){var h,l=(h=n[1]).length;if(3===l)return this.r=parseInt(h.charAt(0)+h.charAt(0),16)/255,this.g=parseInt(h.charAt(1)+h.charAt(1),16)/255,this.b=parseInt(h.charAt(2)+h.charAt(2),16)/255,this;if(6===l)return this.r=parseInt(h.charAt(0)+h.charAt(1),16)/255,this.g=parseInt(h.charAt(2)+h.charAt(3),16)/255,this.b=parseInt(h.charAt(4)+h.charAt(5),16)/255,this}t&&t.length>0&&(void 0!==(h=ln[t])?this.setHex(h):console.warn("THREE.Color: Unknown color "+t));return this},clone:function(){return new this.constructor(this.r,this.g,this.b)},copy:function(t){return this.r=t.r,this.g=t.g,this.b=t.b,this},copyGammaToLinear:function(t,e){return void 0===e&&(e=2),this.r=Math.pow(t.r,e),this.g=Math.pow(t.g,e),this.b=Math.pow(t.b,e),this},copyLinearToGamma:function(t,e){void 0===e&&(e=2);var n=e>0?1/e:1;return this.r=Math.pow(t.r,n),this.g=Math.pow(t.g,n),this.b=Math.pow(t.b,n),this},convertGammaToLinear:function(t){return this.copyGammaToLinear(this,t),this},convertLinearToGamma:function(t){return this.copyLinearToGamma(this,t),this},copySRGBToLinear:function(){function t(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}return function(e){return this.r=t(e.r),this.g=t(e.g),this.b=t(e.b),this}}(),copyLinearToSRGB:function(){function t(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}return function(e){return this.r=t(e.r),this.g=t(e.g),this.b=t(e.b),this}}(),convertSRGBToLinear:function(){return this.copySRGBToLinear(this),this},convertLinearToSRGB:function(){return this.copyLinearToSRGB(this),this},getHex:function(){return 255*this.r<<16^255*this.g<<8^255*this.b<<0},getHexString:function(){return("000000"+this.getHex().toString(16)).slice(-6)},getHSL:function(t){void 0===t&&(console.warn("THREE.Color: .getHSL() target is now required"),t={h:0,s:0,l:0});var e,n,i=this.r,r=this.g,a=this.b,o=Math.max(i,r,a),s=Math.min(i,r,a),c=(s+o)/2;if(s===o)e=0,n=0;else{var h=o-s;switch(n=c<=.5?h/(o+s):h/(2-o-s),o){case i:e=(r-a)/h+(r1){for(var e=0;e1){for(var e=0;e0){i.children=[];for(s=0;s0&&(n.geometries=u),p.length>0&&(n.materials=p),d.length>0&&(n.textures=d),f.length>0&&(n.images=f),o.length>0&&(n.shapes=o)}return n.object=i,n;function m(t){var e=[];for(var n in t){var i=t[n];delete i.metadata,e.push(i)}return e}},clone:function(t){return(new this.constructor).copy(this,t)},copy:function(t,e){if(void 0===e&&(e=!0),this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(var n=0;ne&&(e=t[n]);return e}Pn.prototype=Object.assign(Object.create(i.prototype),{constructor:Pn,isGeometry:!0,applyMatrix:function(t){for(var e=(new Pe).getNormalMatrix(t),n=0,i=this.vertices.length;n0)for(h=0;h0&&(this.normalsNeedUpdate=!0)},computeFlatVertexNormals:function(){var t,e,n;for(this.computeFaceNormals(),t=0,e=this.faces.length;t0&&(this.normalsNeedUpdate=!0)},computeMorphNormals:function(){var t,e,n,i,r;for(n=0,i=this.faces.length;n=0;n--){var f=p[n];for(this.faces.splice(f,1),o=0,s=this.faceVertexUvs.length;o0,g=d.vertexNormals.length>0,v=1!==d.color.r||1!==d.color.g||1!==d.color.b,y=d.vertexColors.length>0,x=0;if(x=M(x,0,0),x=M(x,1,!0),x=M(x,2,!1),x=M(x,3,f),x=M(x,4,m),x=M(x,5,g),x=M(x,6,v),x=M(x,7,y),o.push(x),o.push(d.a,d.b,d.c),o.push(d.materialIndex),f){var b=this.faceVertexUvs[0][r];o.push(E(b[0]),E(b[1]),E(b[2]))}if(m&&o.push(S(d.normal)),g){var w=d.vertexNormals;o.push(S(w[0]),S(w[1]),S(w[2]))}if(v&&o.push(T(d.color)),y){var _=d.vertexColors;o.push(T(_[0]),T(_[1]),T(_[2]))}}function M(t,e,n){return n?t|1<0&&(t.data.colors=h),u.length>0&&(t.data.uvs=[u]),t.data.faces=o,t},clone:function(){return(new Pn).copy(this)},copy:function(t){var e,n,i,r,a,o;this.vertices=[],this.colors=[],this.faces=[],this.faceVertexUvs=[[]],this.morphTargets=[],this.morphNormals=[],this.skinWeights=[],this.skinIndices=[],this.lineDistances=[],this.boundingBox=null,this.boundingSphere=null,this.name=t.name;var s=t.vertices;for(e=0,n=s.length;e0,o=r[1]&&r[1].length>0,s=t.morphTargets,c=s.length;if(c>0){e=[];for(var h=0;h0){l=[];for(h=0;h0&&0===n.length&&console.error("THREE.DirectGeometry: Faceless geometries are not supported.");for(h=0;h0?1:-1,h.push(P.x,P.y,P.z),l.push(y/m),l.push(1-x/g),A+=1}}for(x=0;x65535?Bn:Nn)(t,1):this.index=t},addAttribute:function(t,e){return e&&e.isBufferAttribute||e&&e.isInterleavedBufferAttribute?"index"===t?(console.warn("THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute."),this.setIndex(e),this):(this.attributes[t]=e,this):(console.warn("THREE.BufferGeometry: .addAttribute() now expects ( name, attribute )."),this.addAttribute(t,new Rn(arguments[1],arguments[2])))},getAttribute:function(t){return this.attributes[t]},removeAttribute:function(t){return delete this.attributes[t],this},addGroup:function(t,e,n){this.groups.push({start:t,count:e,materialIndex:void 0!==n?n:0})},clearGroups:function(){this.groups=[]},setDrawRange:function(t,e){this.drawRange.start=t,this.drawRange.count=e},applyMatrix:function(t){var e=this.attributes.position;void 0!==e&&(t.applyToBufferAttribute(e),e.needsUpdate=!0);var n=this.attributes.normal;void 0!==n&&((new Pe).getNormalMatrix(t).applyToBufferAttribute(n),n.needsUpdate=!0);var i=this.attributes.tangent;void 0!==i&&((new Pe).getNormalMatrix(t).applyToBufferAttribute(i),i.needsUpdate=!0);return null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this},rotateX:function(){var t=new nn;return function(e){return t.makeRotationX(e),this.applyMatrix(t),this}}(),rotateY:function(){var t=new nn;return function(e){return t.makeRotationY(e),this.applyMatrix(t),this}}(),rotateZ:function(){var t=new nn;return function(e){return t.makeRotationZ(e),this.applyMatrix(t),this}}(),translate:function(){var t=new nn;return function(e,n,i){return t.makeTranslation(e,n,i),this.applyMatrix(t),this}}(),scale:function(){var t=new nn;return function(e,n,i){return t.makeScale(e,n,i),this.applyMatrix(t),this}}(),lookAt:function(){var t=new Tn;return function(e){t.lookAt(e),t.updateMatrix(),this.applyMatrix(t.matrix)}}(),center:function(){var t=new Le;return function(){return this.computeBoundingBox(),this.boundingBox.getCenter(t).negate(),this.translate(t.x,t.y,t.z),this}}(),setFromObject:function(t){var e=t.geometry;if(t.isPoints||t.isLine){var n=new Un(3*e.vertices.length,3),i=new Un(3*e.colors.length,3);if(this.addAttribute("position",n.copyVector3sArray(e.vertices)),this.addAttribute("color",i.copyColorsArray(e.colors)),e.lineDistances&&e.lineDistances.length===e.vertices.length){var r=new Un(e.lineDistances.length,1);this.addAttribute("lineDistance",r.copyArray(e.lineDistances))}null!==e.boundingSphere&&(this.boundingSphere=e.boundingSphere.clone()),null!==e.boundingBox&&(this.boundingBox=e.boundingBox.clone())}else t.isMesh&&e&&e.isGeometry&&this.fromGeometry(e);return this},setFromPoints:function(t){for(var e=[],n=0,i=t.length;n0){var n=new Float32Array(3*t.normals.length);this.addAttribute("normal",new Rn(n,3).copyVector3sArray(t.normals))}if(t.colors.length>0){var i=new Float32Array(3*t.colors.length);this.addAttribute("color",new Rn(i,3).copyColorsArray(t.colors))}if(t.uvs.length>0){var r=new Float32Array(2*t.uvs.length);this.addAttribute("uv",new Rn(r,2).copyVector2sArray(t.uvs))}if(t.uvs2.length>0){var a=new Float32Array(2*t.uvs2.length);this.addAttribute("uv2",new Rn(a,2).copyVector2sArray(t.uvs2))}for(var o in this.groups=t.groups,t.morphTargets){for(var s=[],c=t.morphTargets[o],h=0,l=c.length;h0){var d=new Un(4*t.skinIndices.length,4);this.addAttribute("skinIndex",d.copyVector4sArray(t.skinIndices))}if(t.skinWeights.length>0){var f=new Un(4*t.skinWeights.length,4);this.addAttribute("skinWeight",f.copyVector4sArray(t.skinWeights))}return null!==t.boundingSphere&&(this.boundingSphere=t.boundingSphere.clone()),null!==t.boundingBox&&(this.boundingBox=t.boundingBox.clone()),this},computeBoundingBox:function(){var t=new Ke;return function(){null===this.boundingBox&&(this.boundingBox=new Ke);var e=this.attributes.position,n=this.morphAttributes.position;if(void 0!==e){if(this.boundingBox.setFromBufferAttribute(e),n)for(var i=0,r=n.length;i0&&(t.userData=this.userData),void 0!==this.parameters){var e=this.parameters;for(var n in e)void 0!==e[n]&&(t[n]=e[n]);return t}t.data={attributes:{}};var i=this.index;null!==i&&(t.data.index={type:i.array.constructor.name,array:Array.prototype.slice.call(i.array)});var r=this.attributes;for(var n in r){var a={itemSize:(p=r[n]).itemSize,type:p.array.constructor.name,array:Array.prototype.slice.call(p.array),normalized:p.normalized};""!==p.name&&(a.name=p.name),t.data.attributes[n]=a}var o={},s=!1;for(var n in this.morphAttributes){for(var c=this.morphAttributes[n],h=[],l=0,u=c.length;l0&&(o[n]=h,s=!0)}s&&(t.data.morphAttributes=o);var d=this.groups;d.length>0&&(t.data.groups=JSON.parse(JSON.stringify(d)));var f=this.boundingSphere;return null!==f&&(t.data.boundingSphere={center:f.center.toArray(),radius:f.radius}),t},clone:function(){return(new Vn).copy(this)},copy:function(t){var e,n,i;this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.name=t.name;var r=t.index;null!==r&&this.setIndex(r.clone());var a=t.attributes;for(e in a){var o=a[e];this.addAttribute(e,o.clone())}var s=t.morphAttributes;for(e in s){var c=[],h=s[e];for(n=0,i=h.length;n0&&(n.alphaTest=this.alphaTest),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(n.wireframe=this.wireframe),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.morphTargets&&(n.morphTargets=!0),!0===this.skinning&&(n.skinning=!0),!1===this.visible&&(n.visible=!1),"{}"!==JSON.stringify(this.userData)&&(n.userData=this.userData),e){var r=i(t.textures),a=i(t.images);r.length>0&&(n.textures=r),a.length>0&&(n.images=a)}return n},clone:function(){return(new this.constructor).copy(this)},copy:function(t){this.name=t.name,this.fog=t.fog,this.lights=t.lights,this.blending=t.blending,this.side=t.side,this.flatShading=t.flatShading,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.premultipliedAlpha=t.premultipliedAlpha,this.visible=t.visible,this.userData=JSON.parse(JSON.stringify(t.userData)),this.clipShadows=t.clipShadows,this.clipIntersection=t.clipIntersection;var e=t.clippingPlanes,n=null;if(null!==e){var i=e.length;n=new Array(i);for(var r=0;r!==i;++r)n[r]=e[r].clone()}return this.clippingPlanes=n,this.shadowSide=t.shadowSide,this},dispose:function(){this.dispatchEvent({type:"dispose"})}});var Zn,Qn,Kn,$n,ti,ei,ni,ii,ri,ai,oi,si,ci="void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",hi="void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";function li(t){Jn.call(this),this.type="ShaderMaterial",this.defines={},this.uniforms={},this.vertexShader=ci,this.fragmentShader=hi,this.linewidth=1,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.lights=!1,this.clipping=!1,this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.extensions={derivatives:!1,fragDepth:!1,drawBuffers:!1,shaderTextureLOD:!1},this.defaultAttributeValues={color:[1,1,1],uv:[0,0],uv2:[0,0]},this.index0AttributeName=void 0,this.uniformsNeedUpdate=!1,void 0!==t&&(void 0!==t.attributes&&console.error("THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead."),this.setValues(t))}function ui(t,e){this.origin=void 0!==t?t:new Le,this.direction=void 0!==e?e:new Le}function pi(t,e,n){this.a=void 0!==t?t:new Le,this.b=void 0!==e?e:new Le,this.c=void 0!==n?n:new Le}function di(t){Jn.call(this),this.type="MeshBasicMaterial",this.color=new un(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=J,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.skinning=!1,this.morphTargets=!1,this.lights=!1,this.setValues(t)}function fi(t,e){Tn.call(this),this.type="Mesh",this.geometry=void 0!==t?t:new Vn,this.material=void 0!==e?e:new di({color:16777215*Math.random()}),this.drawMode=ue,this.updateMorphTargets()}function mi(t,e,n,i){var r,a,o=new un(0),s=0,c=null,h=0;function l(t,n){e.buffers.color.setClear(t.r,t.g,t.b,n,i)}return{getClearColor:function(){return o},setClearColor:function(t,e){o.set(t),l(o,s=void 0!==e?e:1)},getClearAlpha:function(){return s},setClearAlpha:function(t){l(o,s=t)},render:function(e,i,u,p){var m=i.background,g=t.vr,v=g.getSession&&g.getSession();if(v&&"additive"===v.environmentBlendMode&&(m=null),null===m?(l(o,s),c=null,h=0):m&&m.isColor&&(l(m,1),p=!0,c=null,h=0),(t.autoClear||p)&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),m&&(m.isCubeTexture||m.isWebGLRenderTargetCube)){void 0===a&&((a=new fi(new Wn(1,1,1),new li({type:"BackgroundCubeMaterial",uniforms:an(fn.cube.uniforms),vertexShader:fn.cube.vertexShader,fragmentShader:fn.cube.fragmentShader,side:f,depthTest:!1,depthWrite:!1,fog:!1}))).geometry.removeAttribute("normal"),a.geometry.removeAttribute("uv"),a.onBeforeRender=function(t,e,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(a.material,"map",{get:function(){return this.uniforms.tCube.value}}),n.update(a));var y=m.isWebGLRenderTargetCube?m.texture:m;a.material.uniforms.tCube.value=y,a.material.uniforms.tFlip.value=m.isWebGLRenderTargetCube?1:-1,c===m&&h===y.version||(a.material.needsUpdate=!0,c=m,h=y.version),e.unshift(a,a.geometry,a.material,0,0,null)}else m&&m.isTexture&&(void 0===r&&((r=new fi(new Xn(2,2),new li({type:"BackgroundMaterial",uniforms:an(fn.background.uniforms),vertexShader:fn.background.vertexShader,fragmentShader:fn.background.fragmentShader,side:d,depthTest:!1,depthWrite:!1,fog:!1}))).geometry.removeAttribute("normal"),Object.defineProperty(r.material,"map",{get:function(){return this.uniforms.t2D.value}}),n.update(r)),r.material.uniforms.t2D.value=m,!0===m.matrixAutoUpdate&&m.updateMatrix(),r.material.uniforms.uvTransform.value.copy(m.matrix),c===m&&h===m.version||(r.material.needsUpdate=!0,c=m,h=m.version),e.unshift(r,r.geometry,r.material,0,0,null))}}}function gi(t,e,n,i){var r;this.setMode=function(t){r=t},this.render=function(e,i){t.drawArrays(r,e,i),n.update(i,r)},this.renderInstances=function(a,o,s){var c;if(i.isWebGL2)c=t;else if(null===(c=e.get("ANGLE_instanced_arrays")))return void console.error("THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.");c[i.isWebGL2?"drawArraysInstanced":"drawArraysInstancedANGLE"](r,o,s,a.maxInstancedCount),n.update(s,r,a.maxInstancedCount)}}function vi(t,e,n){var i;function r(e){if("highp"===e){if(t.getShaderPrecisionFormat(35633,36338).precision>0&&t.getShaderPrecisionFormat(35632,36338).precision>0)return"highp";e="mediump"}return"mediump"===e&&t.getShaderPrecisionFormat(35633,36337).precision>0&&t.getShaderPrecisionFormat(35632,36337).precision>0?"mediump":"lowp"}var a="undefined"!=typeof WebGL2RenderingContext&&t instanceof WebGL2RenderingContext,o=void 0!==n.precision?n.precision:"highp",s=r(o);s!==o&&(console.warn("THREE.WebGLRenderer:",o,"not supported, using",s,"instead."),o=s);var c=!0===n.logarithmicDepthBuffer,h=t.getParameter(34930),l=t.getParameter(35660),u=t.getParameter(3379),p=t.getParameter(34076),d=t.getParameter(34921),f=t.getParameter(36347),m=t.getParameter(36348),g=t.getParameter(36349),v=l>0,y=a||!!e.get("OES_texture_float");return{isWebGL2:a,getMaxAnisotropy:function(){if(void 0!==i)return i;var n=e.get("EXT_texture_filter_anisotropic");return i=null!==n?t.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT):0},getMaxPrecision:r,precision:o,logarithmicDepthBuffer:c,maxTextures:h,maxVertexTextures:l,maxTextureSize:u,maxCubemapSize:p,maxAttributes:d,maxVertexUniforms:f,maxVaryings:m,maxFragmentUniforms:g,vertexTextures:v,floatFragmentTextures:y,floatVertexTextures:v&&y,maxSamples:a?t.getParameter(36183):0}}function yi(){var t=this,e=null,n=0,i=!1,r=!1,a=new tn,o=new Pe,s={value:null,needsUpdate:!1};function c(){s.value!==e&&(s.value=e,s.needsUpdate=n>0),t.numPlanes=n,t.numIntersection=0}function h(e,n,i,r){var c=null!==e?e.length:0,h=null;if(0!==c){if(h=s.value,!0!==r||null===h){var l=i+4*c,u=n.matrixWorldInverse;o.getNormalMatrix(u),(null===h||h.length65535?Bn:Nn)(a,1),e.update(n,34963),r[t.id]=n,n}}}function wi(t,e,n,i){var r,a,o;this.setMode=function(t){r=t},this.setIndex=function(t){a=t.type,o=t.bytesPerElement},this.render=function(e,i){t.drawElements(r,i,a,e*o),n.update(i,r)},this.renderInstances=function(s,c,h){var l;if(i.isWebGL2)l=t;else if(null===(l=e.get("ANGLE_instanced_arrays")))return void console.error("THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.");l[i.isWebGL2?"drawElementsInstanced":"drawElementsInstancedANGLE"](r,h,a,c*o,s.maxInstancedCount),n.update(h,r,s.maxInstancedCount)}}function _i(t){var e={frame:0,calls:0,triangles:0,points:0,lines:0};return{memory:{geometries:0,textures:0},render:e,programs:null,autoReset:!0,reset:function(){e.frame++,e.calls=0,e.triangles=0,e.points=0,e.lines=0},update:function(t,n,i){switch(i=i||1,e.calls++,n){case 4:e.triangles+=i*(t/3);break;case 5:case 6:e.triangles+=i*(t-2);break;case 1:e.lines+=i*(t/2);break;case 3:e.lines+=i*(t-1);break;case 2:e.lines+=i*t;break;case 0:e.points+=i*t;break;default:console.error("THREE.WebGLInfo: Unknown draw mode:",n)}}}}function Mi(t,e){return Math.abs(e[1])-Math.abs(t[1])}function Si(t){var e={},n=new Float32Array(8);return{update:function(i,r,a,o){var s=i.morphTargetInfluences,c=s.length,h=e[r.id];if(void 0===h){h=[];for(var l=0;l0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader;var r={};for(var a in this.extensions)!0===this.extensions[a]&&(r[a]=!0);return Object.keys(r).length>0&&(e.extensions=r),e},Object.assign(ui.prototype,{set:function(t,e){return this.origin.copy(t),this.direction.copy(e),this},clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this},at:function(t,e){return void 0===e&&(console.warn("THREE.Ray: .at() target is now required"),e=new Le),e.copy(this.direction).multiplyScalar(t).add(this.origin)},lookAt:function(t){return this.direction.copy(t).sub(this.origin).normalize(),this},recast:function(){var t=new Le;return function(e){return this.origin.copy(this.at(e,t)),this}}(),closestPointToPoint:function(t,e){void 0===e&&(console.warn("THREE.Ray: .closestPointToPoint() target is now required"),e=new Le),e.subVectors(t,this.origin);var n=e.dot(this.direction);return n<0?e.copy(this.origin):e.copy(this.direction).multiplyScalar(n).add(this.origin)},distanceToPoint:function(t){return Math.sqrt(this.distanceSqToPoint(t))},distanceSqToPoint:function(){var t=new Le;return function(e){var n=t.subVectors(e,this.origin).dot(this.direction);return n<0?this.origin.distanceToSquared(e):(t.copy(this.direction).multiplyScalar(n).add(this.origin),t.distanceToSquared(e))}}(),distanceSqToSegment:(Qn=new Le,Kn=new Le,$n=new Le,function(t,e,n,i){Qn.copy(t).add(e).multiplyScalar(.5),Kn.copy(e).sub(t).normalize(),$n.copy(this.origin).sub(Qn);var r,a,o,s,c=.5*t.distanceTo(e),h=-this.direction.dot(Kn),l=$n.dot(this.direction),u=-$n.dot(Kn),p=$n.lengthSq(),d=Math.abs(1-h*h);if(d>0)if(a=h*l-u,s=c*d,(r=h*u-l)>=0)if(a>=-s)if(a<=s){var f=1/d;o=(r*=f)*(r+h*(a*=f)+2*l)+a*(h*r+a+2*u)+p}else a=c,o=-(r=Math.max(0,-(h*a+l)))*r+a*(a+2*u)+p;else a=-c,o=-(r=Math.max(0,-(h*a+l)))*r+a*(a+2*u)+p;else a<=-s?o=-(r=Math.max(0,-(-h*c+l)))*r+(a=r>0?-c:Math.min(Math.max(-c,-u),c))*(a+2*u)+p:a<=s?(r=0,o=(a=Math.min(Math.max(-c,-u),c))*(a+2*u)+p):o=-(r=Math.max(0,-(h*c+l)))*r+(a=r>0?c:Math.min(Math.max(-c,-u),c))*(a+2*u)+p;else a=h>0?-c:c,o=-(r=Math.max(0,-(h*a+l)))*r+a*(a+2*u)+p;return n&&n.copy(this.direction).multiplyScalar(r).add(this.origin),i&&i.copy(Kn).multiplyScalar(a).add(Qn),o}),intersectSphere:function(){var t=new Le;return function(e,n){t.subVectors(e.center,this.origin);var i=t.dot(this.direction),r=t.dot(t)-i*i,a=e.radius*e.radius;if(r>a)return null;var o=Math.sqrt(a-r),s=i-o,c=i+o;return s<0&&c<0?null:s<0?this.at(c,n):this.at(s,n)}}(),intersectsSphere:function(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius},distanceToPlane:function(t){var e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;var n=-(this.origin.dot(t.normal)+t.constant)/e;return n>=0?n:null},intersectPlane:function(t,e){var n=this.distanceToPlane(t);return null===n?null:this.at(n,e)},intersectsPlane:function(t){var e=t.distanceToPoint(this.origin);return 0===e||t.normal.dot(this.direction)*e<0},intersectBox:function(t,e){var n,i,r,a,o,s,c=1/this.direction.x,h=1/this.direction.y,l=1/this.direction.z,u=this.origin;return c>=0?(n=(t.min.x-u.x)*c,i=(t.max.x-u.x)*c):(n=(t.max.x-u.x)*c,i=(t.min.x-u.x)*c),h>=0?(r=(t.min.y-u.y)*h,a=(t.max.y-u.y)*h):(r=(t.max.y-u.y)*h,a=(t.min.y-u.y)*h),n>a||r>i?null:((r>n||n!=n)&&(n=r),(a=0?(o=(t.min.z-u.z)*l,s=(t.max.z-u.z)*l):(o=(t.max.z-u.z)*l,s=(t.min.z-u.z)*l),n>s||o>i?null:((o>n||n!=n)&&(n=o),(s=0?n:i,e)))},intersectsBox:(Zn=new Le,function(t){return null!==this.intersectBox(t,Zn)}),intersectTriangle:function(){var t=new Le,e=new Le,n=new Le,i=new Le;return function(r,a,o,s,c){e.subVectors(a,r),n.subVectors(o,r),i.crossVectors(e,n);var h,l=this.direction.dot(i);if(l>0){if(s)return null;h=1}else{if(!(l<0))return null;h=-1,l=-l}t.subVectors(this.origin,r);var u=h*this.direction.dot(n.crossVectors(t,n));if(u<0)return null;var p=h*this.direction.dot(e.cross(t));if(p<0)return null;if(u+p>l)return null;var d=-h*t.dot(i);return d<0?null:this.at(d/l,c)}}(),applyMatrix4:function(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this},equals:function(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}}),Object.assign(pi,{getNormal:(ei=new Le,function(t,e,n,i){void 0===i&&(console.warn("THREE.Triangle: .getNormal() target is now required"),i=new Le),i.subVectors(n,e),ei.subVectors(t,e),i.cross(ei);var r=i.lengthSq();return r>0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}),getBarycoord:function(){var t=new Le,e=new Le,n=new Le;return function(i,r,a,o,s){t.subVectors(o,r),e.subVectors(a,r),n.subVectors(i,r);var c=t.dot(t),h=t.dot(e),l=t.dot(n),u=e.dot(e),p=e.dot(n),d=c*u-h*h;if(void 0===s&&(console.warn("THREE.Triangle: .getBarycoord() target is now required"),s=new Le),0===d)return s.set(-2,-1,-1);var f=1/d,m=(u*l-h*p)*f,g=(c*p-h*l)*f;return s.set(1-m-g,g,m)}}(),containsPoint:function(){var t=new Le;return function(e,n,i,r){return pi.getBarycoord(e,n,i,r,t),t.x>=0&&t.y>=0&&t.x+t.y<=1}}(),getUV:(ti=new Le,function(t,e,n,i,r,a,o,s){return this.getBarycoord(t,e,n,i,ti),s.set(0,0),s.addScaledVector(r,ti.x),s.addScaledVector(a,ti.y),s.addScaledVector(o,ti.z),s})}),Object.assign(pi.prototype,{set:function(t,e,n){return this.a.copy(t),this.b.copy(e),this.c.copy(n),this},setFromPointsAndIndices:function(t,e,n,i){return this.a.copy(t[e]),this.b.copy(t[n]),this.c.copy(t[i]),this},clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this},getArea:function(){var t=new Le,e=new Le;return function(){return t.subVectors(this.c,this.b),e.subVectors(this.a,this.b),.5*t.cross(e).length()}}(),getMidpoint:function(t){return void 0===t&&(console.warn("THREE.Triangle: .getMidpoint() target is now required"),t=new Le),t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},getNormal:function(t){return pi.getNormal(this.a,this.b,this.c,t)},getPlane:function(t){return void 0===t&&(console.warn("THREE.Triangle: .getPlane() target is now required"),t=new Le),t.setFromCoplanarPoints(this.a,this.b,this.c)},getBarycoord:function(t,e){return pi.getBarycoord(t,this.a,this.b,this.c,e)},containsPoint:function(t){return pi.containsPoint(t,this.a,this.b,this.c)},getUV:function(t,e,n,i,r){return pi.getUV(t,this.a,this.b,this.c,e,n,i,r)},intersectsBox:function(t){return t.intersectsTriangle(this)},closestPointToPoint:(ni=new Le,ii=new Le,ri=new Le,ai=new Le,oi=new Le,si=new Le,function(t,e){void 0===e&&(console.warn("THREE.Triangle: .closestPointToPoint() target is now required"),e=new Le);var n,i,r=this.a,a=this.b,o=this.c;ni.subVectors(a,r),ii.subVectors(o,r),ai.subVectors(t,r);var s=ni.dot(ai),c=ii.dot(ai);if(s<=0&&c<=0)return e.copy(r);oi.subVectors(t,a);var h=ni.dot(oi),l=ii.dot(oi);if(h>=0&&l<=h)return e.copy(a);var u=s*l-h*c;if(u<=0&&s>=0&&h<=0)return n=s/(s-h),e.copy(r).addScaledVector(ni,n);si.subVectors(t,o);var p=ni.dot(si),d=ii.dot(si);if(d>=0&&p<=d)return e.copy(o);var f=p*c-s*d;if(f<=0&&c>=0&&d<=0)return i=c/(c-d),e.copy(r).addScaledVector(ii,i);var m=h*d-p*l;if(m<=0&&l-h>=0&&p-d>=0)return ri.subVectors(o,a),i=(l-h)/(l-h+(p-d)),e.copy(a).addScaledVector(ri,i);var g=1/(m+f+u);return n=f*g,i=u*g,e.copy(r).addScaledVector(ni,n).addScaledVector(ii,i)}),equals:function(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}),di.prototype=Object.create(Jn.prototype),di.prototype.constructor=di,di.prototype.isMeshBasicMaterial=!0,di.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this},fi.prototype=Object.assign(Object.create(Tn.prototype),{constructor:fi,isMesh:!0,setDrawMode:function(t){this.drawMode=t},copy:function(t){return Tn.prototype.copy.call(this,t),this.drawMode=t.drawMode,void 0!==t.morphTargetInfluences&&(this.morphTargetInfluences=t.morphTargetInfluences.slice()),void 0!==t.morphTargetDictionary&&(this.morphTargetDictionary=Object.assign({},t.morphTargetDictionary)),this},updateMorphTargets:function(){var t,e,n,i=this.geometry;if(i.isBufferGeometry){var r=i.morphAttributes,a=Object.keys(r);if(a.length>0){var o=r[a[0]];if(void 0!==o)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},t=0,e=o.length;t0&&console.error("THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.")}},raycast:function(){var t=new nn,e=new ui,n=new $e,i=new Le,r=new Le,a=new Le,o=new Le,s=new Le,c=new Le,h=new Le,l=new Le,u=new Le,p=new Ee,d=new Ee,g=new Ee,v=new Le,y=new Le;function x(t,e,n,i,r,a,o,s){if(null===(e.side===f?i.intersectTriangle(o,a,r,!0,s):i.intersectTriangle(r,a,o,e.side!==m,s)))return null;y.copy(s),y.applyMatrix4(t.matrixWorld);var c=n.ray.origin.distanceTo(y);return cn.far?null:{distance:c,point:y.clone(),object:t}}function b(t,e,n,f,m,y,b,w,_,M){i.fromBufferAttribute(m,w),r.fromBufferAttribute(m,_),a.fromBufferAttribute(m,M);var S=t.morphTargetInfluences;if(e.morphTargets&&y&&S){h.set(0,0,0),l.set(0,0,0),u.set(0,0,0);for(var T=0,E=y.length;T0&&(I=B);for(var U=0,G=z.length;U0)return t;var r=e*n,a=Ii[r];if(void 0===a&&(a=new Float32Array(r),Ii[r]=a),0!==e){i.toArray(a,0);for(var o=1,s=0;o!==e;++o)s+=n,t[o].toArray(a,s)}return a}function Gi(t,e){if(t.length!==e.length)return!1;for(var n=0,i=t.length;n/gm,function(t,e){var n=rn[e];if(void 0===n)throw new Error("Can not resolve #include <"+e+">");return Lr(n)})}function Pr(t){return t.replace(/#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,function(t,e,n,i){for(var r="",a=parseInt(e);a0?t.gammaFactor:1,S=o.isWebGL2?"":function(t,e,n){return[(t=t||{}).derivatives||e.envMapCubeUV||e.bumpMap||e.normalMap&&!e.objectSpaceNormalMap||e.flatShading?"#extension GL_OES_standard_derivatives : enable":"",(t.fragDepth||e.logarithmicDepthBuffer)&&n.get("EXT_frag_depth")?"#extension GL_EXT_frag_depth : enable":"",t.drawBuffers&&n.get("WEBGL_draw_buffers")?"#extension GL_EXT_draw_buffers : require":"",(t.shaderTextureLOD||e.envMap)&&n.get("EXT_shader_texture_lod")?"#extension GL_EXT_shader_texture_lod : enable":""].filter(Tr).join("\n")}(i.extensions,a,e),T=function(t){var e=[];for(var n in t){var i=t[n];!1!==i&&e.push("#define "+n+" "+i)}return e.join("\n")}(h),E=c.createProgram();if(i.isRawShaderMaterial?((y=[T].filter(Tr).join("\n")).length>0&&(y+="\n"),(x=[S,T].filter(Tr).join("\n")).length>0&&(x+="\n")):(y=["precision "+a.precision+" float;","precision "+a.precision+" int;","#define SHADER_NAME "+r.name,T,a.supportsVertexTextures?"#define VERTEX_TEXTURES":"","#define GAMMA_FACTOR "+M,"#define MAX_BONES "+a.maxBones,a.useFog&&a.fog?"#define USE_FOG":"",a.useFog&&a.fogExp?"#define FOG_EXP2":"",a.map?"#define USE_MAP":"",a.envMap?"#define USE_ENVMAP":"",a.envMap?"#define "+g:"",a.lightMap?"#define USE_LIGHTMAP":"",a.aoMap?"#define USE_AOMAP":"",a.emissiveMap?"#define USE_EMISSIVEMAP":"",a.bumpMap?"#define USE_BUMPMAP":"",a.normalMap?"#define USE_NORMALMAP":"",a.normalMap&&a.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",a.displacementMap&&a.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",a.specularMap?"#define USE_SPECULARMAP":"",a.roughnessMap?"#define USE_ROUGHNESSMAP":"",a.metalnessMap?"#define USE_METALNESSMAP":"",a.alphaMap?"#define USE_ALPHAMAP":"",a.vertexTangents?"#define USE_TANGENT":"",a.vertexColors?"#define USE_COLOR":"",a.flatShading?"#define FLAT_SHADED":"",a.skinning?"#define USE_SKINNING":"",a.useVertexTexture?"#define BONE_TEXTURE":"",a.morphTargets?"#define USE_MORPHTARGETS":"",a.morphNormals&&!1===a.flatShading?"#define USE_MORPHNORMALS":"",a.doubleSided?"#define DOUBLE_SIDED":"",a.flipSided?"#define FLIP_SIDED":"",a.shadowMapEnabled?"#define USE_SHADOWMAP":"",a.shadowMapEnabled?"#define "+f:"",a.sizeAttenuation?"#define USE_SIZEATTENUATION":"",a.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",a.logarithmicDepthBuffer&&(o.isWebGL2||e.get("EXT_frag_depth"))?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#ifdef USE_COLOR","\tattribute vec3 color;","#endif","#ifdef USE_MORPHTARGETS","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(Tr).join("\n"),x=[S,"precision "+a.precision+" float;","precision "+a.precision+" int;","#define SHADER_NAME "+r.name,T,a.alphaTest?"#define ALPHATEST "+a.alphaTest+(a.alphaTest%1?"":".0"):"","#define GAMMA_FACTOR "+M,a.useFog&&a.fog?"#define USE_FOG":"",a.useFog&&a.fogExp?"#define FOG_EXP2":"",a.map?"#define USE_MAP":"",a.matcap?"#define USE_MATCAP":"",a.envMap?"#define USE_ENVMAP":"",a.envMap?"#define "+m:"",a.envMap?"#define "+g:"",a.envMap?"#define "+v:"",a.lightMap?"#define USE_LIGHTMAP":"",a.aoMap?"#define USE_AOMAP":"",a.emissiveMap?"#define USE_EMISSIVEMAP":"",a.bumpMap?"#define USE_BUMPMAP":"",a.normalMap?"#define USE_NORMALMAP":"",a.normalMap&&a.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",a.specularMap?"#define USE_SPECULARMAP":"",a.roughnessMap?"#define USE_ROUGHNESSMAP":"",a.metalnessMap?"#define USE_METALNESSMAP":"",a.alphaMap?"#define USE_ALPHAMAP":"",a.vertexTangents?"#define USE_TANGENT":"",a.vertexColors?"#define USE_COLOR":"",a.gradientMap?"#define USE_GRADIENTMAP":"",a.flatShading?"#define FLAT_SHADED":"",a.doubleSided?"#define DOUBLE_SIDED":"",a.flipSided?"#define FLIP_SIDED":"",a.shadowMapEnabled?"#define USE_SHADOWMAP":"",a.shadowMapEnabled?"#define "+f:"",a.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",a.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",a.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",a.logarithmicDepthBuffer&&(o.isWebGL2||e.get("EXT_frag_depth"))?"#define USE_LOGDEPTHBUF_EXT":"",a.envMap&&(o.isWebGL2||e.get("EXT_shader_texture_lod"))?"#define TEXTURE_LOD_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;",a.toneMapping!==K?"#define TONE_MAPPING":"",a.toneMapping!==K?rn.tonemapping_pars_fragment:"",a.toneMapping!==K?Sr("toneMapping",a.toneMapping):"",a.dithering?"#define DITHERING":"",a.outputEncoding||a.mapEncoding||a.matcapEncoding||a.envMapEncoding||a.emissiveMapEncoding?rn.encodings_pars_fragment:"",a.mapEncoding?Mr("mapTexelToLinear",a.mapEncoding):"",a.matcapEncoding?Mr("matcapTexelToLinear",a.matcapEncoding):"",a.envMapEncoding?Mr("envMapTexelToLinear",a.envMapEncoding):"",a.emissiveMapEncoding?Mr("emissiveMapTexelToLinear",a.emissiveMapEncoding):"",a.outputEncoding?(b="linearToOutputTexel",w=a.outputEncoding,_=_r(w),"vec4 "+b+"( vec4 value ) { return LinearTo"+_[0]+_[1]+"; }"):"",a.depthPacking?"#define DEPTH_PACKING "+i.depthPacking:"","\n"].filter(Tr).join("\n")),l=Ar(l=Er(l=Lr(l),a),a),d=Ar(d=Er(d=Lr(d),a),a),l=Pr(l),d=Pr(d),o.isWebGL2&&!i.isRawShaderMaterial){var A=!1,L=/^\s*#version\s+300\s+es\s*\n/;i.isShaderMaterial&&null!==l.match(L)&&null!==d.match(L)&&(A=!0,l=l.replace(L,""),d=d.replace(L,"")),y=["#version 300 es\n","#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+y,x=["#version 300 es\n","#define varying in",A?"":"out highp vec4 pc_fragColor;",A?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+x}var P,R,C=x+d,O=br(c,35633,y+l,t.debug.checkShaderErrors),I=br(c,35632,C,t.debug.checkShaderErrors);if(c.attachShader(E,O),c.attachShader(E,I),void 0!==i.index0AttributeName?c.bindAttribLocation(E,0,i.index0AttributeName):!0===a.morphTargets&&c.bindAttribLocation(E,0,"position"),c.linkProgram(E),t.debug.checkShaderErrors){var D=c.getProgramInfoLog(E).trim(),N=c.getShaderInfoLog(O).trim(),z=c.getShaderInfoLog(I).trim(),B=!0,U=!0;!1===c.getProgramParameter(E,35714)?(B=!1,console.error("THREE.WebGLProgram: shader error: ",c.getError(),"35715",c.getProgramParameter(E,35715),"gl.getProgramInfoLog",D,N,z)):""!==D?console.warn("THREE.WebGLProgram: gl.getProgramInfoLog()",D):""!==N&&""!==z||(U=!1),U&&(this.diagnostics={runnable:B,material:i,programLog:D,vertexShader:{log:N,prefix:y},fragmentShader:{log:z,prefix:x}})}return c.deleteShader(O),c.deleteShader(I),this.getUniforms=function(){return void 0===P&&(P=new xr(c,E,s)),P},this.getAttributes=function(){return void 0===R&&(R=function(t,e){for(var n={},i=t.getProgramParameter(e,35721),r=0;r0,maxBones:p,useVertexTexture:n.floatVertexTextures,morphTargets:e.morphTargets,morphNormals:e.morphNormals,maxMorphTargets:t.maxMorphTargets,maxMorphNormals:t.maxMorphNormals,numDirLights:i.directional.length,numPointLights:i.point.length,numSpotLights:i.spot.length,numRectAreaLights:i.rectArea.length,numHemiLights:i.hemi.length,numClippingPlanes:c,numClipIntersection:h,dithering:e.dithering,shadowMapEnabled:t.shadowMap.enabled&&l.receiveShadow&&r.length>0,shadowMapType:t.shadowMap.type,toneMapping:t.toneMapping,physicallyCorrectLights:t.physicallyCorrectLights,premultipliedAlpha:e.premultipliedAlpha,alphaTest:e.alphaTest,doubleSided:e.side===m,flipSided:e.side===f,depthPacking:void 0!==e.depthPacking&&e.depthPacking}},this.getProgramCode=function(e,n){var i=[];if(n.shaderID?i.push(n.shaderID):(i.push(e.fragmentShader),i.push(e.vertexShader)),void 0!==e.defines)for(var r in e.defines)i.push(r),i.push(e.defines[r]);for(var a=0;a1&&n.sort(Ir),i.length>1&&i.sort(Dr)}}}function zr(){var t={};function e(n){var i=n.target;i.removeEventListener("dispose",e),delete t[i.id]}return{get:function(n,i){var r,a=t[n.id];return void 0===a?(r=new Nr,t[n.id]={},t[n.id][i.id]=r,n.addEventListener("dispose",e)):void 0===(r=a[i.id])&&(r=new Nr,a[i.id]=r),r},dispose:function(){t={}}}}function Br(){var t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];var n;switch(e.type){case"DirectionalLight":n={direction:new Le,color:new un,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new Ee};break;case"SpotLight":n={position:new Le,direction:new Le,color:new un,distance:0,coneCos:0,penumbraCos:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new Ee};break;case"PointLight":n={position:new Le,color:new un,distance:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new Ee,shadowCameraNear:1,shadowCameraFar:1e3};break;case"HemisphereLight":n={direction:new Le,skyColor:new un,groundColor:new un};break;case"RectAreaLight":n={color:new un,position:new Le,halfWidth:new Le,halfHeight:new Le}}return t[e.id]=n,n}}}var Ur=0;function Gr(){for(var t=new Br,e={id:Ur++,hash:{stateID:-1,directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,shadowsLength:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],point:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]},n=0;n<9;n++)e.probe.push(new Le);var i=new Le,r=new nn,a=new nn;return{setup:function(n,o,s){for(var c=0,h=0,l=0,u=0;u<9;u++)e.probe[u].set(0,0,0);for(var p=0,d=0,f=0,m=0,g=0,v=s.matrixWorldInverse,y=(u=0,n.length);u0:s&&s.isGeometry&&(d=s.morphTargets&&s.morphTargets.length>0)),e.isSkinnedMesh&&!1===n.skinning&&console.warn("THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:",e);var f=e.isSkinnedMesh&&n.skinning,m=0;d&&(m|=h),f&&(m|=l),c=u[m]}if(t.localClippingEnabled&&!0===n.clipShadows&&0!==n.clippingPlanes.length){var x=c.uuid,w=n.uuid,_=y[x];void 0===_&&(_={},y[x]=_);var M=_[w];void 0===M&&(M=c.clone(),_[w]=M),c=M}return c.visible=n.visible,c.wireframe=n.wireframe,c.side=null!=n.shadowSide?n.shadowSide:b[n.side],c.clipShadows=n.clipShadows,c.clippingPlanes=n.clippingPlanes,c.clipIntersection=n.clipIntersection,c.wireframeLinewidth=n.wireframeLinewidth,c.linewidth=n.linewidth,i&&c.isMeshDistanceMaterial&&(c.referencePosition.copy(r),c.nearDistance=a,c.farDistance=o),c}function C(n,r,a,o){if(!1!==n.visible){if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&n.castShadow&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(a.matrixWorldInverse,n.matrixWorld);var s=e.update(n),h=n.material;if(Array.isArray(h))for(var l=s.groups,u=0,p=l.length;u=1):-1!==Q.indexOf("OpenGL ES")&&(Z=parseFloat(/^OpenGL\ ES\ ([0-9])/.exec(Q)[1]),J=Z>=2);var K=null,$={},tt=new Xe,et=new Xe;function nt(e,n,i){var r=new Uint8Array(4),a=t.createTexture();t.bindTexture(e,a),t.texParameteri(e,10241,9728),t.texParameteri(e,10240,9728);for(var o=0;oi||t.height>i)&&(r=i/Math.max(t.width,t.height)),r<1||!0===e){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){var a=e?Te.floorPowerOfTwo:Math.floor,o=a(r*t.width),c=a(r*t.height);void 0===s&&(s=l(o,c));var h=n?l(o,c):s;return h.width=o,h.height=c,h.getContext("2d").drawImage(t,0,0,o,c),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+t.width+"x"+t.height+") to ("+o+"x"+c+")."),h}return"data"in t&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+t.width+"x"+t.height+")."),t}return t}function p(t){return Te.isPowerOfTwo(t.width)&&Te.isPowerOfTwo(t.height)}function d(t,e){return t.generateMipmaps&&e&&t.minFilter!==ft&&t.minFilter!==vt}function f(e,n,r,a){t.generateMipmap(e),i.get(n).__maxMipLevel=Math.log(Math.max(r,a))*Math.LOG2E}function m(t,n){if(!r.isWebGL2)return t;var i=t;return 6403===t&&(5126===n&&(i=33326),5131===n&&(i=33325),5121===n&&(i=33321)),6407===t&&(5126===n&&(i=34837),5131===n&&(i=34843),5121===n&&(i=32849)),6408===t&&(5126===n&&(i=34836),5131===n&&(i=34842),5121===n&&(i=32856)),33325===i||33326===i||34842===i||34836===i?e.get("EXT_color_buffer_float"):34843!==i&&34837!==i||console.warn("THREE.WebGLRenderer: Floating point textures with RGB format not supported. Please use RGBA instead."),i}function g(t){return t===ft||t===mt||t===gt?9728:9729}function v(e){var n=e.target;n.removeEventListener("dispose",v),function(e){var n=i.get(e);if(void 0===n.__webglInit)return;t.deleteTexture(n.__webglTexture),i.remove(e)}(n),n.isVideoTexture&&delete c[n.id],o.memory.textures--}function y(e){var n=e.target;n.removeEventListener("dispose",y),function(e){var n=i.get(e),r=i.get(e.texture);if(!e)return;void 0!==r.__webglTexture&&t.deleteTexture(r.__webglTexture);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLRenderTargetCube)for(var a=0;a<6;a++)t.deleteFramebuffer(n.__webglFramebuffer[a]),n.__webglDepthbuffer&&t.deleteRenderbuffer(n.__webglDepthbuffer[a]);else t.deleteFramebuffer(n.__webglFramebuffer),n.__webglDepthbuffer&&t.deleteRenderbuffer(n.__webglDepthbuffer);i.remove(e.texture),i.remove(e)}(n),o.memory.textures--}var x=0;function b(t,e){var r=i.get(t);if(t.isVideoTexture&&function(t){var e=t.id,n=o.render.frame;c[e]!==n&&(c[e]=n,t.update())}(t),t.version>0&&r.__version!==t.version){var a=t.image;if(void 0===a)console.warn("THREE.WebGLRenderer: Texture marked for update but image is undefined");else{if(!1!==a.complete)return void T(r,t,e);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.activeTexture(33984+e),n.bindTexture(3553,r.__webglTexture)}function w(e,o){var s=i.get(e);if(6===e.image.length)if(e.version>0&&s.__version!==e.version){S(s,e),n.activeTexture(33984+o),n.bindTexture(34067,s.__webglTexture),t.pixelStorei(37440,e.flipY);for(var c=e&&e.isCompressedTexture,h=e.image[0]&&e.image[0].isDataTexture,l=[],g=0;g<6;g++)l[g]=c||h?h?e.image[g].image:e.image[g]:u(e.image[g],!1,!0,r.maxCubemapSize);var v=l[0],y=p(v)||r.isWebGL2,x=a.convert(e.format),b=a.convert(e.type),w=m(x,b);M(34067,e,y);for(g=0;g<6;g++)if(c)for(var _,T=l[g].mipmaps,E=0,A=T.length;E-1?n.compressedTexImage2D(34069+g,E,w,_.width,_.height,0,_.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()"):n.texImage2D(34069+g,E,w,_.width,_.height,0,x,b,_.data);else h?n.texImage2D(34069+g,0,w,l[g].width,l[g].height,0,x,b,l[g].data):n.texImage2D(34069+g,0,w,x,b,l[g]);s.__maxMipLevel=c?T.length-1:0,d(e,y)&&f(34067,e,v.width,v.height),s.__version=e.version,e.onUpdate&&e.onUpdate(e)}else n.activeTexture(33984+o),n.bindTexture(34067,s.__webglTexture)}function _(t,e){n.activeTexture(33984+e),n.bindTexture(34067,i.get(t).__webglTexture)}function M(n,o,s){var c;if(s?(t.texParameteri(n,10242,a.convert(o.wrapS)),t.texParameteri(n,10243,a.convert(o.wrapT)),32879!==n&&35866!==n||t.texParameteri(n,32882,a.convert(o.wrapR)),t.texParameteri(n,10240,a.convert(o.magFilter)),t.texParameteri(n,10241,a.convert(o.minFilter))):(t.texParameteri(n,10242,33071),t.texParameteri(n,10243,33071),32879!==n&&35866!==n||t.texParameteri(n,32882,33071),o.wrapS===pt&&o.wrapT===pt||console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping."),t.texParameteri(n,10240,g(o.magFilter)),t.texParameteri(n,10241,g(o.minFilter)),o.minFilter!==ft&&o.minFilter!==vt&&console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.")),c=e.get("EXT_texture_filter_anisotropic")){if(o.type===Et&&null===e.get("OES_texture_float_linear"))return;if(o.type===At&&null===(r.isWebGL2||e.get("OES_texture_half_float_linear")))return;(o.anisotropy>1||i.get(o).__currentAnisotropy)&&(t.texParameterf(n,c.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(o.anisotropy,r.getMaxAnisotropy())),i.get(o).__currentAnisotropy=o.anisotropy)}}function S(e,n){void 0===e.__webglInit&&(e.__webglInit=!0,n.addEventListener("dispose",v),e.__webglTexture=t.createTexture(),o.memory.textures++)}function T(e,i,o){var s=3553;i.isDataTexture2DArray&&(s=35866),i.isDataTexture3D&&(s=32879),S(e,i),n.activeTexture(33984+o),n.bindTexture(s,e.__webglTexture),t.pixelStorei(37440,i.flipY),t.pixelStorei(37441,i.premultiplyAlpha),t.pixelStorei(3317,i.unpackAlignment);var c=function(t){return!r.isWebGL2&&(t.wrapS!==pt||t.wrapT!==pt||t.minFilter!==ft&&t.minFilter!==vt)}(i)&&!1===p(i.image),h=u(i.image,c,!1,r.maxTextureSize),l=p(h)||r.isWebGL2,g=a.convert(i.format),v=a.convert(i.type),y=m(g,v);M(s,i,l);var x,b=i.mipmaps;if(i.isDepthTexture){if(y=6402,i.type===Et){if(!r.isWebGL2)throw new Error("Float Depth Texture only supported in WebGL2.0");y=36012}else r.isWebGL2&&(y=33189);i.format===Bt&&6402===y&&i.type!==Mt&&i.type!==Tt&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),i.type=Mt,v=a.convert(i.type)),i.format===Ut&&(y=34041,i.type!==Ct&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),i.type=Ct,v=a.convert(i.type))),n.texImage2D(3553,0,y,h.width,h.height,0,g,v,null)}else if(i.isDataTexture)if(b.length>0&&l){for(var w=0,_=b.length;w<_;w++)x=b[w],n.texImage2D(3553,w,y,x.width,x.height,0,g,v,x.data);i.generateMipmaps=!1,e.__maxMipLevel=b.length-1}else n.texImage2D(3553,0,y,h.width,h.height,0,g,v,h.data),e.__maxMipLevel=0;else if(i.isCompressedTexture){for(w=0,_=b.length;w<_;w++)x=b[w],i.format!==Dt&&i.format!==It?n.getCompressedTextureFormats().indexOf(g)>-1?n.compressedTexImage2D(3553,w,y,x.width,x.height,0,x.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()"):n.texImage2D(3553,w,y,x.width,x.height,0,g,v,x.data);e.__maxMipLevel=b.length-1}else if(i.isDataTexture2DArray)n.texImage3D(35866,0,y,h.width,h.height,h.depth,0,g,v,h.data),e.__maxMipLevel=0;else if(i.isDataTexture3D)n.texImage3D(32879,0,y,h.width,h.height,h.depth,0,g,v,h.data),e.__maxMipLevel=0;else if(b.length>0&&l){for(w=0,_=b.length;w<_;w++)x=b[w],n.texImage2D(3553,w,y,g,v,x);i.generateMipmaps=!1,e.__maxMipLevel=b.length-1}else n.texImage2D(3553,0,y,g,v,h),e.__maxMipLevel=0;d(i,l)&&f(3553,i,h.width,h.height),e.__version=i.version,i.onUpdate&&i.onUpdate(i)}function E(e,r,o,s){var c=a.convert(r.texture.format),h=a.convert(r.texture.type),l=m(c,h);n.texImage2D(s,0,l,r.width,r.height,0,c,h,null),t.bindFramebuffer(36160,e),t.framebufferTexture2D(36160,o,s,i.get(r.texture).__webglTexture,0),t.bindFramebuffer(36160,null)}function A(e,n,i){if(t.bindRenderbuffer(36161,e),n.depthBuffer&&!n.stencilBuffer){if(i){var r=P(n);t.renderbufferStorageMultisample(36161,r,33189,n.width,n.height)}else t.renderbufferStorage(36161,33189,n.width,n.height);t.framebufferRenderbuffer(36160,36096,36161,e)}else if(n.depthBuffer&&n.stencilBuffer){if(i){r=P(n);t.renderbufferStorageMultisample(36161,r,34041,n.width,n.height)}else t.renderbufferStorage(36161,34041,n.width,n.height);t.framebufferRenderbuffer(36160,33306,36161,e)}else{var o=m(a.convert(n.texture.format),a.convert(n.texture.type));if(i){r=P(n);t.renderbufferStorageMultisample(36161,r,o,n.width,n.height)}else t.renderbufferStorage(36161,o,n.width,n.height)}t.bindRenderbuffer(36161,null)}function L(e){var n=i.get(e),r=!0===e.isWebGLRenderTargetCube;if(e.depthTexture){if(r)throw new Error("target.depthTexture not supported in Cube render targets");!function(e,n){if(n&&n.isWebGLRenderTargetCube)throw new Error("Depth Texture with cube render targets is not supported");if(t.bindFramebuffer(36160,e),!n.depthTexture||!n.depthTexture.isDepthTexture)throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");i.get(n.depthTexture).__webglTexture&&n.depthTexture.image.width===n.width&&n.depthTexture.image.height===n.height||(n.depthTexture.image.width=n.width,n.depthTexture.image.height=n.height,n.depthTexture.needsUpdate=!0),b(n.depthTexture,0);var r=i.get(n.depthTexture).__webglTexture;if(n.depthTexture.format===Bt)t.framebufferTexture2D(36160,36096,3553,r,0);else{if(n.depthTexture.format!==Ut)throw new Error("Unknown depthTexture format");t.framebufferTexture2D(36160,33306,3553,r,0)}}(n.__webglFramebuffer,e)}else if(r){n.__webglDepthbuffer=[];for(var a=0;a<6;a++)t.bindFramebuffer(36160,n.__webglFramebuffer[a]),n.__webglDepthbuffer[a]=t.createRenderbuffer(),A(n.__webglDepthbuffer[a],e)}else t.bindFramebuffer(36160,n.__webglFramebuffer),n.__webglDepthbuffer=t.createRenderbuffer(),A(n.__webglDepthbuffer,e);t.bindFramebuffer(36160,null)}function P(t){return r.isWebGL2&&t.isWebGLMultisampleRenderTarget?Math.min(r.maxSamples,t.samples):0}var R=!1,C=!1;this.allocateTextureUnit=function(){var t=x;return t>=r.maxTextures&&console.warn("THREE.WebGLTextures: Trying to use "+t+" texture units while this GPU supports only "+r.maxTextures),x+=1,t},this.resetTextureUnits=function(){x=0},this.setTexture2D=b,this.setTexture2DArray=function(t,e){var r=i.get(t);t.version>0&&r.__version!==t.version?T(r,t,e):(n.activeTexture(33984+e),n.bindTexture(35866,r.__webglTexture))},this.setTexture3D=function(t,e){var r=i.get(t);t.version>0&&r.__version!==t.version?T(r,t,e):(n.activeTexture(33984+e),n.bindTexture(32879,r.__webglTexture))},this.setTextureCube=w,this.setTextureCubeDynamic=_,this.setupRenderTarget=function(e){var s=i.get(e),c=i.get(e.texture);e.addEventListener("dispose",y),c.__webglTexture=t.createTexture(),o.memory.textures++;var h=!0===e.isWebGLRenderTargetCube,l=!0===e.isWebGLMultisampleRenderTarget,u=p(e)||r.isWebGL2;if(h){s.__webglFramebuffer=[];for(var g=0;g<6;g++)s.__webglFramebuffer[g]=t.createFramebuffer()}else if(s.__webglFramebuffer=t.createFramebuffer(),l)if(r.isWebGL2){s.__webglMultisampledFramebuffer=t.createFramebuffer(),s.__webglColorRenderbuffer=t.createRenderbuffer(),t.bindRenderbuffer(36161,s.__webglColorRenderbuffer);var v=m(a.convert(e.texture.format),a.convert(e.texture.type)),x=P(e);t.renderbufferStorageMultisample(36161,x,v,e.width,e.height),t.bindFramebuffer(36160,s.__webglMultisampledFramebuffer),t.framebufferRenderbuffer(36160,36064,36161,s.__webglColorRenderbuffer),t.bindRenderbuffer(36161,null),e.depthBuffer&&(s.__webglDepthRenderbuffer=t.createRenderbuffer(),A(s.__webglDepthRenderbuffer,e,!0)),t.bindFramebuffer(36160,null)}else console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.");if(h){for(n.bindTexture(34067,c.__webglTexture),M(34067,e.texture,u),g=0;g<6;g++)E(s.__webglFramebuffer[g],e,36064,34069+g);d(e.texture,u)&&f(34067,e.texture,e.width,e.height),n.bindTexture(34067,null)}else n.bindTexture(3553,c.__webglTexture),M(3553,e.texture,u),E(s.__webglFramebuffer,e,36064,3553),d(e.texture,u)&&f(3553,e.texture,e.width,e.height),n.bindTexture(3553,null);e.depthBuffer&&L(e)},this.updateRenderTargetMipmap=function(t){var e=t.texture;if(d(e,p(t)||r.isWebGL2)){var a=t.isWebGLRenderTargetCube?34067:3553,o=i.get(e).__webglTexture;n.bindTexture(a,o),f(a,e,t.width,t.height),n.bindTexture(a,null)}},this.updateMultisampleRenderTarget=function(e){if(e.isWebGLMultisampleRenderTarget)if(r.isWebGL2){var n=i.get(e);t.bindFramebuffer(36008,n.__webglMultisampledFramebuffer),t.bindFramebuffer(36009,n.__webglFramebuffer);var a=e.width,o=e.height,s=16384;e.depthBuffer&&(s|=256),e.stencilBuffer&&(s|=1024),t.blitFramebuffer(0,0,a,o,0,0,a,o,s,9728)}else console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.")},this.safeSetTexture2D=function(t,e){t&&t.isWebGLRenderTarget&&(!1===R&&(console.warn("THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead."),R=!0),t=t.texture),b(t,e)},this.safeSetTextureCube=function(t,e){t&&t.isWebGLRenderTargetCube&&(!1===C&&(console.warn("THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead."),C=!0),t=t.texture),t&&t.isCubeTexture||Array.isArray(t.image)&&6===t.image.length?w(t,e):_(t,e)}}function Xr(t,e,n){return{convert:function(t){var i;if(t===ut)return 10497;if(t===pt)return 33071;if(t===dt)return 33648;if(t===ft)return 9728;if(t===mt)return 9984;if(t===gt)return 9986;if(t===vt)return 9729;if(t===yt)return 9985;if(t===xt)return 9987;if(t===bt)return 5121;if(t===Lt)return 32819;if(t===Pt)return 32820;if(t===Rt)return 33635;if(t===wt)return 5120;if(t===_t)return 5122;if(t===Mt)return 5123;if(t===St)return 5124;if(t===Tt)return 5125;if(t===Et)return 5126;if(t===At){if(n.isWebGL2)return 5131;if(null!==(i=e.get("OES_texture_half_float")))return i.HALF_FLOAT_OES}if(t===Ot)return 6406;if(t===It)return 6407;if(t===Dt)return 6408;if(t===Nt)return 6409;if(t===zt)return 6410;if(t===Bt)return 6402;if(t===Ut)return 34041;if(t===Gt)return 6403;if(t===T)return 32774;if(t===E)return 32778;if(t===A)return 32779;if(t===R)return 0;if(t===C)return 1;if(t===O)return 768;if(t===I)return 769;if(t===D)return 770;if(t===N)return 771;if(t===z)return 772;if(t===B)return 773;if(t===U)return 774;if(t===G)return 775;if(t===F)return 776;if((t===Ft||t===Ht||t===kt||t===Vt)&&null!==(i=e.get("WEBGL_compressed_texture_s3tc"))){if(t===Ft)return i.COMPRESSED_RGB_S3TC_DXT1_EXT;if(t===Ht)return i.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(t===kt)return i.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(t===Vt)return i.COMPRESSED_RGBA_S3TC_DXT5_EXT}if((t===jt||t===Wt||t===qt||t===Xt)&&null!==(i=e.get("WEBGL_compressed_texture_pvrtc"))){if(t===jt)return i.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(t===Wt)return i.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(t===qt)return i.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(t===Xt)return i.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}if(t===Yt&&null!==(i=e.get("WEBGL_compressed_texture_etc1")))return i.COMPRESSED_RGB_ETC1_WEBGL;if((t===Jt||t===Zt||t===Qt||t===Kt||t===$t||t===te||t===ee||t===ne||t===ie||t===re||t===ae||t===oe||t===se||t===ce)&&null!==(i=e.get("WEBGL_compressed_texture_astc")))return t;if(t===L||t===P){if(n.isWebGL2){if(t===L)return 32775;if(t===P)return 32776}if(null!==(i=e.get("EXT_blend_minmax"))){if(t===L)return i.MIN_EXT;if(t===P)return i.MAX_EXT}}if(t===Ct){if(n.isWebGL2)return 34042;if(null!==(i=e.get("WEBGL_depth_texture")))return i.UNSIGNED_INT_24_8_WEBGL}return 0}}}function Yr(){Tn.call(this),this.type="Group"}function Jr(){Tn.call(this),this.type="Camera",this.matrixWorldInverse=new nn,this.projectionMatrix=new nn,this.projectionMatrixInverse=new nn}function Zr(t,e,n,i){Jr.call(this),this.type="PerspectiveCamera",this.fov=void 0!==t?t:50,this.zoom=1,this.near=void 0!==n?n:.1,this.far=void 0!==i?i:2e3,this.focus=10,this.aspect=void 0!==e?e:1,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}function Qr(t){Zr.call(this),this.cameras=t||[]}kr.prototype=Object.create(Jn.prototype),kr.prototype.constructor=kr,kr.prototype.isMeshDepthMaterial=!0,kr.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.depthPacking=t.depthPacking,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this},Vr.prototype=Object.create(Jn.prototype),Vr.prototype.constructor=Vr,Vr.prototype.isMeshDistanceMaterial=!0,Vr.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.referencePosition.copy(t.referencePosition),this.nearDistance=t.nearDistance,this.farDistance=t.farDistance,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this},Yr.prototype=Object.assign(Object.create(Tn.prototype),{constructor:Yr,isGroup:!0}),Jr.prototype=Object.assign(Object.create(Tn.prototype),{constructor:Jr,isCamera:!0,copy:function(t,e){return Tn.prototype.copy.call(this,t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this},getWorldDirection:function(t){void 0===t&&(console.warn("THREE.Camera: .getWorldDirection() target is now required"),t=new Le),this.updateMatrixWorld(!0);var e=this.matrixWorld.elements;return t.set(-e[8],-e[9],-e[10]).normalize()},updateMatrixWorld:function(t){Tn.prototype.updateMatrixWorld.call(this,t),this.matrixWorldInverse.getInverse(this.matrixWorld)},clone:function(){return(new this.constructor).copy(this)}}),Zr.prototype=Object.assign(Object.create(Jr.prototype),{constructor:Zr,isPerspectiveCamera:!0,copy:function(t,e){return Jr.prototype.copy.call(this,t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this},setFocalLength:function(t){var e=.5*this.getFilmHeight()/t;this.fov=2*Te.RAD2DEG*Math.atan(e),this.updateProjectionMatrix()},getFocalLength:function(){var t=Math.tan(.5*Te.DEG2RAD*this.fov);return.5*this.getFilmHeight()/t},getEffectiveFOV:function(){return 2*Te.RAD2DEG*Math.atan(Math.tan(.5*Te.DEG2RAD*this.fov)/this.zoom)},getFilmWidth:function(){return this.filmGauge*Math.min(this.aspect,1)},getFilmHeight:function(){return this.filmGauge/Math.max(this.aspect,1)},setViewOffset:function(t,e,n,i,r,a){this.aspect=t/e,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()},clearViewOffset:function(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()},updateProjectionMatrix:function(){var t=this.near,e=t*Math.tan(.5*Te.DEG2RAD*this.fov)/this.zoom,n=2*e,i=this.aspect*n,r=-.5*i,a=this.view;if(null!==this.view&&this.view.enabled){var o=a.fullWidth,s=a.fullHeight;r+=a.offsetX*i/o,e-=a.offsetY*n/s,i*=a.width/o,n*=a.height/s}var c=this.filmOffset;0!==c&&(r+=t*c/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,e,e-n,t,this.far),this.projectionMatrixInverse.getInverse(this.projectionMatrix)},toJSON:function(t){var e=Tn.prototype.toJSON.call(this,t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}),Qr.prototype=Object.assign(Object.create(Zr.prototype),{constructor:Qr,isArrayCamera:!0});var Kr,$r,ta,ea,na,ia,ra=new Le,aa=new Le;function oa(t,e,n){ra.setFromMatrixPosition(e.matrixWorld),aa.setFromMatrixPosition(n.matrixWorld);var i=ra.distanceTo(aa),r=e.projectionMatrix.elements,a=n.projectionMatrix.elements,o=r[14]/(r[10]-1),s=r[14]/(r[10]+1),c=(r[9]+1)/r[5],h=(r[9]-1)/r[5],l=(r[8]-1)/r[0],u=(a[8]+1)/a[0],p=o*l,d=o*u,f=i/(-l+u),m=f*-l;e.matrixWorld.decompose(t.position,t.quaternion,t.scale),t.translateX(m),t.translateZ(f),t.matrixWorld.compose(t.position,t.quaternion,t.scale),t.matrixWorldInverse.getInverse(t.matrixWorld);var g=o+f,v=s+f,y=p-m,x=d+(i-m),b=c*s/v*g,w=h*s/v*g;t.projectionMatrix.makePerspective(y,x,b,w,g,v)}function sa(t){var e=this,n=null,i=null,r=null,a=[],o=new nn,s=new nn,c=1,h="stage";"undefined"!=typeof window&&"VRFrameData"in window&&(i=new window.VRFrameData,window.addEventListener("vrdisplaypresentchange",x,!1));var l=new nn,u=new Ae,p=new Le,d=new Zr;d.bounds=new Xe(0,0,.5,1),d.layers.enable(1);var f=new Zr;f.bounds=new Xe(.5,0,.5,1),f.layers.enable(2);var m=new Qr([d,f]);function g(){return null!==n&&!0===n.isPresenting}m.layers.enable(1),m.layers.enable(2);var v,y=new Ee;function x(){if(g()){var i=n.getEyeParameters("left"),r=i.renderWidth*c,a=i.renderHeight*c;v=t.getPixelRatio(),t.getSize(y),t.setDrawingBufferSize(2*r,a,1),_.start()}else e.enabled&&t.setDrawingBufferSize(y.width,y.height,v),_.stop()}var b=[];function w(t){for(var e=navigator.getGamepads&&navigator.getGamepads(),n=0,i=0,r=e.length;n=0){var c=i[o];if(void 0!==c){var h=c.normalized,l=c.itemSize,u=w.get(c);if(void 0===u)continue;var p=u.buffer,f=u.type,y=u.bytesPerElement;if(c.isInterleavedBufferAttribute){var x=c.data,b=x.stride,_=c.offset;x&&x.isInstancedInterleavedBuffer?(v.enableAttributeAndDivisor(s,x.meshPerAttribute),void 0===n.maxInstancedCount&&(n.maxInstancedCount=x.meshPerAttribute*x.count)):v.enableAttribute(s),d.bindBuffer(34962,p),d.vertexAttribPointer(s,l,f,h,b*y,_*y)}else c.isInstancedBufferAttribute?(v.enableAttributeAndDivisor(s,c.meshPerAttribute),void 0===n.maxInstancedCount&&(n.maxInstancedCount=c.meshPerAttribute*c.count)):v.enableAttribute(s),d.bindBuffer(34962,p),d.vertexAttribPointer(s,l,f,h,0,0)}else if(void 0!==a){var M=a[o];if(void 0!==M)switch(M.length){case 2:d.vertexAttrib2fv(s,M);break;case 3:d.vertexAttrib3fv(s,M);break;case 4:d.vertexAttrib4fv(s,M);break;default:d.vertexAttrib1fv(s,M)}}}}v.disableUnusedAttributes()}(i,s,n),null!==l&&d.bindBuffer(34963,h.buffer));var y=1/0;null!==l?y=l.count:void 0!==u&&(y=u.count);var x=n.drawRange.start*p,b=n.drawRange.count*p,M=null!==a?a.start*p:0,S=null!==a?a.count*p:1/0,T=Math.max(x,M),E=Math.min(y,x+b,M+S)-1,A=Math.max(0,E-T+1);if(0!==A){if(r.isMesh)if(!0===i.wireframe)v.setLineWidth(i.wireframeLinewidth*it()),f.setMode(1);else switch(r.drawMode){case ue:f.setMode(4);break;case pe:f.setMode(5);break;case de:f.setMode(6)}else if(r.isLine){var C=i.linewidth;void 0===C&&(C=1),v.setLineWidth(C*it()),r.isLineSegments?f.setMode(1):r.isLineLoop?f.setMode(2):f.setMode(3)}else r.isPoints?f.setMode(0):r.isSprite&&f.setMode(4);n&&n.isInstancedBufferGeometry?n.maxInstancedCount>0&&f.renderInstances(n,T,A):f.render(T,A)}},this.compile=function(t,e){(p=E.get(t,e)).init(),t.traverse(function(t){t.isLight&&(p.pushLight(t),t.castShadow&&p.pushShadow(t))}),p.setupLights(e),t.traverse(function(e){if(e.material)if(Array.isArray(e.material))for(var n=0;n=0&&t.numSupportedMorphTargets++}if(t.morphNormals){t.numSupportedMorphNormals=0;for(m=0;m=0&&t.numSupportedMorphNormals++}var g=i.shader.uniforms;(t.isShaderMaterial||t.isRawShaderMaterial)&&!0!==t.clipping||(i.numClippingPlanes=Q.numPlanes,i.numIntersection=Q.numIntersection,g.clippingPlanes=Q.uniform),i.fog=e,void 0===o&&(i.lightsHash=o={}),o.stateID=s.stateID,o.directionalLength=s.directionalLength,o.pointLength=s.pointLength,o.spotLength=s.spotLength,o.rectAreaLength=s.rectAreaLength,o.hemiLength=s.hemiLength,o.shadowsLength=s.shadowsLength,t.lights&&(g.ambientLightColor.value=r.state.ambient,g.lightProbe.value=r.state.probe,g.directionalLights.value=r.state.directional,g.spotLights.value=r.state.spot,g.rectAreaLights.value=r.state.rectArea,g.pointLights.value=r.state.point,g.hemisphereLights.value=r.state.hemi,g.directionalShadowMap.value=r.state.directionalShadowMap,g.directionalShadowMatrix.value=r.state.directionalShadowMatrix,g.spotShadowMap.value=r.state.spotShadowMap,g.spotShadowMatrix.value=r.state.spotShadowMatrix,g.pointShadowMap.value=r.state.pointShadowMap,g.pointShadowMatrix.value=r.state.pointShadowMatrix);var v=i.program.getUniforms(),y=xr.seqWithValue(v.seq,g);i.uniformsList=y}function vt(t,e,n,i){b.resetTextureUnits();var r=x.get(n),a=p.state.lights,o=r.lightsHash,s=a.state.hash;if(K&&(tt||t!==G)){var c=t===G&&n.id===B;Q.setState(n.clippingPlanes,n.clipIntersection,n.clipShadows,t,r,c)}!1===n.needsUpdate&&(void 0===r.program?n.needsUpdate=!0:n.fog&&r.fog!==e?n.needsUpdate=!0:(!n.lights||o.stateID===s.stateID&&o.directionalLength===s.directionalLength&&o.pointLength===s.pointLength&&o.spotLength===s.spotLength&&o.rectAreaLength===s.rectAreaLength&&o.hemiLength===s.hemiLength&&o.shadowsLength===s.shadowsLength)&&(void 0===r.numClippingPlanes||r.numClippingPlanes===Q.numPlanes&&r.numIntersection===Q.numIntersection)||(n.needsUpdate=!0)),n.needsUpdate&&(gt(n,e,i),n.needsUpdate=!1);var h,l,u=!1,m=!1,y=!1,w=r.program,_=w.getUniforms(),M=r.shader.uniforms;if(v.useProgram(w.program)&&(u=!0,m=!0,y=!0),n.id!==B&&(B=n.id,m=!0),u||G!==t){if(_.setValue(d,"projectionMatrix",t.projectionMatrix),g.logarithmicDepthBuffer&&_.setValue(d,"logDepthBufFC",2/(Math.log(t.far+1)/Math.LN2)),G!==t&&(G=t,m=!0,y=!0),n.isShaderMaterial||n.isMeshPhongMaterial||n.isMeshStandardMaterial||n.envMap){var S=_.map.cameraPosition;void 0!==S&&S.setValue(d,nt.setFromMatrixPosition(t.matrixWorld))}(n.isMeshPhongMaterial||n.isMeshLambertMaterial||n.isMeshBasicMaterial||n.isMeshStandardMaterial||n.isShaderMaterial||n.skinning)&&_.setValue(d,"viewMatrix",t.matrixWorldInverse)}if(n.skinning){_.setOptional(d,i,"bindMatrix"),_.setOptional(d,i,"bindMatrixInverse");var T=i.skeleton;if(T){var E=T.bones;if(g.floatVertexTextures){if(void 0===T.boneTexture){var A=Math.sqrt(4*E.length);A=Te.ceilPowerOfTwo(A),A=Math.max(A,4);var L=new Float32Array(A*A*4);L.set(T.boneMatrices);var P=new Qe(L,A,A,Dt,Et);P.needsUpdate=!0,T.boneMatrices=L,T.boneTexture=P,T.boneTextureSize=A}_.setValue(d,"boneTexture",T.boneTexture,b),_.setValue(d,"boneTextureSize",T.boneTextureSize)}else _.setOptional(d,T,"boneMatrices")}}return m&&(_.setValue(d,"toneMappingExposure",O.toneMappingExposure),_.setValue(d,"toneMappingWhitePoint",O.toneMappingWhitePoint),n.lights&&(l=y,(h=M).ambientLightColor.needsUpdate=l,h.lightProbe.needsUpdate=l,h.directionalLights.needsUpdate=l,h.pointLights.needsUpdate=l,h.spotLights.needsUpdate=l,h.rectAreaLights.needsUpdate=l,h.hemisphereLights.needsUpdate=l),e&&n.fog&&function(t,e){t.fogColor.value.copy(e.color),e.isFog?(t.fogNear.value=e.near,t.fogFar.value=e.far):e.isFogExp2&&(t.fogDensity.value=e.density)}(M,e),n.isMeshBasicMaterial?yt(M,n):n.isMeshLambertMaterial?(yt(M,n),function(t,e){e.emissiveMap&&(t.emissiveMap.value=e.emissiveMap)}(M,n)):n.isMeshPhongMaterial?(yt(M,n),n.isMeshToonMaterial?function(t,e){xt(t,e),e.gradientMap&&(t.gradientMap.value=e.gradientMap)}(M,n):xt(M,n)):n.isMeshStandardMaterial?(yt(M,n),n.isMeshPhysicalMaterial?function(t,e){wt(t,e),t.reflectivity.value=e.reflectivity,t.clearCoat.value=e.clearCoat,t.clearCoatRoughness.value=e.clearCoatRoughness}(M,n):wt(M,n)):n.isMeshMatcapMaterial?(yt(M,n),function(t,e){e.matcap&&(t.matcap.value=e.matcap);e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,e.side===f&&(t.bumpScale.value*=-1));e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),e.side===f&&t.normalScale.value.negate());e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(M,n)):n.isMeshDepthMaterial?(yt(M,n),function(t,e){e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(M,n)):n.isMeshDistanceMaterial?(yt(M,n),function(t,e){e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias);t.referencePosition.value.copy(e.referencePosition),t.nearDistance.value=e.nearDistance,t.farDistance.value=e.farDistance}(M,n)):n.isMeshNormalMaterial?(yt(M,n),function(t,e){e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,e.side===f&&(t.bumpScale.value*=-1));e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),e.side===f&&t.normalScale.value.negate());e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}(M,n)):n.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity}(M,n),n.isLineDashedMaterial&&function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(M,n)):n.isPointsMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*q,t.scale.value=.5*W,t.map.value=e.map,null!==e.map&&(!0===e.map.matrixAutoUpdate&&e.map.updateMatrix(),t.uvTransform.value.copy(e.map.matrix))}(M,n):n.isSpriteMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.rotation.value=e.rotation,t.map.value=e.map,null!==e.map&&(!0===e.map.matrixAutoUpdate&&e.map.updateMatrix(),t.uvTransform.value.copy(e.map.matrix))}(M,n):n.isShadowMaterial&&(M.color.value.copy(n.color),M.opacity.value=n.opacity),void 0!==M.ltc_1&&(M.ltc_1.value=dn.LTC_1),void 0!==M.ltc_2&&(M.ltc_2.value=dn.LTC_2),xr.upload(d,r.uniformsList,M,b)),n.isShaderMaterial&&!0===n.uniformsNeedUpdate&&(xr.upload(d,r.uniformsList,M,b),n.uniformsNeedUpdate=!1),n.isSpriteMaterial&&_.setValue(d,"center",i.center),_.setValue(d,"modelViewMatrix",i.modelViewMatrix),_.setValue(d,"normalMatrix",i.normalMatrix),_.setValue(d,"modelMatrix",i.matrixWorld),w}function yt(t,e){var n;t.opacity.value=e.opacity,e.color&&t.diffuse.value.copy(e.color),e.emissive&&t.emissive.value.copy(e.emissive).multiplyScalar(e.emissiveIntensity),e.map&&(t.map.value=e.map),e.alphaMap&&(t.alphaMap.value=e.alphaMap),e.specularMap&&(t.specularMap.value=e.specularMap),e.envMap&&(t.envMap.value=e.envMap,t.flipEnvMap.value=e.envMap.isCubeTexture?-1:1,t.reflectivity.value=e.reflectivity,t.refractionRatio.value=e.refractionRatio,t.maxMipLevel.value=x.get(e.envMap).__maxMipLevel),e.lightMap&&(t.lightMap.value=e.lightMap,t.lightMapIntensity.value=e.lightMapIntensity),e.aoMap&&(t.aoMap.value=e.aoMap,t.aoMapIntensity.value=e.aoMapIntensity),e.map?n=e.map:e.specularMap?n=e.specularMap:e.displacementMap?n=e.displacementMap:e.normalMap?n=e.normalMap:e.bumpMap?n=e.bumpMap:e.roughnessMap?n=e.roughnessMap:e.metalnessMap?n=e.metalnessMap:e.alphaMap?n=e.alphaMap:e.emissiveMap&&(n=e.emissiveMap),void 0!==n&&(n.isWebGLRenderTarget&&(n=n.texture),!0===n.matrixAutoUpdate&&n.updateMatrix(),t.uvTransform.value.copy(n.matrix))}function xt(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4),e.emissiveMap&&(t.emissiveMap.value=e.emissiveMap),e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,e.side===f&&(t.bumpScale.value*=-1)),e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),e.side===f&&t.normalScale.value.negate()),e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias)}function wt(t,e){t.roughness.value=e.roughness,t.metalness.value=e.metalness,e.roughnessMap&&(t.roughnessMap.value=e.roughnessMap),e.metalnessMap&&(t.metalnessMap.value=e.metalnessMap),e.emissiveMap&&(t.emissiveMap.value=e.emissiveMap),e.bumpMap&&(t.bumpMap.value=e.bumpMap,t.bumpScale.value=e.bumpScale,e.side===f&&(t.bumpScale.value*=-1)),e.normalMap&&(t.normalMap.value=e.normalMap,t.normalScale.value.copy(e.normalScale),e.side===f&&t.normalScale.value.negate()),e.displacementMap&&(t.displacementMap.value=e.displacementMap,t.displacementScale.value=e.displacementScale,t.displacementBias.value=e.displacementBias),e.envMap&&(t.envMapIntensity.value=e.envMapIntensity)}dt.setAnimationLoop(function(t){ot.isPresenting()||pt&&pt(t)}),"undefined"!=typeof window&&dt.setContext(window),this.setAnimationLoop=function(t){pt=t,ot.setAnimationLoop(t),dt.start()},this.render=function(t,e){var n,i;if(void 0!==arguments[2]&&(console.warn("THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead."),n=arguments[2]),void 0!==arguments[3]&&(console.warn("THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead."),i=arguments[3]),e&&e.isCamera){if(!I){U.geometry=null,U.program=null,U.wireframe=!1,B=-1,G=null,!0===t.autoUpdate&&t.updateMatrixWorld(),null===e.parent&&e.updateMatrixWorld(),ot.enabled&&(e=ot.getCamera(e)),(p=E.get(t,e)).init(),t.onBeforeRender(O,t,e,n||N),et.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),Z.setFromMatrix(et),tt=this.localClippingEnabled,K=Q.init(this.clippingPlanes,tt,e),(u=T.get(t,e)).init(),function t(e,n,i,r){if(!1===e.visible)return;var a=e.layers.test(n.layers);if(a)if(e.isGroup)i=e.renderOrder;else if(e.isLight)p.pushLight(e),e.castShadow&&p.pushShadow(e);else if(e.isSprite){if(!e.frustumCulled||Z.intersectsSprite(e)){r&&nt.setFromMatrixPosition(e.matrixWorld).applyMatrix4(et);var o=M.update(e),s=e.material;s.visible&&u.push(e,o,s,i,nt.z,null)}}else if(e.isImmediateRenderObject)r&&nt.setFromMatrixPosition(e.matrixWorld).applyMatrix4(et),u.push(e,null,e.material,i,nt.z,null);else if((e.isMesh||e.isLine||e.isPoints)&&(e.isSkinnedMesh&&e.skeleton.update(),!e.frustumCulled||Z.intersectsObject(e))){r&&nt.setFromMatrixPosition(e.matrixWorld).applyMatrix4(et);var o=M.update(e),s=e.material;if(Array.isArray(s))for(var c=o.groups,h=0,l=c.length;h=0&&e<=t.width-i&&n>=0&&n<=t.height-r&&d.readPixels(e,n,i,r,C.convert(h),C.convert(l),a):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{s&&d.bindFramebuffer(36160,z)}}}else console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.")},this.copyFramebufferToTexture=function(t,e,n){var i=e.image.width,r=e.image.height,a=C.convert(e.format);b.setTexture2D(e,0),d.copyTexImage2D(3553,n||0,a,t.x,t.y,i,r,0)},this.copyTextureToTexture=function(t,e,n,i){var r=e.image.width,a=e.image.height,o=C.convert(n.format),s=C.convert(n.type);b.setTexture2D(n,0),e.isDataTexture?d.texSubImage2D(3553,i||0,t.x,t.y,r,a,o,s,e.image.data):d.texSubImage2D(3553,i||0,t.x,t.y,o,s,e.image)}}function la(t,e){this.name="",this.color=new un(t),this.density=void 0!==e?e:25e-5}function ua(t,e,n){this.name="",this.color=new un(t),this.near=void 0!==e?e:1,this.far=void 0!==n?n:1e3}function pa(){Tn.call(this),this.type="Scene",this.background=null,this.fog=null,this.overrideMaterial=null,this.autoUpdate=!0}function da(t,e){this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.dynamic=!1,this.updateRange={offset:0,count:-1},this.version=0}function fa(t,e,n,i){this.data=t,this.itemSize=e,this.offset=n,this.normalized=!0===i}function ma(t){Jn.call(this),this.type="SpriteMaterial",this.color=new un(16777215),this.map=null,this.rotation=0,this.sizeAttenuation=!0,this.lights=!1,this.transparent=!0,this.setValues(t)}function ga(t){if(Tn.call(this),this.type="Sprite",void 0===Kr){Kr=new Vn;var e=new da(new Float32Array([-.5,-.5,0,0,0,.5,-.5,0,1,0,.5,.5,0,1,1,-.5,.5,0,0,1]),5);Kr.setIndex([0,1,2,0,2,3]),Kr.addAttribute("position",new fa(e,3,0,!1)),Kr.addAttribute("uv",new fa(e,2,3,!1))}this.geometry=Kr,this.material=void 0!==t?t:new ma,this.center=new Ee(.5,.5)}function va(){Tn.call(this),this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]}})}function ya(t,e){t&&t.isGeometry&&console.error("THREE.SkinnedMesh no longer supports THREE.Geometry. Use THREE.BufferGeometry instead."),fi.call(this,t,e),this.type="SkinnedMesh",this.bindMode="attached",this.bindMatrix=new nn,this.bindMatrixInverse=new nn}function xa(t,e){if(t=t||[],this.bones=t.slice(0),this.boneMatrices=new Float32Array(16*this.bones.length),void 0===e)this.calculateInverses();else if(this.bones.length===e.length)this.boneInverses=e.slice(0);else{console.warn("THREE.Skeleton boneInverses is the wrong length."),this.boneInverses=[];for(var n=0,i=this.bones.length;n=0?(t(g-1e-5,m,u),p.subVectors(l,u)):(t(g+1e-5,m,u),p.subVectors(u,l)),m-1e-5>=0?(t(g,m-1e-5,u),d.subVectors(l,u)):(t(g,m+1e-5,u),d.subVectors(u,l)),h.crossVectors(p,d).normalize(),s.push(h.x,h.y,h.z),c.push(g,m)}}for(i=0;i.9&&o<.1&&(e<.2&&(a[t+0]+=1),n<.2&&(a[t+2]+=1),i<.2&&(a[t+4]+=1))}}()}(),this.addAttribute("position",new Un(r,3)),this.addAttribute("normal",new Un(r.slice(),3)),this.addAttribute("uv",new Un(a,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}function za(t,e){Pn.call(this),this.type="TetrahedronGeometry",this.parameters={radius:t,detail:e},this.fromBufferGeometry(new Ba(t,e)),this.mergeVertices()}function Ba(t,e){Na.call(this,[1,1,1,-1,-1,1,-1,1,-1,1,-1,-1],[2,1,0,0,3,2,1,3,0,2,3,1],t,e),this.type="TetrahedronBufferGeometry",this.parameters={radius:t,detail:e}}function Ua(t,e){Pn.call(this),this.type="OctahedronGeometry",this.parameters={radius:t,detail:e},this.fromBufferGeometry(new Ga(t,e)),this.mergeVertices()}function Ga(t,e){Na.call(this,[1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1],[0,2,4,0,4,3,0,3,5,0,5,2,1,2,5,1,5,3,1,3,4,1,4,2],t,e),this.type="OctahedronBufferGeometry",this.parameters={radius:t,detail:e}}function Fa(t,e){Pn.call(this),this.type="IcosahedronGeometry",this.parameters={radius:t,detail:e},this.fromBufferGeometry(new Ha(t,e)),this.mergeVertices()}function Ha(t,e){var n=(1+Math.sqrt(5))/2,i=[-1,n,0,1,n,0,-1,-n,0,1,-n,0,0,-1,n,0,1,n,0,-1,-n,0,1,-n,n,0,-1,n,0,1,-n,0,-1,-n,0,1];Na.call(this,i,[0,11,5,0,5,1,0,1,7,0,7,10,0,10,11,1,5,9,5,11,4,11,10,2,10,7,6,7,1,8,3,9,4,3,4,2,3,2,6,3,6,8,3,8,9,4,9,5,2,4,11,6,2,10,8,6,7,9,8,1],t,e),this.type="IcosahedronBufferGeometry",this.parameters={radius:t,detail:e}}function ka(t,e){Pn.call(this),this.type="DodecahedronGeometry",this.parameters={radius:t,detail:e},this.fromBufferGeometry(new Va(t,e)),this.mergeVertices()}function Va(t,e){var n=(1+Math.sqrt(5))/2,i=1/n,r=[-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-i,-n,0,-i,n,0,i,-n,0,i,n,-i,-n,0,-i,n,0,i,-n,0,i,n,0,-n,0,-i,n,0,-i,-n,0,i,n,0,i];Na.call(this,r,[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type="DodecahedronBufferGeometry",this.parameters={radius:t,detail:e}}function ja(t,e,n,i,r,a){Pn.call(this),this.type="TubeGeometry",this.parameters={path:t,tubularSegments:e,radius:n,radialSegments:i,closed:r},void 0!==a&&console.warn("THREE.TubeGeometry: taper has been removed.");var o=new Wa(t,e,n,i,r);this.tangents=o.tangents,this.normals=o.normals,this.binormals=o.binormals,this.fromBufferGeometry(o),this.mergeVertices()}function Wa(t,e,n,i,r){Vn.call(this),this.type="TubeBufferGeometry",this.parameters={path:t,tubularSegments:e,radius:n,radialSegments:i,closed:r},e=e||64,n=n||1,i=i||8,r=r||!1;var a=t.computeFrenetFrames(e,r);this.tangents=a.tangents,this.normals=a.normals,this.binormals=a.binormals;var o,s,c=new Le,h=new Le,l=new Ee,u=new Le,p=[],d=[],f=[],m=[];function g(r){u=t.getPointAt(r/e,u);var o=a.normals[r],l=a.binormals[r];for(s=0;s<=i;s++){var f=s/i*Math.PI*2,m=Math.sin(f),g=-Math.cos(f);h.x=g*o.x+m*l.x,h.y=g*o.y+m*l.y,h.z=g*o.z+m*l.z,h.normalize(),d.push(h.x,h.y,h.z),c.x=u.x+n*h.x,c.y=u.y+n*h.y,c.z=u.z+n*h.z,p.push(c.x,c.y,c.z)}}!function(){for(o=0;oi.far||r.push({distance:y,point:t.clone(),uv:pi.getUV(t,o,s,c,h,l,u,new Ee),face:null,object:this})}}}(),clone:function(){return new this.constructor(this.material).copy(this)},copy:function(t){return Tn.prototype.copy.call(this,t),void 0!==t.center&&this.center.copy(t.center),this}}),va.prototype=Object.assign(Object.create(Tn.prototype),{constructor:va,isLOD:!0,copy:function(t){Tn.prototype.copy.call(this,t,!1);for(var e=t.levels,n=0,i=e.length;n1){t.setFromMatrixPosition(n.matrixWorld),e.setFromMatrixPosition(this.matrixWorld);var r=t.distanceTo(e);i[0].object.visible=!0;for(var a=1,o=i.length;a=i[a].distance;a++)i[a-1].object.visible=!1,i[a].object.visible=!0;for(;ah))d.applyMatrix4(this.matrixWorld),(S=i.ray.origin.distanceTo(d))i.far||r.push({distance:S,point:p.clone().applyMatrix4(this.matrixWorld),index:y,face:null,faceIndex:null,object:this})}else for(y=0,x=g.length/3-1;yh))d.applyMatrix4(this.matrixWorld),(S=i.ray.origin.distanceTo(d))i.far||r.push({distance:S,point:p.clone().applyMatrix4(this.matrixWorld),index:y,face:null,faceIndex:null,object:this})}}else if(o.isGeometry){var _=o.vertices,M=_.length;for(y=0;yh))d.applyMatrix4(this.matrixWorld),(S=i.ray.origin.distanceTo(d))i.far||r.push({distance:S,point:p.clone().applyMatrix4(this.matrixWorld),index:y,face:null,faceIndex:null,object:this})}}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),Ma.prototype=Object.assign(Object.create(_a.prototype),{constructor:Ma,isLineSegments:!0,computeLineDistances:function(){var t=new Le,e=new Le;return function(){var n=this.geometry;if(n.isBufferGeometry)if(null===n.index){for(var i=n.attributes.position,r=[],a=0,o=i.count;ai.far)return;r.push({distance:c,distanceToRay:Math.sqrt(o),point:p.clone(),index:n,face:null,object:a})}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),Aa.prototype=Object.assign(Object.create(qe.prototype),{constructor:Aa,isVideoTexture:!0,update:function(){var t=this.image;t.readyState>=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}),La.prototype=Object.create(qe.prototype),La.prototype.constructor=La,La.prototype.isCompressedTexture=!0,Pa.prototype=Object.create(qe.prototype),Pa.prototype.constructor=Pa,Pa.prototype.isCanvasTexture=!0,Ra.prototype=Object.create(qe.prototype),Ra.prototype.constructor=Ra,Ra.prototype.isDepthTexture=!0,Ca.prototype=Object.create(Vn.prototype),Ca.prototype.constructor=Ca,Oa.prototype=Object.create(Pn.prototype),Oa.prototype.constructor=Oa,Ia.prototype=Object.create(Vn.prototype),Ia.prototype.constructor=Ia,Da.prototype=Object.create(Pn.prototype),Da.prototype.constructor=Da,Na.prototype=Object.create(Vn.prototype),Na.prototype.constructor=Na,za.prototype=Object.create(Pn.prototype),za.prototype.constructor=za,Ba.prototype=Object.create(Na.prototype),Ba.prototype.constructor=Ba,Ua.prototype=Object.create(Pn.prototype),Ua.prototype.constructor=Ua,Ga.prototype=Object.create(Na.prototype),Ga.prototype.constructor=Ga,Fa.prototype=Object.create(Pn.prototype),Fa.prototype.constructor=Fa,Ha.prototype=Object.create(Na.prototype),Ha.prototype.constructor=Ha,ka.prototype=Object.create(Pn.prototype),ka.prototype.constructor=ka,Va.prototype=Object.create(Na.prototype),Va.prototype.constructor=Va,ja.prototype=Object.create(Pn.prototype),ja.prototype.constructor=ja,Wa.prototype=Object.create(Vn.prototype),Wa.prototype.constructor=Wa,Wa.prototype.toJSON=function(){var t=Vn.prototype.toJSON.call(this);return t.path=this.parameters.path.toJSON(),t},qa.prototype=Object.create(Pn.prototype),qa.prototype.constructor=qa,Xa.prototype=Object.create(Vn.prototype),Xa.prototype.constructor=Xa,Ya.prototype=Object.create(Pn.prototype),Ya.prototype.constructor=Ya,Ja.prototype=Object.create(Vn.prototype),Ja.prototype.constructor=Ja;var Za=function(t,e,n){n=n||2;var i,r,a,o,s,c,h,l=e&&e.length,u=l?e[0]*n:t.length,p=Qa(t,0,u,n,!0),d=[];if(!p)return d;if(l&&(p=function(t,e,n,i){var r,a,o,s,c,h=[];for(r=0,a=e.length;r80*n){i=a=t[0],r=o=t[1];for(var f=n;fa&&(a=s),c>o&&(o=c);h=0!==(h=Math.max(a-i,o-r))?1/h:0}return $a(p,d,n,i,r,h),d};function Qa(t,e,n,i,r){var a,o;if(r===function(t,e,n,i){for(var r=0,a=e,o=n-i;a0)for(a=e;a=e;a-=i)o=go(a,t[a],t[a+1],o);return o&&uo(o,o.next)&&(vo(o),o=o.next),o}function Ka(t,e){if(!t)return t;e||(e=t);var n,i=t;do{if(n=!1,i.steiner||!uo(i,i.next)&&0!==lo(i.prev,i,i.next))i=i.next;else{if(vo(i),(i=e=i.prev)===i.next)break;n=!0}}while(n||i!==e);return e}function $a(t,e,n,i,r,a,o){if(t){!o&&a&&function(t,e,n,i){var r=t;do{null===r.z&&(r.z=oo(r.x,r.y,e,n,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){var e,n,i,r,a,o,s,c,h=1;do{for(n=t,t=null,a=null,o=0;n;){for(o++,i=n,s=0,e=0;e0||c>0&&i;)0!==s&&(0===c||!i||n.z<=i.z)?(r=n,n=n.nextZ,s--):(r=i,i=i.nextZ,c--),a?a.nextZ=r:t=r,r.prevZ=a,a=r;n=i}a.nextZ=null,h*=2}while(o>1)}(r)}(t,i,r,a);for(var s,c,h=t;t.prev!==t.next;)if(s=t.prev,c=t.next,a?eo(t,i,r,a):to(t))e.push(s.i/n),e.push(t.i/n),e.push(c.i/n),vo(t),t=c.next,h=c.next;else if((t=c)===h){o?1===o?$a(t=no(t,e,n),e,n,i,r,a,2):2===o&&io(t,e,n,i,r,a):$a(Ka(t),e,n,i,r,a,1);break}}}function to(t){var e=t.prev,n=t,i=t.next;if(lo(e,n,i)>=0)return!1;for(var r=t.next.next;r!==t.prev;){if(co(e.x,e.y,n.x,n.y,i.x,i.y,r.x,r.y)&&lo(r.prev,r,r.next)>=0)return!1;r=r.next}return!0}function eo(t,e,n,i){var r=t.prev,a=t,o=t.next;if(lo(r,a,o)>=0)return!1;for(var s=r.xa.x?r.x>o.x?r.x:o.x:a.x>o.x?a.x:o.x,l=r.y>a.y?r.y>o.y?r.y:o.y:a.y>o.y?a.y:o.y,u=oo(s,c,e,n,i),p=oo(h,l,e,n,i),d=t.nextZ;d&&d.z<=p;){if(d!==t.prev&&d!==t.next&&co(r.x,r.y,a.x,a.y,o.x,o.y,d.x,d.y)&&lo(d.prev,d,d.next)>=0)return!1;d=d.nextZ}for(d=t.prevZ;d&&d.z>=u;){if(d!==t.prev&&d!==t.next&&co(r.x,r.y,a.x,a.y,o.x,o.y,d.x,d.y)&&lo(d.prev,d,d.next)>=0)return!1;d=d.prevZ}return!0}function no(t,e,n){var i=t;do{var r=i.prev,a=i.next.next;!uo(r,a)&&po(r,i,i.next,a)&&fo(r,a)&&fo(a,r)&&(e.push(r.i/n),e.push(i.i/n),e.push(a.i/n),vo(i),vo(i.next),i=t=a),i=i.next}while(i!==t);return i}function io(t,e,n,i,r,a){var o=t;do{for(var s=o.next.next;s!==o.prev;){if(o.i!==s.i&&ho(o,s)){var c=mo(o,s);return o=Ka(o,o.next),c=Ka(c,c.next),$a(o,e,n,i,r,a),void $a(c,e,n,i,r,a)}s=s.next}o=o.next}while(o!==t)}function ro(t,e){return t.x-e.x}function ao(t,e){if(e=function(t,e){var n,i=e,r=t.x,a=t.y,o=-1/0;do{if(a<=i.y&&a>=i.next.y&&i.next.y!==i.y){var s=i.x+(a-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(s<=r&&s>o){if(o=s,s===r){if(a===i.y)return i;if(a===i.next.y)return i.next}n=i.x=i.x&&i.x>=l&&r!==i.x&&co(an.x)&&fo(i,t)&&(n=i,p=c),i=i.next;return n}(t,e)){var n=mo(e,t);Ka(n,n.next)}}function oo(t,e,n,i,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-n)*r)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-i)*r)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function so(t){var e=t,n=t;do{e.x=0&&(t-o)*(i-s)-(n-o)*(e-s)>=0&&(n-o)*(a-s)-(r-o)*(i-s)>=0}function ho(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){var n=t;do{if(n.i!==t.i&&n.next.i!==t.i&&n.i!==e.i&&n.next.i!==e.i&&po(n,n.next,t,e))return!0;n=n.next}while(n!==t);return!1}(t,e)&&fo(t,e)&&fo(e,t)&&function(t,e){var n=t,i=!1,r=(t.x+e.x)/2,a=(t.y+e.y)/2;do{n.y>a!=n.next.y>a&&n.next.y!==n.y&&r<(n.next.x-n.x)*(a-n.y)/(n.next.y-n.y)+n.x&&(i=!i),n=n.next}while(n!==t);return i}(t,e)}function lo(t,e,n){return(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y)}function uo(t,e){return t.x===e.x&&t.y===e.y}function po(t,e,n,i){return!!(uo(t,e)&&uo(n,i)||uo(t,i)&&uo(n,e))||lo(t,e,n)>0!=lo(t,e,i)>0&&lo(n,i,t)>0!=lo(n,i,e)>0}function fo(t,e){return lo(t.prev,t,t.next)<0?lo(t,e,t.next)>=0&&lo(t,t.prev,e)>=0:lo(t,e,t.prev)<0||lo(t,t.next,e)<0}function mo(t,e){var n=new yo(t.i,t.x,t.y),i=new yo(e.i,e.x,e.y),r=t.next,a=e.prev;return t.next=e,e.prev=t,n.next=r,r.prev=n,i.next=n,n.prev=i,a.next=i,i.prev=a,i}function go(t,e,n,i){var r=new yo(t,e,n);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function vo(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function yo(t,e,n){this.i=t,this.x=e,this.y=n,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}var xo={area:function(t){for(var e=t.length,n=0,i=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function wo(t,e){for(var n=0;nNumber.EPSILON){var p=Math.sqrt(l),d=Math.sqrt(c*c+h*h),f=e.x-s/p,m=e.y+o/p,g=((n.x-h/d-f)*h-(n.y+c/d-m)*c)/(o*h-s*c),v=(i=f+o*g-t.x)*i+(r=m+s*g-t.y)*r;if(v<=2)return new Ee(i,r);a=Math.sqrt(v/2)}else{var y=!1;o>Number.EPSILON?c>Number.EPSILON&&(y=!0):o<-Number.EPSILON?c<-Number.EPSILON&&(y=!0):Math.sign(s)===Math.sign(h)&&(y=!0),y?(i=-s,r=o,a=Math.sqrt(l)):(i=o,r=s,a=Math.sqrt(l/2))}return new Ee(i/a,r/a)}for(var F=[],H=0,k=P.length,V=k-1,j=H+1;H=0;C--){for(I=C/d,D=l*Math.cos(I*Math.PI/2),O=u*Math.sin(I*Math.PI/2)+p,H=0,k=P.length;H=0;){n=H,(i=H-1)<0&&(i=t.length-1);var r=0,a=s+2*d;for(r=0;r0)&&f.push(_,M,T),(c!==n-1||h0&&v(!0),e>0&&v(!1)),this.setIndex(h),this.addAttribute("position",new Un(l,3)),this.addAttribute("normal",new Un(u,3)),this.addAttribute("uv",new Un(p,2))}function Fo(t,e,n,i,r,a,o){Uo.call(this,0,t,e,n,i,r,a,o),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:n,heightSegments:i,openEnded:r,thetaStart:a,thetaLength:o}}function Ho(t,e,n,i,r,a,o){Go.call(this,0,t,e,n,i,r,a,o),this.type="ConeBufferGeometry",this.parameters={radius:t,height:e,radialSegments:n,heightSegments:i,openEnded:r,thetaStart:a,thetaLength:o}}function ko(t,e,n,i){Pn.call(this),this.type="CircleGeometry",this.parameters={radius:t,segments:e,thetaStart:n,thetaLength:i},this.fromBufferGeometry(new Vo(t,e,n,i)),this.mergeVertices()}function Vo(t,e,n,i){Vn.call(this),this.type="CircleBufferGeometry",this.parameters={radius:t,segments:e,thetaStart:n,thetaLength:i},t=t||1,e=void 0!==e?Math.max(3,e):8,n=void 0!==n?n:0,i=void 0!==i?i:2*Math.PI;var r,a,o=[],s=[],c=[],h=[],l=new Le,u=new Ee;for(s.push(0,0,0),c.push(0,0,1),h.push(.5,.5),a=0,r=3;a<=e;a++,r+=3){var p=n+a/e*i;l.x=t*Math.cos(p),l.y=t*Math.sin(p),s.push(l.x,l.y,l.z),c.push(0,0,1),u.x=(s[r]/t+1)/2,u.y=(s[r+1]/t+1)/2,h.push(u.x,u.y)}for(r=1;r<=e;r++)o.push(r,r+1,0);this.setIndex(o),this.addAttribute("position",new Un(s,3)),this.addAttribute("normal",new Un(c,3)),this.addAttribute("uv",new Un(h,2))}Eo.prototype=Object.create(Pn.prototype),Eo.prototype.constructor=Eo,Ao.prototype=Object.create(Mo.prototype),Ao.prototype.constructor=Ao,Lo.prototype=Object.create(Pn.prototype),Lo.prototype.constructor=Lo,Po.prototype=Object.create(Vn.prototype),Po.prototype.constructor=Po,Ro.prototype=Object.create(Pn.prototype),Ro.prototype.constructor=Ro,Co.prototype=Object.create(Vn.prototype),Co.prototype.constructor=Co,Oo.prototype=Object.create(Pn.prototype),Oo.prototype.constructor=Oo,Io.prototype=Object.create(Vn.prototype),Io.prototype.constructor=Io,Do.prototype=Object.create(Pn.prototype),Do.prototype.constructor=Do,Do.prototype.toJSON=function(){var t=Pn.prototype.toJSON.call(this);return zo(this.parameters.shapes,t)},No.prototype=Object.create(Vn.prototype),No.prototype.constructor=No,No.prototype.toJSON=function(){var t=Vn.prototype.toJSON.call(this);return zo(this.parameters.shapes,t)},Bo.prototype=Object.create(Vn.prototype),Bo.prototype.constructor=Bo,Uo.prototype=Object.create(Pn.prototype),Uo.prototype.constructor=Uo,Go.prototype=Object.create(Vn.prototype),Go.prototype.constructor=Go,Fo.prototype=Object.create(Uo.prototype),Fo.prototype.constructor=Fo,Ho.prototype=Object.create(Go.prototype),Ho.prototype.constructor=Ho,ko.prototype=Object.create(Pn.prototype),ko.prototype.constructor=ko,Vo.prototype=Object.create(Vn.prototype),Vo.prototype.constructor=Vo;var jo=Object.freeze({WireframeGeometry:Ca,ParametricGeometry:Oa,ParametricBufferGeometry:Ia,TetrahedronGeometry:za,TetrahedronBufferGeometry:Ba,OctahedronGeometry:Ua,OctahedronBufferGeometry:Ga,IcosahedronGeometry:Fa,IcosahedronBufferGeometry:Ha,DodecahedronGeometry:ka,DodecahedronBufferGeometry:Va,PolyhedronGeometry:Da,PolyhedronBufferGeometry:Na,TubeGeometry:ja,TubeBufferGeometry:Wa,TorusKnotGeometry:qa,TorusKnotBufferGeometry:Xa,TorusGeometry:Ya,TorusBufferGeometry:Ja,TextGeometry:Eo,TextBufferGeometry:Ao,SphereGeometry:Lo,SphereBufferGeometry:Po,RingGeometry:Ro,RingBufferGeometry:Co,PlaneGeometry:qn,PlaneBufferGeometry:Xn,LatheGeometry:Oo,LatheBufferGeometry:Io,ShapeGeometry:Do,ShapeBufferGeometry:No,ExtrudeGeometry:_o,ExtrudeBufferGeometry:Mo,EdgesGeometry:Bo,ConeGeometry:Fo,ConeBufferGeometry:Ho,CylinderGeometry:Uo,CylinderBufferGeometry:Go,CircleGeometry:ko,CircleBufferGeometry:Vo,BoxGeometry:jn,BoxBufferGeometry:Wn});function Wo(t){Jn.call(this),this.type="ShadowMaterial",this.color=new un(0),this.transparent=!0,this.setValues(t)}function qo(t){li.call(this,t),this.type="RawShaderMaterial"}function Xo(t){Jn.call(this),this.defines={STANDARD:""},this.type="MeshStandardMaterial",this.color=new un(16777215),this.roughness=.5,this.metalness=.5,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new un(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=Me,this.normalScale=new Ee(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.roughnessMap=null,this.metalnessMap=null,this.alphaMap=null,this.envMap=null,this.envMapIntensity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.setValues(t)}function Yo(t){Xo.call(this),this.defines={PHYSICAL:""},this.type="MeshPhysicalMaterial",this.reflectivity=.5,this.clearCoat=0,this.clearCoatRoughness=0,this.setValues(t)}function Jo(t){Jn.call(this),this.type="MeshPhongMaterial",this.color=new un(16777215),this.specular=new un(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new un(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=Me,this.normalScale=new Ee(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=J,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.setValues(t)}function Zo(t){Jo.call(this),this.defines={TOON:""},this.type="MeshToonMaterial",this.gradientMap=null,this.setValues(t)}function Qo(t){Jn.call(this),this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=Me,this.normalScale=new Ee(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.lights=!1,this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.setValues(t)}function Ko(t){Jn.call(this),this.type="MeshLambertMaterial",this.color=new un(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new un(0),this.emissiveIntensity=1,this.emissiveMap=null,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=J,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.setValues(t)}function $o(t){Jn.call(this),this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new un(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=Me,this.normalScale=new Ee(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.skinning=!1,this.morphTargets=!1,this.morphNormals=!1,this.lights=!1,this.setValues(t)}function ts(t){wa.call(this),this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}Wo.prototype=Object.create(Jn.prototype),Wo.prototype.constructor=Wo,Wo.prototype.isShadowMaterial=!0,Wo.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.color.copy(t.color),this},qo.prototype=Object.create(li.prototype),qo.prototype.constructor=qo,qo.prototype.isRawShaderMaterial=!0,Xo.prototype=Object.create(Jn.prototype),Xo.prototype.constructor=Xo,Xo.prototype.isMeshStandardMaterial=!0,Xo.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.defines={STANDARD:""},this.color.copy(t.color),this.roughness=t.roughness,this.metalness=t.metalness,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.roughnessMap=t.roughnessMap,this.metalnessMap=t.metalnessMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.envMapIntensity=t.envMapIntensity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.morphNormals=t.morphNormals,this},Yo.prototype=Object.create(Xo.prototype),Yo.prototype.constructor=Yo,Yo.prototype.isMeshPhysicalMaterial=!0,Yo.prototype.copy=function(t){return Xo.prototype.copy.call(this,t),this.defines={PHYSICAL:""},this.reflectivity=t.reflectivity,this.clearCoat=t.clearCoat,this.clearCoatRoughness=t.clearCoatRoughness,this},Jo.prototype=Object.create(Jn.prototype),Jo.prototype.constructor=Jo,Jo.prototype.isMeshPhongMaterial=!0,Jo.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.morphNormals=t.morphNormals,this},Zo.prototype=Object.create(Jo.prototype),Zo.prototype.constructor=Zo,Zo.prototype.isMeshToonMaterial=!0,Zo.prototype.copy=function(t){return Jo.prototype.copy.call(this,t),this.gradientMap=t.gradientMap,this},Qo.prototype=Object.create(Jn.prototype),Qo.prototype.constructor=Qo,Qo.prototype.isMeshNormalMaterial=!0,Qo.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.morphNormals=t.morphNormals,this},Ko.prototype=Object.create(Jn.prototype),Ko.prototype.constructor=Ko,Ko.prototype.isMeshLambertMaterial=!0,Ko.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.morphNormals=t.morphNormals,this},$o.prototype=Object.create(Jn.prototype),$o.prototype.constructor=$o,$o.prototype.isMeshMatcapMaterial=!0,$o.prototype.copy=function(t){return Jn.prototype.copy.call(this,t),this.defines={MATCAP:""},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.skinning=t.skinning,this.morphTargets=t.morphTargets,this.morphNormals=t.morphNormals,this},ts.prototype=Object.create(wa.prototype),ts.prototype.constructor=ts,ts.prototype.isLineDashedMaterial=!0,ts.prototype.copy=function(t){return wa.prototype.copy.call(this,t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this};var es=Object.freeze({ShadowMaterial:Wo,SpriteMaterial:ma,RawShaderMaterial:qo,ShaderMaterial:li,PointsMaterial:Ta,MeshPhysicalMaterial:Yo,MeshStandardMaterial:Xo,MeshPhongMaterial:Jo,MeshToonMaterial:Zo,MeshNormalMaterial:Qo,MeshLambertMaterial:Ko,MeshDepthMaterial:kr,MeshDistanceMaterial:Vr,MeshBasicMaterial:di,MeshMatcapMaterial:$o,LineDashedMaterial:ts,LineBasicMaterial:wa,Material:Jn}),ns={arraySlice:function(t,e,n){return ns.isTypedArray(t)?new t.constructor(t.subarray(e,void 0!==n?n:t.length)):t.slice(e,n)},convertArray:function(t,e,n){return!t||!n&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)},isTypedArray:function(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)},getKeyframeOrder:function(t){for(var e=t.length,n=new Array(e),i=0;i!==e;++i)n[i]=i;return n.sort(function(e,n){return t[e]-t[n]}),n},sortedArray:function(t,e,n){for(var i=t.length,r=new t.constructor(i),a=0,o=0;o!==i;++a)for(var s=n[a]*e,c=0;c!==e;++c)r[o++]=t[s+c];return r},flattenJSON:function(t,e,n,i){for(var r=1,a=t[0];void 0!==a&&void 0===a[i];)a=t[r++];if(void 0!==a){var o=a[i];if(void 0!==o)if(Array.isArray(o))do{void 0!==(o=a[i])&&(e.push(a.time),n.push.apply(n,o)),a=t[r++]}while(void 0!==a);else if(void 0!==o.toArray)do{void 0!==(o=a[i])&&(e.push(a.time),o.toArray(n,n.length)),a=t[r++]}while(void 0!==a);else do{void 0!==(o=a[i])&&(e.push(a.time),n.push(o)),a=t[r++]}while(void 0!==a)}}};function is(t,e,n,i){this.parameterPositions=t,this._cachedIndex=0,this.resultBuffer=void 0!==i?i:new e.constructor(n),this.sampleValues=e,this.valueSize=n}function rs(t,e,n,i){is.call(this,t,e,n,i),this._weightPrev=-0,this._offsetPrev=-0,this._weightNext=-0,this._offsetNext=-0}function as(t,e,n,i){is.call(this,t,e,n,i)}function os(t,e,n,i){is.call(this,t,e,n,i)}function ss(t,e,n,i){if(void 0===t)throw new Error("THREE.KeyframeTrack: track name is undefined");if(void 0===e||0===e.length)throw new Error("THREE.KeyframeTrack: no keyframes in track named "+t);this.name=t,this.times=ns.convertArray(e,this.TimeBufferType),this.values=ns.convertArray(n,this.ValueBufferType),this.setInterpolation(i||this.DefaultInterpolation)}function cs(t,e,n){ss.call(this,t,e,n)}function hs(t,e,n,i){ss.call(this,t,e,n,i)}function ls(t,e,n,i){ss.call(this,t,e,n,i)}function us(t,e,n,i){is.call(this,t,e,n,i)}function ps(t,e,n,i){ss.call(this,t,e,n,i)}function ds(t,e,n,i){ss.call(this,t,e,n,i)}function fs(t,e,n,i){ss.call(this,t,e,n,i)}function ms(t,e,n){this.name=t,this.tracks=n,this.duration=void 0!==e?e:-1,this.uuid=Te.generateUUID(),this.duration<0&&this.resetDuration()}function gs(t){if(void 0===t.type)throw new Error("THREE.KeyframeTrack: track type undefined, can not parse");var e=function(t){switch(t.toLowerCase()){case"scalar":case"double":case"float":case"number":case"integer":return ls;case"vector":case"vector2":case"vector3":case"vector4":return fs;case"color":return hs;case"quaternion":return ps;case"bool":case"boolean":return cs;case"string":return ds}throw new Error("THREE.KeyframeTrack: Unsupported typeName: "+t)}(t.type);if(void 0===t.times){var n=[],i=[];ns.flattenJSON(t.keys,n,i,"value"),t.times=n,t.values=i}return void 0!==e.parse?e.parse(t):new e(t.name,t.times,t.values,t.interpolation)}Object.assign(is.prototype,{evaluate:function(t){var e=this.parameterPositions,n=this._cachedIndex,i=e[n],r=e[n-1];t:{e:{var a;n:{i:if(!(t=r)break t;var s=e[1];t=(r=e[--n-1]))break e}a=n,n=0}for(;n>>1;te;)--a;if(++a,0!==r||a!==i){r>=a&&(r=(a=Math.max(a,1))-1);var o=this.getValueSize();this.times=ns.arraySlice(n,r,a),this.values=ns.arraySlice(this.values,r*o,a*o)}return this},validate:function(){var t=!0,e=this.getValueSize();e-Math.floor(e)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),t=!1);var n=this.times,i=this.values,r=n.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);for(var a=null,o=0;o!==r;o++){var s=n[o];if("number"==typeof s&&isNaN(s)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,o,s),t=!1;break}if(null!==a&&a>s){console.error("THREE.KeyframeTrack: Out of order keys.",this,o,s,a),t=!1;break}a=s}if(void 0!==i&&ns.isTypedArray(i)){o=0;for(var c=i.length;o!==c;++o){var h=i[o];if(isNaN(h)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,o,h),t=!1;break}}}return t},optimize:function(){for(var t=this.times,e=this.values,n=this.getValueSize(),i=2302===this.getInterpolation(),r=1,a=t.length-1,o=1;o0){t[r]=t[a];for(f=a*n,m=r*n,p=0;p!==n;++p)e[m+p]=e[f+p];++r}return r!==t.length&&(this.times=ns.arraySlice(t,0,r),this.values=ns.arraySlice(e,0,r*n)),this},clone:function(){var t=ns.arraySlice(this.times,0),e=ns.arraySlice(this.values,0),n=new(0,this.constructor)(this.name,t,e);return n.createInterpolant=this.createInterpolant,n}}),cs.prototype=Object.assign(Object.create(ss.prototype),{constructor:cs,ValueTypeName:"bool",ValueBufferType:Array,DefaultInterpolation:2300,InterpolantFactoryMethodLinear:void 0,InterpolantFactoryMethodSmooth:void 0}),hs.prototype=Object.assign(Object.create(ss.prototype),{constructor:hs,ValueTypeName:"color"}),ls.prototype=Object.assign(Object.create(ss.prototype),{constructor:ls,ValueTypeName:"number"}),us.prototype=Object.assign(Object.create(is.prototype),{constructor:us,interpolate_:function(t,e,n,i){for(var r=this.resultBuffer,a=this.sampleValues,o=this.valueSize,s=t*o,c=(n-e)/(i-e),h=s+o;s!==h;s+=4)Ae.slerpFlat(r,0,a,s-o,a,s,c);return r}}),ps.prototype=Object.assign(Object.create(ss.prototype),{constructor:ps,ValueTypeName:"quaternion",DefaultInterpolation:2301,InterpolantFactoryMethodLinear:function(t){return new us(this.times,this.values,this.getValueSize(),t)},InterpolantFactoryMethodSmooth:void 0}),ds.prototype=Object.assign(Object.create(ss.prototype),{constructor:ds,ValueTypeName:"string",ValueBufferType:Array,DefaultInterpolation:2300,InterpolantFactoryMethodLinear:void 0,InterpolantFactoryMethodSmooth:void 0}),fs.prototype=Object.assign(Object.create(ss.prototype),{constructor:fs,ValueTypeName:"vector"}),Object.assign(ms,{parse:function(t){for(var e=[],n=t.tracks,i=1/(t.fps||1),r=0,a=n.length;r!==a;++r)e.push(gs(n[r]).scale(i));return new ms(t.name,t.duration,e)},toJSON:function(t){for(var e=[],n=t.tracks,i={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid},r=0,a=n.length;r!==a;++r)e.push(ss.toJSON(n[r]));return i},CreateFromMorphTargetSequence:function(t,e,n,i){for(var r=e.length,a=[],o=0;o1){var h=i[u=c[1]];h||(i[u]=h=[]),h.push(s)}}var l=[];for(var u in i)l.push(ms.CreateFromMorphTargetSequence(u,i[u],e,n));return l},parseAnimation:function(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;for(var n=function(t,e,n,i,r){if(0!==n.length){var a=[],o=[];ns.flattenJSON(n,a,o,i),0!==a.length&&r.push(new t(e,a,o))}},i=[],r=t.name||"default",a=t.length||-1,o=t.fps||30,s=t.hierarchy||[],c=0;c0||0===t.search(/^data\:image\/jpeg/);r.format=i?It:Dt,r.needsUpdate=!0,void 0!==e&&e(r)},n,i),r},setCrossOrigin:function(t){return this.crossOrigin=t,this},setPath:function(t){return this.path=t,this}}),Object.assign(Ts.prototype,{getPoint:function(){return console.warn("THREE.Curve: .getPoint() not implemented."),null},getPointAt:function(t,e){var n=this.getUtoTmapping(t);return this.getPoint(n,e)},getPoints:function(t){void 0===t&&(t=5);for(var e=[],n=0;n<=t;n++)e.push(this.getPoint(n/t));return e},getSpacedPoints:function(t){void 0===t&&(t=5);for(var e=[],n=0;n<=t;n++)e.push(this.getPointAt(n/t));return e},getLength:function(){var t=this.getLengths();return t[t.length-1]},getLengths:function(t){if(void 0===t&&(t=this.arcLengthDivisions),this.cacheArcLengths&&this.cacheArcLengths.length===t+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;var e,n,i=[],r=this.getPoint(0),a=0;for(i.push(0),n=1;n<=t;n++)a+=(e=this.getPoint(n/t)).distanceTo(r),i.push(a),r=e;return this.cacheArcLengths=i,i},updateArcLengths:function(){this.needsUpdate=!0,this.getLengths()},getUtoTmapping:function(t,e){var n,i=this.getLengths(),r=0,a=i.length;n=e||t*i[a-1];for(var o,s=0,c=a-1;s<=c;)if((o=i[r=Math.floor(s+(c-s)/2)]-n)<0)s=r+1;else{if(!(o>0)){c=r;break}c=r-1}if(i[r=c]===n)return r/(a-1);var h=i[r];return(r+(n-h)/(i[r+1]-h))/(a-1)},getTangent:function(t){var e=t-1e-4,n=t+1e-4;e<0&&(e=0),n>1&&(n=1);var i=this.getPoint(e);return this.getPoint(n).clone().sub(i).normalize()},getTangentAt:function(t){var e=this.getUtoTmapping(t);return this.getTangent(e)},computeFrenetFrames:function(t,e){var n,i,r,a=new Le,o=[],s=[],c=[],h=new Le,l=new nn;for(n=0;n<=t;n++)i=n/t,o[n]=this.getTangentAt(i),o[n].normalize();s[0]=new Le,c[0]=new Le;var u=Number.MAX_VALUE,p=Math.abs(o[0].x),d=Math.abs(o[0].y),f=Math.abs(o[0].z);for(p<=u&&(u=p,a.set(1,0,0)),d<=u&&(u=d,a.set(0,1,0)),f<=u&&a.set(0,0,1),h.crossVectors(o[0],a).normalize(),s[0].crossVectors(o[0],h),c[0].crossVectors(o[0],s[0]),n=1;n<=t;n++)s[n]=s[n-1].clone(),c[n]=c[n-1].clone(),h.crossVectors(o[n-1],o[n]),h.length()>Number.EPSILON&&(h.normalize(),r=Math.acos(Ee.clamp(o[n-1].dot(o[n]),-1,1)),s[n].applyMatrix4(l.makeRotationAxis(h,r))),c[n].crossVectors(o[n],s[n]);if(!0===e)for(r=Math.acos(Ee.clamp(s[0].dot(s[t]),-1,1)),r/=t,o[0].dot(h.crossVectors(s[0],s[t]))>0&&(r=-r),n=1;n<=t;n++)s[n].applyMatrix4(l.makeRotationAxis(o[n],r*n)),c[n].crossVectors(o[n],s[n]);return{tangents:o,normals:s,binormals:c}},clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.arcLengthDivisions=t.arcLengthDivisions,this},toJSON:function(){var t={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t},fromJSON:function(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}),As.prototype=Object.create(Ts.prototype),As.prototype.constructor=As,As.prototype.isEllipseCurve=!0,As.prototype.getPoint=function(t,e){for(var n=e||new Te,i=2*Math.PI,r=this.aEndAngle-this.aStartAngle,a=Math.abs(r)i;)r-=i;r0?0:(Math.floor(Math.abs(l)/c)+1)*c:0===u&&l===c-1&&(l=c-2,u=1),this.closed||l>0?n=s[(l-1)%c]:(Rs.subVectors(s[0],s[1]).add(s[0]),n=Rs),i=s[l%c],r=s[(l+1)%c],this.closed||l+2i.length-2?i.length-1:a+1],l=i[a>i.length-3?i.length-1:a+2];return n.set(Ns(o,s.x,c.x,h.x,l.x),Ns(o,s.y,c.y,h.y,l.y)),n},js.prototype.copy=function(t){Ts.prototype.copy.call(this,t),this.points=[];for(var e=0,n=t.points.length;e=e){var r=n[i]-e,a=this.curves[i],o=a.getLength(),s=0===o?0:1-r/o;return a.getPointAt(s)}i++}return null},getLength:function(){var t=this.getCurveLengths();return t[t.length-1]},updateArcLengths:function(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()},getCurveLengths:function(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;for(var t=[],e=0,n=0,i=this.curves.length;n1&&!n[n.length-1].equals(n[0])&&n.push(n[0]),n},copy:function(t){Ts.prototype.copy.call(this,t),this.curves=[];for(var e=0,n=t.curves.length;e0){var h=c.getPoint(0);h.equals(this.currentPoint)||this.lineTo(h.x,h.y)}this.curves.push(c);var l=c.getPoint(1);this.currentPoint.copy(l)},copy:function(t){return qs.prototype.copy.call(this,t),this.currentPoint.copy(t.currentPoint),this},toJSON:function(){var t=qs.prototype.toJSON.call(this);return t.currentPoint=this.currentPoint.toArray(),t},fromJSON:function(t){return qs.prototype.fromJSON.call(this,t),this.currentPoint.fromArray(t.currentPoint),this}}),Ys.prototype=Object.assign(Object.create(Xs.prototype),{constructor:Ys,getPointsHoles:function(t){for(var e=[],n=0,i=this.holes.length;n0){var a=new Ms(new ys(e));a.setCrossOrigin(this.crossOrigin);for(var o=0,s=t.length;o0?new ya(o,s):new fi(o,s),void 0!==t.drawMode&&i.setDrawMode(t.drawMode);break;case"LOD":i=new va;break;case"Line":i=new _a(r(t.geometry),a(t.material),t.mode);break;case"LineLoop":i=new Sa(r(t.geometry),a(t.material));break;case"LineSegments":i=new Ma(r(t.geometry),a(t.material));break;case"PointCloud":case"Points":i=new Ta(r(t.geometry),a(t.material));break;case"Sprite":i=new ga(a(t.material));break;case"Group":i=new Yr;break;default:i=new En}if(i.uuid=t.uuid,void 0!==t.name&&(i.name=t.name),void 0!==t.matrix?(i.matrix.fromArray(t.matrix),void 0!==t.matrixAutoUpdate&&(i.matrixAutoUpdate=t.matrixAutoUpdate),i.matrixAutoUpdate&&i.matrix.decompose(i.position,i.quaternion,i.scale)):(void 0!==t.position&&i.position.fromArray(t.position),void 0!==t.rotation&&i.rotation.fromArray(t.rotation),void 0!==t.quaternion&&i.quaternion.fromArray(t.quaternion),void 0!==t.scale&&i.scale.fromArray(t.scale)),void 0!==t.castShadow&&(i.castShadow=t.castShadow),void 0!==t.receiveShadow&&(i.receiveShadow=t.receiveShadow),t.shadow&&(void 0!==t.shadow.bias&&(i.shadow.bias=t.shadow.bias),void 0!==t.shadow.radius&&(i.shadow.radius=t.shadow.radius),void 0!==t.shadow.mapSize&&i.shadow.mapSize.fromArray(t.shadow.mapSize),void 0!==t.shadow.camera&&(i.shadow.camera=this.parseObject(t.shadow.camera))),void 0!==t.visible&&(i.visible=t.visible),void 0!==t.frustumCulled&&(i.frustumCulled=t.frustumCulled),void 0!==t.renderOrder&&(i.renderOrder=t.renderOrder),void 0!==t.userData&&(i.userData=t.userData),void 0!==t.layers&&(i.layers.mask=t.layers),void 0!==t.children)for(var c=t.children,h=0;hNumber.EPSILON){if(h<0&&(o=e[a],c=-c,s=e[r],h=-h),t.ys.y)continue;if(t.y===o.y){if(t.x===o.x)return!0}else{var l=h*(t.x-o.x)-c*(t.y-o.y);if(0===l)return!0;if(l<0)continue;i=!i}}else{if(t.y!==o.y)continue;if(s.x<=t.x&&t.x<=o.x||o.x<=t.x&&t.x<=s.x)return!0}}return i}var r=xo.isClockWise,a=this.subPaths;if(0===a.length)return[];if(!0===e)return n(a);var o,s,c,h=[];if(1===a.length)return s=a[0],(c=new Ys).curves=s.curves,h.push(c),h;var l=!r(a[0].getPoints());l=t?!l:l;var u,p,d=[],f=[],m=[],g=0;f[g]=void 0,m[g]=[];for(var v=0,y=a.length;v1){for(var x=!1,b=[],w=0,_=f.length;w<_;w++)d[w]=[];for(w=0,_=f.length;w<_;w++)for(var M=m[w],S=0;S0&&(x||(m=d))}v=0;for(var L=f.length;v0){this.source.connect(this.filters[0]);for(var t=1,e=this.filters.length;t0){this.source.disconnect(this.filters[0]);for(var t=1,e=this.filters.length;t=.5)for(var a=0;a!==r;++a)t[e+a]=t[n+a]},_slerp:function(t,e,n,i){Ae.slerpFlat(t,e,t,e,t,n,i)},_lerp:function(t,e,n,i,r){for(var a=1-i,o=0;o!==r;++o){var s=e+o;t[s]=t[s]*a+t[n+o]*i}}});var Gc,Fc,Hc,kc,Vc,jc,Wc,qc,Xc,Yc,Jc,Zc,Qc,Kc,$c;function th(t,e,n){var i=n||eh.parseTrackName(e);this._targetGroup=t,this._bindings=t.subscribe_(e,i)}function eh(t,e,n){this.path=e,this.parsedPath=n||eh.parseTrackName(e),this.node=eh.findNode(t,this.parsedPath.nodeName)||t,this.rootNode=t}function nh(t,e,n){this._mixer=t,this._clip=e,this._localRoot=n||null;for(var i=e.tracks,r=i.length,a=new Array(r),o={endingStart:le,endingEnd:le},s=0;s!==r;++s){var c=i[s].createInterpolant(null);a[s]=c,c.settings=o}this._interpolantSettings=o,this._interpolants=a,this._propertyBindings=new Array(r),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=he,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}function ih(t){this._root=t,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}function rh(t){"string"==typeof t&&(console.warn("THREE.Uniform: Type parameter is no longer needed."),t=arguments[1]),this.value=t}function ah(){Vn.call(this),this.type="InstancedBufferGeometry",this.maxInstancedCount=void 0}function oh(t,e,n){da.call(this,t,e),this.meshPerAttribute=n||1}function sh(t,e,n,i){"number"==typeof n&&(i=n,n=!1,console.error("THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.")),Rn.call(this,t,e,n),this.meshPerAttribute=i||1}function ch(t,e){return t.distance-e.distance}function hh(t,e,n,i){if(!1!==t.visible&&(t.raycast(e,n),!0===i))for(var r=t.children,a=0,o=r.length;ae;)--a;if(++a,0!==r||a!==i){r>=a&&(r=(a=Math.max(a,1))-1);var o=this.getValueSize();this.times=ns.arraySlice(n,r,a),this.values=ns.arraySlice(this.values,r*o,a*o)}return this},validate:function(){var t=!0,e=this.getValueSize();e-Math.floor(e)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),t=!1);var n=this.times,i=this.values,r=n.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);for(var a=null,o=0;o!==r;o++){var s=n[o];if("number"==typeof s&&isNaN(s)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,o,s),t=!1;break}if(null!==a&&a>s){console.error("THREE.KeyframeTrack: Out of order keys.",this,o,s,a),t=!1;break}a=s}if(void 0!==i&&ns.isTypedArray(i)){o=0;for(var c=i.length;o!==c;++o){var h=i[o];if(isNaN(h)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,o,h),t=!1;break}}}return t},optimize:function(){for(var t=this.times,e=this.values,n=this.getValueSize(),i=2302===this.getInterpolation(),r=1,a=t.length-1,o=1;o0){t[r]=t[a];for(f=a*n,m=r*n,p=0;p!==n;++p)e[m+p]=e[f+p];++r}return r!==t.length&&(this.times=ns.arraySlice(t,0,r),this.values=ns.arraySlice(e,0,r*n)),this},clone:function(){var t=ns.arraySlice(this.times,0),e=ns.arraySlice(this.values,0),n=new(0,this.constructor)(this.name,t,e);return n.createInterpolant=this.createInterpolant,n}}),cs.prototype=Object.assign(Object.create(ss.prototype),{constructor:cs,ValueTypeName:"bool",ValueBufferType:Array,DefaultInterpolation:2300,InterpolantFactoryMethodLinear:void 0,InterpolantFactoryMethodSmooth:void 0}),hs.prototype=Object.assign(Object.create(ss.prototype),{constructor:hs,ValueTypeName:"color"}),ls.prototype=Object.assign(Object.create(ss.prototype),{constructor:ls,ValueTypeName:"number"}),us.prototype=Object.assign(Object.create(is.prototype),{constructor:us,interpolate_:function(t,e,n,i){for(var r=this.resultBuffer,a=this.sampleValues,o=this.valueSize,s=t*o,c=(n-e)/(i-e),h=s+o;s!==h;s+=4)Ae.slerpFlat(r,0,a,s-o,a,s,c);return r}}),ps.prototype=Object.assign(Object.create(ss.prototype),{constructor:ps,ValueTypeName:"quaternion",DefaultInterpolation:2301,InterpolantFactoryMethodLinear:function(t){return new us(this.times,this.values,this.getValueSize(),t)},InterpolantFactoryMethodSmooth:void 0}),ds.prototype=Object.assign(Object.create(ss.prototype),{constructor:ds,ValueTypeName:"string",ValueBufferType:Array,DefaultInterpolation:2300,InterpolantFactoryMethodLinear:void 0,InterpolantFactoryMethodSmooth:void 0}),fs.prototype=Object.assign(Object.create(ss.prototype),{constructor:fs,ValueTypeName:"vector"}),Object.assign(ms,{parse:function(t){for(var e=[],n=t.tracks,i=1/(t.fps||1),r=0,a=n.length;r!==a;++r)e.push(gs(n[r]).scale(i));return new ms(t.name,t.duration,e)},toJSON:function(t){for(var e=[],n=t.tracks,i={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid},r=0,a=n.length;r!==a;++r)e.push(ss.toJSON(n[r]));return i},CreateFromMorphTargetSequence:function(t,e,n,i){for(var r=e.length,a=[],o=0;o1){var h=i[u=c[1]];h||(i[u]=h=[]),h.push(s)}}var l=[];for(var u in i)l.push(ms.CreateFromMorphTargetSequence(u,i[u],e,n));return l},parseAnimation:function(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;for(var n=function(t,e,n,i,r){if(0!==n.length){var a=[],o=[];ns.flattenJSON(n,a,o,i),0!==a.length&&r.push(new t(e,a,o))}},i=[],r=t.name||"default",a=t.length||-1,o=t.fps||30,s=t.hierarchy||[],c=0;c0||0===t.search(/^data\:image\/jpeg/);r.format=i?It:Dt,r.needsUpdate=!0,void 0!==e&&e(r)},n,i),r},setCrossOrigin:function(t){return this.crossOrigin=t,this},setPath:function(t){return this.path=t,this}}),Object.assign(Es.prototype,{getPoint:function(){return console.warn("THREE.Curve: .getPoint() not implemented."),null},getPointAt:function(t,e){var n=this.getUtoTmapping(t);return this.getPoint(n,e)},getPoints:function(t){void 0===t&&(t=5);for(var e=[],n=0;n<=t;n++)e.push(this.getPoint(n/t));return e},getSpacedPoints:function(t){void 0===t&&(t=5);for(var e=[],n=0;n<=t;n++)e.push(this.getPointAt(n/t));return e},getLength:function(){var t=this.getLengths();return t[t.length-1]},getLengths:function(t){if(void 0===t&&(t=this.arcLengthDivisions),this.cacheArcLengths&&this.cacheArcLengths.length===t+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;var e,n,i=[],r=this.getPoint(0),a=0;for(i.push(0),n=1;n<=t;n++)a+=(e=this.getPoint(n/t)).distanceTo(r),i.push(a),r=e;return this.cacheArcLengths=i,i},updateArcLengths:function(){this.needsUpdate=!0,this.getLengths()},getUtoTmapping:function(t,e){var n,i=this.getLengths(),r=0,a=i.length;n=e||t*i[a-1];for(var o,s=0,c=a-1;s<=c;)if((o=i[r=Math.floor(s+(c-s)/2)]-n)<0)s=r+1;else{if(!(o>0)){c=r;break}c=r-1}if(i[r=c]===n)return r/(a-1);var h=i[r];return(r+(n-h)/(i[r+1]-h))/(a-1)},getTangent:function(t){var e=t-1e-4,n=t+1e-4;e<0&&(e=0),n>1&&(n=1);var i=this.getPoint(e);return this.getPoint(n).clone().sub(i).normalize()},getTangentAt:function(t){var e=this.getUtoTmapping(t);return this.getTangent(e)},computeFrenetFrames:function(t,e){var n,i,r,a=new Le,o=[],s=[],c=[],h=new Le,l=new nn;for(n=0;n<=t;n++)i=n/t,o[n]=this.getTangentAt(i),o[n].normalize();s[0]=new Le,c[0]=new Le;var u=Number.MAX_VALUE,p=Math.abs(o[0].x),d=Math.abs(o[0].y),f=Math.abs(o[0].z);for(p<=u&&(u=p,a.set(1,0,0)),d<=u&&(u=d,a.set(0,1,0)),f<=u&&a.set(0,0,1),h.crossVectors(o[0],a).normalize(),s[0].crossVectors(o[0],h),c[0].crossVectors(o[0],s[0]),n=1;n<=t;n++)s[n]=s[n-1].clone(),c[n]=c[n-1].clone(),h.crossVectors(o[n-1],o[n]),h.length()>Number.EPSILON&&(h.normalize(),r=Math.acos(Te.clamp(o[n-1].dot(o[n]),-1,1)),s[n].applyMatrix4(l.makeRotationAxis(h,r))),c[n].crossVectors(o[n],s[n]);if(!0===e)for(r=Math.acos(Te.clamp(s[0].dot(s[t]),-1,1)),r/=t,o[0].dot(h.crossVectors(s[0],s[t]))>0&&(r=-r),n=1;n<=t;n++)s[n].applyMatrix4(l.makeRotationAxis(o[n],r*n)),c[n].crossVectors(o[n],s[n]);return{tangents:o,normals:s,binormals:c}},clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.arcLengthDivisions=t.arcLengthDivisions,this},toJSON:function(){var t={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t},fromJSON:function(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}),As.prototype=Object.create(Es.prototype),As.prototype.constructor=As,As.prototype.isEllipseCurve=!0,As.prototype.getPoint=function(t,e){for(var n=e||new Ee,i=2*Math.PI,r=this.aEndAngle-this.aStartAngle,a=Math.abs(r)i;)r-=i;r0?0:(Math.floor(Math.abs(l)/c)+1)*c:0===u&&l===c-1&&(l=c-2,u=1),this.closed||l>0?n=s[(l-1)%c]:(Rs.subVectors(s[0],s[1]).add(s[0]),n=Rs),i=s[l%c],r=s[(l+1)%c],this.closed||l+2i.length-2?i.length-1:a+1],l=i[a>i.length-3?i.length-1:a+2];return n.set(Ns(o,s.x,c.x,h.x,l.x),Ns(o,s.y,c.y,h.y,l.y)),n},js.prototype.copy=function(t){Es.prototype.copy.call(this,t),this.points=[];for(var e=0,n=t.points.length;e=e){var r=n[i]-e,a=this.curves[i],o=a.getLength(),s=0===o?0:1-r/o;return a.getPointAt(s)}i++}return null},getLength:function(){var t=this.getCurveLengths();return t[t.length-1]},updateArcLengths:function(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()},getCurveLengths:function(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;for(var t=[],e=0,n=0,i=this.curves.length;n1&&!n[n.length-1].equals(n[0])&&n.push(n[0]),n},copy:function(t){Es.prototype.copy.call(this,t),this.curves=[];for(var e=0,n=t.curves.length;e0){var h=c.getPoint(0);h.equals(this.currentPoint)||this.lineTo(h.x,h.y)}this.curves.push(c);var l=c.getPoint(1);this.currentPoint.copy(l)},copy:function(t){return qs.prototype.copy.call(this,t),this.currentPoint.copy(t.currentPoint),this},toJSON:function(){var t=qs.prototype.toJSON.call(this);return t.currentPoint=this.currentPoint.toArray(),t},fromJSON:function(t){return qs.prototype.fromJSON.call(this,t),this.currentPoint.fromArray(t.currentPoint),this}}),Ys.prototype=Object.assign(Object.create(Xs.prototype),{constructor:Ys,getPointsHoles:function(t){for(var e=[],n=0,i=this.holes.length;n0){var a=new Ms(new ys(e));a.setCrossOrigin(this.crossOrigin);for(var o=0,s=t.length;o0?new ya(o,s):new fi(o,s),void 0!==t.drawMode&&i.setDrawMode(t.drawMode);break;case"LOD":i=new va;break;case"Line":i=new _a(r(t.geometry),a(t.material),t.mode);break;case"LineLoop":i=new Sa(r(t.geometry),a(t.material));break;case"LineSegments":i=new Ma(r(t.geometry),a(t.material));break;case"PointCloud":case"Points":i=new Ea(r(t.geometry),a(t.material));break;case"Sprite":i=new ga(a(t.material));break;case"Group":i=new Yr;break;default:i=new Tn}if(i.uuid=t.uuid,void 0!==t.name&&(i.name=t.name),void 0!==t.matrix?(i.matrix.fromArray(t.matrix),void 0!==t.matrixAutoUpdate&&(i.matrixAutoUpdate=t.matrixAutoUpdate),i.matrixAutoUpdate&&i.matrix.decompose(i.position,i.quaternion,i.scale)):(void 0!==t.position&&i.position.fromArray(t.position),void 0!==t.rotation&&i.rotation.fromArray(t.rotation),void 0!==t.quaternion&&i.quaternion.fromArray(t.quaternion),void 0!==t.scale&&i.scale.fromArray(t.scale)),void 0!==t.castShadow&&(i.castShadow=t.castShadow),void 0!==t.receiveShadow&&(i.receiveShadow=t.receiveShadow),t.shadow&&(void 0!==t.shadow.bias&&(i.shadow.bias=t.shadow.bias),void 0!==t.shadow.radius&&(i.shadow.radius=t.shadow.radius),void 0!==t.shadow.mapSize&&i.shadow.mapSize.fromArray(t.shadow.mapSize),void 0!==t.shadow.camera&&(i.shadow.camera=this.parseObject(t.shadow.camera))),void 0!==t.visible&&(i.visible=t.visible),void 0!==t.frustumCulled&&(i.frustumCulled=t.frustumCulled),void 0!==t.renderOrder&&(i.renderOrder=t.renderOrder),void 0!==t.userData&&(i.userData=t.userData),void 0!==t.layers&&(i.layers.mask=t.layers),void 0!==t.children)for(var c=t.children,h=0;hNumber.EPSILON){if(h<0&&(o=e[a],c=-c,s=e[r],h=-h),t.ys.y)continue;if(t.y===o.y){if(t.x===o.x)return!0}else{var l=h*(t.x-o.x)-c*(t.y-o.y);if(0===l)return!0;if(l<0)continue;i=!i}}else{if(t.y!==o.y)continue;if(s.x<=t.x&&t.x<=o.x||o.x<=t.x&&t.x<=s.x)return!0}}return i}var r=xo.isClockWise,a=this.subPaths;if(0===a.length)return[];if(!0===e)return n(a);var o,s,c,h=[];if(1===a.length)return s=a[0],(c=new Ys).curves=s.curves,h.push(c),h;var l=!r(a[0].getPoints());l=t?!l:l;var u,p,d=[],f=[],m=[],g=0;f[g]=void 0,m[g]=[];for(var v=0,y=a.length;v1){for(var x=!1,b=[],w=0,_=f.length;w<_;w++)d[w]=[];for(w=0,_=f.length;w<_;w++)for(var M=m[w],S=0;S0&&(x||(m=d))}v=0;for(var L=f.length;v0){this.source.connect(this.filters[0]);for(var t=1,e=this.filters.length;t0){this.source.disconnect(this.filters[0]);for(var t=1,e=this.filters.length;t=.5)for(var a=0;a!==r;++a)t[e+a]=t[n+a]},_slerp:function(t,e,n,i){Ae.slerpFlat(t,e,t,e,t,n,i)},_lerp:function(t,e,n,i,r){for(var a=1-i,o=0;o!==r;++o){var s=e+o;t[s]=t[s]*a+t[n+o]*i}}});var Gc,Fc,Hc,kc,Vc,jc,Wc,qc,Xc,Yc,Jc,Zc,Qc,Kc,$c;function th(t,e,n){var i=n||eh.parseTrackName(e);this._targetGroup=t,this._bindings=t.subscribe_(e,i)}function eh(t,e,n){this.path=e,this.parsedPath=n||eh.parseTrackName(e),this.node=eh.findNode(t,this.parsedPath.nodeName)||t,this.rootNode=t}function nh(t,e,n){this._mixer=t,this._clip=e,this._localRoot=n||null;for(var i=e.tracks,r=i.length,a=new Array(r),o={endingStart:le,endingEnd:le},s=0;s!==r;++s){var c=i[s].createInterpolant(null);a[s]=c,c.settings=o}this._interpolantSettings=o,this._interpolants=a,this._propertyBindings=new Array(r),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=he,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}function ih(t){this._root=t,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}function rh(t){"string"==typeof t&&(console.warn("THREE.Uniform: Type parameter is no longer needed."),t=arguments[1]),this.value=t}function ah(){Vn.call(this),this.type="InstancedBufferGeometry",this.maxInstancedCount=void 0}function oh(t,e,n){da.call(this,t,e),this.meshPerAttribute=n||1}function sh(t,e,n,i){"number"==typeof n&&(i=n,n=!1,console.error("THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.")),Rn.call(this,t,e,n),this.meshPerAttribute=i||1}function ch(t,e){return t.distance-e.distance}function hh(t,e,n,i){if(!1!==t.visible&&(t.raycast(e,n),!0===i))for(var r=t.children,a=0,o=r.length;a=e){var l=e++,u=t[l];n[u.uuid]=h,t[h]=u,n[c]=l,t[l]=s;for(var p=0,d=r;p!==d;++p){var f=i[p],m=f[l],g=f[h];f[h]=m,f[l]=g}}}this.nCachedObjects_=e},uncache:function(){for(var t=this._objects,e=t.length,n=this.nCachedObjects_,i=this._indicesByUUID,r=this._bindings,a=r.length,o=0,s=arguments.length;o!==s;++o){var c=arguments[o].uuid,h=i[c];if(void 0!==h)if(delete i[c],h0)for(var c=this._interpolants,h=this._propertyBindings,l=0,u=c.length;l!==u;++l)c[l].evaluate(o),h[l].accumulate(i,s)}else this._updateWeight(t)},_updateWeight:function(t){var e=0;if(this.enabled){e=this.weight;var n=this._weightInterpolant;if(null!==n){var i=n.evaluate(t)[0];e*=i,t>n.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=e,e},_updateTimeScale:function(t){var e=0;if(!this.paused){e=this.timeScale;var n=this._timeScaleInterpolant;if(null!==n)e*=n.evaluate(t)[0],t>n.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}return this._effectiveTimeScale=e,e},_updateTime:function(t){var e=this.time+t,n=this._clip.duration,i=this.loop,r=this._loopCount,a=2202===i;if(0===t)return-1===r?e:a&&1==(1&r)?n-e:e;if(2200===i){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(e>=n)e=n;else{if(!(e<0))break t;e=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this._mixer.dispatchEvent({type:"finished",action:this,direction:t<0?-1:1})}}else{if(-1===r&&(t>=0?(r=0,this._setEndings(!0,0===this.repetitions,a)):this._setEndings(0===this.repetitions,!0,a)),e>=n||e<0){var o=Math.floor(e/n);e-=n*o,r+=Math.abs(o);var s=this.repetitions-r;if(s<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,e=t>0?n:0,this._mixer.dispatchEvent({type:"finished",action:this,direction:t>0?1:-1});else{if(1===s){var c=t<0;this._setEndings(c,!c,a)}else this._setEndings(!1,!1,a);this._loopCount=r,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:o})}}if(a&&1==(1&r))return this.time=e,n-e}return this.time=e,e},_setEndings:function(t,e,n){var i=this._interpolantSettings;n?(i.endingStart=2401,i.endingEnd=2401):(i.endingStart=t?this.zeroSlopeAtStart?2401:le:2402,i.endingEnd=e?this.zeroSlopeAtEnd?2401:le:2402)},_scheduleFading:function(t,e,n){var i=this._mixer,r=i.time,a=this._weightInterpolant;null===a&&(a=i._lendControlInterpolant(),this._weightInterpolant=a);var o=a.parameterPositions,s=a.sampleValues;return o[0]=r,s[0]=e,o[1]=r+t,s[1]=n,this}}),ih.prototype=Object.assign(Object.create(i.prototype),{constructor:ih,_bindAction:function(t,e){var n=t._localRoot||this._root,i=t._clip.tracks,r=i.length,a=t._propertyBindings,o=t._interpolants,s=n.uuid,c=this._bindingsByRootAndName,h=c[s];void 0===h&&(h={},c[s]=h);for(var l=0;l!==r;++l){var u=i[l],p=u.name,d=h[p];if(void 0!==d)a[l]=d;else{if(void 0!==(d=a[l])){null===d._cacheIndex&&(++d.referenceCount,this._addInactiveBinding(d,s,p));continue}var f=e&&e._propertyBindings[l].binding.parsedPath;++(d=new Uc(eh.create(n,p,f),u.ValueTypeName,u.getValueSize())).referenceCount,this._addInactiveBinding(d,s,p),a[l]=d}o[l].resultBuffer=d.buffer}},_activateAction:function(t){if(!this._isActiveAction(t)){if(null===t._cacheIndex){var e=(t._localRoot||this._root).uuid,n=t._clip.uuid,i=this._actionsByClip[n];this._bindAction(t,i&&i.knownActions[0]),this._addInactiveAction(t,n,e)}for(var r=t._propertyBindings,a=0,o=r.length;a!==o;++a){var s=r[a];0==s.useCount++&&(this._lendBinding(s),s.saveOriginalState())}this._lendAction(t)}},_deactivateAction:function(t){if(this._isActiveAction(t)){for(var e=t._propertyBindings,n=0,i=e.length;n!==i;++n){var r=e[n];0==--r.useCount&&(r.restoreOriginalState(),this._takeBackBinding(r))}this._takeBackAction(t)}},_initMemoryManager:function(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;var t=this;this.stats={actions:{get total(){return t._actions.length},get inUse(){return t._nActiveActions}},bindings:{get total(){return t._bindings.length},get inUse(){return t._nActiveBindings}},controlInterpolants:{get total(){return t._controlInterpolants.length},get inUse(){return t._nActiveControlInterpolants}}}},_isActiveAction:function(t){var e=t._cacheIndex;return null!==e&&ethis.max.x||t.ythis.max.y)},containsBox:function(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y},getParameter:function(t,e){return void 0===e&&(console.warn("THREE.Box2: .getParameter() target is now required"),e=new Te),e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))},intersectsBox:function(t){return!(t.max.xthis.max.x||t.max.ythis.max.y)},clampPoint:function(t,e){return void 0===e&&(console.warn("THREE.Box2: .clampPoint() target is now required"),e=new Te),e.copy(t).clamp(this.min,this.max)},distanceToPoint:function(){var t=new Te;return function(e){return t.copy(e).clamp(this.min,this.max).sub(e).length()}}(),intersect:function(t){return this.min.max(t.min),this.max.min(t.max),this},union:function(t){return this.min.min(t.min),this.max.max(t.max),this},translate:function(t){return this.min.add(t),this.max.add(t),this},equals:function(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}),Object.assign(uh.prototype,{set:function(t,e){return this.start.copy(t),this.end.copy(e),this},clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.start.copy(t.start),this.end.copy(t.end),this},getCenter:function(t){return void 0===t&&(console.warn("THREE.Line3: .getCenter() target is now required"),t=new Le),t.addVectors(this.start,this.end).multiplyScalar(.5)},delta:function(t){return void 0===t&&(console.warn("THREE.Line3: .delta() target is now required"),t=new Le),t.subVectors(this.end,this.start)},distanceSq:function(){return this.start.distanceToSquared(this.end)},distance:function(){return this.start.distanceTo(this.end)},at:function(t,e){return void 0===e&&(console.warn("THREE.Line3: .at() target is now required"),e=new Le),this.delta(e).multiplyScalar(t).add(this.start)},closestPointToPointParameter:(Yc=new Le,Jc=new Le,function(t,e){Yc.subVectors(t,this.start),Jc.subVectors(this.end,this.start);var n=Jc.dot(Jc),i=Jc.dot(Yc)/n;return e&&(i=Ee.clamp(i,0,1)),i}),closestPointToPoint:function(t,e,n){var i=this.closestPointToPointParameter(t,e);return void 0===n&&(console.warn("THREE.Line3: .closestPointToPoint() target is now required"),n=new Le),this.delta(n).multiplyScalar(i).add(this.start)},applyMatrix4:function(t){return this.start.applyMatrix4(t),this.end.applyMatrix4(t),this},equals:function(t){return t.start.equals(this.start)&&t.end.equals(this.end)}}),ph.prototype=Object.create(En.prototype),ph.prototype.constructor=ph,ph.prototype.isImmediateRenderObject=!0,dh.prototype=Object.create(Ma.prototype),dh.prototype.constructor=dh,dh.prototype.update=function(){var t=new Le,e=new Le,n=new Pe;return function(){var i=["a","b","c"];this.object.updateMatrixWorld(!0),n.getNormalMatrix(this.object.matrixWorld);var r=this.object.matrixWorld,a=this.geometry.attributes.position,o=this.object.geometry;if(o&&o.isGeometry)for(var s=o.vertices,c=o.faces,h=0,l=0,u=c.length;l1&&t.multiplyScalar(1/e),this.children[0].material.color.copy(this.material.color)}},vh.prototype.dispose=function(){this.geometry.dispose(),this.material.dispose(),this.children[0].geometry.dispose(),this.children[0].material.dispose()},yh.prototype=Object.create(En.prototype),yh.prototype.constructor=yh,yh.prototype.dispose=function(){this.children[0].geometry.dispose(),this.children[0].material.dispose()},yh.prototype.update=function(){var t=new Le,e=new un,n=new un;return function(){var i=this.children[0];if(void 0!==this.color)this.material.color.set(this.color);else{var r=i.geometry.getAttribute("color");e.copy(this.light.color),n.copy(this.light.groundColor);for(var a=0,o=r.count;a.99999?this.quaternion.set(0,0,0,1):t.y<-.99999?this.quaternion.set(1,0,0,0):($c.set(t.z,0,-t.x).normalize(),Kc=Math.acos(t.y),this.quaternion.setFromAxisAngle($c,Kc))}),Ph.prototype.setLength=function(t,e,n){void 0===e&&(e=.2*t),void 0===n&&(n=.2*e),this.line.scale.set(1,Math.max(0,t-e),1),this.line.updateMatrix(),this.cone.scale.set(n,e,n),this.cone.position.y=t,this.cone.updateMatrix()},Ph.prototype.setColor=function(t){this.line.material.color.copy(t),this.cone.material.color.copy(t)},Ph.prototype.copy=function(t){return En.prototype.copy.call(this,t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this},Ph.prototype.clone=function(){return(new this.constructor).copy(this)},Rh.prototype=Object.create(Ma.prototype),Rh.prototype.constructor=Rh;function Ch(t){console.warn("THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead."),Ds.call(this,t),this.type="catmullrom"}Ts.create=function(t,e){return console.log("THREE.Curve.create() has been deprecated"),t.prototype=Object.create(Ts.prototype),t.prototype.constructor=t,t.prototype.getPoint=e,t},Object.assign(qs.prototype,{createPointsGeometry:function(t){console.warn("THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.");var e=this.getPoints(t);return this.createGeometry(e)},createSpacedPointsGeometry:function(t){console.warn("THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.");var e=this.getSpacedPoints(t);return this.createGeometry(e)},createGeometry:function(t){console.warn("THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.");for(var e=new Pn,n=0,i=t.length;n0},flags_are_same:function(t,e){return(this.cached_ints[0]&(t|e))==(t|e)||(this.cached_ints[0]&t)+(this.cached_ints[0]&e)==0},flags_are_on:function(t,e){return(this.cached_ints[0]&(t|e))==(t|e)},flags_are_off:function(t,e){return(this.cached_ints[0]&t)+(this.cached_ints[0]&e)==0},flags_are_either_on:function(t,e){return(this.cached_ints[0]&(t|e))>0}};let Ih=function(){let t=this,e=document.getElementById("a");this.hud=document.getElementById("b"),this.hud_context=this.hud.getContext("2d"),this.hud_context.beginPath(),this.hud_context.arc(150,150,50,0,2*Math.PI),this.hud_context.stroke();var n=new pa,i=new Zr(75,window.innerWidth/window.innerHeight,.1,1e3);this.renderer=new ha({canvas:e,context:e.getContext("webgl2")}),this.renderer.setSize(window.innerWidth,window.innerHeight);var r=new fi(new jn(1,1,1),new di({color:65280}));n.add(r),i.position.z=5,this.animate=function(){requestAnimationFrame(t.animate),r.rotation.x+=.01,r.rotation.y+=.01,t.renderer.render(n,i)},this.animate(),window.addEventListener("resize",function(e){return e.preventDefault(),t.cached_ints[1]=window.innerWidth,t.cached_ints[2]=window.innerHeight,t.cached_floats[3]=window.innerWidth/window.innerHeight,console.log("On resize!"),t.renderer.setSize(t.cached_ints[1],t.cached_ints[2]),t.hud.width=t.cached_ints[1],t.hud.height=t.cached_ints[2],t.hud_context.beginPath(),t.hud_context.arc(150,150,50,0,2*Math.PI),t.hud_context.stroke(),!1},!0)};Ih.prototype={cached_ints:new Uint32Array(4),cached_floats:new Float64Array(13)};new Ih}]); \ No newline at end of file +Object.assign(eh.prototype,{_getValue_unbound:eh.prototype.getValue,_setValue_unbound:eh.prototype.setValue}),Object.assign(function(){this.uuid=Te.generateUUID(),this._objects=Array.prototype.slice.call(arguments),this.nCachedObjects_=0;var t={};this._indicesByUUID=t;for(var e=0,n=arguments.length;e!==n;++e)t[arguments[e].uuid]=e;this._paths=[],this._parsedPaths=[],this._bindings=[],this._bindingsIndicesByPath={};var i=this;this.stats={objects:{get total(){return i._objects.length},get inUse(){return this.total-i.nCachedObjects_}},get bindingsPerObject(){return i._bindings.length}}}.prototype,{isAnimationObjectGroup:!0,add:function(){for(var t=this._objects,e=t.length,n=this.nCachedObjects_,i=this._indicesByUUID,r=this._paths,a=this._parsedPaths,o=this._bindings,s=o.length,c=void 0,h=0,l=arguments.length;h!==l;++h){var u=arguments[h],p=u.uuid,d=i[p];if(void 0===d){d=e++,i[p]=d,t.push(u);for(var f=0,m=s;f!==m;++f)o[f].push(new eh(u,r[f],a[f]))}else if(d=e){var l=e++,u=t[l];n[u.uuid]=h,t[h]=u,n[c]=l,t[l]=s;for(var p=0,d=r;p!==d;++p){var f=i[p],m=f[l],g=f[h];f[h]=m,f[l]=g}}}this.nCachedObjects_=e},uncache:function(){for(var t=this._objects,e=t.length,n=this.nCachedObjects_,i=this._indicesByUUID,r=this._bindings,a=r.length,o=0,s=arguments.length;o!==s;++o){var c=arguments[o].uuid,h=i[c];if(void 0!==h)if(delete i[c],h0)for(var c=this._interpolants,h=this._propertyBindings,l=0,u=c.length;l!==u;++l)c[l].evaluate(o),h[l].accumulate(i,s)}else this._updateWeight(t)},_updateWeight:function(t){var e=0;if(this.enabled){e=this.weight;var n=this._weightInterpolant;if(null!==n){var i=n.evaluate(t)[0];e*=i,t>n.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=e,e},_updateTimeScale:function(t){var e=0;if(!this.paused){e=this.timeScale;var n=this._timeScaleInterpolant;if(null!==n)e*=n.evaluate(t)[0],t>n.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}return this._effectiveTimeScale=e,e},_updateTime:function(t){var e=this.time+t,n=this._clip.duration,i=this.loop,r=this._loopCount,a=2202===i;if(0===t)return-1===r?e:a&&1==(1&r)?n-e:e;if(2200===i){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(e>=n)e=n;else{if(!(e<0))break t;e=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this._mixer.dispatchEvent({type:"finished",action:this,direction:t<0?-1:1})}}else{if(-1===r&&(t>=0?(r=0,this._setEndings(!0,0===this.repetitions,a)):this._setEndings(0===this.repetitions,!0,a)),e>=n||e<0){var o=Math.floor(e/n);e-=n*o,r+=Math.abs(o);var s=this.repetitions-r;if(s<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,e=t>0?n:0,this._mixer.dispatchEvent({type:"finished",action:this,direction:t>0?1:-1});else{if(1===s){var c=t<0;this._setEndings(c,!c,a)}else this._setEndings(!1,!1,a);this._loopCount=r,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:o})}}if(a&&1==(1&r))return this.time=e,n-e}return this.time=e,e},_setEndings:function(t,e,n){var i=this._interpolantSettings;n?(i.endingStart=2401,i.endingEnd=2401):(i.endingStart=t?this.zeroSlopeAtStart?2401:le:2402,i.endingEnd=e?this.zeroSlopeAtEnd?2401:le:2402)},_scheduleFading:function(t,e,n){var i=this._mixer,r=i.time,a=this._weightInterpolant;null===a&&(a=i._lendControlInterpolant(),this._weightInterpolant=a);var o=a.parameterPositions,s=a.sampleValues;return o[0]=r,s[0]=e,o[1]=r+t,s[1]=n,this}}),ih.prototype=Object.assign(Object.create(i.prototype),{constructor:ih,_bindAction:function(t,e){var n=t._localRoot||this._root,i=t._clip.tracks,r=i.length,a=t._propertyBindings,o=t._interpolants,s=n.uuid,c=this._bindingsByRootAndName,h=c[s];void 0===h&&(h={},c[s]=h);for(var l=0;l!==r;++l){var u=i[l],p=u.name,d=h[p];if(void 0!==d)a[l]=d;else{if(void 0!==(d=a[l])){null===d._cacheIndex&&(++d.referenceCount,this._addInactiveBinding(d,s,p));continue}var f=e&&e._propertyBindings[l].binding.parsedPath;++(d=new Uc(eh.create(n,p,f),u.ValueTypeName,u.getValueSize())).referenceCount,this._addInactiveBinding(d,s,p),a[l]=d}o[l].resultBuffer=d.buffer}},_activateAction:function(t){if(!this._isActiveAction(t)){if(null===t._cacheIndex){var e=(t._localRoot||this._root).uuid,n=t._clip.uuid,i=this._actionsByClip[n];this._bindAction(t,i&&i.knownActions[0]),this._addInactiveAction(t,n,e)}for(var r=t._propertyBindings,a=0,o=r.length;a!==o;++a){var s=r[a];0==s.useCount++&&(this._lendBinding(s),s.saveOriginalState())}this._lendAction(t)}},_deactivateAction:function(t){if(this._isActiveAction(t)){for(var e=t._propertyBindings,n=0,i=e.length;n!==i;++n){var r=e[n];0==--r.useCount&&(r.restoreOriginalState(),this._takeBackBinding(r))}this._takeBackAction(t)}},_initMemoryManager:function(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;var t=this;this.stats={actions:{get total(){return t._actions.length},get inUse(){return t._nActiveActions}},bindings:{get total(){return t._bindings.length},get inUse(){return t._nActiveBindings}},controlInterpolants:{get total(){return t._controlInterpolants.length},get inUse(){return t._nActiveControlInterpolants}}}},_isActiveAction:function(t){var e=t._cacheIndex;return null!==e&&ethis.max.x||t.ythis.max.y)},containsBox:function(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y},getParameter:function(t,e){return void 0===e&&(console.warn("THREE.Box2: .getParameter() target is now required"),e=new Ee),e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))},intersectsBox:function(t){return!(t.max.xthis.max.x||t.max.ythis.max.y)},clampPoint:function(t,e){return void 0===e&&(console.warn("THREE.Box2: .clampPoint() target is now required"),e=new Ee),e.copy(t).clamp(this.min,this.max)},distanceToPoint:function(){var t=new Ee;return function(e){return t.copy(e).clamp(this.min,this.max).sub(e).length()}}(),intersect:function(t){return this.min.max(t.min),this.max.min(t.max),this},union:function(t){return this.min.min(t.min),this.max.max(t.max),this},translate:function(t){return this.min.add(t),this.max.add(t),this},equals:function(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}),Object.assign(uh.prototype,{set:function(t,e){return this.start.copy(t),this.end.copy(e),this},clone:function(){return(new this.constructor).copy(this)},copy:function(t){return this.start.copy(t.start),this.end.copy(t.end),this},getCenter:function(t){return void 0===t&&(console.warn("THREE.Line3: .getCenter() target is now required"),t=new Le),t.addVectors(this.start,this.end).multiplyScalar(.5)},delta:function(t){return void 0===t&&(console.warn("THREE.Line3: .delta() target is now required"),t=new Le),t.subVectors(this.end,this.start)},distanceSq:function(){return this.start.distanceToSquared(this.end)},distance:function(){return this.start.distanceTo(this.end)},at:function(t,e){return void 0===e&&(console.warn("THREE.Line3: .at() target is now required"),e=new Le),this.delta(e).multiplyScalar(t).add(this.start)},closestPointToPointParameter:(Yc=new Le,Jc=new Le,function(t,e){Yc.subVectors(t,this.start),Jc.subVectors(this.end,this.start);var n=Jc.dot(Jc),i=Jc.dot(Yc)/n;return e&&(i=Te.clamp(i,0,1)),i}),closestPointToPoint:function(t,e,n){var i=this.closestPointToPointParameter(t,e);return void 0===n&&(console.warn("THREE.Line3: .closestPointToPoint() target is now required"),n=new Le),this.delta(n).multiplyScalar(i).add(this.start)},applyMatrix4:function(t){return this.start.applyMatrix4(t),this.end.applyMatrix4(t),this},equals:function(t){return t.start.equals(this.start)&&t.end.equals(this.end)}}),ph.prototype=Object.create(Tn.prototype),ph.prototype.constructor=ph,ph.prototype.isImmediateRenderObject=!0,dh.prototype=Object.create(Ma.prototype),dh.prototype.constructor=dh,dh.prototype.update=function(){var t=new Le,e=new Le,n=new Pe;return function(){var i=["a","b","c"];this.object.updateMatrixWorld(!0),n.getNormalMatrix(this.object.matrixWorld);var r=this.object.matrixWorld,a=this.geometry.attributes.position,o=this.object.geometry;if(o&&o.isGeometry)for(var s=o.vertices,c=o.faces,h=0,l=0,u=c.length;l1&&t.multiplyScalar(1/e),this.children[0].material.color.copy(this.material.color)}},vh.prototype.dispose=function(){this.geometry.dispose(),this.material.dispose(),this.children[0].geometry.dispose(),this.children[0].material.dispose()},yh.prototype=Object.create(Tn.prototype),yh.prototype.constructor=yh,yh.prototype.dispose=function(){this.children[0].geometry.dispose(),this.children[0].material.dispose()},yh.prototype.update=function(){var t=new Le,e=new un,n=new un;return function(){var i=this.children[0];if(void 0!==this.color)this.material.color.set(this.color);else{var r=i.geometry.getAttribute("color");e.copy(this.light.color),n.copy(this.light.groundColor);for(var a=0,o=r.count;a.99999?this.quaternion.set(0,0,0,1):t.y<-.99999?this.quaternion.set(1,0,0,0):($c.set(t.z,0,-t.x).normalize(),Kc=Math.acos(t.y),this.quaternion.setFromAxisAngle($c,Kc))}),Ph.prototype.setLength=function(t,e,n){void 0===e&&(e=.2*t),void 0===n&&(n=.2*e),this.line.scale.set(1,Math.max(0,t-e),1),this.line.updateMatrix(),this.cone.scale.set(n,e,n),this.cone.position.y=t,this.cone.updateMatrix()},Ph.prototype.setColor=function(t){this.line.material.color.copy(t),this.cone.material.color.copy(t)},Ph.prototype.copy=function(t){return Tn.prototype.copy.call(this,t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this},Ph.prototype.clone=function(){return(new this.constructor).copy(this)},Rh.prototype=Object.create(Ma.prototype),Rh.prototype.constructor=Rh;function Ch(t){console.warn("THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead."),Ds.call(this,t),this.type="catmullrom"}Es.create=function(t,e){return console.log("THREE.Curve.create() has been deprecated"),t.prototype=Object.create(Es.prototype),t.prototype.constructor=t,t.prototype.getPoint=e,t},Object.assign(qs.prototype,{createPointsGeometry:function(t){console.warn("THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.");var e=this.getPoints(t);return this.createGeometry(e)},createSpacedPointsGeometry:function(t){console.warn("THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.");var e=this.getSpacedPoints(t);return this.createGeometry(e)},createGeometry:function(t){console.warn("THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.");for(var e=new Pn,n=0,i=t.length;n0},flags_are_same:function(t,e){return(this.cached_ints[0]&(t|e))==(t|e)||(this.cached_ints[0]&t)+(this.cached_ints[0]&e)==0},flags_are_on:function(t,e){return(this.cached_ints[0]&(t|e))==(t|e)},flags_are_off:function(t,e){return(this.cached_ints[0]&t)+(this.cached_ints[0]&e)==0},flags_are_either_on:function(t,e){return(this.cached_ints[0]&(t|e))>0}};let Ih=function(){};Ih.prototype={GLOBAL_DATA:[{id:1,created_at:1564399210,completed_at:1564413610,due_at:1564410610,iteration:0,iterations_needed:1,time_needed:null,description:"Reply to Recruiter email"},{id:2,created_at:1564399210,completed_at:1564413610,due_at:1564413610,iteration:0,iterations_needed:1,time_needed:null,description:"Pay AT&T Internet Bill"},{id:3,created_at:1564399210,completed_at:1564413610,due_at:1564434610,iteration:0,iterations_needed:1,time_needed:null,description:"Pay Dieken phone bill"}],__init__:function(){this.hud=document.getElementById("b"),this.context=this.hud.getContext("2d")},render:function(){let t;console.log("Rendered!"),this.context.clearRect(0,0,this.hud.width,this.hud.height),this.context.font="bold 64px Helvetica";let e=200;for(t=0;thandle($request); diff --git a/applications/asset_server/code_manager/public/quick_test.html b/applications/asset_server/code_manager/public/quick_test.html deleted file mode 100644 index 18cb600e8..000000000 --- a/applications/asset_server/code_manager/public/quick_test.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - NexusLocal - - - - - - - - - - - - - - diff --git a/applications/asset_server/code_manager/src/AppLibs/DoctrineProcess.php b/applications/asset_server/code_manager/src/AppLibs/DoctrineProcess.php new file mode 100644 index 000000000..554da7681 --- /dev/null +++ b/applications/asset_server/code_manager/src/AppLibs/DoctrineProcess.php @@ -0,0 +1,13 @@ +' . $code_builder->get_test_hi() . ''); - } - - public function run_unit_tests(KernelInterface $kernel) { - $content = UtilsProcess::run_qa_tests(); - return new Response($content); - } - -} - - - -/* -use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Output\BufferedOutput; - -public function test_response2(KernelInterface $kernel) { -$app = new Application($kernel); -$app->setAutoExit(false); - -$input = new ArrayInput([ - #'command' => 'bin/phpunit', - 'command' => 'list', -]); - - -$input = new ArrayInput([ - #'command' => 'bin/phpunit', - 'command' => 'phpunit', - // (optional) define the value of command arguments - '--log-junit' => null, - // (optional) pass options to the command - 'report.xml' => null, -]); - -// You can use NullOutput() if you don't need the output -$output = new BufferedOutput(); -$app->run($input, $output); - -// return the output, don't use if you used NullOutput() -$content = $output->fetch(); - - - -#var_dump($content); - -// return new Response(""), if you used NullOutput() -return new Response($content); - - -$content = ProcessUtilities::run_qa_tests(); -return new Response($content); -} -*/ \ No newline at end of file diff --git a/applications/asset_server/code_manager/src/Entity/Abstractions/AbstractEntity.php b/applications/asset_server/code_manager/src/Entity/Abstractions/AbstractEntity.php index 76594034d..18edcb1c7 100644 --- a/applications/asset_server/code_manager/src/Entity/Abstractions/AbstractEntity.php +++ b/applications/asset_server/code_manager/src/Entity/Abstractions/AbstractEntity.php @@ -2,7 +2,7 @@ namespace CodeManager\Entity\Abstractions; -use QuasarSource\SQL\Doctrine\Fields\EnumFields; +use QuasarSource\Doctrine\Fields\EnumFields; use QuasarSource\Utils\DataType\UtilsString as STR; use RuntimeException; use Doctrine\ORM\Mapping\Column; @@ -45,20 +45,30 @@ public function getID(): int { * @return mixed */ public function __call($name, $arguments) { - switch (STR::get_starts_with_match($name, EnumFields::MAGIC_METHODS)) { - case '': - throw new RuntimeException('Invalid function{' . $name . '} called to Entity!'); - case EnumFields::MAGIC_GET; - $func_name = 'get' . static::$func_aliases[STR::remove($name, EnumFields::MAGIC_GET)]; + $match = STR::get_starts_with_match($name, EnumFields::MAGIC_METHODS); + switch ($match) { + case EnumFields::MAGIC_GET: + case EnumFields::MAGIC_GET_ALT: + $func_name = 'get' . static::$func_aliases[STR::remove($name, $match)]; break; case EnumFields::MAGIC_SET: - $func_name = 'set' . static::$func_aliases[STR::remove($name, EnumFields::MAGIC_SET)]; + case EnumFields::MAGIC_SET_ALT: + $func_name = 'set' . static::$func_aliases[STR::remove($name, $match)]; break; + case '': default: - throw new RuntimeException('Invalid function{' . $name . '} called to Entity!'); + throw new RuntimeException('Invalid function{' . $name . '} called to Entity, default branch!'); + break; } - if ($arguments !== null && is_array($arguments) && count($arguments) !== 0) { - return $this->$func_name($arguments[0]); + if ($arguments !== null && is_array($arguments)) { + $num_args = count($arguments); + if ($num_args === 1) { + return $this->$func_name($arguments[0]); + } + if ($num_args === 0) { + return $this->$func_name(); + } + throw new RuntimeException('Invalid number of arguments (or not supported)'); } return $this->$func_name(); } diff --git a/applications/asset_server/code_manager/src/Entity/CodeManager/EntityCodeBuild.php b/applications/asset_server/code_manager/src/Entity/CodeManager/EntityCodeBuild.php index 8886c1b73..3e04c5fa1 100644 --- a/applications/asset_server/code_manager/src/Entity/CodeManager/EntityCodeBuild.php +++ b/applications/asset_server/code_manager/src/Entity/CodeManager/EntityCodeBuild.php @@ -6,12 +6,12 @@ use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\ManyToOne; use Doctrine\ORM\Mapping\Table; -use QuasarSource\SQL\Doctrine\Entity\Field\Boolean\TraitBool0; -use QuasarSource\SQL\Doctrine\Entity\Field\Number\Float\TraitFloat0; -use QuasarSource\SQL\Doctrine\Entity\Field\Number\Int\Small\TraitSmallInt0; -use QuasarSource\SQL\Doctrine\Entity\Field\Text\Blob\TraitBigText1; -use QuasarSource\SQL\Doctrine\Entity\Field\Time\TraitUnixTime0; -use QuasarSource\SQL\Doctrine\Fields\EnumFields as FIELD; +use QuasarSource\Doctrine\Entity\Field\Boolean\TraitBool0; +use QuasarSource\Doctrine\Entity\Field\Number\Float\TraitFloat0; +use QuasarSource\Doctrine\Entity\Field\Number\Int\Small\TraitSmallInt0; +use QuasarSource\Doctrine\Entity\Field\Text\Blob\TraitBigText1; +use QuasarSource\Doctrine\Entity\Field\Time\TraitUnixTime0; +use QuasarSource\Doctrine\Fields\EnumFields as FIELD; /** * Class EntityCodeBuild diff --git a/applications/asset_server/code_manager/src/Entity/CodeManager/EntityCodeProcedure.php b/applications/asset_server/code_manager/src/Entity/CodeManager/EntityCodeProcedure.php new file mode 100644 index 000000000..4cf0c8430 --- /dev/null +++ b/applications/asset_server/code_manager/src/Entity/CodeManager/EntityCodeProcedure.php @@ -0,0 +1,63 @@ + EnumFields::TEXT_0, + 'ExecuteRank' => EnumFields::SMALL_INT_0 + ]; + + /** + * Parent code project. + * + * @var EntityCodeProject + * @ManyToOne(targetEntity="CodeManager\Entity\CodeManager\EntityCodeProject", inversedBy="procedures") + * @JoinColumn(name="code_project_id", referencedColumnName="id") + */ + protected $code_project; + + /** + * @param EntityCodeProject|null $code_project + * @return EntityCodeProcedure + */ + public function setCodeProject(?EntityCodeProject $code_project): self { + $this->code_project = $code_project; + return $this; + } + + /** + * @return EntityCodeProject|null + */ + public function getCodeProject(): ?EntityCodeProject { + return $this->code_project; + } + +} diff --git a/applications/asset_server/code_manager/src/Entity/CodeManager/EntityCodeProject.php b/applications/asset_server/code_manager/src/Entity/CodeManager/EntityCodeProject.php new file mode 100644 index 000000000..e53de7d97 --- /dev/null +++ b/applications/asset_server/code_manager/src/Entity/CodeManager/EntityCodeProject.php @@ -0,0 +1,296 @@ + FIELD::TEXT_0, + 'StartURL' => FIELD::TEXT_1, + 'PathAssets' => FIELD::TEXT_2, + 'PathVar' => FIELD::TEXT_3, + 'PathOutput' => FIELD::TEXT_4, + 'Orientation' => FIELD::SMALL_INT_0, + 'Display' => FIELD::SMALL_INT_1, + 'ColorTheme' => FIELD::HEX_COLOR_0, + 'ColorBackground' => FIELD::HEX_COLOR_1 + ]; + + # TODO: https://developer.mozilla.org/en-US/docs/Web/Manifest/orientation + public const ORIENTATION_TO_STRING = ['landscape', 'portrait', 'dynamic', 'na']; + + /** @see https://developer.mozilla.org/en-US/docs/Web/Manifest/display */ + public const DISPLAY_TO_STRING = ['fullscreen', 'standalone', 'minimal-ui', 'browser']; + + /** @see https://github.com/w3c/manifest/wiki/Categories */ + public const CATEGORY_TO_STRING = [ + 'books', 'business', 'education', 'entertainment', 'finance', 'fitness', 'food', 'games', 'government', + 'health', 'kids', 'lifestyle', 'magazines', 'medical', 'music', 'navigation', 'news', 'personalization', + 'photo', 'politics', 'productivity', 'security', 'shopping', 'social', 'sports', 'travel', 'utilities', 'weather' + ]; + + /** @var $cached_categories */ + protected $cached_categories; + + /** + * @var string + * @Column(name="name_full", type="string", nullable=false, unique=true, length=128) + */ + protected $name_full; + + /** + * @var string + * @Column(name="name_short", type="string", nullable=false, unique=true, length=32) + */ + protected $name_short; + + /** + * Child code procedures. + * + * @var Collection $procedures + * @OneToMany(targetEntity="CodeManager\Entity\CodeManager\EntityCodeProcedure", mappedBy="code_project") + */ + protected $procedures; + + # --------------------------------------------------- M A G I C ---------------------------------------------------- + public function __construct() { + $this->procedures = new ArrayCollection(); + } + + public function __destruct() { + unset($this->cached_categories); + } + + /** + * @return string + */ + public function __toString(): string { + return 'Project{' . $this->getNameFull() . '}'; + } + + # -------------------------------------------------- P U B L I C --------------------------------------------------- + + private $cached_dir_output; + private $cached_dir_assets; + private $cached_dir_var; + + /** + * @param RepoDirectory $repo + * @return void + */ + public function cache_directories(RepoDirectory $repo): void { + $this->validate_path($this->getPathOutput()); + $this->validate_path($this->getPathVar()); + $this->validate_path($this->getPathAssets()); + } + + /** + * @param string $path + * @return void + */ + private function validate_path(string $path): void { + if (!DIR::create_if_dne_but_base_exists($path)) { + throw new RuntimeException('Project{' . $this->getNameFull() . '} could not validate or create path{' . $path . '}'); + } + } + + /** + * @param bool $as_string + * @return string|array + */ + public function get_web_manifest(bool $as_string) { + $json = [ + 'name' => $this->name_full, + 'short_name' => $this->name_short, + 'description' => $this->getDescription(), + 'categories' => $this->getCategoriesAsArray(), + 'lang' => 'en-US', + 'scope' => '', + 'display' => $this->getDisplayAsString(), + 'orientation' => $this->getOrientationAsString(), + 'theme_color' => $this->color_to_word($this->getColorTheme()), + 'background_color' => $this->color_to_word($this->getColorBackground()), + 'start_url' => $this->getStartURL() + ]; + if ($as_string) { + $json = JSON::to_pretty_json($json); + } + return $json; + } + + /** + * @return Collection + */ + public function getCodeProcedures(): Collection { + return $this->procedures; + } + + /** + * @param EntityCodeProcedure $code_procedure + * @return EntityCodeProject + */ + public function addCodeProcedure(EntityCodeProcedure $code_procedure): self { + if (!$this->procedures->contains($code_procedure)) { + $this->procedures[] = $code_procedure; + $code_procedure->setCodeProject($this); + } + return $this; + } + + /** + * @param EntityCodeProcedure $code_procedure + * @return EntityCodeProject + */ + public function removeCodeProcedure(EntityCodeProcedure $code_procedure): self { + if ($this->procedures->contains($code_procedure)) { + $this->procedures->removeElement($code_procedure); + if ($code_procedure->getCodeProject() === $this) { + $code_procedure->setCodeProject(null); + } + } + return $this; + } + + + /** + * @param string $categories + * @return EntityCodeProject + */ + public function setCategories(string $categories): self { + return $this->setBlob0($categories); + } + + /** + * @return string + */ + public function getCategories(): string { + return $this->getBlob0(); + } + + /** + * @return array + */ + public function getCategoriesAsArray(): array { + if ($this->cached_categories === null) { + $this->cached_categories = json_decode($this->getCategories(), true); + } + return $this->cached_categories; + } + + /** + * @return string + */ + public function getOrientationAsString(): string { + return self::ORIENTATION_TO_STRING[$this->smallint0]; + } + + /** + * @return string + */ + public function getDisplayAsString(): string { + return self::DISPLAY_TO_STRING[$this->smallint1]; + } + + /** + * @return string + */ + public function getNameFull(): string { + return $this->name_full; + } + + /** + * @param string $name_full + * @return EntityCodeProject + */ + public function setNameFull(string $name_full): self { + $this->name_full = $name_full; + return $this; + } + + /** + * @return string + */ + public function getNameShort(): string { + return $this->name_short; + } + + /** + * @param string $name_short + * @return EntityCodeProject + */ + public function setNameShort(string $name_short): self { + $this->name_short = $name_short; + return $this; + } + + /** + * @param string $color + * @return string + */ + private function color_to_word(string $color): string { + if ($color === '696969') { + return 'dimgray'; + } + if (strtolower($color) === '98fb98') { + return 'palegreen'; + } + throw new InvalidArgumentException('Color provided{' . $color . '} could not be converted into a word!'); + } + +} diff --git a/applications/asset_server/code_manager/src/Entity/CodeManager/EntityNPMLib.php b/applications/asset_server/code_manager/src/Entity/CodeManager/EntityNPMLib.php index 4547e59ea..6dbcd534d 100644 --- a/applications/asset_server/code_manager/src/Entity/CodeManager/EntityNPMLib.php +++ b/applications/asset_server/code_manager/src/Entity/CodeManager/EntityNPMLib.php @@ -3,12 +3,12 @@ namespace CodeManager\Entity\CodeManager; use CodeManager\Entity\Abstractions\AbstractEntity; -use CodeManager\Entity\Abstractions\Traits\Text\FieldTextThree; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; use QuasarSource\DataStructure\CacheTable\CacheTableInterface; use QuasarSource\DataStructure\CacheTable\TraitCacheTable; -use QuasarSource\SQL\Doctrine\Entity\Field\Time\TraitUnixTime0; +use QuasarSource\Doctrine\Entity\Field\Text\TraitText2; +use QuasarSource\Doctrine\Entity\Field\Time\TraitUnixTime0; use QuasarSource\Utils\File\UtilsPath as PATH; use QuasarSource\Utils\Process\UtilsProcess as RUN; @@ -22,7 +22,7 @@ class EntityNPMLib extends AbstractEntity implements CacheTableInterface { use TraitCacheTable; // Name, VersionLatest, VersionLocal. - use FieldTextThree; + use TraitText2; // Represents the last time it was checked. use TraitUnixTime0; @@ -41,8 +41,6 @@ public function cache_calculate(string $key) { public function cache_needs_inspection() : bool { $last_checked = $this->getUnixTimestamp(); var_dump('Last checked is {' . $last_checked . '}'); - - #if (DATE::is_different_day($last_checked, DATE::now())) { # $this->setLastChecked(TIME::now()); # return true; @@ -68,14 +66,14 @@ public function cache_update(bool $update_state=true): void { } public function on_event_born($data): void { - $latest_version = RUN::get_npm_lib_latest_version($data); - PATH::cwd_push(\CodeManager\Enum\ProjectParameterKeys\Path::DIRECTORY_NODE); - $current_version = RUN::get_npm_lib_version_local($data); - PATH::cwd_pop(); - $this->setName($data); - $this->setVersionLocal($current_version); - $this->setVersionLatest($latest_version); - $this->cache_update(false); + #$latest_version = RUN::get_npm_lib_latest_version($data); + #PATH::cwd_push(\CodeManager\Enum\ProjectParameterKeys\Path::DIRECTORY_NODE); + #$current_version = RUN::get_npm_lib_version_local($data); + #PATH::cwd_pop(); + #$this->setName($data); + #$this->setVersionLocal($current_version); + #$this->setVersionLatest($latest_version); + #$this->cache_update(false); } } diff --git a/applications/asset_server/code_manager/src/Entity/CodeManager/EntitySnapshotDB.php b/applications/asset_server/code_manager/src/Entity/CodeManager/EntitySnapshotDB.php index d48c727b6..1597b16c9 100644 --- a/applications/asset_server/code_manager/src/Entity/CodeManager/EntitySnapshotDB.php +++ b/applications/asset_server/code_manager/src/Entity/CodeManager/EntitySnapshotDB.php @@ -5,12 +5,12 @@ use CodeManager\Entity\Abstractions\AbstractEntity; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; -use QuasarSource\SQL\Doctrine\Entity\Field\Boolean\TraitBool0; -use QuasarSource\SQL\Doctrine\Entity\Field\Number\Int\Byte\TraitSizeInBytes; -use QuasarSource\SQL\Doctrine\Entity\Field\Number\Int\Small\TraitSmallInt1; -use QuasarSource\SQL\Doctrine\Entity\Field\Text\Blob\TraitBigText2; -use QuasarSource\SQL\Doctrine\Entity\Field\Time\TraitUnixTime0; -use QuasarSource\SQL\Doctrine\Fields\EnumFields as FIELD; +use QuasarSource\Doctrine\Entity\Field\Boolean\TraitBool0; +use QuasarSource\Doctrine\Entity\Field\Number\Int\Byte\TraitSizeInBytes; +use QuasarSource\Doctrine\Entity\Field\Number\Int\Small\TraitSmallInt1; +use QuasarSource\Doctrine\Entity\Field\Text\Blob\TraitBigText2; +use QuasarSource\Doctrine\Entity\Field\Time\TraitUnixTime0; +use QuasarSource\Doctrine\Fields\EnumFields as FIELD; /** * Class EntityDBSnapshot diff --git a/applications/asset_server/code_manager/src/Entity/CodeManager/EntitySnapshotQA.php b/applications/asset_server/code_manager/src/Entity/CodeManager/EntitySnapshotQA.php index fcb90fa12..7c467fc79 100644 --- a/applications/asset_server/code_manager/src/Entity/CodeManager/EntitySnapshotQA.php +++ b/applications/asset_server/code_manager/src/Entity/CodeManager/EntitySnapshotQA.php @@ -5,14 +5,14 @@ use CodeManager\Entity\Abstractions\AbstractEntity; use CodeManager\Entity\Abstractions\Traits\Number\Whole\FieldIntFour; use CodeManager\Entity\Abstractions\Traits\Relations\FieldEntityPointer; -use CodeManager\Entity\Abstractions\Traits\Text\FieldText; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; use QuasarSource\DataStructure\CacheTable\CacheTableInterface; use QuasarSource\DataStructure\CacheTable\TraitCacheTable; +use QuasarSource\Doctrine\Entity\Field\Text\TraitText0; use QuasarSource\QualityAssurance\ProjectTestSuiteResult; -use QuasarSource\SQL\Doctrine\Entity\Field\Number\Float\TraitFloat0; -use QuasarSource\SQL\Doctrine\Entity\Field\Time\TraitUnixTime0; +use QuasarSource\Doctrine\Entity\Field\Number\Float\TraitFloat0; +use QuasarSource\Doctrine\Entity\Field\Time\TraitUnixTime0; /** * Class EntityDirectory @@ -31,7 +31,7 @@ class EntitySnapshotQA extends AbstractEntity implements CacheTableInterface { // Num unit-tests failed, errored, skipped, overall. use FieldIntFour; // Raw output of QA run. - use FieldText; + use TraitText0; // A pointer to the EntityFile (the reference to the physical file containing the QA report). use FieldEntityPointer; @@ -55,7 +55,7 @@ public function cache_needs_update(bool $trigger_update): bool { */ public function cache_calculate(string $key) { if ($key === self::CACHE_KEY_QA_TEST_SUITE) { - return new ProjectTestSuiteResult($this->entity_file->getFullPath()); + return new ProjectTestSuiteResult($this->entity_file->getPath()); } return null; } diff --git a/applications/asset_server/code_manager/src/Entity/CodeManager/File/EntityFile.php b/applications/asset_server/code_manager/src/Entity/CodeManager/File/EntityFile.php deleted file mode 100644 index f49cf6e1b..000000000 --- a/applications/asset_server/code_manager/src/Entity/CodeManager/File/EntityFile.php +++ /dev/null @@ -1,297 +0,0 @@ - FIELD::SMALL_INT_0, - 'content' => FIELD::BIG_TEXT_0, - 'cache_last_updated' => FIELD::UNIX_TIME_0 - ]; - - public const TYPE_NO_MATCH = -1; - public const TYPE_CSS = 1; - public const TYPE_XML = 2; - public const TYPE_HTML = 3; - public const TYPE_JSON = 4; - public const TYPE_SHADER_VERTEX = 5; - public const TYPE_SHADER_FRAGMENT = 6; - public const TYPE_WEB_MANIFEST = 7; - public const TYPE_LICENSE = 8; - public const TYPE_READ_ME = 9; - public const TYPE_YAML = 10; - - public const EXTENSION_TO_TYPE = [ - EXTENSION::CSS => self::TYPE_CSS, - EXTENSION::XML => self::TYPE_XML, - EXTENSION::HTML => self::TYPE_HTML, - EXTENSION::JSON => self::TYPE_JSON, - EXTENSION::SHADER_VERTEX => self::TYPE_SHADER_VERTEX, - EXTENSION::SHADER_FRAGMENT => self::TYPE_SHADER_FRAGMENT, - EXTENSION::WEB_MANIFEST => self::TYPE_WEB_MANIFEST, - EXTENSION::YAML => self::TYPE_YAML - ]; - - /** - * Parent directory. - * - * @ManyToOne(targetEntity="CodeManager\Entity\CodeManager\File\EntityDirectory", inversedBy="files") - * @JoinColumn(name="directory_id", referencedColumnName="id") - */ - private $directory; - - /** - * Parent EntityFile. - * - * @var EntityFile - * @OneToOne(targetEntity="CodeManager\Entity\CodeManager\File\EntityFile", mappedBy="child") - * @JoinColumn(name="child_id", referencedColumnName="id") - */ - private $parent; - - /** - * Child EntityFile. - * - * @var EntityFile - * @OneToOne(targetEntity="CodeManager\Entity\CodeManager\File\EntityFile", inversedBy="parent") - * @JoinColumn(name="parent_id", referencedColumnName="id") - */ - private $child; - - /** - * @var EntityFileType - * - * @ManyToOne(targetEntity="CodeManager\Entity\CodeManager\File\EntityFileType", inversedBy="entity_files") - * @JoinColumn(name="file_type_id", referencedColumnName="id") - */ - private $file_type; - - public function __destruct() { - $this->trait_destruct_full_path(); - } - - /** - * @return bool - */ - public function has_sha512sum_changed(): bool { - return $this->get_cached_latest_sha512sum() !== $this->getSHA512Sum(); - } - - /** - * @return EntityFileType - */ - public function getFileType(): EntityFileType { - return $this->file_type; - } - - /** - * @return string - */ - public function getFileTypeString(): string { - return $this->file_type->getAsString(); - } - - /** - * @param EntityFileType $entity - * @return EntityFile - */ - public function setFileType(EntityFileType $entity): self { - $this->file_type = $entity; - return $this; - } - - /** - * @return EntityDirectory - */ - public function getDirectory(): EntityDirectory { - return $this->directory; - } - - /** - * @param $directory - * @return self - */ - public function setDirectory(EntityDirectory $directory): self { - $this->directory = $directory; - return $this; - } - - public function getFullName(): string { - return $this->name . $this->extension; - } - - /** - * @return EntityFile|null - */ - public function getParent(): ?EntityFile { - return $this->parent; - } - - /** - * @return bool - */ - public function hasParent(): bool { - return $this->parent !== null; - } - - /** - * @param EntityFile $parent - * @return self - */ - public function setParent(EntityFile $parent): self { - $this->parent = $parent; - $this->set_rank($parent->get_rank() + 1); - return $this; - } - - /** - * @return mixed - */ - public function getChild() { - return $this->child; - } - - public function get_child_recursively() : EntityFile { - if ($this->child === null) { - return $this; - } - return $this->child->get_child_recursively(); - } - - /** - * @return bool - */ - public function hasChild(): bool { - return $this->child !== null; - } - - /** - * @param mixed $child - * @return self - */ - public function setChild($child): self { - $this->child = $child; - $this->child->set_rank($this->get_rank() + 1); - return $this; - } - - public function remove_child(): void { - $this->child = null; - } - - public function to_full_string(?EntityFile $relative_to=null) : string { - $info = ' --------- EntityFile{' . $this->getName() . $this->getExtension() . '}:' . PHP_EOL; - $info .= "\tpath{" . $this->getFullPath() . '}' . PHP_EOL; - if ($relative_to !== null) { - $base = $this->getSizeInBytes(); - $new = $relative_to->getSizeInBytes(); - $dif = MATH::percentage_decreased($base, $new, true); - $info .= "\tsize{" . $base . '} to {' . $new . '}, reduction of(' . $dif . ')' . PHP_EOL; - } else { - $info .= "\tsize{" . $this->getSizeInBytes() . '}' . PHP_EOL; - } - if ($this->hasParent()) { - $info .= "\tparent{" . $this->getParent()->getFullName() . '}' . PHP_EOL; - } - if ($this->hasChild()) { - $info .= "\tchild{" . $this->getChild()->getFullName() . '}' . PHP_EOL; - } - $info .= '------------------------------------------------------------------------' . PHP_EOL; - return $info; - } - - public function __toString() { - return 'EntityFile{' . $this->getFullPath() . '}'; - } - - // ------ U T I L I T Y ------ - - public function get_full_name_minified() : string { - return $this->name . EXTENSION::MINIFIED . $this->extension; - } - - public function get_full_name_processed() : string { - return $this->name . '.processed' . $this->extension; - } - - public function get_full_name_gzipped() : string { - return $this->getFullName() . EXTENSION::GZIPPED; - } - - // ---- - - public function sync(): void { - var_dump('Syncing entity file{' . $this->getFullPath() . '}'); - $this->calculate_size(); - $this->calculate_sha512sum(); - $this->set_cache_last_updated(-1); - } - - // ----------------------------------------------- C A L C U L A T E ----------------------------------------------- - - /** - * @return EntityFile - */ - public function calculate_size(): self { - return $this->setSizeInBytes(UFO::get_size($this->getFullPath())); - } - - /** - * @return EntityFile - */ - public function calculate_sha512sum(): self { - return $this->setSHA512Sum($this->get_cached_latest_sha512sum()); - } - - /** - * @return string - */ - protected function get_cached_latest_sha512sum(): string { - if ($this->latest_sha512sum_to_update_to === null) { - $this->latest_sha512sum_to_update_to = UFO::get_sha512sum($this->getFullPath()); - } - return $this->latest_sha512sum_to_update_to; - } -} diff --git a/applications/asset_server/code_manager/src/Entity/CodeManager/File/EntityDirectory.php b/applications/asset_server/code_manager/src/Entity/File/EntityDirectory.php similarity index 69% rename from applications/asset_server/code_manager/src/Entity/CodeManager/File/EntityDirectory.php rename to applications/asset_server/code_manager/src/Entity/File/EntityDirectory.php index 7f3286fb3..fc6023b1d 100644 --- a/applications/asset_server/code_manager/src/Entity/CodeManager/File/EntityDirectory.php +++ b/applications/asset_server/code_manager/src/Entity/File/EntityDirectory.php @@ -1,6 +1,6 @@ FIELD::SMALL_INT_0 ]; + /** + * @param string|null $path + * @return EntityDirectory + */ + public static function spawn(string $path=null): EntityDirectory { + $directory = new EntityDirectory(); + if ($path !== null) { + $directory->setPath($path)->set_cache_last_updated(-1); + } + return $directory; + } + /** * Child files. * * @var Collection $files - * @OneToMany(targetEntity="CodeManager\Entity\CodeManager\File\EntityFile", mappedBy="directory") + * @OneToMany(targetEntity="CodeManager\Entity\File\EntityFile", mappedBy="directory") */ private $files; @@ -61,7 +74,7 @@ class EntityDirectory extends AbstractEntity { * Child directories. * * @var Collection $directories - * @OneToMany(targetEntity="CodeManager\Entity\CodeManager\File\EntityDirectory", mappedBy="directory") + * @OneToMany(targetEntity="CodeManager\Entity\File\EntityDirectory", mappedBy="directory") */ private $directories; @@ -69,7 +82,7 @@ class EntityDirectory extends AbstractEntity { * Parent directory. * * @var EntityDirectory $directory - * @ManyToOne(targetEntity="CodeManager\Entity\CodeManager\File\EntityDirectory", inversedBy="directories") + * @ManyToOne(targetEntity="CodeManager\Entity\File\EntityDirectory", inversedBy="directories") * @JoinColumn(name="directory_id", referencedColumnName="id") */ private $directory; @@ -88,7 +101,7 @@ public function get_all_paths(): array { $files = []; $dirs = []; $all_paths = []; - DIR::get_all_contents($this->getFullPath(), false, $files, $dirs); + DIR::get_all_contents($this->getPath(), false, $files, $dirs); ARY::ref_append_both($all_paths, $files, $dirs); return $all_paths; } @@ -100,6 +113,21 @@ public function getFiles(): Collection { return $this->files; } + /** + * @param string $extension_name + * @return array + */ + public function get_files_with_extension_name(string $extension_name): array { + $matches = []; + /** @var EntityFile $file */ + foreach ($this->files as $file) { + if ($file->getFileType()->getAsString() === $extension_name) { + $matches[] = $file; + } + } + return $matches; + } + /** * @param EntityFile $file * @return EntityDirectory diff --git a/applications/asset_server/code_manager/src/Entity/File/EntityFile.php b/applications/asset_server/code_manager/src/Entity/File/EntityFile.php new file mode 100644 index 000000000..9282731be --- /dev/null +++ b/applications/asset_server/code_manager/src/Entity/File/EntityFile.php @@ -0,0 +1,287 @@ + FIELD::SMALL_INT_0, + 'content' => FIELD::BIG_TEXT_0, + 'cache_last_updated' => FIELD::UNIX_TIME_0 + ]; + + /** + * @param string|null $path + * @param EntityDirectory|null $directory + * @param EntityFile|null $parent + * @return EntityFile + */ + public static function spawn(string $path=null, EntityDirectory $directory=null, EntityFile $parent=null): EntityFile { + $file = (new self())->setPath($path); + if ($directory !== null) { + $directory->addFile($file); + $file->setDirectory($directory); + } + if ($path !== null) { + $file->sync(); + } + if ($parent !== null) { + $parent->setChild($file); + // Just to be safe. + $file->setParent($parent); + $file->set_rank($parent->get_rank()); + } else { + $file->set_rank(0); + } + return $file; + } + + /** @var array $cached_file_contents */ + private $cached_file_contents; + + /** + * Parent directory. + * + * @ManyToOne(targetEntity="CodeManager\Entity\File\EntityDirectory", inversedBy="files") + * @JoinColumn(name="directory_id", referencedColumnName="id") + */ + private $directory; + + /** + * Parent EntityFile. + * + * @var EntityFile + * @OneToOne(targetEntity="CodeManager\Entity\File\EntityFile", mappedBy="child") + * @JoinColumn(name="child_id", referencedColumnName="id") + */ + private $parent; + + /** + * Child EntityFile. + * + * @var EntityFile + * @OneToOne(targetEntity="CodeManager\Entity\File\EntityFile", inversedBy="parent") + * @JoinColumn(name="parent_id", referencedColumnName="id") + */ + private $child; + + /** + * @var EntityFileType + * + * @ManyToOne(targetEntity="CodeManager\Entity\File\EntityFileType", inversedBy="entity_files") + * @JoinColumn(name="file_type_id", referencedColumnName="id") + */ + private $file_type; + + # --------------------------------------------------- M A G I C ---------------------------------------------------- + public function __destruct() { + unset($this->cached_file_contents); + $this->trait_destruct_path(); + $this->trait_destruct_sha512sum(); + } + + /** + * @return string + */ + public function __toString(): string { + return $this->getPath(); #'EntityFile{' . $this->getPath() . '}'; + } + # -------------------------------------------------- P U B L I C --------------------------------------------------- + + /** + * @return bool + */ + public function sync(): bool { + $f0 = $this->syncSHA512Sum($this->get_cached_latest_sha512sum()); + $f1 = $this->syncSizeInBytes(UFO::get_size($this->getPath())); + if ($f0 || $f1) { + $this->set_cache_last_updated(-1); + return true; + } + return false; + } + + /** + * @param EntityFileType $file_type + * @return string + */ + public function get_name_as_type(EntityFileType $file_type): string { + return STR::replace( + $this->get_file_name(true), $this->get_file_extensions(), $file_type->getAsString() + ); + } + + # ------------------------------------------------- G E T T E R S -------------------------------------------------- + + /** + * @param bool $as_string + * @return array|string + */ + public function get_contents(bool $as_string=false) { + if ($this->cached_file_contents === null) { + $this->cached_file_contents = UFO::get($this->getPath(), $as_string); + } + return $this->cached_file_contents; + } + + /** + * @return bool + */ + public function has_sha512sum_changed(): bool { + return $this->get_cached_latest_sha512sum() !== $this->getSHA512Sum(); + } + + /** + * @return bool + */ + public function hasParent(): bool { + return $this->parent !== null; + } + + /** + * @return bool + */ + public function hasChild(): bool { + return $this->child !== null; + } + + /** + * @return EntityDirectory + */ + public function getDirectory(): EntityDirectory { + return $this->directory; + } + + /** + * @return EntityFileType + */ + public function getFileType(): EntityFileType { + return $this->file_type; + } + + /** + * @return int + */ + public function getFileTypeGroup(): int { + return $this->file_type->getEntityType(); + } + + /** + * @return string + */ + public function getFileTypeString(): string { + return $this->file_type->getAsString(); + } + + /** + * @return EntityFile|null + */ + public function getParent(): ?EntityFile { + return $this->parent; + } + + /** + * @return EntityFile|null + */ + public function getChild(): ?EntityFile { + return $this->child; + } + + # ------------------------------------------------- S E T T E R S -------------------------------------------------- + + /** + * @param EntityFile $parent + * @return self + */ + public function setParent(EntityFile $parent): self { + $this->parent = $parent; + $this->set_rank($this->parent->get_rank() + 1); + if (!$this->parent->hasChild()) { + $this->parent->setChild($this); + } + return $this; + } + + /** + * @param EntityFile $child + * @return self + */ + public function setChild(EntityFile $child): self { + $this->child = $child; + $this->child->set_rank($this->get_rank() - 1); + if (!$this->child->hasParent()) { + $this->child->setParent($this); + } + return $this; + } + + /** + * @param EntityFileType $file_type + * @return EntityFile + */ + public function setFileType(EntityFileType $file_type): self { + $this->file_type = $file_type; + $file_type->add_entity_file($this); + return $this; + } + + /** + * @param $directory + * @return self + */ + public function setDirectory(EntityDirectory $directory): self { + $this->directory = $directory; + return $this; + } + + # ----------------------------------------------- C A L C U L A T E ------------------------------------------------ + /** + * @return string + */ + protected function get_cached_latest_sha512sum(): string { + if ($this->latest_sha512sum_to_update_to === null) { + $this->latest_sha512sum_to_update_to = UFO::get_sha512sum($this->getPath()); + } + return $this->latest_sha512sum_to_update_to; + } +} diff --git a/applications/asset_server/code_manager/src/Entity/CodeManager/File/EntityFileType.php b/applications/asset_server/code_manager/src/Entity/File/EntityFileType.php similarity index 63% rename from applications/asset_server/code_manager/src/Entity/CodeManager/File/EntityFileType.php rename to applications/asset_server/code_manager/src/Entity/File/EntityFileType.php index 65d18fab0..8e8a2c63d 100644 --- a/applications/asset_server/code_manager/src/Entity/CodeManager/File/EntityFileType.php +++ b/applications/asset_server/code_manager/src/Entity/File/EntityFileType.php @@ -1,6 +1,6 @@ getAsString(); + } + + /** + * @param EntityFile $file + * @return EntityFileType + */ + public function add_entity_file(EntityFile $file): self { + if (!$this->entity_files->contains($file)) { + $this->entity_files->add($file); + } + return $this; + } + + /** + * @return bool */ - public function mark_entity_file(EntityFile $file): void { - $this->entity_files->add($file); - $file->setFileType($this); + public function can_be_minified(): bool { + return $this->entity_type === self::TYPE_CSS || $this->entity_type === self::TYPE_HTML; } /** diff --git a/applications/asset_server/code_manager/src/Entity/Finance/Binance/EntityBinanceBalance.php b/applications/asset_server/code_manager/src/Entity/Finance/Binance/EntityBinanceBalance.php index 76ba5655f..d7a993ad4 100644 --- a/applications/asset_server/code_manager/src/Entity/Finance/Binance/EntityBinanceBalance.php +++ b/applications/asset_server/code_manager/src/Entity/Finance/Binance/EntityBinanceBalance.php @@ -3,10 +3,10 @@ namespace CodeManager\Entity\Finance\Binance; use CodeManager\Entity\Abstractions\AbstractEntity; -use CodeManager\Entity\Abstractions\Traits\Text\FieldText; +use QuasarSource\Doctrine\Entity\Field\Text\TraitText0; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; -use QuasarSource\SQL\Doctrine\Entity\Field\Time\TraitUnixTime0; +use QuasarSource\Doctrine\Entity\Field\Time\TraitUnixTime0; /** @@ -18,7 +18,7 @@ */ class EntityBinanceBalance extends AbstractEntity { // JSON data containing balances of all coins greater than zero. - use FieldText; + use TraitText0; // The time instance that the balance was checked at. use TraitUnixTime0; diff --git a/applications/asset_server/code_manager/src/Entity/Finance/Binance/EntityBinanceOrder.php b/applications/asset_server/code_manager/src/Entity/Finance/Binance/EntityBinanceOrder.php index 4a6d636fd..72631adf0 100644 --- a/applications/asset_server/code_manager/src/Entity/Finance/Binance/EntityBinanceOrder.php +++ b/applications/asset_server/code_manager/src/Entity/Finance/Binance/EntityBinanceOrder.php @@ -3,7 +3,7 @@ namespace CodeManager\Entity\Finance\Binance; use CodeManager\Entity\Abstractions\AbstractEntity; -use CodeManager\Entity\Abstractions\Traits\Text\FieldText; +use QuasarSource\Doctrine\Entity\Field\Text\TraitText0; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; @@ -16,7 +16,7 @@ */ class EntityBinanceOrder extends AbstractEntity { // Represents the coin trade pair ex: {BATBTC} which is BAT to BTC. - use FieldText; + use TraitText0; /** @var string $db_table_name */ public static $db_table_name = 'binance_order'; diff --git a/applications/asset_server/code_manager/src/Entity/Finance/Binance/EntityBinanceTrade.php b/applications/asset_server/code_manager/src/Entity/Finance/Binance/EntityBinanceTrade.php index 81cc74102..f8eb331d0 100644 --- a/applications/asset_server/code_manager/src/Entity/Finance/Binance/EntityBinanceTrade.php +++ b/applications/asset_server/code_manager/src/Entity/Finance/Binance/EntityBinanceTrade.php @@ -4,7 +4,7 @@ use CodeManager\Entity\Abstractions\AbstractEntity; use CodeManager\Entity\Abstractions\Traits\Relations\FieldEntityPointer; -use CodeManager\Entity\Abstractions\Traits\Text\FieldText; +use QuasarSource\Doctrine\Entity\Field\Text\TraitText0; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; @@ -17,7 +17,7 @@ */ class EntityBinanceTrade extends AbstractEntity { // Represents the coin trade pair ex: {BATBTC} which is BAT to BTC. - use FieldText; + use TraitText0; // A pointer to the parent EntityBinanceOrder. use FieldEntityPointer; diff --git a/applications/asset_server/code_manager/src/Entity/Finance/EntityAssetFlow.php b/applications/asset_server/code_manager/src/Entity/Finance/EntityAssetFlow.php index 1dc2dc8a3..cba8189ed 100644 --- a/applications/asset_server/code_manager/src/Entity/Finance/EntityAssetFlow.php +++ b/applications/asset_server/code_manager/src/Entity/Finance/EntityAssetFlow.php @@ -5,12 +5,12 @@ use CodeManager\Entity\Abstractions\AbstractEntity; use CodeManager\Entity\Abstractions\Traits\Number\Whole\FieldIntTwo; use CodeManager\Entity\Abstractions\Traits\Relations\FieldEntityPointerTwo; -use CodeManager\Entity\Abstractions\Traits\Text\FieldText; +use QuasarSource\Doctrine\Entity\Field\Text\TraitText0; use CodeManager\Entity\Users\EntityEntity; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; use QuasarSource\Finance\UtilsFinance; -use QuasarSource\SQL\Doctrine\Entity\Field\Time\TraitUnixTime0; +use QuasarSource\Doctrine\Entity\Field\Time\TraitUnixTime0; use QuasarSource\Utils\Time\UtilsUnixTime as TIME; /** @@ -22,7 +22,7 @@ */ class EntityAssetFlow extends AbstractEntity { // Description - use FieldText; + use TraitText0; // Type, Amount. use FieldIntTwo; // A pointer from Entity and pointer to Entity. diff --git a/applications/asset_server/code_manager/src/Entity/Finance/EntityAssetFlowCategory.php b/applications/asset_server/code_manager/src/Entity/Finance/EntityAssetFlowCategory.php index 39038ea75..7e639dbce 100644 --- a/applications/asset_server/code_manager/src/Entity/Finance/EntityAssetFlowCategory.php +++ b/applications/asset_server/code_manager/src/Entity/Finance/EntityAssetFlowCategory.php @@ -3,7 +3,7 @@ namespace CodeManager\Entity\Finance; use CodeManager\Entity\Abstractions\AbstractEntity; -use CodeManager\Entity\Abstractions\Traits\Text\FieldText; +use QuasarSource\Doctrine\Entity\Field\Text\TraitText0; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; @@ -11,15 +11,12 @@ * Class EntityAssetFlowCategory * @package CodeManager\Entity\Finance * - * @Entity( - * repositoryClass="CodeManager\Repository\Finance\RepoAssetFlowCategory", - * readOnly=true - * ) + * @Entity(repositoryClass="CodeManager\Repository\Finance\RepoAssetFlowCategory", readOnly=true) * @Table(name="asset_flow_category") */ class EntityAssetFlowCategory extends AbstractEntity { // Description - use FieldText; + use TraitText0; /** @var string $db_table_name */ public static $db_table_name = 'asset_flow_category'; diff --git a/applications/asset_server/code_manager/src/Entity/Finance/EntityAssetFlowType.php b/applications/asset_server/code_manager/src/Entity/Finance/EntityAssetFlowType.php index ede419520..eeb1dbdb4 100644 --- a/applications/asset_server/code_manager/src/Entity/Finance/EntityAssetFlowType.php +++ b/applications/asset_server/code_manager/src/Entity/Finance/EntityAssetFlowType.php @@ -4,7 +4,7 @@ use CodeManager\Entity\Abstractions\AbstractEntity; use CodeManager\Entity\Abstractions\Traits\Relations\FieldEntityPointer; -use CodeManager\Entity\Abstractions\Traits\Text\FieldText; +use QuasarSource\Doctrine\Entity\Field\Text\TraitText0; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; @@ -17,7 +17,7 @@ */ class EntityAssetFlowType extends AbstractEntity { // Description - use FieldText; + use TraitText0; // Optional: Category use FieldEntityPointer; diff --git a/applications/asset_server/code_manager/src/Entity/Task/EntityMeeseeksTask.php b/applications/asset_server/code_manager/src/Entity/Task/EntityMeeseeksTask.php new file mode 100644 index 000000000..f1dc97a93 --- /dev/null +++ b/applications/asset_server/code_manager/src/Entity/Task/EntityMeeseeksTask.php @@ -0,0 +1,86 @@ + FIELD::UNIX_TIME_0, + 'due_at' => FIELD::UNIX_TIME_1, + 'completed_at' => FIELD::UNIX_TIME_2, + 'iteration' => FIELD::SMALL_INT_0, + 'iterations_needed' => FIELD::SMALL_INT_1, + 'time_needed' => FIELD::FLOAT_0 + ]; + + /** + * @param string $description + * @return EntityMeeseeksTask + */ + public static function spawn(string $description): EntityMeeseeksTask { + return (new self())->set_created_at(-1)->setText0($description); + } + + /** + * @param int $num_seconds + * @return EntityMeeseeksTask + */ + public function set_to_due_in_delta_time(int $num_seconds): self { + return $this->set_due_at($this->get_created_at() + $num_seconds); + } + + /** + * @return array + */ + public function as_array(): array { + return [ + 'id' => $this->getID(), + 'created_at' => $this->get_created_at(), + 'completed_at' => $this->get_completed_at(), + 'due_at' => $this->get_due_at(), + 'iteration' => $this->get_iteration(), + 'iterations_needed' => $this->get_iterations_needed(), + 'time_needed' => $this->get_time_needed(), + 'description' => $this->getText0() + ]; + } +} diff --git a/applications/asset_server/code_manager/src/Entity/Users/EntityEntity.php b/applications/asset_server/code_manager/src/Entity/Users/EntityEntity.php index b4400c62d..9172d1efa 100644 --- a/applications/asset_server/code_manager/src/Entity/Users/EntityEntity.php +++ b/applications/asset_server/code_manager/src/Entity/Users/EntityEntity.php @@ -4,10 +4,10 @@ use CodeManager\Entity\Abstractions\AbstractEntity; use CodeManager\Entity\Abstractions\Traits\Relations\FieldEntityPointer; -use CodeManager\Entity\Abstractions\Traits\Text\FieldTextThree; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; -use QuasarSource\SQL\Doctrine\Entity\Field\Time\TraitUnixTime1; +use QuasarSource\Doctrine\Entity\Field\Text\TraitText2; +use QuasarSource\Doctrine\Entity\Field\Time\TraitUnixTime1; /** * Class EntityEntity @@ -18,7 +18,7 @@ */ class EntityEntity extends AbstractEntity { // Username, Password, Email. - use FieldTextThree; + use TraitText2; // The time instance that this account was created at and last logged in at. use TraitUnixTime1; // A pointer to the EntityUserRole. diff --git a/applications/asset_server/code_manager/src/Entity/Users/EntityEntityEntityAlias.php b/applications/asset_server/code_manager/src/Entity/Users/EntityEntityEntityAlias.php index 9707b2456..22c5d6ed4 100644 --- a/applications/asset_server/code_manager/src/Entity/Users/EntityEntityEntityAlias.php +++ b/applications/asset_server/code_manager/src/Entity/Users/EntityEntityEntityAlias.php @@ -4,10 +4,10 @@ use CodeManager\Entity\Abstractions\AbstractEntity; use CodeManager\Entity\Abstractions\Traits\Relations\FieldEntityPointer; -use CodeManager\Entity\Abstractions\Traits\Text\FieldText; +use QuasarSource\Doctrine\Entity\Field\Text\TraitText0; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; -use QuasarSource\SQL\Doctrine\Entity\Field\Boolean\TraitBool0; +use QuasarSource\Doctrine\Entity\Field\Boolean\TraitBool0; /** * Class EntityUserAlias @@ -21,7 +21,7 @@ */ class EntityEntityEntityAlias extends AbstractEntity { // Alias name. - use FieldText; + use TraitText0; // Pointer to the User Entity. use FieldEntityPointer; diff --git a/applications/asset_server/code_manager/src/Entity/Users/EntityEntityEntityRole.php b/applications/asset_server/code_manager/src/Entity/Users/EntityEntityEntityRole.php index 77b73cf1a..a4b650e5c 100644 --- a/applications/asset_server/code_manager/src/Entity/Users/EntityEntityEntityRole.php +++ b/applications/asset_server/code_manager/src/Entity/Users/EntityEntityEntityRole.php @@ -4,7 +4,7 @@ use CodeManager\Entity\Abstractions\AbstractEntity; use CodeManager\Entity\Abstractions\Traits\Number\Whole\FieldInt; -use CodeManager\Entity\Abstractions\Traits\Text\FieldText; +use QuasarSource\Doctrine\Entity\Field\Text\TraitText0; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; @@ -12,15 +12,12 @@ * Class EntityUserRole * @package CodeManager\Entity\Users * - * @Entity( - * repositoryClass="CodeManager\Repository\Users\RepoEntityEntityRole", - * readOnly=true - * ) + * @Entity(repositoryClass="CodeManager\Repository\Users\RepoEntityEntityRole", readOnly=true) * @Table(name="entity_entity_role") */ class EntityEntityEntityRole extends AbstractEntity { // Name. - use FieldText; + use TraitText0; // RankID. use FieldInt; diff --git a/applications/asset_server/code_manager/src/Enum/ProjectParameterKeys/Path.php b/applications/asset_server/code_manager/src/Enum/ProjectParameterKeys/Path.php deleted file mode 100644 index c2d8b64e9..000000000 --- a/applications/asset_server/code_manager/src/Enum/ProjectParameterKeys/Path.php +++ /dev/null @@ -1,25 +0,0 @@ -project_directory === null) { - $this->project_directory = dirname(__DIR__); - } - return $this->project_directory; + return '/quasar_source/applications/asset_server/code_manager'; } /** @@ -50,26 +45,13 @@ public function getProjectDir(): string { * @throws Exception */ protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void { - #var_dump('CONFIGURE CONTAINER!'); - $container->setParameter(SCHEMAS::YAML_CODE_MANAGER, [ - 'global_information' => null, - 'assets' => ['.vert' => null, '.frag' => null], - 'npm' => null, - 'qa_report' => null, - 'docker' => null, - 'projects' => null - ]); - $container->setParameter(SCHEMAS::YAML_ASSETS, [ - [PATHS::DIRECTORY_OUTPUT => null, PATHS::DIRECTORY_DATA => null, 'files' => null] - ]); - - $container->addResource(new FileResource(getenv(PATHS::PROJECT_BUNDLES))); + $container->addResource(new FileResource('/quasar_source/applications/asset_server/code_manager/config/bundles.php')); $container->setParameter('container.dumper.inline_class_loader', true); - $confDir = $this->getProjectDir() . '/config'; + $confDir = '/quasar_source/applications/asset_server/code_manager/config'; $loader->load($confDir.'/{packages}/*.yaml', 'glob'); $loader->load($confDir.'/{packages}/'.$this->environment.'/**/*.yaml', 'glob'); - $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob'); - $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob'); + $loader->load($confDir.'/{services}.{php,xml,yaml,yml}', 'glob'); + $loader->load($confDir.'/{services}_'.$this->environment.'.{php,xml,yaml,yml}', 'glob'); } /** @@ -77,9 +59,9 @@ protected function configureContainer(ContainerBuilder $container, LoaderInterfa * @throws LoaderLoadException */ protected function configureRoutes(RouteCollectionBuilder $routes): void { - $conf_dir = dirname(__DIR__).'/config/{routes}'; + $conf_dir = '/quasar_source/applications/asset_server/code_manager/config/{routes}'; $routes->import($conf_dir.'/'.$this->environment.'/**/*.yaml', '/', 'glob'); - $routes->import($conf_dir.'/*'.self::CONFIG_EXTS, '/', 'glob'); - $routes->import($conf_dir.self::CONFIG_EXTS, '/', 'glob'); + $routes->import($conf_dir.'/*.{php,xml,yaml,yml}', '/', 'glob'); + $routes->import($conf_dir.'.{php,xml,yaml,yml}', '/', 'glob'); } } diff --git a/applications/asset_server/code_manager/src/Repository/Abstractions/AbstractRepo.php b/applications/asset_server/code_manager/src/Repository/Abstractions/AbstractRepo.php index e0751b6eb..5ef57d15e 100644 --- a/applications/asset_server/code_manager/src/Repository/Abstractions/AbstractRepo.php +++ b/applications/asset_server/code_manager/src/Repository/Abstractions/AbstractRepo.php @@ -3,12 +3,10 @@ namespace CodeManager\Repository\Abstractions; use CodeManager\Entity\Abstractions\AbstractEntity; -use Doctrine\Common\Persistence\ObjectRepository; +use CodeManager\Service\DBService; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\ORMException; -use QuasarSource\Utils\Exception\ExceptionDB; /** * Class AbstractRepo @@ -16,69 +14,99 @@ */ abstract class AbstractRepo extends EntityRepository { - public const ENTITY_CLASS = ''; + /** @var string $entity_class */ + protected $entity_class; /** @var EntityManagerInterface $em */ protected $em; + # --------------------------------------------------- M A G I C ---------------------------------------------------- /** - * Initializes a new EntityRepository. - * - * @param EntityManagerInterface $em The EntityManager to use. - * @param ClassMetadata $class The class descriptor. + * @param EntityManagerInterface $em + * @param ClassMetadata $class */ public function __construct(EntityManagerInterface $em, ClassMetadata $class) { parent::__construct($em, $class); $this->em = $em; } + # -------------------------------------------------- P U B L I C --------------------------------------------------- /** - * @return array + * @return string */ - public function get_all(): array { - return $this->findAll(); + public function get_entity_class(): string { + return $this->_entityName; } /** - * @param bool $auto_save - * @return AbstractEntity + * @param mixed $entity + * @param bool $save_db_state */ - public function get_new_entity(bool $auto_save=false): AbstractEntity { - $entity_class = static::ENTITY_CLASS; - $entity = new $entity_class(); - if ($auto_save) { - $this->save_entity($entity, true); + public function save($entity, bool $save_db_state=false): void { + if (is_array($entity)) { + foreach ($entity as $e) { + $this->em->persist($e); + } + } else { + $this->em->persist($entity); + } + if ($save_db_state) { + $this->em->flush(); } - return $entity; } /** - * @param string $repo_class - * @return ObjectRepository + * @param string $find_key + * @param mixed $find_value + * @param string $sort_key + * @return array */ - protected function get_repo(string $repo_class): ObjectRepository { - return $this->em->getRepository($repo_class); + public function findByAscendingBy(string $find_key, $find_value, string $sort_key): array { + return $this->findBy([$find_key => $find_value], [$sort_key => 'ASC']); + } + + /** + * @param string $find_key + * @param mixed $find_value + * @param string $sort_key + * @return array + */ + public function findByDescendingBy(string $find_key, $find_value, string $sort_key): array { + return $this->findBy([$find_key => $find_value], [$sort_key => 'DESC']); } /** * @param int $id * @return object|null */ - protected function get_entity_by_id(int $id) { + public function find_by_id(int $id) { return $this->findOneBy(['id' => $id]); } - protected $default_search_attribute; - - /** @var string $entity_class */ - protected $entity_class; + /** + * @return array + */ + public function get_all(): array { + return $this->findAll(); + } - public function get_entity($search_value) { - return $this->findOneBy([$this->default_search_attribute => $search_value]); + protected function flush(): void { + $this->em->flush(); } - public function has_entity($search_value): bool { - return $this->get_entity($search_value) !== null; + # ------------ + + /** + * @param bool $auto_save + * @return AbstractEntity + */ + public function get_new_entity(bool $auto_save=false): AbstractEntity { + $entity_class = $this->get_entity_class(); + $entity = new $entity_class(); + if ($auto_save) { + $this->save($entity, true); + } + return $entity; } /** @@ -89,7 +117,7 @@ public function create_new_entity($value, bool $save=true) { $entity = new $this->entity_class(); //$entity->on_event_born($value); if ($save) { - $this->save_entity($entity, true); + $this->save($entity, true); } return $entity; } @@ -106,18 +134,8 @@ public function remove_entity($entity, bool $save_db_state=false): void { } /** - * @param mixed $entity - * @param bool $save_db_state + * @param DBService $db_service */ - public function save_entity($entity, bool $save_db_state=false): void { - $this->em->persist($entity); - if ($save_db_state) { - $this->em->flush(); - } - } - - protected function flush(): void { - $this->em->flush(); - } + public function set_db_service(DBService $db_service): void {} } diff --git a/applications/asset_server/code_manager/src/Repository/Abstractions/QueryableRepo.php b/applications/asset_server/code_manager/src/Repository/Abstractions/QueryableRepo.php index d97f6110c..7968fb390 100644 --- a/applications/asset_server/code_manager/src/Repository/Abstractions/QueryableRepo.php +++ b/applications/asset_server/code_manager/src/Repository/Abstractions/QueryableRepo.php @@ -2,6 +2,7 @@ namespace CodeManager\Repository\Abstractions; +use CodeManager\Entity\Abstractions\AbstractEntity; use CodeManager\Service\DBService; use CodeManager\Service\LoggerService; use QuasarSource\SQL\DBTable; @@ -24,6 +25,12 @@ abstract class QueryableRepo extends AbstractRepo implements InterfaceSQLQueryOw /** @var LoggerService $logger */ protected $logger; + # --------------------------------------------------- M A G I C ---------------------------------------------------- + public function __destruct() { + unset($this->db_table, $this->db_service, $this->logger); + } + # -------------------------------------------------- P U B L I C --------------------------------------------------- + /** * @return mixed */ @@ -69,10 +76,9 @@ protected function execute_custom_query(string $query) { * @return DBTable */ protected function get_db_table(): DBTable { - $entity_class = static::ENTITY_CLASS; - if (!isset($entity_class::$db_table_name)) { - throw new RuntimeException('{' . $entity_class . '} does not have a table name public const set.'); - } + /** @var AbstractEntity $entity_class */ + $entity_class = $this->get_entity_class(); + var_dump('ENTITY CLASS IS {' . $entity_class . '}'); $db_table = $this->db_service->get_db_table_by_name($entity_class::$db_table_name); if (isset($entity_class::$sort_field_time) && !$db_table->is_sort_field_set()) { $db_table->set_sort_field_time($entity_class::$sort_field_time); diff --git a/applications/asset_server/code_manager/src/Repository/Abstractions/SingleEntityRepo.php b/applications/asset_server/code_manager/src/Repository/Abstractions/SingleEntityRepo.php index 5de0a2413..d116e1ac1 100644 --- a/applications/asset_server/code_manager/src/Repository/Abstractions/SingleEntityRepo.php +++ b/applications/asset_server/code_manager/src/Repository/Abstractions/SingleEntityRepo.php @@ -53,7 +53,7 @@ public function re_use_previous_entity(int $previous_entity_id): AbstractEntity $this->current_entity_was_created = false; $this->current_entity_was_re_used = true; /** @var AbstractEntity $previous_entity */ - $previous_entity = $this->get_entity_by_id($previous_entity_id); + $previous_entity = $this->find_by_id($previous_entity_id); #$this->current_entity = $previous_entity; return $previous_entity; } diff --git a/applications/asset_server/code_manager/src/Repository/CodeManager/File/RepoFile.php b/applications/asset_server/code_manager/src/Repository/CodeManager/File/RepoFile.php deleted file mode 100644 index e2f911677..000000000 --- a/applications/asset_server/code_manager/src/Repository/CodeManager/File/RepoFile.php +++ /dev/null @@ -1,157 +0,0 @@ -findOneBy([FIELD::FULL_PATH_AS_SQL => $path]); - $out_of_date = false; - if ($file->has_sha512sum_changed()) { - $out_of_date = true; - $file->sync(); - $this->save_entity($file, true); - } - return $out_of_date; - } - - /** - * @param string $path - * @return bool - */ - public function does_entity_exist(string $path): bool { - return $this->findOneBy([FIELD::FULL_PATH_AS_SQL => $path]) !== null; - } - - /** - * @param string $path - * @param EntityDirectory $parent_directory - * @return EntityFile - */ - public function create_new_fully_cached_entity(string $path, EntityDirectory $parent_directory): EntityFile { - var_dump('create_new_fully_cached_entity'); - $entity = $this->create_new_file_entity($path); - $parent_directory->addFile($entity); - $entity->sync(); - $entity->setDirectory($parent_directory); - if (!$entity->hasParent()) { - $entity->set_rank(0); - } - return $this->fully_save_entity($entity, $this->repo_file_types->get_entity_needed_file_type($entity)); - } - - /** - * @param EntityFile $parent_file - * @param EntityFileType $child_file_type - * @param string $child_path - * @param EntityDirectory $parent_directory - * @return EntityFile - */ - public function create_new_fully_cached_entity_child( - EntityFile $parent_file, - EntityFileType $child_file_type, - string $child_path, - EntityDirectory $parent_directory=null - ): EntityFile { - var_dump('create_new_fully_cached_child_entity'); - if ($this->does_entity_exist($child_path)) { - throw new RuntimeException('Trying to create EntityFile for path{' . $child_path . '} which already exists in the DB!'); - } - $entity = $this->create_new_file_entity($child_path); - if ($parent_directory !== null) { - $parent_directory->addFile($entity); - } - $entity->sync(); - if ($parent_directory !== null) { - $entity->setDirectory($parent_directory); - } - $entity = $this->fully_save_entity($entity, $child_file_type); - if ($parent_file !== null) { - $this->set_parent_and_child($parent_file, $entity); - } - return $entity; - } - - /** - * @param EntityFile $file - * @param string $output_directory - * @return EntityFile - */ - public function ensure_file_has_gzipped_child(EntityFile $file, string $output_directory): EntityFile { - if (!$file->hasChild()) { - $needed_type = $this->repo_file_types->get_type_as_gzipped($file); - $output_path = $output_directory . STR::replace(PATH::get_file_full_name($file->getFullPath()), $file->getFileTypeString(), $needed_type->getAsString()); - UFO::gzip($file->getFullPath(), $output_path); - return $this->create_new_fully_cached_entity_child($file, $needed_type, $output_path); - } - return $file->getChild(); - } - - # ------------------------------------------------- P R I V A T E -------------------------------------------------- - - /** - * @param EntityFile $parent - * @param EntityFile $child - * @return void - */ - private function set_parent_and_child(EntityFile $parent, EntityFile $child): void { - $parent->setChild($child); - $child->setParent($parent); - $this->save_entity($parent, false); - $this->save_entity($child, true); - } - - /** - * @param string $path - * @return EntityFile - */ - private function create_new_file_entity(string $path): EntityFile { - $file = new EntityFile(); - $file->setFullPath($path); - return $file; - } - - /** - * @param EntityFile $file - * @param EntityFileType $file_type - * @return EntityFile - */ - private function fully_save_entity(EntityFile $file, EntityFileType $file_type): EntityFile { - $file_type->mark_entity_file($file); - $this->save_entity($file, true); - $this->repo_file_types->save_entity($file_type); - return $file; - } - - # ----------------------------------- A B S T R A C T I O N -- C O N T R A C T S ----------------------------------- - public function set_needed_repos(): void { - $this->repo_file_types = $this->db_service->get_repo(RepoFileType::class); - } -} diff --git a/applications/asset_server/code_manager/src/Repository/CodeManager/File/RepoFileType.php b/applications/asset_server/code_manager/src/Repository/CodeManager/File/RepoFileType.php deleted file mode 100644 index d8422ac22..000000000 --- a/applications/asset_server/code_manager/src/Repository/CodeManager/File/RepoFileType.php +++ /dev/null @@ -1,135 +0,0 @@ -get_file_type_and_ensure_validity($file, self::EXTENSION_TYPE_GZIPPED); - - $minified = $current_type->get_is_minified() ? 'true' : 'false'; - $processed = $current_type->get_is_processed() ? 'true' : 'false'; - $entity_type = $current_type->getEntityType(); - - $sql = 'SELECT id FROM public.file_type WHERE bool_1 = ' . $processed; - $sql .= ' AND bool_0 = ' . $minified . ' AND entity_type = ' . $entity_type; - $sql .= ' AND bool_2 = true'; - $sql .= " AND as_string != '" . $current_type->getAsString() . "'"; - - $result = $this->execute_custom_query( - $sql - ); - $id_to_get = (int) $result[0][0]; - /** @var EntityFileType $type */ - $type = $this->findOneBy(['id' => $id_to_get]); - var_dump('FOR GETTING GZIP TYPE, I GOT THE FOLLOWING {' . $type->getAsString() . '}'); - return $type; - } - - /** - * @param EntityFile $file - * @return EntityFileType - */ - public function get_type_as_minified(EntityFile $file): EntityFileType { - $current_type = $this->get_file_type_and_ensure_validity($file, self::EXTENSION_TYPE_MINIFIED); - - $gzipped = $current_type->get_is_gzipped() ? 'true' : 'false'; - $processed = $current_type->get_is_processed() ? 'true' : 'false'; - $entity_type = $current_type->getEntityType(); - - $sql = 'SELECT id FROM public.file_type WHERE bool_1 = ' . $processed; - $sql .= ' AND bool_2 = ' . $gzipped . ' AND entity_type = ' . $entity_type; - $sql .= ' AND bool_0 = true'; - $sql .= " AND as_string != '" . $current_type->getAsString() . "'"; - - $query = new SQLQuery(); - $query->SELECT('id')->FROM('public.file_type') - ->WHERE_EQUAL_TO_BOOL('bool_1', $processed) - ->AND_EQUAL_TO_BOOL('bool_2', $gzipped) - ->AND_EQUAL_TO('entity_type', $entity_type) - ->AND_EQUAL_TO_STR('as_string', $current_type->getAsString()); - - #var_dump($sql); - $result = $this->execute_custom_query( - $sql - ); - $id_to_get = (int) $result[0][0]; - /** @var EntityFileType $type */ - $type = $this->findOneBy(['id' => $id_to_get]); - return $type; - } - - /** - * @param EntityFile $file - * @return EntityFileType - */ - public function get_entity_needed_file_type(EntityFile $file): EntityFileType { - $extensions = PATH::get_extensions_as_string($file->getFullPath()); - /** - * @var string $extension_string - * @var EntityFileType $entity - */ - foreach ($this->cached_extensions_to_entity_ids as $extension_string => $entity) { - if ($extensions === $extension_string) { - return $entity; - } - } - throw new RuntimeException('Unable to find needed file type for entity file {' . $file->getFullPath() . '}'); - } - - public function set_needed_repos(): void { - $this->repo_files = $this->db_service->get_repo(RepoFile::class); - /** @var EntityFileType $file_type */ - foreach ($this->get_all() as $file_type) { - $this->cached_extensions_to_entity_ids[$file_type->getAsString()] = $file_type; - } - } - - # ------------------------------------------------- P R I V A T E -------------------------------------------------- - - /** - * @param EntityFile $file - * @param string $extension_type - * @return EntityFileType - */ - private function get_file_type_and_ensure_validity(EntityFile $file, string $extension_type): EntityFileType { - $type = $file->getFileType(); - if ($extension_type === self::EXTENSION_TYPE_GZIPPED && $type->get_is_gzipped() || - $extension_type === self::EXTENSION_TYPE_MINIFIED && $type->get_is_minified() || - $extension_type === self::EXTENSION_TYPE_PROCESSED && $type->get_is_processed() - ) { - throw new RuntimeException( - 'The entity file{' . $file->getFullPath() . '}\'s extension is already {' . $extension_type . '}!' - ); - } - return $type; - } -} diff --git a/applications/asset_server/code_manager/src/Repository/CodeManager/RepoCodeBuild.php b/applications/asset_server/code_manager/src/Repository/CodeManager/RepoCodeBuild.php index ada5134a8..57d56b527 100644 --- a/applications/asset_server/code_manager/src/Repository/CodeManager/RepoCodeBuild.php +++ b/applications/asset_server/code_manager/src/Repository/CodeManager/RepoCodeBuild.php @@ -15,8 +15,6 @@ */ class RepoCodeBuild extends QueryableRepo { - public const ENTITY_CLASS = EntityCodeBuild::class; - public function sync_to_logs(): void { var_dump('Syncing logs'); @@ -42,7 +40,7 @@ public function sync_to_logs(): void { $entity->set_timestamp($section_times[$c]); $entity->set_logs_session($sections[$c]); - $this->save_entity($entity, true); + $this->save($entity, true); } $this->flush(); } else { diff --git a/applications/asset_server/code_manager/src/Repository/CodeManager/RepoCodeProcedure.php b/applications/asset_server/code_manager/src/Repository/CodeManager/RepoCodeProcedure.php new file mode 100644 index 000000000..d8721976b --- /dev/null +++ b/applications/asset_server/code_manager/src/Repository/CodeManager/RepoCodeProcedure.php @@ -0,0 +1,32 @@ +findByAscendingBy('code_project', $project_id, 'smallint0'); + $procedures = []; + /** @var EntityCodeProcedure $entity */ + foreach ($entities as $entity) { + $class = $entity->getTaskClass(); + $task = new $class(); + $procedures[] = $task; + } + return $procedures; + } + + # ------------------------------------ A B S T R A C T I O N C O N T R A C T ------------------------------------ + public function set_needed_repos(): void {} +} diff --git a/applications/asset_server/code_manager/src/Repository/CodeManager/RepoCodeProject.php b/applications/asset_server/code_manager/src/Repository/CodeManager/RepoCodeProject.php new file mode 100644 index 000000000..8554e70a4 --- /dev/null +++ b/applications/asset_server/code_manager/src/Repository/CodeManager/RepoCodeProject.php @@ -0,0 +1,70 @@ +get_project_by_name(SYS::get_env('BUILD_PROJECT')); + } + + /** + * @param string $name + * @return EntityCodeProject + */ + public function get_project_by_name(string $name): EntityCodeProject { + /** @var EntityCodeProject $project */ + $project = $this->findOneBy(['name_full' => $name]); + + if (!in_array($name, $this->projects_fetched, true)) { + $this->projects_fetched[] = $name; + $this->health_check_project_paths($project); + } + + return $project; + } + + /** + * @param EntityCodeProject $project + * @return array + */ + public function get_project_procedures(EntityCodeProject $project): array { + return $this->repo_procedure->get_all_procedures_for_project($project->getID()); + } + + /** + * @param EntityCodeProject $project + */ + private function health_check_project_paths(EntityCodeProject $project): void { + $project->cache_directories($this->repo_dir); + } + + # ------------------------------------ A B S T R A C T I O N C O N T R A C T ------------------------------------ + public function set_needed_repos(): void { + $this->repo_dir = $this->db_service->get_repo(EntityDirectory::class); + $this->repo_procedure = $this->db_service->get_repo(EntityCodeProcedure::class); + } +} diff --git a/applications/asset_server/code_manager/src/Repository/CodeManager/RepoNPMLib.php b/applications/asset_server/code_manager/src/Repository/CodeManager/RepoNPMLib.php index 47109bbb0..18fc07350 100644 --- a/applications/asset_server/code_manager/src/Repository/CodeManager/RepoNPMLib.php +++ b/applications/asset_server/code_manager/src/Repository/CodeManager/RepoNPMLib.php @@ -11,8 +11,6 @@ */ class RepoNPMLib extends AbstractRepo { - protected $default_search_attribute = 'name'; - public const ENTITY_CLASS = EntityNPMLib::class; - protected $entity_class = EntityNPMLib::class; + protected $entity_class = EntityNPMLib::class; } diff --git a/applications/asset_server/code_manager/src/Repository/CodeManager/RepoSnapshotDB.php b/applications/asset_server/code_manager/src/Repository/CodeManager/RepoSnapshotDB.php index 947d86ac9..b86467c62 100644 --- a/applications/asset_server/code_manager/src/Repository/CodeManager/RepoSnapshotDB.php +++ b/applications/asset_server/code_manager/src/Repository/CodeManager/RepoSnapshotDB.php @@ -3,11 +3,12 @@ namespace CodeManager\Repository\CodeManager; use CodeManager\Entity\Abstractions\AbstractEntity; +use CodeManager\Entity\CodeManager\EntityCodeBuild; use CodeManager\Entity\CodeManager\EntitySnapshotDB; use CodeManager\Repository\Abstractions\SingleEntityRepo; -use QuasarSource\CommonFeatures\TraitEnvironmentVariablesAsFields; +use QuasarSource\CommonFeatures\TraitEnvVarsAsFields; use QuasarSource\SQL\DBSchema; -use QuasarSource\Utils\Process\ProcessDoctrine; +use QuasarSource\Utils\Process\ProcessRunner; use QuasarSource\Utils\Time\UtilsUnixTime as TIME; /** @@ -15,9 +16,7 @@ * @package CodeManager\Repository\CodeManager */ class RepoSnapshotDB extends SingleEntityRepo { - use TraitEnvironmentVariablesAsFields; - - public const ENTITY_CLASS = EntitySnapshotDB::class; + use TraitEnvVarsAsFields; /** @var string */ private $env_db_name; @@ -47,7 +46,7 @@ public function get_queries_db_schema(): DBSchema { public function set_needed_repos(): void { $this->envs_set_as_str(['DB_NAME' => 'env_db_name']); $this->queries_schema = new DBSchema($this->env_db_name, $this->db_service->get_db_connection()); - $this->repo_code_builds = $this->db_service->get_repo(RepoCodeBuild::class); + $this->repo_code_builds = $this->db_service->get_repo(EntityCodeBuild::class); } /** @@ -98,10 +97,10 @@ protected function set_current_entity(array $prev_entity_data=null): AbstractEnt } /** - * @param ProcessDoctrine|null $doctrine + * @param ProcessRunner|null $doctrine * @return AbstractEntity */ - private function create_new_db_snapshot(ProcessDoctrine $doctrine=null): AbstractEntity { + private function create_new_db_snapshot(ProcessRunner $doctrine=null): AbstractEntity { $this->mark_current_entity_as_created(new EntitySnapshotDB()); /** @var EntitySnapshotDB $entity */ $entity = $this->current_entity; @@ -112,15 +111,15 @@ private function create_new_db_snapshot(ProcessDoctrine $doctrine=null): Abstrac if ($doctrine !== null) { $entity->set_schema_command_output('|||' . json_encode($doctrine->get_output()) . '|||' . json_encode($doctrine->get_error_output()) . '|||'); } - $this->save_entity($entity, true); + $this->save($entity, true); $this->logger->log('A new SnapshotDB Entity was created with timestamp{' . $entity->get_timestamp() . '}'); return $entity; } /** - * @param ProcessDoctrine|null $doctrine + * @param ProcessRunner|null $doctrine */ - private function parse_doctrine_results(ProcessDoctrine $doctrine=null): void { + private function parse_doctrine_results(ProcessRunner $doctrine=null): void { if ($doctrine !== null) { $errors = json_encode($doctrine->get_error_output()); $output = json_encode($doctrine->get_output()); diff --git a/applications/asset_server/code_manager/src/Repository/CodeManager/RepoSnapshotQA.php b/applications/asset_server/code_manager/src/Repository/CodeManager/RepoSnapshotQA.php index 6f1e19203..75621fc50 100644 --- a/applications/asset_server/code_manager/src/Repository/CodeManager/RepoSnapshotQA.php +++ b/applications/asset_server/code_manager/src/Repository/CodeManager/RepoSnapshotQA.php @@ -11,7 +11,6 @@ */ class RepoSnapshotQA extends AbstractRepo { - public const ENTITY_CLASS = EntitySnapshotQA::class; - protected $entity_class = EntitySnapshotQA::class; + protected $entity_class = EntitySnapshotQA::class; } diff --git a/applications/asset_server/code_manager/src/Repository/CodeManager/File/RepoDirectory.php b/applications/asset_server/code_manager/src/Repository/File/RepoDirectory.php similarity index 53% rename from applications/asset_server/code_manager/src/Repository/CodeManager/File/RepoDirectory.php rename to applications/asset_server/code_manager/src/Repository/File/RepoDirectory.php index 85b7d78ee..d7f60642e 100644 --- a/applications/asset_server/code_manager/src/Repository/CodeManager/File/RepoDirectory.php +++ b/applications/asset_server/code_manager/src/Repository/File/RepoDirectory.php @@ -1,39 +1,48 @@ find_by_path($path_to_directory); + $force_sha512sum_sync = false; + $entity = $this->find_by_path($path_to_directory); if ($entity === null) { - $entity = $this->create_real_directory($path_to_directory); - return $this->sync_directory_contents($entity, true); + $this->logger->log('Creating EntityDir{' . $path_to_directory . '}'); + $entity = $this->save_directory(EntityDirectory::spawn($path_to_directory)); + $force_sha512sum_sync = true; + } + if (!array_key_exists($path_to_directory, $this->cache_real_dirs)) { + $dir_entity = $this->sync_directory_contents($entity, $force_sha512sum_sync); + $this->cache_real_dirs[$path_to_directory] = $dir_entity; } - return $this->sync_directory_contents($entity, false); + return $this->cache_real_dirs[$path_to_directory]; } /** @@ -42,7 +51,7 @@ public function get_real(string $path_to_directory): EntityDirectory { */ protected function find_by_path(string $path): ?EntityDirectory { /** @var EntityDirectory $entity */ - $entity = $this->findOneBy([FIELD::FULL_PATH_AS_SQL => $path]); + $entity = $this->findOneBy([FIELD::PATH_AS_SQL => $path]); return $entity; } @@ -57,44 +66,40 @@ protected function sync_directory_contents(EntityDirectory $directory, bool $for $all_paths = $directory->get_all_paths(); foreach ($all_paths as $path) { if (!$this->repo_files->does_entity_exist($path)) { - var_dump('Path{' . $path . '} does not exist in the DB, creating it.'); + $this->logger->log('Entity[File|Dir]{' . $path . '} did not exist, creating it!'); $already_synced = false; $file = $this->repo_files->create_new_fully_cached_entity($path, $directory); } else { $updated = $this->repo_files->sync($path, $directory); if ($updated) { - var_dump('Path{' . $path . '} already exists but was not up to date.'); + $this->logger->log('Entity[File|Dir]{' . $path . '} exists but will be updated.'); $already_synced = false; } else { - var_dump('Path{' . $path . '} already exists and is up to date.'); + $this->logger->log('Entity[File|Dir]{' . $path . '} is up to date.'); } } } if (!$already_synced || $force_sha512sum_sync) { - $directory->setSHA512Sum(DIR::get_sha512sum($directory->getFullPath(), true)); - } else { - var_dump('Directory{' . $directory->getFullPath() . '} is up to date.'); + $directory->setSHA512Sum(DIR::get_sha512sum($directory->getPath(), true)); + return $this->save_directory($directory); } + $this->logger->log('EntityDir{' . $directory->getPath() . '} is up to date.'); return $directory; } /** - * @param string $path + * @param EntityDirectory $directory * @return EntityDirectory - * @throws Exception */ - private function create_real_directory(string $path): EntityDirectory { - $this->logger->log('Creating Directory Entity for path{' . $path . '}'); - $directory = new EntityDirectory(); - $directory->setFullPath($path)->set_cache_last_updated(-1); - $this->save_entity($directory, true); + private function save_directory(EntityDirectory $directory): EntityDirectory { + $this->save($directory, true); return $directory; } # ------------------------------------ A B S T R A C T I O N C O N T R A C T ------------------------------------ public function set_needed_repos(): void { - $this->repo_files = $this->db_service->get_repo(RepoFile::class); - $this->repo_file_types = $this->db_service->get_repo(RepoFileType::class); + $this->repo_files = $this->db_service->get_repo(EntityFile::class); + $this->repo_file_types = $this->db_service->get_repo(EntityFileType::class); } } diff --git a/applications/asset_server/code_manager/src/Repository/File/RepoFile.php b/applications/asset_server/code_manager/src/Repository/File/RepoFile.php new file mode 100644 index 000000000..8d959414a --- /dev/null +++ b/applications/asset_server/code_manager/src/Repository/File/RepoFile.php @@ -0,0 +1,186 @@ +repo_file_types, $this->env_node_file_minifier); + parent::__destruct(); + } + # -------------------------------------------------- P U B L I C --------------------------------------------------- + + /** + * @param string $path + * @param EntityDirectory $directory + * @return bool + */ + public function sync(string $path, EntityDirectory $directory): bool { + /** @var EntityFile $file */ + $file = $this->findOneBy([FIELD::PATH_AS_SQL => $path]); + if ($file->sync()) { + $this->save($file, true); + return true; + } + return false; + } + + /** + * @param string $path + * @return EntityFile|null + */ + public function find_by_path(string $path): ?EntityFile { + /** @var EntityFile $entity */ + $entity = $this->findOneBy([FIELD::PATH_AS_SQL => $path]); + return $entity; + } + + /** + * @param string $path + * @return bool + */ + public function does_entity_exist(string $path): bool { + return $this->findOneBy([FIELD::PATH_AS_SQL => $path]) !== null; + } + + /** + * @param string $path + * @param EntityDirectory $parent_directory + * @return EntityFile + */ + public function create_new_fully_cached_entity(string $path, EntityDirectory $parent_directory): EntityFile { + $this->ensure_path_dne_in_db($path); + $entity = EntityFile::spawn($path, $parent_directory); + return $this->fully_save_entity($entity, $this->repo_file_types->get_entity_needed_file_type($entity)); + } + + /** + * @param EntityFile $parent_file + * @param EntityFileType $child_file_type + * @param string $child_path + * @param EntityDirectory $parent_directory + * @return EntityFile + */ + public function create_new_fully_cached_entity_child( + EntityFile $parent_file, + EntityFileType $child_file_type, + string $child_path, + EntityDirectory $parent_directory=null + ): EntityFile { + $this->ensure_path_dne_in_db($child_path); + return $this->fully_save_entity(EntityFile::spawn($child_path, $parent_directory, $parent_file), $child_file_type); + } + + /** + * @param EntityFile $file + * @param string $extension + * @return EntityFile|null + */ + public function find_matching_file_with_alt_extension(EntityFile $file, string $extension): ?EntityFile { + return $this->find_by_path(STR::replace($file->getPath(), $file->get_file_extensions(), $extension)); + } + + /** + * @param EntityFile $file + * @param string $output_directory + * @return EntityFile + */ + public function ensure_file_has_gzipped_child(EntityFile $file, string $output_directory): EntityFile { + return $this->ensure_file_has_child_file($file, RepoFileType::EXTENSION_TYPE_GZIPPED, $output_directory); + } + + /** + * @param EntityFile $file + * @param string $output_directory + * @return EntityFile + */ + public function ensure_file_has_minified_child(EntityFile $file, string $output_directory): EntityFile { + return $this->ensure_file_has_child_file($file, RepoFileType::EXTENSION_TYPE_MINIFIED, $output_directory); + } + + /** + * @param EntityFile $file + * @param string $child_extension_type + * @param string $output_directory + * @return EntityFile + */ + public function ensure_file_has_child_file(EntityFile $file, string $child_extension_type, string $output_directory): EntityFile { + if (!$file->hasChild()) { + $needed_type = $this->repo_file_types->get_type_as($file, $child_extension_type); + $output_path = $output_directory . $file->get_name_as_type($needed_type); + switch ($child_extension_type) { + case RepoFileType::EXTENSION_TYPE_GZIPPED: + UFO::gzip($file->getPath(), $output_path); + return $this->create_new_fully_cached_entity_child($file, $needed_type, $output_path); + case RepoFileType::EXTENSION_TYPE_MINIFIED: + if (!$file->getFileType()->can_be_minified()) { + throw new RuntimeException('Currently can only minify CSS and HTML files.'); + } + UtilsProcess::run_cmd(['node', $this->env_node_file_minifier, '-i', $file->getPath(), '-o', $output_path]); + return $this->create_new_fully_cached_entity_child($file, $needed_type, $output_path); + default: + throw new InvalidArgumentException('Unknown EntityFile extension type/group{' . $child_extension_type . '}'); + } + } + return $file->getChild(); + } + + # ------------------------------------------------- P R I V A T E -------------------------------------------------- + + /** + * @param EntityFile $file + * @param EntityFileType $file_type + * @return EntityFile + */ + private function fully_save_entity(EntityFile $file, EntityFileType $file_type): EntityFile { + $file->setFileType($file_type); + $this->save($file, true); + if ($file->hasParent()) { + $this->save($file->getParent(), true); + } + $this->repo_file_types->save($file_type); + return $file; + } + + /** + * @param string $path + */ + private function ensure_path_dne_in_db(string $path): void { + if ($this->does_entity_exist($path)) { + throw new RuntimeException('The path{' . $path . '} already exists in the DB!'); + } + } + + # ----------------------------------- A B S T R A C T I O N -- C O N T R A C T S ----------------------------------- + public function set_needed_repos(): void { + $this->repo_file_types = $this->db_service->get_repo(EntityFileType::class); + $this->envs_set_as_str(['PATH_NODE_MINIFY_FILE' => 'env_node_file_minifier']); + } + +} diff --git a/applications/asset_server/code_manager/src/Repository/File/RepoFileType.php b/applications/asset_server/code_manager/src/Repository/File/RepoFileType.php new file mode 100644 index 000000000..ea286e175 --- /dev/null +++ b/applications/asset_server/code_manager/src/Repository/File/RepoFileType.php @@ -0,0 +1,126 @@ +repo_files, $this->cached_extensions_to_entity_ids); + parent::__destruct(); + } + + /** + * @param string $extension + * @return EntityFileType + */ + public function find_file_type_by_name(string $extension): EntityFileType { + /** @var EntityFileType $entity */ + $entity = $this->findOneBy(['as_string' => $extension]); + return $entity; + } + + /** + * @param EntityFile $file + * @return EntityFileType + */ + public function get_type_as_processed(EntityFile $file): EntityFileType { + return $this->get_type_as($file, self::EXTENSION_TYPE_PROCESSED); + } + + /** + * @param EntityFile $file + * @param string $extension_type + * @return EntityFileType + */ + public function get_type_as(EntityFile $file, string $extension_type): EntityFileType { + $file_type = $file->getFileType(); + if ($extension_type === self::EXTENSION_TYPE_GZIPPED && $file_type->get_is_gzipped() || + $extension_type === self::EXTENSION_TYPE_MINIFIED && $file_type->get_is_minified() || + $extension_type === self::EXTENSION_TYPE_PROCESSED && $file_type->get_is_processed() + ) { + throw new RuntimeException('EntityFile{' . $file->getPath() . '}\'s extension is already {' . $extension_type . '}!'); + } + $sql = $this->get_query_find_file_type($file_type, $extension_type); + $result = $this->execute_custom_query($sql); + /** @var EntityFileType $type */ + $type = $this->findOneBy(['id' => (int) $result[0][0]]); + return $type; + #$query = new SQLQuery(); + #$query->SELECT('id')->FROM('public.file_type') + # ->WHERE_EQUAL_TO_BOOL('bool_1', $processed) + # ->AND_EQUAL_TO_BOOL('bool_2', $gzipped) + # ->AND_EQUAL_TO('entity_type', $entity_type) + # ->AND_EQUAL_TO_STR('as_string', $current_type->getAsString()); + } + + /** + * @param EntityFile $file + * @return EntityFileType + */ + public function get_entity_needed_file_type(EntityFile $file): EntityFileType { + $extensions = PATH::get_extensions_as_string($file->getPath()); + /** + * @var string $extension_string + * @var EntityFileType $entity + */ + foreach ($this->cached_extensions_to_entity_ids as $extension_string => $entity) { + if ($extensions === $extension_string) { + return $entity; + } + } + throw new RuntimeException('Unable to find needed file type for entity file {' . $file->getPath() . '}'); + } + + # ------------------------------------------------- P R I V A T E -------------------------------------------------- + + /** + * @param EntityFileType $file_type + * @param string $extension_type + * @return string + */ + private function get_query_find_file_type(EntityFileType $file_type, string $extension_type): string { + $minified = $file_type->get_is_minified() ? 'true ' : 'false '; + $gzipped = $file_type->get_is_gzipped() ? 'true ' : 'false '; + $processed = $file_type->get_is_processed() ? 'true ' : 'false '; + $sql = 'SELECT id FROM public.file_type WHERE bool_0 = '; + $sql .= $extension_type === self::EXTENSION_TYPE_MINIFIED ? 'true ' : $minified; + $sql .= 'AND bool_1 = '; + $sql .= $extension_type === self::EXTENSION_TYPE_PROCESSED ? 'true ' : $processed; + $sql .= 'AND bool_2 = '; + $sql .= $extension_type === self::EXTENSION_TYPE_GZIPPED ? 'true ' : $gzipped; + $sql .= 'AND entity_type = ' . $file_type->getEntityType() . ' '; + $sql .= "AND as_string != '" . $file_type->getAsString() . "'"; + return $sql; + } + + # ----------------------------------- A B S T R A C T I O N -- C O N T R A C T S ----------------------------------- + public function set_needed_repos(): void { + $this->repo_files = $this->db_service->get_repo(EntityFile::class); + /** @var EntityFileType $file_type */ + foreach ($this->get_all() as $file_type) { + $this->cached_extensions_to_entity_ids[$file_type->getAsString()] = $file_type; + } + } +} diff --git a/applications/asset_server/code_manager/src/Repository/Finance/Binance/RepoBinanceBalance.php b/applications/asset_server/code_manager/src/Repository/Finance/Binance/RepoBinanceBalance.php index ff257d30b..ea3052e85 100644 --- a/applications/asset_server/code_manager/src/Repository/Finance/Binance/RepoBinanceBalance.php +++ b/applications/asset_server/code_manager/src/Repository/Finance/Binance/RepoBinanceBalance.php @@ -10,7 +10,6 @@ */ class RepoBinanceBalance extends AbstractRepo { - protected $entity_class = EntityBinanceBalance::class; - public const ENTITY_CLASS = EntityBinanceBalance::class; + protected $entity_class = EntityBinanceBalance::class; } diff --git a/applications/asset_server/code_manager/src/Repository/Finance/Binance/RepoBinanceOrder.php b/applications/asset_server/code_manager/src/Repository/Finance/Binance/RepoBinanceOrder.php index b765f51b8..3b1da03e8 100644 --- a/applications/asset_server/code_manager/src/Repository/Finance/Binance/RepoBinanceOrder.php +++ b/applications/asset_server/code_manager/src/Repository/Finance/Binance/RepoBinanceOrder.php @@ -10,7 +10,5 @@ */ class RepoBinanceOrder extends AbstractRepo { - protected $entity_class = EntityBinanceOrder::class; - public const ENTITY_CLASS = EntityBinanceOrder::class; - + protected $entity_class = EntityBinanceOrder::class; } diff --git a/applications/asset_server/code_manager/src/Repository/Finance/Binance/RepoBinanceTrade.php b/applications/asset_server/code_manager/src/Repository/Finance/Binance/RepoBinanceTrade.php index 04598de40..5502606c0 100644 --- a/applications/asset_server/code_manager/src/Repository/Finance/Binance/RepoBinanceTrade.php +++ b/applications/asset_server/code_manager/src/Repository/Finance/Binance/RepoBinanceTrade.php @@ -11,6 +11,5 @@ class RepoBinanceTrade extends AbstractRepo { protected $entity_class = EntityBinanceTrade::class; - public const ENTITY_CLASS = EntityBinanceTrade::class; } diff --git a/applications/asset_server/code_manager/src/Repository/Finance/RepoAssetFlow.php b/applications/asset_server/code_manager/src/Repository/Finance/RepoAssetFlow.php index d84488e60..090a7204a 100644 --- a/applications/asset_server/code_manager/src/Repository/Finance/RepoAssetFlow.php +++ b/applications/asset_server/code_manager/src/Repository/Finance/RepoAssetFlow.php @@ -7,7 +7,6 @@ use CodeManager\Repository\Abstractions\QueryableRepo; use CodeManager\Repository\Users\RepoEntityEntity; use QuasarSource\Utils\DataType\UtilsString as STR; -use QuasarSource\Utils\File\Discrete\UtilsCSV as CSV; /** * Class RepoAssetFlow @@ -15,8 +14,7 @@ */ class RepoAssetFlow extends QueryableRepo { - public const ENTITY_CLASS = EntityAssetFlow::class; - protected $entity_class = EntityAssetFlow::class; + protected $entity_class = EntityAssetFlow::class; public const TYPE_QUICK_PAY = 2; @@ -75,7 +73,7 @@ private function handle_personal_expense(EntityEntity $user, string $user_to_key ->set_transaction_type(3) ->set_from_to_dynamically($user, $to, $data[3]); - $this->save_entity($entity, true); + $this->save($entity, true); } /** @@ -91,7 +89,7 @@ private function handle_quick_pay(EntityEntity $user, array $data): void { ->set_transaction_type(2) ->set_from_to_dynamically($user, $match, $data[3]); - $this->save_entity($entity, true); + $this->save($entity, true); } /** @@ -107,6 +105,6 @@ private function get_user_match(string $search_text): EntityEntity { # ------------------------------------ A B S T R A C T I O N C O N T R A C T ------------------------------------ public function set_needed_repos(): void { - $this->repo_users = $this->db_service->get_repo(RepoEntityEntity::class); + $this->repo_users = $this->db_service->get_repo(EntityEntity::class); } } diff --git a/applications/asset_server/code_manager/src/Repository/Finance/RepoAssetFlowCategory.php b/applications/asset_server/code_manager/src/Repository/Finance/RepoAssetFlowCategory.php index b3856d808..786a1995b 100644 --- a/applications/asset_server/code_manager/src/Repository/Finance/RepoAssetFlowCategory.php +++ b/applications/asset_server/code_manager/src/Repository/Finance/RepoAssetFlowCategory.php @@ -10,8 +10,7 @@ */ class RepoAssetFlowCategory extends QueryableRepo { - public const ENTITY_CLASS = EntityAssetFlowCategory::class; - protected $entity_class = EntityAssetFlowCategory::class; + protected $entity_class = EntityAssetFlowCategory::class; # ------------------------------------ A B S T R A C T I O N C O N T R A C T ------------------------------------ public function set_needed_repos(): void {} diff --git a/applications/asset_server/code_manager/src/Repository/Finance/RepoAssetFlowType.php b/applications/asset_server/code_manager/src/Repository/Finance/RepoAssetFlowType.php index e4e8519c6..ab41032b1 100644 --- a/applications/asset_server/code_manager/src/Repository/Finance/RepoAssetFlowType.php +++ b/applications/asset_server/code_manager/src/Repository/Finance/RepoAssetFlowType.php @@ -10,8 +10,7 @@ */ class RepoAssetFlowType extends QueryableRepo { - public const ENTITY_CLASS = EntityAssetFlowType::class; - protected $entity_class = EntityAssetFlowType::class; + protected $entity_class = EntityAssetFlowType::class; # ------------------------------------ A B S T R A C T I O N C O N T R A C T ------------------------------------ public function set_needed_repos(): void {} diff --git a/applications/asset_server/code_manager/src/Repository/Task/RepoMeeseeksTask.php b/applications/asset_server/code_manager/src/Repository/Task/RepoMeeseeksTask.php new file mode 100644 index 000000000..30630207f --- /dev/null +++ b/applications/asset_server/code_manager/src/Repository/Task/RepoMeeseeksTask.php @@ -0,0 +1,29 @@ +set_iteration(0) + ->set_iterations_needed(1); + $task->set_to_due_in_delta_time(60 * 60 * $num_hours_from_now); + return $task; + } + + # ----------------------------------- A B S T R A C T I O N -- C O N T R A C T ------------------------------------ + public function set_needed_repos(): void {} +} diff --git a/applications/asset_server/code_manager/src/Repository/Users/RepoEntityEntity.php b/applications/asset_server/code_manager/src/Repository/Users/RepoEntityEntity.php index 442764d88..6f1db4dd9 100644 --- a/applications/asset_server/code_manager/src/Repository/Users/RepoEntityEntity.php +++ b/applications/asset_server/code_manager/src/Repository/Users/RepoEntityEntity.php @@ -3,7 +3,6 @@ namespace CodeManager\Repository\Users; use CodeManager\Entity\Users\EntityEntity; -use CodeManager\Entity\Users\EntityEntityEntityAlias; use CodeManager\Repository\Abstractions\AbstractRepo; use CodeManager\Service\DBService; use Doctrine\ORM\EntityManagerInterface; @@ -16,8 +15,7 @@ */ class RepoEntityEntity extends AbstractRepo { - public const ENTITY_CLASS = EntityEntity::class; - protected $entity_class = EntityEntity::class; + protected $entity_class = EntityEntity::class; /** @var RepoEntityEntityAlias $repo_entity_entity_aliases */ protected $repo_entity_entity_aliases; @@ -30,7 +28,6 @@ class RepoEntityEntity extends AbstractRepo { */ public function __construct(EntityManagerInterface $em, ClassMetadata $class) { parent::__construct($em, $class); - $this->repo_entity_entity_aliases = $this->get_repo(EntityEntityEntityAlias::class); } /** @@ -53,7 +50,7 @@ public function find_user_match(DBService $db_service, string $search_text) { } foreach ($this->cache_aliases as $alias => $data) { if (STR::has($search_text, (string) $alias, $data[1])) { - return $this->get_entity_by_id($data[0]); + return $this->find_by_id($data[0]); } } throw new \RuntimeException('No user matched for search text{' . $search_text . '}'); diff --git a/applications/asset_server/code_manager/src/Repository/Users/RepoEntityEntityAlias.php b/applications/asset_server/code_manager/src/Repository/Users/RepoEntityEntityAlias.php index 4b3de7aa1..cc23d88cf 100644 --- a/applications/asset_server/code_manager/src/Repository/Users/RepoEntityEntityAlias.php +++ b/applications/asset_server/code_manager/src/Repository/Users/RepoEntityEntityAlias.php @@ -2,7 +2,6 @@ namespace CodeManager\Repository\Users; -use CodeManager\Entity\Users\EntityEntityEntityAlias; use CodeManager\Repository\Abstractions\QueryableRepo; use CodeManager\Service\DBService; @@ -12,8 +11,6 @@ */ class RepoEntityEntityAlias extends QueryableRepo { - public const ENTITY_CLASS = EntityEntityEntityAlias::class; - /** * @param int $user_id * @return array diff --git a/applications/asset_server/code_manager/src/Repository/Users/RepoEntityEntityRole.php b/applications/asset_server/code_manager/src/Repository/Users/RepoEntityEntityRole.php index be1ac0978..075f95b49 100644 --- a/applications/asset_server/code_manager/src/Repository/Users/RepoEntityEntityRole.php +++ b/applications/asset_server/code_manager/src/Repository/Users/RepoEntityEntityRole.php @@ -11,8 +11,7 @@ */ class RepoEntityEntityRole extends QueryableRepo { - public const ENTITY_CLASS = EntityEntityEntityRole::class; - protected $entity_class = EntityEntityEntityRole::class; + protected $entity_class = EntityEntityEntityRole::class; # ------------------------------------ A B S T R A C T I O N C O N T R A C T ------------------------------------ public function set_needed_repos(): void {} diff --git a/applications/asset_server/code_manager/src/Service/CodeBuilderService.php b/applications/asset_server/code_manager/src/Service/CodeBuilderService.php index 26a88cb28..aff9e0245 100644 --- a/applications/asset_server/code_manager/src/Service/CodeBuilderService.php +++ b/applications/asset_server/code_manager/src/Service/CodeBuilderService.php @@ -3,44 +3,38 @@ namespace CodeManager\Service; use CodeManager\Entity\CodeManager\EntityCodeBuild; -use CodeManager\Entity\CodeManager\File\EntityFile; -use CodeManager\Repository\CodeManager\File\RepoDirectory; -use CodeManager\Repository\CodeManager\File\RepoFile; -use CodeManager\Repository\CodeManager\File\RepoFileType; +use CodeManager\Entity\CodeManager\EntityCodeProject; +use CodeManager\Entity\File\EntityDirectory; +use CodeManager\Entity\File\EntityFile; +use CodeManager\Entity\File\EntityFileType; +use CodeManager\Entity\Task\EntityMeeseeksTask; +use CodeManager\Repository\File\RepoDirectory; +use CodeManager\Repository\File\RepoFile; +use CodeManager\Repository\File\RepoFileType; use CodeManager\Repository\CodeManager\RepoCodeBuild; +use CodeManager\Repository\CodeManager\RepoCodeProject; +use CodeManager\Repository\Task\RepoMeeseeksTask; use CodeManager\Service\Feature\AbstractFactoryService; -use CodeManager\Service\Task\Minification; +use CodeManager\Service\Task\TaskAbstract; use CodeManager\Service\Task\TaskBuildWebAssets; use Doctrine\Common\Persistence\ObjectRepository; use Exception; -use QuasarSource\QualityAssurance\ProjectTestSuiteResult; -use CodeManager\Service\Feature\Config\InterfaceConfigUniversal; use CodeManager\Service\Feature\Config\TraitConfigYAML; use QuasarSource\Utils\DataType\UtilsArray as ARY; use QuasarSource\Utils\DataType\UtilsString as STR; use QuasarSource\Utils\DataType\UtilsTextLines as TEXT_LINES; use QuasarSource\Utils\File\UtilsFile as UFO; -use QuasarSource\Utils\SystemOS\UtilsSystem as SYS; -use CodeManager\Enum\ProjectParameterKeys\Path as PATHS_ENUM; -use CodeManager\Enum\ProjectParameterKeys\Schema as SCHEMAS_ENUM; -use Symfony\Component\DependencyInjection\ContainerInterface; // <- Add this -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Throwable; /** * @Service */ -class CodeBuilderService extends AbstractFactoryService implements InterfaceConfigUniversal { +class CodeBuilderService extends AbstractFactoryService { use TraitConfigYAML; - /** @var ParameterBagInterface $configs_universal */ - private $configs_universal; - /** @var EntityCodeBuild */ private $current_code_build; - #private $container; - /** @var DBService $service_db */ private $service_db; @@ -48,43 +42,35 @@ class CodeBuilderService extends AbstractFactoryService implements InterfaceConf private $repo_code_build; /** - * @param ContainerInterface $container - * @param ParameterBagInterface $bag * @param LoggerService $logger_service * @param DBService $service_db * @throws Exception */ - public function __construct( - ContainerInterface $container, - ParameterBagInterface $bag, - LoggerService $logger_service, - DBService $service_db - ) { + public function __construct(LoggerService $logger_service, DBService $service_db) { parent::__construct($logger_service); - $this->configs_universal = $bag; - $this->service_db = $service_db; - $this->config_yaml_load( - $this->configs_universal->get(SCHEMAS_ENUM::YAML_CODE_MANAGER), - SYS::get_env(PATHS_ENUM::PROJECT_CONFIG) - ); - #foreach (self::BUILD_STEPS as $build_section_class) { - # $this->all_build_sections[] = new $build_section_class($this); - #} + $this->service_db = $service_db; } - #NPMLibBuildSection::class, - #QAReportBuildSection::class - public function __destruct() { $this->destruct_trait_config_yaml(); } /** - * @param string $key - * @return mixed + * @return array + * @throws Exception */ - public function config_universal_get(string $key) { - return $this->configs_universal->get($key); + public function get_report_volume(): array { + var_dump('Getting report volume!'); + /** @var RepoDirectory $repo_dirs */ + $repo_dirs = $this->get_repo(EntityDirectory::class); + // TODO: Run this locally, see what the output is + $volume_dir = $repo_dirs->get_real('/v/'); + $all_files = $volume_dir->get_all_paths(); + $paths = []; + foreach ($all_files as $path) { + $paths[] = $path; + } + return $paths; } /** @@ -95,10 +81,59 @@ public function run_code_health_check(): void { // correctly matching up to the logs. $this->info('CodeBuild start!'); + UFO::copy('/quasar_source/var/nexus_local/nl.qs.html', '/v/nexus_local/nl_raw.html'); + var_dump(scandir('/v/nexus_local/')); + + + + exit(); + + $this->service_db->run_build_step_n(0); + + /** @var RepoCodeProject $repo_projects */ + $repo_projects = $this->get_repo(EntityCodeProject::class); + $project = $repo_projects->get_current_build_project(); + $tasks = $repo_projects->get_project_procedures($project); + + /** @var TaskAbstract $task */ + foreach ($tasks as $task) { + $task->run_task($project, $this); + } + + /** @var RepoDirectory $repo_dir */ + #$repo_dir = $this->get_repo(EntityDirectory::class); + #$project->cache_directories($repo_dir); + #$path_volume = $project->getPathOutput(); + #var_dump($path_volume); + #var_dump(scandir($path_volume)); + + + + + /* + #$p = new ProcessRunner(['composer', 'dump-env', 'dev'], true, '/quasar_source/applications/asset_server/code_manager/', 20, false, ProcessRunner::OUTPUT_FORMAT_LINES_CLEAN); + #$p->run(); + #var_dump($p->get_output()); + #var_dump($p->get_error_output()); + + $contents = include '/quasar_source/applications/asset_server/code_manager/.env.local.php'; + var_dump($contents); + $path_bootstrap = '/quasar_source/applications/asset_server/code_manager/config/bootstrap.php'; + $lines = UFO::get($path_bootstrap); + var_dump($lines); + $new_lines = CodeParserPHP::replace_array($lines, '_ENV', $contents); + #var_dump($new_lines); + UFO::set($path_bootstrap, $new_lines); + return; + + #$p = new ProcessRunner(['php', '-v'], true, null, 20, false, ProcessRunner::OUTPUT_FORMAT_LINES_CLEAN); + #var_dump($p->get_output()); + #exit();*/ + // Un-comment this line as a quick means to easily force update running schema update for DB. #$this->service_db->update_db_schema(); - $this->service_db->run_build_step_n(0); + #$this->service_db->run_build_step_n(0); $this->service_db->run_build_step_n(1); $this->service_db->run_build_step_n(2); $this->service_db->run_build_step_n(3); @@ -107,6 +142,22 @@ public function run_code_health_check(): void { $this->run_build_step_n(4); $this->run_build_step_n(5); + /** @var RepoMeeseeksTask $repo_tasks */ + $repo_tasks = $this->service_db->get_repo(EntityMeeseeksTask::class); + #$task = $repo_tasks->create_new_task('Pay AT&T Internet Bill', 4); + #$repo_tasks->save($task, true); + + $all_task_entities = $repo_tasks->get_all(); + $all_tasks = []; + /** @var EntityMeeseeksTask $entity_task */ + foreach ($all_task_entities as $entity_task) { + $all_tasks[] = $entity_task->as_array(); + } + $json_data = json_encode($all_tasks); + #var_dump($json_data); + #applications/asset_server/code_manager/public + #UFO::set('/quasar_source/applications/asset_server/code_manager/public/data.json', $json_data, true); + #$next_step = $this->generate_build_step('Code Manager'); #$next_step->run(); @@ -122,7 +173,7 @@ public function run_code_health_check(): void { } public function build_step0_code_build_entity(): void { - $this->repo_code_build = $this->get_repo(RepoCodeBuild::class); + $this->repo_code_build = $this->get_repo(EntityCodeBuild::class); $this->current_code_build = $this->repo_code_build->get_new_entity(); } @@ -185,55 +236,30 @@ public function build_step2_DB_Health_Checks(): void { */ public function build_step3_Temporary_Testing(): void { return; - // TODO: Use a DirectoryEntity to get the contents of the Docker volume! - #$path_volume = SYS::get_env('EXTERNAL_VOLUME'); - #var_dump($path_volume); - #var_dump(scandir($path_volume)); - - /** @var RepoDirectory $repo_directory */ - $repo = $this->get_repo(RepoDirectory::class); - $min = new Minification($repo); - $step = $min->generate_build_step('minification'); - $step->run(); + #/** @var RepoDirectory $repo_directory */ + #$repo = $this->get_repo(EntityDirectory::class); + #$min = new Minification($repo); + #$step = $min->generate_build_step('minification'); + #$step->run(); } public function build_step4_css_build(): void { /** @var RepoDirectory $repo_directory */ - $repo_directory = $this->get_repo(RepoDirectory::class); + $repo_directory = $this->get_repo(EntityDirectory::class); /** @var RepoFileType $repo_file_type */ - $repo_file_type = $this->get_repo(RepoFileType::class); + $repo_file_type = $this->get_repo(EntityFileType::class); /** @var RepoFile $repo_file */ - $repo_file = $this->get_repo(RepoFile::class); - $min = new TaskBuildWebAssets($repo_directory, $repo_file, $repo_file_type); - $step = $min->generate_build_step('minification'); + $repo_file = $this->get_repo(EntityFile::class); + $min = new TaskBuildWebAssets($repo_directory, $repo_file, $repo_file_type, $this->service_logger); + $step = $min->generate_build_step('minification'); $step->run(); - - #$min_html = #HTMLBuildSection } public function build_step5_save_code_build(): void { var_dump('Saving entity!'); - $this->repo_code_build->save_entity($this->current_code_build, true); - } - - private function print_final_results(): void { - $repo_entity_files = $this->get_repo(RepoFile::class); - $all_db_files = $repo_entity_files->get_all_entities(); - - foreach ($all_db_files as $entity_file) { - if (!$entity_file->hasParent()) { - - if ($entity_file->getType() === EntityFile::TYPE_HTML) { - var_dump($entity_file->getChild()->to_full_string($entity_file->get_child_recursively())); - } else { - var_dump($entity_file->to_full_string($entity_file->get_child_recursively())); - } - } - } - - $qa_results = new ProjectTestSuiteResult(SYS::get_env(PATHS_ENUM::QA_REPORT)); - var_dump($qa_results->get_qa_report()); + $this->repo_code_build->save($this->current_code_build, true); + // TODO: Save anything needed here, perform flush. } /** diff --git a/applications/asset_server/code_manager/src/Service/DBService.php b/applications/asset_server/code_manager/src/Service/DBService.php index 18f8d881d..6064e2f98 100644 --- a/applications/asset_server/code_manager/src/Service/DBService.php +++ b/applications/asset_server/code_manager/src/Service/DBService.php @@ -4,23 +4,23 @@ use function array_key_exists; use CodeManager\Entity\CodeManager\EntitySnapshotDB; +use CodeManager\Entity\File\EntityFileType; use CodeManager\Entity\Users\EntityEntity; -use CodeManager\Repository\Abstractions\AbstractRepo; use CodeManager\Repository\Abstractions\QueryableRepo; -use CodeManager\Repository\CodeManager\File\RepoFileType; +use CodeManager\Repository\File\RepoFileType; use CodeManager\Repository\CodeManager\RepoSnapshotDB; use CodeManager\Repository\Finance\RepoAssetFlow; use CodeManager\Repository\Users\RepoEntityEntity; use CodeManager\Service\Feature\AbstractFactoryService; use Doctrine\Common\Persistence\ObjectRepository; use Doctrine\ORM\EntityManagerInterface; -use QuasarSource\CommonFeatures\TraitEnvironmentVariablesAsFields; +use QuasarSource\CommonFeatures\TraitEnvVarsAsFields; use QuasarSource\DataStructure\FlagTable\TraitFlagTable; use QuasarSource\SQL\DBSchema; use QuasarSource\SQL\DBTable; use QuasarSource\SQL\TraitDBConnection; -use QuasarSource\Utils\Process\ProcessDoctrine as DOCTRINE; -use QuasarSource\Utils\Process\ProcessDoctrine; +use QuasarSource\Utils\DataType\UtilsTextLines as TEXT_LINES; +use QuasarSource\Utils\Process\ProcessRunner; use RuntimeException; /** @@ -28,13 +28,22 @@ */ class DBService extends AbstractFactoryService { use TraitFlagTable; - use TraitEnvironmentVariablesAsFields; + use TraitEnvVarsAsFields; use TraitDBConnection; + private const ROUTINE_SCHEMA_VALIDATE = ['php', './bin/console', 'doctrine:schema:validate', '-vvv']; + private const ROUTINE_SCHEMA_UPDATE = ['php', './bin/console', 'doctrine:schema:update', '--no-interaction', '--force', '--complete', '--dump-sql', '-vvv']; + private const FLAG_HEALTHY_DB_MAPPING = 'db_entity_mapping'; private const FLAG_HEALTHY_DB_SCHEMA = 'db_schema'; private const FLAG_DB_SCHEMA_UPDATED = 'db_schema_was_updated'; + /** @var ProcessRunner $process_db_validate */ + private $process_db_validate; + + /** @var ProcessRunner $process_db_update */ + private $process_db_update; + /** @var EntityManagerInterface */ private $entity_manager; @@ -47,22 +56,20 @@ class DBService extends AbstractFactoryService { /** @var RepoSnapshotDB $repo_db_snapshot */ private $repo_db_snapshot; - /** @var DOCTRINE $cached_doctrine_cmd */ - private $cached_doctrine_cmd; - /** @var bool */ private $env_db_checks; /** @var bool */ private $env_db_checks_forced; /** @var string $env_path_transactions_file */ private $env_path_transactions_file; - + /** @var string $env_path_code_manager */ + private $env_path_code_manager; // TODO: REMOVE? This is the 'singleton' entity from repo_snapshotDB /** @var EntitySnapshotDB $db_snapshot */ private $db_snapshot; - + # --------------------------------------------------- M A G I C ---------------------------------------------------- /** * @param LoggerService $logger * @param EntityManagerInterface $entity_manager @@ -70,19 +77,21 @@ class DBService extends AbstractFactoryService { public function __construct(LoggerService $logger, EntityManagerInterface $entity_manager) { parent::__construct($logger); $this->envs_set_as_bool(['DB_CHECKS' => 'env_db_checks', 'DB_CHECKS_FORCED' => 'env_db_checks_forced']); - $this->envs_set_as_str(['DB_DATA_CSV' => 'env_path_transactions_file']); + $this->envs_set_as_str(['DB_DATA_CSV' => 'env_path_transactions_file', 'PATH_DIRECTORY_CODE_MANAGER' => 'env_path_code_manager']); $this->entity_manager = $entity_manager; } public function __destruct() { - var_dump('DBService destruct!'); $this->trait_destruct_db_connection(); + unset($this->process_db_validate, $this->process_db_update); } + # -------------------------------------------------- P U B L I C --------------------------------------------------- public function update_db_schema(): void { - if ($this->cached_doctrine_cmd === null) { + if ($this->process_db_update === null) { $this->log('DBService is running Doctrine schema update.'); - $this->cached_doctrine_cmd = DOCTRINE::execute_update_and_return_object(); + $this->process_db_update = $this->create_doctrine_cmd(self::ROUTINE_SCHEMA_UPDATE); + $this->cmd_run_and_error_check($this->process_db_update); } else { $this->log('DBService has already ran Doctrine schema update this session.'); } @@ -92,8 +101,8 @@ public function update_db_schema(): void { public function build_step0_LazyLoad(): void { $this->trait_construct_db_connection($this->entity_manager); - $this->get_repo(RepoFileType::class); - $this->repo_db_snapshot = $this->get_repo(RepoSnapshotDB::class); + $this->get_repo(EntityFileType::class); + $this->repo_db_snapshot = $this->get_repo(EntitySnapshotDB::class); $this->queries_schema = $this->repo_db_snapshot->get_queries_db_schema(); } @@ -117,21 +126,29 @@ public function build_step1_on_failed(): void { } public function build_step2_DB_Health_Check(): void { - // TODO: REMOVE FLAGS, MOVE THEM INTO MORE NICHE OBJECT! - // TODO: REMOVE FLAGS, MOVE THEM INTO MORE NICHE OBJECT! - // TODO: REMOVE FLAGS, MOVE THEM INTO MORE NICHE OBJECT! - - if ($this->env_db_checks && $this->repo_db_snapshot->was_current_entity_created()) { - [$mapping, $schema] = DOCTRINE::execute_validate_checks(); - $this->flag_set(self::FLAG_HEALTHY_DB_MAPPING, $mapping); - $this->flag_set(self::FLAG_HEALTHY_DB_SCHEMA, $schema); + if ($this->process_db_validate === null) { + $this->process_db_validate = $this->create_doctrine_cmd(self::ROUTINE_SCHEMA_VALIDATE); + } + $this->cmd_run_and_error_check($this->process_db_validate); + $output = $this->process_db_validate->get_output(); + $mapping_okay = TEXT_LINES::does_line_after_pattern_contain_text($output, ['Mapping', '-------'], '[OK]'); + $this->flag_set(self::FLAG_HEALTHY_DB_MAPPING, $mapping_okay); + if ($mapping_okay) { + $this->log('The DB Mapping is healthy.'); + $schema_okay = TEXT_LINES::does_line_after_pattern_contain_text($output, ['Database', '--------'], '[OK]'); + $this->flag_set(self::FLAG_HEALTHY_DB_SCHEMA, $schema_okay); + if ($schema_okay) { + $this->log('The DB Schema is healthy.'); + } else { + $this->log('The DB Schema is not healthy.'); + } + } else { + $this->log('The DB Mapping is not healthy.'); + } } else { $this->log('Skipping DB health checks!'); - $this->flags_set_all( - [self::FLAG_HEALTHY_DB_MAPPING, self::FLAG_HEALTHY_DB_SCHEMA], - true - ); + $this->flags_set_all_on([self::FLAG_HEALTHY_DB_MAPPING, self::FLAG_HEALTHY_DB_SCHEMA]); } if ($this->flag_is_off(self::FLAG_HEALTHY_DB_MAPPING)) { throw new RuntimeException('DB Mapping is NOT healthy'); @@ -147,15 +164,15 @@ public function build_step3_DB_Snapshot_Entity(): void { $this->log('Flag HealthDB Schema was off so running Update DB Schema!'); $this->update_db_schema(); } - $this->repo_db_snapshot->save_entity($this->db_snapshot, true); + $this->repo_db_snapshot->save($this->db_snapshot, true); } } public function build_step4_Finance_Data_Processing(): void { /** @var RepoAssetFlow $repo_cash_flows */ - #$repo_cash_flows = $this->get_repo(RepoAssetFlow::class); + #$repo_cash_flows = $this->get_repo(EntityAssetFlow::class); /** @var RepoEntityEntity $repo_users $repo_users */ - #$repo_users = $this->get_repo(RepoEntityEntity::class); + #$repo_users = $this->get_repo(EntityEntity::class); /** @var EntityEntity $user_base */ #$user_base = $repo_users->find_user_match($this, 'vlad'); #$repo_cash_flows->parse_bank_transactions_for($user_base, $this->env_path_transactions_file); @@ -164,10 +181,10 @@ public function build_step4_Finance_Data_Processing(): void { // ------------------------------------------------ G E T T E R S ------------------------------------------------ /** - * @return ProcessDoctrine|null + * @return ProcessRunner|null */ - public function get_doctrine_process(): ?ProcessDoctrine { - return $this->cached_doctrine_cmd; + public function get_doctrine_process(): ?ProcessRunner { + return $this->process_db_update; } /** @@ -190,22 +207,45 @@ public function get_db_table_by_name(string $db_table_name): DBTable { // ----------------------------------------- I N T E R F A C E {OwnsRepo} ------------------------------------------ /** - * @param string $repo_key + * @param string $entity_class * @return ObjectRepository */ - public function get_repo(string $repo_key): ObjectRepository { - if (!array_key_exists($repo_key, $this->repos)) { - /** @var AbstractRepo $repo_key */ - $entity_class = $repo_key::ENTITY_CLASS; - /** @noinspection PhpUndefinedFieldInspection */ - $this->repos[$repo_key] = $this->entity_manager->getRepository($entity_class); - $repo = $this->repos[$repo_key]; - if ($repo instanceof QueryableRepo) { - $repo->set_db_service($this); - } - return $repo; + public function get_repo(string $entity_class): ObjectRepository { + if (!array_key_exists($entity_class, $this->repos)) { + $this->repos[$entity_class] = $this->entity_manager->getRepository($entity_class); + $this->repos[$entity_class]->set_db_service($this); + } + return $this->repos[$entity_class]; + } + + # ------------------------------------------------- P R I V A T E -------------------------------------------------- + + /** + * @param array $cmd + * @return ProcessRunner + */ + private function create_doctrine_cmd(array $cmd): ProcessRunner { + return new ProcessRunner( + $cmd, + false, + $this->env_path_code_manager, + 20, + false, + ProcessRunner::OUTPUT_FORMAT_LINES_CLEAN + ); + } + + /** + * @param ProcessRunner $cmd + * @return void + */ + private function cmd_run_and_error_check(ProcessRunner $cmd): void { + $cmd->run(); + if (!$cmd->was_successful()) { + var_dump($cmd->get_output()); + var_dump($cmd->get_error_output()); + throw new RuntimeException('Investigate db process'); } - return $this->repos[$repo_key]; } } diff --git a/applications/asset_server/code_manager/src/Service/Feature/Config/InterfaceConfigUniversal.php b/applications/asset_server/code_manager/src/Service/Feature/Config/InterfaceConfigUniversal.php deleted file mode 100644 index 69354599e..000000000 --- a/applications/asset_server/code_manager/src/Service/Feature/Config/InterfaceConfigUniversal.php +++ /dev/null @@ -1,17 +0,0 @@ -repo_directory = $repo_directory; - $this->envs_set_as_str(['LOG_FILE' => 'env_log_file']); - } - - /** - * @throws Exception - */ - public function build_step0_task_css(): void { - var_dump('TASK 0: BUILD CSS'); - var_dump('Get assets from {' . $this->env_build_css . '}'); - - $directory = $this->repo_directory->get_real($this->env_build_css); - - $files = $directory->getFiles(); - - foreach ($files as $file) { - var_dump((string) $file); - } - - // TODO: Sync directory lol - - } - -} diff --git a/applications/asset_server/code_manager/src/Service/Task/TaskAbstract.php b/applications/asset_server/code_manager/src/Service/Task/TaskAbstract.php new file mode 100644 index 000000000..379f724ad --- /dev/null +++ b/applications/asset_server/code_manager/src/Service/Task/TaskAbstract.php @@ -0,0 +1,62 @@ +logger = null; + $this->project = null; + $this->code_builder = null; + } + # -------------------------------------------------- P U B L I C --------------------------------------------------- + + /** + * @param EntityCodeProject $project + * @param CodeBuilderService $code_builder + * @throws Exception + */ + public function run_task(EntityCodeProject $project, CodeBuilderService $code_builder): void { + $this->logger = $code_builder->service_get_logger(); + $this->project = $project; + $this->code_builder = $code_builder; + $this->task_prepare(); + $this->task_execute(); + } + + # ----------------------------------------------- P R O T E C T E D ------------------------------------------------ + + /** + * @throws Exception + */ + abstract protected function task_prepare(): void; + + /** + * @throws Exception + */ + abstract protected function task_execute(): void; + + # ------------------------------------------------- P R I V A T E -------------------------------------------------- +} diff --git a/applications/asset_server/code_manager/src/Service/Task/TaskBuildWebAssets.php b/applications/asset_server/code_manager/src/Service/Task/TaskBuildWebAssets.php index f8d54ff0e..b989ff1eb 100644 --- a/applications/asset_server/code_manager/src/Service/Task/TaskBuildWebAssets.php +++ b/applications/asset_server/code_manager/src/Service/Task/TaskBuildWebAssets.php @@ -2,19 +2,13 @@ namespace CodeManager\Service\Task; -use CodeManager\Entity\CodeManager\File\EntityFile; -use CodeManager\Entity\CodeManager\File\EntityFileType; -use CodeManager\Repository\CodeManager\File\RepoDirectory; -use CodeManager\Repository\CodeManager\File\RepoFile; -use CodeManager\Repository\CodeManager\File\RepoFileType; -use Exception; -use QuasarSource\CommonFeatures\TraitEnvironmentVariablesAsFields; +use CodeManager\Repository\File\RepoDirectory; +use CodeManager\Repository\File\RepoFile; +use CodeManager\Repository\File\RepoFileType; +use CodeManager\Service\LoggerService; +use QuasarSource\CommonFeatures\TraitEnvVarsAsFields; use QuasarSource\DataStructure\Factory\TraitFactoryBuildStep; -use QuasarSource\Utils\Process\UtilsProcess; -use RuntimeException; -use QuasarSource\Utils\DataType\UtilsString as STR; -use QuasarSource\Utils\File\UtilsPath as PATH; -use QuasarSource\Utils\File\UtilsFile as UFO; +use QuasarSource\Utils\Process\ProcessRunner; /** * Class TaskBuildWebAssets @@ -22,14 +16,13 @@ */ final class TaskBuildWebAssets { # -------------------------------------------------- T R A I T S --------------------------------------------------- - use TraitEnvironmentVariablesAsFields; + use TraitEnvVarsAsFields; use TraitFactoryBuildStep; - # ----------------------------------------------- C O N S T A N T S ------------------------------------------------ - private const PRE_PROCESS = '#pre-process-'; - private const PATTERN_MANIFEST = '/*' . self::PRE_PROCESS . 'manifest'; - private const PATTERN_SUB_MANIFEST_REPLACE = self::PATTERN_MANIFEST . '{default}*/'; # -------------------------------------------------- F I E L D S --------------------------------------------------- + /** @var LoggerService $logger */ + private $logger; + /** @var RepoDirectory $repo_directory */ private $repo_directory; @@ -39,10 +32,12 @@ final class TaskBuildWebAssets { /** @var RepoFileType $repo_file_type */ private $repo_file_type; - private $env_build_css; - private $env_build_html; + /** @var string $default_web_manifest */ + private $default_web_manifest; + private $env_path_output; - private $env_node_file_minifier; + private $env_path_node; + private $env_path_node_libs; # --------------------------------------------------- M A G I C ---------------------------------------------------- @@ -50,100 +45,35 @@ final class TaskBuildWebAssets { * @param RepoDirectory $repo_directory * @param RepoFile $repo_file * @param RepoFileType $repo_file_type + * @param LoggerService $logger */ - public function __construct(RepoDirectory $repo_directory, RepoFile $repo_file, RepoFileType $repo_file_type) { + public function __construct(RepoDirectory $repo_directory, RepoFile $repo_file, RepoFileType $repo_file_type, LoggerService $logger) { $this->repo_directory = $repo_directory; $this->repo_file = $repo_file; $this->repo_file_type = $repo_file_type; + $this->logger = $logger; $this->envs_set_as_str([ - 'PATH_DIR_BUILD_CSS_DATA' => 'env_build_css', - 'PATH_DIR_BUILD_HTML_DATA' => 'env_build_html', - 'PATH_BUILD_CSS_OUTPUT' => 'env_path_output', - 'PATH_NODE_MINIFY_FILE' => 'env_node_file_minifier' + 'PATH_DIRECTORY_NODE' => 'env_path_node', + 'PATH_DIRECTORY_NODE_JS_LIBS' => 'env_path_node_libs' ]); } public function __destruct() { $this->trait_destruct_factory_build_step(); unset($this->repo_file, $this->repo_file_type, $this->repo_directory, - $this->env_build_css, $this->env_build_html, $this->env_path_output, $this->env_node_file_minifier); + $this->env_build_css, $this->env_path_output, $this->env_node_file_minifier); } # -------------------------------------------------- P U B L I C --------------------------------------------------- - /** - * @throws Exception - */ - public function build_step0_task_css(): void { - $directory = $this->repo_directory->get_real($this->env_build_css); - /** @var EntityFile $file */ - foreach ($directory->getFiles() as $file) { - // TODO: Potentially also check that the physical file exists - $this->repo_file->ensure_file_has_gzipped_child( - $this->ensure_file_has_minified_child($file), $this->env_path_output - ); - } - } - - /** - * @throws Exception - */ - public function build_step1_task_html(): void { - $directory = $this->repo_directory->get_real($this->env_build_html); - /** @var EntityFile $file */ - foreach ($directory->getFiles() as $file) { - $this->process_html_file($file); - } + public function build_step1_task_js(): void { + $cmd = ProcessRunner::execute(['npm', 'run-script', 'build'], $this->env_path_node); + var_dump($cmd->get_output()); + var_dump($cmd->get_error_output()); } # ----------------------------------------------- P R O T E C T E D ------------------------------------------------ - /** - * @param EntityFile $file - * @return EntityFile - */ - protected function ensure_file_has_minified_child(EntityFile $file): EntityFile { - if (!$file->hasChild()) { - $needed_type = $this->repo_file_type->get_type_as_minified($file); - $output_path = $this->env_path_output . STR::replace(PATH::get_file_full_name($file->getFullPath()), $file->getFileTypeString(), $needed_type->getAsString()); - $this->minify($file, $output_path); - return $this->repo_file->create_new_fully_cached_entity_child($file, $needed_type, $output_path); - } - return $file->getChild(); - } - # ------------------------------------------------- P R I V A T E -------------------------------------------------- - /** - * @param EntityFile $file - */ - private function process_html_file(EntityFile $file): void { - var_dump('Need to run process for the HTML file {' . $file->getFullPath() . '}'); - - $lines = UFO::get($file->getFullPath()); - foreach ($lines as $line) { - if (STR::has($line, self::PATTERN_MANIFEST)) { - $processed_lines[] = STR::replace($line, self::PATTERN_SUB_MANIFEST_REPLACE, $this->web_manifest_default); - } - } - - } - - /** - * @param EntityFile $file - * @param string $output_path - */ - private function minify(EntityFile $file, string $output_path): void { - $file_type = $file->getFileType(); - $file_type_group = $file_type->getEntityType(); - switch ($file_type_group) { - case EntityFileType::GROUP_CSS: - case EntityFileType::GROUP_HTML: - UtilsProcess::run_cmd(['node', $this->env_node_file_minifier, '-i', $file->getFullPath(), '-o', $output_path]); - break; - default: - throw new RuntimeException('Unable to minify the provided file {' . $file->getFullPath() . '}'); - } - } - } diff --git a/applications/asset_server/code_manager/src/Service/Task/TaskFile.php b/applications/asset_server/code_manager/src/Service/Task/TaskFile.php new file mode 100644 index 000000000..84f4af321 --- /dev/null +++ b/applications/asset_server/code_manager/src/Service/Task/TaskFile.php @@ -0,0 +1,68 @@ +repo_directory = null; + $this->repo_file = null; + $this->repo_file_type = null; + $this->directory_assets = null; + parent::__destruct(); + } + # -------------------------------------------------- P U B L I C --------------------------------------------------- + + # ----------------------------------------------- P R O T E C T E D ------------------------------------------------ + + /** + * @throws Exception + */ + protected function task_prepare(): void { + $this->repo_directory = $this->code_builder->get_repo(EntityDirectory::class); + $this->repo_file = $this->code_builder->get_repo(EntityFile::class); + $this->repo_file_type = $this->code_builder->get_repo(EntityFileType::class); + $this->directory_assets = $this->repo_directory->get_real($this->project->getPathAssets()); + } + + /** + * @param EntityCodeProject $code_project + * @return EntityDirectory + * @throws Exception + */ + protected function get_directory_assets(EntityCodeProject $code_project): EntityDirectory { + return $this->repo_directory->get_real($code_project->getPathAssets()); + } + + # ------------------------------------------------- P R I V A T E -------------------------------------------------- + +} diff --git a/applications/asset_server/code_manager/src/Service/Task/TaskSyncCSS.php b/applications/asset_server/code_manager/src/Service/Task/TaskSyncCSS.php new file mode 100644 index 000000000..50b68adea --- /dev/null +++ b/applications/asset_server/code_manager/src/Service/Task/TaskSyncCSS.php @@ -0,0 +1,32 @@ +get_directory_assets($this->project); + $files_css = $assets->get_files_with_extension_name('.css'); + + foreach ($files_css as $file) { + $this->logger->log('Syncing{' . $file . '}'); + $this->repo_file->ensure_file_has_minified_child($file, $this->project->getPathVar()); + } + } + + # ----------------------------------------------- P R O T E C T E D ------------------------------------------------ + # ------------------------------------------------- P R I V A T E -------------------------------------------------- +} diff --git a/applications/asset_server/code_manager/src/Service/Task/TaskSyncHTML.php b/applications/asset_server/code_manager/src/Service/Task/TaskSyncHTML.php new file mode 100644 index 000000000..833a70c5c --- /dev/null +++ b/applications/asset_server/code_manager/src/Service/Task/TaskSyncHTML.php @@ -0,0 +1,72 @@ +get_directory_assets($this->project); + $files_html = $assets->get_files_with_extension_name('.html'); + + /** @var EntityFile $file */ + foreach ($files_html as $file) { + $this->logger->log('Syncing{' . $file . '}'); + + if (!$file->hasChild()) { + $needed_type = $this->repo_file_type->get_type_as_processed($file); + $output_path = $this->project->getPathVar() . $file->get_name_as_type($needed_type); + $processed_child = $this->process_html_file($file, $output_path); + } else { + $processed_child = $file->getChild(); + } + + $minified_child = $this->repo_file->ensure_file_has_minified_child($processed_child, $this->project->getPathVar()); + $this->repo_file->ensure_file_has_gzipped_child($minified_child, $this->project->getPathVar()); + } + } + + # ----------------------------------------------- P R O T E C T E D ------------------------------------------------ + + # ------------------------------------------------- P R I V A T E -------------------------------------------------- + + /** + * @param EntityFile $file + * @param string $output_path + * @return EntityFile + */ + private function process_html_file(EntityFile $file, string $output_path): EntityFile { + $file_css = $this->repo_file->find_matching_file_with_alt_extension($file, '.css'); + $html = CodeSpawnerHTML::spawn() + ->title($this->project->getNameFull()) + ->manifest($this->project->get_web_manifest(true)) + ->style($file_css->getChild()->get_contents(true)) + ->indent() + ->get_contents(); + + $modified_lines = TEXT_LINES::insert_lines_inbetween($file->get_contents(), self::PATTERN_START, self::PATTERN_END, $html); + + UFO::set($output_path, $modified_lines, true); + + return $this->repo_file->create_new_fully_cached_entity_child($file, $this->repo_file_type->get_type_as_processed($file), $output_path); + } +} diff --git a/applications/asset_server/code_manager/src/Service/Task/TaskSyncJS.php b/applications/asset_server/code_manager/src/Service/Task/TaskSyncJS.php new file mode 100644 index 000000000..c8ed4741a --- /dev/null +++ b/applications/asset_server/code_manager/src/Service/Task/TaskSyncJS.php @@ -0,0 +1,37 @@ +env_set_as_str('PATH_DIRECTORY_NODE', 'env_path_node'); + } + + /** + * @throws Exception + */ + protected function task_execute(): void { + $cmd = ProcessRunner::execute_must_pass(['npm', 'run-script', 'build'], $this->env_path_node); + $output = $cmd->get_output(); + } + + # ----------------------------------------------- P R O T E C T E D ------------------------------------------------ + # ------------------------------------------------- P R I V A T E -------------------------------------------------- +} diff --git a/applications/asset_server/code_manager/symfony.lock b/applications/asset_server/code_manager/symfony.lock index dd89321c5..e9836e3be 100644 --- a/applications/asset_server/code_manager/symfony.lock +++ b/applications/asset_server/code_manager/symfony.lock @@ -245,6 +245,15 @@ "symfony/var-exporter": { "version": "v4.2.7" }, + "symfony/web-server-bundle": { + "version": "3.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "3.3", + "ref": "dae9b39fd6717970be7601101ce5aa960bf53d9a" + } + }, "symfony/yaml": { "version": "v4.2.7" }, diff --git a/applications/asset_server/js/webpack.config.js b/applications/asset_server/js/webpack.config.js index 745c79348..26347a06f 100644 --- a/applications/asset_server/js/webpack.config.js +++ b/applications/asset_server/js/webpack.config.js @@ -3,8 +3,8 @@ module.exports = { entry: '/quasar_source/libraries/front_end/hello_world.js', output: { - filename: 'hello_world_output.js', - path: '/quasar_source/applications/asset_server/code_manager/public' + filename: 'nl.js', + path: '/quasar_source/var/nexus_local/' }, mode: 'production', resolve: { diff --git a/applications/asset_server/src/asset_server.sh b/applications/asset_server/src/asset_server.sh index b497646a4..d0ced8944 100755 --- a/applications/asset_server/src/asset_server.sh +++ b/applications/asset_server/src/asset_server.sh @@ -1,26 +1,34 @@ #!/usr/bin/env bash #----------------------------------------------------------------------------------------------------------------------- +QS_APPS='/quasar_source/applications/' +QS_VAR='/quasar_source/var/' +QS_ASSETS='/quasar_source/assets/' +QS_LIBS='/quasar_source/libraries/' +QS_LIBS_NODE=${QS_LIBS}'node/' +QS_ASSET_SERVER=${QS_APPS}'asset_server/' + export PATH_DIRECTORY_PROJECT_BASE='/quasar_source/' -export PATH_DIRECTORY_CODE_MANAGER='/quasar_source/applications/asset_server/code_manager/' -export PATH_DIRECTORY_NODE='/quasar_source/applications/asset_server/js/' +export PATH_DIRECTORY_CODE_MANAGER=${QS_APPS}'asset_server/code_manager/' +export PATH_DIRECTORY_NODE=${QS_APPS}'asset_server/js/' +export PATH_DIRECTORY_NODE_JS_LIBS='/quasar_source/libraries/node/' export PATH_QA_REPORT=${PATH_DIRECTORY_CODE_MANAGER}'report.xml' export PATH_PROJECT_CONFIGS='/quasar_source/configs/code_manager.yml' -export PATH_PROJECT_BUNDLES='/quasar_source/applications/asset_server/code_manager/config/bundles.php' -export PATH_NODE_MINIFY_HTML='/quasar_source/libraries/node/minifier_html.js' -export PATH_NODE_MINIFY_CSS='/quasar_source/libraries/node/minifier_css.js' -export PATH_NODE_MINIFY_JS='/quasar_source/libraries/node/minifier_css.js' +export PATH_PROJECT_BUNDLES=${QS_APPS}'asset_server/code_manager/config/bundles.php' +export PATH_NODE_MINIFY_HTML=${QS_LIBS_NODE}'minifier_html.js' +export PATH_NODE_MINIFY_CSS=${QS_LIBS_NODE}'minifier_css.js' +export PATH_NODE_MINIFY_JS=${QS_LIBS_NODE}'minifier_css.js' export SYMFONY_ENV='dev' export PATH_RELATIVE_NODE_MINIFY_HTML='applications/asset_server/js/minify_html_file.js' -export PATH_NODE_MINIFY_CSS='/quasar_source/applications/asset_server/js/minify_css_file.js' +export PATH_NODE_MINIFY_CSS=${QS_ASSET_SERVER}'js/minify_css_file.js' # ---- Node Scripting ---- -export PATH_NODE_MINIFY_FILE='/quasar_source/applications/asset_server/js/script_minify_file.js' +export PATH_NODE_MINIFY_FILE=${QS_ASSET_SERVER}'js/script_minify_file.js' # ---- DB ----- -#export DATABASE_URL='pgsql://postgres:password@postgres_server:5432/postgres' -export DATABASE_URL='pgsql://postgres:password@172.18.0.2:5432/postgres' +export DATABASE_URL='pgsql://postgres:password@postgres_server:5432/postgres' +#export DATABASE_URL='pgsql://postgres:password@172.18.0.2:5432/postgres' export DB_NAME='postgres' -export DB_MIGRATIONS='/quasar_source/var/db/migrations' -export DB_EXTRA_DATA='/quasar_source/var/db/extra_data' -export DB_DATA_CSV='/quasar_source/var/db/extra_data/data.csv' +export DB_MIGRATIONS=${QS_VAR}'db/migrations' +export DB_EXTRA_DATA=${QS_VAR}'db/extra_data' +export DB_DATA_CSV=${QS_VAR}'db/extra_data/data.csv' # ---- FTP ---- export FTP_HOST='192.168.1.170' export FTP_USER='l0_c4_m4' @@ -28,21 +36,16 @@ export FTP_PASS='sudoadmin' export FTP_TIMEOUT='5' # Default{90} (seconds) export FTP_PORT='21' # Default{21} # ---- Session Settings ---- -export EXTERNAL_VOLUME='/v/' +export BUILD_PROJECT='NexusLocal' export DB_CHECKS='true' export DB_CHECKS_FORCED='false' # ---- B U I L D S ---- -export PATH_DIR_BUILD_HTML_DATA='/quasar_source/assets/html/' -export PATH_DIR_BUILD_CSS_DATA='/quasar_source/assets/css/' -#'/v/' -export PATH_BUILD_CSS_OUTPUT='/quasar_source/var/temp_test/' -export PATH_BUILD_HTML_OUTPUT='/quasar_source/var/temp_test/' -export LOG_FILE='/quasar_source/applications/asset_server/code_manager/var/log/dev.log' +export LOG_FILE=${QS_ASSET_SERVER}'code_manager/var/log/dev.log' #----------------------------------------------------------------------------------------------------------------------- BASH_LIBS='/quasar_source/libraries/bash/' source ${BASH_LIBS}common.sh; source ${BASH_LIBS}utils_composer.sh; -source '/quasar_source/applications/asset_server/src/utils_console.sh' +source ${QS_ASSET_SERVER}'src/utils_console.sh' #----------------------------------------------------------------------------------------------------------------------- cd ${PATH_DIRECTORY_CODE_MANAGER} #----------------------------------------------------------------------------------------------------------------------- @@ -54,18 +57,43 @@ CMD_DEPLOYER_RUN_ALL_TESTS="run_all_tests -vvv" CMD_DEPLOYER_FULL_BUILD="full_build -vvv" CMD_DEPLOYER_DEBUG="debug -vvv" CMD_DEPLOYER_BUILD_NEXUS_COURIER="build_nexus_courier -vvv" -FILE_CSS_NEXUS_LOCAL=/quasar_source/assets/css/nexus_local.css -FILE_CSS_NEXUS_LOCAL_OUTPUT=/quasar_source/var/web_assets/nexus_local.min.css -FILE_CSS_NEXUS_LOCAL_OUTPUT_FINAL=/quasar_source/var/web_assets/nexus_local.min.css.gz #${RUN_DEPLOYER} ${CMD_DEPLOYER_FULL_BUILD} #${RUN_DEPLOYER} ${CMD_DEPLOYER_RUN_ALL_TESTS} #${RUN_DEPLOYER} ${CMD_DEPLOYER_DEBUG} #${RUN_DEPLOYER} ${CMD_DEPLOYER_BUILD_NEXUS_COURIER} -#php -S "0.0.0.0:1337" +#cd /tmp/; +#pwd; +#ls; +#mkdir php-opcache; +#ls; + +cd /quasar_source/applications/asset_server/code_manager; +#composer require symfony/web-server-bundle +#symfony serve --no-tls +php bin/console list +#php bin/console server:start *:80; + +#php -S "0.0.0.0:80" + +#echo 'SLEEPING!' +#sleep 10000000 + +#console_list +#console_debug #php -v +#node -v +#npm -v + +#composer_optimize +#console_db_schema_update +#console_code_manager + +#cd ${QS_ASSET_SERVER}'js/' +#pwd +#npm run-script build #composer_install #console_list @@ -73,10 +101,11 @@ FILE_CSS_NEXUS_LOCAL_OUTPUT_FINAL=/quasar_source/var/web_assets/nexus_local.min. #composer -V #composer self-update -#composer_optimize -#console_db_schema_update +#echo 'sleeping...' +#sleep 10000000 + #console_db_schema_validate -console_code_manager +#composer_test #stdbuf -oL ${RUN_CONSOLE_CMD} code:health_check -vvv | # while IFS= read -r line diff --git a/applications/asset_server/src/utils_console.sh b/applications/asset_server/src/utils_console.sh index 738fb76cb..5d18135ca 100755 --- a/applications/asset_server/src/utils_console.sh +++ b/applications/asset_server/src/utils_console.sh @@ -6,6 +6,10 @@ console_code_manager () { ${RUN_CONSOLE_CMD} code:health_check -vvv } +console_debug() { + ${RUN_CONSOLE_CMD} debug:config +} + console_list () { ${RUN_CONSOLE_CMD} list } diff --git a/applications/asset_server/src/www.conf b/applications/asset_server/src/www.conf new file mode 100644 index 000000000..50addbdf2 --- /dev/null +++ b/applications/asset_server/src/www.conf @@ -0,0 +1,423 @@ +; Start a new pool named 'www'. +; the variable $pool can be used in any directive and will be replaced by the +; pool name ('www' here) +[www] + +; Per pool prefix +; It only applies on the following directives: +; - 'access.log' +; - 'slowlog' +; - 'listen' (unixsocket) +; - 'chroot' +; - 'chdir' +; - 'php_values' +; - 'php_admin_values' +; When not set, the global prefix (or /usr) applies instead. +; Note: This directive can also be relative to the global prefix. +; Default Value: none +;prefix = /path/to/pools/$pool + +; Unix user/group of processes +; Note: The user is mandatory. If the group is not set, the default user's group +; will be used. +user = _www +group = _www + +; The address on which to accept FastCGI requests. +; Valid syntaxes are: +; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on +; a specific port; +; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on +; a specific port; +; 'port' - to listen on a TCP socket to all addresses +; (IPv6 and IPv4-mapped) on a specific port; +; '/path/to/unix/socket' - to listen on a unix socket. +; Note: This value is mandatory. +listen = 0.0.0.0:80 + +; Set listen(2) backlog. +; Default Value: 511 (-1 on FreeBSD and OpenBSD) +;listen.backlog = 511 + +; Set permissions for unix socket, if one is used. In Linux, read/write +; permissions must be set in order to allow connections from a web server. Many +; BSD-derived systems allow connections regardless of permissions. +; Default Values: user and group are set as the running user +; mode is set to 0660 +listen.owner = _www +listen.group = _www +;listen.mode = 0660 +; When POSIX Access Control Lists are supported you can set them using +; these options, value is a comma separated list of user/group names. +; When set, listen.owner and listen.group are ignored +;listen.acl_users = apache +;listen.acl_groups = apache + +; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect. +; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original +; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address +; must be separated by a comma. If this value is left blank, connections will be +; accepted from any ip address. +; Default Value: any +;listen.allowed_clients = 127.0.0.1 + +; Specify the nice(2) priority to apply to the pool processes (only if set) +; The value can vary from -19 (highest priority) to 20 (lower priority) +; Note: - It will only work if the FPM master process is launched as root +; - The pool processes will inherit the master process priority +; unless it specified otherwise +; Default Value: no set +process.priority = -19 + +; Set the process dumpable flag (PR_SET_DUMPABLE prctl) even if the process user +; or group is differrent than the master process user. It allows to create process +; core dump and ptrace the process for the pool user. +; Default Value: no +process.dumpable = yes + +; Choose how the process manager will control the number of child processes. +; Possible Values: +; static - a fixed number (pm.max_children) of child processes; +; dynamic - the number of child processes are set dynamically based on the +; following directives. With this process management, there will be +; always at least 1 children. +; pm.max_children - the maximum number of children that can +; be alive at the same time. +; pm.start_servers - the number of children created on startup. +; pm.min_spare_servers - the minimum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is less than this +; number then some children will be created. +; pm.max_spare_servers - the maximum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is greater than this +; number then some children will be killed. +; ondemand - no children are created at startup. Children will be forked when +; new requests will connect. The following parameter are used: +; pm.max_children - the maximum number of children that +; can be alive at the same time. +; pm.process_idle_timeout - The number of seconds after which +; an idle process will be killed. +; Note: This value is mandatory. +pm = dynamic + +; The number of child processes to be created when pm is set to 'static' and the +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. +; This value sets the limit on the number of simultaneous requests that will be +; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. +; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' +; Note: This value is mandatory. +pm.max_children = 10 + +; The number of child processes created on startup. +; Note: Used only when pm is set to 'dynamic' +; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 +pm.start_servers = 4 + +; The desired minimum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.min_spare_servers = 1 + +; The desired maximum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.max_spare_servers = 5 + +; The number of seconds after which an idle process will be killed. +; Note: Used only when pm is set to 'ondemand' +; Default Value: 10s +;pm.process_idle_timeout = 30s; + +; The number of requests each child process should execute before respawning. +; This can be useful to work around memory leaks in 3rd party libraries. For +; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. +; Default Value: 0 +;pm.max_requests = 500 + +; The URI to view the FPM status page. If this value is not set, no URI will be +; recognized as a status page. It shows the following informations: +; pool - the name of the pool; +; process manager - static, dynamic or ondemand; +; start time - the date and time FPM has started; +; start since - number of seconds since FPM has started; +; accepted conn - the number of request accepted by the pool; +; listen queue - the number of request in the queue of pending +; connections (see backlog in listen(2)); +; max listen queue - the maximum number of requests in the queue +; of pending connections since FPM has started; +; listen queue len - the size of the socket queue of pending connections; +; idle processes - the number of idle processes; +; active processes - the number of active processes; +; total processes - the number of idle + active processes; +; max active processes - the maximum number of active processes since FPM +; has started; +; max children reached - number of times, the process limit has been reached, +; when pm tries to start more children (works only for +; pm 'dynamic' and 'ondemand'); +; Value are updated in real time. +; Example output: +; pool: www +; process manager: static +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 62636 +; accepted conn: 190460 +; listen queue: 0 +; max listen queue: 1 +; listen queue len: 42 +; idle processes: 4 +; active processes: 11 +; total processes: 15 +; max active processes: 12 +; max children reached: 0 +; +; By default the status page output is formatted as text/plain. Passing either +; 'html', 'xml' or 'json' in the query string will return the corresponding +; output syntax. Example: +; http://www.foo.bar/status +; http://www.foo.bar/status?json +; http://www.foo.bar/status?html +; http://www.foo.bar/status?xml +; +; By default the status page only outputs short status. Passing 'full' in the +; query string will also return status for each pool process. +; Example: +; http://www.foo.bar/status?full +; http://www.foo.bar/status?json&full +; http://www.foo.bar/status?html&full +; http://www.foo.bar/status?xml&full +; The Full status returns for each process: +; pid - the PID of the process; +; state - the state of the process (Idle, Running, ...); +; start time - the date and time the process has started; +; start since - the number of seconds since the process has started; +; requests - the number of requests the process has served; +; request duration - the duration in µs of the requests; +; request method - the request method (GET, POST, ...); +; request URI - the request URI with the query string; +; content length - the content length of the request (only with POST); +; user - the user (PHP_AUTH_USER) (or '-' if not set); +; script - the main script called (or '-' if not set); +; last request cpu - the %cpu the last request consumed +; it's always 0 if the process is not in Idle state +; because CPU calculation is done when the request +; processing has terminated; +; last request memory - the max amount of memory the last request consumed +; it's always 0 if the process is not in Idle state +; because memory calculation is done when the request +; processing has terminated; +; If the process is in Idle state, then informations are related to the +; last request the process has served. Otherwise informations are related to +; the current request being served. +; Example output: +; ************************ +; pid: 31330 +; state: Running +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 63087 +; requests: 12808 +; request duration: 1250261 +; request method: GET +; request URI: /test_mem.php?N=10000 +; content length: 0 +; user: - +; script: /home/fat/web/docs/php/test_mem.php +; last request cpu: 0.00 +; last request memory: 0 +; +; Note: There is a real-time FPM status monitoring sample web page available +; It's available in: /usr/share/php7/fpm/status.html +; +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;pm.status_path = /status + +; The ping URI to call the monitoring page of FPM. If this value is not set, no +; URI will be recognized as a ping page. This could be used to test from outside +; that FPM is alive and responding, or to +; - create a graph of FPM availability (rrd or such); +; - remove a server from a group if it is not responding (load balancing); +; - trigger alerts for the operating team (24/7). +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;ping.path = /ping + +; This directive may be used to customize the response of a ping request. The +; response is formatted as text/plain with a 200 response code. +; Default Value: pong +;ping.response = pong + +; The access log file +; Default: not set +;access.log = log/php7/$pool.access.log + +; The access log format. +; The following syntax is allowed +; %%: the '%' character +; %C: %CPU used by the request +; it can accept the following format: +; - %{user}C for user CPU only +; - %{system}C for system CPU only +; - %{total}C for user + system CPU (default) +; %d: time taken to serve the request +; it can accept the following format: +; - %{seconds}d (default) +; - %{miliseconds}d +; - %{mili}d +; - %{microseconds}d +; - %{micro}d +; %e: an environment variable (same as $_ENV or $_SERVER) +; it must be associated with embraces to specify the name of the env +; variable. Some exemples: +; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e +; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e +; %f: script filename +; %l: content-length of the request (for POST request only) +; %m: request method +; %M: peak of memory allocated by PHP +; it can accept the following format: +; - %{bytes}M (default) +; - %{kilobytes}M +; - %{kilo}M +; - %{megabytes}M +; - %{mega}M +; %n: pool name +; %o: output header +; it must be associated with embraces to specify the name of the header: +; - %{Content-Type}o +; - %{X-Powered-By}o +; - %{Transfert-Encoding}o +; - .... +; %p: PID of the child that serviced the request +; %P: PID of the parent of the child that serviced the request +; %q: the query string +; %Q: the '?' character if query string exists +; %r: the request URI (without the query string, see %q and %Q) +; %R: remote IP address +; %s: status (response code) +; %t: server time the request was received +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %T: time the log has been written (the request has finished) +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %u: remote user +; +; Default: "%R - %u %t \"%m %r\" %s" +;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" + +; The log file for slow requests +; Default Value: not set +; Note: slowlog is mandatory if request_slowlog_timeout is set +;slowlog = log/php7/$pool.slow.log + +; The timeout for serving a single request after which a PHP backtrace will be +; dumped to the 'slowlog' file. A value of '0s' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_slowlog_timeout = 0 + +; Depth of slow log stack trace. +; Default Value: 20 +;request_slowlog_trace_depth = 20 + +; The timeout for serving a single request after which the worker process will +; be killed. This option should be used when the 'max_execution_time' ini option +; does not stop script execution for some reason. A value of '0' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_terminate_timeout = 0 + +; Set open file descriptor rlimit. +; Default Value: system defined value +;rlimit_files = 1024 + +; Set max core size rlimit. +; Possible Values: 'unlimited' or an integer greater or equal to 0 +; Default Value: system defined value +;rlimit_core = 0 + +; Chroot to this directory at the start. This value must be defined as an +; absolute path. When this value is not set, chroot is not used. +; Note: you can prefix with '$prefix' to chroot to the pool prefix or one +; of its subdirectories. If the pool prefix is not set, the global prefix +; will be used instead. +; Note: chrooting is a great security feature and should be used whenever +; possible. However, all PHP paths will be relative to the chroot +; (error_log, sessions.save_path, ...). +; Default Value: not set +;chroot = + +; Chdir to this directory at the start. +; Note: relative path can be used. +; Default Value: current directory or / when chroot +;chdir = /var/www + +; Redirect worker stdout and stderr into main error log. If not set, stdout and +; stderr will be redirected to /dev/null according to FastCGI specs. +; Note: on highloaded environement, this can cause some delay in the page +; process time (several ms). +; Default Value: no +catch_workers_output = yes + +; Clear environment in FPM workers +; Prevents arbitrary environment variables from reaching FPM worker processes +; by clearing the environment in workers before env vars specified in this +; pool configuration are added. +; Setting to "no" will make all environment variables available to PHP code +; via getenv(), $_ENV and $_SERVER. +; Default Value: yes +clear_env = no + +; Limits the extensions of the main script FPM will allow to parse. This can +; prevent configuration mistakes on the web server side. You should only limit +; FPM to .php extensions to prevent malicious users to use other extensions to +; execute php code. +; Note: set an empty value to allow all extensions. +; Default Value: .php +security.limit_extensions = + +; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from +; the current environment. +; Default Value: clean env +;env[HOSTNAME] = $HOSTNAME +;env[PATH] = /usr/local/bin:/usr/bin:/bin +;env[TMP] = /tmp +;env[TMPDIR] = /tmp +;env[TEMP] = /tmp + +; Additional php.ini defines, specific to this pool of workers. These settings +; overwrite the values previously defined in the php.ini. The directives are the +; same as the PHP SAPI: +; php_value/php_flag - you can set classic ini defines which can +; be overwritten from PHP call 'ini_set'. +; php_admin_value/php_admin_flag - these directives won't be overwritten by +; PHP call 'ini_set' +; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. + +; Defining 'extension' will load the corresponding shared extension from +; extension_dir. Defining 'disable_functions' or 'disable_classes' will not +; overwrite previously defined php.ini values, but will append the new value +; instead. + +; Note: path INI options can be relative and will be expanded with the prefix +; (pool, global or /usr) + +; Default Value: nothing is defined by default except the values in php.ini and +; specified at startup with the -d argument +;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com +;php_flag[display_errors] = off +;php_admin_value[error_log] = /var/log/php7/$pool.error.log +;php_admin_flag[log_errors] = on +;php_admin_value[memory_limit] = 32M \ No newline at end of file diff --git a/applications/nginx/Dockerfile b/applications/nginx/Dockerfile index b594145c8..fabef50e1 100644 --- a/applications/nginx/Dockerfile +++ b/applications/nginx/Dockerfile @@ -1,151 +1,14 @@ -FROM alpine:3.7 -# See attached LICENSE, code based from : https://github.com/nginxinc/docker-nginx/blob/master/stable/alpine/Dockerfile +# https://hub.docker.com/_/nginx/ +FROM nginx:1.17.2-alpine -# Update index of available packages, then update the currently installed packages. -RUN apk update && apk upgrade +RUN apk add --no-cache bash bash-completion \ + && mkdir /etc/nginx/qs \ + && rm /etc/nginx/conf.d/default.conf; -ENV NGINX_VERSION 1.14.0 +COPY ./applications/nginx/includes /etc/nginx/qs -RUN GPG_KEYS=B0F4253373F8F6F510D42178520A9993A1C052F8 \ - && CONFIG="\ - --prefix=/etc/nginx \ - --sbin-path=/usr/sbin/nginx \ - --modules-path=/usr/lib/nginx/modules \ - --conf-path=/etc/nginx/nginx.conf \ - --error-log-path=/var/log/nginx/error.log \ - --http-log-path=/var/log/nginx/access.log \ - --pid-path=/var/run/nginx.pid \ - --lock-path=/var/run/nginx.lock \ - --http-client-body-temp-path=/var/cache/nginx/client_temp \ - --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ - --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ - --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ - --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ - --user=nginx \ - --group=nginx \ - --with-http_ssl_module \ - --with-http_realip_module \ - --with-http_addition_module \ - --with-http_sub_module \ - --with-http_dav_module \ - --with-http_flv_module \ - --with-http_mp4_module \ - --with-http_gunzip_module \ - --with-http_gzip_static_module \ - --with-http_random_index_module \ - --with-http_secure_link_module \ - --with-http_stub_status_module \ - --with-http_auth_request_module \ - --with-http_xslt_module=dynamic \ - --with-http_image_filter_module=dynamic \ - --with-http_geoip_module=dynamic \ - --with-threads \ - --with-stream \ - --with-stream_ssl_module \ - --with-stream_ssl_preread_module \ - --with-stream_realip_module \ - --with-stream_geoip_module=dynamic \ - --with-http_slice_module \ - --with-mail \ - --with-mail_ssl_module \ - --with-compat \ - --with-file-aio \ - --with-http_v2_module \ - " \ - && addgroup -S nginx \ - && adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx nginx \ - && apk add --no-cache --virtual .build-deps \ - gcc \ - libc-dev \ - make \ - openssl-dev \ - pcre-dev \ - zlib-dev \ - linux-headers \ - curl \ - gnupg \ - libxslt-dev \ - gd-dev \ - geoip-dev \ - && curl -fSL https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz -o nginx.tar.gz \ - && curl -fSL https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz.asc -o nginx.tar.gz.asc \ - && export GNUPGHOME="$(mktemp -d)" \ - && found=''; \ - for server in \ - ha.pool.sks-keyservers.net \ - hkp://keyserver.ubuntu.com:80 \ - hkp://p80.pool.sks-keyservers.net:80 \ - pgp.mit.edu \ - ; do \ - echo "Fetching GPG key $GPG_KEYS from $server"; \ - gpg --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$GPG_KEYS" && found=yes && break; \ - done; \ - test -z "$found" && echo >&2 "error: failed to fetch GPG key $GPG_KEYS" && exit 1; \ - gpg --batch --verify nginx.tar.gz.asc nginx.tar.gz \ - && rm -rf "$GNUPGHOME" nginx.tar.gz.asc \ - && mkdir -p /usr/src \ - && tar -zxC /usr/src -f nginx.tar.gz \ - && rm nginx.tar.gz \ - && cd /usr/src/nginx-$NGINX_VERSION \ - && ./configure $CONFIG --with-debug \ - && make -j$(getconf _NPROCESSORS_ONLN) \ - && mv objs/nginx objs/nginx-debug \ - && mv objs/ngx_http_xslt_filter_module.so objs/ngx_http_xslt_filter_module-debug.so \ - && mv objs/ngx_http_image_filter_module.so objs/ngx_http_image_filter_module-debug.so \ - && mv objs/ngx_http_geoip_module.so objs/ngx_http_geoip_module-debug.so \ - && mv objs/ngx_stream_geoip_module.so objs/ngx_stream_geoip_module-debug.so \ - && ./configure $CONFIG \ - && make -j$(getconf _NPROCESSORS_ONLN) \ - && make install \ - && rm -rf /etc/nginx/html/ \ - && mkdir /etc/nginx/conf.d/ \ - && mkdir -p /usr/share/nginx/html/ \ - && install -m644 html/index.html /usr/share/nginx/html/ \ - && install -m644 html/50x.html /usr/share/nginx/html/ \ - && install -m755 objs/nginx-debug /usr/sbin/nginx-debug \ - && install -m755 objs/ngx_http_xslt_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_xslt_filter_module-debug.so \ - && install -m755 objs/ngx_http_image_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_image_filter_module-debug.so \ - && install -m755 objs/ngx_http_geoip_module-debug.so /usr/lib/nginx/modules/ngx_http_geoip_module-debug.so \ - && install -m755 objs/ngx_stream_geoip_module-debug.so /usr/lib/nginx/modules/ngx_stream_geoip_module-debug.so \ - && ln -s ../../usr/lib/nginx/modules /etc/nginx/modules \ - && strip /usr/sbin/nginx* \ - && strip /usr/lib/nginx/modules/*.so \ - && rm -rf /usr/src/nginx-$NGINX_VERSION \ - \ - # Bring in gettext so we can get `envsubst`, then throw - # the rest away. To do this, we need to install `gettext` - # then move `envsubst` out of the way so `gettext` can - # be deleted completely, then move `envsubst` back. - && apk add --no-cache --virtual .gettext gettext \ - && mv /usr/bin/envsubst /tmp/ \ - \ - && runDeps="$( \ - scanelf --needed --nobanner --format '%n#p' /usr/sbin/nginx /usr/lib/nginx/modules/*.so /tmp/envsubst \ - | tr ',' '\n' \ - | sort -u \ - | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ - )" \ - && apk add --no-cache --virtual .nginx-rundeps $runDeps \ - && apk del .build-deps \ - && apk del .gettext \ - && mv /tmp/envsubst /usr/local/bin/ \ - \ - # Bring in tzdata so users could set the timezones through the environment - # variables - && apk add --no-cache tzdata \ - #\ - # forward request and error logs to docker log collector - && ln -sf /dev/stdout /var/log/nginx/access.log \ - && ln -sf /dev/stderr /var/log/nginx/error.log - -# ------------------------------------------------------------------------------------------------------------------------------ - -RUN apk add --no-cache bash \ - #&& apk add --no-cache bash-completion \ - && rm -rf /var/cache/apk/* - -#EXPOSE 80 - -STOPSIGNAL SIGTERM +RUN set -x ; \ + addgroup -g 82 -S www-data ; \ + adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1 CMD ["nginx", "-g", "daemon off;"] diff --git a/applications/nginx/includes/buffers.nginx b/applications/nginx/includes/buffers.nginx new file mode 100644 index 000000000..da30e8dff --- /dev/null +++ b/applications/nginx/includes/buffers.nginx @@ -0,0 +1,11 @@ +# Client buffer size that gets sent to NGINX. +client_body_buffer_size 10K; + +# Client buffer size for header size. +client_header_buffer_size 1k; + +# Client request maximum size. +client_max_body_size 8m; + +# Client maximum number + size for large header buffers. +large_client_header_buffers 2 2k; diff --git a/applications/nginx/includes/cors.nginx b/applications/nginx/includes/cors.nginx new file mode 100644 index 000000000..4cdcc5281 --- /dev/null +++ b/applications/nginx/includes/cors.nginx @@ -0,0 +1,23 @@ +# Thanks to original author: https://gist.github.com/Stanback/7145487 + +set $cors ''; +if ($http_origin ~ '^https?://(localhost|www\.nexuslocal\.com|www\.quasarsource\.com)') { + set $cors 'true'; +} + +if ($cors = 'true') { + add_header 'Access-Control-Allow-Origin' "$http_origin" always; + add_header 'Access-Control-Allow-Credentials' 'true' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always; + # required to be able to read Authorization header in frontend + add_header 'Access-Control-Expose-Headers' 'Authorization' always; +} + +if ($request_method = 'OPTIONS') { + # Tell client that this pre-flight info is valid for 20 days + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain charset=UTF-8'; + add_header 'Content-Length' 0; + return 204; +} diff --git a/applications/nginx/includes/docker_dns_fix.nginx b/applications/nginx/includes/docker_dns_fix.nginx new file mode 100644 index 000000000..ff1a0f064 --- /dev/null +++ b/applications/nginx/includes/docker_dns_fix.nginx @@ -0,0 +1,5 @@ +# this is the internal Docker DNS, cache only for 30s +#resolver 127.0.0.11 valid=30s; + +# this works as well but also fixed an additional edge case. +resolver 127.0.0.11 ipv6=off; diff --git a/applications/nginx/includes/file_cache.nginx b/applications/nginx/includes/file_cache.nginx new file mode 100644 index 000000000..b15fef864 --- /dev/null +++ b/applications/nginx/includes/file_cache.nginx @@ -0,0 +1,5 @@ +# Cache information about FDs, frequently accessed files can boost performance (values need to be fine tuned). +open_file_cache max=200000 inactive=90s; +open_file_cache_valid 180s; +open_file_cache_min_uses 2; +open_file_cache_errors on; diff --git a/applications/nginx/includes/gzip_dynamic.nginx b/applications/nginx/includes/gzip_dynamic.nginx new file mode 100644 index 000000000..5b57587ff --- /dev/null +++ b/applications/nginx/includes/gzip_dynamic.nginx @@ -0,0 +1,9 @@ +gzip on; +gzip_http_version 1.0; +gzip_comp_level 6; +gzip_min_length 0; +gzip_buffers 16 8k; +gzip_proxied any; +gzip_types text/plain text/css text/xml text/javascript application/xml application/xml+rss application/javascript application/json; +gzip_disable "MSIE [1-6]\."; +gzip_vary on; diff --git a/applications/nginx/includes/gzip_static.nginx b/applications/nginx/includes/gzip_static.nginx new file mode 100644 index 000000000..8e85a56d4 --- /dev/null +++ b/applications/nginx/includes/gzip_static.nginx @@ -0,0 +1,10 @@ +gzip off; +gzip_static on; +#gzip_disable "msie6"; +#gzip_vary on; +#gzip_proxied any; +#gzip_comp_level 6; +#gzip_buffers 16 8k; +#gzip_http_version 1.1; +#gzip_min_length 256; +#gzip_types text/plain application/javascript text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon; diff --git a/applications/nginx/includes/header_cache_disable.nginx b/applications/nginx/includes/header_cache_disable.nginx new file mode 100644 index 000000000..e4d718ba4 --- /dev/null +++ b/applications/nginx/includes/header_cache_disable.nginx @@ -0,0 +1,3 @@ +add_header X-Cache-Status $upstream_cache_status; +expires -1; +add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; diff --git a/applications/nginx/includes/header_cache_enable.nginx b/applications/nginx/includes/header_cache_enable.nginx new file mode 100644 index 000000000..14b3c62e5 --- /dev/null +++ b/applications/nginx/includes/header_cache_enable.nginx @@ -0,0 +1,6 @@ +add_header X-Cache-Status $upstream_cache_status; +expires 30d; +add_header Cache-Control "public"; + +# @see https://stackoverflow.com/questions/1920781/what-does-the-http-header-pragma-public-mean +add_header Pragma public; diff --git a/applications/nginx/includes/header_cookie_disable.nginx b/applications/nginx/includes/header_cookie_disable.nginx new file mode 100644 index 000000000..f2fba2915 --- /dev/null +++ b/applications/nginx/includes/header_cookie_disable.nginx @@ -0,0 +1,2 @@ +proxy_ignore_headers Set-Cookie; +proxy_hide_header Set-Cookie; diff --git a/applications/nginx/includes/http_performance.nginx b/applications/nginx/includes/http_performance.nginx new file mode 100644 index 000000000..014ec8907 --- /dev/null +++ b/applications/nginx/includes/http_performance.nginx @@ -0,0 +1,7 @@ +# don't delay sending small data bursts by buffering data sent +tcp_nodelay on; +# sends headers in single data piece +tcp_nopush on; +# avoid slower read() + write() by using FD(file_descriptor) to copy data +sendfile on; +sendfile_max_chunk 1m; diff --git a/applications/nginx/includes/proxy_pass.nginx b/applications/nginx/includes/proxy_pass.nginx new file mode 100644 index 000000000..dc778fb83 --- /dev/null +++ b/applications/nginx/includes/proxy_pass.nginx @@ -0,0 +1,8 @@ +# TODO: Document. +#proxy_redirect off; +proxy_set_header Host $host; +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-Host $server_name; + +proxy_http_version 1.1; diff --git a/applications/nginx/includes/timeouts.nginx b/applications/nginx/includes/timeouts.nginx new file mode 100644 index 000000000..70b90d51f --- /dev/null +++ b/applications/nginx/includes/timeouts.nginx @@ -0,0 +1,14 @@ +# time to wait to get body (or reply with a 408) +client_body_timeout 10; + +# time to wait to get headers (or reply with a 408) +client_header_timeout 10; + +# close connections after x seconds +keepalive_timeout 30; + +# wait time for single response within a full round trip/ack +send_timeout 10; + +# allow the server to close connection on non responding client, this will free up memory +reset_timedout_connection on; diff --git a/applications/nginx/nginx.nginx b/applications/nginx/nginx.nginx deleted file mode 100644 index 637edb84d..000000000 --- a/applications/nginx/nginx.nginx +++ /dev/null @@ -1,166 +0,0 @@ -user nginx; - -worker_processes auto; - -events { - # Max clients = 1024 * worker_processes - worker_connections 1024; - # Optimized for serving many clients for each thread, esspecially for Linux. - use epoll; - # Accept as many connections as possible, can flood worker connections if set too low. - multi_accept on; -} - -http { - access_log /dev/stdout; - access_log /dev/stdout; - #error_log /etc/nginx/logs/nginx-error.log; - - #upstream docker-jenkins { - # server jenkins:8080; - #} - - # Needed headers for websockets and jenkins. ------------------------------------------------------------------------- - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $host; - #--------------------------------------------------------------------------------------------------------------------- - - - include /etc/nginx/mime.types; - default_type application/octet-stream; - - # Don't buffer data sent, good for small data bursts in real time. - tcp_nodelay on; - # Send headers in one piece (better than sending one by one). - tcp_nopush on; - # Copies data between on FD to another within kernel, faster than read() + write(). - sendfile on; - - #upstream service-jenkins { - # server 10.1.3.46:8080; - #server jenkins:8080; - #} - - client_body_timeout 10; - client_header_timeout 10; - keepalive_timeout 15; - send_timeout 10; - # allow the server to close connection on non responding client, this will free up memory - reset_timedout_connection on; - - server { - root /; - - listen 80 reuseport; - #server_name quasarsource.com www.quasarsource.com; - server_name localhost; - - #add_header 'Referrer-Policy' 'origin'; - - location ^~ /jenkins/ { - #proxy_pass http://docker-jenkins; - #proxy_pass http://jenkins:8080; - #proxy_pass http://service-jenkins/; - - #set $upstream jenkins:8080; - #proxy_pass $upstream; - proxy_pass http://jenkins:8080/jenkins/; - - ##### - proxy_request_buffering off; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_http_version 1.1; - #proxy_set_header X-Forwarded-Proto http; - add_header 'X-SSH-Endpoint' 'jenkins.domain.tld:50022' always; - ##### - - # Sendfile provides no advantages when operating as a proxy - sendfile off; - - #proxy_redirect off; - - proxy_set_header Referer $http_referer; - - #set $upstream jenkins:8080; - #proxy_pass $upstream; - # - proxy_set_header Host $host; - #proxy_set_header Host $host:$server_port; - #proxy_set_header Host $http_host; - #proxy_set_header X-Forwarded_proto http; - # - proxy_set_header X-Real-IP $remote_addr; - #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-For $remote_addr; - - #proxy_set_header X-Forwarded-Host $server_name; - - proxy_max_temp_file_size 0; - - proxy_connect_timeout 150; - proxy_send_timeout 100; - proxy_read_timeout 100; - - proxy_buffer_size 8k; - proxy_buffers 4 32k; - proxy_busy_buffers_size 64k; - proxy_temp_file_write_size 64k; - - default_type application/octet-stream; - - keepalive_timeout 65; - - client_max_body_size 300m; - client_body_buffer_size 128k; - - gzip on; - gzip_http_version 1.0; - gzip_comp_level 6; - gzip_min_length 0; - gzip_buffers 16 8k; - gzip_proxied any; - gzip_types text/plain text/css text/xml text/javascript application/xml application/xml+rss application/javascript application/json; - gzip_disable "MSIE [1-6]\."; - gzip_vary on; - } - - location ^~ /v/nl.min.js { - expires -1; - add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; - } - - location /v/ { - #proxy_ignore_headers Set-Cookie; - #proxy_hide_header Set-Cookie; - - expires 30d; - #add_header Pragma public; - add_header Cache-Control "public"; - - sendfile_max_chunk 1m; - } - - location /nginx_status { - # Turn on nginx stats - stub_status on; - - # I do not need logs for stats - #access_log off; - - # Security: Only allow access from 192.168.1.100 IP # - #allow 192.168.1.100; - - # Send rest of the world to /dev/null # - #deny all; - } - - location / { - add_header X-Cache-Status $upstream_cache_status; - index nl.min.html; - root /v/; - } - } - - include /etc/nginx/conf.d/*.conf; -} diff --git a/applications/nginx/nginx_copy.nginx b/applications/nginx/nginx_copy.nginx deleted file mode 100644 index c41e5a801..000000000 --- a/applications/nginx/nginx_copy.nginx +++ /dev/null @@ -1,210 +0,0 @@ -#------------------------------------------------------------------------------------------------------------------------- -# Prevent Docker from thinking this process has stopped. -daemon off; -# Set the user to use. -user nginx; -# Set number of worker processes based off machine's CPU cores. -worker_processes auto; -# Set number of file descriptors that can be used by NGINX. -worker_rlimit_nofile 1048575; -# Enable just-in-time compilation. -pcre_jit on; -#------------------------------------------------------------------------------------------------------------------------- -events { - # Max clients = 1024 * worker_processes - worker_connections 1024; - # Optimized for serving many clients for each thread, esspecially for Linux. - use epoll; - # Accept as many connections as possible, can flood worker connections if set too low. - multi_accept on; - # Since 'reuseport' is being used, 'accept_mutex' should be set off. - accept_mutex off; -} -#------------------------------------------------------------------------------------------------------------------------- -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - # Needed headers for websockets and jenkins. ------------------------------------------------------------------------- - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $host; - #--------------------------------------------------------------------------------------------------------------------- - - # Don't buffer data sent, good for small data bursts in real time. - tcp_nodelay on; - # Send headers in one piece (better than sending one by one). - tcp_nopush on; - # Copies data between on FD to another within kernel, faster than read() + write(). - sendfile on; - - # - # Cache information about FDs, frequently accessed files can boost performance (values need to be fine tuned). - open_file_cache max=200000 inactive=90s; - open_file_cache_valid 180s; - open_file_cache_min_uses 2; - open_file_cache_errors on; - # - - log_format cache_status '[$time_local] "$request" $upstream_cache_status'; - - #access_log logs/cache.log cache_status; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"' - 'rt=$request_time uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"'; - - #access_log /v/nginx.log main; - #error_log /v/nginx.errors warn; - - gzip off; - gzip_static on; - #gzip_disable "msie6"; - #gzip_vary on; - #gzip_proxied any; - #gzip_comp_level 6; - #gzip_buffers 16 8k; - #gzip_http_version 1.1; - #gzip_min_length 256; - #gzip_types text/plain application/javascript text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon; - - #client_body_buffer_size 10K; - #client_header_buffer_size 1k; - #client_max_body_size 8m; - #large_client_header_buffers 4 4k; - - client_body_timeout 10; - client_header_timeout 10; - keepalive_timeout 15; - send_timeout 10; - # allow the server to close connection on non responding client, this will free up memory - reset_timedout_connection on; - - #upstream service-websocket { - #server nexus_courier:3001; - # server 10.1.3.46:3001; - #} - - upstream service-jenkins { - server 10.1.3.46:8080; - } - - upstream service-asset-server { - server 10.1.3.46:7999; - } - - server { - #listen 80 default_server; - listen 80 reuseport; - #listen [::]:80 default_server; - server_name quasarsource.com www.quasarsource.com; - root /; - - #rewrite ^(.*)/$ $1/nl.min.html.gz; - - - location /ws { - # 301 --> page has permanently moved to a new location. - # 302 --> page has only moved temporary. - return 302 /ws/; - } - - location /ws/ { - # - #set $upstream http://service-websocket; - #set $upstream nexus_courier:3001; - # - #proxy_pass http://service-websocket; - #proxy_pass $upstream; - - ## - #proxy_pass http://service-websocket; - ## - - resolver 10.1.3.46 valid=30s; - set $upstream_websocket upstream_websocket; - proxy_pass http://$upstream_websocket:3001; - - # - #proxy_redirect default; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_read_timeout 86400; - } - - location ^~ /service-asset-server { - proxy_pass http://service-asset-server; - } - - location ^~ /jenkins { - # - #proxy_pass 10.1.3.46:8080; - #set $upstream jenkins:8080; - #proxy_pass $upstream; - # - proxy_request_buffering off; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_http_version 1.1; - proxy_pass http://service-jenkins; - proxy_set_header X-Forwarded_proto http; - - #resolver 10.1.3.46 valid=30s; - #set $upstream_jenkins upstream_jenkins; - #proxy_pass http://$upstream_jenkins:8080; - - add_header 'X-SSH-Endpoint' 'jenkins.domain.tld:50022' always; - - # - #proxy_max_temp_file_size 0; - #proxy_connect_timeout 150; - #proxy_send_timeout 100; - #proxy_read_timeout 100; - #proxy_buffer_size 8k; - #proxy_buffers 4 32k; - #proxy_busy_buffers_size 64k; - #proxy_temp_file_write_size 64k; - # - - keepalive_timeout 65; - - client_max_body_size 300m; - client_body_buffer_size 128k; - - gzip on; - gzip_http_version 1.0; - gzip_comp_level 6; - gzip_min_length 0; - gzip_buffers 16 8k; - gzip_proxied any; - gzip_types text/plain text/css text/xml text/javascript application/xml application/xml+rss application/javascript application/json; - gzip_disable "MSIE [1-6]\."; - gzip_vary on; - } - - location ^~ /v/nl.min.js { - expires -1; - add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; - } - - location /v/ { - proxy_ignore_headers Set-Cookie; - proxy_hide_header Set-Cookie; - - expires 30d; - #add_header Pragma public; - add_header Cache-Control "public"; - - sendfile_max_chunk 1m; - } - - location / { - add_header X-Cache-Status $upstream_cache_status; - index nl.min.html; - root /v/; - } - - } - - include /etc/nginx/conf.d/*.conf; -} \ No newline at end of file diff --git a/applications/nginx/nginx_previous.nginx b/applications/nginx/nginx_previous.nginx deleted file mode 100644 index b8594b770..000000000 --- a/applications/nginx/nginx_previous.nginx +++ /dev/null @@ -1,223 +0,0 @@ -user nginx; - -# Set number of worker processes based off machine's CPU cores. -worker_processes auto; - -# Set number of file descriptors that can be used by NGINX. -worker_rlimit_nofile 1048575; - -#error_log /var/log/nginx/error.log warn; -#pid /var/run/nginx.pid; - -events { - # Max clients = 1024 * worker_processes - worker_connections 1024; - - # Optimized for serving many clients for each thread, esspecially for Linux. - use epoll; - - # Accept as many connections as possible, can flood worker connections if set too low. - multi_accept on; -} - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - # Don't buffer data sent, good for small data bursts in real time. - tcp_nodelay on; - # Send headers in one piece (better than sending one by one). - tcp_nopush on; - # Copies data between on FD to another within kernel, faster than read() + write(). - sendfile on; - - # - # Cache information about FDs, frequently accessed files can boost performance (values need to be fine tuned). - open_file_cache max=200000 inactive=90s; - open_file_cache_valid 180s; - open_file_cache_min_uses 2; - open_file_cache_errors on; - # - - - gzip off; - gzip_static on; - #gzip_disable "msie6"; - #gzip_vary on; - #gzip_proxied any; - #gzip_comp_level 6; - #gzip_buffers 16 8k; - #gzip_http_version 1.1; - #gzip_min_length 256; - #gzip_types text/plain application/javascript text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon; - - client_body_buffer_size 10K; - client_header_buffer_size 1k; - client_max_body_size 8m; - large_client_header_buffers 4 4k; - - client_body_timeout 10; - client_header_timeout 10; - keepalive_timeout 15; - send_timeout 10; - # allow the server to close connection on non responding client, this will free up memory - reset_timedout_connection on; - - proxy_cache_path /nginx_cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; - proxy_cache_methods GET HEAD; - - #upstream service-websocket { - # server nexus_courier:3001; - #} - - server { - #listen 80 default_server; - listen 80 reuseport; - #listen [::]:80 default_server; - server_name quasarsource.com www.quasarsource.com; - root /; - - # Internal Docker DNS, cache only for 30s. - # TODO: might not need this? - #resolver 127.0.0.11 valid=30s; - ### - - #rewrite ^(.*)/$ $1/nl.min.html.gz; - - location /ws { - return 302 /ws/; - } - - location /ws/ { - # - #set $upstream http://service-websocket; - set $upstream nexus_courier:3001; - # - #proxy_pass http://service-websocket; - proxy_pass $upstream; - # - #proxy_redirect default; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Host $server_name; - proxy_read_timeout 86400; - } - - location /jenkins { - # - #proxy_pass http://10.1.3.46:8080; - set $upstream jenkins:8080; - proxy_pass $upstream; - # - proxy_set_header Host $host; - proxy_set_header X-Forwarded_proto http; - # - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - # - #proxy_max_temp_file_size 0; - #proxy_connect_timeout 150; - #proxy_send_timeout 100; - #proxy_read_timeout 100; - #proxy_buffer_size 8k; - #proxy_buffers 4 32k; - #proxy_busy_buffers_size 64k; - #proxy_temp_file_write_size 64k; - # - - default_type application/octet-stream; - - sendfile on; - - keepalive_timeout 65; - - client_max_body_size 300m; - client_body_buffer_size 128k; - - gzip on; - gzip_http_version 1.0; - gzip_comp_level 6; - gzip_min_length 0; - gzip_buffers 16 8k; - gzip_proxied any; - gzip_types text/plain text/css text/xml text/javascript application/xml application/xml+rss application/javascript application/json; - gzip_disable "MSIE [1-6]\."; - gzip_vary on; - } - - location ^~ /v/nl.min.js { - expires -1; - add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; - } - - location /v/ { - # https://www.nginx.com/blog/nginx-caching-guide/ - proxy_cache my_cache; - #proxy_pass http://my_upstream; - proxy_cache_revalidate on; - proxy_cache_min_uses 1; - proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; - proxy_cache_background_update on; - proxy_cache_lock on; - proxy_cache_valid 200 302 10m; - proxy_cache_valid 404 1m; - #add_header X-Cache-Status $upstream_cache_status; - - proxy_ignore_headers Set-Cookie; - proxy_hide_header Set-Cookie; - - expires 30d; - #add_header Pragma public; - add_header Cache-Control "public"; - - sendfile_max_chunk 1m; - } - - location / { - proxy_cache my_cache; - proxy_cache_revalidate on; - proxy_cache_min_uses 1; - proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; - proxy_cache_background_update on; - #proxy_cache_lock on; - add_header X-Cache-Status $upstream_cache_status; - - index nl.min.html; - root /v/; - } - - } - - #server { - # listen 3001; - # location / { - # proxy_pass http://service-websocket; - # proxy_redirect off; - # proxy_http_version 1.1; - # proxy_set_header Upgrade $http_upgrade; - # proxy_set_header Host $host; - # proxy_set_header X-Real-IP $remote_addr; - # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - # proxy_set_header X-Forwarded-Host $server_name; - # } - #} - - log_format cache_status '[$time_local] "$request" $upstream_cache_status'; - #access_log logs/cache.log cache_status; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"' - 'rt=$request_time uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"'; - - access_log /v/nginx.log main; - error_log /v/nginx.errors warn; - - #error_log logs/error.log warn; - #include /etc/nginx/conf.d/*.conf; - -} \ No newline at end of file diff --git a/applications/nginx/nl.nginx b/applications/nginx/nl.nginx new file mode 100644 index 000000000..b068e5d5e --- /dev/null +++ b/applications/nginx/nl.nginx @@ -0,0 +1,137 @@ +# Main Context {configurations that apply on a broad application level} + +# ideally (at max) 1 worker per 1 CPU +worker_processes auto; + +# number of file descriptors that can be used by NGINX (default is 2000) +worker_rlimit_nofile 1048575; + +# TODO: +#error_log logs/error.log notice; +#error_log logs/error.log info; + +# this context is used for setting global options that affect general behavior of handling connections +events { + # max clients = worker_connections * worker_processes + worker_connections 1024; + + # NON-PROD-SAFE:{an optimization for serving many clients in each thread (esp. for Linux)} + use epoll; + + # NON-PROD-SAFE:{accept as many connections as possible, ideally requires more worker_processes} + multi_accept on; + + # since 'reuseport' is being used, 'accept_mutex' should be set off + accept_mutex off; +} + +# sibling of the events context +http { + default_type application/octet-stream; + + include /etc/nginx/mime.types; + include /etc/nginx/qs/buffers.nginx; + include /etc/nginx/qs/http_performance.nginx; + include /etc/nginx/qs/file_cache.nginx; + include /etc/nginx/qs/timeouts.nginx; + include /etc/nginx/qs/docker_dns_fix.nginx; + + #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + # '$status $body_bytes_sent "$http_referer" ' + # '"$http_user_agent" "$http_x_forwarded_for"'; + + #access_log logs/access.log main; + + add_header X-Frame-Options ""; + + upstream docker_rabbit_manager { + server rabbit_manager; #server rabbit_manager:15672; + } + + upstream docker_pgadmin { + server pgadmin4; #server pgadmin4:5050; + } + + upstream docker_asset_server { + server asset_server; + } + + server { + listen 80 reuseport; + server_name localhost; + + # __ + # |\ | / _` | |\ | \_/ + # | \| \__> | | \| / \ + location /nginx { + stub_status on; + } + + # __ __ ___ ___ __ + # /\ /__` /__` |__ | /__` + # /~~\ .__/ .__/ |___ | .__/ + location /v/ { + include /etc/nginx/qs/cors.nginx; + #include /etc/nginx/qs/header_cache_disable.nginx; + root /; + } + + # __ __ __ + # |__) / _` /\ | \ |\/| | |\ | + # | \__> /~~\ |__/ | | | | \| + location /pgadmin4/ { + proxy_pass http://docker_pgadmin; + include /etc/nginx/qs/proxy_pass.nginx; + include /etc/nginx/qs/cors.nginx; + add_header X-Frame-Options ""; + proxy_set_header X-Frame-Options ""; + } + + # __ __ + # |__) |__| |__) + # | | | | + location /php/ { + #set $upstream asset_server:8000; + # Mitigate https://httpoxy.org/ vulnerabilities + + #fastcgi_split_path_info ^(.+?\.php)(/.*)$; + #if (!-f $document_root$fastcgi_script_name) { + # return 404; + #} + + fastcgi_param HTTP_PROXY ""; + fastcgi_param HTTPS off; + #fastcgi_pass $upstream; + fastcgi_pass docker_asset_server; + #fastcgi_pass docker_asset_server; + #fastcgi_index index.php; + include fastcgi_params; + + keepalive_timeout 300; + client_max_body_size 32m; + + #fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + #fastcgi_param DOCUMENT_ROOT $realpath_root; + + #root /quasar_source/applications/asset_server/code_manager/public; + } + } + + # __ __ __ ___ __ + # |__) /\ |__) |__) | | |\/| / \ + # | \ /~~\ |__) |__) | | | | \__X + server { + listen 5672 reuseport; + listen 15672 reuseport; + listen 25672 reuseport; + + server_name rabbit_manager.*; + + location /rabbit_manager/ { + proxy_pass http://docker_rabbit_manager; + include /etc/nginx/qs/proxy_pass.nginx; + include /etc/nginx/qs/cors.nginx; + } + } + +} diff --git a/applications/pgadmin/config.py b/applications/pgadmin/config.py new file mode 100644 index 000000000..f91b6af15 --- /dev/null +++ b/applications/pgadmin/config.py @@ -0,0 +1,453 @@ +# -*- coding: utf-8 -*- + +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2019, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +# config.py - Core application configuration settings +# +########################################################################## + +import logging +import os +import sys + +if sys.version_info[0] >= 3: + import builtins +else: + import __builtin__ as builtins + +# We need to include the root directory in sys.path to ensure that we can +# find everything we need when running in the standalone runtime. +root = os.path.dirname(os.path.realpath(__file__)) +if sys.path[0] != root: + sys.path.insert(0, root) + +from pgadmin.utils import env, IS_PY2, IS_WIN, fs_short_path + +########################################################################## +# Application settings +########################################################################## + +# Name of the application to display in the UI +APP_NAME = 'pgAdmin 4' +APP_ICON = 'pg-icon' + +########################################################################## +# Application settings +########################################################################## + +# NOTE!!! +# If you change any of APP_RELEASE, APP_REVISION or APP_SUFFIX, then you +# must also change APP_VERSION_INT to match. +# +# Any changes made here must also be made in runtime/pgAdmin4.pro and +# runtime/Info.plist +# + +# Application version number components +APP_RELEASE = 4 +APP_REVISION = 10 + +# Application version suffix, e.g. 'beta1', 'dev'. Usually an empty string +# for GA releases. +APP_SUFFIX = '' + +# Numeric application version for upgrade checks. Should be in the format: +# [X]XYYZZ, where X is the release version, Y is the revision, with a leading +# zero if needed, and Z represents the suffix, with a leading zero if needed +APP_VERSION_INT = 41000 + +# DO NOT CHANGE! +# The application version string, constructed from the components +if not APP_SUFFIX: + APP_VERSION = '%s.%s' % (APP_RELEASE, APP_REVISION) +else: + APP_VERSION = '%s.%s-%s' % (APP_RELEASE, APP_REVISION, APP_SUFFIX) + +# Copyright string for display in the app +# Any changes made here must also be made in runtime/pgAdmin4.pro +APP_COPYRIGHT = 'Copyright (C) 2013 - 2019, The pgAdmin Development Team' + +########################################################################## +# Misc stuff +########################################################################## + +# Path to the online help. +HELP_PATH = '../../../docs/en_US/_build/html/' + +# Languages we support in the UI +LANGUAGES = { + 'en': 'English', + 'zh': 'Chinese (Simplified)', + 'fr': 'French', + 'de': 'German', + 'ja': 'Japanese', + 'ko': 'Korean', + 'pl': 'Polish', + 'ru': 'Russian', + 'es': 'Spanish', +} + +# DO NOT CHANGE UNLESS YOU KNOW WHAT YOU ARE DOING! +# List of modules to skip when dynamically loading +MODULE_BLACKLIST = ['test'] + +# DO NOT CHANGE UNLESS YOU KNOW WHAT YOU ARE DOING! +# List of treeview browser nodes to skip when dynamically loading +NODE_BLACKLIST = [] + +########################################################################## +# Server settings +########################################################################## + +# The server mode determines whether or not we're running on a web server +# requiring user authentication, or desktop mode which uses an automatic +# default login. +# +# DO NOT DISABLE SERVER MODE IF RUNNING ON A WEBSERVER!! +# +# We only set SERVER_MODE if it's not already set. That's to allow the +# runtime to force it to False. +# +# NOTE: If you change the value of SERVER_MODE in an included config file, +# you may also need to redefine any values below that are derived +# from it, notably various paths such as LOG_FILE and anything +# using DATA_DIR. + +if (not hasattr(builtins, 'SERVER_MODE')) or builtins.SERVER_MODE is None: + SERVER_MODE = True +else: + SERVER_MODE = builtins.SERVER_MODE + +# HTTP headers to search for CSRF token when it is not provided in the form. +# Default is ['X-CSRFToken', 'X-CSRF-Token'] +WTF_CSRF_HEADERS = ['X-pgA-CSRFToken'] + +# User ID (email address) to use for the default user in desktop mode. +# The default should be fine here, as it's not exposed in the app. +DESKTOP_USER = 'pgadmin4@pgadmin.org' + +# This option allows the user to host the application on a LAN +# Default hosting is on localhost (DEFAULT_SERVER='localhost'). +# To host pgAdmin4 over LAN set DEFAULT_SERVER='0.0.0.0' (or a specific +# adaptor address. +# +# NOTE: This is NOT recommended for production use, only for debugging +# or testing. Production installations should be run as a WSGI application +# behind Apache HTTPD. +#DEFAULT_SERVER = '127.0.0.1' +DEFAULT_SERVER = '0.0.0.0' + +# The default port on which the app server will listen if not set in the +# environment by the runtime +#DEFAULT_SERVER_PORT = 5050 +DEFAULT_SERVER_PORT = 80 + +# Enable X-Frame-Option protection. +# Set to one of "SAMEORIGIN", "ALLOW-FROM origin" or "" to disable. +# Note that "DENY" is NOT supported (and will be silently ignored). +# See https://tools.ietf.org/html/rfc7034 for more info. +#ORIGINAL{}X_FRAME_OPTIONS = "SAMEORIGIN"} +X_FRAME_OPTIONS = "" + +# Hashing algorithm used for password storage +SECURITY_PASSWORD_HASH = 'pbkdf2_sha512' + +# NOTE: CSRF_SESSION_KEY, SECRET_KEY and SECURITY_PASSWORD_SALT are no +# longer part of the main configuration, but are stored in the +# configuration databases 'keys' table and are auto-generated. + +# Should HTML be minified on the fly when not in debug mode? +# NOTE: The HTMLMIN module doesn't work with Python 2.6, so this option +# has no effect on <= Python 2.7. +MINIFY_PAGE = True + +# This will be added to static urls as url parameter with value as +# APP_VERSION_INT for cache busting on version upgrade. If the value is set as +# None or empty string then it will not be added. +# eg - http:localhost:5050/pgadmin.css?intver=3.13 +APP_VERSION_PARAM = 'ver' + +# Add the internal version param to below extensions only +APP_VERSION_EXTN = ('.css', '.js', '.html', '.svg', '.png', '.gif', '.ico') + +# Data directory for storage of config settings etc. This shouldn't normally +# need to be changed - it's here as various other settings depend on it. +# On Windows, we always store data in %APPDATA%\pgAdmin. On other platforms, +# if we're in server mode we use /var/lib/pgadmin, otherwise ~/.pgadmin +if IS_WIN: + # Use the short path on windows + DATA_DIR = os.path.realpath( + os.path.join(fs_short_path(env('APPDATA')), u"pgAdmin") + ) +else: + if SERVER_MODE: + DATA_DIR = '/var/lib/pgadmin' + else: + DATA_DIR = os.path.realpath(os.path.expanduser(u'~/.pgadmin/')) + +########################################################################## +# Log settings +########################################################################## + +# Debug mode? +DEBUG = False + +# Application log level - one of: +# CRITICAL 50 +# ERROR 40 +# WARNING 30 +# SQL 25 +# INFO 20 +# DEBUG 10 +# NOTSET 0 +CONSOLE_LOG_LEVEL = logging.WARNING +FILE_LOG_LEVEL = logging.WARNING + +# Log format. +CONSOLE_LOG_FORMAT = '%(asctime)s: %(levelname)s\t%(name)s:\t%(message)s' +FILE_LOG_FORMAT = '%(asctime)s: %(levelname)s\t%(name)s:\t%(message)s' + +# Log file name. This goes in the data directory, except on non-Windows +# platforms in server mode. +if SERVER_MODE and not IS_WIN: + LOG_FILE = '/var/log/pgadmin/pgadmin4.log' +else: + LOG_FILE = os.path.join(DATA_DIR, 'pgadmin4.log') + +########################################################################## +# Server Connection Driver Settings +########################################################################## + +# The default driver used for making connection with PostgreSQL +PG_DEFAULT_DRIVER = 'psycopg2' + +# Maximum allowed idle time in minutes before which releasing the connection +# for the particular session. (in minutes) +MAX_SESSION_IDLE_TIME = 60 + +########################################################################## +# User account and settings storage +########################################################################## + +# The default path to the SQLite database used to store user accounts and +# settings. This default places the file in the same directory as this +# config file, but generates an absolute path for use througout the app. +SQLITE_PATH = env('SQLITE_PATH') or os.path.join(DATA_DIR, 'pgadmin4.db') + +# SQLITE_TIMEOUT will define how long to wait before throwing the error - +# OperationError due to database lock. On slower system, you may need to change +# this to some higher value. +# (Default: 500 milliseconds) +SQLITE_TIMEOUT = 500 + +# Allow database connection passwords to be saved if the user chooses. +# Set to False to disable password saving. +ALLOW_SAVE_PASSWORD = True + +# Maximum number of history queries stored per user/server/database +MAX_QUERY_HIST_STORED = 20 + +########################################################################## +# Server-side session storage path +# +# SESSION_DB_PATH (Default: $HOME/.pgadmin4/sessions) +########################################################################## +# +# We use SQLite for server-side session storage. There will be one +# SQLite database object per session created. +# +# Specify the path used to store your session objects. +# +# If the specified directory does not exist, the setup script will create +# it with permission mode 700 to keep the session database secure. +# +# On certain systems, you can use shared memory (tmpfs) for maximum +# scalability, for example, on Ubuntu: +# +# SESSION_DB_PATH = '/run/shm/pgAdmin4_session' +# +########################################################################## +SESSION_DB_PATH = os.path.join(DATA_DIR, 'sessions') + +SESSION_COOKIE_NAME = 'pga4_session' + +########################################################################## +# Mail server settings +########################################################################## + +# These settings are used when running in web server mode for confirming +# and resetting passwords etc. +# See: http://pythonhosted.org/Flask-Mail/ for more info +MAIL_SERVER = 'localhost' +MAIL_PORT = 25 +MAIL_USE_SSL = False +MAIL_USE_TLS = False +MAIL_USERNAME = '' +MAIL_PASSWORD = '' +MAIL_DEBUG = False + +# Flask-Security overrides Flask-Mail's MAIL_DEFAULT_SENDER setting, so +# that should be set as such: +SECURITY_EMAIL_SENDER = 'no-reply@localhost' + +########################################################################## +# Mail content settings +########################################################################## + +# These settings define the content of password reset emails +SECURITY_EMAIL_SUBJECT_PASSWORD_RESET = "Password reset instructions for %s" \ + % APP_NAME +SECURITY_EMAIL_SUBJECT_PASSWORD_NOTICE = "Your %s password has been reset" \ + % APP_NAME +SECURITY_EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE = \ + "Your password for %s has been changed" % APP_NAME + +########################################################################## +# Upgrade checks +########################################################################## + +# Check for new versions of the application? +UPGRADE_CHECK_ENABLED = True + +# Where should we get the data from? +UPGRADE_CHECK_URL = 'https://www.pgadmin.org/versions.json' + +# What key should we look at in the upgrade data file? +UPGRADE_CHECK_KEY = 'pgadmin4' + +# Which CA file should we use? +# Default to cacert.pem in the same directory as config.py et al. +CA_FILE = os.path.join(os.path.dirname(os.path.realpath(__file__)), + "cacert.pem") + +########################################################################## +# Storage Manager storage url config settings +# If user sets STORAGE_DIR to empty it will show all volumes if platform +# is Windows, '/' if it is Linux, Mac or any other unix type system. + +# For example: +# 1. STORAGE_DIR = get_drive("C") or get_drive() # return C:/ by default +# where C can be any drive character such as "D", "E", "G" etc +# 2. Set path manually like +# STORAGE_DIR = "/path/to/directory/" +########################################################################## +STORAGE_DIR = os.path.join(DATA_DIR, 'storage') + +########################################################################## +# Default locations for binary utilities (pg_dump, pg_restore etc) +# +# These are intentionally left empty in the main config file, but are +# expected to be overridden by packagers in config_distro.py. +# +# A default location can be specified for each database driver ID, in +# a dictionary. Either an absolute or relative path can be specified. +# In cases where it may be difficult to know what the working directory +# is, "$DIR" can be specified. This will be replaced with the path to the +# top-level pgAdmin4.py file. For example, on macOS we might use: +# +# $DIR/../../SharedSupport +# +########################################################################## +DEFAULT_BINARY_PATHS = { + "pg": "", + "ppas": "", + "gpdb": "" +} + +########################################################################## +# Test settings - used primarily by the regression suite, not for users +########################################################################## + +# The default path for SQLite database for testing +TEST_SQLITE_PATH = os.path.join(DATA_DIR, 'test_pgadmin4.db') + +########################################################################## +# Allows flask application to response to the each request asynchronously +########################################################################## +THREADED_MODE = True + +########################################################################## +# Do not allow SQLALCHEMY to track modification as it is going to be +# deprecated in future +########################################################################## +SQLALCHEMY_TRACK_MODIFICATIONS = False + +########################################################################## +# Number of records to fetch in one batch in query tool when query result +# set is large. +########################################################################## +ON_DEMAND_RECORD_COUNT = 1000 + +########################################################################## +# Allow users to display Gravatar image for their username in Server mode +########################################################################## +SHOW_GRAVATAR_IMAGE = True + +########################################################################## +# Set cookie path +########################################################################## +COOKIE_DEFAULT_PATH = '/' +COOKIE_DEFAULT_DOMAIN = None +SESSION_COOKIE_DOMAIN = None +SESSION_COOKIE_SAMESITE = 'Lax' + +######################################################################### +# Skip storing session in files and cache for specific paths +######################################################################### +SESSION_SKIP_PATHS = [ + '/misc/ping' +] + +########################################################################## +# Session expiration support +########################################################################## +# SESSION_EXPIRATION_TIME is the interval in Days. Session will be +# expire after the specified number of *days*. +SESSION_EXPIRATION_TIME = 1 + +# CHECK_SESSION_FILES_INTERVAL is interval in Hours. Application will check +# the session files for cleanup after specified number of *hours*. +CHECK_SESSION_FILES_INTERVAL = 24 + +########################################################################## +# SSH Tunneling supports only for Python 2.7 and 3.4+ +########################################################################## +SUPPORT_SSH_TUNNEL = True +# Allow SSH Tunnel passwords to be saved if the user chooses. +# Set to False to disable password saving. +ALLOW_SAVE_TUNNEL_PASSWORD = True + +########################################################################## +# Master password is used to encrypt/decrypt saved server passwords +# Applicable for desktop mode only +########################################################################## +MASTER_PASSWORD_REQUIRED = False + +########################################################################## +# Local config settings +########################################################################## + +# Load distribution-specific config overrides +try: + from config_distro import * +except ImportError: + pass + +# Load local config overrides +try: + from config_local import * +except ImportError: + pass + +# SUPPORT_SSH_TUNNEL can be override in local config file and if that +# setting is False in local config then we should not check the Python version. +if (SUPPORT_SSH_TUNNEL is True and + ((sys.version_info[0] == 2 and sys.version_info[1] < 7) or + (sys.version_info[0] == 3 and sys.version_info[1] < 4))): + SUPPORT_SSH_TUNNEL = False + ALLOW_SAVE_TUNNEL_PASSWORD = False \ No newline at end of file diff --git a/applications/rabbitmq_manager/Dockerfile b/applications/rabbitmq_manager/Dockerfile index 4edc4cd02..7779f77e1 100644 --- a/applications/rabbitmq_manager/Dockerfile +++ b/applications/rabbitmq_manager/Dockerfile @@ -1,5 +1,10 @@ FROM rabbitmq:3.6.9-management-alpine - #CMD ["echo", "BUILD RABBITMQ MANAGEMENT"] + + + + + + diff --git a/assets/css/nexus_local.css b/assets/css/nexus_local.css deleted file mode 100644 index c308d639f..000000000 --- a/assets/css/nexus_local.css +++ /dev/null @@ -1,95 +0,0 @@ -/* __ __ __ ___ ___ __ ___ ___ - | |\/| |__) / \ |__) | /\ |\ | | |\ | / \ | |__ . - | | | | \__/ | \ | /~~\ | \| | | \| \__/ | |___ . -Do not worry about logically organizing & optimizing the CSS rules, this is automatically handled. */ - -@font-face { - font-family: 'Inconsolata'; - src: url('Inconsolata.woff') format('woff'); -} - -/* TODO: Fully test the difference with and without this.*/ -html, body { - height: 100%; -} - -/*__ __ ___ __ __ ___ ___ ___ - |__) /\ | | /__` |__ | \ /__` | /\ | |__ - | /~~\ \__/ .__/ |___ |__/ .__/ | /~~\ | |___ */ -#a { - width: 100vw; - height: 100vh; - z-index: 15; - position: absolute; - background: rgba(1,1,1,0.5); -} - -#b { - -webkit-font-smoothing: subpixel-antialiased; - text-align: center; - font-family: Helvetica, Sans-serif, serif; - - position: absolute; - z-index: 16; - top: 35%; - left: 12.5%; - width: 75%; - background: rgba(1,1,1,0.55); - border: 5px solid rgba(101,128,84,0.77); - color: rgba(236,255,240,0.99); - display: table; -} - -#c { - font-size: 13vw; - margin: 0; -} - -#d { - font-size: 3vw; - margin: 0; -} - - -/*__ ___ ___ ___ __ __ __ __ __ __ - / ` |__ |\ | | |__ |__) / ` | | |__) /__` / \ |__) - \__, |___ | \| | |___ | \ \__, \__/ | \ .__/ \__/ | \ */ -#e { - position: fixed; - z-index: 10; - top: 50%; - left: 50%; - width: 32px; - height: 32px; - margin-top: -16px; - margin-left: -16px; -} - -/*__ __ __ __ ___ __ - / _` | / \ |__) /\ | |__) | | | |__ /__` - \__> |___ \__/ |__) /~~\ |___ | \ \__/ |___ |___ .__/ */ -.f { - user-select: none; - touch-action: none; - margin: 0; - background-color: rgba(0, 0, 0, 0.59); - overflow-y: hidden; - overflow-x: hidden; -} - -/*__ - / _` | | | - \__> \__/ | */ -.g { - position: fixed; - z-index: 13; -} - -/* __ __ - |\/| /\ | |\ | / ` /\ |\ | \ / /\ /__` - | | /~~\ | | \| \__, /~~\ | \| \/ /~~\ .__/ */ -#h { - left: 0; - display: block; - z-index: 5; -} diff --git a/assets/html/dev.html b/assets/html/dev.html deleted file mode 100644 index 15b5db72c..000000000 --- a/assets/html/dev.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - NexusLocal - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/html/nexus_local.html b/assets/html/nexus_local.html deleted file mode 100644 index 7f1a6dade..000000000 --- a/assets/html/nexus_local.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - NexusLocal - - - - - - -
- - -
-

Loading 🤓

-
Nexus Local
-
- - - - - - - - - - - - - - - - - - - - - diff --git a/assets/css/dev.css b/assets/nexus_local/nl.css similarity index 68% rename from assets/css/dev.css rename to assets/nexus_local/nl.css index 4842cd9a0..ee7a8cf86 100644 --- a/assets/css/dev.css +++ b/assets/nexus_local/nl.css @@ -1,10 +1,16 @@ -/* TODO: Fully test the difference with and without this.*/ +/*@font-face { + font-family: 'Inconsolata'; + src: url('Inconsolata.woff') format('woff'); +}*/ * { margin: 0; + /*user-select: none; + touch-action: none;*/ } html, body { + width: 100%; height: 100%; } diff --git a/assets/nexus_local/nl.html b/assets/nexus_local/nl.html new file mode 100644 index 000000000..ffde4b0b0 --- /dev/null +++ b/assets/nexus_local/nl.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/assets/audio/background_music.ogg b/assets/quasar/audio/background_music.ogg similarity index 100% rename from assets/audio/background_music.ogg rename to assets/quasar/audio/background_music.ogg diff --git a/assets/audio/checkbox_toggle.ogg b/assets/quasar/audio/checkbox_toggle.ogg similarity index 100% rename from assets/audio/checkbox_toggle.ogg rename to assets/quasar/audio/checkbox_toggle.ogg diff --git a/assets/audio/error.ogg b/assets/quasar/audio/error.ogg similarity index 100% rename from assets/audio/error.ogg rename to assets/quasar/audio/error.ogg diff --git a/assets/audio/on_disengage.ogg b/assets/quasar/audio/on_disengage.ogg similarity index 100% rename from assets/audio/on_disengage.ogg rename to assets/quasar/audio/on_disengage.ogg diff --git a/assets/audio/on_engage.ogg b/assets/quasar/audio/on_engage.ogg similarity index 100% rename from assets/audio/on_engage.ogg rename to assets/quasar/audio/on_engage.ogg diff --git a/assets/audio/on_hover.ogg b/assets/quasar/audio/on_hover.ogg similarity index 100% rename from assets/audio/on_hover.ogg rename to assets/quasar/audio/on_hover.ogg diff --git a/assets/audio/success.ogg b/assets/quasar/audio/success.ogg similarity index 100% rename from assets/audio/success.ogg rename to assets/quasar/audio/success.ogg diff --git a/assets/audio/transition.ogg b/assets/quasar/audio/transition.ogg similarity index 100% rename from assets/audio/transition.ogg rename to assets/quasar/audio/transition.ogg diff --git a/assets/audio/typing_sound.ogg b/assets/quasar/audio/typing_sound.ogg similarity index 100% rename from assets/audio/typing_sound.ogg rename to assets/quasar/audio/typing_sound.ogg diff --git a/assets/favicon/favicon.png b/assets/quasar/favicon/favicon.png similarity index 100% rename from assets/favicon/favicon.png rename to assets/quasar/favicon/favicon.png diff --git a/assets/texture/skybox/ba.jpg b/assets/quasar/texture/skybox/ba.jpg similarity index 100% rename from assets/texture/skybox/ba.jpg rename to assets/quasar/texture/skybox/ba.jpg diff --git a/assets/texture/skybox/bo.jpg b/assets/quasar/texture/skybox/bo.jpg similarity index 100% rename from assets/texture/skybox/bo.jpg rename to assets/quasar/texture/skybox/bo.jpg diff --git a/assets/texture/skybox/f.jpg b/assets/quasar/texture/skybox/f.jpg similarity index 100% rename from assets/texture/skybox/f.jpg rename to assets/quasar/texture/skybox/f.jpg diff --git a/assets/texture/skybox/l.jpg b/assets/quasar/texture/skybox/l.jpg similarity index 100% rename from assets/texture/skybox/l.jpg rename to assets/quasar/texture/skybox/l.jpg diff --git a/assets/texture/skybox/r.jpg b/assets/quasar/texture/skybox/r.jpg similarity index 100% rename from assets/texture/skybox/r.jpg rename to assets/quasar/texture/skybox/r.jpg diff --git a/assets/texture/skybox/t.jpg b/assets/quasar/texture/skybox/t.jpg similarity index 100% rename from assets/texture/skybox/t.jpg rename to assets/quasar/texture/skybox/t.jpg diff --git a/assets/texture/spritesheet/icons.png b/assets/quasar/texture/spritesheet/icons.png similarity index 100% rename from assets/texture/spritesheet/icons.png rename to assets/quasar/texture/spritesheet/icons.png diff --git a/assets/texture/third_party/hardwood/wood_parquet_02_ALB_1.png b/assets/quasar/texture/third_party/hardwood/wood_parquet_02_ALB_1.png similarity index 100% rename from assets/texture/third_party/hardwood/wood_parquet_02_ALB_1.png rename to assets/quasar/texture/third_party/hardwood/wood_parquet_02_ALB_1.png diff --git a/assets/texture/third_party/hardwood/wood_parquet_02_GLOSS_med.png b/assets/quasar/texture/third_party/hardwood/wood_parquet_02_GLOSS_med.png similarity index 100% rename from assets/texture/third_party/hardwood/wood_parquet_02_GLOSS_med.png rename to assets/quasar/texture/third_party/hardwood/wood_parquet_02_GLOSS_med.png diff --git a/assets/texture/third_party/hardwood/wood_parquet_02_NRM.png b/assets/quasar/texture/third_party/hardwood/wood_parquet_02_NRM.png similarity index 100% rename from assets/texture/third_party/hardwood/wood_parquet_02_NRM.png rename to assets/quasar/texture/third_party/hardwood/wood_parquet_02_NRM.png diff --git a/assets/texture/third_party/hardwood/wood_parquet_02_SPEC.png b/assets/quasar/texture/third_party/hardwood/wood_parquet_02_SPEC.png similarity index 100% rename from assets/texture/third_party/hardwood/wood_parquet_02_SPEC.png rename to assets/quasar/texture/third_party/hardwood/wood_parquet_02_SPEC.png diff --git a/assets/texture/third_party/transition.png b/assets/quasar/texture/third_party/transition.png similarity index 100% rename from assets/texture/third_party/transition.png rename to assets/quasar/texture/third_party/transition.png diff --git a/configs/code_manager.yml b/configs/code_manager.yml index 63c2dde9a..28f0bd11a 100644 --- a/configs/code_manager.yml +++ b/configs/code_manager.yml @@ -3,12 +3,6 @@ global_information: theme_color: '#6fff9a' assets: - .html: - PATH_DIRECTORY_DATA : '/quasar_source/assets/html/' - PATH_DIRECTORY_OUTPUT: '/quasar_source/var/web_assets/' - files : - nexus_local.html: ['pre_process', '/quasar_source/var/web_assets/nexus_local.min.css', 'minify', 'gzipped'] - dev.html : ['pre_process', '/quasar_source/var/web_assets/dev.min.css' , 'minify', 'gzipped'] .vert: PATH_DIRECTORY_DATA : '/quasar_source/assets/shaders/' PATH_DIRECTORY_OUTPUT: '/quasar_source/var/web_assets/' diff --git a/docker-compose.asset_server.yml b/docker-compose.asset_server.yml index 024bfaa42..ca7a639a6 100644 --- a/docker-compose.asset_server.yml +++ b/docker-compose.asset_server.yml @@ -3,44 +3,95 @@ version: '3.7' # Services collectively make up a distributed application. (0x1) services: - + # ---------------------------------------------------------------------------------------------------------------{0x0} + rabbit_manager: + tty: true + build: + context: '.' + dockerfile: './applications/rabbitmq_manager/Dockerfile' + environment: + _SERVICE_NAME: 'rabbit_manager' + RABBITMQ_ERLANG_COOKIE: 'secret string' + RABBITMQ_NODENAME: rabbit_manager + volumes: + - './applications/rabbitmq_manager/rabbitmq.config:/etc/rabbitmq/rabbitmq.config' + - './applications/rabbitmq_manager/definitions.json:/etc/rabbitmq/definitions.json' + ports: + - "5672:5672" + - "15672:15672" + - "25672:25672" + # ---------------------------------------------------------------------------------------------------------------{0x1} + nginx: + tty: true + build: + context: '.' + dockerfile: './applications/nginx/Dockerfile' + environment: + _SERVICE_NAME: "nginx" + ports: + - "80:80" + volumes: + - 'nexus_volume:/v' + - './applications/nginx/nl.nginx:/etc/nginx/nginx.conf' + depends_on: + - asset_server + - pgadmin4 + - rabbit_manager + # ---------------------------------------------------------------------------------------------------------------{0x2} asset_server: - tty : true + tty: true container_name: asset_server - #network_mode : host - build : - context : '.' + build: + context: '.' dockerfile: './applications/asset_server/Dockerfile' - ports : - - '80:80' - - '21:21' - - '20:20' - - '40000-50000:40000-50000' - volumes : + ports: + - "80:80" + volumes: - 'nexus_volume:/v' - './:/quasar_source' - environment : + - './applications/asset_server/src/www.conf:/etc/php7/php-fpm.d/www.conf' + environment: _SERVICE_NAME: 'asset_server' - DATABASE_URL : 'pgsql://postgres:password@postgres_server:5432/postgres' - + DATABASE_URL: 'pgsql://postgres:password@postgres_server:5432/postgres' + # ---------------------------------------------------------------------------------------------------------------{0x3} postgres_server: - tty : true + tty: true container_name: postgres_server - hostname : postgres - image : postgres - ports : - - '5432:5432' - volumes : + hostname: postgres + image: postgres + ports: + - "5432:5432" + volumes: - '/Users/utarsuno/code/quasar_source/var/db/postgres:/var/lib/postgresql/data' - environment : - POSTGRES_USER : 'postgres' - POSTGRES_DB : 'postgres' + environment: + POSTGRES_USER: 'postgres' + POSTGRES_DB: 'postgres' POSTGRES_PASSWORD: 'password' + # ---------------------------------------------------------------------------------------------------------------{0x4} + # https://hub.docker.com/r/dpage/pgadmin4/ + # https://info.crunchydata.com/blog/easy-postgresql-10-and-pgadmin-4-setup-with-docker + # TODO: env_var like how {https://github.com/khezen/compose-postgres/blob/master/docker-compose.yml} does it + pgadmin4: + container_name: pgadmin4 + hostname: pgadmin4 + image: dpage/pgadmin4 + environment: + PGADMIN_DEFAULT_EMAIL: 'pgadmin4@pgadmin.org' + PGADMIN_DEFAULT_PASSWORD: 'admin' + PGADMIN_ADMIN_PORT: '80' + PGADMIN_LISTEN_ADDRESS: '0.0.0.0' + SCRIPT_NAME: '/pgadmin4' + DEBUG: 'True' + volumes: + - '/Users/utarsuno/code/quasar_source/var/pgadmin/pgadmin:/root/.pgadmin' + - '/Users/utarsuno/code/quasar_source/var/pgadmin/lib:/var/lib/pgadmin' + - '/Users/utarsuno/code/quasar_source/applications/pgadmin/config.py:/pgadmin4/config.py' + # -------------------------------------------------------------------------------------------------------------------- -#networks: -# default: -# external: -# name: nexus_network +networks: + default: + external: + name: nexus_network volumes: nexus_volume: @@ -52,23 +103,6 @@ volumes: # jenkins-data: # external: true - # Serves static content and forwards requests to servers. -# dapp_nginx: - #hostname: nginx -# build: -# context: . -# dockerfile: ./applications/nginx/Dockerfile -# environment: -# _SERVICE_NAME: "dapp_nginx" - #container_name: nginx -# ports: -# - "80:80" -# - "3000:3000" -# tty: true -# volumes: -# - nexus_volume:/v -# - ./applications/nginx/nginx.nginx:/etc/nginx/nginx.conf - # Manages automated jobs, builds, etc. # jenkins: #hostname: jenkins diff --git a/docker-compose.yml b/docker-compose.yml index 4120072e2..be89a7905 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -35,10 +35,10 @@ services: tty: true #container_name: rabbit_manager volumes: - - './applications/rabbitmq_manager/rabbitmq.config:/etc/rabbitmq/rabitmq.config' + - './applications/rabbitmq_manager/rabbitmq.config:/etc/rabbitmq/rabbitmq.config' - './applications/rabbitmq_manager/definitions.json:/etc/rabbitmq/definitions.json' ports: - - '5672:5672' + - "5672:5672" - "15672:15672" - "25672:25672" diff --git a/libraries/bash/common.sh b/libraries/bash/common.sh index 577727049..90b1c641e 100644 --- a/libraries/bash/common.sh +++ b/libraries/bash/common.sh @@ -15,4 +15,4 @@ str_contains () { # Date : 'answered Feb 6 '18 at 2:29' esc () { printf "%s\n" "$1" | sed -e "s/'/'\"'\"'/g" -e "1s/^/'/" -e "\$s/\$/'/" -} \ No newline at end of file +} diff --git a/libraries/bash/utils_composer.sh b/libraries/bash/utils_composer.sh index a685f8f57..d17c12169 100644 --- a/libraries/bash/utils_composer.sh +++ b/libraries/bash/utils_composer.sh @@ -14,6 +14,10 @@ composer_health_check () { #composer validate --with-dependencies --strict } +composer_test () { + composer dump-env dev -vvv +} + composer_update_full () { sudo -H composer self-update } @@ -28,4 +32,4 @@ composer_install () { composer_optimize () { composer dump-autoload --optimize --classmap-authoritative -vvv -} \ No newline at end of file +} diff --git a/libraries/front_end/engine/hud.js b/libraries/front_end/engine/hud.js new file mode 100644 index 000000000..dbba1f164 --- /dev/null +++ b/libraries/front_end/engine/hud.js @@ -0,0 +1,58 @@ + +let HUD = function(){}; +HUD.prototype = { + + GLOBAL_DATA: [ + {"id":1,"created_at":1564399210,"completed_at":1564413610,"due_at":1564410610,"iteration":0,"iterations_needed":1,"time_needed":null,"description":"Reply to Recruiter email"}, + {"id":2,"created_at":1564399210,"completed_at":1564413610,"due_at":1564413610,"iteration":0,"iterations_needed":1,"time_needed":null,"description":"Pay AT&T Internet Bill"}, + {"id":3,"created_at":1564399210,"completed_at":1564413610,"due_at":1564434610,"iteration":0,"iterations_needed":1,"time_needed":null,"description":"Pay Dieken phone bill"}, + ], + + __init__: function() { + this.hud = document.getElementById('b'); + this.context = this.hud.getContext('2d'); + }, + + render: function() { + console.log('Rendered!'); + //this.context.beginPath(); + //this.context.arc(150,150,50,0,2 * Math.PI); + //this.context.stroke(); + + this.context.clearRect(0, 0, this.hud.width, this.hud.height); + //this.context.font = '128px Arial'; + this.context.font = 'bold 64px Helvetica'; + + let i; + let y = 200; + for (i = 0; i < this.GLOBAL_DATA.length; i++) { + let row = this.GLOBAL_DATA[i]; + + var date = new Date(row['due_at']*1000); + var s0 = new Date(row['due_at']*1000).toLocaleDateString('en-US'); + var s1 = new Date(row['due_at']*1000).toLocaleTimeString('en-US'); + + this.context.fillText( + 'TASK[' + row['description'] + '], DUE AT[' + (s0 + '\t' + s1) + ']', 200, 200 + y + //'TASK[' + this.GLOBAL_DATA['description'] + '], DUE IN[' + this.GLOBAL_DATA['due_at'] + ']', 200, 200 + ); + + y += 72; + } + }, + + set_dimensions: function(w, h) { + this.hud.width = w * 2; + this.hud.height = h * 2; + this.hud.style.width = w; + this.hud.style.height = h; + this.context.width = w * 2; + this.context.height = h * 2; + } +}; + +let _hud = new HUD(); + +export default { + singleton_hud: _hud +} diff --git a/libraries/front_end/hello_world.js b/libraries/front_end/hello_world.js index 1cb02392d..95d792235 100644 --- a/libraries/front_end/hello_world.js +++ b/libraries/front_end/hello_world.js @@ -1,6 +1,7 @@ import * as THREE from '../../applications/asset_server/js/node_modules/three'; import DataStructureFlags31 from './data_structures/bitwise_flags_max_31'; import InputMouse from './engine/input/mouse'; +import HUD from './engine/hud'; /* -- F L A G S -- I N T -- @@ -29,81 +30,90 @@ THREE.Cache.enabled = true; THREE.Object3D.DefaultMatrixAutoUpdate = false; -let Engine = function() { - let self = this; +function loadJSON(callback) { + var xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open('GET', 'data.json', true); // Replace 'my_data' with the path to your file + xobj.onreadystatechange = function () { + if (xobj.readyState === 4 && xobj.status === "200") { + // Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode + callback(xobj.responseText); + } + }; + xobj.send(null); +} - let main_canvas = document.getElementById('a'); - this.hud = document.getElementById('b'); - this.hud_context = this.hud.getContext('2d'); - this.hud_context.beginPath(); - this.hud_context.arc(150,150,50,0,2*Math.PI); - this.hud_context.stroke(); - var scene = new THREE.Scene(); - var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 ); +let Engine = function() { + let self = this; + this.json_data = null; + + //loadJSON(function (response) { + // self.json_data = response; + // console.log('THE RESPONSE WAS'); + // console.log(response); + //}); + + let main_canvas = document.getElementById('a'); + this.hud = HUD.singleton_hud; + this.hud.__init__(); + this.hud.render(); this.renderer = new THREE.WebGLRenderer({canvas: main_canvas, context: main_canvas.getContext('webgl2')}); //renderer.setClearColor(0xffffff, 1); - - this.renderer.setSize( window.innerWidth, window.innerHeight ); + this.renderer.setSize(window.innerWidth, window.innerHeight); //document.body.appendChild( renderer.domElement ); - var geometry = new THREE.BoxGeometry( 1, 1, 1 ); - var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); - var cube = new THREE.Mesh( geometry, material ); - scene.add( cube ); + var scene = new THREE.Scene(); + var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 ); + let geometry = new THREE.BoxGeometry(1, 1, 1); + let material = new THREE.MeshBasicMaterial({}); //color: 0x00ff00 + let cube = new THREE.Mesh(geometry, material); + scene.add(cube); camera.position.z = 5; + this.event_action_resize = function() { + // TODO: Eventually throttle this event (only execute once no event is no longer sent for longer than 200 ms?). + this.cached_ints[1] = window.innerWidth; + this.cached_ints[2] = window.innerHeight; + this.cached_floats[3] = window.innerWidth / window.innerHeight; + this.renderer.setSize(self.cached_ints[1], self.cached_ints[2]); + this.hud.set_dimensions(self.cached_ints[1], self.cached_ints[2]); + + self.hud.render(); + self.renderer.render(scene, camera); + }; + this.animate = function () { requestAnimationFrame( self.animate ); - cube.rotation.x += 0.01; cube.rotation.y += 0.01; - - self.renderer.render( scene, camera ); + //self.hud.render(); + //self.renderer.render(scene, camera); }; + // Make sure proper resolution gets set as soon as possible. + this.event_action_resize(); this.animate(); - - - - - - - - - // E V E N T {window resize} window.addEventListener('resize', function(event) { event.preventDefault(); //event.stopPropagation(); - // TODO: Eventually throttle this event (only execute once no event is no longer sent for longer than 200 ms?). - self.cached_ints[1] = window.innerWidth; - self.cached_ints[2] = window.innerHeight; - self.cached_floats[3] = window.innerWidth / window.innerHeight; - //self._update_renderer_dimensions(); - - console.log('On resize!'); - self.renderer.setSize(self.cached_ints[1], self.cached_ints[2]); - self.hud.width = self.cached_ints[1]; - self.hud.height = self.cached_ints[2]; - - self.hud_context.beginPath(); - self.hud_context.arc(150,150,50,0,2*Math.PI); - self.hud_context.stroke(); + self.event_action_resize(); return false; }, true); }; + Engine.prototype = { // C A C H E D - I N T E G E R S. cached_ints : new Uint32Array(4), @@ -113,6 +123,10 @@ Engine.prototype = { }; + + + + let engine = new Engine(); diff --git a/libraries/php/BuildProcess/Abstractions/AssetBuildSection.php b/libraries/php/BuildProcess/Abstractions/AssetBuildSection.php deleted file mode 100644 index 99f31c86e..000000000 --- a/libraries/php/BuildProcess/Abstractions/AssetBuildSection.php +++ /dev/null @@ -1,69 +0,0 @@ -config_yaml_set_data( - $this->config_universal_get(SCHEMAS::YAML_ASSETS), $code_builder->config_yaml_get(['assets', $name]) - ); - - $this->repo_entity_files = $this->get_repo(RepoFile::class); - $directory_data = $this->config_yaml_get(PATHS::DIRECTORY_DATA); - foreach ($this->config_yaml_get('files') as $k => $v) { - $this->file_builds[$directory_data . $k] = $v; - } - } - - private function parse_file(string $file, array $flags) { - if ($this->repo_entity_files->has_entity($file)) { - $f = $this->process_entity($this->repo_entity_files->get_entity($file)); - } else { - $f = $this->repo_entity_files->create_new_entity($file); - } - - #if ($this->has_flag_processed($flags)) { - # $result = $this->handle_step_processed($f, $flags[1]); - # $f = $result ?? $f; - #} - #if ($this->has_flag_minified($flags)) { - # $f = $this->repo_entity_files->ensure_file_has_child($f, $this->get_path_output() . $f->get_full_name_minified(), EntityFile::FLAG_MINIFY); - #} - #if ($this->has_flag_gzipped($flags)) { - # $f = $this->repo_entity_files->ensure_file_has_child($f, $this->get_path_output() . $f->get_full_name_gzipped(), EntityFile::FLAG_GZIP); - #} - } - - public function perform_work() : void { - foreach ($this->file_builds as $file => $flags) { - $this->parse_file($file, $flags); - } - } - - protected function get_path_output(): string { - return $this->config_yaml_get(PATHS::DIRECTORY_OUTPUT); - } -} diff --git a/libraries/php/BuildProcess/Abstractions/BuildSection.php b/libraries/php/BuildProcess/Abstractions/BuildSection.php deleted file mode 100644 index 06404fa94..000000000 --- a/libraries/php/BuildProcess/Abstractions/BuildSection.php +++ /dev/null @@ -1,58 +0,0 @@ -service_get_logger()); - $this->code_builder = $code_builder; - } - - /** - * @param string $repo_name - * @return ObjectRepository - */ - public function get_repo(string $repo_name): ObjectRepository { - return $this->code_builder->get_repo($repo_name); - } - - protected function process_entity($entity) { - if ($entity->cache_needs_update(true)) { - #$entity->set_state(EntityState::STATE_UPDATED); - } else { - #$entity->set_state(EntityState::STATE_NO_CHANGE); - } - return $entity; - } - - /** - * @param string $key - * @return mixed - */ - public function config_universal_get(string $key) { - return $this->code_builder->config_universal_get($key); - } -} - diff --git a/libraries/php/BuildProcess/Abstractions/UnitOfWork.php b/libraries/php/BuildProcess/Abstractions/UnitOfWork.php deleted file mode 100644 index e3815dffa..000000000 --- a/libraries/php/BuildProcess/Abstractions/UnitOfWork.php +++ /dev/null @@ -1,81 +0,0 @@ -service_set_logger($logger); - $this->set_name_and_label($name, 'Step'); - $this->init_trait_timer(false); - } - - public function run_unit_of_work(): void { - $this->header($this->name); - $this->timer->start(); - $this->pre_work(); - $this->perform_work(); - $this->post_work(); - $this->timer->stop(); - if ($this->failed()) { - $this->log('--- ' . $this->name . ' failed in {' . $this->timer->get_delta() . '}---'); - $this->header(STR::brackets($this->name . ' failed in ', $this->timer->get_delta())); - $this->print_header(self::HEADER_FAILED); - # TODO: stop the rest of the build! - } else { - $this->log('--- ' . $this->name . ' completed in {' . $this->timer->get_delta() . '}---'); - $this->header(STR::brackets($this->name . ' completed in ', $this->timer->get_delta())); - } - } - - /** - * @param string $result - */ - private function print_header(string $result): void { - $this->header(STR::brackets($this->name . ' ' . $result . ' in ', $this->timer->get_delta())); - } - - protected function mark_as_failed(): void { - $this->step_failed = true; - } - - /** - * @return bool - */ - protected function failed(): bool { - return $this->step_failed; - } - - abstract protected function pre_work(): void; - - abstract protected function perform_work(): void; - - abstract protected function post_work(): void; - -} \ No newline at end of file diff --git a/libraries/php/BuildProcess/HTMLBuildSection.php b/libraries/php/BuildProcess/HTMLBuildSection.php deleted file mode 100644 index b4a043ad7..000000000 --- a/libraries/php/BuildProcess/HTMLBuildSection.php +++ /dev/null @@ -1,81 +0,0 @@ -', '', self::PRE_PROCESS_CSS]; - private const PATTERN_SUB_CSS_FILE_LINE = ['/*', '}*/', self::PRE_PROCESS_CSS]; - - private const PATTERN_MANIFEST = '/*' . self::PRE_PROCESS . 'manifest'; - private const PATTERN_SUB_MANIFEST_REPLACE = '/*#pre-process-manifest{default}*/'; - - private const RAW_WEB_MANIFEST = [ - 'name' => 'QuasarSource', - 'short_name' => 'QS', - 'lang' => 'en', - 'description' => 'QuasarSource in development.', - 'display' => 'fullscreen', - 'orientation' => 'landscape', - #'theme_color' => '#6fff9a', - #'background_color' => '#3a3a3a', - 'start_url' => '/', - #'icons' => [ - # 'src' => '/p2.png', - # 'sizes' => '64x64', - # 'type' => 'image/png' - #] - ]; - - /** @var string */ - private $web_manifest_default; - - public function __construct(CodeBuilderService $code_builder) { - parent::__construct(EXTENSION::HTML, $code_builder); - $this->web_manifest_default = 'data:application/manifest+json,' . json_encode(self::RAW_WEB_MANIFEST); - } - - protected function handle_step_processed(EntityFile $file, string $output_file_path): ?EntityFile { - $file_path = $file->getFullPath(); - $processed_lines = []; - $lines = UFO::get($file_path); - foreach ($lines as $line) { - if (STR::has($line, self::PATTERN_CSS)) { - $this->process_line_css($line, $processed_lines); - } else if (STR::has($line, self::PATTERN_MANIFEST)) { - $this->process_line_manifest($line, $processed_lines); - } else { - $processed_lines[] = $line; - } - } - - $path_processed = $this->get_path_output() . $file->get_full_name_processed(); - UFO::set($path_processed, $processed_lines); - return $this->repo_entity_files->ensure_file_has_child($file, $path_processed, EntityFile::FLAG_PRE_PROCESS); - } - - private function process_line_css(string $line, array & $processed_lines): void { - $css_file_name = STR::remove(trim($line), self::PATTERN_SUB_CSS_FILE_NAME); - #if (!$this->repo_entity_files->has_checked_file_by_path($css_file_name)) { - # DBG::throw_exception('Needed pre-process file not found in memory {' . $css_file_name . '}'); - #} - $modified_line = STR::remove($line, self::PATTERN_SUB_CSS_FILE_LINE); - #$processed_lines[] = STR::replace($modified_line, $css_file_name, CSS::get($css_file_name)); - } - - private function process_line_manifest(string $line, array & $processed_lines): void { - $processed_lines[] = STR::replace($line, self::PATTERN_SUB_MANIFEST_REPLACE, $this->web_manifest_default); - } - -} - diff --git a/libraries/php/BuildProcess/NPMLibBuildSection.php b/libraries/php/BuildProcess/NPMLibBuildSection.php deleted file mode 100644 index 9b55ace37..000000000 --- a/libraries/php/BuildProcess/NPMLibBuildSection.php +++ /dev/null @@ -1,39 +0,0 @@ -config_initialize( - ['npm' => null], - $code_builder->config_yaml_get_all() - ); - $this->repo = $this->get_repo(RepoNPMLib::class); - } - - protected function perform_work(): void { - foreach ($this->config_yaml_get_all() as $file_value) { - if (!$this->repo->has_entity($file_value)) { - $this->repo->create_new_entity($file_value); - } else { - $this->process_entity($this->repo->get_entity($file_value)); - } - } - } - -} - diff --git a/libraries/php/BuildProcess/QAReportBuildSection.php b/libraries/php/BuildProcess/QAReportBuildSection.php deleted file mode 100644 index f18f3aac5..000000000 --- a/libraries/php/BuildProcess/QAReportBuildSection.php +++ /dev/null @@ -1,52 +0,0 @@ -config_initialize( - ['stats' => ['unit_tests' => null]], - $code_builder->config_yaml_get('qa_report') - ); - $this->repo_entity_files = $this->get_repo(RepoFile::class); - $this->repo = $this->get_repo(RepoSnapshotQA::class); - } - - protected function perform_work() : void { - foreach ($this->config_yaml_get('stats') as $stat => $file_path) { - if (!$this->repo_entity_files->has_entity($file_path)) { - $this->event_qa_entity_file_not_stored_in_db($file_path); - } else { - $this->process_entity($this->repo_entity_files->get_entity($file_path)); - } - } - } - - protected function on_entity_update($entity) { - $this->repo->create_new_entity($entity); - } - - private function event_qa_entity_file_not_stored_in_db(string $file_path): void { - $entity_file = $this->repo_entity_files->create_new_entity($file_path); - $this->repo->create_new_entity($entity_file); - } - -} - diff --git a/libraries/php/CodeGeneration/CodeSpawnerHTML.php b/libraries/php/CodeGeneration/CodeSpawnerHTML.php new file mode 100644 index 000000000..b7395c4c7 --- /dev/null +++ b/libraries/php/CodeGeneration/CodeSpawnerHTML.php @@ -0,0 +1,87 @@ +html); + for ($c = 0; $c < $num_lines; $c++) { + $this->html[$c] = "\t" . $this->html[$c]; + } + return $this; + } + + /** + * @return array + */ + public function get_contents(): array { + return $this->html; + } + + /** + * @param string $name + * @param string $content + * @return CodeSpawnerHTML + */ + public function meta(string $name, string $content): CodeSpawnerHTML { + return $this->add(''); + } + + /** + * @param string $manifest + * @return CodeSpawnerHTML + */ + public function manifest(string $manifest): CodeSpawnerHTML { + return $this->add(''); + } + + /** + * @param string $title + * @return CodeSpawnerHTML + */ + public function title(string $title): CodeSpawnerHTML { + return $this->add('' . $title . ''); + } + + /** + * @param string $title + * @return CodeSpawnerHTML + */ + public function style(string $title): CodeSpawnerHTML { + return $this->add(''); + } + + /** + * @param string $html_code + * @return CodeSpawnerHTML + */ + private function add(string $html_code): CodeSpawnerHTML { + if (STR::ends_in($html_code, PHP_EOL)) { + $this->html[] = $html_code; + } else { + $this->html[] = $html_code . PHP_EOL; + } + return $this; + } + +} diff --git a/libraries/php/CommonFeatures/TraitEnvironmentVariablesAsFields.php b/libraries/php/CommonFeatures/TraitEnvVarsAsFields.php similarity index 95% rename from libraries/php/CommonFeatures/TraitEnvironmentVariablesAsFields.php rename to libraries/php/CommonFeatures/TraitEnvVarsAsFields.php index 5bf8d4716..df8d4a8b6 100644 --- a/libraries/php/CommonFeatures/TraitEnvironmentVariablesAsFields.php +++ b/libraries/php/CommonFeatures/TraitEnvVarsAsFields.php @@ -6,10 +6,10 @@ use QuasarSource\Utils\SystemOS\UtilsSystem as SYS; /** - * Trait TraitAliveOrDead + * Trait TraitEnvVarsAsFields * @package QuasarSource\CommonFeatures */ -trait TraitEnvironmentVariablesAsFields { +trait TraitEnvVarsAsFields { /** * @param string $field_name diff --git a/libraries/php/DataStructure/BuildStep/BuildStep.php b/libraries/php/DataStructure/BuildStep/BuildStep.php index 1b20a8265..b73583b4f 100644 --- a/libraries/php/DataStructure/BuildStep/BuildStep.php +++ b/libraries/php/DataStructure/BuildStep/BuildStep.php @@ -7,7 +7,6 @@ use QuasarSource\CommonFeatures\TraitTimer; use QuasarSource\DataStructure\FlagTable\TraitFlagTable; use QuasarSource\Utils\DataType\UtilsArray as ARY; -use QuasarSource\Utils\DataType\UtilsString as STR; use Throwable; /** @@ -47,6 +46,10 @@ public function __construct(string $name) { $this->flags_set_all([self::FLAG_STARTED, self::FLAG_FAILED, self::FLAG_INTERRUPTED, self::FLAG_COMPLETED, self::FLAG_RECOVERED]); } + public function __destruct() { + unset($this->callbacks, $this->callbacks_on_failed, $this->callbacks_on_passed, $this->callback_executions, $this->last_exception_thrown); + } + /** * @return mixed */ @@ -97,6 +100,8 @@ private function execute_callback(string $description, callable $callback): bool * @throws Throwable */ public function run_step(int $n): void { + # TODO: TIMER! + $index = 0; $index_found = false; foreach ($this->callbacks as $desc => $callback) { @@ -148,7 +153,7 @@ public function run(): void { * @throws Throwable */ private function run_on_failed_if_exists(string $description): void { - if (!$this->has_on_failed($description)) { + if (!array_key_exists($description, $this->callbacks_on_failed)) { throw $this->last_exception_thrown; } $on_failed = $this->execute_callback($description, $this->callbacks_on_failed[$description]); @@ -172,7 +177,7 @@ private function has_step_already_ran(string $description): bool { * @throws Throwable */ private function run_on_passed_if_exists(string $description): void { - if ($this->has_on_passed($description)) { + if (array_key_exists($description, $this->callbacks_on_passed)) { $on_passed = $this->execute_callback($description, $this->callbacks_on_passed[$description]); if (!$on_passed) { throw $this->last_exception_thrown; @@ -210,20 +215,4 @@ protected function passed(): bool { return $this->flag_is_off(self::FLAG_FAILED) && $this->flag_is_on(self::FLAG_COMPLETED); } - /** - * @param string $desc - * @return bool - */ - private function has_on_failed(string $desc): bool { - return array_key_exists($desc, $this->callbacks_on_failed); - } - - /** - * @param string $desc - * @return bool - */ - private function has_on_passed(string $desc): bool { - return array_key_exists($desc, $this->callbacks_on_passed); - } - } \ No newline at end of file diff --git a/libraries/php/DataStructure/FlagTable/TraitFlagsTable.php b/libraries/php/DataStructure/FlagTable/TraitFlagsTable.php index abdbee57b..8867c8763 100644 --- a/libraries/php/DataStructure/FlagTable/TraitFlagsTable.php +++ b/libraries/php/DataStructure/FlagTable/TraitFlagsTable.php @@ -70,6 +70,14 @@ public function flags_set_all(array $flags, $value=false): void { } } + /** + * @param array $flags + */ + public function flags_set_all_on(array $flags): void { + $this->flags_set_all($flags, true); + } + + /** * @param string $flag * @return bool diff --git a/libraries/php/SQL/Doctrine/Entity/Field/Boolean/TraitBool0.php b/libraries/php/Doctrine/Entity/Field/Boolean/TraitBool0.php similarity index 81% rename from libraries/php/SQL/Doctrine/Entity/Field/Boolean/TraitBool0.php rename to libraries/php/Doctrine/Entity/Field/Boolean/TraitBool0.php index d43a88eec..01d832d94 100644 --- a/libraries/php/SQL/Doctrine/Entity/Field/Boolean/TraitBool0.php +++ b/libraries/php/Doctrine/Entity/Field/Boolean/TraitBool0.php @@ -1,12 +1,12 @@ hexcolor0; + } + + /** + * @param string $hex_color0 + * @return self + */ + public function setHexColor0(string $hex_color0): self { + $this->verify_value($hex_color0); + $this->hexcolor0 = strtoupper($hex_color0); + return $this; + } +} diff --git a/libraries/php/Doctrine/Entity/Field/Color/TraitHexColor1.php b/libraries/php/Doctrine/Entity/Field/Color/TraitHexColor1.php new file mode 100644 index 000000000..6bd82a0ac --- /dev/null +++ b/libraries/php/Doctrine/Entity/Field/Color/TraitHexColor1.php @@ -0,0 +1,36 @@ +hexcolor1; + } + + /** + * @param string $hex_color1 + * @return self + */ + public function setHexColor1(string $hex_color1): self { + $this->verify_value($hex_color1); + $this->hexcolor1 = strtoupper($hex_color1); + return $this; + } +} diff --git a/libraries/php/SQL/Doctrine/Entity/Field/EnumFields.php b/libraries/php/Doctrine/Entity/Field/EnumFields.php similarity index 58% rename from libraries/php/SQL/Doctrine/Entity/Field/EnumFields.php rename to libraries/php/Doctrine/Entity/Field/EnumFields.php index c6a247ad4..8a9c66811 100644 --- a/libraries/php/SQL/Doctrine/Entity/Field/EnumFields.php +++ b/libraries/php/Doctrine/Entity/Field/EnumFields.php @@ -1,25 +1,34 @@ float0; } diff --git a/libraries/php/SQL/Doctrine/Entity/Field/Number/Int/Byte/TraitSizeInBytes.php b/libraries/php/Doctrine/Entity/Field/Number/Int/Byte/TraitSizeInBytes.php similarity index 56% rename from libraries/php/SQL/Doctrine/Entity/Field/Number/Int/Byte/TraitSizeInBytes.php rename to libraries/php/Doctrine/Entity/Field/Number/Int/Byte/TraitSizeInBytes.php index 6a18720e3..4be46df6d 100644 --- a/libraries/php/SQL/Doctrine/Entity/Field/Number/Int/Byte/TraitSizeInBytes.php +++ b/libraries/php/Doctrine/Entity/Field/Number/Int/Byte/TraitSizeInBytes.php @@ -1,14 +1,14 @@ verify_value($size_in_bytes); $this->size_in_bytes = $size_in_bytes; return $this; } + /** + * @param int $size_in_bytes + * @return bool + */ + public function syncSizeInBytes(int $size_in_bytes): bool { + $this->verify_value($size_in_bytes); + if ($this->size_in_bytes !== $size_in_bytes) { + $this->size_in_bytes = $size_in_bytes; + return true; + } + return false; + } + + /** + * @param int $size_in_bytes + */ + private function verify_value(int $size_in_bytes): void { + if (!UtilsDoctrine::does_value_fit_into_int($size_in_bytes)) { + throw new InvalidArgumentException('SmallInt0{' . $size_in_bytes . '} is either too small or too large!'); + } + } } diff --git a/libraries/php/SQL/Doctrine/Entity/Field/Number/Int/Small/TraitEntityType.php b/libraries/php/Doctrine/Entity/Field/Number/Int/Small/TraitEntityType.php similarity index 82% rename from libraries/php/SQL/Doctrine/Entity/Field/Number/Int/Small/TraitEntityType.php rename to libraries/php/Doctrine/Entity/Field/Number/Int/Small/TraitEntityType.php index 73cf3aacf..e8b18156a 100644 --- a/libraries/php/SQL/Doctrine/Entity/Field/Number/Int/Small/TraitEntityType.php +++ b/libraries/php/Doctrine/Entity/Field/Number/Int/Small/TraitEntityType.php @@ -1,14 +1,14 @@ smallint1; } diff --git a/libraries/php/SQL/Doctrine/Entity/Field/Text/Blob/TraitBigText0.php b/libraries/php/Doctrine/Entity/Field/Text/Blob/TraitBigText0.php similarity index 78% rename from libraries/php/SQL/Doctrine/Entity/Field/Text/Blob/TraitBigText0.php rename to libraries/php/Doctrine/Entity/Field/Text/Blob/TraitBigText0.php index 911917421..bab34b17f 100644 --- a/libraries/php/SQL/Doctrine/Entity/Field/Text/Blob/TraitBigText0.php +++ b/libraries/php/Doctrine/Entity/Field/Text/Blob/TraitBigText0.php @@ -1,13 +1,13 @@ description; + } + + /** + * @param string $description + * @return self + */ + public function setDescription(string $description): self { + $this->description = $description; + return $this; + } + +} diff --git a/libraries/php/Doctrine/Entity/Field/Text/TraitPath.php b/libraries/php/Doctrine/Entity/Field/Text/TraitPath.php new file mode 100644 index 000000000..b9ff12562 --- /dev/null +++ b/libraries/php/Doctrine/Entity/Field/Text/TraitPath.php @@ -0,0 +1,91 @@ +path_cache_directory, $this->path_cache_file_name, $this->path_cache_file_name_full, $this->path_cache_file_extensions); + } + + /** + * @return string + */ + public function getPath(): string { + return $this->path; + } + + /** + * @param string $path + * @return self + */ + public function setPath(string $path): self { + if ($this->path !== $path) { + PATH::is_valid($path, true); + $this->path = $path; + $this->calculate_cache_for_paths(false); + } + return $this; + } + + /** + * @return string + */ + public function get_path_directory(): string { + $this->calculate_cache_for_paths(true); + return $this->path_cache_directory; + } + + /** + * @param bool $with_extensions + * @return string + */ + public function get_file_name(bool $with_extensions=false): string { + $this->calculate_cache_for_paths(true); + if ($with_extensions) { + return $this->path_cache_file_name_full; + } + return $this->path_cache_file_name; + } + + /** + * @return string + */ + public function get_file_extensions(): string { + $this->calculate_cache_for_paths(true); + return $this->path_cache_file_extensions; + } + + /** + * @param bool $set_only_if_null + * @return TraitPath + */ + private function calculate_cache_for_paths(bool $set_only_if_null=false): self { + if (!$set_only_if_null || ($set_only_if_null && $this->path_cache_directory === null)) { + $segments = PATH::get_all_path_segments($this->path); + $this->path_cache_directory = $segments[0]; + $this->path_cache_file_name = $segments[1]; + $this->path_cache_file_extensions = $segments[2]; + $this->path_cache_file_name_full = $this->path_cache_file_name . $this->path_cache_file_extensions; + } + return $this; + } +} diff --git a/libraries/php/SQL/Doctrine/Entity/Field/Text/TraitSHA512Sum.php b/libraries/php/Doctrine/Entity/Field/Text/TraitSHA512Sum.php similarity index 62% rename from libraries/php/SQL/Doctrine/Entity/Field/Text/TraitSHA512Sum.php rename to libraries/php/Doctrine/Entity/Field/Text/TraitSHA512Sum.php index 98f64385b..7986ee323 100644 --- a/libraries/php/SQL/Doctrine/Entity/Field/Text/TraitSHA512Sum.php +++ b/libraries/php/Doctrine/Entity/Field/Text/TraitSHA512Sum.php @@ -1,6 +1,6 @@ latest_sha512sum_to_update_to); + } + + /** + * @param string $sum + * @return bool + */ + public function syncSHA512Sum(string $sum): bool { + if ($this->sha512sum !== $sum) { + $this->sha512sum = $sum; + return true; + } + return false; + } + /** * @return string */ diff --git a/applications/asset_server/code_manager/src/Entity/Abstractions/Traits/Text/FieldText.php b/libraries/php/Doctrine/Entity/Field/Text/TraitText0.php similarity index 75% rename from applications/asset_server/code_manager/src/Entity/Abstractions/Traits/Text/FieldText.php rename to libraries/php/Doctrine/Entity/Field/Text/TraitText0.php index a045fd7a4..9b24dca1f 100644 --- a/applications/asset_server/code_manager/src/Entity/Abstractions/Traits/Text/FieldText.php +++ b/libraries/php/Doctrine/Entity/Field/Text/TraitText0.php @@ -1,18 +1,18 @@ text3; + } + + /** + * @param string $text3 + * @return self + */ + public function setText3(string $text3): self { + $this->text3 = $text3; + return $this; + } +} diff --git a/libraries/php/Doctrine/Entity/Field/Text/TraitText4.php b/libraries/php/Doctrine/Entity/Field/Text/TraitText4.php new file mode 100644 index 000000000..d02adcf86 --- /dev/null +++ b/libraries/php/Doctrine/Entity/Field/Text/TraitText4.php @@ -0,0 +1,35 @@ +text4; + } + + /** + * @param string $text4 + * @return self + */ + public function setText4(string $text4): self { + $this->text4 = $text4; + return $this; + } +} diff --git a/libraries/php/SQL/Doctrine/Entity/Field/Time/TraitUnixTime0.php b/libraries/php/Doctrine/Entity/Field/Time/TraitUnixTime0.php similarity index 85% rename from libraries/php/SQL/Doctrine/Entity/Field/Time/TraitUnixTime0.php rename to libraries/php/Doctrine/Entity/Field/Time/TraitUnixTime0.php index 8c6c4b5d6..c5a523ae9 100644 --- a/libraries/php/SQL/Doctrine/Entity/Field/Time/TraitUnixTime0.php +++ b/libraries/php/Doctrine/Entity/Field/Time/TraitUnixTime0.php @@ -1,13 +1,13 @@ unix_time1)) { $this->unix_time1 = (int) $this->unix_time1; } @@ -29,10 +29,10 @@ public function getUnixTime0(): ?int { } /** - * @param int $unix_time1 + * @param int $unix_time1 * @return self */ - public function setUnixTime0(int $unix_time1=-1): self { + public function setUnixTime1(int $unix_time1=-1): self { if ($unix_time1 === -1) { $this->unix_time1 = UNIX::now(); } else { diff --git a/libraries/php/Doctrine/Entity/Field/Time/TraitUnixTime2.php b/libraries/php/Doctrine/Entity/Field/Time/TraitUnixTime2.php new file mode 100644 index 000000000..84a0a7f30 --- /dev/null +++ b/libraries/php/Doctrine/Entity/Field/Time/TraitUnixTime2.php @@ -0,0 +1,44 @@ +unix_time2)) { + $this->unix_time2 = (int) $this->unix_time2; + } + return $this->unix_time2; + } + + /** + * @param int $unix_time2 + * @return self + */ + public function setUnixTime2(int $unix_time2=-1): self { + if ($unix_time2 === -1) { + $this->unix_time2 = UNIX::now(); + } else { + $this->unix_time2 = $unix_time2; + } + return $this; + } + +} diff --git a/libraries/php/SQL/Doctrine/UtilsDoctrine.php b/libraries/php/Doctrine/UtilsDoctrine.php similarity index 93% rename from libraries/php/SQL/Doctrine/UtilsDoctrine.php rename to libraries/php/Doctrine/UtilsDoctrine.php index 8f1c2626c..aa8f7dd5f 100644 --- a/libraries/php/SQL/Doctrine/UtilsDoctrine.php +++ b/libraries/php/Doctrine/UtilsDoctrine.php @@ -1,12 +1,13 @@ api_secret = $api_secret; diff --git a/libraries/php/SQL/Doctrine/Entity/Field/Text/TraitFullPath.php b/libraries/php/SQL/Doctrine/Entity/Field/Text/TraitFullPath.php deleted file mode 100644 index b53347297..000000000 --- a/libraries/php/SQL/Doctrine/Entity/Field/Text/TraitFullPath.php +++ /dev/null @@ -1,50 +0,0 @@ -path_cache_directory, $this->path_cache_file_name, $this->path_cache_file_name_full, $this->path_cache_file_extensions); - } - - /** - * @return string - */ - public function getFullPath(): string { - return $this->full_path; - } - - /** - * @param string $full_path - * @return self - */ - public function setFullPath(string $full_path): self { - PATH::is_valid($full_path, true); - $this->full_path = $full_path; - $segments = PATH::get_all_path_segments($full_path); - $this->path_cache_directory = $segments[0]; - $this->path_cache_file_name = $segments[1]; - $this->path_cache_file_extensions = $segments[2]; - $this->path_cache_file_name_full = $this->path_cache_file_name . $this->path_cache_file_extensions; - return $this; - } -} diff --git a/libraries/php/Traits/pattern_parent_child/InterfacePatternChild.php b/libraries/php/Traits/pattern_parent_child/InterfacePatternChild.php deleted file mode 100644 index 02ed2eda1..000000000 --- a/libraries/php/Traits/pattern_parent_child/InterfacePatternChild.php +++ /dev/null @@ -1,14 +0,0 @@ -parent !== null; - } - - /** - * @param $parent - * @param bool $raise_exception_if_parent_exists - * @throws LogicException - */ - public function set_parent($parent, bool $raise_exception_if_parent_exists=true): void { - if ($raise_exception_if_parent_exists && ($this->parent !== null && $parent !== $this->parent)) { - throw LogicException::invalid_function_call('set_parent', 'Can not set parent when current parent is not null!'); - } - $this->parent = $parent; - if (!$this->parent->has_child($this)) { - $this->parent->add_child($this); - } - if ($this->callback_on_parent_set !== null) { - call_user_func($this->callback_on_parent_set, $parent); - } - } - - public function get_parent() { - return $this->parent; - } - - protected function set_on_parent_set($function): void { - $this->callback_on_parent_set = $function; - } - -} diff --git a/libraries/php/Traits/pattern_parent_child/TraitPatternParent.php b/libraries/php/Traits/pattern_parent_child/TraitPatternParent.php deleted file mode 100644 index c5ac3d412..000000000 --- a/libraries/php/Traits/pattern_parent_child/TraitPatternParent.php +++ /dev/null @@ -1,46 +0,0 @@ -children as $c) { - if ($child === $c) { - return true; - } - } - return false; - } - - /** - * @param $child - * @param bool $raise_exception_if_child_exists - * @throws LogicException - */ - public function add_child($child, bool $raise_exception_if_child_exists=true): void { - if ($raise_exception_if_child_exists && $this->has_child($child)) { - throw LogicException::invalid_function_call('add_child', 'Can not add child to parent when it already exists!'); - } - $this->children[] = $child; - if (!$child->has_parent()) { - $child->set_parent($this); - } - if ($this->callback_on_child_added !== null) { - call_user_func($this->callback_on_child_added, $child); - } - } - - protected function set_on_child_added($function): void { - $this->callback_on_child_added = $function; - } - - public function get_children(): array { - return $this->children; - } -} diff --git a/libraries/php/Traits/pattern_parent_child/TraitPatternParentAndChild.php b/libraries/php/Traits/pattern_parent_child/TraitPatternParentAndChild.php deleted file mode 100644 index 0e79f290e..000000000 --- a/libraries/php/Traits/pattern_parent_child/TraitPatternParentAndChild.php +++ /dev/null @@ -1,19 +0,0 @@ -parent === null; - } - - public function get_root_parent() { - if ($this->is_root_parent()) { - return $this; - } - return $this->parent->get_root_parent(); - } -} diff --git a/libraries/php/Utils/DataType/UtilsArray.php b/libraries/php/Utils/DataType/UtilsArray.php index a9e5671e0..f289c7b91 100644 --- a/libraries/php/Utils/DataType/UtilsArray.php +++ b/libraries/php/Utils/DataType/UtilsArray.php @@ -10,6 +10,18 @@ */ abstract class UtilsArray implements InterfaceDivisible { + /** + * @param array $array + * @return string + */ + public static function to_string(array $array): string { + $text = ''; + foreach ($array as $line) { + $text .= $line; + } + return $text; + } + /** * @param array $array * @return string @@ -107,6 +119,45 @@ public static function ref_append_values(array & $base, array $values): void { } } + /** + * @param array $array + * @param array $a0 + * @param array $a1 + * @param array $a2 + * @return array + */ + public static function add_vals_from_3(array $array, array $a0, array $a1, array $a2): array { + foreach ($a0 as $k => $v) { + $array[] = $v; + } + foreach ($a1 as $k => $v) { + $array[] = $v; + } + foreach ($a2 as $k => $v) { + $array[] = $v; + } + return $array; + } + + /** + * @param array $array + * @param array $a0 + * @param array $a1 + * @param array $a2 + * @return void + */ + public static function ref_add_vals_from_3(array & $array, array $a0, array $a1, array $a2): void { + foreach ($a0 as $k => $v) { + $array[] = $v; + } + foreach ($a1 as $k => $v) { + $array[] = $v; + } + foreach ($a2 as $k => $v) { + $array[] = $v; + } + } + /** * @param array $base * @param array $v0 diff --git a/libraries/php/Utils/DataType/UtilsChar.php b/libraries/php/Utils/DataType/UtilsChar.php new file mode 100644 index 000000000..47c5521f3 --- /dev/null +++ b/libraries/php/Utils/DataType/UtilsChar.php @@ -0,0 +1,30 @@ + $v) { + foreach (self::REMOVE_TERMS as $term) { + if (STR::has($v, $term)) { + throw new RuntimeException( + 'JSON data contains value with a remove term, one of {' . json_encode(self::REMOVE_TERMS) . '}' + ); + } + } + }*/ + $json_data = json_encode($json_data); + } + if (STR::ends_in($json_data, ',')) { + STR::ref_remove_last_char($json_data); + } + STR::ref_replace($json_data, '\/', '/'); + foreach (self::REMOVE_TERMS as $term) { + if (STR::has($json_data, $term)) { + STR::ref_remove($json_data, $term); + } + } + return $json_data; + } + +} diff --git a/libraries/php/Utils/DataType/UtilsString.php b/libraries/php/Utils/DataType/UtilsString.php index eb2b59c12..bc05a5907 100644 --- a/libraries/php/Utils/DataType/UtilsString.php +++ b/libraries/php/Utils/DataType/UtilsString.php @@ -14,33 +14,12 @@ abstract class UtilsString implements InterfaceDivisible { /** - * @param string|array $lines - * @param string $align_on - * @return array - */ - public static function column_aligned($lines, string $align_on): array { - $depths = []; - if (is_string($lines)) { - $lines = self::split_clean($lines); - } - foreach ($lines as $line) { - $depths[] = self::position_of($line, $align_on, false); - } - $num_lines = count($lines); - $max_depth = UtilsArray::max($depths); - for ($i = 0; $i < $num_lines; $i++) { - $lines[$i] = self::insert_before($lines[$i], str_repeat(' ', $max_depth - $depths[$i]), $align_on); - } - return $lines; - } - - /** - * @param string $text + * @param string $str * @param string $match * @return bool */ - public static function has_only_one(string $text, string $match): bool { - return substr_count($text, $match) === 1; + public static function has_only_one(string $str, string $match): bool { + return substr_count($str, $match) === 1; } /** @@ -63,72 +42,72 @@ public static function to_associative(string $raw): array { } /** - * @param string $base + * @param string $str * @return string */ - public static function to_lower(string $base): string { - return strtolower($base); + public static function to_lower(string $str): string { + return strtolower($str); } /** - * @param string $base + * @param string $str * @return void */ - public static function ref_to_lower(string & $base): void { - $base = strtolower($base); + public static function ref_to_lower(string & $str): void { + $str = strtolower($str); } - public static function indexed(string $base, int $start, int $end=-1): string { + public static function indexed(string $str, int $start, int $end=-1): string { // TODO: Error checks on bad sizes given. if ($end === -1) { - $end = strlen($base) - 1; + $end = strlen($str) - 1; } - return substr($base, $start, $end); + return substr($str, $start, $end); } /** - * @param string $base + * @param string $str * @param array $matches * @return string */ - public static function replace_many(string $base, array $matches): string { + public static function replace_many(string $str, array $matches): string { foreach ($matches as $find => $replace_as) { - $base = str_replace($find, $replace_as, $base); + $str = str_replace($find, $replace_as, $str); } - return $base; + return $str; } /** - * @param string $base + * @param string $str * @param array $matches * @return void */ - public static function ref_replace_many(string & $base, array $matches): void { + public static function ref_replace_many(string & $str, array $matches): void { foreach ($matches as $find => $replace_as) { - $base = str_replace($find, $replace_as, $base); + $str = str_replace($find, $replace_as, $str); } } /** * Returns the provided string with any matches replaced. * - * @param string $base [The string to return a modified version of.] - * @param string $match [Text instance to find and replace. ] - * @param string $replacement [Content for replaced text instances. ] + * @param string $str {string to return a modified version of} + * @param string $match {text instance to find and replace } + * @param string $replacement {content for replaced text instances } * @return string */ - public static function replace(string $base, string $match, string $replacement): string { - return str_replace($match, $replacement, $base); + public static function replace(string $str, string $match, string $replacement): string { + return str_replace($match, $replacement, $str); } /** - * @param string $base + * @param string $str * @param string $match * @param string $replacement * @return void */ - public static function ref_replace(string & $base, string $match, string $replacement): void { - $base = str_replace($match, $replacement, $base); + public static function ref_replace(string & $str, string $match, string $replacement): void { + $str = str_replace($match, $replacement, $str); } /* __ ___ __ ___ __ @@ -136,23 +115,23 @@ public static function ref_replace(string & $base, string $match, string $replac | | \| .__/ |___ | \ | .__/ */ /** - * @param string $text + * @param string $str * @param string $insert * @param string $after * @return string */ - public static function insert_before(string $text, string $insert, string $after): string { - return substr_replace($text, $insert, self::position_of($text, $after, false), 0); + public static function insert_before(string $str, string $insert, string $after): string { + return substr_replace($str, $insert, self::position_of($str, $after, false), 0); } /** - * @param string $text + * @param string $str * @param string $insert * @param string $after * @return string */ - public static function insert_after(string $text, string $insert, string $after): string { - return substr_replace($text, $insert, self::position_of($text, $after, false) + 1, 0); + public static function insert_after(string $str, string $insert, string $after): string { + return substr_replace($str, $insert, self::position_of($str, $after, false) + 1, 0); } /*__ ___ ___ ___ ___ __ __ @@ -160,17 +139,25 @@ public static function insert_after(string $text, string $insert, string $after) \__> |___ | | |___ | \ .__/ */ /** - * @param string $base + * @param string $str + * @return array + */ + public static function get_words(string $str): array { + return preg_split('/\s+/', $str); + } + + /** + * @param string $str * @param string $char_start * @param string $char_end * @return string */ - public static function get_text_inbetween_chars(string $base, string $char_start, string $char_end): string { + public static function get_text_inbetween_chars(string $str, string $char_start, string $char_end): string { $text = ''; - $len = strlen($base); + $len = strlen($str); $in_pattern = false; for ($c = 0; $c < $len; $c++) { - $char = $base[$c]; + $char = $str[$c]; if (!$in_pattern && $char === $char_start) { $in_pattern = true; } else if ($in_pattern) { @@ -184,14 +171,14 @@ public static function get_text_inbetween_chars(string $base, string $char_start } /** - * @param string $base [The text to search through ] - * @param array $text_matches [The text matches (sub-strings) to find/match] - * @return int [-1 is returned if no match was found ] + * @param string $str {text to search through } + * @param array $text_matches {text matches (sub-strings) to find/match} + * @return int {-1 is returned if no match was found } */ - public static function get_starts_with_index(string $base, array $text_matches): int { + public static function get_starts_with_index(string $str, array $text_matches): int { $index = 0; foreach ($text_matches as $text) { - if (self::starts_with($base, $text)) { + if (self::starts_with($str, $text)) { return $index; } ++$index; @@ -200,13 +187,13 @@ public static function get_starts_with_index(string $base, array $text_matches): } /** - * @param string $base [The text to search through ] - * @param array $text_matches [The text matches (sub-strings) to find/match] - * @return string [the found match or null '' if no match found] + * @param string $str {text to search through } + * @param array $text_matches {text matches (sub-strings) to find/match } + * @return string {the found match or null '' if no match found} */ - public static function get_starts_with_match(string $base, array $text_matches): string { + public static function get_starts_with_match(string $str, array $text_matches): string { foreach ($text_matches as $text) { - if (self::starts_with($base, $text)) { + if (self::starts_with($str, $text)) { return $text; } } @@ -214,14 +201,14 @@ public static function get_starts_with_match(string $base, array $text_matches): } /** - * @param string $base [The text to search through ] - * @param array $text_matches [The text matches (sub-strings) to find/match] - * @return int [-1 is returned if no match was found ] + * @param string $str {text to search through } + * @param array $text_matches {text matches (sub-strings) to find/match} + * @return int {-1 is returned if no match was found } */ - public static function get_match_index(string $base, array $text_matches): int { + public static function get_match_index(string $str, array $text_matches): int { $index = 0; foreach ($text_matches as $text) { - if (self::has($base, $text)) { + if (self::has($str, $text)) { return $index; } ++$index; @@ -230,87 +217,119 @@ public static function get_match_index(string $base, array $text_matches): int { } /** - * @param string $base + * @param string $str * @param string $match - * @param bool $first_match [If false, the position of the last match will be returned.] + * @param bool $first_match {if false, the position of the last match will be returned} * @return int */ - public static function position_of(string $base, string $match, bool $first_match=true): int { + public static function position_of(string $str, string $match, bool $first_match=true): int { if ($first_match) { - return strpos($base, $match); + return strpos($str, $match); } - return strrpos($base, $match); + return strrpos($str, $match); } /** - * @param string $base + * @param string $str * @return bool */ - public static function has_content(string $base): bool { - return $base && trim($base); + public static function has_content(string $str): bool { + return $str && trim($str); } /** * Checks if provided string has any occurrences of the secondary string provided. * - * @param string $base + * @param string $str * @param string $match * @param bool $case_sensitive * @return bool */ - public static function has(string $base, string $match, bool $case_sensitive=true): bool { - if ($match === '' || $base === '') { + public static function has(string $str, string $match, bool $case_sensitive=true): bool { + if ($match === '' || $str === '') { return false; } if ($case_sensitive) { - return strpos($base, $match) !== false; + return strpos($str, $match) !== false; } - return stripos($base, $match) !== false; + return stripos($str, $match) !== false; } /** - * @param string $base + * @param string $str + * @param array $matches + * @param bool $case_sensitive + * @return bool + */ + public static function has_any(string $str, array $matches, bool $case_sensitive=true): bool { + if ($str === '' || count($matches) === 0) { + return false; + } + foreach ($matches as $match) { + if (self::has($str, $match, $case_sensitive)) { + return true; + } + } + return false; + } + + /** + * @param string $str * @param string $match * @return bool */ - public static function does_not_have(string $base, string $match): bool { - return !self::has($base, $match); + public static function does_not_have(string $str, string $match): bool { + return !self::has($str, $match); } /** - * @param string $base + * @param string $str * @return bool */ - public static function has_underscore(string $base): bool { - return self::has($base, '_'); + public static function has_underscore(string $str): bool { + return self::has($str, '_'); } /** * Checks if the provided string starts with the prefix to match. * - * @param string $base [The string to search. ] - * @param string $prefix [The prefix to search for.] - * @return bool [True if prefix matched. ] + * @param string $str {string to search } + * @param string $prefix {prefix to search for } + * @return bool {true if prefix matched} */ - public static function starts_with(string $base, string $prefix): bool { + public static function starts_with(string $str, string $prefix): bool { if ($prefix === '') { return false; } - return strpos($base, $prefix) === 0; + return strpos($str, $prefix) === 0; } /** * Checks if the provided string ends with the suffix to match. * - * @param string $base [The string to search. ] - * @param string $suffix [The suffix to search for.] - * @return bool [True if suffix matched. ] + * @param string $str {string to search } + * @param string $ending_match {suffix to search for } + * @return bool {true if suffix matched} */ - public static function ends_with(string $base, string $suffix): bool { - if ($suffix === '') { + public static function ends_in(string $str, string $ending_match): bool { + if ($ending_match === '') { return false; } - return substr($base, -strlen($suffix)) === $suffix; + return substr($str, -strlen($ending_match)) === $ending_match; + } + + /** + * @param string $str + * @param array $ending_matches + * @return bool + */ + public static function ends_in_any_of(string $str, array $ending_matches): bool { + foreach ($ending_matches as $ending) { + if ($ending !== '' && substr($str, -strlen($ending)) === $ending) { + return true; + } + } + return false; } /*__ __ ___ __ @@ -320,30 +339,30 @@ public static function ends_with(string $base, string $suffix): bool { /** * Returns an array with the provided string split based of the pattern to match. * - * @param string $base {string to base contents off of } + * @param string $str {string to base contents off of } * @param string $delimiter {string to match and split by } * @param bool $keep_delimiter {if true, prepend delimiter to each segment} * @return array {array of string segments } */ - public static function split(string $base, string $delimiter=PHP_EOL, bool $keep_delimiter=false): array { + public static function split(string $str, string $delimiter=PHP_EOL, bool $keep_delimiter=false): array { if ($keep_delimiter) { - $segments = explode($delimiter, $base, PHP_INT_MAX); + $segments = explode($delimiter, $str, PHP_INT_MAX); $segments_with_delimiter = []; foreach ($segments as $segment) { $segments_with_delimiter[] = $delimiter . $segment; } return $segments_with_delimiter; } - return explode($delimiter, $base, PHP_INT_MAX); + return explode($delimiter, $str, PHP_INT_MAX); } /** - * @param string $base + * @param string $str * @param string $delimiter * @return array */ - public static function split_clean(string $base, string $delimiter=PHP_EOL): array { - $lines = self::split($base, $delimiter); + public static function split_clean(string $str, string $delimiter=PHP_EOL): array { + $lines = self::split($str, $delimiter); $cleaned = []; foreach ($lines as $line) { if (self::has_content($line)) { @@ -358,147 +377,155 @@ public static function split_clean(string $base, string $delimiter=PHP_EOL): arr | \ |___ | | \__/ \/ /~~\ |___ .__/ */ /** - * @param string $base + * @param string $str * @param string $char * @return array * @throws RuntimeException */ - public static function remove_char_and_split(string $base, string $char): array { + public static function remove_char_and_split(string $str, string $char): array { $start = ''; $c = 0; - $len = strlen($base); + $len = strlen($str); while ($c < $len) { - $_c = $base[$c]; + $_c = $str[$c]; if ($_c === $char) { - return [$start, self::indexed($base, $c + 1)]; + return [$start, self::indexed($str, $c + 1)]; } $start .= $_c; ++$c; } - throw new RuntimeException('The string{' . $base . '} did not contain the character{' . $char . '}'); + throw new RuntimeException('The string{' . $str . '} did not contain the character{' . $char . '}'); } /** * Returns a string having the contents of the base string with any occurrences of secondary string provided removed. * - * @param string $base [The string to base contents off of. ] - * @param string|array $match [The string (or array of strings) to find occurrences of.] - * @return string [A new string. ] + * @param string $str {string to base contents off of } + * @param string|array $match {string (or array of strings) to find occurrences of} + * @return string {a new string } */ - public static function remove(string $base, $match): string { + public static function remove(string $str, $match): string { if (is_string($match)) { - return str_replace($match, '', $base); + return str_replace($match, '', $str); } foreach ($match as $m) { - $base = str_replace($m, '', $base); + $str = str_replace($m, '', $str); } - return $base; + return $str; } /** - * @param string $base + * @param string $str * @param string|array $patterns0 * @param string|array $patterns1 * @return string */ - public static function remove_twice(string $base, $patterns0, $patterns1): string { - return self::remove(self::remove($base, $patterns0), $patterns1); + public static function remove_twice(string $str, $patterns0, $patterns1): string { + return self::remove(self::remove($str, $patterns0), $patterns1); } /** - * @param string $base + * @param string $str * @param $match */ - public static function ref_remove(string & $base, $match): void { - $base = self::remove($base, $match); + public static function ref_remove(string & $str, $match): void { + $str = self::remove($str, $match); } /** - * @param string $base + * @param string $str * @param string $match * @param bool $first_match * @return string */ - public static function remove_after(string $base, string $match, bool $first_match=false): string { - return self::indexed($base, 0, self::position_of($base, $match, $first_match) + strlen($match)); + public static function remove_after(string $str, string $match, bool $first_match=false): string { + return self::indexed($str, 0, self::position_of($str, $match, $first_match) + strlen($match)); } /** - * @param string $base + * @param string $str * @param string $match * @return string */ - public static function keep_all_before(string $base, string $match): string { - return self::indexed($base, 0, self::position_of($base, $match)); + public static function keep_all_before(string $str, string $match): string { + return self::indexed($str, 0, self::position_of($str, $match)); } /** - * @param string $base + * @param string $str * @param string $match * @return string */ - public static function remove_up_to_last_match_inclusive(string $base, string $match): string { - return self::indexed($base, self::position_of($base, $match, false) + strlen($match), strlen($base) - 1); + public static function remove_up_to_last_match_inclusive(string $str, string $match): string { + return self::indexed($str, self::position_of($str, $match, false) + strlen($match), strlen($str) - 1); } /** - * @param string $base + * @param string $str * @param string $match * @return void */ - public static function ref_remove_up_to_last_match_inclusive(string & $base, string $match): void { - $base = self::indexed($base, self::position_of($base, $match, false) + strlen($match), strlen($base) - 1); + public static function ref_remove_up_to_last_match_inclusive(string & $str, string $match): void { + $str = self::indexed($str, self::position_of($str, $match, false) + strlen($match), strlen($str) - 1); } /** - * @param string $text + * @param string $str * @return string */ - public static function remove_last_character(string $text): string { - return self::remove_last_n($text, 1); + public static function remove_last_char(string $str): string { + return self::remove_last_n($str, 1); + } + + /** + * @param string $str + * @return void + */ + public static function ref_remove_last_char(string & $str): void { + $str = self::remove_last_n($str, 1); } /** - * @param string $text + * @param string $str * @return string */ - public static function remove_first_character(string $text): string { - return self::remove_first_n($text, 1); + public static function remove_first_char(string $str): string { + return self::remove_first_n($str, 1); } /** - * @param string $text + * @param string $str * @param int $num_digits * @return string */ - public static function remove_first_n($text, int $num_digits): string { - return substr($text, $num_digits); + public static function remove_first_n($str, int $num_digits): string { + return substr($str, $num_digits); } /** - * @param string $text + * @param string $str * @param int $num_digits * @return void */ - public static function ref_remove_first_n(& $text, int $num_digits): void { - $text = substr($text, $num_digits); + public static function ref_remove_first_n(& $str, int $num_digits): void { + $str = substr($str, $num_digits); } /** - * @param string $text + * @param string $str * @param int $num_digits * @return string */ - public static function remove_last_n(string $text, int $num_digits): string { - return substr($text, 0, strlen($text) - 1 - $num_digits); + public static function remove_last_n(string $str, int $num_digits): string { + return substr($str, 0, strlen($str) - 1 - $num_digits); } /** - * @param string $base + * @param string $str * @return string */ - public static function remove_newline(string $base): string { - return self::replace($base, PHP_EOL, ''); + public static function remove_newline(string $str): string { + return self::replace($str, PHP_EOL, ''); } /* __ __ __ ___ __ @@ -506,51 +533,51 @@ public static function remove_newline(string $base): string { |/\| | \ /~~\ | | |___ |__/ | | \| */ /** - * @param string $base + * @param string $str * @param bool $single_quotes * @param bool $replace_incorrect_quotes * @return string */ - public static function in_quotes(string $base, bool $single_quotes=true, bool $replace_incorrect_quotes=true): string { + public static function in_quotes(string $str, bool $single_quotes=true, bool $replace_incorrect_quotes=true): string { $quote = $single_quotes ? "'" : '"'; if ($replace_incorrect_quotes) { $wrong_quote = $single_quotes ? '"' : "'"; - if (self::starts_with($base, $wrong_quote)) { - $base = self::remove_first_character($base); + if (self::starts_with($str, $wrong_quote)) { + $str = self::remove_first_char($str); } - if (self::ends_with($base, $wrong_quote)) { - $base = self::remove_last_character($base); + if (self::ends_in($str, $wrong_quote)) { + $str = self::remove_last_char($str); } } - return self::ensure_wrapped_in($base, $quote, $quote); + return self::ensure_wrapped_in($str, $quote, $quote); } /** - * @param string $text + * @param string $str * @param $value * @return string */ - public static function parentheses(string $text, $value): string { - return $text . self::ensure_wrapped_in($value, '(', ')'); + public static function parentheses(string $str, $value): string { + return $str . self::ensure_wrapped_in($value, '(', ')'); } /** - * @param string $text + * @param string $str * @param $value * @return string */ - public static function brackets(string $text, $value): string { - return $text . self::ensure_wrapped_in($value, '{', '}'); + public static function brackets(string $str, $value): string { + return $str . self::ensure_wrapped_in($value, '{', '}'); } /** - * @param string $text + * @param string $str * @param string $start_with * @param string $end_with * @return string */ - public static function ensure_wrapped_in(string $text, string $start_with, string $end_with): string { - return self::ensure_ending(self::ensure_start($text, $start_with), $end_with); + public static function ensure_wrapped_in(string $str, string $start_with, string $end_with): string { + return self::ensure_ending(self::ensure_start($str, $start_with), $end_with); } /*___ __ __ ___ @@ -558,50 +585,50 @@ public static function ensure_wrapped_in(string $text, string $start_with, strin |___ | \| .__/ \__/ | \ |___ */ /** - * @param string $base + * @param string $str * @param string $match * @return string */ - public static function ensure_start_is_not(string $base, string $match): string { - if (self::starts_with($base, $match)) { - return self::remove_first_n($base, strlen($match)); + public static function ensure_start_is_not(string $str, string $match): string { + if (self::starts_with($str, $match)) { + return self::remove_first_n($str, strlen($match)); } - return $base; + return $str; } /** - * @param string $base + * @param string $str * @param string $match * @return string */ - public static function ensure_ending_is_not(string $base, string $match): string { - if (self::ends_with($base, $match)) { - return self::remove_last_n($base, strlen($match)); + public static function ensure_ending_is_not(string $str, string $match): string { + if (self::ends_in($str, $match)) { + return self::remove_last_n($str, strlen($match)); } - return $base; + return $str; } /** - * @param string $text + * @param string $str * @param string $start_with * @return string */ - public static function ensure_start(string $text, string $start_with): string { - if (!self::starts_with($text, $start_with)) { - return $start_with . $text; + public static function ensure_start(string $str, string $start_with): string { + if (!self::starts_with($str, $start_with)) { + return $start_with . $str; } - return $text; + return $str; } /** - * @param string $text + * @param string $str * @param string $ends_with * @return string */ - public static function ensure_ending(string $text, string $ends_with): string { - if (!self::ends_with($text, $ends_with)) { - return $text . $ends_with; + public static function ensure_ending(string $str, string $ends_with): string { + if (!self::ends_in($str, $ends_with)) { + return $str . $ends_with; } - return $text; + return $str; } } diff --git a/libraries/php/Utils/DataType/UtilsTextLines.php b/libraries/php/Utils/DataType/UtilsTextLines.php index 16754e13a..b7ea839a1 100644 --- a/libraries/php/Utils/DataType/UtilsTextLines.php +++ b/libraries/php/Utils/DataType/UtilsTextLines.php @@ -4,6 +4,7 @@ use QuasarSource\Utils\DataType\UtilsString as STR; use QuasarSource\Utils\DataType\UtilsArray as ARY; +use RuntimeException; /** * Class UtilsArray @@ -12,7 +13,61 @@ abstract class UtilsTextLines { /** - * @param array $text_lines + * @param array $lines + * @param string $start + * @param string $end + * @param array $insert + * @return array + */ + public static function insert_lines_inbetween(array $lines, string $start, string $end, array $insert): array { + $processed = []; + $started = false; + foreach ($lines as $line) { + if (STR::has($line, $start)) { + if ($started) { + throw new RuntimeException('Start pattern found twice{' . $start . '}'); + } + $started = true; + $processed[] = $line; + } else if (STR::has($line, $end)) { + if (!$started) { + throw new RuntimeException('End pattern found before start{' . $end . '}'); + } + UtilsArray::ref_append_values($processed, $insert); + $processed[] = $line; + } else { + $processed[] = $line; + } + } + if (count($processed) === count($lines)) { + throw new RuntimeException('Did not find start-end patterns in lines provided! Start{' . $start . '} End{' . $end . '}'); + } + return $processed; + } + + /** + * @param string|array $lines + * @param string $align_on + * @return array + */ + public static function column_aligned($lines, string $align_on): array { + $depths = []; + if (is_string($lines)) { + $lines = STR::split_clean($lines); + } + foreach ($lines as $line) { + $depths[] = STR::position_of($line, $align_on, false); + } + $num_lines = count($lines); + $max_depth = ARY::max($depths); + for ($i = 0; $i < $num_lines; $i++) { + $lines[$i] = STR::insert_before($lines[$i], str_repeat(' ', $max_depth - $depths[$i]), $align_on); + } + return $lines; + } + + /** + * @param array $text_lines * @param string $pattern * @return array */ @@ -45,6 +100,7 @@ public static function parse_into_sections(array $text_lines, string $pattern): $sections = []; $section = []; $in_section = false; + #(is_array($pattern) && STR::has_any($line, $pattern)) || (is_string($pattern) && STR::has($line, $pattern)) foreach ($text_lines as $line) { if (STR::has($line, $pattern)) { if ($in_section) { diff --git a/libraries/php/Utils/File/Discrete/PHP/CodeParserPHP.php b/libraries/php/Utils/File/Discrete/PHP/CodeParserPHP.php new file mode 100644 index 000000000..2d545d539 --- /dev/null +++ b/libraries/php/Utils/File/Discrete/PHP/CodeParserPHP.php @@ -0,0 +1,93 @@ + $v) { + $inner[] = "\t'" . $k . "' => '" . $v . "'," . PHP_EOL; + } + $clean_assignment_lines = TEXT_LINES::column_aligned($inner, '=>'); + foreach ($clean_assignment_lines as $l) { + $code[] = $l; + } + $code[] = '];' . PHP_EOL; + return $code; + } + + #$marker_one = '{A U T O G E N E R A T E D C O D E}:{0x0}'; + #$maker_end = '{E N D}:{0x0}'; + + /** + * @param array $code_lines + * @param string $array_name + * @param array $replacement + * @return array + */ + public static function replace_array(array $code_lines, string $array_name, array $replacement): array { + $new_code = []; + $after_split = []; + $i = 0; + $num = count($code_lines); + $inside = false; + $got_in = false; + + while ($i < $num) { + $line = $code_lines[$i]; + switch (STR::get_match_index($line, ['{A U T O G E N E R A T E D C O D E}:{0x0}', '{E N D}:{0x0}'])) { + case 0: + if ($inside) { + throw new RuntimeException('Invalid auto-generated-code syntax!'); + } + $got_in = true; + $inside = true; + $new_code[] = $line; + break; + case 1: + if (!$inside) { + throw new RuntimeException('Invalid auto-generated-code syntax!'); + } + $inside = false; + $after_split[] = $line; + break; + default: + if (!$inside) { + if ($got_in) { + $after_split[] = $line; + } else { + $new_code[] = $line; + } + } + break; + } + ++$i; + } + #$sections = UtilsTextLines::parse_into_sections($code_lines, [$marker_one, $maker_end]); + if ($inside || !$got_in) { + throw new RuntimeException('Invalid auto-generated-code syntax!'); + } + #$replaced_code = self::array_as_code($array_name, $replacement); + #return ARY::add_vals_from_3($new_code, $before_split, $replaced_code, $after_split); + #return ARY::add_vals_from_2($new_code, $replaced_code, $after_split); + return ARY::add_vals_from_3($new_code, self::array_as_code($array_name, $replacement), $after_split, []); + } + +} diff --git a/libraries/php/Utils/File/Discrete/UtilsCSV.php b/libraries/php/Utils/File/Discrete/UtilsCSV.php index bf986a310..cf5eea8b5 100644 --- a/libraries/php/Utils/File/Discrete/UtilsCSV.php +++ b/libraries/php/Utils/File/Discrete/UtilsCSV.php @@ -13,9 +13,10 @@ final class UtilsCSV extends UtilsFile { /** * @param string $path - * @return array + * @param bool $as_string + * @return array|string */ - public static function get(string $path): array { + public static function get(string $path, bool $as_string=false): array { self::is_valid($path); $content = []; $lines = parent::get($path); @@ -37,7 +38,7 @@ public static function get(string $path): array { private static function split_csv(string $line): array { $contents = STR::split($line, ','); $len_contents = count($contents); - if (STR::ends_with($contents[$len_contents - 1], PHP_EOL)) { + if (STR::ends_in($contents[$len_contents - 1], PHP_EOL)) { $contents[$len_contents - 1] = trim($contents[$len_contents - 1]); } return $contents; diff --git a/libraries/php/Utils/File/Discrete/UtilsWebManifest.php b/libraries/php/Utils/File/Discrete/UtilsWebManifest.php deleted file mode 100644 index 0c25176a2..000000000 --- a/libraries/php/Utils/File/Discrete/UtilsWebManifest.php +++ /dev/null @@ -1,19 +0,0 @@ -getMessage()); diff --git a/libraries/php/Utils/File/UtilsDirectory.php b/libraries/php/Utils/File/UtilsDirectory.php index c4c174286..1e5ff52de 100644 --- a/libraries/php/Utils/File/UtilsDirectory.php +++ b/libraries/php/Utils/File/UtilsDirectory.php @@ -23,10 +23,74 @@ abstract class UtilsDirectory { * @return bool */ public static function is_valid(string $path, bool $raise_exception_if_not = true): bool { - if ($raise_exception_if_not && !is_dir($path)) { + $valid = is_dir($path); + if ($raise_exception_if_not && !$valid) { throw DNE::exception('is_valid', 'path provided{' . $path . '} does not exist!'); } - return true; + return $valid; + } + + /** + * @param string $path + * @return bool + */ + public static function is_base_of_valid(string $path): bool { + if (self::is_valid($path, false)) { + return true; + } + return self::is_valid(self::get_base_path($path), false); + } + + /** + * @param string $path + * @return bool + */ + public static function create_if_dne_but_base_exists(string $path): bool { + if (self::is_base_of_valid($path)) { + return self::create_recursively($path); + } + return false; + } + + /** + * @param string $path + * @return string + */ + public static function get_base_path(string $path): string { + $base_path = ''; + $num_chars = strlen($path); + $num_matches_needed = 1; + if (STR::starts_with($path, '/')) { + ++$num_matches_needed; + } + for ($c = 0; $c < $num_chars; $c++) { + $char = $path[$c]; + $base_path .= $char; + if ($char === '/') { + --$num_matches_needed; + if ($num_matches_needed === 0) { + return $base_path; + } + } + } + return $base_path; + } + + /** + * @see https://stackoverflow.com/questions/2303372/create-a-folder-if-it-doesnt-already-exist + * @author phazei + * Original code has been modified! + * + * @param string $path + * @return bool + */ + public static function create_recursively(string $path): bool { + if (is_dir($path)) { + return true; + } + $prev_path = substr($path, 0, strrpos($path, '/', -2) + 1 ); + $return = self::create_recursively($prev_path); + return ($return && is_writable($prev_path)) ? mkdir($path) : false; } /** @@ -66,7 +130,7 @@ public static function get_all_contents(string $path_directory, bool $use_recurs self::is_valid($path_directory); $files = scandir($path_directory, SCANDIR_SORT_NONE); - if (!STR::ends_with($path_directory, DIRECTORY_SEPARATOR)) { + if (!STR::ends_in($path_directory, DIRECTORY_SEPARATOR)) { $path_directory .= DIRECTORY_SEPARATOR; } foreach ($files as $key => $value) { diff --git a/libraries/php/Utils/File/UtilsFile.php b/libraries/php/Utils/File/UtilsFile.php index c84e079b2..1bb4c2aea 100644 --- a/libraries/php/Utils/File/UtilsFile.php +++ b/libraries/php/Utils/File/UtilsFile.php @@ -6,11 +6,13 @@ use function is_array; use Exception; use QuasarSource\Utils\Exception\ExceptionSystem; +use QuasarSource\Utils\File\Enum\EnumFileTypeExtensions; +use QuasarSource\Utils\Process\ProcessRunner; +use QuasarSource\Utils\DataType\UtilsArray as ARY; use QuasarSource\Utils\DataType\UtilsTextLines as TEXT_LINES; use QuasarSource\Utils\Process\UtilsProcess as RUN; use QuasarSource\Utils\Math\UtilsCryptography as HASH; use QuasarSource\Utils\SystemOS\UtilsSystem as SYS; -use QuasarSource\Utils\Process\UtilsProcess; /** * Class UtilsFile @@ -102,12 +104,15 @@ public static function get_size(string $path): int { * @throws ExceptionSystem */ public static function gzip(string $path_base, string $path_output): void { + self::is_valid($path_base); + $p = new ProcessRunner(['gzip', '-f', '-k', '-9', $path_base], true); try { - self::is_valid($path_base); - RUN::gzip_file_to($path_base, $path_output); + $p->run(); + self::rename($path_base . EnumFileTypeExtensions::GZIPPED, $path_output); } catch (Exception $e) { throw self::exception('gzip', $e->getMessage()); } + unset($p); } /** @@ -127,13 +132,20 @@ public static function delete(string $path): void { /** * @param string $path * @param mixed $contents + * @param bool $create_if_file_does_not_exist * @throws ExceptionSystem */ - public static function set(string $path, $contents): void { - try { + public static function set(string $path, $contents, bool $create_if_file_does_not_exist=false): void { + if (!$create_if_file_does_not_exist) { self::is_valid($path); + } + try { #file_put_contents($path, $contents, LOCK_EX); - $f = fopen($path, 'wb'); + if ($create_if_file_does_not_exist) { + $f = fopen($path, 'wb+'); + } else { + $f = fopen($path, 'wb'); + } if (is_array($contents)) { $contents = implode($contents); } @@ -146,17 +158,21 @@ public static function set(string $path, $contents): void { /** * @param string $path - * @return array + * @param bool $as_string + * @return array|string * @throws ExceptionSystem */ - public static function get(string $path): array { + public static function get(string $path, bool $as_string=false) { + self::is_valid($path); try { - self::is_valid($path); $file_lines = []; $lines = file($path); foreach ($lines as $line) { $file_lines[] = $line; } + if ($as_string) { + return ARY::to_string($file_lines); + } return $file_lines; } catch (Exception $e) { throw self::exception('get', $e->getMessage()); @@ -178,7 +194,7 @@ public static function get_from_env_path(string $env_key): array { */ public static function get_last_n_lines(string $path, int $num_lines): array { self::is_valid($path); - return TEXT_LINES::parse_string(UtilsProcess::run_cmd(['tail', '-' . $num_lines, $path])); + return TEXT_LINES::parse_string(RUN::run_cmd(['tail', '-' . $num_lines, $path])); } /** diff --git a/libraries/php/Utils/File/UtilsPath.php b/libraries/php/Utils/File/UtilsPath.php index d17f644ce..26868af1e 100644 --- a/libraries/php/Utils/File/UtilsPath.php +++ b/libraries/php/Utils/File/UtilsPath.php @@ -94,7 +94,7 @@ public static function get_extensions_as_string(string $path): string { */ public static function get_extensions(string $path): array { $full_name = self::get_file_full_name($path); - if (!STR::has($path, '.') || (STR::has_only_one($path, '.') && STR::ends_with($path, '.'))) { + if (!STR::has($path, '.') || (STR::has_only_one($path, '.') && STR::ends_in($path, '.'))) { return []; } $extensions = STR::remove($full_name, STR::keep_all_before($full_name, '.')); diff --git a/libraries/php/Utils/HTTP/UtilsHTTP.php b/libraries/php/Utils/HTTP/UtilsHTTP.php index 53f667a3f..518824b1b 100644 --- a/libraries/php/Utils/HTTP/UtilsHTTP.php +++ b/libraries/php/Utils/HTTP/UtilsHTTP.php @@ -5,6 +5,11 @@ /** * Class UtilsHTTP * @package QuasarSource\Utils\HTTP + * + * @see https://www.freeformatter.com/mime-types-list.html + * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#Important_MIME_types_for_Web_developers + * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types + * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types */ abstract class UtilsHTTP { @@ -14,6 +19,12 @@ abstract class UtilsHTTP { public const REQUEST_TYPE_POST = 'POST'; public const REQUEST_TYPE_DELETE = 'DELETE'; + public const MIME_WEB_MANIFEST = 'data:application/manifest+json'; + + public const ENCODING_DEFAULT = 'application/x-www-form-urlencoded'; + public const ENCODING_BINARY = 'multipart/form-data'; + public const ENCODING_PLAIN = 'text/plain'; + /** * Executes a HTTP request. * diff --git a/libraries/php/Utils/Process/ProcessDoctrine.php b/libraries/php/Utils/Process/ProcessDoctrine.php deleted file mode 100644 index a757e5d70..000000000 --- a/libraries/php/Utils/Process/ProcessDoctrine.php +++ /dev/null @@ -1,116 +0,0 @@ -get_output(); - } - - /** - * @return array - */ - public static function execute_validate_checks(): array { - $output = self::execute_validate(); - $mapping_okay = TEXT_LINES::does_line_after_pattern_contain_text($output, ['Mapping', '-------'], '[OK]'); - if ($mapping_okay) { - $schema_okay = TEXT_LINES::does_line_after_pattern_contain_text($output, ['Database', '--------'], '[OK]'); - if ($schema_okay) { - return [true, true]; - } - var_dump('Fix DB schema {' . json_encode($output) . '}'); - return [true, false]; - } - var_dump('Fix DB mapping {' . json_encode($output) . '}'); - return [false, false]; - } - - /** - * @return array - */ - public static function execute_update(): array { - $p = new ProcessDoctrine(self::ROUTINE_SCHEMA_UPDATE, true); - return $p->get_output(); - } - - /** - * @return ProcessDoctrine - */ - public static function execute_update_and_return_object(): ProcessDoctrine { - return new ProcessDoctrine(self::ROUTINE_SCHEMA_UPDATE, true); - } - - /** - * @return array - */ - public static function execute_create(): array { - $p = new ProcessDoctrine(self::ROUTINE_SCHEMA_CREATE, true); - return $p->get_output(); - } - - /** @var string $cmd_cwd */ - private static $cmd_cwd; - - /** - * ProcessDoctrine constructor. - * @param string $command - * @param bool $auto_run - */ - private function __construct(string $command, bool $auto_run=false) { - if (self::$cmd_cwd === null) { - self::$cmd_cwd = SYS::get_env(Path::DIRECTORY_CODE_MANAGER); - } - $cmd = ['php', './bin/console', $command]; - if ($command === self::ROUTINE_SCHEMA_VALIDATE) { - $cmd[] = '-vvv'; - } else if ($command === self::ROUTINE_SCHEMA_UPDATE || $command === self::ROUTINE_SCHEMA_CREATE) { - $cmd = ARY::append_values($cmd, self::CACHED_FLAGS); - } - parent::__construct($cmd, false, 20, self::$cmd_cwd); - if ($auto_run) { - $this->run(); - } - $err = $this->get_error_output(); - if (count($err) !== 0) { - throw new \RuntimeException('TODO: investigate{' . json_encode($err) . '}'); - } - } - - /** - * @return string|array - */ - public function get_output() { - $output = parent::get_output(); - return STR::split_clean($output); - } - - /** - * @return string|array - */ - public function get_error_output() { - $error = parent::get_error_output(); - return STR::split_clean($error); - } - -} diff --git a/libraries/php/Utils/Process/ProcessRunner.php b/libraries/php/Utils/Process/ProcessRunner.php index 9b421999d..f6825c6fc 100644 --- a/libraries/php/Utils/Process/ProcessRunner.php +++ b/libraries/php/Utils/Process/ProcessRunner.php @@ -2,8 +2,10 @@ namespace QuasarSource\Utils\Process; +use RuntimeException; use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Process; +use QuasarSource\Utils\DataType\UtilsString as STR; /** * Class ProcessRunner @@ -11,51 +13,185 @@ */ class ProcessRunner { - private $failed = false; + public const OUTPUT_FORMAT_RAW = 0; + public const OUTPUT_FORMAT_LINES = 1; + public const OUTPUT_FORMAT_LINES_CLEAN = 2; + public const OUTPUT_FORMAT_JSON = 3; + + /** @var array|string $parsed_output */ + private $parsed_output; + + /** @var array|string $parsed_errors */ + private $parsed_errors; + + /** @var Process $process */ private $process; + + /** @var bool $raise_exception_on_error */ private $raise_exception_on_error; + /** @var bool $failed */ + private $failed = false; + + /** @var bool $was_ran */ + private $was_ran = false; + + /** @var int $output_format */ + private $output_format; + + /** @var int $exit_code */ + private $exit_code; + + /** @var string $exit_code_meaning */ + private $exit_code_meaning; + + /** @var bool $uses_custom_exit_code */ + private $uses_custom_exit_code; + /** - * @param array $command - * @param bool $raise_exception_on_error - * @param int $timeout - * @param string $cwd + * @param string|array $cmd + * @param string|null $cwd + * @return ProcessRunner */ - public function __construct(array $command, bool $raise_exception_on_error=true, int $timeout=20, string $cwd=null) { + public static function spawn($cmd, string $cwd=null): ProcessRunner { + return new ProcessRunner($cmd, false, $cwd); + } + + /** + * @param $cmd + * @param string|null $cwd + * @param bool $raise_exception_on_error + * @return ProcessRunner + */ + public static function execute($cmd, string $cwd=null, bool $raise_exception_on_error=false): ProcessRunner { + $p = new ProcessRunner($cmd, $raise_exception_on_error, $cwd); + $p->run(); + return $p; + } + + /** + * @param string|array $cmd + * @param string|null $cwd + * @return ProcessRunner + */ + public static function execute_must_pass($cmd, string $cwd=null): ProcessRunner { + $p = new ProcessRunner($cmd, true, $cwd); + $p->run(); + $errors = $p->get_error_output(); + if ($errors !== '') { + throw new RuntimeException('The cmd{' . json_encode($cmd) . '} had error {' . $errors . '}'); + } + return $p; + } + + /** + * @param array|string $command + * @param bool $raise_exception_on_error + * @param string $cwd + * @param int $timeout + * @param bool $uses_custom_exit_code + * @param int $output_format + */ + public function __construct( + $command, + bool $raise_exception_on_error=true, + string $cwd=null, + int $timeout=20, + bool $uses_custom_exit_code=false, + int $output_format=self::OUTPUT_FORMAT_RAW + ) { #flush(); - $this->process = new Process($command, $cwd); + $this->uses_custom_exit_code = $uses_custom_exit_code; + $this->output_format = $output_format; + $this->process = new Process(is_string($command) ? STR::get_words($command) : $command, $cwd); $this->raise_exception_on_error = $raise_exception_on_error; $this->process->setTimeout($timeout); } + public function __destruct() { + if ($this->process !== null) { + $this->process->stop(); + $this->process->clearOutput(); + $this->process->clearErrorOutput(); + } + unset( + $this->process, $this->failed, $this->raise_exception_on_error, $this->exit_code, $this->exit_code_meaning, + $this->parsed_output, $this->parsed_errors, $this->output_format + ); + } + public function run(): void { + if ($this->was_ran) { + throw new RuntimeException('ProcessRunner has already been ran!'); + } $this->process->run(); $this->process->wait(); - $this->failed = !$this->process->isSuccessful(); + $this->was_ran = true; + $this->failed = !$this->process->isSuccessful(); + $this->exit_code = $this->process->getExitCode(); + if (!$this->uses_custom_exit_code) { + $this->exit_code_meaning = $this->process->getExitCodeText(); + } if ($this->raise_exception_on_error && $this->failed) { throw new ProcessFailedException($this->process); } } /** - * @return array + * @return bool */ - public function get_output_and_error(): array { - return [$this->get_output(), $this->get_error_output()]; + public function was_successful(): bool { + if (!$this->was_ran) { + throw new RuntimeException('Can\'t call {was_successful} as the process was never ran'); + } + return !$this->failed && $this->get_error_output() === ''; } /** - * @return string|array + * @return array|false|string|null */ public function get_output() { - return $this->process->getOutput(); + if (!$this->was_ran) { + $this->run(); + } + if ($this->parsed_output === null) { + $this->parsed_output = $this->parse_output($this->process->getOutput()); + } + return $this->parsed_output; } /** - * @return string|array + * @return array|string|null */ public function get_error_output() { - return $this->process->getErrorOutput(); + if (!$this->was_ran) { + $this->run(); + } + if ($this->parsed_errors === null) { + $this->parsed_errors = $this->parse_output($this->process->getErrorOutput()); + } + return $this->parsed_errors; + } + + # ------------------------------------------------- P R I V A T E -------------------------------------------------- + + /** + * @param string $output + * @return array|false|string|null + */ + private function parse_output(string $output) { + switch ($this->output_format) { + case self::OUTPUT_FORMAT_RAW: + return $output; + case self::OUTPUT_FORMAT_LINES: + return $output === '' ? [] : STR::split($output); + case self::OUTPUT_FORMAT_LINES_CLEAN: + return $output === '' ? [] : STR::split_clean($output); + case self::OUTPUT_FORMAT_JSON: + return json_encode($output); + default: + throw new RuntimeException('Output format not defined.'); + } } } \ No newline at end of file diff --git a/libraries/php/Utils/Process/UtilsProcess.php b/libraries/php/Utils/Process/UtilsProcess.php index de1a8ba83..b8789e10c 100644 --- a/libraries/php/Utils/Process/UtilsProcess.php +++ b/libraries/php/Utils/Process/UtilsProcess.php @@ -2,9 +2,6 @@ namespace QuasarSource\Utils\Process; -use CodeManager\Enum\ProjectParameterKeys\Path; -use QuasarSource\Utils\File\Enum\EnumFileTypeExtensions as EXTENSION; -use QuasarSource\Utils\File\UtilsFile as UFO; use QuasarSource\Utils\DataType\UtilsString as STR; use QuasarSource\Utils\SystemOS\UtilsSystem as SYS; @@ -15,54 +12,17 @@ abstract class UtilsProcess { /** - * @param array $command - * @param string $cwd - * @param bool $raise_exception_on_error - * @param bool $pretty_output - * @return array - */ - public static function run_process( - array $command, - string $cwd=null, - bool $raise_exception_on_error=true, - bool $pretty_output=false - ): array { - flush(); - #ob_clean(); - $p = new ProcessRunner($command, $raise_exception_on_error, 20, $cwd); - $p->run(); - if (!$pretty_output) { - return [$p->get_output(), $p->get_error_output()]; - } - $output = $p->get_output(); - $errors = $p->get_error_output(); - $output = STR::split_clean($output); - $errors = STR::split_clean($errors); - return [$output, $errors]; - } - - /** - * @param array $command - * @param string|null $cwd + * @param string|array $command + * @param string|null $cwd * @return string */ - public static function run_cmd(array $command, string $cwd=null): string { - $p = new ProcessRunner($command, true, 20, $cwd); + public static function run_cmd($command, string $cwd=null): string { + $p = new ProcessRunner($command, true, $cwd, 20); $p->run(); #var_dump($p->get_error_output()); return $p->get_output(); } - /** - * @param string $path_input - * @param string $path_output - * @return void - */ - public static function gzip_file_to(string $path_input, string $path_output): void { - self::run_cmd(['gzip', '-f', '-k', '-9', $path_input]); - UFO::rename($path_input . EXTENSION::GZIPPED, $path_output); - } - // Q A. /** @@ -71,19 +31,13 @@ public static function gzip_file_to(string $path_input, string $path_output): vo public static function run_qa_tests(): string { #'--log-junit' # --log-teamcity - return self::run_cmd(['php', 'bin/phpunit', '--log-junit', 'report.xml'], SYS::get_env(Path::DIRECTORY_CODE_MANAGER)); + return self::run_cmd(['php', 'bin/phpunit', '--log-junit', 'report.xml'], SYS::get_env('PATH_DIRECTORY_CODE_MANAGER')); } // C O M P O S E R. public static function run_composer_self_update(string $path_composer): string { - return self::run_cmd(['php', $path_composer, 'self-update'], SYS::get_env(Path::DIRECTORY_CODE_MANAGER)); - } - - // W E B P A C K. - - public static function run_webpack_build(): string { - return self::run_cmd(['npm', 'run-script', 'build'], SYS::get_env(Path::DIRECTORY_NODE)); + return self::run_cmd(['php', $path_composer, 'self-update'], SYS::get_env('PATH_DIRECTORY_CODE_MANAGER')); } // N P M. diff --git a/libraries/php/Utils/SystemOS/UtilsSystem.php b/libraries/php/Utils/SystemOS/UtilsSystem.php index 42090b8ec..08c22bb89 100644 --- a/libraries/php/Utils/SystemOS/UtilsSystem.php +++ b/libraries/php/Utils/SystemOS/UtilsSystem.php @@ -10,6 +10,9 @@ */ abstract class UtilsSystem { + #var_dump(opcache_get_status()); + #var_dump(opcache_get_configuration()); + public static function ask_for_garbage_collection(): void { gc_collect_cycles(); } diff --git a/libraries/php/code_abstractions/FileAbstraction.php b/libraries/php/code_abstractions/FileAbstraction.php deleted file mode 100644 index 1712d1974..000000000 --- a/libraries/php/code_abstractions/FileAbstraction.php +++ /dev/null @@ -1,51 +0,0 @@ -set_parent($parent); - } - $this->name = $name; - $this->is_type_file = $is_type_file; - $this->path_relative = $path_relative; - $this->cached = false; - - if (!$this->is_type_file) { - if ($parent === null) { - $this->path_full = DIRECTORY_SEPARATOR . $this->path_relative; - } else { - $this->path_full = $this->get_parent()->get_path_full() . $this->path_relative; - } - } else if ($parent === null) { - $this->path_full = $this->path_relative; - } else { - $this->path_full = $this->get_parent()->get_path_full() . $this->path_relative; - } - } - - public function is_file(): bool { - return $this->is_type_file; - } - - public function get_path_relative(): string { - return $this->path_relative; - } - - public function get_path_full(): string { - return $this->path_full; - } - -} diff --git a/libraries/php/code_abstractions/FileManager.php b/libraries/php/code_abstractions/FileManager.php deleted file mode 100644 index 2869b1d17..000000000 --- a/libraries/php/code_abstractions/FileManager.php +++ /dev/null @@ -1,112 +0,0 @@ -base_dir = new DirectoryInstance('quasar_source'); - } - - private static function get_instance() : FileManager { - if (self::$manager === null) { - self::$manager = new FileManager(); - } - return self::$manager; - } - - public static function get_file_contents(string $todo) { - $manager = self::get_instance(); - - $file = $manager->base_dir->get_file($todo); - - #L::ll('TODO: get contents for', $todo); - - #echo gettype($file) . PHP_EOL; - - return $file->get_contents(); - } - - public static function get_file_instance(string $path) { - - } - - public function get_root_directory() : DirectoryInstance { - return $this->base_dir; - } - - public static function get_base_directory() : DirectoryInstance { - $manager = self::get_instance(); - return $manager->get_root_directory(); - } - - public static function get_needed_file_class_type(string $file_path, DirectoryInstance $parent_directory) : ?FileAbstraction { - $extension = UPO::get_ending_extension($file_path); - $path = STR::remove($file_path, $extension); - - if ($path === null || $path === '') { - // -------------------------------------------------------------------------------------------------- - switch ($extension) { - case '.dockerignore': - return new FileDockerIgnore($path, $extension, $parent_directory); - case '.gitignore': - return new FileGITIgnore($path, $extension, $parent_directory); - case '.DS_Store': - return new FileDS_Store($path, $extension, $parent_directory); - } - if ($extension !== '.dockerenv') { - return new FileText($path, $extension, $parent_directory); - } - // -------------------------------------------------------------------------------------------------- - } else if ($extension === '.yml' || $extension === '.yaml') { - // -------------------------------------------------------------------------------------------------- - if (STR::has($path, 'docker-compose')) { - return new FileDockerCompose($path, $extension, $parent_directory); - } - return new FileYAML($path, $extension, $parent_directory); - // -------------------------------------------------------------------------------------------------- - } else if ($extension === '.js') { - // -------------------------------------------------------------------------------------------------- - if (STR::has($path, 'eslintrc')) { - return new FileESLint($path, $extension, $parent_directory); - } - return new FileJavascript($path, $extension, $parent_directory); - // -------------------------------------------------------------------------------------------------- - } else if ($extension === '.php') { - // -------------------------------------------------------------------------------------------------- - return new FilePHP($path, $extension, $parent_directory); - // -------------------------------------------------------------------------------------------------- - } else if ($extension === '.md') { - // -------------------------------------------------------------------------------------------------- - return new FileMarkDown($path, $extension, $parent_directory); - // -------------------------------------------------------------------------------------------------- - } else if ($extension === null || $extension === '') { - // -------------------------------------------------------------------------------------------------- - if ($path === 'LICENSE') { - return new FileLicense($path, $extension, $parent_directory); - } - return new FileLicense($path, $extension, $parent_directory); - // -------------------------------------------------------------------------------------------------- - } - - return null; - } -} diff --git a/libraries/php/code_abstractions/code_abstractions/Comment.php b/libraries/php/code_abstractions/code_abstractions/Comment.php deleted file mode 100644 index d7e9ea29b..000000000 --- a/libraries/php/code_abstractions/code_abstractions/Comment.php +++ /dev/null @@ -1,11 +0,0 @@ -raw_line = $raw_line; - $this->line_type = $line_type; - $this->line_number = $line_number; - } - - public function has_text(string $text): bool { - return STR::has($this->raw_line, $text); - } - - public function get_line_number(): int { - return $this->line_number; - } - - public function get_line_type(): string { - return $this->line_type; - } - - public function __toString(): string { - return $this->raw_line; - } - - public function apply_line_number_delta(int $delta): void { - $this->line_number += $delta; - } - -} diff --git a/libraries/php/code_abstractions/code_abstractions/code_segments/CodeSegment.php b/libraries/php/code_abstractions/code_abstractions/code_segments/CodeSegment.php deleted file mode 100644 index 6e7ab5e1e..000000000 --- a/libraries/php/code_abstractions/code_abstractions/code_segments/CodeSegment.php +++ /dev/null @@ -1,13 +0,0 @@ -lines = []; - } - -} diff --git a/libraries/php/code_abstractions/code_abstractions/code_segments/CodeSegments.php b/libraries/php/code_abstractions/code_abstractions/code_segments/CodeSegments.php deleted file mode 100644 index 109fabdbd..000000000 --- a/libraries/php/code_abstractions/code_abstractions/code_segments/CodeSegments.php +++ /dev/null @@ -1,89 +0,0 @@ -segments = $code_segments; - $this->last_line_number = 1; - } - - public function add_comment(string $line, bool $add_to_start=false): void { - if (!STR::ends_with($line, PHP_EOL)) { - $line .= PHP_EOL; - } - if (!$add_to_start) { - $this->segments[] = new Comment($line, $this->last_line_number); - ++$this->last_line_number; - } else { - $this->apply_line_number_delta(1); - array_unshift($this->segments, new Comment($line, 1)); - } - } - - public function add_empty_line(bool $add_to_start=false): void { - if (!$add_to_start) { - $this->segments[] = new EmptyLine(PHP_EOL, $this->last_line_number); - ++$this->last_line_number; - } else { - $this->apply_line_number_delta(1); - array_unshift($this->segments, new EmptyLine(PHP_EOL,1)); - } - } - - public function add_line(string $line, bool $add_to_start=false): void { - if (!STR::ends_with($line, PHP_EOL)) { - $line .= PHP_EOL; - } - if (!$add_to_start) { - $this->segments[] = new LineOfCode($line, $this->last_line_number); - ++$this->last_line_number; - } else { - $this->apply_line_number_delta(1); - array_unshift($this->segments, new LineOfCode($line, 1)); - } - } - - public function remove_all_after_and_before(LineOfCode $start, LineOfCode $end): void { - - } - - public function remove_all_before(LineOfCode $line_to_keep): void { - $delta = $line_to_keep->get_line_number() - 1; - - ARY::remove_first_n($this->segments, $delta); - - $this->apply_line_number_delta(-$delta); - } - - private function apply_line_number_delta(int $delta): void { - $this->last_line_number += $delta; - foreach ($this->segments as $line) { - $line->apply_line_number_delta($delta); - } - } - - public function get_line_with_text(string $text): ?LineOfCode { - foreach ($this->segments as $segment) { - if ($segment->has_text($text)) { - return $segment; - } - } - return null; - } - - public function get_segments(): array { - return $this->segments; - } - -} diff --git a/libraries/php/code_abstractions/code_abstractions/code_segments/EmptyCodeSegment.php b/libraries/php/code_abstractions/code_abstractions/code_segments/EmptyCodeSegment.php deleted file mode 100644 index 597255718..000000000 --- a/libraries/php/code_abstractions/code_abstractions/code_segments/EmptyCodeSegment.php +++ /dev/null @@ -1,7 +0,0 @@ -get_path_full()); - foreach ($this->children as $child) { - if ($child->is_file()) { - #L::ll($offset . ' F', $child); - } else { - $child->print_tree(' ' . $offset); - } - } - } - - /** - * @param string $path - * @throws LogicException - */ - private function add_file_from_path(string $path): void { - $instance = FileManager::get_needed_file_class_type($path, $this); - if ($instance === null) { - throw LogicException::invalid_function_call('add_file_from_path', 'Warning: no file created for path {' . $path . '}'); - #L::l('Warning: no file created for path {' . $path . '}'); - } - } - - private function contains_directory_path(string $path): bool { - return STR::has($this->get_path_full(), $path); - } - - public function get_local_files_of_type($file_type): array { - $files = []; - foreach ($this->children as $child) { - if ($child->is_file() && get_class($child) === $file_type) { - $files[] = $child; - } - } - return $files; - } - - public function get_file(string $path) : ?FileInstance { - $this->load_cache(); - - if (!STR::starts_with($path, DIRECTORY_SEPARATOR)) { - $path = DIRECTORY_SEPARATOR . $path; - } - $p = UPO::get_directory($path); - $f = STR::remove($path, $p); - - /** @var DirectoryInstance $child */ - foreach ($this->children as $child) { - if (!$child->is_file() && $child->contains_directory_path($p)) { - $child->load_cache(true); - $file_match = $child->find_file($path); - if ($file_match !== null) { - return $file_match; - } - } - } - #$this->print_tree(); - return null; - } - - private function find_file(string $path) { - foreach ($this->children as $child) { - if ($child->is_file() && STR::has($child->get_path_full(), $path)) { - return $child; - } - } - return null; - } - - public function load_cache(bool $use_recursion=false): void { - if (!$this->cached) { - $this->cached = true; - $path_full = $this->get_path_full(); - $path_files = []; - $path_directories = []; - UDO::get_all_contents($path_full, $use_recursion, $path_files, $path_directories); - - foreach ($path_files as $path) { - $p = STR::remove($path, $path_full); - if (!STR::has($p, DIRECTORY_SEPARATOR)) { - $this->add_file_from_path(STR::remove($path, $path_full)); - } - } - - foreach ($path_directories as $path) { - $directory = new DirectoryInstance(STR::remove($path, $path_full), $this); - if ($use_recursion) { - $directory->load_cache(true); - } - } - } - } -} diff --git a/libraries/php/code_abstractions/file_abstractions/FileInstance.php b/libraries/php/code_abstractions/file_abstractions/FileInstance.php deleted file mode 100644 index 3f67e5f03..000000000 --- a/libraries/php/code_abstractions/file_abstractions/FileInstance.php +++ /dev/null @@ -1,48 +0,0 @@ -extension = $extension; - $this->loaded = false; - $this->loaded_lines = false; - $this->contents = null; - $this->file_lines = []; - } - - public function get_lines() : array { - if (!$this->loaded_lines) { - $this->file_lines = UFO::get($this->get_path_full()); - $this->loaded_lines = true; - } - return $this->file_lines; - } - - public function get_contents() { - if (!$this->loaded) { - $this->contents = $this->load_contents(); - } - return $this->contents; - } - - abstract protected function load_contents(); - -} - - diff --git a/libraries/php/code_abstractions/file_abstractions/FileText.php b/libraries/php/code_abstractions/file_abstractions/FileText.php deleted file mode 100644 index 618ec30d4..000000000 --- a/libraries/php/code_abstractions/file_abstractions/FileText.php +++ /dev/null @@ -1,11 +0,0 @@ -get_path_full()); - } - -} diff --git a/libraries/php/code_abstractions/file_abstractions/discrete/docker/FileDockerCompose.php b/libraries/php/code_abstractions/file_abstractions/discrete/docker/FileDockerCompose.php deleted file mode 100644 index f3f026f98..000000000 --- a/libraries/php/code_abstractions/file_abstractions/discrete/docker/FileDockerCompose.php +++ /dev/null @@ -1,62 +0,0 @@ -getFullPath()); - } - - private function temp_get_parsed_lines(array $file_lines) : CodeSegments { - $segments = new CodeSegments(); - foreach ($file_lines as $line) { - if (trim($line) === '') { - $segments->add_empty_line(); - } else if (STR::starts_with(trim($line), '#')) { - $segments->add_comment($line); - } else { - $segments->add_line($line); - } - } - return $segments; - } - - private function perform_clean(CodeSegments $segments): void { - $version = $segments->get_line_with_text("version: '3.7'"); - $services = $segments->get_line_with_text('services:'); - - $segments->remove_all_before($services); - $segments->add_comment('# Services collectively make up a distributed application. (0x1)', true); - $segments->add_empty_line(true); - $segments->add_line("version: '3.7'", true); - $segments->add_comment("# {'Compose file format': 3.7, 'Docker Engine release': 18.06.0*} (0x0)", true); - - $lines = $segments->get_segments(); - $file_text = ''; - foreach ($lines as $line) { - $file_text .= $line; - } - #echo $file_text; - - UFO::set($this->get_path_full(), $file_text); - } - - public function clean(): void { - var_dump('TODO: CLEAN DOCKER FILE!'); - #var_dump($this); - - $lines = $this->get_lines(); - - $code_segments = $this->temp_get_parsed_lines($lines); - $this->perform_clean($code_segments); - - //die(); - } -} diff --git a/libraries/php/code_abstractions/file_abstractions/discrete/docker/FileDockerIgnore.php b/libraries/php/code_abstractions/file_abstractions/discrete/docker/FileDockerIgnore.php deleted file mode 100644 index ca83803f9..000000000 --- a/libraries/php/code_abstractions/file_abstractions/discrete/docker/FileDockerIgnore.php +++ /dev/null @@ -1,12 +0,0 @@ -