X-Git-Url: http://www2.svjatoslav.eu/gitweb/?p=sixth-3d.git;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Feu%2Fsvjatoslav%2Fsixth%2Fe3d%2Fgui%2Fhumaninput%2FHIDEventTracker.java;fp=src%2Fmain%2Fjava%2Feu%2Fsvjatoslav%2Fsixth%2Fe3d%2Fgui%2Fhumaninput%2FHIDEventTracker.java;h=19dee506414352a06d0242d83b13d4d520417271;hp=0000000000000000000000000000000000000000;hb=e87345f40ecb4ea526bd8d5dca58afaaee9ec6b3;hpb=7e383c71392e298dde478015129bc739f3eb4e4a diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/gui/humaninput/HIDEventTracker.java b/src/main/java/eu/svjatoslav/sixth/e3d/gui/humaninput/HIDEventTracker.java new file mode 100755 index 0000000..19dee50 --- /dev/null +++ b/src/main/java/eu/svjatoslav/sixth/e3d/gui/humaninput/HIDEventTracker.java @@ -0,0 +1,271 @@ +/* + * Sixth 3D engine. Author: Svjatoslav Agejenko. + * This project is released under Creative Commons Zero (CC0) license. + */ +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; + +/** + * This class is responsible for tracking human input devices (keyboard, mouse, etc.) and + * forwarding those inputs to subsequent virtual components. + */ +public class HIDEventTracker implements + MouseMotionListener, KeyListener, MouseListener, MouseWheelListener, ViewRenderListener { + + /** + *
Map of pressed keys.
+ *Key is mouse button code.
+ *Value is system milliseconds when button was pressed.
+ *So by reading the map one can determine currently pressed buttons as well as duration.
+ */ + private final Maptrue
if view needs to be repainted.
+ */
+ private boolean handleKeyboardEvents() {
+ final KeyboardInputHandler currentFocusOwner = viewPanel.getKeyboardFocusStack().getCurrentFocusOwner();
+ ArrayListtrue
if view update is needed.
+ */
+ private boolean forwardKeyboardEventsToFocusOwner(
+ KeyboardInputHandler currentFocusOwner, ArrayListtrue
if view needs to be repainted.
+ */
+ private synchronized boolean handleMouseClicksAndHover(final ViewPanel viewPanel) {
+ boolean rerenderNeeded = false;
+ MouseEvent event = findClickLocationToTrace();
+ if (event != null) {
+ // process mouse clicks as a first priority
+ rerenderNeeded = true;
+ } else {
+ // when there are no mouse clicks, process mouse hovering
+
+ if (mouseMoved) {
+ mouseMoved = false;
+ // we would like to re-render frame when user moved mouse, to see what objects mouse is hovering over
+ rerenderNeeded = true;
+ }
+
+ if (currentMouseLocation != null) {
+ // mouse click with button 0 amounts to mouse hovering event
+ event = new MouseEvent(currentMouseLocation, 0);
+ }
+ }
+
+ if (viewPanel.getRenderingContext() != null)
+ viewPanel.getRenderingContext().setMouseEvent(event);
+
+ return rerenderNeeded;
+ }
+
+ private MouseEvent findClickLocationToTrace() {
+ synchronized (detectedMouseEvents) {
+ if (detectedMouseEvents.isEmpty())
+ return null;
+
+ return detectedMouseEvents.remove(0);
+ }
+ }
+
+ 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 java.awt.event.MouseEvent e) {
+ synchronized (detectedMouseEvents) {
+ detectedMouseEvents.add(new MouseEvent(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 java.awt.event.MouseEvent e) {
+ mouseWithinWindow = true;
+ }
+
+ @Override
+ public synchronized void mouseExited(final java.awt.event.MouseEvent e) {
+ mouseWithinWindow = false;
+ currentMouseLocation = null;
+ }
+
+ @Override
+ public synchronized void mouseMoved(final java.awt.event.MouseEvent e) {
+ currentMouseLocation = new Point2D(e.getX(), e.getY());
+ mouseMoved = true;
+ }
+
+ @Override
+ public void mousePressed(final java.awt.event.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: It would be nice here to detect somehow whether user moved mouse or touch screen.
+ // in case of touch screen, we would like to reverse movement along X and Y axis.
+
+ 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;
+ }
+
+}