Calculate mouse events in only cases when there are listeners of this type. Reduces frame time in situations when mouse processing not needed.

This commit is contained in:
Yaski
2012-06-14 21:02:33 +06:00
parent 41c2e9639c
commit a45149aed4
3 changed files with 98 additions and 18 deletions

View File

@@ -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++) {

View File

@@ -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 <code>Object3D</code> 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.<Function> = listeners[type];
if (vector == null) {
// There are not listeners of this type
vector = new Vector.<Function>();
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);

View File

@@ -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;