elation-engine 0.9.113 → 0.9.115

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/css/systems/render.css +5 -1
  2. package/package.json +1 -1
  3. package/scripts/assets.js +103 -20
  4. package/scripts/assetworker.js +18 -1
  5. package/scripts/external/holoplay.js +1494 -0
  6. package/scripts/external/octree.js +0 -0
  7. package/scripts/external/three/CSS3DRenderer.js +46 -43
  8. package/scripts/external/three/CubemapToEquirectangular.js +1 -1
  9. package/scripts/external/three/three-extras.js +1553 -392
  10. package/scripts/external/three/three-icosa.js +2575 -0
  11. package/scripts/external/three/three-loaders.js +925 -133
  12. package/scripts/external/three/three-postprocessing.js +3 -3
  13. package/scripts/external/three/three-r116dev.js +50930 -0
  14. package/scripts/external/three/three-spotlighttextures.js +50953 -0
  15. package/scripts/external/three/three-vrm.js +2 -2
  16. package/scripts/external/three/three-working.js +35968 -0
  17. package/scripts/external/three/three.js +38532 -24087
  18. package/scripts/external/three-mesh-bvh.js +5370 -0
  19. package/scripts/external/three-old/BVHLoader.js +406 -0
  20. package/scripts/external/three-old/ColladaLoader.js +5519 -0
  21. package/scripts/external/three-old/ColladaLoader2.js +1694 -0
  22. package/scripts/external/three-old/CubemapToEquirectangular.js +188 -0
  23. package/scripts/external/three-old/DDSLoader.js +269 -0
  24. package/scripts/external/three-old/FBXLoader-mine.js +5063 -0
  25. package/scripts/external/three-old/FBXLoader.js +5112 -0
  26. package/scripts/external/three-old/FlyControls.js +295 -0
  27. package/scripts/external/three-old/GLTF2Loader.js +2950 -0
  28. package/scripts/external/three-old/GLTFLoader.js +2213 -0
  29. package/scripts/external/three-old/JSONLoader.js +435 -0
  30. package/scripts/external/three-old/MTLLoader.js +533 -0
  31. package/scripts/external/three-old/OBJLoader-experimental.js +874 -0
  32. package/scripts/external/three-old/OBJLoader-working.js +727 -0
  33. package/scripts/external/three-old/OBJLoader.js +723 -0
  34. package/scripts/external/three-old/OBJMTLLoader.js +440 -0
  35. package/scripts/external/three-old/OrbitControls.js +592 -0
  36. package/scripts/external/three-old/PLYLoader.js +517 -0
  37. package/scripts/external/three-old/TransformControls.js +1100 -0
  38. package/scripts/external/three-old/VRMLLoader.js +1021 -0
  39. package/scripts/external/three-old/glTFLoader-combined.js +2513 -0
  40. package/scripts/external/three-old/nodethree.js +44018 -0
  41. package/scripts/external/three-old/render/BleachBypassShader.js +64 -0
  42. package/scripts/external/three-old/render/BloomPass.js +116 -0
  43. package/scripts/external/three-old/render/CSS3DRenderer.js +310 -0
  44. package/scripts/external/three-old/render/ClearPass.js +44 -0
  45. package/scripts/external/three-old/render/ConvolutionShader.js +101 -0
  46. package/scripts/external/three-old/render/CopyShader.js +46 -0
  47. package/scripts/external/three-old/render/EffectComposer.js +211 -0
  48. package/scripts/external/three-old/render/FXAAShader.js +88 -0
  49. package/scripts/external/three-old/render/FilmPass.js +60 -0
  50. package/scripts/external/three-old/render/FilmShader.js +104 -0
  51. package/scripts/external/three-old/render/ManualMSAARenderPass.js +168 -0
  52. package/scripts/external/three-old/render/MaskPass.js +97 -0
  53. package/scripts/external/three-old/render/OculusRenderPass.js +84 -0
  54. package/scripts/external/three-old/render/OculusRiftEffect.js +240 -0
  55. package/scripts/external/three-old/render/PortalRenderPass.js +166 -0
  56. package/scripts/external/three-old/render/RecordingPass.js +208 -0
  57. package/scripts/external/three-old/render/RenderPass.js +57 -0
  58. package/scripts/external/three-old/render/SSAOShader.js +259 -0
  59. package/scripts/external/three-old/render/SepiaShader.js +54 -0
  60. package/scripts/external/three-old/render/ShaderPass.js +66 -0
  61. package/scripts/external/three-old/render/VREffect.js +482 -0
  62. package/scripts/external/three-old/shimthree.js +23 -0
  63. package/scripts/external/three-old/stats.js +6 -0
  64. package/scripts/external/three-old/three-88dev.js +45004 -0
  65. package/scripts/external/three-old/three-backgroundoptimization.js +44432 -0
  66. package/scripts/external/three-old/three-updates.js +44735 -0
  67. package/scripts/external/three-old/three-working.js +44719 -0
  68. package/scripts/external/three-old/three.js +44431 -0
  69. package/scripts/external/three-old/threex.rendererstats.js +66 -0
  70. package/scripts/external/three-old/tween.js +13 -0
  71. package/scripts/external/webvr-polyfill-new.js +3497 -0
  72. package/scripts/external/webvr-polyfill-newest.js +3491 -0
  73. package/scripts/external/webvr-polyfill-old.js +6337 -0
  74. package/scripts/geometries.js +2 -2
  75. package/scripts/math.js +6 -6
  76. package/scripts/systems/admin.js +1 -1
  77. package/scripts/systems/controls.js +6 -4
  78. package/scripts/systems/physics.js +10 -10
  79. package/scripts/systems/render.js +58 -20
  80. package/scripts/systems/render2.js +38 -0
  81. package/scripts/things/camera.js +6 -1
  82. package/scripts/things/generic-trackedvectors.js +1875 -0
  83. package/scripts/things/generic.js +3 -4
  84. package/scripts/things/label2d.js +1 -1
  85. package/scripts/things/leapmotion.js +6 -6
  86. package/scripts/things/menu.js +1 -1
  87. package/scripts/things/player-bak.js +638 -0
  88. package/scripts/things/player.js +28 -10
  89. package/scripts/things/skysphere.js +1 -1
  90. package/scripts/things/terrain.js +1 -1
  91. package/scripts/things/text.js +1 -1
