three-stdlib 2.20.5 → 2.21.0

Sign up to get free protection for your applications and to get access to all the features.
package/index.d.ts CHANGED
@@ -249,3 +249,4 @@ export * from './curves/NURBSCurve';
249
249
  export * from './curves/NURBSSurface';
250
250
  export * from './curves/CurveExtras';
251
251
  export * from './deprecated/Geometry';
252
+ export * from './libs/MotionControllers';
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});const e={Handedness:Object.freeze({NONE:"none",LEFT:"left",RIGHT:"right"}),ComponentState:Object.freeze({DEFAULT:"default",TOUCHED:"touched",PRESSED:"pressed"}),ComponentProperty:Object.freeze({BUTTON:"button",X_AXIS:"xAxis",Y_AXIS:"yAxis",STATE:"state"}),ComponentType:Object.freeze({TRIGGER:"trigger",SQUEEZE:"squeeze",TOUCHPAD:"touchpad",THUMBSTICK:"thumbstick",BUTTON:"button"}),ButtonTouchThreshold:.05,AxisTouchThreshold:.1,VisualResponseProperty:Object.freeze({TRANSFORM:"transform",VISIBILITY:"visibility"})};async function t(e){const t=await fetch(e);if(t.ok)return t.json();throw new Error(t.statusText)}async function s(e){if(!e)throw new Error("No basePath supplied");return await t(`${e}/profilesList.json`)}const o={xAxis:0,yAxis:0,button:0,state:e.ComponentState.DEFAULT};class a{constructor(t){this.componentProperty=t.componentProperty,this.states=t.states,this.valueNodeName=t.valueNodeName,this.valueNodeProperty=t.valueNodeProperty,this.valueNodeProperty===e.VisualResponseProperty.TRANSFORM&&(this.minNodeName=t.minNodeName,this.maxNodeName=t.maxNodeName),this.value=0,this.updateFromComponent(o)}updateFromComponent({xAxis:t,yAxis:s,button:o,state:a}){const{normalizedXAxis:i,normalizedYAxis:n}=function(e=0,t=0){let s=e,o=t;if(Math.sqrt(e*e+t*t)>1){const a=Math.atan2(t,e);s=Math.cos(a),o=Math.sin(a)}return{normalizedXAxis:.5*s+.5,normalizedYAxis:.5*o+.5}}(t,s);switch(this.componentProperty){case e.ComponentProperty.X_AXIS:this.value=this.states.includes(a)?i:.5;break;case e.ComponentProperty.Y_AXIS:this.value=this.states.includes(a)?n:.5;break;case e.ComponentProperty.BUTTON:this.value=this.states.includes(a)?o:0;break;case e.ComponentProperty.STATE:this.valueNodeProperty===e.VisualResponseProperty.VISIBILITY?this.value=this.states.includes(a):this.value=this.states.includes(a)?1:0;break;default:throw new Error(`Unexpected visualResponse componentProperty ${this.componentProperty}`)}}}class i{constructor(t,s){if(!(t&&s&&s.visualResponses&&s.gamepadIndices&&0!==Object.keys(s.gamepadIndices).length))throw new Error("Invalid arguments supplied");this.id=t,this.type=s.type,this.rootNodeName=s.rootNodeName,this.touchPointNodeName=s.touchPointNodeName,this.visualResponses={},Object.keys(s.visualResponses).forEach((e=>{const t=new a(s.visualResponses[e]);this.visualResponses[e]=t})),this.gamepadIndices=Object.assign({},s.gamepadIndices),this.values={state:e.ComponentState.DEFAULT,button:void 0!==this.gamepadIndices.button?0:void 0,xAxis:void 0!==this.gamepadIndices.xAxis?0:void 0,yAxis:void 0!==this.gamepadIndices.yAxis?0:void 0}}get data(){return{id:this.id,...this.values}}updateFromGamepad(t){if(this.values.state=e.ComponentState.DEFAULT,void 0!==this.gamepadIndices.button&&t.buttons.length>this.gamepadIndices.button){const s=t.buttons[this.gamepadIndices.button];this.values.button=s.value,this.values.button=this.values.button<0?0:this.values.button,this.values.button=this.values.button>1?1:this.values.button,s.pressed||1===this.values.button?this.values.state=e.ComponentState.PRESSED:(s.touched||this.values.button>e.ButtonTouchThreshold)&&(this.values.state=e.ComponentState.TOUCHED)}void 0!==this.gamepadIndices.xAxis&&t.axes.length>this.gamepadIndices.xAxis&&(this.values.xAxis=t.axes[this.gamepadIndices.xAxis],this.values.xAxis=this.values.xAxis<-1?-1:this.values.xAxis,this.values.xAxis=this.values.xAxis>1?1:this.values.xAxis,this.values.state===e.ComponentState.DEFAULT&&Math.abs(this.values.xAxis)>e.AxisTouchThreshold&&(this.values.state=e.ComponentState.TOUCHED)),void 0!==this.gamepadIndices.yAxis&&t.axes.length>this.gamepadIndices.yAxis&&(this.values.yAxis=t.axes[this.gamepadIndices.yAxis],this.values.yAxis=this.values.yAxis<-1?-1:this.values.yAxis,this.values.yAxis=this.values.yAxis>1?1:this.values.yAxis,this.values.state===e.ComponentState.DEFAULT&&Math.abs(this.values.yAxis)>e.AxisTouchThreshold&&(this.values.state=e.ComponentState.TOUCHED)),Object.values(this.visualResponses).forEach((e=>{e.updateFromComponent(this.values)}))}}exports.MotionController=class{constructor(e,t,s){if(!e)throw new Error("No xrInputSource supplied");if(!t)throw new Error("No profile supplied");this.xrInputSource=e,this.assetUrl=s,this.id=t.profileId,this.layoutDescription=t.layouts[e.handedness],this.components={},Object.keys(this.layoutDescription.components).forEach((e=>{const t=this.layoutDescription.components[e];this.components[e]=new i(e,t)})),this.updateFromGamepad()}get gripSpace(){return this.xrInputSource.gripSpace}get targetRaySpace(){return this.xrInputSource.targetRaySpace}get data(){const e=[];return Object.values(this.components).forEach((t=>{e.push(t.data)})),e}updateFromGamepad(){Object.values(this.components).forEach((e=>{e.updateFromGamepad(this.xrInputSource.gamepad)}))}},exports.MotionControllerConstants=e,exports.fetchProfile=async function(e,o,a=null,i=!0){if(!e)throw new Error("No xrInputSource supplied");if(!o)throw new Error("No basePath supplied");const n=await s(o);let r;if(e.profiles.some((e=>{const t=n[e];return t&&(r={profileId:e,profilePath:`${o}/${t.path}`,deprecated:!!t.deprecated}),!!r})),!r){if(!a)throw new Error("No matching profile name found");const e=n[a];if(!e)throw new Error(`No matching profile name found and default profile "${a}" missing.`);r={profileId:a,profilePath:`${o}/${e.path}`,deprecated:!!e.deprecated}}const h=await t(r.profilePath);let u;if(i){let t;if(t="any"===e.handedness?h.layouts[Object.keys(h.layouts)[0]]:h.layouts[e.handedness],!t)throw new Error(`No matching handedness, ${e.handedness}, in profile ${r.profileId}`);t.assetPath&&(u=r.profilePath.replace("profile.json",t.assetPath))}return{profile:h,assetPath:u}},exports.fetchProfilesList=s;
1
+ "use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}Object.defineProperty(exports,"__esModule",{value:!0});var t=e(require("@babel/runtime/helpers/defineProperty"));const s={Handedness:Object.freeze({NONE:"none",LEFT:"left",RIGHT:"right"}),ComponentState:Object.freeze({DEFAULT:"default",TOUCHED:"touched",PRESSED:"pressed"}),ComponentProperty:Object.freeze({BUTTON:"button",X_AXIS:"xAxis",Y_AXIS:"yAxis",STATE:"state"}),ComponentType:Object.freeze({TRIGGER:"trigger",SQUEEZE:"squeeze",TOUCHPAD:"touchpad",THUMBSTICK:"thumbstick",BUTTON:"button"}),ButtonTouchThreshold:.05,AxisTouchThreshold:.1,VisualResponseProperty:Object.freeze({TRANSFORM:"transform",VISIBILITY:"visibility"})};async function o(e){const t=await fetch(e);if(t.ok)return t.json();throw new Error(t.statusText)}async function i(e){if(!e)throw new Error("No basePath supplied");return await o(`${e}/profilesList.json`)}const a={xAxis:0,yAxis:0,button:0,state:s.ComponentState.DEFAULT};class n{constructor(e){t.default(this,"value",void 0),t.default(this,"componentProperty",void 0),t.default(this,"states",void 0),t.default(this,"valueNodeName",void 0),t.default(this,"valueNodeProperty",void 0),t.default(this,"minNodeName",void 0),t.default(this,"maxNodeName",void 0),t.default(this,"valueNode",void 0),t.default(this,"minNode",void 0),t.default(this,"maxNode",void 0),this.componentProperty=e.componentProperty,this.states=e.states,this.valueNodeName=e.valueNodeName,this.valueNodeProperty=e.valueNodeProperty,this.valueNodeProperty===s.VisualResponseProperty.TRANSFORM&&(this.minNodeName=e.minNodeName,this.maxNodeName=e.maxNodeName),this.value=0,this.updateFromComponent(a)}updateFromComponent({xAxis:e,yAxis:t,button:o,state:i}){const{normalizedXAxis:a,normalizedYAxis:n}=function(e=0,t=0){let s=e,o=t;if(Math.sqrt(e*e+t*t)>1){const i=Math.atan2(t,e);s=Math.cos(i),o=Math.sin(i)}return{normalizedXAxis:.5*s+.5,normalizedYAxis:.5*o+.5}}(e,t);switch(this.componentProperty){case s.ComponentProperty.X_AXIS:this.value=this.states.includes(i)?a:.5;break;case s.ComponentProperty.Y_AXIS:this.value=this.states.includes(i)?n:.5;break;case s.ComponentProperty.BUTTON:this.value=this.states.includes(i)&&o?o:0;break;case s.ComponentProperty.STATE:this.valueNodeProperty===s.VisualResponseProperty.VISIBILITY?this.value=this.states.includes(i):this.value=this.states.includes(i)?1:0;break;default:throw new Error(`Unexpected visualResponse componentProperty ${this.componentProperty}`)}}}class r{constructor(e,o){if(t.default(this,"id",void 0),t.default(this,"values",void 0),t.default(this,"type",void 0),t.default(this,"gamepadIndices",void 0),t.default(this,"rootNodeName",void 0),t.default(this,"visualResponses",void 0),t.default(this,"touchPointNodeName",void 0),t.default(this,"touchPointNode",void 0),!(e&&o&&o.visualResponses&&o.gamepadIndices&&0!==Object.keys(o.gamepadIndices).length))throw new Error("Invalid arguments supplied");this.id=e,this.type=o.type,this.rootNodeName=o.rootNodeName,this.touchPointNodeName=o.touchPointNodeName,this.visualResponses={},Object.keys(o.visualResponses).forEach((e=>{const t=new n(o.visualResponses[e]);this.visualResponses[e]=t})),this.gamepadIndices=Object.assign({},o.gamepadIndices),this.values={state:s.ComponentState.DEFAULT,button:void 0!==this.gamepadIndices.button?0:void 0,xAxis:void 0!==this.gamepadIndices.xAxis?0:void 0,yAxis:void 0!==this.gamepadIndices.yAxis?0:void 0}}get data(){return{id:this.id,...this.values}}updateFromGamepad(e){if(this.values.state=s.ComponentState.DEFAULT,void 0!==this.gamepadIndices.button&&e.buttons.length>this.gamepadIndices.button){const t=e.buttons[this.gamepadIndices.button];this.values.button=t.value,this.values.button=this.values.button<0?0:this.values.button,this.values.button=this.values.button>1?1:this.values.button,t.pressed||1===this.values.button?this.values.state=s.ComponentState.PRESSED:(t.touched||this.values.button>s.ButtonTouchThreshold)&&(this.values.state=s.ComponentState.TOUCHED)}void 0!==this.gamepadIndices.xAxis&&e.axes.length>this.gamepadIndices.xAxis&&(this.values.xAxis=e.axes[this.gamepadIndices.xAxis],this.values.xAxis=this.values.xAxis<-1?-1:this.values.xAxis,this.values.xAxis=this.values.xAxis>1?1:this.values.xAxis,this.values.state===s.ComponentState.DEFAULT&&Math.abs(this.values.xAxis)>s.AxisTouchThreshold&&(this.values.state=s.ComponentState.TOUCHED)),void 0!==this.gamepadIndices.yAxis&&e.axes.length>this.gamepadIndices.yAxis&&(this.values.yAxis=e.axes[this.gamepadIndices.yAxis],this.values.yAxis=this.values.yAxis<-1?-1:this.values.yAxis,this.values.yAxis=this.values.yAxis>1?1:this.values.yAxis,this.values.state===s.ComponentState.DEFAULT&&Math.abs(this.values.yAxis)>s.AxisTouchThreshold&&(this.values.state=s.ComponentState.TOUCHED)),Object.values(this.visualResponses).forEach((e=>{e.updateFromComponent(this.values)}))}}exports.MotionController=class{constructor(e,s,o){if(t.default(this,"xrInputSource",void 0),t.default(this,"assetUrl",void 0),t.default(this,"layoutDescription",void 0),t.default(this,"id",void 0),t.default(this,"components",void 0),!e)throw new Error("No xrInputSource supplied");if(!s)throw new Error("No profile supplied");if(!s.layouts[e.handedness])throw new Error("No layout for "+e.handedness+" handedness");this.xrInputSource=e,this.assetUrl=o,this.id=s.profileId,this.layoutDescription=s.layouts[e.handedness],this.components={},Object.keys(this.layoutDescription.components).forEach((e=>{const t=this.layoutDescription.components[e];this.components[e]=new r(e,t)})),this.updateFromGamepad()}get gripSpace(){return this.xrInputSource.gripSpace}get targetRaySpace(){return this.xrInputSource.targetRaySpace}get data(){const e=[];return Object.values(this.components).forEach((t=>{e.push(t.data)})),e}updateFromGamepad(){Object.values(this.components).forEach((e=>{e.updateFromGamepad(this.xrInputSource.gamepad)}))}},exports.MotionControllerConstants=s,exports.fetchProfile=async function(e,t,s=null,a=!0){if(!e)throw new Error("No xrInputSource supplied");if(!t)throw new Error("No basePath supplied");const n=await i(t);let r;if(e.profiles.some((e=>{const s=n[e];return s&&(r={profileId:e,profilePath:`${t}/${s.path}`,deprecated:!!s.deprecated}),!!r})),!r){if(!s)throw new Error("No matching profile name found");const e=n[s];if(!e)throw new Error(`No matching profile name found and default profile "${s}" missing.`);r={profileId:s,profilePath:`${t}/${e.path}`,deprecated:!!e.deprecated}}const d=await o(r.profilePath);let u;if(a){let t;if(t="any"===e.handedness?d.layouts[Object.keys(d.layouts)[0]]:d.layouts[e.handedness],!t)throw new Error(`No matching handedness, ${e.handedness}, in profile ${r.profileId}`);t.assetPath&&(u=r.profilePath.replace("profile.json",t.assetPath))}return{profile:d,assetPath:u}},exports.fetchProfilesList=i;
@@ -0,0 +1,132 @@
1
+ import type { Object3D, XRGamepad, XRHandedness, XRInputSource } from 'three';
2
+ interface GamepadIndices {
3
+ button: number;
4
+ xAxis?: number;
5
+ yAxis?: number;
6
+ }
7
+ interface VisualResponseDescription {
8
+ componentProperty: string;
9
+ states: string[];
10
+ valueNodeProperty: string;
11
+ valueNodeName: string;
12
+ minNodeName?: string;
13
+ maxNodeName?: string;
14
+ }
15
+ declare type VisualResponses = Record<string, VisualResponseDescription>;
16
+ interface ComponentDescription {
17
+ type: string;
18
+ gamepadIndices: GamepadIndices;
19
+ rootNodeName: string;
20
+ visualResponses: VisualResponses;
21
+ touchPointNodeName?: string;
22
+ }
23
+ interface Components {
24
+ [componentKey: string]: ComponentDescription;
25
+ }
26
+ interface LayoutDescription {
27
+ selectComponentId: string;
28
+ components: Components;
29
+ gamepadMapping: string;
30
+ rootNodeName: string;
31
+ assetPath: string;
32
+ }
33
+ declare type Layouts = Partial<Record<XRHandedness, LayoutDescription>>;
34
+ export interface Profile {
35
+ profileId: string;
36
+ fallbackProfileIds: string[];
37
+ layouts: Layouts;
38
+ }
39
+ interface ProfilesList {
40
+ [profileId: string]: {
41
+ path: string;
42
+ deprecated?: boolean;
43
+ } | undefined;
44
+ }
45
+ declare const MotionControllerConstants: {
46
+ Handedness: Readonly<{
47
+ NONE: string;
48
+ LEFT: string;
49
+ RIGHT: string;
50
+ }>;
51
+ ComponentState: Readonly<{
52
+ DEFAULT: string;
53
+ TOUCHED: string;
54
+ PRESSED: string;
55
+ }>;
56
+ ComponentProperty: Readonly<{
57
+ BUTTON: string;
58
+ X_AXIS: string;
59
+ Y_AXIS: string;
60
+ STATE: string;
61
+ }>;
62
+ ComponentType: Readonly<{
63
+ TRIGGER: string;
64
+ SQUEEZE: string;
65
+ TOUCHPAD: string;
66
+ THUMBSTICK: string;
67
+ BUTTON: string;
68
+ }>;
69
+ ButtonTouchThreshold: number;
70
+ AxisTouchThreshold: number;
71
+ VisualResponseProperty: Readonly<{
72
+ TRANSFORM: string;
73
+ VISIBILITY: string;
74
+ }>;
75
+ };
76
+ declare function fetchProfilesList(basePath: string): Promise<ProfilesList>;
77
+ declare function fetchProfile(xrInputSource: XRInputSource, basePath: string, defaultProfile?: string | null, getAssetPath?: boolean): Promise<{
78
+ profile: Profile;
79
+ assetPath: string | undefined;
80
+ }>;
81
+ declare class VisualResponse implements VisualResponseDescription {
82
+ value: number | boolean;
83
+ componentProperty: string;
84
+ states: string[];
85
+ valueNodeName: string;
86
+ valueNodeProperty: string;
87
+ minNodeName?: string;
88
+ maxNodeName?: string;
89
+ valueNode: Object3D | undefined;
90
+ minNode: Object3D | undefined;
91
+ maxNode: Object3D | undefined;
92
+ constructor(visualResponseDescription: VisualResponseDescription);
93
+ updateFromComponent({ xAxis, yAxis, button, state, }: {
94
+ xAxis?: number;
95
+ yAxis?: number;
96
+ button?: number;
97
+ state: string;
98
+ }): void;
99
+ }
100
+ declare class Component implements ComponentDescription {
101
+ id: string;
102
+ values: {
103
+ state: string;
104
+ button: number | undefined;
105
+ xAxis: number | undefined;
106
+ yAxis: number | undefined;
107
+ };
108
+ type: string;
109
+ gamepadIndices: GamepadIndices;
110
+ rootNodeName: string;
111
+ visualResponses: Record<string, VisualResponse>;
112
+ touchPointNodeName?: string | undefined;
113
+ touchPointNode?: Object3D;
114
+ constructor(componentId: string, componentDescription: ComponentDescription);
115
+ get data(): {
116
+ id: Component['id'];
117
+ } & Component['values'];
118
+ updateFromGamepad(gamepad: XRGamepad): void;
119
+ }
120
+ declare class MotionController {
121
+ xrInputSource: XRInputSource;
122
+ assetUrl: string;
123
+ layoutDescription: LayoutDescription;
124
+ id: string;
125
+ components: Record<string, Component>;
126
+ constructor(xrInputSource: XRInputSource, profile: Profile, assetUrl: string);
127
+ get gripSpace(): XRInputSource['gripSpace'];
128
+ get targetRaySpace(): XRInputSource['targetRaySpace'];
129
+ get data(): Array<Component['data']>;
130
+ updateFromGamepad(): void;
131
+ }
132
+ export { MotionControllerConstants, MotionController, fetchProfile, fetchProfilesList };
@@ -1,3 +1,5 @@
1
+ import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
2
+
1
3
  /**
2
4
  * @webxr-input-profiles/motion-controllers 1.0.0 https://github.com/immersive-web/webxr-input-profiles
3
5
  */
