From 68a890e75d774b7c1f1d9d604e45bd7c48ad70fd Mon Sep 17 00:00:00 2001 From: rob-bateman Date: Fri, 25 Jan 2013 16:47:58 +0000 Subject: [PATCH] added setIgnoreList and onlyMouseEnabled to IPicker Updated comment for ray origin check when entity has bounds collision --- src/away3d/core/pick/IPicker.as | 6 +++ src/away3d/core/pick/RaycastPicker.as | 65 +++++++++++++++++++++++---- src/away3d/core/pick/ShaderPicker.as | 16 ++++++- 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/src/away3d/core/pick/IPicker.as b/src/away3d/core/pick/IPicker.as index 8318e8d3f..5d5bbcdb3 100644 --- a/src/away3d/core/pick/IPicker.as +++ b/src/away3d/core/pick/IPicker.as @@ -26,5 +26,11 @@ package away3d.core.pick * @param scene The scene on which the picking object acts. */ function getSceneCollision(position:Vector3D, direction:Vector3D, scene:Scene3D):PickingCollisionVO; + + /** + * Determines whether the picker takes account of the mouseEnabled properties of entities. Defaults to true. + */ + function get onlyMouseEnabled():Boolean; + function set onlyMouseEnabled(value:Boolean):void; } } diff --git a/src/away3d/core/pick/RaycastPicker.as b/src/away3d/core/pick/RaycastPicker.as index fd7868d43..e8aef53d4 100644 --- a/src/away3d/core/pick/RaycastPicker.as +++ b/src/away3d/core/pick/RaycastPicker.as @@ -23,11 +23,26 @@ package away3d.core.pick private var _findClosestCollision:Boolean; private var _raycastCollector:RaycastCollector = new RaycastCollector(); + private var _ignoredEntities:Array = new Array(); + private var _onlyMouseEnabled:Boolean = true; protected var _entities:Vector.; protected var _numEntities:uint; protected var _hasCollisions:Boolean; - + + /** + * @inheritDoc + */ + public function get onlyMouseEnabled():Boolean + { + return _onlyMouseEnabled; + } + + public function set onlyMouseEnabled(value:Boolean):void + { + _onlyMouseEnabled = value; + } + /** * Creates a new RaycastPicker object. * @@ -64,9 +79,14 @@ package away3d.core.pick while (node) { entity = node.entity; + if (isIgnored(entity)) { + node = node.next; + continue; + } + // If collision detected, store in new data set. - if( entity.isVisible && entity._ancestorsAllowMouseEnabled && entity.mouseEnabled && entity.isIntersectingRay(rayPosition, rayDirection )) - _entities[_numEntities++] = entity; + if( entity.isVisible && entity.isIntersectingRay(rayPosition, rayDirection )) + _entities[_numEntities++] = entity; node = node.next; } @@ -83,11 +103,14 @@ package away3d.core.pick */ public function getSceneCollision(position:Vector3D, direction:Vector3D, scene:Scene3D):PickingCollisionVO { + //clear collector + _raycastCollector.clear(); + //setup ray vectors _raycastCollector.rayPosition = position; _raycastCollector.rayDirection = direction; - // collect stuff to test + // collect entities to test scene.traversePartitions(_raycastCollector); _numEntities = 0; @@ -96,6 +119,11 @@ package away3d.core.pick while (node) { entity = node.entity; + if (isIgnored(entity)) { + node = node.next; + continue; + } + _entities[_numEntities++] = entity; node = node.next; @@ -107,7 +135,25 @@ package away3d.core.pick return getPickingCollisionVO(); } - + + public function setIgnoreList(entities:Array):void + { + _ignoredEntities = entities; + } + + private function isIgnored(entity:Entity):Boolean + { + if (_onlyMouseEnabled && (!entity._ancestorsAllowMouseEnabled ||!entity.mouseEnabled)) + return true; + + var ignoredEntity:Entity; + for each (ignoredEntity in _ignoredEntities) + if (ignoredEntity == entity) + return true; + + return false; + } + private function sortOnNearT( entity1:Entity, entity2:Entity ):Number { return entity1.pickingCollisionVO.rayEntryDistance > entity2.pickingCollisionVO.rayEntryDistance ? 1 : -1; @@ -147,10 +193,11 @@ package away3d.core.pick } } else if (bestCollisionVO == null || pickingCollisionVO.rayEntryDistance < bestCollisionVO.rayEntryDistance) { // A bounds collision with no triangle collider stops all checks. - // Note: rayEntryDistances of 0 mean a collision caused by the ray starting inside the bounds. - // This makes the object eligible for triangle picking but should not represent a successful pick - // if the object's picker is bounds only. - if( pickingCollisionVO.rayEntryDistance != 0 ) { + // Note: a bounds collision with a ray origin inside its bounds is ONLY ever used + // to enable the detection of a corresponsding triangle collision. + // Therefore, bounds collisions with a ray origin inside its bounds can be ignored + // if it has been established that there is NO triangle collider to test + if( !pickingCollisionVO.rayOriginIsInsideBounds ) { updateLocalPosition( pickingCollisionVO ); return pickingCollisionVO; } diff --git a/src/away3d/core/pick/ShaderPicker.as b/src/away3d/core/pick/ShaderPicker.as index 6a4afe2e1..e2b4e3b96 100644 --- a/src/away3d/core/pick/ShaderPicker.as +++ b/src/away3d/core/pick/ShaderPicker.as @@ -32,6 +32,7 @@ package away3d.core.pick { private var _stage3DProxy:Stage3DProxy; private var _context:Context3D; + private var _onlyMouseEnabled:Boolean = true; private var _objectProgram3D : Program3D; private var _triangleProgram3D : Program3D; @@ -57,6 +58,19 @@ package away3d.core.pick private var _potentialFound : Boolean; private static const MOUSE_SCISSOR_RECT : Rectangle = new Rectangle(0, 0, 1, 1); + /** + * @inheritDoc + */ + public function get onlyMouseEnabled():Boolean + { + return _onlyMouseEnabled; + } + + public function set onlyMouseEnabled(value:Boolean):void + { + _onlyMouseEnabled = value; + } + /** * Creates a new ShaderPicker object. */ @@ -167,7 +181,7 @@ package away3d.core.pick renderable = item.renderable; // it's possible that the renderable was already removed from the scene - if (!renderable.sourceEntity.scene || !renderable.mouseEnabled) { + if (!renderable.sourceEntity.scene || (!renderable.mouseEnabled && _onlyMouseEnabled)) { item = item.next; continue; }