41 |
42 | ## Usage (Scripts)
43 |
44 | In the [dist/](https://github.com/c-frame/aframe-extras/tree/master/dist) folder, download any package(s) you need. Include the scripts on your page, and all components are automatically registered for you:
45 |
46 | ```html
47 |
48 | ```
49 |
50 | replace `7.5.4` by another tag or a commit hash (for example `3e0ab50`) if you want to use a build from master branch.
51 | You can [look at the commits](https://github.com/c-frame/aframe-extras/commits/master) and use the latest commit hash.
52 |
53 | For partial builds, use a subpackage like `aframe-extras.controls.min.js`. Full list of packages above.
54 |
55 | **A-Frame Version Compatibility**
56 |
57 | | A-Frame | Extras |
58 | |----------|--------|
59 | | v1.4.0 | v7.0.0 |
60 | | v1.3.0 | v7.0.0 |
61 | | v1.2.0 | v7.0.0 |
62 | | v1.1.0 | v6.1.1 |
63 |
64 | > **NOTE:** Several components and examples also rely on [aframe-physics-system](https://github.com/c-frame/aframe-physics-system).
65 |
66 | ## Usage (NPM)
67 |
68 | ```
69 | npm install --save aframe-extras
70 | ```
71 |
72 | ```javascript
73 | // index.js
74 | import 'aframe-extras';
75 | // or specific packages
76 | import "aframe-extras/controls/index.js";
77 | import "aframe-extras/pathfinding/index.js";
78 | ```
79 |
80 | Once installed, you'll need to compile your JavaScript using something like [webpack](https://webpack.js.org) with three defined as external, see webpack.config.js in this repo for an example.
81 |
82 | ## Examples
83 |
84 | A live set of usage examples can be found here:
85 |
86 | https://c-frame.github.io/aframe-extras/examples/
87 |
88 | ## Deprecated Components
89 |
90 | The following components existed in previous versions of A-Frame Extras, but have been removed as of the latest release
91 |
92 | | Component | Removed in | Reasons |
93 | | ---------------- | ---------- | ------------------------------------------------------------ |
94 | | `kinematic-body` | 7.0.0 | Using physics for movement is unstable and performs poorly. When preventing players from passing through obstacles, use a navigation mesh instead whenever possible.
The `kinematic-body` component constrainted player movement using physics, and depended on [aframe-physics-system](http://github.com/c-frame/aframe-physics-system). Using physics for locomotion is not VR-friendly, and often glitchy even for traditional 3D experiences. [Use a navigation mesh](https://github.com/c-frame/aframe-extras/tree/master/src/controls#usage) instead, whenever possible. |
95 | | `jump-ability` | 7.0.0 | Dependent on `kinematic-body` |
96 | | `a-hexgrid` | 7.0.0 | Was based on [this repo](https://github.com/vonWolfehaus/von-grid), which is no longer maintained, and does not work with recent versions of THREE.js. |
97 | | `mesh-smooth` | 7.0.0 | Intended for JSON models, but the JSON Loader is [no longer part of this repo](https://github.com/c-frame/aframe-extras/commit/d079064e6ac55a4cd6bbf64bd46a576e26dd214e). More background [here](https://github.com/c-frame/aframe-extras/issues/411). |
98 |
99 |
--------------------------------------------------------------------------------
/dist/aframe-extras.misc.min.js:
--------------------------------------------------------------------------------
1 | !function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var i=e();for(var s in i)("object"==typeof exports?exports:t)[s]=i[s]}}(self,(()=>(()=>{var t={95:t=>{t.exports=AFRAME.registerComponent("checkpoint",{schema:{offset:{default:{x:0,y:0,z:0},type:"vec3"}},init:function(){this.active=!1,this.targetEl=null,this.fire=this.fire.bind(this),this.offset=new THREE.Vector3},update:function(){this.offset.copy(this.data.offset)},play:function(){this.el.addEventListener("click",this.fire)},pause:function(){this.el.removeEventListener("click",this.fire)},remove:function(){this.pause()},fire:function(){const t=this.el.sceneEl.querySelector("[checkpoint-controls]");if(!t)throw new Error("No `checkpoint-controls` component found.");t.components["checkpoint-controls"].setCheckpoint(this.el)},getOffset:function(){return this.offset.copy(this.data.offset)}})},889:t=>{function e(t,e,i,s){t&&(e=e||[],t.traverse((t=>{var n;t.isMesh&&((n=t.material)?Array.isArray(n)?n:n.materials?n.materials:[n]:[]).forEach((t=>{t&&!("envMap"in t)||e.length&&-1===e.indexOf(t.name)||(t.envMap=i,t.reflectivity=s,t.needsUpdate=!0)}))})))}t.exports=AFRAME.registerComponent("cube-env-map",{multiple:!0,schema:{path:{default:""},extension:{default:"jpg",oneOf:["jpg","png"]},enableBackground:{default:!1},reflectivity:{default:1,min:0,max:1},materials:{default:[]}},init:function(){const t=this.data;this.texture=(new THREE.CubeTextureLoader).load([t.path+"posx."+t.extension,t.path+"negx."+t.extension,t.path+"posy."+t.extension,t.path+"negy."+t.extension,t.path+"posz."+t.extension,t.path+"negz."+t.extension]),this.texture.format=THREE.RGBAFormat,this.object3dsetHandler=()=>{const t=this.el.getObject3D("mesh"),i=this.data;e(t,i.materials,this.texture,i.reflectivity)},this.object3dsetHandler(),this.el.addEventListener("object3dset",this.object3dsetHandler)},update:function(t){const i=this.data,s=this.el.getObject3D("mesh");let n=[],r=[];if(i.materials.length&&(t.materials?(n=i.materials.filter((e=>!t.materials.includes(e))),r=t.materials.filter((t=>!i.materials.includes(t)))):n=i.materials),n.length&&e(s,n,this.texture,i.reflectivity),r.length&&e(s,r,null,1),t.materials&&i.reflectivity!==t.reflectivity){const n=i.materials.filter((e=>t.materials.includes(e)));n.length&&e(s,n,this.texture,i.reflectivity)}this.data.enableBackground&&!t.enableBackground?this.setBackground(this.texture):!this.data.enableBackground&&t.enableBackground&&this.setBackground(null)},remove:function(){this.el.removeEventListener("object3dset",this.object3dsetHandler);const t=this.el.getObject3D("mesh"),i=this.data;e(t,i.materials,null,1),i.enableBackground&&this.setBackground(null)},setBackground:function(t){this.el.sceneEl.object3D.background=t}})},771:t=>{t.exports=AFRAME.registerComponent("grab",{init:function(){this.system=this.el.sceneEl.systems.physics,this.GRABBED_STATE="grabbed",this.grabbing=!1,this.hitEl=null,this.physics=this.el.sceneEl.systems.physics,this.constraint=null,this.onHit=this.onHit.bind(this),this.onGripOpen=this.onGripOpen.bind(this),this.onGripClose=this.onGripClose.bind(this)},play:function(){const t=this.el;t.addEventListener("hit",this.onHit),t.addEventListener("gripdown",this.onGripClose),t.addEventListener("gripup",this.onGripOpen),t.addEventListener("trackpaddown",this.onGripClose),t.addEventListener("trackpadup",this.onGripOpen),t.addEventListener("triggerdown",this.onGripClose),t.addEventListener("triggerup",this.onGripOpen)},pause:function(){const t=this.el;t.removeEventListener("hit",this.onHit),t.removeEventListener("gripdown",this.onGripClose),t.removeEventListener("gripup",this.onGripOpen),t.removeEventListener("trackpaddown",this.onGripClose),t.removeEventListener("trackpadup",this.onGripOpen),t.removeEventListener("triggerdown",this.onGripClose),t.removeEventListener("triggerup",this.onGripOpen)},onGripClose:function(){this.grabbing=!0},onGripOpen:function(){const t=this.hitEl;this.grabbing=!1,t&&(t.removeState(this.GRABBED_STATE),this.hitEl=void 0,this.system.removeConstraint(this.constraint),this.constraint=null)},onHit:function(t){const e=t.detail.el;e.is(this.GRABBED_STATE)||!this.grabbing||this.hitEl||(e.addState(this.GRABBED_STATE),this.hitEl=e,this.constraint=new CANNON.LockConstraint(this.el.body,e.body),this.system.addConstraint(this.constraint))}})},778:t=>{t.exports=AFRAME.registerComponent("normal-material",{init:function(){this.material=new THREE.MeshNormalMaterial({flatShading:!0}),this.applyMaterial=this.applyMaterial.bind(this),this.el.addEventListener("object3dset",this.applyMaterial),this.applyMaterial()},remove:function(){this.el.removeEventListener("object3dset",this.applyMaterial)},applyMaterial:function(){this.el.object3D.traverse((t=>{t.isMesh&&(t.material=this.material)}))}})},109:t=>{t.exports=AFRAME.registerComponent("sphere-collider",{schema:{enabled:{default:!0},interval:{default:80},objects:{default:""},state:{default:"collided"},radius:{default:.05},watch:{default:!0}},init:function(){this.observer=null,this.els=[],this.collisions=[],this.prevCheckTime=void 0,this.eventDetail={},this.handleHit=this.handleHit.bind(this),this.handleHitEnd=this.handleHitEnd.bind(this)},play:function(){const t=this.el.sceneEl;this.data.watch&&(this.observer=new MutationObserver(this.update.bind(this,null)),this.observer.observe(t,{childList:!0,subtree:!0}))},pause:function(){this.observer&&(this.observer.disconnect(),this.observer=null)},update:function(){const t=this.data;let e;e=t.objects?this.el.sceneEl.querySelectorAll(t.objects):this.el.sceneEl.children,this.els=Array.prototype.slice.call(e)},tick:function(){const t=new THREE.Vector3,e=new THREE.Vector3,i=new THREE.Vector3,s=new THREE.Vector3,n=new THREE.Box3,r=[],o=new Map;return function(a){if(!this.data.enabled)return;const h=this.prevCheckTime;if(h&&a-ho.get(t)>o.get(e)?1:-1)).forEach(this.handleHit),this.collisions.filter((t=>!o.has(t))).forEach(this.handleHitEnd),function(t,e){t.length=0;for(let i=0;i {
11 | return /******/ (() => { // webpackBootstrap
12 | /******/ var __webpack_modules__ = ({
13 |
14 | /***/ "./src/primitives/a-grid.js":
15 | /*!**********************************!*\
16 | !*** ./src/primitives/a-grid.js ***!
17 | \**********************************/
18 | /***/ ((module) => {
19 |
20 | /**
21 | * Flat grid.
22 | *
23 | * Defaults to 75x75.
24 | */
25 | module.exports = AFRAME.registerPrimitive('a-grid', {
26 | defaultComponents: {
27 | geometry: {
28 | primitive: 'plane',
29 | width: 75,
30 | height: 75
31 | },
32 | rotation: {x: -90, y: 0, z: 0},
33 | material: {
34 | src: 'url(https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras@v1.16.3/assets/grid.png)',
35 | repeat: '75 75'
36 | }
37 | },
38 | mappings: {
39 | width: 'geometry.width',
40 | height: 'geometry.height',
41 | src: 'material.src'
42 | }
43 | });
44 |
45 |
46 | /***/ }),
47 |
48 | /***/ "./src/primitives/a-ocean.js":
49 | /*!***********************************!*\
50 | !*** ./src/primitives/a-ocean.js ***!
51 | \***********************************/
52 | /***/ ((module) => {
53 |
54 | /**
55 | * Flat-shaded ocean primitive.
56 | *
57 | * Based on a Codrops tutorial:
58 | * http://tympanus.net/codrops/2016/04/26/the-aviator-animating-basic-3d-scene-threejs/
59 | */
60 | module.exports.Primitive = AFRAME.registerPrimitive('a-ocean', {
61 | defaultComponents: {
62 | ocean: {},
63 | rotation: {x: -90, y: 0, z: 0}
64 | },
65 | mappings: {
66 | width: 'ocean.width',
67 | depth: 'ocean.depth',
68 | density: 'ocean.density',
69 | amplitude: 'ocean.amplitude',
70 | amplitudeVariance: 'ocean.amplitudeVariance',
71 | speed: 'ocean.speed',
72 | speedVariance: 'ocean.speedVariance',
73 | color: 'ocean.color',
74 | opacity: 'ocean.opacity'
75 | }
76 | });
77 |
78 | module.exports.Component = AFRAME.registerComponent('ocean', {
79 | schema: {
80 | // Dimensions of the ocean area.
81 | width: {default: 10, min: 0},
82 | depth: {default: 10, min: 0},
83 |
84 | // Density of waves.
85 | density: {default: 10},
86 |
87 | // Wave amplitude and variance.
88 | amplitude: {default: 0.1},
89 | amplitudeVariance: {default: 0.3},
90 |
91 | // Wave speed and variance.
92 | speed: {default: 1},
93 | speedVariance: {default: 2},
94 |
95 | // Material.
96 | color: {default: '#7AD2F7', type: 'color'},
97 | opacity: {default: 0.8}
98 | },
99 |
100 | /**
101 | * Use play() instead of init(), because component mappings – unavailable as dependencies – are
102 | * not guaranteed to have parsed when this component is initialized.
103 | */
104 | play: function () {
105 | const el = this.el;
106 | const data = this.data;
107 | let material = el.components.material;
108 |
109 | const geometry = new THREE.PlaneGeometry(data.width, data.depth, data.density, data.density);
110 | this.waves = [];
111 | const posAttribute = geometry.getAttribute('position');
112 | for (let i = 0; i < posAttribute.count; i++) {
113 | this.waves.push({
114 | z: posAttribute.getZ(i),
115 | ang: Math.random() * Math.PI * 2,
116 | amp: data.amplitude + Math.random() * data.amplitudeVariance,
117 | speed: (data.speed + Math.random() * data.speedVariance) / 1000 // radians / frame
118 | });
119 | }
120 |
121 | if (!material) {
122 | material = {};
123 | material.material = new THREE.MeshPhongMaterial({
124 | color: data.color,
125 | transparent: data.opacity < 1,
126 | opacity: data.opacity,
127 | flatShading: true,
128 | });
129 | }
130 |
131 | this.mesh = new THREE.Mesh(geometry, material.material);
132 | el.setObject3D('mesh', this.mesh);
133 | },
134 |
135 | remove: function () {
136 | this.el.removeObject3D('mesh');
137 | },
138 |
139 | tick: function (t, dt) {
140 | if (!dt) return;
141 |
142 | const posAttribute = this.mesh.geometry.getAttribute('position');
143 | for (let i = 0; i < posAttribute.count; i++){
144 | const vprops = this.waves[i];
145 | const value = vprops.z + Math.sin(vprops.ang) * vprops.amp;
146 | posAttribute.setZ(i, value);
147 | vprops.ang += vprops.speed * dt;
148 | }
149 | posAttribute.needsUpdate = true;
150 | }
151 | });
152 |
153 |
154 | /***/ }),
155 |
156 | /***/ "./src/primitives/a-tube.js":
157 | /*!**********************************!*\
158 | !*** ./src/primitives/a-tube.js ***!
159 | \**********************************/
160 | /***/ ((module) => {
161 |
162 | /**
163 | * Tube following a custom path.
164 | *
165 | * Usage:
166 | *
167 | * ```html
168 | *
169 | * ```
170 | */
171 | module.exports.Primitive = AFRAME.registerPrimitive('a-tube', {
172 | defaultComponents: {
173 | tube: {},
174 | },
175 | mappings: {
176 | path: 'tube.path',
177 | segments: 'tube.segments',
178 | radius: 'tube.radius',
179 | 'radial-segments': 'tube.radialSegments',
180 | closed: 'tube.closed'
181 | }
182 | });
183 |
184 | module.exports.Component = AFRAME.registerComponent('tube', {
185 | schema: {
186 | path: {default: []},
187 | segments: {default: 64},
188 | radius: {default: 1},
189 | radialSegments: {default: 8},
190 | closed: {default: false}
191 | },
192 |
193 | init: function () {
194 | const el = this.el,
195 | data = this.data;
196 | let material = el.components.material;
197 |
198 | if (!data.path.length) {
199 | console.error('[a-tube] `path` property expected but not found.');
200 | return;
201 | }
202 |
203 | const curve = new THREE.CatmullRomCurve3(data.path.map(function (point) {
204 | point = point.split(' ');
205 | return new THREE.Vector3(Number(point[0]), Number(point[1]), Number(point[2]));
206 | }));
207 | const geometry = new THREE.TubeGeometry(
208 | curve, data.segments, data.radius, data.radialSegments, data.closed
209 | );
210 |
211 | if (!material) {
212 | material = {};
213 | material.material = new THREE.MeshPhongMaterial();
214 | }
215 |
216 | this.mesh = new THREE.Mesh(geometry, material.material);
217 | this.el.setObject3D('mesh', this.mesh);
218 | },
219 |
220 | update: function (prevData) {
221 | if (!Object.keys(prevData).length) return;
222 |
223 | this.remove();
224 | this.init();
225 | },
226 |
227 | remove: function () {
228 | if (this.mesh) this.el.removeObject3D('mesh');
229 | }
230 | });
231 |
232 |
233 | /***/ })
234 |
235 | /******/ });
236 | /************************************************************************/
237 | /******/ // The module cache
238 | /******/ var __webpack_module_cache__ = {};
239 | /******/
240 | /******/ // The require function
241 | /******/ function __webpack_require__(moduleId) {
242 | /******/ // Check if module is in cache
243 | /******/ var cachedModule = __webpack_module_cache__[moduleId];
244 | /******/ if (cachedModule !== undefined) {
245 | /******/ return cachedModule.exports;
246 | /******/ }
247 | /******/ // Create a new module (and put it into the cache)
248 | /******/ var module = __webpack_module_cache__[moduleId] = {
249 | /******/ // no module.id needed
250 | /******/ // no module.loaded needed
251 | /******/ exports: {}
252 | /******/ };
253 | /******/
254 | /******/ // Execute the module function
255 | /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
256 | /******/
257 | /******/ // Return the exports of the module
258 | /******/ return module.exports;
259 | /******/ }
260 | /******/
261 | /************************************************************************/
262 | var __webpack_exports__ = {};
263 | // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
264 | (() => {
265 | /*!*********************************!*\
266 | !*** ./src/primitives/index.js ***!
267 | \*********************************/
268 | __webpack_require__(/*! ./a-grid */ "./src/primitives/a-grid.js");
269 | __webpack_require__(/*! ./a-ocean */ "./src/primitives/a-ocean.js");
270 | __webpack_require__(/*! ./a-tube */ "./src/primitives/a-tube.js");
271 |
272 | })();
273 |
274 | /******/ return __webpack_exports__;
275 | /******/ })()
276 | ;
277 | });
278 | //# sourceMappingURL=aframe-extras.primitives.js.map
--------------------------------------------------------------------------------
/dist/aframe-extras.primitives.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"aframe-extras.primitives.js","mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD,O;;;;;;;;;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,eAAe,mBAAmB;AAClC;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,CAAC;;;;;;;;;;;ACvBD;AACA;AACA;AACA;AACA;AACA;AACA,wBAAwB;AACxB;AACA,aAAa;AACb,eAAe;AACf,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED,wBAAwB;AACxB;AACA;AACA,YAAY,oBAAoB;AAChC,YAAY,oBAAoB;;AAEhC;AACA,cAAc,YAAY;;AAE1B;AACA,gBAAgB,aAAa;AAC7B,wBAAwB,aAAa;;AAErC;AACA,YAAY,WAAW;AACvB,oBAAoB,WAAW;;AAE/B;AACA,YAAY,kCAAkC;AAC9C,cAAc;AACd,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,oBAAoB,wBAAwB;AAC5C;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;;AAEA;AACA;AACA,GAAG;;AAEH;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA,oBAAoB,wBAAwB;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;;;;;;;;;;ACjGD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAwB;AACxB;AACA,sBAAsB;AACtB,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED,wBAAwB;AACxB;AACA,qBAAqB,YAAY;AACjC,qBAAqB,YAAY;AACjC,qBAAqB,WAAW;AAChC,qBAAqB,WAAW;AAChC,qBAAqB;AACrB,GAAG;;AAEH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA,CAAC;;;;;;;UCpED;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;;;;;;;;ACtBA,mBAAO,CAAC,4CAAU;AAClB,mBAAO,CAAC,8CAAW;AACnB,mBAAO,CAAC,4CAAU","sources":["webpack://aframe-extras/webpack/universalModuleDefinition","webpack://aframe-extras/./src/primitives/a-grid.js","webpack://aframe-extras/./src/primitives/a-ocean.js","webpack://aframe-extras/./src/primitives/a-tube.js","webpack://aframe-extras/webpack/bootstrap","webpack://aframe-extras/./src/primitives/index.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse {\n\t\tvar a = factory();\n\t\tfor(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n\t}\n})(self, () => {\nreturn ","/**\n * Flat grid.\n *\n * Defaults to 75x75.\n */\nmodule.exports = AFRAME.registerPrimitive('a-grid', {\n defaultComponents: {\n geometry: {\n primitive: 'plane',\n width: 75,\n height: 75\n },\n rotation: {x: -90, y: 0, z: 0},\n material: {\n src: 'url(https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras@v1.16.3/assets/grid.png)',\n repeat: '75 75'\n }\n },\n mappings: {\n width: 'geometry.width',\n height: 'geometry.height',\n src: 'material.src'\n }\n});\n","/**\n * Flat-shaded ocean primitive.\n *\n * Based on a Codrops tutorial:\n * http://tympanus.net/codrops/2016/04/26/the-aviator-animating-basic-3d-scene-threejs/\n */\nmodule.exports.Primitive = AFRAME.registerPrimitive('a-ocean', {\n defaultComponents: {\n ocean: {},\n rotation: {x: -90, y: 0, z: 0}\n },\n mappings: {\n width: 'ocean.width',\n depth: 'ocean.depth',\n density: 'ocean.density',\n amplitude: 'ocean.amplitude',\n amplitudeVariance: 'ocean.amplitudeVariance',\n speed: 'ocean.speed',\n speedVariance: 'ocean.speedVariance',\n color: 'ocean.color',\n opacity: 'ocean.opacity'\n }\n});\n\nmodule.exports.Component = AFRAME.registerComponent('ocean', {\n schema: {\n // Dimensions of the ocean area.\n width: {default: 10, min: 0},\n depth: {default: 10, min: 0},\n\n // Density of waves.\n density: {default: 10},\n\n // Wave amplitude and variance.\n amplitude: {default: 0.1},\n amplitudeVariance: {default: 0.3},\n\n // Wave speed and variance.\n speed: {default: 1},\n speedVariance: {default: 2},\n\n // Material.\n color: {default: '#7AD2F7', type: 'color'},\n opacity: {default: 0.8}\n },\n\n /**\n * Use play() instead of init(), because component mappings – unavailable as dependencies – are\n * not guaranteed to have parsed when this component is initialized.\n */\n play: function () {\n const el = this.el;\n const data = this.data;\n let material = el.components.material;\n\n const geometry = new THREE.PlaneGeometry(data.width, data.depth, data.density, data.density);\n this.waves = [];\n const posAttribute = geometry.getAttribute('position');\n for (let i = 0; i < posAttribute.count; i++) {\n this.waves.push({\n z: posAttribute.getZ(i),\n ang: Math.random() * Math.PI * 2,\n amp: data.amplitude + Math.random() * data.amplitudeVariance,\n speed: (data.speed + Math.random() * data.speedVariance) / 1000 // radians / frame\n });\n }\n\n if (!material) {\n material = {};\n material.material = new THREE.MeshPhongMaterial({\n color: data.color,\n transparent: data.opacity < 1,\n opacity: data.opacity,\n flatShading: true,\n });\n }\n\n this.mesh = new THREE.Mesh(geometry, material.material);\n el.setObject3D('mesh', this.mesh);\n },\n\n remove: function () {\n this.el.removeObject3D('mesh');\n },\n\n tick: function (t, dt) {\n if (!dt) return;\n\n const posAttribute = this.mesh.geometry.getAttribute('position');\n for (let i = 0; i < posAttribute.count; i++){\n const vprops = this.waves[i];\n const value = vprops.z + Math.sin(vprops.ang) * vprops.amp;\n posAttribute.setZ(i, value);\n vprops.ang += vprops.speed * dt;\n }\n posAttribute.needsUpdate = true;\n }\n});\n","/**\n * Tube following a custom path.\n *\n * Usage:\n *\n * ```html\n * \n * ```\n */\nmodule.exports.Primitive = AFRAME.registerPrimitive('a-tube', {\n defaultComponents: {\n tube: {},\n },\n mappings: {\n path: 'tube.path',\n segments: 'tube.segments',\n radius: 'tube.radius',\n 'radial-segments': 'tube.radialSegments',\n closed: 'tube.closed'\n }\n});\n\nmodule.exports.Component = AFRAME.registerComponent('tube', {\n schema: {\n path: {default: []},\n segments: {default: 64},\n radius: {default: 1},\n radialSegments: {default: 8},\n closed: {default: false}\n },\n\n init: function () {\n const el = this.el,\n data = this.data;\n let material = el.components.material;\n\n if (!data.path.length) {\n console.error('[a-tube] `path` property expected but not found.');\n return;\n }\n\n const curve = new THREE.CatmullRomCurve3(data.path.map(function (point) {\n point = point.split(' ');\n return new THREE.Vector3(Number(point[0]), Number(point[1]), Number(point[2]));\n }));\n const geometry = new THREE.TubeGeometry(\n curve, data.segments, data.radius, data.radialSegments, data.closed\n );\n\n if (!material) {\n material = {};\n material.material = new THREE.MeshPhongMaterial();\n }\n\n this.mesh = new THREE.Mesh(geometry, material.material);\n this.el.setObject3D('mesh', this.mesh);\n },\n\n update: function (prevData) {\n if (!Object.keys(prevData).length) return;\n\n this.remove();\n this.init();\n },\n\n remove: function () {\n if (this.mesh) this.el.removeObject3D('mesh');\n }\n});\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","require('./a-grid');\nrequire('./a-ocean');\nrequire('./a-tube');\n"],"names":[],"sourceRoot":""}
--------------------------------------------------------------------------------
/dist/aframe-extras.primitives.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var a=t();for(var i in a)("object"==typeof exports?exports:e)[i]=a[i]}}(self,(()=>(()=>{var e={785:e=>{e.exports=AFRAME.registerPrimitive("a-grid",{defaultComponents:{geometry:{primitive:"plane",width:75,height:75},rotation:{x:-90,y:0,z:0},material:{src:"url(https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras@v1.16.3/assets/grid.png)",repeat:"75 75"}},mappings:{width:"geometry.width",height:"geometry.height",src:"material.src"}})},683:e=>{e.exports.Primitive=AFRAME.registerPrimitive("a-ocean",{defaultComponents:{ocean:{},rotation:{x:-90,y:0,z:0}},mappings:{width:"ocean.width",depth:"ocean.depth",density:"ocean.density",amplitude:"ocean.amplitude",amplitudeVariance:"ocean.amplitudeVariance",speed:"ocean.speed",speedVariance:"ocean.speedVariance",color:"ocean.color",opacity:"ocean.opacity"}}),e.exports.Component=AFRAME.registerComponent("ocean",{schema:{width:{default:10,min:0},depth:{default:10,min:0},density:{default:10},amplitude:{default:.1},amplitudeVariance:{default:.3},speed:{default:1},speedVariance:{default:2},color:{default:"#7AD2F7",type:"color"},opacity:{default:.8}},play:function(){const e=this.el,t=this.data;let a=e.components.material;const i=new THREE.PlaneGeometry(t.width,t.depth,t.density,t.density);this.waves=[];const n=i.getAttribute("position");for(let e=0;e{e.exports.Primitive=AFRAME.registerPrimitive("a-tube",{defaultComponents:{tube:{}},mappings:{path:"tube.path",segments:"tube.segments",radius:"tube.radius","radial-segments":"tube.radialSegments",closed:"tube.closed"}}),e.exports.Component=AFRAME.registerComponent("tube",{schema:{path:{default:[]},segments:{default:64},radius:{default:1},radialSegments:{default:8},closed:{default:!1}},init:function(){const e=this.el,t=this.data;let a=e.components.material;if(!t.path.length)return void console.error("[a-tube] `path` property expected but not found.");const i=new THREE.CatmullRomCurve3(t.path.map((function(e){return e=e.split(" "),new THREE.Vector3(Number(e[0]),Number(e[1]),Number(e[2]))}))),n=new THREE.TubeGeometry(i,t.segments,t.radius,t.radialSegments,t.closed);a||(a={},a.material=new THREE.MeshPhongMaterial),this.mesh=new THREE.Mesh(n,a.material),this.el.setObject3D("mesh",this.mesh)},update:function(e){Object.keys(e).length&&(this.remove(),this.init())},remove:function(){this.mesh&&this.el.removeObject3D("mesh")}})}},t={};function a(i){var n=t[i];if(void 0!==n)return n.exports;var o=t[i]={exports:{}};return e[i](o,o.exports,a),o.exports}return a(785),a(683),a(539),{}})()));
2 | //# sourceMappingURL=aframe-extras.primitives.min.js.map
--------------------------------------------------------------------------------
/dist/components/grab.js:
--------------------------------------------------------------------------------
1 | (function webpackUniversalModuleDefinition(root, factory) {
2 | if(typeof exports === 'object' && typeof module === 'object')
3 | module.exports = factory();
4 | else if(typeof define === 'function' && define.amd)
5 | define([], factory);
6 | else {
7 | var a = factory();
8 | for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
9 | }
10 | })(self, () => {
11 | return /******/ (() => { // webpackBootstrap
12 | /******/ var __webpack_modules__ = ({
13 |
14 | /***/ "./src/misc/grab.js":
15 | /*!**************************!*\
16 | !*** ./src/misc/grab.js ***!
17 | \**************************/
18 | /***/ ((module) => {
19 |
20 | /* global CANNON */
21 |
22 | /**
23 | * Based on aframe/examples/showcase/tracked-controls.
24 | *
25 | * Handles events coming from the hand-controls.
26 | * Determines if the entity is grabbed or released.
27 | * Updates its position to move along the controller.
28 | */
29 | module.exports = AFRAME.registerComponent('grab', {
30 | init: function () {
31 | this.system = this.el.sceneEl.systems.physics;
32 |
33 | this.GRABBED_STATE = 'grabbed';
34 |
35 | this.grabbing = false;
36 | this.hitEl = /** @type {AFRAME.Element} */ null;
37 | this.physics = /** @type {AFRAME.System} */ this.el.sceneEl.systems.physics;
38 | this.constraint = /** @type {CANNON.Constraint} */ null;
39 |
40 | // Bind event handlers
41 | this.onHit = this.onHit.bind(this);
42 | this.onGripOpen = this.onGripOpen.bind(this);
43 | this.onGripClose = this.onGripClose.bind(this);
44 | },
45 |
46 | play: function () {
47 | const el = this.el;
48 | el.addEventListener('hit', this.onHit);
49 | el.addEventListener('gripdown', this.onGripClose);
50 | el.addEventListener('gripup', this.onGripOpen);
51 | el.addEventListener('trackpaddown', this.onGripClose);
52 | el.addEventListener('trackpadup', this.onGripOpen);
53 | el.addEventListener('triggerdown', this.onGripClose);
54 | el.addEventListener('triggerup', this.onGripOpen);
55 | },
56 |
57 | pause: function () {
58 | const el = this.el;
59 | el.removeEventListener('hit', this.onHit);
60 | el.removeEventListener('gripdown', this.onGripClose);
61 | el.removeEventListener('gripup', this.onGripOpen);
62 | el.removeEventListener('trackpaddown', this.onGripClose);
63 | el.removeEventListener('trackpadup', this.onGripOpen);
64 | el.removeEventListener('triggerdown', this.onGripClose);
65 | el.removeEventListener('triggerup', this.onGripOpen);
66 | },
67 |
68 | onGripClose: function () {
69 | this.grabbing = true;
70 | },
71 |
72 | onGripOpen: function () {
73 | const hitEl = this.hitEl;
74 | this.grabbing = false;
75 | if (!hitEl) { return; }
76 | hitEl.removeState(this.GRABBED_STATE);
77 | this.hitEl = undefined;
78 | this.system.removeConstraint(this.constraint);
79 | this.constraint = null;
80 | },
81 |
82 | onHit: function (evt) {
83 | const hitEl = evt.detail.el;
84 | // If the element is already grabbed (it could be grabbed by another controller).
85 | // If the hand is not grabbing the element does not stick.
86 | // If we're already grabbing something you can't grab again.
87 | if (hitEl.is(this.GRABBED_STATE) || !this.grabbing || this.hitEl) { return; }
88 | hitEl.addState(this.GRABBED_STATE);
89 | this.hitEl = hitEl;
90 | this.constraint = new CANNON.LockConstraint(this.el.body, hitEl.body);
91 | this.system.addConstraint(this.constraint);
92 | }
93 | });
94 |
95 |
96 | /***/ })
97 |
98 | /******/ });
99 | /************************************************************************/
100 | /******/ // The module cache
101 | /******/ var __webpack_module_cache__ = {};
102 | /******/
103 | /******/ // The require function
104 | /******/ function __webpack_require__(moduleId) {
105 | /******/ // Check if module is in cache
106 | /******/ var cachedModule = __webpack_module_cache__[moduleId];
107 | /******/ if (cachedModule !== undefined) {
108 | /******/ return cachedModule.exports;
109 | /******/ }
110 | /******/ // Create a new module (and put it into the cache)
111 | /******/ var module = __webpack_module_cache__[moduleId] = {
112 | /******/ // no module.id needed
113 | /******/ // no module.loaded needed
114 | /******/ exports: {}
115 | /******/ };
116 | /******/
117 | /******/ // Execute the module function
118 | /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
119 | /******/
120 | /******/ // Return the exports of the module
121 | /******/ return module.exports;
122 | /******/ }
123 | /******/
124 | /************************************************************************/
125 | /******/
126 | /******/ // startup
127 | /******/ // Load entry module and return exports
128 | /******/ // This entry module is referenced by other modules so it can't be inlined
129 | /******/ var __webpack_exports__ = __webpack_require__("./src/misc/grab.js");
130 | /******/
131 | /******/ return __webpack_exports__;
132 | /******/ })()
133 | ;
134 | });
135 | //# sourceMappingURL=grab.js.map
--------------------------------------------------------------------------------
/dist/components/grab.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"components/grab.js","mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD,O;;;;;;;;;ACVA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,iCAAiC,mBAAmB;AACpD,iCAAiC,mBAAmB;AACpD,iCAAiC,mBAAmB;;AAEpD;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA,kBAAkB;AAClB;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,wEAAwE;AACxE;AACA;AACA;AACA;AACA;AACA,CAAC;;;;;;;UCzED;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;;;UEtBA;UACA;UACA;UACA","sources":["webpack://aframe-extras/webpack/universalModuleDefinition","webpack://aframe-extras/./src/misc/grab.js","webpack://aframe-extras/webpack/bootstrap","webpack://aframe-extras/webpack/before-startup","webpack://aframe-extras/webpack/startup","webpack://aframe-extras/webpack/after-startup"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse {\n\t\tvar a = factory();\n\t\tfor(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n\t}\n})(self, () => {\nreturn ","/* global CANNON */\n\n/**\n * Based on aframe/examples/showcase/tracked-controls.\n *\n * Handles events coming from the hand-controls.\n * Determines if the entity is grabbed or released.\n * Updates its position to move along the controller.\n */\nmodule.exports = AFRAME.registerComponent('grab', {\n init: function () {\n this.system = this.el.sceneEl.systems.physics;\n\n this.GRABBED_STATE = 'grabbed';\n\n this.grabbing = false;\n this.hitEl = /** @type {AFRAME.Element} */ null;\n this.physics = /** @type {AFRAME.System} */ this.el.sceneEl.systems.physics;\n this.constraint = /** @type {CANNON.Constraint} */ null;\n\n // Bind event handlers\n this.onHit = this.onHit.bind(this);\n this.onGripOpen = this.onGripOpen.bind(this);\n this.onGripClose = this.onGripClose.bind(this);\n },\n\n play: function () {\n const el = this.el;\n el.addEventListener('hit', this.onHit);\n el.addEventListener('gripdown', this.onGripClose);\n el.addEventListener('gripup', this.onGripOpen);\n el.addEventListener('trackpaddown', this.onGripClose);\n el.addEventListener('trackpadup', this.onGripOpen);\n el.addEventListener('triggerdown', this.onGripClose);\n el.addEventListener('triggerup', this.onGripOpen);\n },\n\n pause: function () {\n const el = this.el;\n el.removeEventListener('hit', this.onHit);\n el.removeEventListener('gripdown', this.onGripClose);\n el.removeEventListener('gripup', this.onGripOpen);\n el.removeEventListener('trackpaddown', this.onGripClose);\n el.removeEventListener('trackpadup', this.onGripOpen);\n el.removeEventListener('triggerdown', this.onGripClose);\n el.removeEventListener('triggerup', this.onGripOpen);\n },\n\n onGripClose: function () {\n this.grabbing = true;\n },\n\n onGripOpen: function () {\n const hitEl = this.hitEl;\n this.grabbing = false;\n if (!hitEl) { return; }\n hitEl.removeState(this.GRABBED_STATE);\n this.hitEl = undefined;\n this.system.removeConstraint(this.constraint);\n this.constraint = null;\n },\n\n onHit: function (evt) {\n const hitEl = evt.detail.el;\n // If the element is already grabbed (it could be grabbed by another controller).\n // If the hand is not grabbing the element does not stick.\n // If we're already grabbing something you can't grab again.\n if (hitEl.is(this.GRABBED_STATE) || !this.grabbing || this.hitEl) { return; }\n hitEl.addState(this.GRABBED_STATE);\n this.hitEl = hitEl;\n this.constraint = new CANNON.LockConstraint(this.el.body, hitEl.body);\n this.system.addConstraint(this.constraint);\n }\n});\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(\"./src/misc/grab.js\");\n",""],"names":[],"sourceRoot":""}
--------------------------------------------------------------------------------
/dist/components/grab.min.js:
--------------------------------------------------------------------------------
1 | !function(t,i){if("object"==typeof exports&&"object"==typeof module)module.exports=i();else if("function"==typeof define&&define.amd)define([],i);else{var e=i();for(var n in e)("object"==typeof exports?exports:t)[n]=e[n]}}(self,(()=>{return t={771:t=>{t.exports=AFRAME.registerComponent("grab",{init:function(){this.system=this.el.sceneEl.systems.physics,this.GRABBED_STATE="grabbed",this.grabbing=!1,this.hitEl=null,this.physics=this.el.sceneEl.systems.physics,this.constraint=null,this.onHit=this.onHit.bind(this),this.onGripOpen=this.onGripOpen.bind(this),this.onGripClose=this.onGripClose.bind(this)},play:function(){const t=this.el;t.addEventListener("hit",this.onHit),t.addEventListener("gripdown",this.onGripClose),t.addEventListener("gripup",this.onGripOpen),t.addEventListener("trackpaddown",this.onGripClose),t.addEventListener("trackpadup",this.onGripOpen),t.addEventListener("triggerdown",this.onGripClose),t.addEventListener("triggerup",this.onGripOpen)},pause:function(){const t=this.el;t.removeEventListener("hit",this.onHit),t.removeEventListener("gripdown",this.onGripClose),t.removeEventListener("gripup",this.onGripOpen),t.removeEventListener("trackpaddown",this.onGripClose),t.removeEventListener("trackpadup",this.onGripOpen),t.removeEventListener("triggerdown",this.onGripClose),t.removeEventListener("triggerup",this.onGripOpen)},onGripClose:function(){this.grabbing=!0},onGripOpen:function(){const t=this.hitEl;this.grabbing=!1,t&&(t.removeState(this.GRABBED_STATE),this.hitEl=void 0,this.system.removeConstraint(this.constraint),this.constraint=null)},onHit:function(t){const i=t.detail.el;i.is(this.GRABBED_STATE)||!this.grabbing||this.hitEl||(i.addState(this.GRABBED_STATE),this.hitEl=i,this.constraint=new CANNON.LockConstraint(this.el.body,i.body),this.system.addConstraint(this.constraint))}})}},i={},function e(n){var s=i[n];if(void 0!==s)return s.exports;var o=i[n]={exports:{}};return t[n](o,o.exports,e),o.exports}(771);var t,i}));
2 | //# sourceMappingURL=grab.min.js.map
--------------------------------------------------------------------------------
/dist/components/grab.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"components/grab.min.js","mappings":"CAAA,SAA2CA,EAAMC,GAChD,GAAsB,iBAAZC,SAA0C,iBAAXC,OACxCA,OAAOD,QAAUD,SACb,GAAqB,mBAAXG,QAAyBA,OAAOC,IAC9CD,OAAO,GAAIH,OACP,CACJ,IAAIK,EAAIL,IACR,IAAI,IAAIM,KAAKD,GAAuB,iBAAZJ,QAAuBA,QAAUF,GAAMO,GAAKD,EAAEC,EACvE,CACA,CATD,CASGC,MAAM,KACT,O,WCDAL,EAAOD,QAAUO,OAAOC,kBAAkB,OAAQ,CAChDC,KAAM,WACJC,KAAKC,OAASD,KAAKE,GAAGC,QAAQC,QAAQC,QAEtCL,KAAKM,cAAgB,UAErBN,KAAKO,UAAW,EAChBP,KAAKQ,MAA8C,KACnDR,KAAKK,QAA8CL,KAAKE,GAAGC,QAAQC,QAAQC,QAC3EL,KAAKS,WAA8C,KAGnDT,KAAKU,MAAQV,KAAKU,MAAMC,KAAKX,MAC7BA,KAAKY,WAAaZ,KAAKY,WAAWD,KAAKX,MACvCA,KAAKa,YAAcb,KAAKa,YAAYF,KAAKX,KAC3C,EAEAc,KAAM,WACJ,MAAMZ,EAAKF,KAAKE,GAChBA,EAAGa,iBAAiB,MAAOf,KAAKU,OAChCR,EAAGa,iBAAiB,WAAYf,KAAKa,aACrCX,EAAGa,iBAAiB,SAAUf,KAAKY,YACnCV,EAAGa,iBAAiB,eAAgBf,KAAKa,aACzCX,EAAGa,iBAAiB,aAAcf,KAAKY,YACvCV,EAAGa,iBAAiB,cAAef,KAAKa,aACxCX,EAAGa,iBAAiB,YAAaf,KAAKY,WACxC,EAEAI,MAAO,WACL,MAAMd,EAAKF,KAAKE,GAChBA,EAAGe,oBAAoB,MAAOjB,KAAKU,OACnCR,EAAGe,oBAAoB,WAAYjB,KAAKa,aACxCX,EAAGe,oBAAoB,SAAUjB,KAAKY,YACtCV,EAAGe,oBAAoB,eAAgBjB,KAAKa,aAC5CX,EAAGe,oBAAoB,aAAcjB,KAAKY,YAC1CV,EAAGe,oBAAoB,cAAejB,KAAKa,aAC3CX,EAAGe,oBAAoB,YAAajB,KAAKY,WAC3C,EAEAC,YAAa,WACXb,KAAKO,UAAW,CAClB,EAEAK,WAAY,WACV,MAAMJ,EAAQR,KAAKQ,MACnBR,KAAKO,UAAW,EACXC,IACLA,EAAMU,YAAYlB,KAAKM,eACvBN,KAAKQ,WAAQW,EACbnB,KAAKC,OAAOmB,iBAAiBpB,KAAKS,YAClCT,KAAKS,WAAa,KACpB,EAEAC,MAAO,SAAUW,GACf,MAAMb,EAAQa,EAAIC,OAAOpB,GAIrBM,EAAMe,GAAGvB,KAAKM,iBAAmBN,KAAKO,UAAYP,KAAKQ,QAC3DA,EAAMgB,SAASxB,KAAKM,eACpBN,KAAKQ,MAAQA,EACbR,KAAKS,WAAa,IAAIgB,OAAOC,eAAe1B,KAAKE,GAAGyB,KAAMnB,EAAMmB,MAChE3B,KAAKC,OAAO2B,cAAc5B,KAAKS,YACjC,G,GCvEEoB,EAA2B,CAAC,EAGhC,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqBZ,IAAjBa,EACH,OAAOA,EAAa1C,QAGrB,IAAIC,EAASsC,EAAyBE,GAAY,CAGjDzC,QAAS,CAAC,GAOX,OAHA2C,EAAoBF,GAAUxC,EAAQA,EAAOD,QAASwC,GAG/CvC,EAAOD,OACf,CCnB0BwC,CAAoB,K,MDF1CD,C","sources":["webpack://aframe-extras/webpack/universalModuleDefinition","webpack://aframe-extras/./src/misc/grab.js","webpack://aframe-extras/webpack/bootstrap","webpack://aframe-extras/webpack/startup"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse {\n\t\tvar a = factory();\n\t\tfor(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n\t}\n})(self, () => {\nreturn ","/* global CANNON */\n\n/**\n * Based on aframe/examples/showcase/tracked-controls.\n *\n * Handles events coming from the hand-controls.\n * Determines if the entity is grabbed or released.\n * Updates its position to move along the controller.\n */\nmodule.exports = AFRAME.registerComponent('grab', {\n init: function () {\n this.system = this.el.sceneEl.systems.physics;\n\n this.GRABBED_STATE = 'grabbed';\n\n this.grabbing = false;\n this.hitEl = /** @type {AFRAME.Element} */ null;\n this.physics = /** @type {AFRAME.System} */ this.el.sceneEl.systems.physics;\n this.constraint = /** @type {CANNON.Constraint} */ null;\n\n // Bind event handlers\n this.onHit = this.onHit.bind(this);\n this.onGripOpen = this.onGripOpen.bind(this);\n this.onGripClose = this.onGripClose.bind(this);\n },\n\n play: function () {\n const el = this.el;\n el.addEventListener('hit', this.onHit);\n el.addEventListener('gripdown', this.onGripClose);\n el.addEventListener('gripup', this.onGripOpen);\n el.addEventListener('trackpaddown', this.onGripClose);\n el.addEventListener('trackpadup', this.onGripOpen);\n el.addEventListener('triggerdown', this.onGripClose);\n el.addEventListener('triggerup', this.onGripOpen);\n },\n\n pause: function () {\n const el = this.el;\n el.removeEventListener('hit', this.onHit);\n el.removeEventListener('gripdown', this.onGripClose);\n el.removeEventListener('gripup', this.onGripOpen);\n el.removeEventListener('trackpaddown', this.onGripClose);\n el.removeEventListener('trackpadup', this.onGripOpen);\n el.removeEventListener('triggerdown', this.onGripClose);\n el.removeEventListener('triggerup', this.onGripOpen);\n },\n\n onGripClose: function () {\n this.grabbing = true;\n },\n\n onGripOpen: function () {\n const hitEl = this.hitEl;\n this.grabbing = false;\n if (!hitEl) { return; }\n hitEl.removeState(this.GRABBED_STATE);\n this.hitEl = undefined;\n this.system.removeConstraint(this.constraint);\n this.constraint = null;\n },\n\n onHit: function (evt) {\n const hitEl = evt.detail.el;\n // If the element is already grabbed (it could be grabbed by another controller).\n // If the hand is not grabbing the element does not stick.\n // If we're already grabbing something you can't grab again.\n if (hitEl.is(this.GRABBED_STATE) || !this.grabbing || this.hitEl) { return; }\n hitEl.addState(this.GRABBED_STATE);\n this.hitEl = hitEl;\n this.constraint = new CANNON.LockConstraint(this.el.body, hitEl.body);\n this.system.addConstraint(this.constraint);\n }\n});\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(771);\n"],"names":["root","factory","exports","module","define","amd","a","i","self","AFRAME","registerComponent","init","this","system","el","sceneEl","systems","physics","GRABBED_STATE","grabbing","hitEl","constraint","onHit","bind","onGripOpen","onGripClose","play","addEventListener","pause","removeEventListener","removeState","undefined","removeConstraint","evt","detail","is","addState","CANNON","LockConstraint","body","addConstraint","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__"],"sourceRoot":""}
--------------------------------------------------------------------------------
/dist/components/sphere-collider.js:
--------------------------------------------------------------------------------
1 | (function webpackUniversalModuleDefinition(root, factory) {
2 | if(typeof exports === 'object' && typeof module === 'object')
3 | module.exports = factory();
4 | else if(typeof define === 'function' && define.amd)
5 | define([], factory);
6 | else {
7 | var a = factory();
8 | for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
9 | }
10 | })(self, () => {
11 | return /******/ (() => { // webpackBootstrap
12 | /******/ var __webpack_modules__ = ({
13 |
14 | /***/ "./src/misc/sphere-collider.js":
15 | /*!*************************************!*\
16 | !*** ./src/misc/sphere-collider.js ***!
17 | \*************************************/
18 | /***/ ((module) => {
19 |
20 | /**
21 | * Based on aframe/examples/showcase/tracked-controls.
22 | *
23 | * Implement bounding sphere collision detection for entities with a mesh.
24 | * Sets the specified state on the intersected entities.
25 | *
26 | * @property {string} objects - Selector of the entities to test for collision.
27 | * @property {string} state - State to set on collided entities.
28 | *
29 | */
30 | module.exports = AFRAME.registerComponent('sphere-collider', {
31 | schema: {
32 | enabled: {default: true},
33 | interval: {default: 80},
34 | objects: {default: ''},
35 | state: {default: 'collided'},
36 | radius: {default: 0.05},
37 | watch: {default: true}
38 | },
39 |
40 | init: function () {
41 | /** @type {MutationObserver} */
42 | this.observer = null;
43 | /** @type {Array} Elements to watch for collisions. */
44 | this.els = [];
45 | /** @type {Array} Elements currently in collision state. */
46 | this.collisions = [];
47 | this.prevCheckTime = undefined;
48 |
49 | this.eventDetail = {};
50 | this.handleHit = this.handleHit.bind(this);
51 | this.handleHitEnd = this.handleHitEnd.bind(this);
52 | },
53 |
54 | play: function () {
55 | const sceneEl = this.el.sceneEl;
56 |
57 | if (this.data.watch) {
58 | this.observer = new MutationObserver(this.update.bind(this, null));
59 | this.observer.observe(sceneEl, {childList: true, subtree: true});
60 | }
61 | },
62 |
63 | pause: function () {
64 | if (this.observer) {
65 | this.observer.disconnect();
66 | this.observer = null;
67 | }
68 | },
69 |
70 | /**
71 | * Update list of entities to test for collision.
72 | */
73 | update: function () {
74 | const data = this.data;
75 | let objectEls;
76 |
77 | // Push entities into list of els to intersect.
78 | if (data.objects) {
79 | objectEls = this.el.sceneEl.querySelectorAll(data.objects);
80 | } else {
81 | // If objects not defined, intersect with everything.
82 | objectEls = this.el.sceneEl.children;
83 | }
84 | // Convert from NodeList to Array
85 | this.els = Array.prototype.slice.call(objectEls);
86 | },
87 |
88 | tick: (function () {
89 | const position = new THREE.Vector3(),
90 | meshPosition = new THREE.Vector3(),
91 | colliderScale = new THREE.Vector3(),
92 | size = new THREE.Vector3(),
93 | box = new THREE.Box3(),
94 | collisions = [],
95 | distanceMap = new Map();
96 | return function (time) {
97 | if (!this.data.enabled) { return; }
98 |
99 | // Only check for intersection if interval time has passed.
100 | const prevCheckTime = this.prevCheckTime;
101 | if (prevCheckTime && (time - prevCheckTime < this.data.interval)) { return; }
102 | // Update check time.
103 | this.prevCheckTime = time;
104 |
105 | const el = this.el,
106 | data = this.data,
107 | mesh = el.getObject3D('mesh');
108 | let colliderRadius;
109 |
110 | if (!mesh) { return; }
111 |
112 | collisions.length = 0;
113 | distanceMap.clear();
114 | el.object3D.getWorldPosition(position);
115 | el.object3D.getWorldScale(colliderScale);
116 | colliderRadius = data.radius * scaleFactor(colliderScale);
117 | // Update collision list.
118 | this.els.forEach(intersect);
119 |
120 | // Emit events and add collision states, in order of distance.
121 | collisions
122 | .sort((a, b) => distanceMap.get(a) > distanceMap.get(b) ? 1 : -1)
123 | .forEach(this.handleHit);
124 |
125 | // Remove collision state from other elements.
126 | this.collisions
127 | .filter((el) => !distanceMap.has(el))
128 | .forEach(this.handleHitEnd);
129 |
130 | // Store new collisions
131 | copyArray(this.collisions, collisions);
132 |
133 | // Bounding sphere collision detection
134 | function intersect (el) {
135 | let radius, mesh, distance, extent;
136 |
137 | if (!el.isEntity) { return; }
138 |
139 | mesh = el.getObject3D('mesh');
140 |
141 | if (!mesh) { return; }
142 |
143 | box.setFromObject(mesh).getSize(size);
144 | extent = Math.max(size.x, size.y, size.z) / 2;
145 | radius = Math.sqrt(2 * extent * extent);
146 | box.getCenter(meshPosition);
147 |
148 | if (!radius) { return; }
149 |
150 | distance = position.distanceTo(meshPosition);
151 | if (distance < radius + colliderRadius) {
152 | collisions.push(el);
153 | distanceMap.set(el, distance);
154 | }
155 | }
156 | // use max of scale factors to maintain bounding sphere collision
157 | function scaleFactor (scaleVec) {
158 | return Math.max(scaleVec.x, scaleVec.y, scaleVec.z);
159 | }
160 | };
161 | })(),
162 |
163 | handleHit: function (targetEl) {
164 | targetEl.emit('hit');
165 | targetEl.addState(this.data.state);
166 | this.eventDetail.el = targetEl;
167 | this.el.emit('hit', this.eventDetail);
168 | },
169 | handleHitEnd: function (targetEl) {
170 | targetEl.emit('hitend');
171 | targetEl.removeState(this.data.state);
172 | this.eventDetail.el = targetEl;
173 | this.el.emit('hitend', this.eventDetail);
174 | }
175 | });
176 |
177 | function copyArray (dest, source) {
178 | dest.length = 0;
179 | for (let i = 0; i < source.length; i++) { dest[i] = source[i]; }
180 | }
181 |
182 |
183 | /***/ })
184 |
185 | /******/ });
186 | /************************************************************************/
187 | /******/ // The module cache
188 | /******/ var __webpack_module_cache__ = {};
189 | /******/
190 | /******/ // The require function
191 | /******/ function __webpack_require__(moduleId) {
192 | /******/ // Check if module is in cache
193 | /******/ var cachedModule = __webpack_module_cache__[moduleId];
194 | /******/ if (cachedModule !== undefined) {
195 | /******/ return cachedModule.exports;
196 | /******/ }
197 | /******/ // Create a new module (and put it into the cache)
198 | /******/ var module = __webpack_module_cache__[moduleId] = {
199 | /******/ // no module.id needed
200 | /******/ // no module.loaded needed
201 | /******/ exports: {}
202 | /******/ };
203 | /******/
204 | /******/ // Execute the module function
205 | /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
206 | /******/
207 | /******/ // Return the exports of the module
208 | /******/ return module.exports;
209 | /******/ }
210 | /******/
211 | /************************************************************************/
212 | /******/
213 | /******/ // startup
214 | /******/ // Load entry module and return exports
215 | /******/ // This entry module is referenced by other modules so it can't be inlined
216 | /******/ var __webpack_exports__ = __webpack_require__("./src/misc/sphere-collider.js");
217 | /******/
218 | /******/ return __webpack_exports__;
219 | /******/ })()
220 | ;
221 | });
222 | //# sourceMappingURL=sphere-collider.js.map
--------------------------------------------------------------------------------
/dist/components/sphere-collider.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"components/sphere-collider.js","mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD,O;;;;;;;;;ACVA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc,QAAQ;AACtB,cAAc,QAAQ;AACtB;AACA;AACA;AACA;AACA,cAAc,cAAc;AAC5B,eAAe,YAAY;AAC3B,cAAc,YAAY;AAC1B,YAAY,oBAAoB;AAChC,aAAa,cAAc;AAC3B,YAAY;AACZ,GAAG;;AAEH;AACA,eAAe,kBAAkB;AACjC;AACA,eAAe,gBAAgB;AAC/B;AACA,eAAe,gBAAgB;AAC/B;AACA;;AAEA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA,sCAAsC,+BAA+B;AACrE;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gCAAgC;;AAEhC;AACA;AACA,0EAA0E;AAC1E;AACA;;AAEA;AACA;AACA;AACA;;AAEA,mBAAmB;;AAEnB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA,4BAA4B;;AAE5B;;AAEA,qBAAqB;;AAErB;AACA;AACA;AACA;;AAEA,uBAAuB;;AAEvB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA,kBAAkB,mBAAmB,OAAO;AAC5C;;;;;;;UChKA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;;;UEtBA;UACA;UACA;UACA","sources":["webpack://aframe-extras/webpack/universalModuleDefinition","webpack://aframe-extras/./src/misc/sphere-collider.js","webpack://aframe-extras/webpack/bootstrap","webpack://aframe-extras/webpack/before-startup","webpack://aframe-extras/webpack/startup","webpack://aframe-extras/webpack/after-startup"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse {\n\t\tvar a = factory();\n\t\tfor(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n\t}\n})(self, () => {\nreturn ","/**\n * Based on aframe/examples/showcase/tracked-controls.\n *\n * Implement bounding sphere collision detection for entities with a mesh.\n * Sets the specified state on the intersected entities.\n *\n * @property {string} objects - Selector of the entities to test for collision.\n * @property {string} state - State to set on collided entities.\n *\n */\nmodule.exports = AFRAME.registerComponent('sphere-collider', {\n schema: {\n enabled: {default: true},\n interval: {default: 80},\n objects: {default: ''},\n state: {default: 'collided'},\n radius: {default: 0.05},\n watch: {default: true}\n },\n\n init: function () {\n /** @type {MutationObserver} */\n this.observer = null;\n /** @type {Array} Elements to watch for collisions. */\n this.els = [];\n /** @type {Array} Elements currently in collision state. */\n this.collisions = [];\n this.prevCheckTime = undefined;\n\n this.eventDetail = {};\n this.handleHit = this.handleHit.bind(this);\n this.handleHitEnd = this.handleHitEnd.bind(this);\n },\n\n play: function () {\n const sceneEl = this.el.sceneEl;\n\n if (this.data.watch) {\n this.observer = new MutationObserver(this.update.bind(this, null));\n this.observer.observe(sceneEl, {childList: true, subtree: true});\n }\n },\n\n pause: function () {\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n },\n\n /**\n * Update list of entities to test for collision.\n */\n update: function () {\n const data = this.data;\n let objectEls;\n\n // Push entities into list of els to intersect.\n if (data.objects) {\n objectEls = this.el.sceneEl.querySelectorAll(data.objects);\n } else {\n // If objects not defined, intersect with everything.\n objectEls = this.el.sceneEl.children;\n }\n // Convert from NodeList to Array\n this.els = Array.prototype.slice.call(objectEls);\n },\n\n tick: (function () {\n const position = new THREE.Vector3(),\n meshPosition = new THREE.Vector3(),\n colliderScale = new THREE.Vector3(),\n size = new THREE.Vector3(),\n box = new THREE.Box3(),\n collisions = [],\n distanceMap = new Map();\n return function (time) {\n if (!this.data.enabled) { return; }\n\n // Only check for intersection if interval time has passed.\n const prevCheckTime = this.prevCheckTime;\n if (prevCheckTime && (time - prevCheckTime < this.data.interval)) { return; }\n // Update check time.\n this.prevCheckTime = time;\n\n const el = this.el,\n data = this.data,\n mesh = el.getObject3D('mesh');\n let colliderRadius;\n\n if (!mesh) { return; }\n\n collisions.length = 0;\n distanceMap.clear();\n el.object3D.getWorldPosition(position);\n el.object3D.getWorldScale(colliderScale);\n colliderRadius = data.radius * scaleFactor(colliderScale);\n // Update collision list.\n this.els.forEach(intersect);\n\n // Emit events and add collision states, in order of distance.\n collisions\n .sort((a, b) => distanceMap.get(a) > distanceMap.get(b) ? 1 : -1)\n .forEach(this.handleHit);\n\n // Remove collision state from other elements.\n this.collisions\n .filter((el) => !distanceMap.has(el))\n .forEach(this.handleHitEnd);\n\n // Store new collisions\n copyArray(this.collisions, collisions);\n\n // Bounding sphere collision detection\n function intersect (el) {\n let radius, mesh, distance, extent;\n\n if (!el.isEntity) { return; }\n\n mesh = el.getObject3D('mesh');\n\n if (!mesh) { return; }\n\n box.setFromObject(mesh).getSize(size);\n extent = Math.max(size.x, size.y, size.z) / 2;\n radius = Math.sqrt(2 * extent * extent);\n box.getCenter(meshPosition);\n\n if (!radius) { return; }\n\n distance = position.distanceTo(meshPosition);\n if (distance < radius + colliderRadius) {\n collisions.push(el);\n distanceMap.set(el, distance);\n }\n }\n // use max of scale factors to maintain bounding sphere collision\n function scaleFactor (scaleVec) {\n return Math.max(scaleVec.x, scaleVec.y, scaleVec.z);\n }\n };\n })(),\n\n handleHit: function (targetEl) {\n targetEl.emit('hit');\n targetEl.addState(this.data.state);\n this.eventDetail.el = targetEl;\n this.el.emit('hit', this.eventDetail);\n },\n handleHitEnd: function (targetEl) {\n targetEl.emit('hitend');\n targetEl.removeState(this.data.state);\n this.eventDetail.el = targetEl;\n this.el.emit('hitend', this.eventDetail);\n }\n});\n\nfunction copyArray (dest, source) {\n dest.length = 0;\n for (let i = 0; i < source.length; i++) { dest[i] = source[i]; }\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(\"./src/misc/sphere-collider.js\");\n",""],"names":[],"sourceRoot":""}
--------------------------------------------------------------------------------
/dist/components/sphere-collider.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var i=t();for(var s in i)("object"==typeof exports?exports:e)[s]=i[s]}}(self,(()=>{return e={109:e=>{e.exports=AFRAME.registerComponent("sphere-collider",{schema:{enabled:{default:!0},interval:{default:80},objects:{default:""},state:{default:"collided"},radius:{default:.05},watch:{default:!0}},init:function(){this.observer=null,this.els=[],this.collisions=[],this.prevCheckTime=void 0,this.eventDetail={},this.handleHit=this.handleHit.bind(this),this.handleHitEnd=this.handleHitEnd.bind(this)},play:function(){const e=this.el.sceneEl;this.data.watch&&(this.observer=new MutationObserver(this.update.bind(this,null)),this.observer.observe(e,{childList:!0,subtree:!0}))},pause:function(){this.observer&&(this.observer.disconnect(),this.observer=null)},update:function(){const e=this.data;let t;t=e.objects?this.el.sceneEl.querySelectorAll(e.objects):this.el.sceneEl.children,this.els=Array.prototype.slice.call(t)},tick:function(){const e=new THREE.Vector3,t=new THREE.Vector3,i=new THREE.Vector3,s=new THREE.Vector3,n=new THREE.Box3,o=[],l=new Map;return function(r){if(!this.data.enabled)return;const h=this.prevCheckTime;if(h&&r-hl.get(e)>l.get(t)?1:-1)).forEach(this.handleHit),this.collisions.filter((e=>!l.has(e))).forEach(this.handleHitEnd),function(e,t){e.length=0;for(let i=0;i {\nreturn ","/**\n * Based on aframe/examples/showcase/tracked-controls.\n *\n * Implement bounding sphere collision detection for entities with a mesh.\n * Sets the specified state on the intersected entities.\n *\n * @property {string} objects - Selector of the entities to test for collision.\n * @property {string} state - State to set on collided entities.\n *\n */\nmodule.exports = AFRAME.registerComponent('sphere-collider', {\n schema: {\n enabled: {default: true},\n interval: {default: 80},\n objects: {default: ''},\n state: {default: 'collided'},\n radius: {default: 0.05},\n watch: {default: true}\n },\n\n init: function () {\n /** @type {MutationObserver} */\n this.observer = null;\n /** @type {Array} Elements to watch for collisions. */\n this.els = [];\n /** @type {Array} Elements currently in collision state. */\n this.collisions = [];\n this.prevCheckTime = undefined;\n\n this.eventDetail = {};\n this.handleHit = this.handleHit.bind(this);\n this.handleHitEnd = this.handleHitEnd.bind(this);\n },\n\n play: function () {\n const sceneEl = this.el.sceneEl;\n\n if (this.data.watch) {\n this.observer = new MutationObserver(this.update.bind(this, null));\n this.observer.observe(sceneEl, {childList: true, subtree: true});\n }\n },\n\n pause: function () {\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n },\n\n /**\n * Update list of entities to test for collision.\n */\n update: function () {\n const data = this.data;\n let objectEls;\n\n // Push entities into list of els to intersect.\n if (data.objects) {\n objectEls = this.el.sceneEl.querySelectorAll(data.objects);\n } else {\n // If objects not defined, intersect with everything.\n objectEls = this.el.sceneEl.children;\n }\n // Convert from NodeList to Array\n this.els = Array.prototype.slice.call(objectEls);\n },\n\n tick: (function () {\n const position = new THREE.Vector3(),\n meshPosition = new THREE.Vector3(),\n colliderScale = new THREE.Vector3(),\n size = new THREE.Vector3(),\n box = new THREE.Box3(),\n collisions = [],\n distanceMap = new Map();\n return function (time) {\n if (!this.data.enabled) { return; }\n\n // Only check for intersection if interval time has passed.\n const prevCheckTime = this.prevCheckTime;\n if (prevCheckTime && (time - prevCheckTime < this.data.interval)) { return; }\n // Update check time.\n this.prevCheckTime = time;\n\n const el = this.el,\n data = this.data,\n mesh = el.getObject3D('mesh');\n let colliderRadius;\n\n if (!mesh) { return; }\n\n collisions.length = 0;\n distanceMap.clear();\n el.object3D.getWorldPosition(position);\n el.object3D.getWorldScale(colliderScale);\n colliderRadius = data.radius * scaleFactor(colliderScale);\n // Update collision list.\n this.els.forEach(intersect);\n\n // Emit events and add collision states, in order of distance.\n collisions\n .sort((a, b) => distanceMap.get(a) > distanceMap.get(b) ? 1 : -1)\n .forEach(this.handleHit);\n\n // Remove collision state from other elements.\n this.collisions\n .filter((el) => !distanceMap.has(el))\n .forEach(this.handleHitEnd);\n\n // Store new collisions\n copyArray(this.collisions, collisions);\n\n // Bounding sphere collision detection\n function intersect (el) {\n let radius, mesh, distance, extent;\n\n if (!el.isEntity) { return; }\n\n mesh = el.getObject3D('mesh');\n\n if (!mesh) { return; }\n\n box.setFromObject(mesh).getSize(size);\n extent = Math.max(size.x, size.y, size.z) / 2;\n radius = Math.sqrt(2 * extent * extent);\n box.getCenter(meshPosition);\n\n if (!radius) { return; }\n\n distance = position.distanceTo(meshPosition);\n if (distance < radius + colliderRadius) {\n collisions.push(el);\n distanceMap.set(el, distance);\n }\n }\n // use max of scale factors to maintain bounding sphere collision\n function scaleFactor (scaleVec) {\n return Math.max(scaleVec.x, scaleVec.y, scaleVec.z);\n }\n };\n })(),\n\n handleHit: function (targetEl) {\n targetEl.emit('hit');\n targetEl.addState(this.data.state);\n this.eventDetail.el = targetEl;\n this.el.emit('hit', this.eventDetail);\n },\n handleHitEnd: function (targetEl) {\n targetEl.emit('hitend');\n targetEl.removeState(this.data.state);\n this.eventDetail.el = targetEl;\n this.el.emit('hitend', this.eventDetail);\n }\n});\n\nfunction copyArray (dest, source) {\n dest.length = 0;\n for (let i = 0; i < source.length; i++) { dest[i] = source[i]; }\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(109);\n"],"names":["root","factory","exports","module","define","amd","a","i","self","AFRAME","registerComponent","schema","enabled","default","interval","objects","state","radius","watch","init","this","observer","els","collisions","prevCheckTime","undefined","eventDetail","handleHit","bind","handleHitEnd","play","sceneEl","el","data","MutationObserver","update","observe","childList","subtree","pause","disconnect","objectEls","querySelectorAll","children","Array","prototype","slice","call","tick","position","THREE","Vector3","meshPosition","colliderScale","size","box","Box3","distanceMap","Map","time","colliderRadius","scaleVec","getObject3D","length","clear","object3D","getWorldPosition","getWorldScale","Math","max","x","y","z","forEach","mesh","distance","extent","isEntity","setFromObject","getSize","sqrt","getCenter","distanceTo","push","set","sort","b","get","filter","has","dest","source","copyArray","targetEl","emit","addState","removeState","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__"],"sourceRoot":""}
--------------------------------------------------------------------------------
/examples/animation-controls/animation-controls.js:
--------------------------------------------------------------------------------
1 |
2 | const animationNames = {
3 | attack: 'Armature|TRex_Attack',
4 | death: 'Armature|TRex_Death',
5 | idle: 'Armature|TRex_Idle',
6 | jump: 'Armature|TRex_Jump',
7 | run: 'Armature|TRex_Run',
8 | walk: 'Armature|TRex_Walk',
9 | };
10 |
11 | updateAnimationMixer = () => {
12 |
13 | const data = {useRegExp: true}
14 | data.clip = 'none'
15 | Object.entries(animationNames).forEach((name) => {
16 |
17 | const regExpEscape = (s) => {
18 | return s.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
19 | }
20 |
21 | el = document.getElementById(name[0])
22 | if (el.checked) {
23 | if (data.clip) data.clip += "|"
24 | data.clip += regExpEscape(name[1])
25 | }
26 | })
27 |
28 | const keys = ['duration',
29 | 'clampWhenFinished',
30 | 'crossFadeDuration',
31 | 'loop',
32 | 'repetitions',
33 | 'timeScale',
34 | 'startAt']
35 | keys.forEach((key) => {
36 | const el = document.getElementById(key)
37 | let value = el.value
38 |
39 | const type = AFRAME.components['animation-mixer'].schema[key].type
40 |
41 | if (type === 'number' && isNaN(value)) {
42 | return;
43 | }
44 |
45 | if (type === 'boolean') {
46 | value = el.checked
47 | }
48 |
49 | data[key] = value
50 | })
51 |
52 | const target = document.getElementById('trex1')
53 | target.setAttribute('animation-mixer', data)
54 | }
55 |
56 | document.addEventListener('DOMContentLoaded', () => {
57 |
58 | const inputs = document.querySelectorAll('input, select')
59 |
60 | inputs.forEach((input) => {
61 | input.addEventListener('change', updateAnimationMixer)
62 | input.addEventListener('click', updateAnimationMixer)
63 | })
64 |
65 | updateAnimationMixer()
66 | })
67 |
--------------------------------------------------------------------------------
/examples/animation-controls/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Examples • Animation Controls
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |