|
@@ -7461,6 +7461,7 @@ var BABYLON;
|
|
this.bv = 0;
|
|
this.bv = 0;
|
|
this.faceId = -1;
|
|
this.faceId = -1;
|
|
this.subMeshId = 0;
|
|
this.subMeshId = 0;
|
|
|
|
+ this.pickedSprite = null;
|
|
}
|
|
}
|
|
// Methods
|
|
// Methods
|
|
PickingInfo.prototype.getNormal = function (useWorldCoordinates, useVerticesNormals) {
|
|
PickingInfo.prototype.getNormal = function (useWorldCoordinates, useVerticesNormals) {
|
|
@@ -12846,11 +12847,15 @@ var BABYLON;
|
|
// Pointers handling
|
|
// Pointers handling
|
|
Scene.prototype.attachControl = function () {
|
|
Scene.prototype.attachControl = function () {
|
|
var _this = this;
|
|
var _this = this;
|
|
|
|
+ var spritePredicate = function (sprite) {
|
|
|
|
+ return sprite.isPickable && sprite.actionManager && sprite.actionManager.hasPickTriggers;
|
|
|
|
+ };
|
|
this._onPointerMove = function (evt) {
|
|
this._onPointerMove = function (evt) {
|
|
var canvas = _this._engine.getRenderingCanvas();
|
|
var canvas = _this._engine.getRenderingCanvas();
|
|
_this._updatePointerPosition(evt);
|
|
_this._updatePointerPosition(evt);
|
|
|
|
+ // Meshes
|
|
var pickResult = _this.pick(_this._pointerX, _this._pointerY, function (mesh) { return mesh.isPickable && mesh.isVisible && mesh.isReady(); }, false, _this.cameraToUseForPointers);
|
|
var pickResult = _this.pick(_this._pointerX, _this._pointerY, function (mesh) { return mesh.isPickable && mesh.isVisible && mesh.isReady(); }, false, _this.cameraToUseForPointers);
|
|
- if (pickResult.hit) {
|
|
|
|
|
|
+ if (pickResult.hit && pickResult.pickedMesh) {
|
|
_this._meshUnderPointer = pickResult.pickedMesh;
|
|
_this._meshUnderPointer = pickResult.pickedMesh;
|
|
_this.setPointerOverMesh(pickResult.pickedMesh);
|
|
_this.setPointerOverMesh(pickResult.pickedMesh);
|
|
if (_this._meshUnderPointer.actionManager && _this._meshUnderPointer.actionManager.hasPointerTriggers) {
|
|
if (_this._meshUnderPointer.actionManager && _this._meshUnderPointer.actionManager.hasPointerTriggers) {
|
|
@@ -12861,21 +12866,29 @@ var BABYLON;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
|
|
+ // Sprites
|
|
|
|
+ pickResult = _this.pickSprite(_this._pointerX, _this._pointerY, spritePredicate, false, _this.cameraToUseForPointers);
|
|
|
|
+ if (pickResult.hit && pickResult.pickedSprite) {
|
|
|
|
+ canvas.style.cursor = "pointer";
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // Restore pointer
|
|
_this.setPointerOverMesh(null);
|
|
_this.setPointerOverMesh(null);
|
|
canvas.style.cursor = "";
|
|
canvas.style.cursor = "";
|
|
_this._meshUnderPointer = null;
|
|
_this._meshUnderPointer = null;
|
|
}
|
|
}
|
|
};
|
|
};
|
|
this._onPointerDown = function (evt) {
|
|
this._onPointerDown = function (evt) {
|
|
|
|
+ _this._updatePointerPosition(evt);
|
|
var predicate = null;
|
|
var predicate = null;
|
|
|
|
+ // Meshes
|
|
if (!_this.onPointerDown) {
|
|
if (!_this.onPointerDown) {
|
|
predicate = function (mesh) {
|
|
predicate = function (mesh) {
|
|
return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.actionManager && mesh.actionManager.hasPickTriggers;
|
|
return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.actionManager && mesh.actionManager.hasPickTriggers;
|
|
};
|
|
};
|
|
}
|
|
}
|
|
- _this._updatePointerPosition(evt);
|
|
|
|
var pickResult = _this.pick(_this._pointerX, _this._pointerY, predicate, false, _this.cameraToUseForPointers);
|
|
var pickResult = _this.pick(_this._pointerX, _this._pointerY, predicate, false, _this.cameraToUseForPointers);
|
|
- if (pickResult.hit) {
|
|
|
|
|
|
+ if (pickResult.hit && pickResult.pickedMesh) {
|
|
if (pickResult.pickedMesh.actionManager) {
|
|
if (pickResult.pickedMesh.actionManager) {
|
|
switch (evt.button) {
|
|
switch (evt.button) {
|
|
case 0:
|
|
case 0:
|
|
@@ -12894,17 +12907,38 @@ var BABYLON;
|
|
if (_this.onPointerDown) {
|
|
if (_this.onPointerDown) {
|
|
_this.onPointerDown(evt, pickResult);
|
|
_this.onPointerDown(evt, pickResult);
|
|
}
|
|
}
|
|
|
|
+ // Sprites
|
|
|
|
+ if (_this.spriteManagers.length > 0) {
|
|
|
|
+ pickResult = _this.pickSprite(_this._pointerX, _this._pointerY, spritePredicate, false, _this.cameraToUseForPointers);
|
|
|
|
+ if (pickResult.hit && pickResult.pickedSprite) {
|
|
|
|
+ if (pickResult.pickedSprite.actionManager) {
|
|
|
|
+ switch (evt.button) {
|
|
|
|
+ case 0:
|
|
|
|
+ pickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnLeftPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(pickResult.pickedSprite, _this, evt));
|
|
|
|
+ break;
|
|
|
|
+ case 1:
|
|
|
|
+ pickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnCenterPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(pickResult.pickedSprite, _this, evt));
|
|
|
|
+ break;
|
|
|
|
+ case 2:
|
|
|
|
+ pickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnRightPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(pickResult.pickedSprite, _this, evt));
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ pickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(pickResult.pickedSprite, _this, evt));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
};
|
|
};
|
|
this._onPointerUp = function (evt) {
|
|
this._onPointerUp = function (evt) {
|
|
var predicate = null;
|
|
var predicate = null;
|
|
|
|
+ _this._updatePointerPosition(evt);
|
|
if (!_this.onPointerUp) {
|
|
if (!_this.onPointerUp) {
|
|
predicate = function (mesh) {
|
|
predicate = function (mesh) {
|
|
return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.actionManager && mesh.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnPickUpTrigger);
|
|
return mesh.isPickable && mesh.isVisible && mesh.isReady() && mesh.actionManager && mesh.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnPickUpTrigger);
|
|
};
|
|
};
|
|
}
|
|
}
|
|
- _this._updatePointerPosition(evt);
|
|
|
|
|
|
+ // Meshes
|
|
var pickResult = _this.pick(_this._pointerX, _this._pointerY, predicate, false, _this.cameraToUseForPointers);
|
|
var pickResult = _this.pick(_this._pointerX, _this._pointerY, predicate, false, _this.cameraToUseForPointers);
|
|
- if (pickResult.hit) {
|
|
|
|
|
|
+ if (pickResult.hit && pickResult.pickedMesh) {
|
|
if (pickResult.pickedMesh.actionManager) {
|
|
if (pickResult.pickedMesh.actionManager) {
|
|
pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, BABYLON.ActionEvent.CreateNew(pickResult.pickedMesh, evt));
|
|
pickResult.pickedMesh.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, BABYLON.ActionEvent.CreateNew(pickResult.pickedMesh, evt));
|
|
}
|
|
}
|
|
@@ -12912,6 +12946,15 @@ var BABYLON;
|
|
if (_this.onPointerUp) {
|
|
if (_this.onPointerUp) {
|
|
_this.onPointerUp(evt, pickResult);
|
|
_this.onPointerUp(evt, pickResult);
|
|
}
|
|
}
|
|
|
|
+ // Sprites
|
|
|
|
+ if (_this.spriteManagers.length > 0) {
|
|
|
|
+ pickResult = _this.pickSprite(_this._pointerX, _this._pointerY, spritePredicate, false, _this.cameraToUseForPointers);
|
|
|
|
+ if (pickResult.hit && pickResult.pickedSprite) {
|
|
|
|
+ if (pickResult.pickedSprite.actionManager) {
|
|
|
|
+ pickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, BABYLON.ActionEvent.CreateNewFromSprite(pickResult.pickedSprite, _this, evt));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
};
|
|
};
|
|
this._onKeyDown = function (evt) {
|
|
this._onKeyDown = function (evt) {
|
|
if (_this.actionManager) {
|
|
if (_this.actionManager) {
|
|
@@ -14203,6 +14246,28 @@ var BABYLON;
|
|
}
|
|
}
|
|
return pickingInfo || new BABYLON.PickingInfo();
|
|
return pickingInfo || new BABYLON.PickingInfo();
|
|
};
|
|
};
|
|
|
|
+ Scene.prototype._internalPickSprites = function (rayFunction, predicate, fastCheck) {
|
|
|
|
+ var pickingInfo = null;
|
|
|
|
+ if (this.spriteManagers.length > 0) {
|
|
|
|
+ var ray = rayFunction(BABYLON.Matrix.Identity());
|
|
|
|
+ for (var spriteIndex = 0; spriteIndex < this.spriteManagers.length; spriteIndex++) {
|
|
|
|
+ var spriteManager = this.spriteManagers[spriteIndex];
|
|
|
|
+ if (!spriteManager.isPickable) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ var result = spriteManager.intersects(ray, predicate, fastCheck);
|
|
|
|
+ if (!result || !result.hit)
|
|
|
|
+ continue;
|
|
|
|
+ if (!fastCheck && pickingInfo != null && result.distance >= pickingInfo.distance)
|
|
|
|
+ continue;
|
|
|
|
+ pickingInfo = result;
|
|
|
|
+ if (fastCheck) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return pickingInfo || new BABYLON.PickingInfo();
|
|
|
|
+ };
|
|
Scene.prototype.pick = function (x, y, predicate, fastCheck, camera) {
|
|
Scene.prototype.pick = function (x, y, predicate, fastCheck, camera) {
|
|
var _this = this;
|
|
var _this = this;
|
|
/// <summary>Launch a ray to try to pick a mesh in the scene</summary>
|
|
/// <summary>Launch a ray to try to pick a mesh in the scene</summary>
|
|
@@ -14213,6 +14278,16 @@ var BABYLON;
|
|
/// <param name="camera">camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used</param>
|
|
/// <param name="camera">camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used</param>
|
|
return this._internalPick(function (world) { return _this.createPickingRay(x, y, world, camera); }, predicate, fastCheck);
|
|
return this._internalPick(function (world) { return _this.createPickingRay(x, y, world, camera); }, predicate, fastCheck);
|
|
};
|
|
};
|
|
|
|
+ Scene.prototype.pickSprite = function (x, y, predicate, fastCheck, camera) {
|
|
|
|
+ var _this = this;
|
|
|
|
+ /// <summary>Launch a ray to try to pick a mesh in the scene</summary>
|
|
|
|
+ /// <param name="x">X position on screen</param>
|
|
|
|
+ /// <param name="y">Y position on screen</param>
|
|
|
|
+ /// <param name="predicate">Predicate function used to determine eligible sprites. Can be set to null. In this case, a sprite must have isPickable set to true</param>
|
|
|
|
+ /// <param name="fastCheck">Launch a fast check only using the bounding boxes. Can be set to null.</param>
|
|
|
|
+ /// <param name="camera">camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used</param>
|
|
|
|
+ return this._internalPickSprites(function (world) { return _this.createPickingRay(x, y, world, camera); }, predicate, fastCheck);
|
|
|
|
+ };
|
|
Scene.prototype.pickWithRay = function (ray, predicate, fastCheck) {
|
|
Scene.prototype.pickWithRay = function (ray, predicate, fastCheck) {
|
|
var _this = this;
|
|
var _this = this;
|
|
return this._internalPick(function (world) {
|
|
return this._internalPick(function (world) {
|
|
@@ -21701,6 +21776,7 @@ var BABYLON;
|
|
this.renderingGroupId = 0;
|
|
this.renderingGroupId = 0;
|
|
this.layerMask = 0x0FFFFFFF;
|
|
this.layerMask = 0x0FFFFFFF;
|
|
this.fogEnabled = true;
|
|
this.fogEnabled = true;
|
|
|
|
+ this.isPickable = false;
|
|
this._vertexDeclaration = [4, 4, 4, 4];
|
|
this._vertexDeclaration = [4, 4, 4, 4];
|
|
this._vertexStrideSize = 16 * 4; // 15 floats per sprite (x, y, z, angle, sizeX, sizeY, offsetX, offsetY, invertU, invertV, cellIndexX, cellIndexY, color)
|
|
this._vertexStrideSize = 16 * 4; // 15 floats per sprite (x, y, z, angle, sizeX, sizeY, offsetX, offsetY, invertU, invertV, cellIndexX, cellIndexY, color)
|
|
this._capacity = capacity;
|
|
this._capacity = capacity;
|
|
@@ -21758,6 +21834,47 @@ var BABYLON;
|
|
this._vertices[arrayOffset + 14] = sprite.color.b;
|
|
this._vertices[arrayOffset + 14] = sprite.color.b;
|
|
this._vertices[arrayOffset + 15] = sprite.color.a;
|
|
this._vertices[arrayOffset + 15] = sprite.color.a;
|
|
};
|
|
};
|
|
|
|
+ SpriteManager.prototype.intersects = function (ray, predicate, fastCheck) {
|
|
|
|
+ var count = Math.min(this._capacity, this.sprites.length);
|
|
|
|
+ var min = BABYLON.Vector3.Zero();
|
|
|
|
+ var max = BABYLON.Vector3.Zero();
|
|
|
|
+ var distance = Number.MAX_VALUE;
|
|
|
|
+ var currentSprite;
|
|
|
|
+ for (var index = 0; index < count; index++) {
|
|
|
|
+ var sprite = this.sprites[index];
|
|
|
|
+ if (!sprite) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ if (predicate) {
|
|
|
|
+ if (!predicate(sprite)) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else if (!sprite.isPickable) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ min.copyFromFloats(sprite.position.x - sprite.width / 2, sprite.position.y - sprite.height / 2, sprite.position.z);
|
|
|
|
+ max.copyFromFloats(sprite.position.x + sprite.width / 2, sprite.position.y + sprite.height / 2, sprite.position.z);
|
|
|
|
+ if (ray.intersectsBoxMinMax(min, max)) {
|
|
|
|
+ var currentDistance = BABYLON.Vector3.Distance(sprite.position, ray.origin);
|
|
|
|
+ if (distance > currentDistance) {
|
|
|
|
+ distance = currentDistance;
|
|
|
|
+ currentSprite = sprite;
|
|
|
|
+ if (fastCheck) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (currentSprite) {
|
|
|
|
+ var result = new BABYLON.PickingInfo();
|
|
|
|
+ result.hit = true;
|
|
|
|
+ result.pickedSprite = currentSprite;
|
|
|
|
+ result.distance = distance;
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ };
|
|
SpriteManager.prototype.render = function () {
|
|
SpriteManager.prototype.render = function () {
|
|
// Check
|
|
// Check
|
|
if (!this._effectBase.isReady() || !this._effectFog.isReady() || !this._spriteTexture || !this._spriteTexture.isReady())
|
|
if (!this._effectBase.isReady() || !this._effectFog.isReady() || !this._spriteTexture || !this._spriteTexture.isReady())
|
|
@@ -21849,6 +21966,7 @@ var BABYLON;
|
|
this.invertU = 0;
|
|
this.invertU = 0;
|
|
this.invertV = 0;
|
|
this.invertV = 0;
|
|
this.animations = new Array();
|
|
this.animations = new Array();
|
|
|
|
+ this.isPickable = true;
|
|
this._animationStarted = false;
|
|
this._animationStarted = false;
|
|
this._loopAnimation = false;
|
|
this._loopAnimation = false;
|
|
this._fromIndex = 0;
|
|
this._fromIndex = 0;
|
|
@@ -28839,9 +28957,9 @@ var BABYLON;
|
|
var ActionEvent = (function () {
|
|
var ActionEvent = (function () {
|
|
/**
|
|
/**
|
|
* @constructor
|
|
* @constructor
|
|
- * @param source The mesh that triggered the action.
|
|
|
|
- * @param pointerX the X mouse cursor position at the time of the event
|
|
|
|
- * @param pointerY the Y mouse cursor position at the time of the event
|
|
|
|
|
|
+ * @param source The mesh or sprite that triggered the action.
|
|
|
|
+ * @param pointerX The X mouse cursor position at the time of the event
|
|
|
|
+ * @param pointerY The Y mouse cursor position at the time of the event
|
|
* @param meshUnderPointer The mesh that is currently pointed at (can be null)
|
|
* @param meshUnderPointer The mesh that is currently pointed at (can be null)
|
|
* @param sourceEvent the original (browser) event that triggered the ActionEvent
|
|
* @param sourceEvent the original (browser) event that triggered the ActionEvent
|
|
*/
|
|
*/
|
|
@@ -28855,7 +28973,7 @@ var BABYLON;
|
|
}
|
|
}
|
|
/**
|
|
/**
|
|
* Helper function to auto-create an ActionEvent from a source mesh.
|
|
* Helper function to auto-create an ActionEvent from a source mesh.
|
|
- * @param source the source mesh that triggered the event
|
|
|
|
|
|
+ * @param source The source mesh that triggered the event
|
|
* @param evt {Event} The original (browser) event
|
|
* @param evt {Event} The original (browser) event
|
|
*/
|
|
*/
|
|
ActionEvent.CreateNew = function (source, evt, additionalData) {
|
|
ActionEvent.CreateNew = function (source, evt, additionalData) {
|
|
@@ -28863,6 +28981,15 @@ var BABYLON;
|
|
return new ActionEvent(source, scene.pointerX, scene.pointerY, scene.meshUnderPointer, evt, additionalData);
|
|
return new ActionEvent(source, scene.pointerX, scene.pointerY, scene.meshUnderPointer, evt, additionalData);
|
|
};
|
|
};
|
|
/**
|
|
/**
|
|
|
|
+ * Helper function to auto-create an ActionEvent from a source mesh.
|
|
|
|
+ * @param source The source sprite that triggered the event
|
|
|
|
+ * @param scene Scene associated with the sprite
|
|
|
|
+ * @param evt {Event} The original (browser) event
|
|
|
|
+ */
|
|
|
|
+ ActionEvent.CreateNewFromSprite = function (source, scene, evt, additionalData) {
|
|
|
|
+ return new ActionEvent(source, scene.pointerX, scene.pointerY, scene.meshUnderPointer, evt, additionalData);
|
|
|
|
+ };
|
|
|
|
+ /**
|
|
* Helper function to auto-create an ActionEvent from a scene. If triggered by a mesh use ActionEvent.CreateNew
|
|
* Helper function to auto-create an ActionEvent from a scene. If triggered by a mesh use ActionEvent.CreateNew
|
|
* @param scene the scene where the event occurred
|
|
* @param scene the scene where the event occurred
|
|
* @param evt {Event} The original (browser) event
|
|
* @param evt {Event} The original (browser) event
|
|
@@ -29024,7 +29151,7 @@ var BABYLON;
|
|
if (action.trigger >= ActionManager._OnPickTrigger && action.trigger <= ActionManager._OnPointerOutTrigger) {
|
|
if (action.trigger >= ActionManager._OnPickTrigger && action.trigger <= ActionManager._OnPointerOutTrigger) {
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
- if (action.trigger == ActionManager._OnPickUpTrigger) {
|
|
|
|
|
|
+ if (action.trigger === ActionManager._OnPickUpTrigger) {
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -29044,6 +29171,9 @@ var BABYLON;
|
|
if (action.trigger >= ActionManager._OnPickTrigger && action.trigger <= ActionManager._OnCenterPickTrigger) {
|
|
if (action.trigger >= ActionManager._OnPickTrigger && action.trigger <= ActionManager._OnCenterPickTrigger) {
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
+ if (action.trigger === ActionManager._OnPickUpTrigger) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
return false;
|
|
return false;
|
|
},
|
|
},
|