/* * Sixth 3D engine. Copyright ©2012-2018, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu * * This program is free software; you can redistribute it and/or * modify it under the terms of version 3 of the GNU Lesser General Public License * or later as published by the Free Software Foundation. * */ package eu.svjatoslav.sixth.e3d.gui.humaninput; import eu.svjatoslav.sixth.e3d.geometry.Point2D; import eu.svjatoslav.sixth.e3d.gui.Avatar; import eu.svjatoslav.sixth.e3d.gui.ViewPanel; import eu.svjatoslav.sixth.e3d.gui.ViewRenderListener; import javax.swing.*; import java.awt.event.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class UserInputTracker implements MouseMotionListener, KeyListener, MouseListener, MouseWheelListener, ViewRenderListener { /** *
* Key is keyboard key code. * Value is system milliseconds when key was pressed. * * So by reading the map one can determine currently pressed keys as well as duration. **/ private final Map
true
if view needs to be repainted.
*/
private boolean handleKeyboardEvents() {
final UserInputHandler currentFocusOwner = viewPanel.getKeyboardFocusTracker().getCurrentFocusOwner();
ArrayListtrue
if view update is needed.
*/
private boolean forwardKeyboardEventsToFocusOwner(
UserInputHandler currentFocusOwner, ArrayListtrue
if view needs to be repainted.
*/
private synchronized boolean handleMouseClicksAndHover(final ViewPanel viewPanel) {
MouseClick unprocessedMouseClick = findUnprocessedMouseClick();
if (unprocessedMouseClick != null) {
viewPanel.getRenderingContext().mouseClick = unprocessedMouseClick;
return false;
} else
return handleMouseHovering(viewPanel);
}
private MouseClick findUnprocessedMouseClick() {
synchronized (detectedMouseClicks) {
if (detectedMouseClicks.isEmpty())
return null;
return detectedMouseClicks.remove(0);
}
}
private boolean handleMouseHovering(ViewPanel viewPanel) {
if (currentMouseLocation != null)
// mouse click with button 0 amounts to mouse hovering event
viewPanel.getRenderingContext().mouseClick = new MouseClick(currentMouseLocation, 0);
if (mouseMoved) {
mouseMoved = false;
return true;
} else
return false;
}
boolean isKeyPressed(final int keyCode) {
return pressedKeysToPressedTimeMap.containsKey(keyCode);
}
@Override
public void keyPressed(final KeyEvent evt) {
synchronized (detectedKeyEvents) {
pressedKeysToPressedTimeMap.put(evt.getKeyCode(), System.currentTimeMillis());
detectedKeyEvents.add(evt);
}
}
@Override
public void keyReleased(final KeyEvent evt) {
synchronized (detectedKeyEvents) {
pressedKeysToPressedTimeMap.remove(evt.getKeyCode());
detectedKeyEvents.add(evt);
}
}
@Override
public void keyTyped(final KeyEvent e) {
}
@Override
public void mouseClicked(final MouseEvent e) {
synchronized (detectedMouseClicks) {
detectedMouseClicks.add(new MouseClick(e.getX(), e.getY(), e.getButton()));
}
}
@Override
public void mouseDragged(final java.awt.event.MouseEvent evt) {
final Point2D mouseLocation = new Point2D(evt.getX(), evt.getY());
if (oldMouseCoordinatesWhenDragging == null) {
oldMouseCoordinatesWhenDragging = mouseLocation;
return;
}
mouseDraggedDirection.add(mouseLocation.clone().subtract(oldMouseCoordinatesWhenDragging));
oldMouseCoordinatesWhenDragging = mouseLocation;
}
@Override
public void mouseEntered(final MouseEvent e) {
mouseWithinWindow = true;
}
@Override
public synchronized void mouseExited(final MouseEvent e) {
mouseWithinWindow = false;
currentMouseLocation = null;
}
@Override
public synchronized void mouseMoved(final MouseEvent e) {
currentMouseLocation = new Point2D(e.getX(), e.getY());
mouseMoved = true;
}
@Override
public void mousePressed(final MouseEvent e) {
}
@Override
public void mouseReleased(final java.awt.event.MouseEvent evt) {
oldMouseCoordinatesWhenDragging = null;
}
@Override
public void mouseWheelMoved(final java.awt.event.MouseWheelEvent evt) {
wheelMovedDirection += evt.getWheelRotation();
}
/**
* @return true
if view needs to be repainted.
*/
private boolean handleMouseVerticalScrolling() {
final Avatar avatar = viewPanel.getAvatar();
final double actualAcceleration = 50 * avatar.avatarAcceleration * (1 + (avatar.getMovementSpeed() / 10));
avatar.getMovementVector().y += (wheelMovedDirection * actualAcceleration);
avatar.enforceSpeedLimit();
boolean repaintNeeded = wheelMovedDirection != 0;
wheelMovedDirection = 0;
return repaintNeeded;
}
/**
* @return true
if view needs to be repainted.
*/
private boolean handleMouseDragging() {
// TODO: need to detect whether user moved mouse or touch screen
final Avatar avatar = viewPanel.getAvatar();
// for mouse
avatar.setAngleXZ(avatar.getAngleXZ() - ((float) mouseDraggedDirection.x / 50));
avatar.setAngleYZ(avatar.getAngleYZ() - ((float) mouseDraggedDirection.y / 50));
// for touch screen
// avatar.setAngleXZ(avatar.getAngleXZ() + ((float)
// mouseDraggedDirection.x / 50));
// avatar.setAngleYZ(avatar.getAngleYZ() + ((float)
// mouseDraggedDirection.y / 50));
boolean viewUpdateNeeded = !mouseDraggedDirection.isZero();
mouseDraggedDirection.zero();
return viewUpdateNeeded;
}
}