diff --git a/src/alternativa/engine3d/core/Camera3D.as b/src/alternativa/engine3d/core/Camera3D.as
index 98b3e96..69b29f7 100644
--- a/src/alternativa/engine3d/core/Camera3D.as
+++ b/src/alternativa/engine3d/core/Camera3D.as
@@ -136,6 +136,11 @@ public class Camera3D extends Object3D {
*/
alternativa3d var raysLength:int = 0;
+ /**
+ * @private
+ */
+ alternativa3d var globalMouseHandlingType:uint;
+
/**
* @private
*/
@@ -230,19 +235,16 @@ public class Camera3D extends Object3D {
}
var excludedLightLength:int = root.excludedLights.length;
- // Calculating the rays of mouse events
- view.calculateRays(this);
- for (i = origins.length; i < view.raysLength; i++) {
- origins[i] = new Vector3D();
- directions[i] = new Vector3D();
- }
- raysLength = view.raysLength;
// Check if object of hierarchy is visible
if (root.visible) {
+ globalMouseHandlingType = 0;
+
// Calculating the matrix to transform from the camera space to local space
root.cameraToLocalTransform.combine(root.inverseTransform, localToGlobalTransform);
// Calculating the matrix to transform from local space to the camera space
root.localToCameraTransform.combine(globalToLocalTransform, root.transform);
+
+ if (root.mouseEnabled) globalMouseHandlingType |= root.mouseHandlingType;
// Checking the culling
if (root.boundBox != null) {
calculateFrustum(root.cameraToLocalTransform);
@@ -308,7 +310,6 @@ public class Camera3D extends Object3D {
// Shadows preparing
if (light.shadow != null) {
- // TODO: Need check by occluders
light.shadow.process(this);
}
lights[j] = light;
@@ -318,14 +319,25 @@ public class Camera3D extends Object3D {
}
lightsLength = j;
lights.length = j;
+
+ // Calculating the rays of mouse events
+ view.calculateRays(this, (globalMouseHandlingType & Object3D.MOUSE_HANDLING_MOVING) != 0, (globalMouseHandlingType & Object3D.MOUSE_HANDLING_PRESSING) != 0, (globalMouseHandlingType & Object3D.MOUSE_HANDLING_WHEEL) != 0);
+ for (i = origins.length; i < view.raysLength; i++) {
+ origins[i] = new Vector3D();
+ directions[i] = new Vector3D();
+ }
+ raysLength = view.raysLength;
+
+ trace(raysLength, globalMouseHandlingType);
+
// Check getting in frustum and occluding
if (root.culling >= 0 && (root.boundBox == null || occludersLength == 0 || !root.boundBox.checkOcclusion(occluders, occludersLength, root.localToCameraTransform))) {
// Check if the ray crossing the bounding box
- if (root.boundBox != null) {
+ if (globalMouseHandlingType > 0 && root.boundBox != null) {
calculateRays(root.cameraToLocalTransform);
root.listening = root.boundBox.checkRays(origins, directions, raysLength);
} else {
- root.listening = true;
+ root.listening = globalMouseHandlingType > 0;
}
// Check if object needs in lightning
if (lightsLength > 0 && root.useLights) {
@@ -370,11 +382,12 @@ public class Camera3D extends Object3D {
}
// Gather the draws for children
root.collectChildrenDraws(this, lights, lightsLength, root.useShadow);
+
+ // Mouse events prosessing
+ view.processMouseEvents(context3D, this);
+ // Render
+ renderer.render(context3D);
}
- // Mouse events prosessing
- view.processMouseEvents(context3D, this);
- // Render
- renderer.render(context3D);
// Output
if (view._canvas == null) {
context3D.present();
@@ -600,6 +613,7 @@ public class Camera3D extends Object3D {
/**
* @private
+ * Transform rays in object space.
*/
alternativa3d function calculateRays(transform:Transform3D):void {
for (var i:int = 0; i < raysLength; i++) {
diff --git a/src/alternativa/engine3d/core/Object3D.as b/src/alternativa/engine3d/core/Object3D.as
index 460e642..42720c1 100644
--- a/src/alternativa/engine3d/core/Object3D.as
+++ b/src/alternativa/engine3d/core/Object3D.as
@@ -11,6 +11,7 @@ package alternativa.engine3d.core {
import alternativa.engine3d.alternativa3d;
import alternativa.engine3d.collisions.EllipsoidCollider;
import alternativa.engine3d.core.events.Event3D;
+ import alternativa.engine3d.core.events.MouseEvent3D;
import alternativa.engine3d.materials.compiler.Linker;
import alternativa.engine3d.materials.compiler.Procedure;
import alternativa.engine3d.objects.Surface;
@@ -125,6 +126,19 @@ package alternativa.engine3d.core {
*/
public class Object3D implements IEventDispatcher {
+ /**
+ * @private
+ */
+ alternativa3d static const MOUSE_HANDLING_MOVING:uint = 1;
+ /**
+ * @private
+ */
+ alternativa3d static const MOUSE_HANDLING_PRESSING:uint = 2;
+ /**
+ * @private
+ */
+ alternativa3d static const MOUSE_HANDLING_WHEEL:uint = 4;
+
/**
* Custom data available to store within Object3D by user.
*/
@@ -307,6 +321,11 @@ package alternativa.engine3d.core {
*/
alternativa3d var listening:Boolean;
+ /**
+ * @private
+ */
+ alternativa3d var mouseHandlingType:uint = 0;
+
/**
* @private
*/
@@ -662,8 +681,19 @@ package alternativa.engine3d.core {
}
var vector:Vector. = listeners[type];
if (vector == null) {
+ // There are not listeners of this type
vector = new Vector.();
listeners[type] = vector;
+
+ if (type == MouseEvent3D.MOUSE_MOVE || type == MouseEvent3D.MOUSE_OVER || type == MouseEvent3D.MOUSE_OUT || type == MouseEvent3D.ROLL_OVER || type == MouseEvent3D.ROLL_OUT) {
+ mouseHandlingType |= MOUSE_HANDLING_MOVING;
+ }
+ if (type == MouseEvent3D.MOUSE_DOWN || type == MouseEvent3D.MOUSE_UP || type == MouseEvent3D.CLICK || type == MouseEvent3D.DOUBLE_CLICK) {
+ mouseHandlingType |= MOUSE_HANDLING_PRESSING;
+ }
+ if (type == MouseEvent3D.MOUSE_WHEEL) {
+ mouseHandlingType |= MOUSE_HANDLING_WHEEL;
+ }
}
if (vector.indexOf(listener) < 0) {
vector.push(listener);
@@ -701,6 +731,15 @@ package alternativa.engine3d.core {
bubbleListeners = null;
}
}
+ if (type == MouseEvent3D.MOUSE_MOVE || type == MouseEvent3D.MOUSE_OVER || type == MouseEvent3D.MOUSE_OUT || type == MouseEvent3D.ROLL_OVER || type == MouseEvent3D.ROLL_OUT) {
+ mouseHandlingType &= ~MOUSE_HANDLING_MOVING;
+ }
+ if (type == MouseEvent3D.MOUSE_DOWN || type == MouseEvent3D.MOUSE_UP || type == MouseEvent3D.CLICK || type == MouseEvent3D.DOUBLE_CLICK) {
+ mouseHandlingType &= ~MOUSE_HANDLING_PRESSING;
+ }
+ if (type == MouseEvent3D.MOUSE_WHEEL) {
+ mouseHandlingType &= ~MOUSE_HANDLING_WHEEL;
+ }
}
}
}
@@ -1295,6 +1334,8 @@ package alternativa.engine3d.core {
child.cameraToLocalTransform.combine(child.inverseTransform, cameraToLocalTransform);
// Calculating matrix for converting from local coordinates to camera coordinates
child.localToCameraTransform.combine(localToCameraTransform, child.transform);
+
+ if (child.mouseEnabled) camera.globalMouseHandlingType |= child.mouseHandlingType;
// Culling checking
if (child.boundBox != null) {
camera.calculateFrustum(child.cameraToLocalTransform);
diff --git a/src/alternativa/engine3d/core/View.as b/src/alternativa/engine3d/core/View.as
index 96748ad..8df3705 100644
--- a/src/alternativa/engine3d/core/View.as
+++ b/src/alternativa/engine3d/core/View.as
@@ -370,11 +370,11 @@ package alternativa.engine3d.core {
/**
* @private
*/
- alternativa3d function calculateRays(camera:Camera3D):void {
+ alternativa3d function calculateRays(camera:Camera3D, processMoving:Boolean, processPressing:Boolean, processMouseWheel:Boolean):void {
var i:int;
var mouseEvent:MouseEvent;
// Case of last coordinates fits in the view.
- if (lastEvent != null) {
+ if (processMoving && lastEvent != null) {
// Detecting mouse movement within the frame
var mouseMoved:Boolean = false;
for (i = 0; i < eventsLength; i++) {
@@ -398,11 +398,32 @@ package alternativa.engine3d.core {
}
}
+ if (!processMoving) {
+ overedTarget = null;
+ overedTargetSurface = null;
+ }
+ if (!processPressing) {
+ pressedTarget = null;
+ clickedTarget = null;
+ }
+
// Creation of exclusive rays
var mouseX:Number = 1e+22;
var mouseY:Number = 1e+22;
+ var totalEvents:int = 0;
for (i = 0; i < eventsLength; i++) {
mouseEvent = events[i];
+ // Filter events
+ if (!processMoving && (mouseEvent.type == MouseEvent.MOUSE_MOVE || mouseEvent.type == MouseEvent.MOUSE_OVER || mouseEvent.type == MouseEvent.MOUSE_OUT)) {
+ continue;
+ }
+ if (!processPressing && (mouseEvent.type == MouseEvent.MOUSE_DOWN || mouseEvent.type == MouseEvent.CLICK || mouseEvent.type == MouseEvent.DOUBLE_CLICK)) {
+ continue;
+ }
+ if (!processMouseWheel && mouseEvent.type == MouseEvent.MOUSE_WHEEL) {
+ continue;
+ }
+
if (mouseEvent.type != "mouseOut") {
// Calculation of ray within the camera
if (mouseEvent.localX != mouseX || mouseEvent.localY != mouseY) {
@@ -450,11 +471,14 @@ package alternativa.engine3d.core {
raysLength++;
}
// Considering event with the ray
- indices[i] = raysLength - 1;
+ indices[totalEvents] = raysLength - 1;
} else {
- indices[i] = -1;
+ indices[totalEvents] = -1;
}
+ events[totalEvents] = mouseEvent;
+ totalEvents++;
}
+ eventsLength = totalEvents;
}
/**
@@ -616,6 +640,7 @@ package alternativa.engine3d.core {
}
break;
case "mouseOut":
+ // TODO: lastEvent not need change here. For example when MOUSE_OUT and MOUSE_MOVE exists in the one frame.
lastEvent = null;
target = null;
targetSurface = null;