UNPKG

spacesvr-websessions

Version:

A standardized reality for future of the 3D Web

1,216 lines (1,070 loc) 326 kB
var React = require('react'); 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _extends = require('@babel/runtime/helpers/extends'); var _objectWithoutPropertiesLoose = require('@babel/runtime/helpers/objectWithoutPropertiesLoose'); var React$1 = require('react'); var fiber = require('@react-three/fiber'); var three = require('three'); var three$1 = require('@react-spring/three'); var culori = require('culori'); var drei = require('@react-three/drei'); var cannon = require('@react-three/cannon'); var WebGLExtensions = require('three/src/renderers/webgl/WebGLExtensions'); var KTX2Loader = require('three/examples/jsm/loaders/KTX2Loader'); var suspendReact = require('suspend-react'); var BufferGeometryUtils = require('three/examples/jsm/utils/BufferGeometryUtils'); var threeMeshBvh = require('three-mesh-bvh'); var _taggedTemplateLiteralLoose = require('@babel/runtime/helpers/taggedTemplateLiteralLoose'); var react = require('@emotion/react'); var nipplejs = require('nipplejs'); var styled = require('@emotion/styled'); var framerMotion = require('framer-motion'); var reactDeviceDetect = require('react-device-detect'); var _asyncToGenerator = require('@babel/runtime/helpers/asyncToGenerator'); var xr = require('@react-three/xr'); var threeStdlib = require('three-stdlib'); var reactErrorBoundary = require('react-error-boundary'); var RoundedBoxGeometry = require('three/examples/jsm/geometries/RoundedBoxGeometry'); var troikaThreeText = require('troika-three-text'); var snapshotInterpolation = require('@geckos.io/snapshot-interpolation'); var peerjs = require('peerjs'); var nodeFetch = require('node-fetch'); var core = require('@react-spring/core'); var reactDom = require('react-dom'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n["default"] = e; return Object.freeze(n); } var _extends__default = /*#__PURE__*/_interopDefaultLegacy(_extends); var _objectWithoutPropertiesLoose__default = /*#__PURE__*/_interopDefaultLegacy(_objectWithoutPropertiesLoose); var React__default = /*#__PURE__*/_interopDefaultLegacy(React$1); var culori__namespace = /*#__PURE__*/_interopNamespace(culori); var _taggedTemplateLiteralLoose__default = /*#__PURE__*/_interopDefaultLegacy(_taggedTemplateLiteralLoose); var nipplejs__default = /*#__PURE__*/_interopDefaultLegacy(nipplejs); var styled__default = /*#__PURE__*/_interopDefaultLegacy(styled); var _asyncToGenerator__default = /*#__PURE__*/_interopDefaultLegacy(_asyncToGenerator); var nodeFetch__default = /*#__PURE__*/_interopDefaultLegacy(nodeFetch); var vertHead$3 = "\n // Description : Array and textureless GLSL 2D/3D/4D simplex\n // noise functions.\n // Author : Ian McEwan, Ashima Arts.\n // Maintainer : ijm\n // Lastmod : 20110822 (ijm)\n // License : Copyright (C) 2011 Ashima Arts. All rights reserved.\n // Distributed under the MIT License. See LICENSE file.\n // https://github.com/ashima/webgl-noise\n //\n \n vec3 mod289(vec3 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n }\n \n vec4 mod289(vec4 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n }\n \n vec4 permute(vec4 x) {\n return mod289(((x*34.0)+1.0)*x);\n }\n \n vec4 taylorInvSqrt(vec4 r)\n {\n return 1.79284291400159 - 0.85373472095314 * r;\n }\n \n float snoise(vec3 v)\n {\n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n \n // First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n \n // Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n \n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n \n // Permutations\n i = mod289(i);\n vec4 p = permute( permute( permute(\n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 ))\n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n \n // Gradients: 7x7 points over a square, mapped onto an octahedron.\n // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n \n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n \n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n \n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n \n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n \n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n \n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n \n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n \n //Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n \n // Mix final noise value\n vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),\n dot(p2,x2), dot(p3,x3) ) );\n }\n \n \n float fsnoise(float val1, float val2, float val3){\n return snoise(vec3(val1,val2,val3));\n }\n \n vec3 distortFunct(vec3 transformed, float factor) {\n float radiusVariation = -fsnoise(\n transformed.x * radiusNoiseFrequency + time,\n transformed.y * radiusNoiseFrequency + time,\n transformed.z * radiusNoiseFrequency + time \n ) * radiusVariationAmplitude * factor;\n return normalize(transformed) * (radiusVariation + radius);\n }\n \n vec3 orthogonal(vec3 v) {\n return normalize(abs(v.x) > abs(v.z) ? vec3(-v.y, v.x, 0.0)\n : vec3(0.0, -v.z, v.y));\n }\n \n vec3 distortNormal(vec3 position, vec3 distortedPosition, vec3 normal){\n vec3 tangent1 = orthogonal(normal);\n vec3 tangent2 = normalize(cross(normal, tangent1));\n vec3 nearby1 = position + tangent1 * 0.1;\n vec3 nearby2 = position + tangent2 * 0.1;\n vec3 distorted1 = distortFunct(nearby1, 1.0);\n vec3 distorted2 = distortFunct(nearby2, 1.0);\n return normalize(cross(distorted1 - distortedPosition, distorted2 - distortedPosition));\n }\n"; var vert$3 = "\n #include <begin_vertex>\n float updateTime = time / 10.0;\n transformed = distortFunct(transformed, 1.0);\n vec3 distortedNormal = distortNormal(position, transformed, normal);\n vNormal = normal + distortedNormal;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(transformed,1.);\n"; var frag$3 = "\n #include <dithering_fragment>\n float angle = clamp(dot(normalize(vNormal), vec3(0., -1., 0.)), 0., 1.);\n gl_FragColor = vec4(gl_FragColor.rgb * color, gl_FragColor.a); \n gl_FragColor.rgb = mix(gl_FragColor.rgb, mix(color, vec3(0.), 0.5), angle);\n"; /** * Returns a function that, when used every frame, will mark itself * as ready maximum {frequency} times per second. * * @param frequency How many times per second to be marked as ready */ var useLimiter = function useLimiter(frequency) { var lastCall = React$1.useRef(0); return { isReady: function isReady(clock) { var time = clock.elapsedTime; var ready = time - lastCall.current > 1 / frequency; if (ready) { lastCall.current = time; } return ready; } }; }; /** * A 1:1 copy of useFrame, but adds a limiter * * Callback will only run {frequency} times per second */ var useLimitedFrame = function useLimitedFrame(frequency, callback, renderPriority) { var limiter = useLimiter(frequency); fiber.useFrame(function (state, delta) { if (!limiter.isReady(state.clock)) return; callback(state, delta); }, renderPriority); }; var _excluded$p = ["idea"]; function VisualIdea(props) { var idea = props.idea, rest = _objectWithoutPropertiesLoose__default["default"](props, _excluded$p); var hex = React$1.useMemo(function () { return (idea == null ? void 0 : idea.getHex()) || "#808080"; }, [idea]); var seed = React$1.useMemo(function () { return Math.random(); }, []); var color = React$1.useMemo(function () { return new three.Color(hex); }, [hex]); var RADIUS = 4; var NOISE_AMPLITUDE = 0.82; var NOISE_FREQ = 0.154; var _useSpring = three$1.useSpring({ col: hex }), col = _useSpring.col; var mat = React$1.useMemo(function () { var material = new three.MeshStandardMaterial({ metalness: 0.18, roughness: 0.49, envMapIntensity: 0.66, side: three.DoubleSide }); material.onBeforeCompile = function (shader) { shader.uniforms.radius = new three.Uniform(RADIUS); shader.uniforms.time = new three.Uniform(0); shader.uniforms.color = new three.Uniform(color); shader.uniforms.radiusVariationAmplitude = new three.Uniform(NOISE_AMPLITUDE); shader.uniforms.radiusNoiseFrequency = new three.Uniform(NOISE_FREQ); var uniforms = "\n uniform float radius;\n uniform float time;\n uniform vec3 color;\n uniform float radiusVariationAmplitude;\n uniform float radiusNoiseFrequency;\n "; shader.vertexShader = uniforms + vertHead$3 + shader.vertexShader.replace("#include <begin_vertex>", vert$3); shader.fragmentShader = uniforms + shader.fragmentShader.replace("#include <dithering_fragment>", frag$3); material.userData.shader = shader; }; return material; }, [RADIUS, color, NOISE_AMPLITUDE, NOISE_FREQ, frag$3, vert$3]); var limiter = useLimiter(50); fiber.useFrame(function (_ref) { var _mat$userData; var clock = _ref.clock; if (!(mat != null && (_mat$userData = mat.userData) != null && _mat$userData.shader) || !limiter.isReady(clock)) return; mat.userData.shader.uniforms.time.value = clock.elapsedTime / 6 + seed * 1000; mat.userData.shader.uniforms.color.value.set(col.get()); }); return /*#__PURE__*/React.createElement("group", _extends__default["default"]({ name: "spacesvr-basis-idea" }, rest), /*#__PURE__*/React.createElement("mesh", { material: mat, scale: 0.2 }, /*#__PURE__*/React.createElement("sphereBufferGeometry", { args: [RADIUS, 48, 32] }))); } var rgb_helper = "\n vec3 rgb2hsv(vec3 c)\n {\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n \n float d = q.x - min(q.w, q.y);\n float e = 1.0e-10;\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n }\n \n vec3 hsv2rgb(vec3 c)\n {\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n }\n"; var noise4D = "\n vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}\nfloat permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));}\nvec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}\nfloat taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;}\n\nvec4 grad4(float j, vec4 ip){\n const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);\n vec4 p,s;\n\n p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;\n p.w = 1.5 - dot(abs(p.xyz), ones.xyz);\n s = vec4(lessThan(p, vec4(0.0)));\n p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; \n\n return p;\n}\n\nfloat snoise(vec4 v){\n const vec2 C = vec2( 0.138196601125010504, // (5 - sqrt(5))/20 G4\n 0.309016994374947451); // (sqrt(5) - 1)/4 F4\n// First corner\n vec4 i = floor(v + dot(v, C.yyyy) );\n vec4 x0 = v - i + dot(i, C.xxxx);\n\n// Other corners\n\n// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)\n vec4 i0;\n\n vec3 isX = step( x0.yzw, x0.xxx );\n vec3 isYZ = step( x0.zww, x0.yyz );\n// i0.x = dot( isX, vec3( 1.0 ) );\n i0.x = isX.x + isX.y + isX.z;\n i0.yzw = 1.0 - isX;\n\n// i0.y += dot( isYZ.xy, vec2( 1.0 ) );\n i0.y += isYZ.x + isYZ.y;\n i0.zw += 1.0 - isYZ.xy;\n\n i0.z += isYZ.z;\n i0.w += 1.0 - isYZ.z;\n\n // i0 now contains the unique values 0,1,2,3 in each channel\n vec4 i3 = clamp( i0, 0.0, 1.0 );\n vec4 i2 = clamp( i0-1.0, 0.0, 1.0 );\n vec4 i1 = clamp( i0-2.0, 0.0, 1.0 );\n\n // x0 = x0 - 0.0 + 0.0 * C \n vec4 x1 = x0 - i1 + 1.0 * C.xxxx;\n vec4 x2 = x0 - i2 + 2.0 * C.xxxx;\n vec4 x3 = x0 - i3 + 3.0 * C.xxxx;\n vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx;\n\n// Permutations\n i = mod(i, 289.0); \n float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x);\n vec4 j1 = permute( permute( permute( permute (\n i.w + vec4(i1.w, i2.w, i3.w, 1.0 ))\n + i.z + vec4(i1.z, i2.z, i3.z, 1.0 ))\n + i.y + vec4(i1.y, i2.y, i3.y, 1.0 ))\n + i.x + vec4(i1.x, i2.x, i3.x, 1.0 ));\n// Gradients\n// ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.)\n// 7*7*6 = 294, which is close to the ring size 17*17 = 289.\n\n vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;\n\n vec4 p0 = grad4(j0, ip);\n vec4 p1 = grad4(j1.x, ip);\n vec4 p2 = grad4(j1.y, ip);\n vec4 p3 = grad4(j1.z, ip);\n vec4 p4 = grad4(j1.w, ip);\n\n// Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n p4 *= taylorInvSqrt(dot(p4,p4));\n\n// Mix contributions from the five corners\n vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);\n vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0);\n m0 = m0 * m0;\n m1 = m1 * m1;\n float final = 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))\n + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ;\n return (final + 1.) / 2.;\n}\n"; var oklab$1 = "\nfloat fixedpow(float a, float x)\n{\n return pow(abs(a), x) * sign(a);\n}\n\nfloat cbrt(float a)\n{\n return fixedpow(a, 0.3333333333);\n}\n\nvec3 lsrgb2oklab(vec3 c)\n{\n float l = 0.4122214708 * c.r + 0.5363325363 * c.g + 0.0514459929 * c.b;\n float m = 0.2119034982 * c.r + 0.6806995451 * c.g + 0.1073969566 * c.b;\n float s = 0.0883024619 * c.r + 0.2817188376 * c.g + 0.6299787005 * c.b;\n\n float l_ = cbrt(l);\n float m_ = cbrt(m);\n float s_ = cbrt(s);\n\n return vec3(\n 0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_,\n 1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_,\n 0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_\n );\n}\n\nvec3 oklab2lsrgb(vec3 c)\n{\n float l_ = c.r + 0.3963377774 * c.g + 0.2158037573 * c.b;\n float m_ = c.r - 0.1055613458 * c.g - 0.0638541728 * c.b;\n float s_ = c.r - 0.0894841775 * c.g - 1.2914855480 * c.b;\n\n float l = l_ * l_ * l_;\n float m = m_ * m_ * m_;\n float s = s_ * s_ * s_;\n\n return vec3(\n 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,\n -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,\n -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s\n );\n}\n"; var vertHead$2 = "\n precision highp float;\n varying vec2 vUv;\n varying float terrain;\n varying float terrain_perc;\n varying vec3 vfNormal;\n\n uniform float radius;\n uniform float time;\n uniform vec3 color;\n\n " + noise4D + "\n"; var vert$2 = "\n vec3 pos = position;\n \n terrain = 0.;\n float u_time = time * 0.25;\n \n terrain += 1. * pow(snoise(vec4(pos.xyz * 0.15, u_time + 100.)), 1.);\n terrain += 0.8 * pow(snoise(vec4(pos.xyz * 0.2, u_time + 200.)), 1.5);\n terrain += 0.4 * pow(snoise(vec4(pos.xyz * 0.8, u_time + 300.)), 2.);\n terrain += 0.2 * pow(snoise(vec4(pos.xyz * 1.6, u_time + 400.)), 8.);\n terrain_perc = terrain / (1. + 0.8 + 0.4 + 0.2);\n terrain_perc = terrain_perc;\n \n pos = pos + normal * 2. * 2. * (terrain_perc - 0.5);\n vfNormal = normal;\n \n gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.);\n"; var fragHead$1 = "\n precision highp float;\n varying vec2 vUv;\n varying vec3 vfNormal;\n varying float terrain;\n varying float terrain_perc;\n\n uniform float time;\n uniform vec3 axiom;\n uniform float range;\n uniform vec3 up_norm;\n \n \n " + rgb_helper + "\n " + oklab$1 + "\n"; var frag$2 = "\n vec3 hsv_col = rgb2hsv(gl_FragColor.rgb);\n \n // todo: offset vfNormal by up_norm\n vec3 oklab_axiom = lsrgb2oklab(axiom);\n vec3 oklab_range_idea = lsrgb2oklab(axiom + 0.35 * range * vfNormal);\n vec3 col = oklab2lsrgb(mix(oklab_axiom, oklab_range_idea, 1. - terrain_perc));\n \n gl_FragColor.rgb = col * pow(hsv_col.z, 1.3);\n \n \n gl_FragColor.rgb *= 0.15 + 1.85 * pow((1. - terrain_perc), 1.5);\n"; // @ts-ignore /** * an idea is the fundamental substrate of reality. */ var Idea = /*#__PURE__*/function () { // identifiers // mediation // [0, 1) // [0, 1] // [0, 1] function Idea(m, s, u) { if (m === void 0) { m = 0; } if (s === void 0) { s = 0; } if (u === void 0) { u = 0.5; } this.setFromCreation(m, s, u); return this; } var _proto = Idea.prototype; _proto.setFromCreation = function setFromCreation(m, s, u) { if (m === void 0) { m = 0; } if (s === void 0) { s = 0; } if (u === void 0) { u = 0.5; } this.mediation = m; this.specificity = s; this.utility = u; return this; }; _proto.setFromHex = function setFromHex(hex) { var color = culori__namespace.oklch(culori__namespace.rgb(hex)); if (!color) { console.warn("idea :: setFromHex - invalid hex color"); return this; } this.mediation = color.h / 360; this.specificity = color.c / 0.322; this.utility = color.l; return this; }; _proto.updateFromText = function updateFromText(text) { var len = text.length; this.mediation = hashStringToRange$1(text); this.specificity = (1 - (len == 0 ? 1 : 1 / len)) * 0.5; return this; }; _proto.setUtility = function setUtility(utility) { this.utility = utility; return this; }; _proto.getHex = function getHex() { var fixedColor = culori__namespace.rgb({ mode: "oklch", l: this.utility, c: this.specificity * 0.322, h: this.mediation * 360 }); return culori__namespace.formatHex(fixedColor); }; _proto.getOpposite = function getOpposite() { var newM = this.mediation + 0.5 > 1 ? this.mediation - 0.5 : this.mediation + 0.5; var newS = this.specificity; var newU = 0.5 - (this.utility - 0.5); return new Idea().setFromCreation(newM, newS, newU); }; _proto.clone = function clone() { return new Idea(this.mediation, this.specificity, this.utility); }; return Idea; }(); var AVG_CHAR_VAL$1 = 100; // each char is roughly 100, so loop every ~50 chars var hashStringToRange$1 = function hashStringToRange(str, loop) { if (loop === void 0) { loop = 20; } var count = 0; for (var i = 0; i < str.length; i++) { count += str.substr(i, 1).charCodeAt(0); } var scaledLoop = loop * AVG_CHAR_VAL$1; return count % scaledLoop / scaledLoop; }; var _excluded$o = ["world"]; function VisualWorld(props) { var world = props.world, rest = _objectWithoutPropertiesLoose__default["default"](props, _excluded$o); var RADIUS = 4; var SEED = React$1.useMemo(function () { return Math.random(); }, []); var mat = React$1.useMemo(function () { var material = new three.MeshStandardMaterial({ metalness: 0.18, roughness: 0.49, side: three.DoubleSide }); material.onBeforeCompile = function (shader) { var uniforms = { time: new three.Uniform(0), axiom: new three.Uniform(new three.Color("#888888")), up_norm: new three.Uniform(new three.Vector3(0, 1, 0)), range: new three.Uniform(0) }; shader.uniforms = _extends__default["default"]({}, shader.uniforms, uniforms); shader.vertexShader = vertHead$2 + shader.vertexShader.replace("#include <worldpos_vertex>", "#include <worldpos_vertex>\n" + vert$2); shader.fragmentShader = fragHead$1 + shader.fragmentShader.replace("#include <dithering_fragment>", "#include <dithering_fragment>\n" + frag$2); material.userData.shader = shader; }; material.needsUpdate = true; return material; }, []); React$1.useEffect(function () { if (!mat || !mat.userData.shader || !world) return; var unifs = mat.userData.shader.uniforms; var axiom = world ? world.getAxiom() : new Idea(); unifs.axiom.value.set(new three.Color(axiom.getHex())); unifs.up_norm.value = world == null ? void 0 : world.getUpNorm(); unifs.range.value = world == null ? void 0 : world.getRange(); }, [world, mat]); useLimitedFrame(50, function (_ref) { var clock = _ref.clock; if (!mat || !mat.userData.shader) return; mat.userData.shader.uniforms.time.value = clock.elapsedTime + SEED * 500; }); return /*#__PURE__*/React.createElement("group", _extends__default["default"]({ name: "spacesvr-basis-world" }, rest), /*#__PURE__*/React.createElement("mesh", { material: mat, scale: 0.2 }, /*#__PURE__*/React.createElement("sphereBufferGeometry", { args: [RADIUS, 48, 32] }))); } var DOWN_AXIS = new three.Vector3(0, -1, 0); /** * Will smoothly rotate its children to face the camera along the Y axis, regardless of the parent's rotation. */ function LookAtPlayer(props) { var _props$enabled = props.enabled, enabled = _props$enabled === void 0 ? true : _props$enabled, children = props.children; var group = React$1.useRef(null); var flatDelta = React$1.useMemo(function () { return new three.Vector2(); }, []); var worldPos = React$1.useMemo(function () { return new three.Vector3(); }, []); var worldQuat = React$1.useMemo(function () { return new three.Quaternion(); }, []); var targetQuat = React$1.useMemo(function () { return new three.Quaternion(); }, []); var parentQuat = React$1.useMemo(function () { return new three.Quaternion(); }, []); var offsetRot = React$1.useMemo(function () { return new three.Euler(); }, []); useLimitedFrame(50, function (_ref, delta) { var _group$current$parent; var camera = _ref.camera; if (!group.current) return; (_group$current$parent = group.current.parent) == null ? void 0 : _group$current$parent.getWorldQuaternion(parentQuat); offsetRot.setFromQuaternion(parentQuat, "YXZ"); targetQuat.set(0, 0, 0, 1); if (enabled) { group.current.getWorldPosition(worldPos); group.current.getWorldQuaternion(worldQuat); flatDelta.x = camera.position.x - worldPos.x; flatDelta.y = camera.position.z - worldPos.z; var angle = flatDelta.angle() - Math.PI / 2 + offsetRot.y; targetQuat.setFromAxisAngle(DOWN_AXIS, angle); } group.current.quaternion.slerp(targetQuat, 0.11); }); return /*#__PURE__*/React.createElement("group", { name: "look-at-player", ref: group }, children); } function Background$1(props) { var color = props.color; var scene = fiber.useThree(function (state) { return state.scene; }); React$1.useLayoutEffect(function () { var oldBackground = scene.background; var col = color instanceof three.Color ? color : new three.Color(color); scene.background = col; return function () { scene.background = oldBackground; }; }, [color]); return null; } function Fog(props) { var _props$color = props.color, color = _props$color === void 0 ? "white" : _props$color, _props$near = props.near, near = _props$near === void 0 ? 10 : _props$near, _props$far = props.far, far = _props$far === void 0 ? 80 : _props$far; var scene = fiber.useThree(function (state) { return state.scene; }); React$1.useEffect(function () { var col = color instanceof three.Color ? color : new three.Color(color); scene.fog = new three.Fog(col, near, far); return function () { scene.fog = null; }; }, [scene, color, near, far]); return null; } function InfinitePlane(props) { var _props$height = props.height, height = _props$height === void 0 ? -0.0001 : _props$height, _props$size = props.size, size = _props$size === void 0 ? [100, 100] : _props$size, visible = props.visible; var _usePlane = cannon.usePlane(function () { return { rotation: [-Math.PI / 2, 0, 0], position: [0, height, 0], args: size, type: "Static" }; }), ref = _usePlane[0]; if (!visible) return null; return /*#__PURE__*/React.createElement("mesh", { name: "spacesvr-infinite-plane", ref: ref }, /*#__PURE__*/React.createElement("planeBufferGeometry", { args: size }), /*#__PURE__*/React.createElement("meshPhongMaterial", { color: "#660000" })); } var _excluded$n = ["url", "dCone", "rollOff", "volume", "setAudioAnalyser", "fftSize"]; function Audio$1(props) { var url = props.url, _props$dCone = props.dCone, dCone = _props$dCone === void 0 ? new three.Vector3(180, 230, 0.1) : _props$dCone, _props$rollOff = props.rollOff, rollOff = _props$rollOff === void 0 ? 1 : _props$rollOff, _props$volume = props.volume, volume = _props$volume === void 0 ? 1 : _props$volume, setAudioAnalyser = props.setAudioAnalyser, _props$fftSize = props.fftSize, fftSize = _props$fftSize === void 0 ? 128 : _props$fftSize, rest = _objectWithoutPropertiesLoose__default["default"](props, _excluded$n); var _useState = React$1.useState(), speaker = _useState[0], setSpeaker = _useState[1]; var camera = fiber.useThree(function (state) { return state.camera; }); var audio = React$1.useMemo(function () { var a = document.createElement("audio"); a.src = url; a.autoplay = false; a.preload = "auto"; a.crossOrigin = "Anonymous"; a.loop = true; return a; }, []); React$1.useEffect(function () { var setupAudio = function setupAudio() { if (!audio.paused && !speaker) { var listener = new three.AudioListener(); camera.add(listener); var speak = new three.PositionalAudio(listener); speak.setMediaElementSource(audio); speak.setRefDistance(0.75); speak.setRolloffFactor(rollOff); speak.setVolume(volume); speak.setDirectionalCone(dCone.x, dCone.y, dCone.z); if (setAudioAnalyser) { setAudioAnalyser(new three.AudioAnalyser(speak, fftSize)); } setSpeaker(speak); } }; var playAudio = function playAudio() { return audio.play().then(function () { return setupAudio(); }); }; if (audio) { audio.setAttribute("src", url); audio.play().then(function () { return setupAudio(); }); document.addEventListener("click", playAudio); return function () { document.removeEventListener("click", playAudio); }; } }, [speaker, audio, url]); React$1.useEffect(function () { if (!speaker) return; speaker.setRolloffFactor(rollOff); speaker.setVolume(volume); speaker.setDirectionalCone(dCone.x, dCone.y, dCone.z); }, [dCone, rollOff, volume]); return /*#__PURE__*/React.createElement("group", _extends__default["default"]({ name: "spacesvr-audio" }, rest), speaker && /*#__PURE__*/React.createElement("primitive", { object: speaker })); } function HDRI(props) { var src = props.src, disableBackground = props.disableBackground, disableEnvironment = props.disableEnvironment; return /*#__PURE__*/React.createElement(React$1.Suspense, { fallback: null }, /*#__PURE__*/React.createElement(drei.Environment, { files: src, background: !disableBackground && !disableEnvironment ? true : disableEnvironment && !disableBackground ? "only" : false })); } var fallbackTexture; var SIZE = 128; var SIZE_2 = SIZE / 2; var RAD = 12; var LINE_W = 1; /** * Provides a default texture that is created locally */ function getFallbackTexture() { if (fallbackTexture) return fallbackTexture; var canvas = document.createElement("canvas"); canvas.height = SIZE; canvas.width = SIZE; var context = canvas.getContext("2d"); context.fillStyle = "#FFFFFF"; context.fillRect(0, 0, SIZE, SIZE); // main circle context.fillStyle = "#000000"; context.beginPath(); context.arc(SIZE_2, SIZE_2, RAD, 0, 2 * Math.PI); context.fill(); // draw a white line down the middle of the circle context.strokeStyle = "#FFFFFF"; context.lineWidth = Math.ceil(LINE_W); context.beginPath(); context.moveTo(SIZE_2, SIZE_2 - RAD); context.lineTo(SIZE_2, SIZE_2 + RAD); context.stroke(); // draw a horizontal line across the middle of the circle context.beginPath(); context.moveTo(SIZE_2 - RAD, SIZE_2); context.lineTo(SIZE_2 + RAD, SIZE_2); context.stroke(); fallbackTexture = new three.CanvasTexture(canvas); return fallbackTexture; } var KTX_CDN = "https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/basis/"; var textureLoader = new three.TextureLoader(); var ktx2loader; // it's inconvenient to have to produce a gl object to check for ktx2 support, especially when it comes to the cache keys // solution is to create a skeleton object that provides the minimum requirements to check for ktx support, defined below // https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/KTX2Loader.js#L113-L135 var setupKtx2 = function setupKtx2() { if (ktx2loader) return; ktx2loader = new KTX2Loader.KTX2Loader(); ktx2loader.setTranscoderPath(KTX_CDN); var supportsWebgl2; var el = document.createElement("canvas"); var gl = el.getContext("webgl2"); if (gl) { supportsWebgl2 = true; } else { gl = el.getContext("webgl"); supportsWebgl2 = false; } if (!gl) { throw new Error("No WebGL support"); } el.remove(); var minimumGL = { extensions: new WebGLExtensions.WebGLExtensions(gl), capabilities: { isWebGL2: supportsWebgl2 } }; // @ts-ignore ktx2loader.detectSupport(minimumGL); }; function loadimage() { return function (url) { var IS_KTX2 = url.toLowerCase().endsWith("ktx2"); setupKtx2(); var loader = IS_KTX2 ? ktx2loader : textureLoader; return new Promise(function (res) { return loader.load(url, res, undefined, function (error) { console.error(error); res(getFallbackTexture()); }); }); }; } /** * A single hook akin to useTexture but with ktx support * * KTX_CDN is from drei so that we don't download two separate transcoders when using the useKtx2 hook elsewhere * https://github.com/pmndrs/drei/blob/a2daf02853f624ef6062c70ba0b218bc03e5b626/src/core/useKTX2.tsx#L7 * @param url */ function useImage(url) { return suspendReact.suspend(loadimage(), [url]); } useImage.preload = function (url) { return suspendReact.preload(loadimage(), [url]); }; useImage.clear = function (url) { return suspendReact.clear([url]); }; /** * A hook to load gltf models with draco, meshopt, and ktx2 support out of the box * * For all cases, functionality is to only download decoder files if needed by the file * @param url */ function useModel(url) { return drei.useGLTF(url, true, true, function (loader) { setupKtx2(); loader.setKTX2Loader(ktx2loader); }); } useModel.preload = function (url) { return drei.useGLTF.preload(url, true, true, function (loader) { setupKtx2(); loader.setKTX2Loader(ktx2loader); }); }; useModel.clear = function (url) { return drei.useGLTF.clear([url]); }; /** * * Builds a frame for a mesh with a texture (image, video, etc.) * * In the code, the frame is the back panel and the border is the * four meshes that make up the top, left, right, and bottom sides * of the border. * * @param props * @constructor */ function Frame(props) { var width = props.width, height = props.height, _props$thickness = props.thickness, thickness = _props$thickness === void 0 ? 1 : _props$thickness, passedMaterial = props.material, innerFrameMaterial = props.innerFrameMaterial; var material = React$1.useMemo(function () { return passedMaterial || new three.MeshStandardMaterial({ color: 0x333333, roughness: 0.8, metalness: 0.05 }); }, [passedMaterial]); var frameDepth = 0.075; var frameWidth = 0.06; var borderDepth = 0.08; var borderThickness = 0.05 * thickness; var meshOffset = 0.0005; var geometry = React$1.useMemo(function () { var backPanel = new three.BoxBufferGeometry(width + frameWidth, height + frameWidth, frameDepth); backPanel.translate(0, 0, -frameDepth - meshOffset); var topFrame = new three.BoxBufferGeometry(width + frameWidth, borderThickness, borderDepth); topFrame.translate(0, height / 2 + frameWidth / 2 - borderThickness / 2, 0); var bottomFrame = new three.BoxBufferGeometry(width + frameWidth, borderThickness, borderDepth); bottomFrame.translate(0, -height / 2 - frameWidth / 2 + borderThickness / 2, 0); var leftFrame = new three.BoxBufferGeometry(borderThickness, height + frameWidth, borderDepth); leftFrame.translate(-width / 2 - frameWidth / 2 + borderThickness / 2, 0, 0); var rightFrame = new three.BoxBufferGeometry(borderThickness, height + frameWidth, borderDepth); rightFrame.translate(width / 2 + frameWidth / 2 - borderThickness / 2, 0, 0); var geos = [backPanel, topFrame, bottomFrame, leftFrame, rightFrame]; var geo = BufferGeometryUtils.mergeBufferGeometries(geos); backPanel.dispose(); topFrame.dispose(); bottomFrame.dispose(); leftFrame.dispose(); rightFrame.dispose(); return geo; }, [innerFrameMaterial, borderThickness, width, height]); var backFrameGeometry = React$1.useMemo(function () { if (!innerFrameMaterial) return undefined; var backPanel = new three.BoxBufferGeometry(width + frameWidth, height + frameWidth, frameDepth); backPanel.translate(0, 0, -frameDepth - meshOffset); return backPanel; }, [innerFrameMaterial, width, height]); return /*#__PURE__*/React.createElement("group", { name: "spacesvr-frame" }, /*#__PURE__*/React.createElement("mesh", { geometry: geometry, material: material }), backFrameGeometry && innerFrameMaterial && /*#__PURE__*/React.createElement("mesh", { geometry: backFrameGeometry, material: innerFrameMaterial })); } var _excluded$m = ["src", "size", "framed", "frameMaterial", "frameWidth", "innerFrameMaterial"]; function UnsuspensedImage(props) { var src = props.src, _props$size = props.size, size = _props$size === void 0 ? 1 : _props$size, framed = props.framed, frameMaterial = props.frameMaterial, _props$frameWidth = props.frameWidth, frameWidth = _props$frameWidth === void 0 ? 1 : _props$frameWidth, innerFrameMaterial = props.innerFrameMaterial, rest = _objectWithoutPropertiesLoose__default["default"](props, _excluded$m); var tex = useImage(src); var _tex$image = tex.image, width = _tex$image.width, height = _tex$image.height; var max = Math.max(width, height); var WIDTH = width / max * size; var HEIGHT = height / max * size; var IS_COMPRESSED = tex.isCompressedTexture; return /*#__PURE__*/React.createElement("group", _extends__default["default"]({ name: "spacesvr-image" }, rest), /*#__PURE__*/React.createElement("mesh", { rotation: IS_COMPRESSED ? [0, Math.PI, Math.PI] : [0, 0, 0] }, /*#__PURE__*/React.createElement("planeBufferGeometry", { args: [WIDTH, HEIGHT] }), /*#__PURE__*/React.createElement("meshBasicMaterial", { map: tex, side: three.DoubleSide, transparent: true })), framed && /*#__PURE__*/React.createElement(Frame, { width: WIDTH, height: HEIGHT, thickness: frameWidth, material: frameMaterial, innerFrameMaterial: innerFrameMaterial })); } function Image$1(props) { return /*#__PURE__*/React.createElement(React$1.Suspense, { fallback: null }, /*#__PURE__*/React.createElement(UnsuspensedImage, props)); } /** * a world is a set of ideas */ var World = /*#__PURE__*/function () { function World() { return this; } var _proto = World.prototype; _proto.getIdea = function getIdea() { return new Idea().setFromCreation(hashStringToRange(JSON.stringify(this.tree || this.id), 3), 0.3 + 0.7 * hashStringToRange(this.id), 0.8); }; _proto.getAxiom = function getAxiom() { var str = JSON.stringify(this.tree || this.id); var strHash = new Array(10).fill(1).map(function () { return str; }).join(""); return new Idea().setFromCreation(hashStringToRange(strHash, 15), 0.3 + 0.7 * hashStringToRange(strHash, 10), 0.8); }; _proto.getUpNorm = function getUpNorm() { // 4 digit long hex values var x = parseInt(this.id.split("-")[1], 16) / Math.pow(16, 4); var y = parseInt(this.id.split("-")[2], 16) / Math.pow(16, 4); var z = parseInt(this.id.split("-")[3], 16) / Math.pow(16, 4); return new three.Vector3(x, y, z).normalize(); }; _proto.getRange = function getRange() { var r = parseInt(this.id.split("-")[0], 16) / Math.pow(16, 8); return 0.3 + 0.7 * r; }; _proto.getHex = function getHex() { return this.getIdea().getHex(); }; return World; }(); var AVG_CHAR_VAL = 100; // each char is roughly 100, so loop every ~50 chars var hashStringToRange = function hashStringToRange(str, loop) { if (loop === void 0) { loop = 8; } var count = 0; for (var i = 0; i < str.length; i++) { count += str.substr(i, 1).charCodeAt(0); } var scaledLoop = loop * AVG_CHAR_VAL; return count % scaledLoop / scaledLoop; }; /** * A site is a delivery method of a world. */ var Site = function Site() { return this; }; /** * Gets the number of triangles in a geometry */ var getGeometryTriCount$1 = function getGeometryTriCount(geometry) { return geometry.index ? geometry.index.count / 3 : geometry.attributes.position.count / 3; }; /** * For a given mesh, set up bvh raycasting for it if it meets the threshold for * amount of triangles to use * * @param mesh * @param threshold */ var enableBVHRaycast = function enableBVHRaycast(mesh, threshold) { if (threshold === void 0) { threshold = 0; } if (!mesh.geometry || !mesh.geometry.isBufferGeometry) { return; } var geometry = mesh.geometry; var triCount = getGeometryTriCount$1(geometry); if (geometry.boundsTree || triCount < threshold) return; mesh.raycast = threeMeshBvh.acceleratedRaycast; geometry.computeBoundsTree = threeMeshBvh.computeBoundsTree; geometry.disposeBoundsTree = threeMeshBvh.disposeBoundsTree; geometry.computeBoundsTree({ verbose: true }); }; var universe_cache = new Map(); function getResource(key, constructor, opts) { var resource = universe_cache.get(key); if (!resource) { if (opts != null && opts.verbose) console.log("[CACHE] " + key + " not found, creating new"); resource = constructor(); universe_cache.set(key, resource); } else { if (opts != null && opts.verbose) console.log("[CACHE] " + key + " found, returning"); } return resource; } var cache = { getResource: getResource, useResource: function useResource(key, constructor, opts) { var _useState = React$1.useState(getResource(key, constructor, opts)), resource = _useState[0], setResource = _useState[1]; React$1.useEffect(function () { setResource(getResource(key, constructor, opts)); }, [key]); return resource; }, get mat_standard_white() { return getResource("mat_standard_white", function () { return new three.MeshStandardMaterial({ color: "white" }); }); }, get mat_standard_cream_double() { return getResource("mat_standard_cream_double", function () { return new three.MeshStandardMaterial({ color: "#aaa", side: three.DoubleSide }); }); }, get mat_standard_black() { return getResource("mat_standard_black", function () { return new three.MeshStandardMaterial({ color: "black" }); }); }, get mat_standard_rose() { return getResource("mat_standard_rose", function () { return new three.MeshStandardMaterial({ color: "#ff007f" }); }); }, get mat_standard_red() { return getResource("mat_standard_red", function () { return new three.MeshStandardMaterial({ color: "#ff0000" }); }); }, get mat_basic_white() { return getResource("mat_basic_white", function () { return new three.MeshBasicMaterial({ color: "white" }); }); }, get mat_basic_black() { return getResource("mat_basic_black", function () { return new three.MeshBasicMaterial({ color: "black" }); }); }, get mat_basic_gray() { return getResource("mat_basic_gray", function () { return new three.MeshBasicMaterial({ color: "#828282" }); }); }, get mat_basic_red() { return getResource("mat_basic_red", function () { return new three.MeshBasicMaterial({ color: "red" }); }); }, get mat_basic_black_wireframe() { return getResource("mat_basic_black_wireframe", function () { return new three.MeshBasicMaterial({ color: "black", wireframe: true }); }); } }; var useTrimeshCollision$1 = function useTrimeshCollision(geometry) { var indices = geometry.index.array; var isInterleaved = // @ts-ignore geometry.attributes.position.isInterleavedBufferAttribute; var vertices = []; if (isInterleaved) { var attr = geometry.attributes.position; var data = attr.data; for (var i = attr.offset; i < data.array.length; i += data.stride) { for (var x = 0; x < attr.itemSize; x++) { vertices.push(data.array[i + x]); } } } else { vertices = geometry.attributes.position.array; } var _useTrimesh = cannon.useTrimesh(function () { return { type: "Static", args: [vertices, indices] }; }), hitbox = _useTrimesh[0]; return hitbox; }; // check whether the user is currently typing var isTyping = function isTyping() { var _document, _document$activeEleme, _document2; return ((_document = document) == null ? void 0 : (_document$activeEleme = _document.activeElement) == null ? void 0 : _document$activeEleme.tagName) === "INPUT" && ((_document2 = document) == null ? void 0 : _document2.hasFocus()); }; var useDrag = function useDrag(callback, domElem, deps) { if (deps === void 0) { deps = []; } var _useThree = fiber.useThree(), clock = _useThree.clock, size = _useThree.size, viewport = _useThree.viewport; var aspect = size.width / viewport.width; var _useState = React$1.useState(new three.Vector2()), downPoint = _useState[0]; var _useState2 = React$1.useState(new three.Vector2()), dragPoint = _useState2[0]; var _useState3 = React$1.useState(new three.Vector2()), velocity = _useState3[0]; var _useState4 = React$1.useState(new three.Vector2()), delta = _useState4[0]; var lastTouchRead = React$1.useRef(0); var onStart = React$1.useCallback(function (p) { if (callback.onStart) callback.onStart(p); }, [].concat(deps)); var onMove = React$1.useCallback(function (p) { if (callback.onMove) callback.onMove(p); }, [].concat(deps)); var onEnd = React$1.useCallback(function (p) { if (callback.onEnd) callback.onEnd(p); }, [].concat(deps)); var startDrag = React$1.useCallback(function (e) { e.preventDefault(); var touch = e.changedTouches[0]; downPoint.set(touch.clientX, touch.clientY); onStart({ e: e, touch: touch, downPoint: downPoint, dragPoint: downPoint, velocity: velocity }); }, [onStart, downPoint, velocity]); var moveDrag = React$1.useCallback(function (e) { var touch = e.touches[0]; dragPoint.set(touch.clientX, touch.clientY); var delta = dragPoint.sub(downPoint); var time = clock.elapsedTime; var elapsed = time - lastTouchRead.current; velocity.set(delta.x / elapsed / aspect, delta.y / elapsed / aspect); lastTouchRead.current = time; onMove({ e: e, touch: touch, downPoint: downPoint, dragPoint: dragPoint, velocity: velocity, delta: delta }); }, [aspect, onMove, clock, downPoint, dragPoint, velocity]); var endDrag = React$1.useCallback(function (e) { var touch = e.changedTouches[0]; dragPoint.set(touch.clientX, touch.clientY); delta.copy(dragPoint).sub(downPoint); onEnd({ e: e, touch: touch, downPoint: downPoint, dragPoint: dragPoint, velocity: velocity, delta: delta }); }, [onEnd, delta, downPoint, dragPoint, velocity]); React$1.useEffect(function () { var elem = domElem || document; elem.addEventListener("touchstart", startDrag); elem.addEventListener("touchmove", moveDrag); elem.addEventListener("touchend", endDrag); return function () { elem.removeEventListener("touchstart", startDrag); elem.removeEventListener("touchmove", moveDrag); elem.removeEventListener("touchend", endDrag); }; }, [domElem, endDrag, moveDrag, startDrag]); return { startDrag: startDrag, moveDrag: moveDrag, endDrag: endDrag }; }; var PADDING_X = 0.125; var PADDING_X_2 = PADDING_X * 2; var PADDING_Y = 0.125; var PADDING_Y_2 = PADDING_Y * 2; var RAD_PER_DEG_2 = Math.PI / 180 / 2; var getHudPos = function getHudPos(pos, camera, distance, target) { var vFOV = camera.fov * RAD_PER_DEG_2; var height = 2 * Math.tan(vFOV) * Math.abs(distance); var width = height * camera.aspect; var px = pos.x || pos[0]; var py = pos.y || pos[1]; var x = px * (width - PADDING_X_2) * 0.5; var y = py * (height - PADDING_Y_2) * 0.5; if (target) { target.x = x; target.y = y; return target; } return new three.Vector2(x, y); }; var getHudDims = function getHudDims(camera, distance) { var vFOV = camera.fov * RAD_PER_DEG_2; var height = 2 * Math.tan(vFOV) * Math.abs(distance); var width = height * camera.aspect; return { width: width, height: height }; }; var useHudDims = function useHudDims(distance) { if (distance === void 0) { distance = 1; } var camera = fiber.useThree(function (state) { return state.camera; }); return React$1.useMemo(function () { return getHudDims(camera, distance); // make sure aspect is there }, [camera, distance, camera.aspect]); }; var _templateObject$6; var Container$2 = styled__default["default"].div(_templateObject$6 || (_templateObject$6 = _taggedTemplateLiteralLoose__default["default"](["\n position: absolute;\n width: 100%;\n height: 100%;\n overflow: hidden;\n\n canvas {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n outline: 0;\n }\n"]))); var _templateObject$5; var globalStyles = react.css(_templateObject$5 || (_templateObject$5 = _taggedTemplateLiteralLoose__default["default"](["\n @font-face {\n font-family: \"Quicksand\";\n src: url(\"https://cdn.websessions.co/select/fonts/FTBasicSpace-Regular.woff2\");\n }\n\n html {\n position: fixed;\n height: 100%;\n overflow: hidden;\n }\n\n body {\n margin: 0;\n width: 100vw;\n height: 100vh;\n user-select: none;\n overflow: hidden;\n touch-action: none;\n -webkit-overflow-scrolling: touch;\n font-family: \"Quicksand\", sans-serif;\n font-size: 18px;\n @media screen and (max-width: 500px) {\n font-size: 16px;\n }\n }\n"]))); function GlobalStyles() { React$1.useEffect(function () { var view = document.createElement("meta"); view.name = "viewport"; view.content = "initial-scale=1, viewport-fit=cover"; document.head.append(view); return function () { document.head.removeChild(view); }; }, []); return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(react.Global, { styles: globalStyles })); } /** * A modified version of the controlled progress hooks that adds * - a minimum wait time, in case it takes a second to register an as