// See if the WindowSwing has already determined a pickInfo for this event.
// TODO: right now, button release events are never sent to createCoordinateHandler so they
// never have pre-calculated pickInfos. I don't yet know if this is an Embedded Swing bug or
// whether it is a feature.
PickInfo swingHitPickInfo = null;
if (swingPickInfos.peek() != null) {
try {
PickInfoQueueEntry entry = swingPickInfos.take();
// TODO: for now, verify that this is the right pickInfo for this event
// Only check certain fields. Other fields (such as absolute X and Y) are
// expected to be different
if (e.getID() == entry.mouseEvent.getID() &&
e.getX() == entry.mouseEvent.getX() &&
e.getY() == entry.mouseEvent.getY()) {
swingHitPickInfo = entry.hitPickInfo;
} else {
logger.finest("Swing pickInfo event doesn't match 3D event. Repicking.");
logger.finest("3D event = " + e);
logger.finest("pickInfo event = " + entry.mouseEvent);
}
} catch (InterruptedException ex) {}
}
// Implement the click threshold. Allow click event to be passed along only
if (e.getID() == MouseEvent.MOUSE_PRESSED) {
buttonLastX = e.getX();
buttonLastY = e.getY();
} else if (e.getID() == MouseEvent.MOUSE_CLICKED) {
if (!buttonWithinClickThreshold(e.getX(), e.getY())) {
// Discard the event by returing a miss
return null;
}
}
// Handle button clicked events specially. The mouse clicked event
// comes after the grab has terminated. So we do this in order to
// force the clicked event to go to the same destination as the
// pressed event
if (e.getID() == MouseEvent.MOUSE_CLICKED) {
return new DetermineDestPickInfoReturn(lastButtonPressedPickInfo, lastButtonPressedPickInfo);
}
// First perform the pick (the pick details in the info are ordered
// from least to greatest eye distance.
PickInfo hitPickInfo;
if (swingHitPickInfo == null) {
hitPickInfo = pickEventScreenPos(e.getX(), e.getY());
logger.finest("Result of pickEventScreenPos = " + hitPickInfo);
if (hitPickInfo != null) {
logger.finest("hitPickInfo.size() = " + hitPickInfo.size());
}
} else {
hitPickInfo = swingHitPickInfo;
}
/* For Debug
int n = hitPickInfo.size();
System.err.println("n = " + n);
for (int i = 0; i < n; i++) {
PickDetails pd = hitPickInfo.get(i);
System.err.println("pd[" + i + "] = " + pd);
Entity pickEntity = pd.getEntity();
System.err.println("entity[" + i + "] = " + pickEntity);
}
*/
// Calculate how the grab state should change. If the a grab should activate, activate it.
GrabChangeType grabChange = GrabChangeType.GRAB_NO_CHANGE;
int eventID = e.getID();
if (eventID == MouseEvent.MOUSE_PRESSED ||
eventID == MouseEvent.MOUSE_RELEASED) {
grabChange = evaluateButtonGrabStateChange(eventID, e);
if (grabChange == GrabChangeType.GRAB_ACTIVATE) {
grabIsActive = true;
grabPickInfo = hitPickInfo;
logger.finest("Grab activate, grabPickInfo = " + grabPickInfo);
if (grabPickInfo != null) {
logger.finest("grabPickInfo.size() = " + grabPickInfo.size());
if (grabPickInfo.size() > 0) {
PickDetails pd = grabPickInfo.get(0);
logger.finest("Grab pickDetails[0] = " + pd);
if (pd != null) {
logPickDetailsEntity(pd);
CollisionComponent cc = pd.getCollisionComponent();
logger.finest("cc = " + cc);
if (cc != null) {
logger.finest("cc entity = " + cc.getEntity());
}
}
}
}
}
}
// If a grab is active, the event destination pick info will be the grabbed pick info
PickInfo destPickInfo;
logger.finest("grabIsActive = " + grabIsActive);
if (grabIsActive) {
destPickInfo = grabPickInfo;
logger.finest("Grab is active, grabPickInfo = " + grabPickInfo);
} else {