@@ -0,0 +1,638 @@
1
+ elation.require(['engine.things.generic', 'engine.things.camera', 'engine.things.label2d', 'engine.things.objecttracker'], function() {
2
+ elation.component.add('engine.things.player', function() {
3
+ this.targetrange = 8;
4
+ this.postinit = function() {
5
+ this.defineProperties({
6
+ height: { type: 'float', default: 2.0 },
7
+ fatness: { type: 'float', default: .25 },
8
+ mass: { type: 'float', default: 10.0 },
9
+ movestrength: { type: 'float', default: 200.0 },
10
+ movespeed: { type: 'float', default: 1.8 },
11
+ runstrength: { type: 'float', default: 250.0 },
12
+ runspeed: { type: 'float', default: 5.4 },
13
+ crouchspeed: { type: 'float', default: 150.0 },
14
+ turnspeed: { type: 'float', default: Math.PI/2 },
15
+ jumpstrength: { type: 'float', default: 300.0 },
16
+ jumptime: { type: 'float', default: 150 },
17
+ movefriction: { type: 'float', default: 4.0 },
18
+ defaultplayer: { type: 'boolean', default: true },
19
+ startposition: { type: 'vector3', default: new THREE.Vector3() },
20
+ startorientation: { type: 'quaternion', default: new THREE.Quaternion() },
21
+ startcameraorientation: { type: 'quaternion', default: new THREE.Quaternion() },
22
+ walking: { type: 'boolean', default: true },
23
+ running: { type: 'boolean', default: false },
24
+ flying: { type: 'boolean', default: false, set: function(key, value) { this.properties.flying = value; this.toggle_flying(value); }},
25
+ });
26
+ this.controlstate = this.engine.systems.controls.addContext('player', {
27
+ 'move_forward': ['keyboard_w', elation.bind(this, this.updateControls)],
28
+ 'move_backward': ['keyboard_s,gamepad_any_axis_1', elation.bind(this, this.updateControls)],
29
+ 'move_left': ['keyboard_a', elation.bind(this, this.updateControls)],
30
+ 'move_right': ['keyboard_d,gamepad_any_axis_0', elation.bind(this, this.updateControls)],
31
+ 'move_up': ['keyboard_r', elation.bind(this, this.updateControls)],
32
+ 'move_down': ['keyboard_f', elation.bind(this, this.updateControls)],
33
+ 'turn_left': ['keyboard_left', elation.bind(this, this.updateControls)],
34
+ 'turn_right': ['keyboard_right,gamepad_any_axis_2', elation.bind(this, this.updateControls)],
35
+ //'mouse_turn': ['mouse_delta_x', elation.bind(this, this.updateMouseControls)],
36
+ //'mouse_pitch': ['mouse_delta_y', elation.bind(this, this.updateMouseControls)],
37
+ 'mouse_look': ['mouse_delta', elation.bind(this, this.updateMouseControls)],
38
+ 'look_up': ['keyboard_up', elation.bind(this, this.updateControls)],
39
+ 'look_down': ['keyboard_down,gamepad_any_axis_3', elation.bind(this, this.updateControls)],
40
+ 'run': ['keyboard_shift,gamepad_any_button_10', elation.bind(this, this.updateControls)],
41
+ 'crouch': ['keyboard_c', elation.bind(this, this.updateControls)],
42
+ //'jump': ['keyboard_space,gamepad_any_button_1', elation.bind(this, this.handleJump)],
43
+ //'toss': ['keyboard_space,gamepad_any_button_0,mouse_button_0', elation.bind(this, this.toss)],
44
+ //'toss_cube': ['keyboard_shift_space,gamepad_any_button_1', elation.bind(this, this.toss_cube)],
45
+ //'use': ['keyboard_e,gamepad_any_button_0,mouse_button_0', elation.bind(this, this.handleUse)],
46
+ //'toggle_flying': ['keyboard_f', elation.bind(this, this.toggle_flying)],
47
+ 'reset_position': ['keyboard_backspace', elation.bind(this, this.reset_position)],
48
+ 'pointerlock': ['mouse_0', elation.bind(this, this.updateControls)],
49
+ });
50
+ // Separate HMD context so it can remain active when player controls are disabled
51
+ this.hmdstate = this.engine.systems.controls.addContext('playerhmd', {
52
+ 'hmd': ['hmd_0', elation.bind(this, this.refresh)],
53
+ 'orientation': ['orientation', elation.bind(this, this.refresh)],
54
+ });
55
+ this.mousedelta = [0,0];
56
+ this.moveVector = new THREE.Vector3();
57
+ this.turnVector = new THREE.Euler(0, 0, 0);
58
+ this.lookVector = new THREE.Euler(0, 0, 0);
59
+ //this.engine.systems.controls.activateContext('player');
60
+ this.engine.systems.controls.activateContext('playerhmd');
61
+
62
+
63
+ this.charging = false;
64
+ this.usegravity = false;
65
+ this.flying = true;
66
+
67
+ this.lights = [];
68
+ this.lightnum = 0;
69
+
70
+ this.target = false;
71
+ this.addTag('player');
72
+ this.viewfrustum = new THREE.Frustum();
73
+ this.viewmatrix = new THREE.Matrix4();
74
+
75
+ elation.events.add(this.engine, 'engine_frame', elation.bind(this, this.engine_frame));
76
+ elation.events.add(this.engine, 'engine_frame', elation.bind(this, this.handleTargeting));
77
+ elation.events.add(this, 'thing_create', elation.bind(this, this.handleCreate));
78
+ elation.events.add(document, "pointerlockchange", elation.bind(this, this.handlePointerLockChange));
79
+ }
80
+ this.createObjectDOM = function() {
81
+ //this.strengthmeter = elation.ui.progressbar(null, elation.html.create({append: document.body, classname: 'player_strengthmeter'}), {orientation: 'vertical'});
82
+ }
83
+ this.getCharge = function() {
84
+ return Math.max(0, Math.min(100, Math.pow((new Date().getTime() - this.charging) / 1000 * 5, 2)));
85
+ }
86
+ this.updateHUD = function(ev) {
87
+ if (this.charging !== false) {
88
+ var charge = this.getCharge();
89
+ this.strengthmeter.set(charge);
90
+ } else if (this.strengthmeter.value != 0) {
91
+ this.strengthmeter.set(0);
92
+ }
93
+ }
94
+ this.toss = function(ev) {
95
+ if (this.holding) {
96
+ if (ev.value == 1) {
97
+ this.charging = new Date().getTime();
98
+ } else if (this.charging) {
99
+ var bounds = this.holding.getBoundingSphere();
100
+ var campos = this.camera.localToWorld(new THREE.Vector3(0,0,-bounds.radius));
101
+ var camdir = this.camera.localToWorld(new THREE.Vector3(0,0,-2)).sub(campos).normalize();
102
+ var velocity = 0 + this.getCharge() / 10;
103
+ camdir.multiplyScalar(velocity);
104
+ camdir.add(this.objects.dynamics.velocity);
105
+ //console.log('pew!', velocity);
106
+ //var foo = this.spawn('ball', 'ball_' + Math.round(Math.random() * 100000), { radius: .125, mass: 1, position: campos, velocity: camdir, lifetime: 30, gravity: true, player_id: this.properties.player_id, tags: 'local_sync' }, true);
107
+ //var foo = this.spawn('ball', 'ball_' + Math.round(Math.random() * 100000), { radius: .08, mass: 1, position: campos, velocity: camdir, lifetime: 30, gravity: this.usegravity, player_id: this.properties.player_id, tags: 'local_sync' }, true);
108
+
109
+ //foo.addTag('enemy');
110
+ this.holding.reparent(this.engine.client.world);
111
+ //this.holding.properties.position.copy(campos);
112
+ this.holding.objects.dynamics.setVelocity(camdir);
113
+ console.log('throw it!', this.holding, campos, camdir);
114
+ this.holding = false;
115
+ this.charging = false;
116
+ }
117
+ } else {
118
+ if (ev.value == 1) {
119
+ this.charging = new Date().getTime();
120
+ } else if (this.charging) {
121
+ var campos = this.camera.localToWorld(new THREE.Vector3(0,0,-1));
122
+ var camdir = this.camera.localToWorld(new THREE.Vector3(0,0,-2)).sub(campos).normalize();
123
+ var velocity = 1 + this.getCharge() / 4;
124
+ camdir.multiplyScalar(velocity);
125
+ camdir.add(this.objects.dynamics.velocity);
126
+ var foo = this.spawn('ball', 'ball_' + Math.round(Math.random() * 100000), { radius: .125, mass: 1, position: campos, velocity: camdir, lifetime: 120, gravity: false, player_id: this.properties.player_id, tags: 'local_sync' }, true);
127
+ }
128
+ }
129
+ }
130
+ this.toss_cube = function(ev) {
131
+ if (ev.value == 1) {
132
+ this.charging = new Date().getTime();
133
+ } else {
134
+ var cam = this.engine.systems.render.views['main'].camera;
135
+ var campos = cam.localToWorld(new THREE.Vector3(0,0,-2));
136
+ var camdir = cam.localToWorld(new THREE.Vector3(0,0,-3)).sub(campos).normalize();
137
+ var velocity = 5 + this.getCharge();
138
+ camdir.multiplyScalar(velocity);
139
+ camdir.add(this.objects.dynamics.velocity);
140
+ //console.log('pew!', velocity);
141
+ var foo = this.spawn('crate', 'crate_' + Math.round(Math.random() * 100000), { mass: 1, position: campos, velocity: camdir, angular: this.getspin(), lifetime: 30, gravity: this.usegravity }, true);
142
+ this.charging = false;
143
+ }
144
+ }
145
+ this.toggle_flying = function(value) {
146
+ if (value === undefined) value = !this.flying;
147
+ //if (ev.value == 1) {
148
+ //this.flying = !this.flying;
149
+ this.properties.flying = value;
150
+ this.usegravity = !this.flying;
151
+ if (this.gravityForce) {
152
+ this.gravityForce.update(new THREE.Vector3(0,(this.usegravity ? -9.8 : 0), 0));
153
+ }
154
+ //}
155
+ }
156
+ this.reset_position = function(ev) {
157
+ if (!ev || ev.value == 1) {
158
+ this.properties.position.copy(this.properties.startposition);
159
+ this.properties.orientation.copy(this.properties.startorientation);
160
+ this.head.properties.orientation.copy(this.properties.startcameraorientation);
161
+ this.properties.velocity.set(0,0,0);
162
+ this.objects.dynamics.angular.set(0,0,0);
163
+ this.engine.systems.controls.calibrateHMDs();
164
+ this.refresh();
165
+ }
166
+ }
167
+ this.getspin = function() {
168
+ //return new THREE.Vector3();
169
+ return new THREE.Vector3((Math.random() - .5) * 4 * Math.PI, (Math.random() - .5) * 4 * Math.PI, (Math.random() - .5) * 4 * Math.PI);
170
+ }
171
+ this.createObject3D = function() {
172
+ this.objects['3d'] = new THREE.Object3D();
173
+ this.ears = new THREE.Object3D();
174
+ //this.camera.rotation.set(-Math.PI/16, 0, 0);
175
+
176
+ return this.objects['3d'];
177
+ }
178
+ this.createChildren = function() {
179
+ // place camera at head height
180
+ this.headconstraint = this.head.objects.dynamics.addConstraint('axis', { axis: new THREE.Vector3(1,0,0), min: -Math.PI/2, max: Math.PI/2 });
181
+ this.reset_position();
182
+ }
183
+ this.createForces = function() {
184
+ this.frictionForce = this.objects.dynamics.addForce("friction", this.properties.movefriction);
185
+ this.gravityForce = this.objects.dynamics.addForce("gravity", new THREE.Vector3(0,0,0));
186
+ this.moveForce = this.objects.dynamics.addForce("static", {});
187
+ this.jumpForce = this.objects.dynamics.addForce("static", {});
188
+ this.objects.dynamics.restitution = 0.1;
189
+ //this.objects.dynamics.setCollider('sphere', {radius: this.properties.fatness, offset: new THREE.Vector3(0, this.fatness, 0)});
190
+ this.objects.dynamics.addConstraint('axis', { axis: new THREE.Vector3(0,1,0) });
191
+ // FIXME - should be in createChildren
192
+ this.createBodyParts();
193
+ // FIXME - the object tracker needs some work. Some systems report tracked objects relative to the world, and some relative to the head
194
+ // The hardcoded offset is also specific to my own personal set-up, and helps to keep leap motion and tracked controllers in sync
195
+ this.tracker = this.neck.spawn('objecttracker', null, {player: this, position: [0, -.05, -.185]});
196
+ this.camera = this.head.spawn('camera', this.name + '_camera', { position: [0,0,0], mass: 0.1, player_id: this.properties.player_id } );
197
+ this.camera.objects['3d'].add(this.ears);
198
+
199
+ //var camhelper = new THREE.CameraHelper(this.camera.camera);
200
+ //this.engine.systems.world.scene['world-3d'].add(camhelper);
201
+ }
202
+ this.createBodyParts = function() {
203
+ this.torso = this.spawn('generic', this.properties.player_id + '_torso', {
204
+ 'position': [0,1,0]
205
+ });
206
+ this.shoulders = this.torso.spawn('generic', this.properties.player_id + '_shoulders', {
207
+ 'position': [0,0.3,-0.2]
208
+ });
209
+ this.neck = this.torso.spawn('generic', this.properties.player_id + '_neck', {
210
+ 'position': [0,0.6,0]
211
+ });
212
+ this.head = this.neck.spawn('generic', this.properties.player_id + '_head', {
213
+ 'position': [0,0,0],
214
+ 'mass': 1
215
+ });
216
+
217
+ this.placeholder_body = new THREE.Mesh(new THREE.CylinderGeometry(this.fatness, this.fatness, this.height), new THREE.MeshPhongMaterial({color: 0xcccccc}));
218
+ this.placeholder_body.position.y = this.height / 2;
219
+ this.placeholder_body.layers.set(1);
220
+ this.objects['3d'].add(this.placeholder_body);
221
+ }
222
+ this.getGroundHeight = function() {
223
+
224
+ }
225
+ this.enable = function() {
226
+ var controls = this.engine.systems.controls;
227
+ this.gravityForce.update(new THREE.Vector3(0,this.usegravity * -9.8 , 0));
228
+ controls.activateContext('player');
229
+
230
+ if (this.engine.systems.render.views.main) {
231
+ //this.engine.systems.render.views.main.disablePicking();
232
+ }
233
+ controls.enablePointerLock(true);
234
+ this.controlstate._reset();
235
+ this.lookVector.set(0,0,0);
236
+ this.turnVector.set(0,0,0);
237
+ this.enableuse = true;
238
+ this.enabled = true;
239
+ controls.requestPointerLock();
240
+
241
+ // FIXME - quick hack to ensure we don't refresh before everything is initialized
242
+ if (this.objects.dynamics) {
243
+ this.refresh();
244
+ }
245
+ }
246
+ this.disable = function() {
247
+ var controls = this.engine.systems.controls;
248
+ controls.deactivateContext('player');
249
+ controls.releasePointerLock();
250
+ if (this.engine.systems.render.views.main) {
251
+ //this.engine.systems.render.views.main.enablePicking();
252
+ }
253
+ this.enableuse = false;
254
+ if (this.objects.dynamics) {
255
+ this.moveForce.update(this.moveVector.set(0,0,0));
256
+ this.gravityForce.update(new THREE.Vector3(0,0,0));
257
+ this.objects.dynamics.angular.set(0,0,0);
258
+ this.objects.dynamics.velocity.set(0,0,0);
259
+ this.objects.dynamics.updateState();
260
+ this.head.objects.dynamics.velocity.set(0,0,0);
261
+ this.head.objects.dynamics.angular.set(0,0,0);
262
+ this.head.objects.dynamics.updateState();
263
+ }
264
+ this.lookVector.set(0,0,0);
265
+ this.turnVector.set(0,0,0);
266
+ this.hideUseDialog();
267
+ this.controlstate._reset();
268
+ this.enabled = false;
269
+ this.refresh();
270
+ }
271
+ this.engine_frame = (function() {
272
+ var _dir = new THREE.Euler(); // Closure scratch variable
273
+ var _moveforce = new THREE.Vector3();
274
+ return function(ev) {
275
+ if (this.camera && (this.enabled || (this.hmdstate && this.hmdstate.hmd))) {
276
+ var diff = ev.data.delta;
277
+ fps = Math.max(1/diff, 20);
278
+ this.moveVector.x = (this.controlstate.move_right - this.controlstate.move_left);
279
+ this.moveVector.y = (this.controlstate.move_up - this.controlstate.move_down);
280
+ this.moveVector.z = -(this.controlstate.move_forward - this.controlstate.move_backward);
281
+
282
+ this.turnVector.y = (this.controlstate.turn_left - this.controlstate.turn_right) * this.properties.turnspeed;
283
+ this.lookVector.x = (this.controlstate.look_up - this.controlstate.look_down) * this.properties.turnspeed;
284
+ //this.turnVector.x = (this.controlstate.look_up - this.controlstate.look_down) * this.properties.turnspeed;
285
+
286
+ if (this.controlstate.crouch) {
287
+ if (this.flying) {
288
+ this.moveVector.y -= 1;
289
+ } else {
290
+ //this.head.properties.position.y = this.properties.height * .4 - this.properties.fatness;
291
+ }
292
+ } else {
293
+ if (!this.flying) {
294
+ //this.head.properties.position.y = this.properties.height * .8 - this.properties.fatness;
295
+ }
296
+ }
297
+
298
+ if (this.moveForce) {
299
+ var moveSpeed = Math.min(1.0, this.moveVector.length());
300
+ //if (moveSpeed !== 0) debugger;
301
+ var dumbhack = false;
302
+ if (this.flying || this.canJump()) {
303
+ this.frictionForce.update(this.properties.movefriction);
304
+ if (this.controlstate['jump']) {
305
+ this.jumpForce.update(new THREE.Vector3(0, this.jumpstrength, 0));
306
+ console.log('jump up!', this.jumpForce.force.toArray());
307
+ setTimeout(elation.bind(this, function() {
308
+ this.jumpForce.update(new THREE.Vector3(0, 0, 0));
309
+ }), this.jumptime);
310
+ }
311
+ var velsq = this.velocity.lengthSq();
312
+ if (this.controlstate.crouch) {
313
+ moveSpeed *= this.crouchspeed;
314
+ } else if (this.controlstate.run) {
315
+ moveSpeed *= this.runstrength;
316
+ } else {
317
+ moveSpeed *= this.movestrength;
318
+ }
319
+
320
+ if (moveSpeed == 0 && velsq > 0) {
321
+ // The player isn't actively moving via control input, so apply opposing force to stop us
322
+ //this.objects.dynamics.worldToLocalDir(this.moveVector.copy(this.velocity).negate());
323
+ //moveSpeed = Math.min(this.moveVector.length(), 1) * this.movestrength;
324
+ //this.moveVector.normalize();
325
+ dumbhack = true;
326
+ }
327
+ } else {
328
+ this.frictionForce.update(0);
329
+ //this.moveVector.set(0,0,0);
330
+ moveSpeed *= this.movestrength / 32;
331
+ }
332
+ _moveforce.copy(this.moveVector).normalize().multiplyScalar(moveSpeed);
333
+ if (this.flying && !dumbhack) {
334
+ _moveforce.applyQuaternion(this.head.properties.orientation);
335
+ }
336
+ this.moveForce.update(_moveforce);
337
+ this.objects.dynamics.setAngularVelocity(this.turnVector);
338
+
339
+ this.head.objects.dynamics.setAngularVelocity(this.lookVector);
340
+ this.head.objects.dynamics.updateState();
341
+ //this.neck.refresh();
342
+ }
343
+ if (this.headconstraint) this.headconstraint.enabled = (!this.vrdevice || !this.vrdevice.isPresenting);
344
+ }
345
+ //this.handleTargeting();
346
+
347
+ //this.refresh();
348
+ //elation.events.fire({type: 'thing_change', element: this});
349
+
350
+ // Store the player's current view frustum so we can do visibility testing in scripts
351
+ this.camera.camera.updateProjectionMatrix(); // FIXME - this should only be needed if camera parameters change
352
+ this.viewfrustum.setFromMatrix(this.viewmatrix.multiplyMatrices(this.camera.camera.projectionMatrix, this.camera.camera.matrixWorldInverse));
353
+ }
354
+ })();
355
+ this.updateHMD = (function() {
356
+ // closure scratch vars
357
+ var standingMatrix = new THREE.Matrix4(),
358
+ tmpvec = new THREE.Vector3(),
359
+ lastheadpos = new THREE.Vector3();
360
+
361
+ return function(vrdevice) {
362
+ var hmd = this.hmdstate.hmd;
363
+ if (vrdevice && (true || vrdevice.isPresenting)) {
364
+ var pose = false;
365
+ if (!this.framedata) {
366
+ this.framedata = (vrdevice.isPolyfilled ? new WebVRPolyfillFrameData() : new VRFrameData());
367
+ }
368
+ if (vrdevice.getFrameData && this.framedata) {
369
+ if (vrdevice.getFrameData(this.framedata)) {
370
+ pose = this.framedata.pose;
371
+ }
372
+ } else if (vrdevice.getPose) {
373
+ pose = vrdevice.getPose();
374
+ }
375
+ if (pose) this.hmdstate.hmd = pose;
376
+ this.vrdevice = vrdevice;
377
+ if (this.headconstraint) this.headconstraint.enabled = false;
378
+
379
+ if (pose.position && !pose.position.includes(NaN)) {
380
+ var pos = this.head.objects.dynamics.position;
381
+ pos.fromArray(pose.position);
382
+ //pos.y += this.properties.height * .8 - this.properties.fatness;
383
+ }
384
+ if (pose.linearVelocity && !pose.linearVelocity.includes(NaN)) {
385
+ this.head.objects.dynamics.velocity.fromArray(pose.linearVelocity);
386
+ } else {
387
+ this.head.objects.dynamics.velocity.set(0,0,0);
388
+ }
389
+ var o = pose.orientation;
390
+ // FIXME - why am I getting NaN / Infinity values here? This makes no sense.
391
+ if (o && !o.includes(NaN) && !o.includes(Infinity) && !o.includes(-Infinity)) {
392
+ this.head.objects.dynamics.orientation.fromArray(o);
393
+ }
394
+ if (pose.angularVelocity) {
395
+ //this.head.objects.dynamics.angular.fromArray(hmd.angularVelocity);
396
+ }
397
+ this.waspresentingvr = true;
398
+ this.head.objects.dynamics.updateState();
399
+ this.refresh();
400
+ } else {
401
+ if (this.headconstraint) this.headconstraint.enabled = true;
402
+ if (this.waspresentingvr) {
403
+ this.resetHead();
404
+ this.waspresentingvr = false;
405
+ }
406
+ }
407
+
408
+ var view = this.engine.systems.render.views.main;
409
+ if (view.size[0] == 0 || view.size[1] == 0) {
410
+ view.getsize();
411
+ }
412
+ //view.mousepos = [view.size[0] / 2, view.size[1] / 2, 0];
413
+ view.pickingactive = true;
414
+
415
+ }
416
+ })();
417
+ this.updateControls = function() {
418
+ }
419
+ this.updateMouseControls = (function() {
420
+ var angular = new THREE.Vector3(),
421
+ tmpquat = new THREE.Quaternion();
422
+
423
+ return function(ev, force) {
424
+ if (this.engine.systems.controls.pointerLockActive || force) {
425
+ var mouselook = ev.data.mouse_look;
426
+ var changed = false;
427
+ if (mouselook[0]) {
428
+ angular.set(0, -mouselook[0] * this.properties.turnspeed / 60, 0);
429
+ var theta = angular.length();
430
+ angular.divideScalar(theta);
431
+ tmpquat.setFromAxisAngle(angular, theta);
432
+ this.properties.orientation.multiply(tmpquat);
433
+ ev.data.mouse_turn = 0;
434
+ ev.data.mouse_look[0] = 0;
435
+ changed = true;
436
+ }
437
+
438
+ if (mouselook[1]) {
439
+ angular.set(-mouselook[1] * this.properties.turnspeed / 60, 0, 0)
440
+ theta = angular.length();
441
+ angular.divideScalar(theta);
442
+ tmpquat.setFromAxisAngle(angular, theta);
443
+ this.head.properties.orientation.multiply(tmpquat);
444
+ ev.data.mouse_pitch = 0;
445
+ ev.data.mouse_look[1] = 0;
446
+ changed = true;
447
+ }
448
+
449
+ if (changed) {
450
+ this.refresh();
451
+ }
452
+ }
453
+ };
454
+ })();
455
+ this.handleCreate = function(ev) {
456
+ if (this.properties.defaultplayer) {
457
+ this.engine.client.setActiveThing(this);
458
+ this.enable();
459
+ }
460
+ }
461
+ this.handleTargeting = function() {
462
+ if (this.enableuse) {
463
+ var targetinfo = this.getUsableTarget('usable');
464
+ if (targetinfo) {
465
+ var target = this.getThingByObject(targetinfo.object);
466
+ if (target !== this.target) {
467
+ this.setUseTarget(target);
468
+ }
469
+ } else if (this.target != false || this.distanceTo(this.target) > this.targetrange) {
470
+ this.setUseTarget(false);
471
+ }
472
+ }
473
+ }
474
+ this.setUseTarget = function(target) {
475
+ if (!target && this.target) {
476
+ // deselect current target
477
+ elation.events.fire({type: 'thing_use_blur', element: this.target, data: this});
478
+ this.target = target;
479
+ this.hideUseDialog();
480
+ } else if (target && !this.target) {
481
+ elation.events.fire({type: 'thing_use_focus', element: target, data: this});
482
+ this.target = target;
483
+ this.showUseDialog('play', target.properties.gamename); // FIXME - hardcoded for arcade games...
484
+ }
485
+ }
486
+ this.handleUse = function(ev) {
487
+ if (this.holding && !(this.target && this.target.canUse(this))) {
488
+ this.toss(ev);
489
+ } else {
490
+ if (ev.value == 1) {
491
+ this.activateUseTarget();
492
+ }
493
+ }
494
+ }
495
+ this.activateUseTarget = function() {
496
+ if (this.target && this.target.canUse(this)) {
497
+ elation.events.fire({type: 'thing_use_activate', element: this.target, data: this});
498
+ //this.disable(); // FIXME - temporary
499
+ }
500
+ }
501
+ this.getUsableTarget = (function() {
502
+ // closure scratch variables
503
+ var _pos = new THREE.Vector3(),
504
+ _dir = new THREE.Vector3(),
505
+ _caster = new THREE.Raycaster(_pos, _dir, .01, this.targetrange);
506
+ return function(tagname) {
507
+ if (!this.camera) return; // FIXME - hack to make sure we don't try to execute if our camera isn't initialized
508
+ var things = (tagname ? this.engine.getThingsByTag(tagname) : this.engine.getThingsByProperty('pickable', true));
509
+ if (things.length > 0) {
510
+ var objects = things.map(function(t) { return t.objects['3d']; });
511
+ // Get my position and direction in world space
512
+ var pos = this.camera.localToWorld(_pos.set(0,0,0));
513
+ var dir = this.camera.localToWorld(_dir.set(0,0,-1)).sub(pos).normalize();
514
+
515
+ var intersects = _caster.intersectObjects(objects, true);
516
+ if (intersects.length > 0) {
517
+ for (var i = 0; i < intersects.length; i++) {
518
+ if (intersects[i].object.visible)
519
+ return intersects[i];
520
+ }
521
+ }
522
+ }
523
+ return false;
524
+ }
525
+ }.bind(this))();
526
+
527
+ this.showUseDialog = function(verb, noun) {
528
+ var useable = this.target.canUse(this);
529
+
530
+ if (useable) {
531
+ var verb = useable.verb || 'use';
532
+ var noun = useable.noun || '';
533
+ var content = 'Press E or click to ' + verb + '\n' + noun;
534
+
535
+ if (!this.uselabel) {
536
+ this.uselabel = this.head.spawn('generic', null, {
537
+ position: [0,-.15,-.5],
538
+ scale: [0.5,0.5,0.5]
539
+ });
540
+ this.toplabel = this.uselabel.spawn('label2d', null, {
541
+ text: 'Press E or click to ' + verb,
542
+ color: 0x00ff00,
543
+ size: 16,
544
+ scale: [.5,.5,.5],
545
+ });
546
+ this.uselabelnoun = this.uselabel.spawn('label2d', null, {
547
+ position: [0,-0.1,0],
548
+ color: 0x000099,
549
+ text: noun,
550
+ size: 64
551
+ });
552
+ } else {
553
+ this.toplabel.setText('Press E or click to ' + verb);
554
+ this.uselabelnoun.setText(noun);
555
+ if (!this.uselabel.parent) {
556
+ this.head.add(this.uselabel);
557
+ }
558
+ }
559
+
560
+ }
561
+
562
+ /*
563
+ // FIXME - hack for arcade games
564
+ if (this.target && !this.target.properties.working) {
565
+ content = 'Sorry, ' + (this.target.properties.gamename || 'this machine') + ' is temporarily out of order!';
566
+ }
567
+ */
568
+
569
+ }
570
+ this.handleJump = function(ev) {
571
+ var keydown = ev.value;
572
+ if (!keydown) {
573
+ this.jumpForce.update(new THREE.Vector3(0, 0, 0));
574
+ }
575
+ }
576
+ this.hideUseDialog = function() {
577
+ if (this.uselabel && this.uselabel.parent) {
578
+ this.uselabel.parent.remove(this.uselabel);
579
+ }
580
+ }
581
+ this.pickup = function(object, force) {
582
+ if (this.holding) {
583
+ //this.holding.reparent(this.engine.systems.world);
584
+ this.charging = 0.0001; // fixme - hardcoded value is silly here, this lets us just drop the item
585
+ this.toss({value: 0});
586
+ }
587
+ this.holding = object;
588
+ object.reparent(this.camera);
589
+ object.properties.position.set(0,-.075,-.15);
590
+ object.properties.velocity.set(0,0,0);
591
+ object.properties.angular.set(0,0,0);
592
+ object.properties.orientation.setFromEuler(new THREE.Euler(Math.PI/2,0,0)); // FIXME - probably not the best way to do this
593
+ }
594
+ this.canJump = (function() {
595
+ // Cast a ray downwards to see if we're touching a surface and can jump
596
+ var _pos = new THREE.Vector3(),
597
+ _dir = new THREE.Vector3(0, -1, 0),
598
+ _caster = new THREE.Raycaster(_pos, _dir, .01, 1 + this.fatness);
599
+ return function(tagname) {
600
+ if (!this.camera) return; // FIXME - hack to make sure we don't try to execute if our camera isn't initialized
601
+ //var things = this.engine.getThingsByProperty('pickable', true);
602
+ var objects = [this.engine.systems.world.scene['colliders']];
603
+ if (objects.length > 0) {
604
+ //var objects = things.map(function(t) { return t.objects['3d']; });
605
+ // Get my position and direction in world space
606
+ var pos = this.localToWorld(_pos.set(0,1,0));
607
+
608
+ var intersects = _caster.intersectObjects(objects, true);
609
+ if (intersects.length > 0) {
610
+ for (var i = 0; i < intersects.length; i++) {
611
+ if (intersects[i].distance <= 1 + this.fatness) {
612
+ return intersects[i];
613
+ }
614
+ }
615
+ }
616
+ }
617
+ return false;
618
+ }
619
+ })();
620
+ this.resetHead = function() {
621
+ this.head.objects.dynamics.position.set(0,0,0);
622
+ this.head.objects.dynamics.velocity.set(0,0,0);
623
+ this.head.objects.dynamics.angular.set(0,0,0);
624
+ this.head.objects.dynamics.orientation.set(0,0,0,1);
625
+ }
626
+ this.handlePointerLockChange = function(ev) {
627
+ if (document.pointerLockElement) {
628
+ this.enable();
629
+ if (document.pointerLockElement.tabIndex == -1) {
630
+ document.pointerLockElement.setAttribute( 'tabindex', 0 );
631
+ }
632
+ document.pointerLockElement.focus();
633
+ } else {
634
+ this.disable();
635
+ }
636
+ }
637
+ }, elation.engine.things.generic);
638
+ });