@@ -69,7 +71,7 @@ async function fetchProfile(xrInputSource, basePath, defaultProfile = null, getA
69
71
 
70
72
  const supportedProfilesList = await fetchProfilesList(basePath); // Find the relative path to the first requested profile that is recognized
71
73
 
72
- let match;
74
+ let match = undefined;
73
75
  xrInputSource.profiles.some(profileId => {
74
76
  const supportedProfile = supportedProfilesList[profileId];
75
77
 
@@ -103,7 +105,7 @@ async function fetchProfile(xrInputSource, basePath, defaultProfile = null, getA
103
105
  }
104
106
 
105
107
  const profile = await fetchJsonFile(match.profilePath);
106
- let assetPath;
108
+ let assetPath = undefined;
107
109
 
108
110
  if (getAssetPath) {
109
111
  let layout;
@@ -142,8 +144,8 @@ const defaultComponentValues = {
142
144
  * API) to the range 0 to 1 (for interpolation). Also caps the X, Y values to be bounded within
143
145
  * a circle. This ensures that thumbsticks are not animated outside the bounds of their physical
144
146
  * range of motion and touchpads do not report touch locations off their physical bounds.
145
- * @param {number} x The original x coordinate in the range -1 to 1
146
- * @param {number} y The original y coordinate in the range -1 to 1
147
+ * @param {number | undefined} x The original x coordinate in the range -1 to 1
148
+ * @param {number | undefined} y The original y coordinate in the range -1 to 1
147
149
  */
148
150
 
149
151
  function normalizeAxes(x = 0, y = 0) {
@@ -179,6 +181,26 @@ function normalizeAxes(x = 0, y = 0) {
179
181
 
180
182
  class VisualResponse {
181
183
  constructor(visualResponseDescription) {
184
+ _defineProperty(this, "value", void 0);
185
+
186
+ _defineProperty(this, "componentProperty", void 0);
187
+
188
+ _defineProperty(this, "states", void 0);
189
+
190
+ _defineProperty(this, "valueNodeName", void 0);
191
+
192
+ _defineProperty(this, "valueNodeProperty", void 0);
193
+
194
+ _defineProperty(this, "minNodeName", void 0);
195
+
196
+ _defineProperty(this, "maxNodeName", void 0);
197
+
198
+ _defineProperty(this, "valueNode", void 0);
199
+
200
+ _defineProperty(this, "minNode", void 0);
201
+
202
+ _defineProperty(this, "maxNode", void 0);
203
+
182
204
  this.componentProperty = visualResponseDescription.componentProperty;
183
205
  this.states = visualResponseDescription.states;
184
206
  this.valueNodeName = visualResponseDescription.valueNodeName;
@@ -196,9 +218,9 @@ class VisualResponse {
196
218
  /**
197
219
  * Computes the visual response's interpolation weight based on component state
198
220
  * @param {Object} componentValues - The component from which to update
199
- * @param {number} xAxis - The reported X axis value of the component
200
- * @param {number} yAxis - The reported Y axis value of the component
201
- * @param {number} button - The reported value of the component's button
221
+ * @param {number | undefined} xAxis - The reported X axis value of the component
222
+ * @param {number | undefined} yAxis - The reported Y axis value of the component
223
+ * @param {number | undefined} button - The reported value of the component's button
202
224
  * @param {string} state - The component's active state
203
225
  */
204
226
 
@@ -224,7 +246,7 @@ class VisualResponse {
224
246
  break;
225
247
 
226
248
  case MotionControllerConstants.ComponentProperty.BUTTON:
227
- this.value = this.states.includes(state) ? button : 0;
249
+ this.value = this.states.includes(state) && button ? button : 0;
228
250
  break;
229
251
 
230
252
  case MotionControllerConstants.ComponentProperty.STATE:
@@ -245,10 +267,26 @@ class VisualResponse {
245
267
 
246
268
  class Component {
247
269
  /**
248
- * @param {Object} componentId - Id of the component
249
- * @param {Object} componentDescription - Description of the component to be created
270
+ * @param {string} componentId - Id of the component
271
+ * @param {InputProfileComponent} componentDescription - Description of the component to be created
250
272
  */
251
273
  constructor(componentId, componentDescription) {
274
+ _defineProperty(this, "id", void 0);
275
+
276
+ _defineProperty(this, "values", void 0);
277
+
278
+ _defineProperty(this, "type", void 0);
279
+
280
+ _defineProperty(this, "gamepadIndices", void 0);
281
+
282
+ _defineProperty(this, "rootNodeName", void 0);
283
+
284
+ _defineProperty(this, "visualResponses", void 0);
285
+
286
+ _defineProperty(this, "touchPointNodeName", void 0);
287
+
288
+ _defineProperty(this, "touchPointNode", void 0);
289
+
252
290
  if (!componentId || !componentDescription || !componentDescription.visualResponses || !componentDescription.gamepadIndices || Object.keys(componentDescription.gamepadIndices).length === 0) {
253
291
  throw new Error('Invalid arguments supplied');
254
292
  }
@@ -341,11 +379,21 @@ class Component {
341
379
 
342
380
  class MotionController {
343
381
  /**
344
- * @param {Object} xrInputSource - The XRInputSource to build the MotionController around
345
- * @param {Object} profile - The best matched profile description for the supplied xrInputSource
346
- * @param {Object} assetUrl
382
+ * @param {XRInputSource} xrInputSource - The XRInputSource to build the MotionController around
383
+ * @param {Profile} profile - The best matched profile description for the supplied xrInputSource
384
+ * @param {string} assetUrl
347
385
  */
348
386
  constructor(xrInputSource, profile, assetUrl) {
387
+ _defineProperty(this, "xrInputSource", void 0);
388
+
389
+ _defineProperty(this, "assetUrl", void 0);
390
+
391
+ _defineProperty(this, "layoutDescription", void 0);
392
+
393
+ _defineProperty(this, "id", void 0);
394
+
395
+ _defineProperty(this, "components", void 0);
396
+
349
397
  if (!xrInputSource) {
350
398
  throw new Error('No xrInputSource supplied');
351
399
  }
@@ -354,6 +402,10 @@ class MotionController {
354
402
  throw new Error('No profile supplied');
355
403
  }
356
404
 
405
+ if (!profile.layouts[xrInputSource.handedness]) {
406
+ throw new Error('No layout for ' + xrInputSource.handedness + ' handedness');
407
+ }
408
+
357
409
  this.xrInputSource = xrInputSource;
358
410
  this.assetUrl = assetUrl;
359
411
  this.id = profile.profileId; // Build child components as described in the profile description
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "three-stdlib",
3
- "version": "2.20.5",
3
+ "version": "2.21.0",
4
4
  "private": false,
5
5
  "description": "stand-alone library of threejs examples",
6
6
  "main": "index.cjs.js",
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("three"),o=require("../loaders/GLTFLoader.cjs.js"),t=require("../libs/MotionControllers.cjs.js");class n extends e.Object3D{constructor(){super(),this.motionController=null,this.envMap=null}setEnvironmentMap(e){return this.envMap==e||(this.envMap=e,this.traverse((e=>{e.isMesh&&(e.material.envMap=this.envMap,e.material.needsUpdate=!0)}))),this}updateMatrixWorld(e){super.updateMatrixWorld(e),this.motionController&&(this.motionController.updateFromGamepad(),Object.values(this.motionController.components).forEach((e=>{Object.values(e.visualResponses).forEach((e=>{const{valueNode:o,minNode:n,maxNode:r,value:s,valueNodeProperty:a}=e;o&&(a===t.MotionControllerConstants.VisualResponseProperty.VISIBILITY?o.visible=s:a===t.MotionControllerConstants.VisualResponseProperty.TRANSFORM&&(o.quaternion.slerpQuaternions(n.quaternion,r.quaternion,s),o.position.lerpVectors(n.position,r.position,s)))}))})))}}function r(o,n){!function(o,n){Object.values(o.components).forEach((o=>{const{type:r,touchPointNodeName:s,visualResponses:a}=o;if(r===t.MotionControllerConstants.ComponentType.TOUCHPAD)if(o.touchPointNode=n.getObjectByName(s),o.touchPointNode){const t=new e.SphereGeometry(.001),n=new e.MeshBasicMaterial({color:255}),r=new e.Mesh(t,n);o.touchPointNode.add(r)}else console.warn(`Could not find touch dot, ${o.touchPointNodeName}, in touchpad component ${o.id}`);Object.values(a).forEach((e=>{const{valueNodeName:o,minNodeName:r,maxNodeName:s,valueNodeProperty:a}=e;if(a===t.MotionControllerConstants.VisualResponseProperty.TRANSFORM){if(e.minNode=n.getObjectByName(r),e.maxNode=n.getObjectByName(s),!e.minNode)return void console.warn(`Could not find ${r} in the model`);if(!e.maxNode)return void console.warn(`Could not find ${s} in the model`)}e.valueNode=n.getObjectByName(o),e.valueNode||console.warn(`Could not find ${o} in the model`)}))}))}(o.motionController,n),o.envMap&&n.traverse((e=>{e.isMesh&&(e.material.envMap=o.envMap,e.material.needsUpdate=!0)})),o.add(n)}exports.XRControllerModelFactory=class{constructor(e=null){this.gltfLoader=e,this.path="https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles",this._assetCache={},this.gltfLoader||(this.gltfLoader=new o.GLTFLoader)}createControllerModel(e){const o=new n;let s=null;return e.addEventListener("connected",(e=>{const n=e.data;"tracked-pointer"===n.targetRayMode&&n.gamepad&&t.fetchProfile(n,this.path,"generic-trigger").then((({profile:e,assetPath:a})=>{o.motionController=new t.MotionController(n,e,a);const l=this._assetCache[o.motionController.assetUrl];if(l)s=l.scene.clone(),r(o,s);else{if(!this.gltfLoader)throw new Error("GLTFLoader not set.");this.gltfLoader.setPath(""),this.gltfLoader.load(o.motionController.assetUrl,(e=>{this._assetCache[o.motionController.assetUrl]=e,s=e.scene.clone(),r(o,s)}),null,(()=>{throw new Error(`Asset ${o.motionController.assetUrl} missing or malformed.`)}))}})).catch((e=>{console.warn(e)}))})),e.addEventListener("disconnected",(()=>{o.motionController=null,o.remove(s),s=null})),o}};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/defineProperty"),o=require("three"),t=require("../loaders/GLTFLoader.cjs.js"),n=require("../libs/MotionControllers.cjs.js");function r(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=r(e);const a=(e,t)=>{t.traverse((t=>{t instanceof o.Mesh&&"envMap"in t.material&&(t.material.envMap=e,t.material.needsUpdate=!0)}))};class l extends o.Object3D{constructor(){super(),s.default(this,"envMap",void 0),s.default(this,"motionController",void 0),this.motionController=null,this.envMap=null}setEnvironmentMap(e){return this.envMap==e||(this.envMap=e,a(this.envMap,this)),this}updateMatrixWorld(e){super.updateMatrixWorld(e),this.motionController&&(this.motionController.updateFromGamepad(),Object.values(this.motionController.components).forEach((e=>{Object.values(e.visualResponses).forEach((e=>{const{valueNode:o,minNode:t,maxNode:r,value:s,valueNodeProperty:a}=e;o&&(a===n.MotionControllerConstants.VisualResponseProperty.VISIBILITY&&"boolean"==typeof s?o.visible=s:a===n.MotionControllerConstants.VisualResponseProperty.TRANSFORM&&t&&r&&"number"==typeof s&&(o.quaternion.slerpQuaternions(t.quaternion,r.quaternion,s),o.position.lerpVectors(t.position,r.position,s)))}))})))}}function i(e,t){!function(e,t){Object.values(e.components).forEach((e=>{const{type:r,touchPointNodeName:s,visualResponses:a}=e;if(r===n.MotionControllerConstants.ComponentType.TOUCHPAD&&s)if(e.touchPointNode=t.getObjectByName(s),e.touchPointNode){const t=new o.SphereGeometry(.001),n=new o.MeshBasicMaterial({color:255}),r=new o.Mesh(t,n);e.touchPointNode.add(r)}else console.warn(`Could not find touch dot, ${e.touchPointNodeName}, in touchpad component ${e.id}`);Object.values(a).forEach((e=>{const{valueNodeName:o,minNodeName:r,maxNodeName:s,valueNodeProperty:a}=e;if(a===n.MotionControllerConstants.VisualResponseProperty.TRANSFORM&&r&&s){if(e.minNode=t.getObjectByName(r),e.maxNode=t.getObjectByName(s),!e.minNode)return void console.warn(`Could not find ${r} in the model`);if(!e.maxNode)return void console.warn(`Could not find ${s} in the model`)}e.valueNode=t.getObjectByName(o),e.valueNode||console.warn(`Could not find ${o} in the model`)}))}))}(e.motionController,t),e.envMap&&a(e.envMap,t),e.add(t)}exports.XRControllerModelFactory=class{constructor(e=null){s.default(this,"gltfLoader",void 0),s.default(this,"path",void 0),s.default(this,"_assetCache",void 0),this.gltfLoader=e,this.path="https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles",this._assetCache={},this.gltfLoader||(this.gltfLoader=new t.GLTFLoader)}createControllerModel(e){const o=new l;let t=null;return e.addEventListener("connected",(e=>{const r=e.data;"tracked-pointer"===r.targetRayMode&&r.gamepad&&n.fetchProfile(r,this.path,"generic-trigger").then((({profile:e,assetPath:s})=>{if(!s)throw new Error("no asset path");o.motionController=new n.MotionController(r,e,s);const a=o.motionController.assetUrl,l=this._assetCache[a];if(l)t=l.scene.clone(),i(o,t);else{if(!this.gltfLoader)throw new Error("GLTFLoader not set.");this.gltfLoader.setPath(""),this.gltfLoader.load(o.motionController.assetUrl,(e=>{o.motionController?(this._assetCache[a]=e,t=e.scene.clone(),i(o,t)):console.warn("motionController gone while gltf load, bailing...")}),null,(()=>{throw new Error(`Asset ${a} missing or malformed.`)}))}})).catch((e=>{console.warn(e)}))})),e.addEventListener("disconnected",(()=>{o.motionController=null,t&&o.remove(t),t=null})),o}};
@@ -1,19 +1,19 @@
1
- import { Group, Object3D, Texture } from 'three';
2
-
1
+ import { Object3D } from 'three';
2
+ import type { Texture, Group } from 'three';
3
3
  import { GLTFLoader } from '../loaders/GLTFLoader';
4
-
5
- export class XRControllerModel extends Object3D {
4
+ import { MotionController } from '../libs/MotionControllers';
5
+ declare class XRControllerModel extends Object3D {
6
+ envMap: Texture | null;
7
+ motionController: MotionController | null;
6
8
  constructor();
7
-
8
- motionController: any;
9
-
10
9
  setEnvironmentMap(envMap: Texture): XRControllerModel;
10
+ updateMatrixWorld(force: boolean): void;
11
11
  }
12
-
13
- export class XRControllerModelFactory {
14
- constructor(gltfLoader?: GLTFLoader);
15
- gltfLoader: GLTFLoader | null;
12
+ declare class XRControllerModelFactory {
13
+ gltfLoader: GLTFLoader;
16
14
  path: string;
17
-
15
+ private _assetCache;
16
+ constructor(gltfLoader?: GLTFLoader);
18
17
  createControllerModel(controller: Group): XRControllerModel;
19
18
  }
19
+ export { XRControllerModelFactory };
@@ -1,13 +1,28 @@
1
- import { Object3D, SphereGeometry, MeshBasicMaterial, Mesh } from 'three';
1
+ import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
2
+ import { Object3D, Mesh, SphereGeometry, MeshBasicMaterial } from 'three';
2
3
  import { GLTFLoader } from '../loaders/GLTFLoader.js';
3
4
  import { fetchProfile, MotionController, MotionControllerConstants } from '../libs/MotionControllers.js';
4
5
 
5
6
  const DEFAULT_PROFILES_PATH = 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles';
6
7
  const DEFAULT_PROFILE = 'generic-trigger';
7
8
 
9
+ const applyEnvironmentMap = (envMap, obj) => {
10
+ obj.traverse(child => {
11
+ if (child instanceof Mesh && 'envMap' in child.material) {
12
+ child.material.envMap = envMap;
13
+ child.material.needsUpdate = true;
14
+ }
15
+ });
16
+ };
17
+
8
18
  class XRControllerModel extends Object3D {
9
19
  constructor() {
10
20
  super();
21
+
22
+ _defineProperty(this, "envMap", void 0);
23
+
24
+ _defineProperty(this, "motionController", void 0);
25
+
11
26
  this.motionController = null;
12
27
  this.envMap = null;
13
28
  }
@@ -18,12 +33,7 @@ class XRControllerModel extends Object3D {
18
33
  }
19
34
 
20
35
  this.envMap = envMap;
21
- this.traverse(child => {
22
- if (child.isMesh) {
23
- child.material.envMap = this.envMap;
24
- child.material.needsUpdate = true;
25
- }
26
- });
36
+ applyEnvironmentMap(this.envMap, this);
27
37
  return this;
28
38
  }
29
39
  /**
@@ -52,9 +62,9 @@ class XRControllerModel extends Object3D {
52
62
 
53
63
  if (!valueNode) return; // Calculate the new properties based on the weight supplied
54
64
 
55
- if (valueNodeProperty === MotionControllerConstants.VisualResponseProperty.VISIBILITY) {
65
+ if (valueNodeProperty === MotionControllerConstants.VisualResponseProperty.VISIBILITY && typeof value === 'boolean') {
56
66
  valueNode.visible = value;
57
- } else if (valueNodeProperty === MotionControllerConstants.VisualResponseProperty.TRANSFORM) {
67
+ } else if (valueNodeProperty === MotionControllerConstants.VisualResponseProperty.TRANSFORM && minNode && maxNode && typeof value === 'number') {
58
68
  valueNode.quaternion.slerpQuaternions(minNode.quaternion, maxNode.quaternion, value);
59
69
  valueNode.position.lerpVectors(minNode.position, maxNode.position, value);
60
70
  }
@@ -79,7 +89,7 @@ function findNodes(motionController, scene) {
79
89
  visualResponses
80
90
  } = component;
81
91
 
82
- if (type === MotionControllerConstants.ComponentType.TOUCHPAD) {
92
+ if (type === MotionControllerConstants.ComponentType.TOUCHPAD && touchPointNodeName) {
83
93
  component.touchPointNode = scene.getObjectByName(touchPointNodeName);
84
94
 
85
95
  if (component.touchPointNode) {
@@ -104,7 +114,7 @@ function findNodes(motionController, scene) {
104
114
  valueNodeProperty
105
115
  } = visualResponse; // If animating a transform, find the two nodes to be interpolated between.
106
116
 
107
- if (valueNodeProperty === MotionControllerConstants.VisualResponseProperty.TRANSFORM) {
117
+ if (valueNodeProperty === MotionControllerConstants.VisualResponseProperty.TRANSFORM && minNodeName && maxNodeName) {
108
118
  visualResponse.minNode = scene.getObjectByName(minNodeName);
109
119
  visualResponse.maxNode = scene.getObjectByName(maxNodeName); // If the extents cannot be found, skip this animation
110
120
 
@@ -134,12 +144,7 @@ function addAssetSceneToControllerModel(controllerModel, scene) {
134
144
  findNodes(controllerModel.motionController, scene); // Apply any environment map that the mesh already has set.
135
145
 
136
146
  if (controllerModel.envMap) {
137
- scene.traverse(child => {
138
- if (child.isMesh) {
139
- child.material.envMap = controllerModel.envMap;
140
- child.material.needsUpdate = true;
141
- }
142
- });
147
+ applyEnvironmentMap(controllerModel.envMap, scene);
143
148
  } // Add the glTF scene to the controllerModel.
144
149
 
145
150
 
@@ -148,6 +153,12 @@ function addAssetSceneToControllerModel(controllerModel, scene) {
148
153
 
149
154
  class XRControllerModelFactory {
150
155
  constructor(gltfLoader = null) {
156
+ _defineProperty(this, "gltfLoader", void 0);
157
+
158
+ _defineProperty(this, "path", void 0);
159
+
160
+ _defineProperty(this, "_assetCache", void 0);
161
+
151
162
  this.gltfLoader = gltfLoader;
152
163
  this.path = DEFAULT_PROFILES_PATH;
153
164
  this._assetCache = {}; // If a GLTFLoader wasn't supplied to the constructor create a new one.
@@ -167,8 +178,13 @@ class XRControllerModelFactory {
167
178
  profile,
168
179
  assetPath
169
180
  }) => {
181
+ if (!assetPath) {
182
+ throw new Error('no asset path');
183
+ }
184
+
170
185
  controllerModel.motionController = new MotionController(xrInputSource, profile, assetPath);
171
- const cachedAsset = this._assetCache[controllerModel.motionController.assetUrl];
186
+ const assetUrl = controllerModel.motionController.assetUrl;
187
+ const cachedAsset = this._assetCache[assetUrl];
172
188
 
173
189
  if (cachedAsset) {
174
190
  scene = cachedAsset.scene.clone();
@@ -180,11 +196,16 @@ class XRControllerModelFactory {
180
196
 
181
197
  this.gltfLoader.setPath('');
182
198
  this.gltfLoader.load(controllerModel.motionController.assetUrl, asset => {
183
- this._assetCache[controllerModel.motionController.assetUrl] = asset;
199
+ if (!controllerModel.motionController) {
200
+ console.warn('motionController gone while gltf load, bailing...');
201
+ return;
202
+ }
203
+
204
+ this._assetCache[assetUrl] = asset;
184
205
  scene = asset.scene.clone();
185
206
  addAssetSceneToControllerModel(controllerModel, scene);
186
207
  }, null, () => {
187
- throw new Error(`Asset ${controllerModel.motionController.assetUrl} missing or malformed.`);
208
+ throw new Error(`Asset ${assetUrl} missing or malformed.`);
188
209
  });
189
210
  }
190
211
  }).catch(err => {
@@ -193,7 +214,11 @@ class XRControllerModelFactory {
193
214
  });
194
215
  controller.addEventListener('disconnected', () => {
195
216
  controllerModel.motionController = null;
196
- controllerModel.remove(scene);
217
+
218
+ if (scene) {
219
+ controllerModel.remove(scene);
220
+ }
221
+
197
222
  scene = null;
198
223
  });
199
224
  return controllerModel;