|
14 | 14 | this.handRight = new XRHandData();
|
15 | 15 | this.viewerHitTestPose = new XRHitPoseData();
|
16 | 16 | this.frameNumber = 0;
|
17 |
| - this.handHeldMove = false; |
18 |
| - this.xrData = null; |
| 17 | + this.touchIDs = []; |
| 18 | + this.touches = []; |
| 19 | + this.CreateTouch = function (pageElement, xPercentage, yPercentage) { |
| 20 | + let touchID = 0; |
| 21 | + while (this.touchIDs.includes(touchID)) |
| 22 | + { |
| 23 | + touchID++; |
| 24 | + } |
| 25 | + let touch = new XRTouch(touchID, pageElement, xPercentage, yPercentage); |
| 26 | + this.touchIDs.push(touchID); |
| 27 | + this.touches.push(touch); |
| 28 | + return touch; |
| 29 | + } |
| 30 | + this.RemoveTouch = function (touch) { |
| 31 | + touch.ended = true; |
| 32 | + this.touchIDs = this.touchIDs.filter(function(item) { |
| 33 | + return item !== touch.identifier |
| 34 | + }); |
| 35 | + this.touches = this.touches.filter(function(item) { |
| 36 | + return item !== touch |
| 37 | + }); |
| 38 | + } |
| 39 | + this.SendTouchEvent = function(JSEventsObject, eventID, eventName, target, changedTouches) { |
| 40 | + let touchEvent = new XRTouchEvent(eventName, target, this.touches, this.touches, changedTouches); |
| 41 | + JSEventsObject.eventHandlers[eventID].eventListenerFunc(touchEvent); |
| 42 | + } |
19 | 43 | }
|
20 | 44 |
|
21 | 45 | function XRControllerData() {
|
|
77 | 101 | return start + (end - start) * percentage;
|
78 | 102 | }
|
79 | 103 |
|
80 |
| - function XRMouseEvent(eventName, pageElement, xPercentage, yPercentage, buttonNumber) { |
| 104 | + function XRTouch(touchID, pageElement, xPercentage, yPercentage) { |
| 105 | + this.identifier = touchID; |
| 106 | + this.ended = false; |
81 | 107 | let rect = pageElement.getBoundingClientRect();
|
82 |
| - this.type = eventName; |
83 | 108 | // It was pageElement.size / window.devicePixelRatio, but now we treat devicePixelRatio in XR session as 1
|
84 | 109 | this.clientX = lerp(rect.left, rect.left + pageElement.width / 1, xPercentage);
|
85 | 110 | this.clientY = lerp(rect.top, rect.top + pageElement.height / 1, yPercentage);
|
|
95 | 120 | this.screenY = this.clientY;
|
96 | 121 | this.movementX = 0; // diff between movements
|
97 | 122 | this.movementY = 0; // diff between movements
|
98 |
| - this.button = 0; // 0 none or main, 1 middle, 2 secondary |
99 |
| - this.buttons = 0; // 0 none, 1 main, 4 middle, 2 secondary |
100 |
| - switch (buttonNumber) |
101 |
| - { |
102 |
| - case -1: |
103 |
| - this.button = 0; |
104 |
| - this.buttons = 0; |
105 |
| - break; |
106 |
| - case 0: |
107 |
| - this.button = 0; |
108 |
| - this.buttons = 1; |
109 |
| - break; |
110 |
| - case 1: |
111 |
| - this.button = 1; |
112 |
| - this.buttons = 4; |
113 |
| - break; |
114 |
| - case 2: |
115 |
| - this.button = 2; |
116 |
| - this.buttons = 2; |
117 |
| - break; |
| 123 | + this.UpdateTouch = function (pageElement, xPercentage, yPercentage) { |
| 124 | + let rect = pageElement.getBoundingClientRect(); |
| 125 | + let newClientX = lerp(rect.left, rect.left + pageElement.width / 1, xPercentage); |
| 126 | + let newClientY = lerp(rect.top, rect.top + pageElement.height / 1, yPercentage); |
| 127 | + this.movementX = newClientX-this.clientX; |
| 128 | + this.movementY = newClientY-this.clientY; |
| 129 | + this.clientX = newClientX; |
| 130 | + this.clientY = newClientY; |
| 131 | + this.layerX = this.clientX; |
| 132 | + this.layerY = this.clientY; |
| 133 | + this.offsetX = this.clientX; |
| 134 | + this.offsetY = this.clientY; |
| 135 | + this.pageX = this.clientX; |
| 136 | + this.pageY = this.clientY; |
| 137 | + this.x = this.clientX; |
| 138 | + this.y = this.clientY; |
| 139 | + this.screenX = this.clientX; |
| 140 | + this.screenY = this.clientY; |
| 141 | + } |
| 142 | + this.HasMovement = function () { |
| 143 | + return (this.movementX != 0 || this.movementY != 0); |
| 144 | + } |
| 145 | + this.ResetMovement = function () { |
| 146 | + this.movementX = 0; |
| 147 | + this.movementY = 0; |
118 | 148 | }
|
| 149 | + } |
| 150 | + |
| 151 | + function XRTouchEvent(eventName, target, touches, targetTouchs, changedTouches) { |
| 152 | + this.type = eventName; |
| 153 | + this.target = target; |
| 154 | + this.touches = touches; |
| 155 | + this.targetTouches = targetTouchs; |
| 156 | + this.changedTouches = changedTouches; |
119 | 157 | this.ctrlKey = false;
|
120 | 158 | this.altKey = false;
|
121 | 159 | this.metaKey = false;
|
122 | 160 | this.shiftKey = false;
|
123 |
| - this.detail = 0; |
| 161 | + this.preventDefault = function () {}; |
124 | 162 | }
|
125 | 163 |
|
126 | 164 | function XRManager() {
|
|
259 | 297 | this.viewerHitTestSource.cancel();
|
260 | 298 | this.viewerHitTestSource = null;
|
261 | 299 | }
|
| 300 | + |
| 301 | + this.removeRemainingTouches(); |
262 | 302 |
|
263 | 303 | this.xrData.controllerA.enabled = 0;
|
264 | 304 | this.xrData.controllerB.enabled = 0;
|
|
295 | 335 | });
|
296 | 336 | }
|
297 | 337 |
|
| 338 | + XRManager.prototype.removeRemainingTouches = function () { |
| 339 | + while (this.xrData.touches.length > 0) |
| 340 | + { |
| 341 | + let touch = this.xrData.touches[0]; |
| 342 | + this.xrData.RemoveTouch(touch); |
| 343 | + this.xrData.SendTouchEvent(this.JSEventsObject, 8, "touchend", this.canvas, [touch]); |
| 344 | + } |
| 345 | + } |
| 346 | + |
298 | 347 | XRManager.prototype.onInputSourceEvent = function (xrInputSourceEvent) {
|
299 | 348 | if (xrInputSourceEvent.type && xrInputSourceEvent.inputSource
|
300 | 349 | && xrInputSourceEvent.inputSource.handedness != 'none') {
|
|
345 | 394 | } else {
|
346 | 395 | let xPercentage = 0.5;
|
347 | 396 | let yPercentage = 0.5;
|
348 |
| - if (xrInputSourceEvent.inputSource && |
349 |
| - xrInputSourceEvent.inputSource.gamepad && |
350 |
| - xrInputSourceEvent.inputSource.gamepad.axes) { |
351 |
| - xPercentage = (xrInputSourceEvent.inputSource.gamepad.axes[0] + 1.0) * 0.5; |
352 |
| - yPercentage = (xrInputSourceEvent.inputSource.gamepad.axes[1] + 1.0) * 0.5; |
353 |
| - } |
354 |
| - switch (xrInputSourceEvent.type) { |
355 |
| - case "select": // mousemove 5 |
356 |
| - this.JSEventsObject.eventHandlers[5].eventListenerFunc( |
357 |
| - new XRMouseEvent("mousemove", this.canvas, xPercentage, yPercentage, 0)); |
358 |
| - break; |
359 |
| - case "selectstart": // mousedown 4 |
360 |
| - this.xrData.handHeldMove = true; |
361 |
| - this.JSEventsObject.eventHandlers[5].eventListenerFunc( |
362 |
| - new XRMouseEvent("mousemove", this.canvas, xPercentage, yPercentage, 0)); |
363 |
| - this.JSEventsObject.eventHandlers[4].eventListenerFunc( |
364 |
| - new XRMouseEvent("mousedown", this.canvas, xPercentage, yPercentage, 0)); |
365 |
| - break; |
366 |
| - case "selectend": // mouseup 3 |
367 |
| - this.xrData.handHeldMove = false; |
368 |
| - this.JSEventsObject.eventHandlers[3].eventListenerFunc( |
369 |
| - new XRMouseEvent("mouseup", this.canvas, xPercentage, yPercentage, 0)); |
370 |
| - break; |
| 397 | + let inputSource = xrInputSourceEvent.inputSource; |
| 398 | + if (inputSource) { |
| 399 | + if (inputSource.gamepad && |
| 400 | + inputSource.gamepad.axes) { |
| 401 | + xPercentage = (inputSource.gamepad.axes[0] + 1.0) * 0.5; |
| 402 | + yPercentage = (inputSource.gamepad.axes[1] + 1.0) * 0.5; |
| 403 | + } |
| 404 | + switch (xrInputSourceEvent.type) { |
| 405 | + case "select": // 9 touchmove |
| 406 | + // no need to call touchmove here |
| 407 | + break; |
| 408 | + case "selectstart": // 7 touchstart |
| 409 | + inputSource.xrTouchObject = this.xrData.CreateTouch(this.canvas, xPercentage, yPercentage); |
| 410 | + this.xrData.SendTouchEvent(this.JSEventsObject, 7, "touchstart", this.canvas, [inputSource.xrTouchObject]) |
| 411 | + break; |
| 412 | + case "selectend": // 8 touchend |
| 413 | + this.xrData.RemoveTouch(inputSource.xrTouchObject); |
| 414 | + this.xrData.SendTouchEvent(this.JSEventsObject, 8, "touchend", this.canvas, [inputSource.xrTouchObject]); |
| 415 | + inputSource.xrTouchObject = null; |
| 416 | + break; |
| 417 | + } |
371 | 418 | }
|
372 | 419 | }
|
373 | 420 | }
|
|
506 | 553 | xrData.handRight.frame = xrData.frameNumber;
|
507 | 554 | xrData.controllerA.frame = xrData.frameNumber;
|
508 | 555 | xrData.controllerB.frame = xrData.frameNumber;
|
509 |
| - if (!inputSources || !inputSources.length) { |
| 556 | + if (!inputSources || !inputSources.length || inputSources.length == 0) { |
| 557 | + this.removeRemainingTouches(); |
510 | 558 | return;
|
511 | 559 | }
|
| 560 | + let touchesToSend = []; |
512 | 561 | for (var i = 0; i < inputSources.length; i++) {
|
513 | 562 | let inputSource = inputSources[i];
|
514 | 563 | // Show the input source if it has a grip space
|
|
635 | 684 | xrData.controllerB = controller;
|
636 | 685 | }
|
637 | 686 | }
|
638 |
| - } else if (xrData.handHeldMove && inputSource.gamepad && inputSource.gamepad.axes) { |
639 |
| - if (xrData.handHeldMove) |
640 |
| - { |
641 |
| - this.JSEventsObject.eventHandlers[5].eventListenerFunc( |
642 |
| - new XRMouseEvent("mousemove", this.canvas, |
643 |
| - (inputSource.gamepad.axes[0] + 1.0) * 0.5, |
644 |
| - (inputSource.gamepad.axes[1] + 1.0) * 0.5, 0)); |
645 |
| - } |
| 687 | + } else if (inputSource.xrTouchObject && !inputSource.xrTouchObject.ended && inputSource.gamepad && inputSource.gamepad.axes) { |
| 688 | + inputSource.xrTouchObject.UpdateTouch( this.canvas, |
| 689 | + (inputSource.gamepad.axes[0] + 1.0) * 0.5, |
| 690 | + (inputSource.gamepad.axes[1] + 1.0) * 0.5); |
| 691 | + if (inputSource.xrTouchObject.HasMovement()) { |
| 692 | + touchesToSend.push(inputSource.xrTouchObject); |
| 693 | + } |
| 694 | + } |
| 695 | + } |
| 696 | + if (touchesToSend.length > 0) { |
| 697 | + this.xrData.SendTouchEvent(this.JSEventsObject, 9, "touchmove", this.canvas, touchesToSend); |
| 698 | + for (var i = 0; i < touchesToSend.length; i++) { |
| 699 | + touchesToSend[i].ResetMovement(); |
646 | 700 | }
|
647 | 701 | }
|
648 | 702 | }
|
|
737 | 791 | this.ctx.bindFramebuffer(this.ctx.FRAMEBUFFER, glLayer.framebuffer);
|
738 | 792 | if (session.isAR) {
|
739 | 793 | this.ctx.dontClearOnFrameStart = true;
|
| 794 | + this.ctx.clear(this.ctx.STENCIL_BUFFER_BIT | this.ctx.DEPTH_BUFFER_BIT); |
740 | 795 | } else {
|
741 | 796 | this.ctx.clear(this.ctx.COLOR_BUFFER_BIT | this.ctx.DEPTH_BUFFER_BIT);
|
742 | 797 | }
|
|
847 | 902 | leftRect.w = (viewport.width / glLayer.framebufferWidth) * (glLayer.framebufferWidth / this.canvas.width);
|
848 | 903 | leftRect.h = (viewport.height / glLayer.framebufferHeight) * (glLayer.framebufferHeight / this.canvas.height);
|
849 | 904 | }
|
850 |
| - } else if (view.eye === 'right') { |
| 905 | + } else if (view.eye === 'right' && viewport.width != 0 && viewport.height != 0) { |
851 | 906 | eyeCount = 2;
|
852 | 907 | if (viewport) {
|
853 | 908 | rightRect.x = (viewport.x / glLayer.framebufferWidth) * (glLayer.framebufferWidth / this.canvas.width);
|
|
0 commit comments