فهرست منبع

Support for mutli-touch when interacting with multiple gui elements simultaneously

Trevor Baron 7 سال پیش
والد
کامیت
c7038f96a5

+ 1 - 0
dist/preview release/what's new.md

@@ -69,6 +69,7 @@
 - Added promise-based async functions for initWebVRAsync and useStandingMatrixAsync ([trevordev](https://github.com/trevordev))
 - Add stroke (outline) options on GUI text control ([SvenFrankson](https://github.com/SvenFrankson))
 - Add floating point texture support for RenderTargetCubeTexture ([PeapBoy](https://github.com/NicolasBuecher))
+- Support for mutli-touch when interacting with multiple gui elements simultaneously ([trevordev](https://github.com/trevordev))
 
 ## Bug fixes
 

+ 10 - 9
gui/src/advancedDynamicTexture.ts

@@ -20,7 +20,7 @@ module BABYLON.GUI {
         public _lastPickedControl: Control;
         public _lastControlOver: Nullable<Control>;
         public _lastControlDown: Nullable<Control>;
-        public _capturingControl: Nullable<Control>;
+        public _capturingControl: {[pointerId:number]:Control} = {};
         public _shouldBlockPointer: boolean;
         public _layerToDispose: Nullable<Layer>;
         public _linkedControls = new Array<Control>();
@@ -370,7 +370,7 @@ module BABYLON.GUI {
             this._rootContainer._draw(measure, context);
         }
 
-        private _doPicking(x: number, y: number, type: number, buttonIndex: number): void {
+        private _doPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): void {
             var scene = this.getScene();
 
             if (!scene) {
@@ -385,12 +385,12 @@ module BABYLON.GUI {
                 y = y * ((textureSize.height / this._renderScale) / engine.getRenderHeight());
             }
 
-            if (this._capturingControl) {
-                this._capturingControl._processObservables(type, x, y, buttonIndex);
+            if (this._capturingControl[pointerId]) {
+                this._capturingControl[pointerId]._processObservables(type, x, y, pointerId, buttonIndex);
                 return;
             }
 
-            if (!this._rootContainer._processPicking(x, y, type, buttonIndex)) {
+            if (!this._rootContainer._processPicking(x, y, type, pointerId, buttonIndex)) {
 
                 if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
                     if (this._lastControlOver) {
@@ -432,7 +432,7 @@ module BABYLON.GUI {
                 let y = (scene.pointerY / engine.getHardwareScalingLevel() - viewport.y * engine.getRenderHeight()) / viewport.height;
 
                 this._shouldBlockPointer = false;
-                this._doPicking(x, y, pi.type, pi.event.button);
+                this._doPicking(x, y, pi.type, (pi.event as PointerEvent).pointerId || 0, pi.event.button);
 
                 pi.skipOnPointerObservable = this._shouldBlockPointer;
             });
@@ -451,17 +451,18 @@ module BABYLON.GUI {
                     && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
                     return;
                 }
-
+                var pointerId = (pi.event as PointerEvent).pointerId || 0;
                 if (pi.pickInfo && pi.pickInfo.hit && pi.pickInfo.pickedMesh === mesh) {
                     var uv = pi.pickInfo.getTextureCoordinates();
 
                     if (uv) {
                         let size = this.getSize();
-                        this._doPicking(uv.x * size.width, (1.0 - uv.y) * size.height, pi.type, pi.event.button);
+                        
+                        this._doPicking(uv.x * size.width, (1.0 - uv.y) * size.height, pi.type, pointerId, pi.event.button);
                     }
                 } else if (pi.type === BABYLON.PointerEventTypes.POINTERUP) {
                     if (this._lastControlDown) {
-                        this._lastControlDown.forcePointerUp();
+                        this._lastControlDown.forcePointerUp(pointerId);
                     }
                     this._lastControlDown = null;
 

+ 6 - 6
gui/src/controls/button.ts

@@ -37,7 +37,7 @@ module BABYLON.GUI {
         }
 
         // While being a container, the button behaves like a control.
-        public _processPicking(x: number, y: number, type: number, buttonIndex: number): boolean {
+        public _processPicking(x: number, y: number, type: number, pointerId:number, buttonIndex: number): boolean {
             if (!this.isHitTestVisible || !this.isVisible || this.notRenderable) {
                 return false;
             }
@@ -46,7 +46,7 @@ module BABYLON.GUI {
                 return false;
             }
 
-            this._processObservables(type, x, y, buttonIndex);
+            this._processObservables(type, x, y, pointerId, buttonIndex);
 
             return true;
         }
@@ -71,8 +71,8 @@ module BABYLON.GUI {
             super._onPointerOut(target);
         }
 
-        public _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean {
-            if (!super._onPointerDown(target, coordinates, buttonIndex)) {
+        public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
+            if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
                 return false;
             }
 
@@ -84,12 +84,12 @@ module BABYLON.GUI {
             return true;
         }
 
-        public _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void {
+        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): void {
             if (this.pointerUpAnimation) {
                 this.pointerUpAnimation();
             }
 
-            super._onPointerUp(target, coordinates, buttonIndex);
+            super._onPointerUp(target, coordinates, pointerId, buttonIndex);
         }        
 
         // Statics

+ 2 - 2
gui/src/controls/checkbox.ts

@@ -115,8 +115,8 @@ module BABYLON.GUI {
         }
 
         // Events
-        public _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean {
-            if (!super._onPointerDown(target, coordinates, buttonIndex)) {
+        public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
+            if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
                 return false;
             }
 

+ 6 - 6
gui/src/controls/colorpicker.ts

@@ -377,8 +377,8 @@ module BABYLON.GUI {
             return false;
         }
 
-        public _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean {
-            if (!super._onPointerDown(target, coordinates, buttonIndex)) {
+        public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
+            if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
                 return false;
             }            
 
@@ -394,7 +394,7 @@ module BABYLON.GUI {
             }
 
             this._updateValueFromPointer(coordinates.x, coordinates.y);
-            this._host._capturingControl = this;
+            this._host._capturingControl[pointerId] = this;
 
             return true;
         }
@@ -407,11 +407,11 @@ module BABYLON.GUI {
             super._onPointerMove(target, coordinates);
         }
 
-        public _onPointerUp (target: Control, coordinates: Vector2, buttonIndex: number): void {
+        public _onPointerUp (target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): void {
             this._pointerIsDown = false;
             
-            this._host._capturingControl = null;
-            super._onPointerUp(target, coordinates, buttonIndex);
+            delete this._host._capturingControl[pointerId];
+            super._onPointerUp(target, coordinates, pointerId, buttonIndex);
         }     
     }    
 }

+ 3 - 3
gui/src/controls/container.ts

@@ -175,7 +175,7 @@ module BABYLON.GUI {
             }
         }
 
-        public _processPicking(x: number, y: number, type: number, buttonIndex: number): boolean {
+        public _processPicking(x: number, y: number, type: number, pointerId:number, buttonIndex: number): boolean {
             if (!this.isVisible || this.notRenderable) {
                 return false;
             }
@@ -187,7 +187,7 @@ module BABYLON.GUI {
             // Checking backwards to pick closest first
             for (var index = this._children.length - 1; index >= 0; index--) {
                 var child = this._children[index];
-                if (child._processPicking(x, y, type, buttonIndex)) {
+                if (child._processPicking(x, y, type, pointerId, buttonIndex)) {
                     return true;
                 }
             }
@@ -196,7 +196,7 @@ module BABYLON.GUI {
                 return false;
             }
 
-            return this._processObservables(type, x, y, buttonIndex);
+            return this._processObservables(type, x, y, pointerId, buttonIndex);
         }
 
         protected _clipForChildren(context: CanvasRenderingContext2D): void {

+ 22 - 11
gui/src/controls/control.ts

@@ -46,6 +46,7 @@ module BABYLON.GUI {
         private _downCount = 0;
         private _enterCount = 0;
         private _doNotRender = false;
+        private _downPointerIds:{[id:number] : boolean} = {};
 
         public isHitTestVisible = true;
         public isPointerBlocker = false;
@@ -859,7 +860,7 @@ module BABYLON.GUI {
             return true;
         }
 
-        public _processPicking(x: number, y: number, type: number, buttonIndex: number): boolean {
+        public _processPicking(x: number, y: number, type: number, pointerId:number, buttonIndex: number): boolean {
             if (!this.isHitTestVisible || !this.isVisible || this._doNotRender) {
                 return false;
             }
@@ -868,7 +869,7 @@ module BABYLON.GUI {
                 return false;
             }
 
-            this._processObservables(type, x, y, buttonIndex);
+            this._processObservables(type, x, y, pointerId, buttonIndex);
 
             return true;
         }
@@ -901,33 +902,43 @@ module BABYLON.GUI {
             if (canNotify && this.parent != null) this.parent._onPointerOut(target);
         }
 
-        public _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean {
+        public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
             if (this._downCount !== 0) {
                 return false;
             }
 
             this._downCount++;
 
+            this._downPointerIds[pointerId] = true;
+
             var canNotify: boolean = this.onPointerDownObservable.notifyObservers(new Vector2WithInfo(coordinates, buttonIndex), -1, target, this);
 
-            if (canNotify && this.parent != null) this.parent._onPointerDown(target, coordinates, buttonIndex);
+            if (canNotify && this.parent != null) this.parent._onPointerDown(target, coordinates, pointerId, buttonIndex);
 
             return true;
         }
 
-        public _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void {
+        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): void {
             this._downCount = 0;
 
+            delete this._downPointerIds[pointerId];
+
             var canNotify: boolean = this.onPointerUpObservable.notifyObservers(new Vector2WithInfo(coordinates, buttonIndex), -1, target, this);
 
-            if (canNotify && this.parent != null) this.parent._onPointerUp(target, coordinates, buttonIndex);
+            if (canNotify && this.parent != null) this.parent._onPointerUp(target, coordinates, pointerId, buttonIndex);
         }
 
-        public forcePointerUp() {
-            this._onPointerUp(this, Vector2.Zero(), 0);
+        public forcePointerUp(pointerId:Nullable<number> = null) {
+            if(pointerId !== null){
+                this._onPointerUp(this, Vector2.Zero(), pointerId, 0);
+            }else{
+                for(var key in this._downPointerIds){
+                    this._onPointerUp(this, Vector2.Zero(), +key as number, 0);
+                }
+            }
         }
 
-        public _processObservables(type: number, x: number, y: number, buttonIndex: number): boolean {
+        public _processObservables(type: number, x: number, y: number, pointerId:number, buttonIndex: number): boolean {
             this._dummyVector2.copyFromFloats(x, y);
             if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
                 this._onPointerMove(this, this._dummyVector2);
@@ -946,7 +957,7 @@ module BABYLON.GUI {
             }
 
             if (type === BABYLON.PointerEventTypes.POINTERDOWN) {
-                this._onPointerDown(this, this._dummyVector2, buttonIndex);
+                this._onPointerDown(this, this._dummyVector2, pointerId, buttonIndex);
                 this._host._lastControlDown = this;
                 this._host._lastPickedControl = this;
                 return true;
@@ -954,7 +965,7 @@ module BABYLON.GUI {
 
             if (type === BABYLON.PointerEventTypes.POINTERUP) {
                 if (this._host._lastControlDown) {
-                    this._host._lastControlDown._onPointerUp(this, this._dummyVector2, buttonIndex);
+                    this._host._lastControlDown._onPointerUp(this, this._dummyVector2, pointerId, buttonIndex);
                 }
                 this._host._lastControlDown = null;
                 return true;

+ 4 - 4
gui/src/controls/inputText.ts

@@ -432,8 +432,8 @@ module BABYLON.GUI {
             context.restore();
         }
 
-        public _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean {
-            if (!super._onPointerDown(target, coordinates, buttonIndex)) {
+        public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
+            if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
                 return false;
             }
 
@@ -449,8 +449,8 @@ module BABYLON.GUI {
             return true;
         }
 
-        public _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void {
-            super._onPointerUp(target, coordinates, buttonIndex);
+        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): void {
+            super._onPointerUp(target, coordinates, pointerId, buttonIndex);
         }
 
         public dispose() {

+ 2 - 2
gui/src/controls/radioButton.ts

@@ -144,8 +144,8 @@ module BABYLON.GUI {
         }
 
         // Events
-        public _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean {
-            if (!super._onPointerDown(target, coordinates, buttonIndex)) {
+        public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
+            if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
                 return false;
             }
             this.isChecked = !this.isChecked;

+ 6 - 6
gui/src/controls/slider.ts

@@ -266,15 +266,15 @@ module BABYLON.GUI {
             this.value = this._minimum + ((x - this._currentMeasure.left) / this._currentMeasure.width) * (this._maximum - this._minimum);
         }
 
-        public _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean {
-            if (!super._onPointerDown(target, coordinates, buttonIndex)) {
+        public _onPointerDown(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): boolean {
+            if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex)) {
                 return false;
             }
 
             this._pointerIsDown = true;
 
             this._updateValueFromPointer(coordinates.x, coordinates.y);
-            this._host._capturingControl = this;
+            this._host._capturingControl[pointerId] = this;
 
             return true;
         }
@@ -287,11 +287,11 @@ module BABYLON.GUI {
             super._onPointerMove(target, coordinates);
         }
 
-        public _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void {
+        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): void {
             this._pointerIsDown = false;
 
-            this._host._capturingControl = null;
-            super._onPointerUp(target, coordinates, buttonIndex);
+            delete this._host._capturingControl[pointerId];
+            super._onPointerUp(target, coordinates, pointerId, buttonIndex);
         }
     }
 }