/*
- * Sixth 3D engine. Copyright ©2012-2016, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 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
import eu.svjatoslav.sixth.e3d.geometry.Point2D;
import eu.svjatoslav.sixth.e3d.gui.Avatar;
-import eu.svjatoslav.sixth.e3d.gui.View;
-import eu.svjatoslav.sixth.e3d.gui.ViewContext;
-import eu.svjatoslav.sixth.e3d.gui.ViewUpdateListener;
+import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
+import eu.svjatoslav.sixth.e3d.gui.ViewRenderListener;
import javax.swing.*;
import java.awt.event.*;
import java.util.List;
import java.util.Map;
-public class UserInputTracker
- implements MouseMotionListener, KeyListener, MouseListener, MouseWheelListener, ViewUpdateListener {
+public class UserInputTracker implements
+ MouseMotionListener, KeyListener, MouseListener, MouseWheelListener, ViewRenderListener {
/**
* <pre>
private final Map<Integer, Long> pressedKeysToPressedTimeMap = new HashMap<>();
private final List<MouseClick> detectedMouseClicks = new ArrayList<>();
private final List<KeyEvent> detectedKeyEvents = new ArrayList<>();
- public int wheelMovedDirection = 0;
- Point2D mouseDraggedDirection = new Point2D();
- Point2D oldMouseCoordinatesWhenDragging;
- ViewContext viewContext;
- Point2D currentMouseLocation;
- boolean mouseMoved;
+ private int wheelMovedDirection = 0;
+ private Point2D mouseDraggedDirection = new Point2D();
+ private Point2D oldMouseCoordinatesWhenDragging;
+ private ViewPanel viewPanel;
+ private Point2D currentMouseLocation;
+ private boolean mouseMoved;
private boolean mouseWithinWindow = false;
- public UserInputTracker(final ViewContext viewContext) {
- this.viewContext = viewContext;
+ public UserInputTracker(final ViewPanel viewPanel) {
+ this.viewPanel = viewPanel;
+ bind(viewPanel);
}
/**
* {@inheritDoc}
*/
@Override
- public boolean beforeViewUpdate(final ViewContext viewContext, final int millisecondsSinceLastFrame) {
+ public boolean beforeRender(final ViewPanel viewPanel, final int millisecondsSinceLastFrame) {
- boolean viewUpdateNeeded = handleDetectedMouseClicks(viewContext.getView());
-
- viewUpdateNeeded |= handleDetectedKeyEvents();
-
- viewContext.getKeyboardFocusTracker().getCurrentFocusOwner().beforeViewUpdate(viewContext,
- millisecondsSinceLastFrame);
- viewUpdateNeeded |= trackMouse();
+ boolean viewUpdateNeeded = handleKeyboardEvents();
+ viewUpdateNeeded |= handleMouseClicksAndHover(viewPanel);
+ viewUpdateNeeded |= handleMouseDragging();
+ viewUpdateNeeded |= handleMouseVerticalScrolling();
return viewUpdateNeeded;
}
- public void bind(final JPanel panel) {
+ private void bind(final JPanel panel) {
panel.addMouseMotionListener(this);
panel.addKeyListener(this);
panel.addMouseWheelListener(this);
}
- public boolean handleDetectedKeyEvents() {
- boolean keyEventsHandled = false;
+ /**
+ * @return <code>true</code> if view needs to be repainted.
+ */
+ private boolean handleKeyboardEvents() {
+ final UserInputHandler currentFocusOwner = viewPanel.getKeyboardFocusTracker().getCurrentFocusOwner();
+ ArrayList<KeyEvent> unprocessedKeyboardEvents = getUnprocessedKeyboardEvents();
- final UserInputHandler currentFocusOwner = viewContext.getKeyboardFocusTracker().getCurrentFocusOwner();
+ return currentFocusOwner == null ? false :
+ forwardKeyboardEventsToFocusOwner(currentFocusOwner, unprocessedKeyboardEvents);
+ }
+ private ArrayList<KeyEvent> getUnprocessedKeyboardEvents() {
synchronized (detectedKeyEvents) {
- if (currentFocusOwner == null) {
- detectedKeyEvents.clear();
- return false;
- }
-
- while (!detectedKeyEvents.isEmpty()) {
- final KeyEvent keyEvent = detectedKeyEvents.remove(0);
-
- switch (keyEvent.getID()) {
- case KeyEvent.KEY_PRESSED:
- currentFocusOwner.keyPressed(keyEvent, viewContext);
- keyEventsHandled = true;
- break;
-
- case KeyEvent.KEY_RELEASED:
- currentFocusOwner.keyReleased(keyEvent, viewContext);
- keyEventsHandled = true;
- break;
- }
- }
+ ArrayList<KeyEvent> result = new ArrayList<>(detectedKeyEvents);
+ detectedKeyEvents.clear();
+ return result;
}
+ }
+
+ /**
+ * @return <code>true</code> if view update is needed.
+ */
+ private boolean forwardKeyboardEventsToFocusOwner(
+ UserInputHandler currentFocusOwner, ArrayList<KeyEvent> keyEvents) {
+ boolean viewUpdateNeeded = false;
- return keyEventsHandled;
+ for (KeyEvent keyEvent : keyEvents)
+ viewUpdateNeeded |= processKeyEvent(currentFocusOwner, keyEvent);
+
+ return viewUpdateNeeded;
+ }
+
+ private boolean processKeyEvent(UserInputHandler currentFocusOwner, KeyEvent keyEvent) {
+ switch (keyEvent.getID()) {
+ case KeyEvent.KEY_PRESSED:
+ return currentFocusOwner.keyPressed(keyEvent, viewPanel);
+
+ case KeyEvent.KEY_RELEASED:
+ return currentFocusOwner.keyReleased(keyEvent, viewPanel);
+ }
+ return false;
}
/**
- * Returns <code>true</code> if mouse events are detected and view needs to
- * be repainted.
+ * @return <code>true</code> if view needs to be repainted.
*/
- public synchronized boolean handleDetectedMouseClicks(final View view) {
- if (detectedMouseClicks.isEmpty()) {
+ private synchronized boolean handleMouseClicksAndHover(final ViewPanel viewPanel) {
+ MouseClick unprocessedMouseClick = findUnprocessedMouseClick();
+
+ if (unprocessedMouseClick != null) {
+ viewPanel.getRenderingContext().mouseClick = unprocessedMouseClick;
+ return false;
+ } else
+ return handleMouseHovering(viewPanel);
+ }
- if (currentMouseLocation != null)
- view.getRenderingContext().mouseClick = new MouseClick(currentMouseLocation, 0);
+ private MouseClick findUnprocessedMouseClick() {
+ synchronized (detectedMouseClicks) {
+ if (detectedMouseClicks.isEmpty())
+ return null;
- if (mouseMoved) {
- mouseMoved = false;
- return true;
- } else
- return false;
+ return detectedMouseClicks.remove(0);
}
+ }
- view.getRenderingContext().mouseClick = 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);
- return true;
+ if (mouseMoved) {
+ mouseMoved = false;
+ return true;
+ } else
+ return false;
}
- public boolean isKeyPressed(final int keyCode) {
+ boolean isKeyPressed(final int keyCode) {
return pressedKeysToPressedTimeMap.containsKey(keyCode);
}
synchronized (detectedKeyEvents) {
pressedKeysToPressedTimeMap.put(evt.getKeyCode(), System.currentTimeMillis());
detectedKeyEvents.add(evt);
- viewContext.getView().repaintDuringNextViewUpdate();
}
}
synchronized (detectedKeyEvents) {
pressedKeysToPressedTimeMap.remove(evt.getKeyCode());
detectedKeyEvents.add(evt);
- viewContext.getView().repaintDuringNextViewUpdate();
}
}
}
/**
- * Interpret mouse movement
+ * @return <code>true</code> if view needs to be repainted.
*/
- public boolean trackMouse() {
- final Avatar avatar = viewContext.getAvatar();
-
- // track mouse dragging
+ 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 <code>true</code> 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));
// avatar.setAngleYZ(avatar.getAngleYZ() + ((float)
// mouseDraggedDirection.y / 50));
- // track mouse wheel movements
- final double actualAcceleration = 50 * avatar.avatarAcceleration * (1 + (avatar.getMovementSpeed() / 10));
-
- avatar.getMovementDirection().y += (wheelMovedDirection * actualAcceleration);
- avatar.enforceSpeedLimit();
-
- // check if view shall be repainted
- boolean repaintNeeded;
- repaintNeeded = (mouseDraggedDirection.x != 0) || (mouseDraggedDirection.y != 0) || (wheelMovedDirection != 0);
-
- // reset movement counters
- wheelMovedDirection = 0;
+ boolean viewUpdateNeeded = !mouseDraggedDirection.isZero();
mouseDraggedDirection.zero();
-
- return repaintNeeded;
+ return viewUpdateNeeded;
}
}