package ca.cmput301f13t03.adventure_datetime.view.treeView; import android.view.MotionEvent; import ca.cmput301f13t03.adventure_datetime.view.IFragmentSelected; class InputHandler { private Camera m_camera = null; private NodeGrid m_nodeGrid = null; // touch input private boolean m_hasPrimaryTouch = false; private int m_pointerId = 0; // only supporting single touch private boolean m_isDragging = false; private static final float DRAG_MINIMUM_SQUARED = 625.0f; private float m_initialX = 0; private float m_initialY = 0; private float m_previousX = 0; private float m_previousY = 0; private IFragmentSelected m_selectionCallback = null; private enum MoveType { TAP, DRAG } public InputHandler(Camera camera, NodeGrid nodeGrid) { m_camera = camera; m_nodeGrid = nodeGrid; } public boolean OnTouchAction(MotionEvent event) { boolean result = false; int pointerIndex = event.getActionIndex(); int pointerId = event.getPointerId(pointerIndex); if(event.getActionMasked() == MotionEvent.ACTION_DOWN) { HandleTouchDown(event, pointerId, pointerIndex); } else if(event.getActionMasked() == MotionEvent.ACTION_UP) { result = HandleTouchUp(event, pointerId, pointerIndex); } else if(event.getActionMasked() == MotionEvent.ACTION_MOVE) { result = HandleMove(event, pointerId, pointerIndex); } else if(event.getActionMasked() == MotionEvent.ACTION_CANCEL) { result = HandleCancel(event, pointerId); } return result; } public void SetSelectionCallback(IFragmentSelected callback) { m_selectionCallback = callback; } public IFragmentSelected GetSelectionCallback() { return m_selectionCallback; } private boolean HandleTouchUp(MotionEvent event, int pointerId, int pointerIndex) { boolean result = false; if(m_hasPrimaryTouch && m_pointerId == pointerId) { // then the pointer was released // stop tracking m_pointerId = 0; m_hasPrimaryTouch = false; result = true; m_previousX = event.getX(pointerIndex); m_previousY = event.getY(pointerIndex); // and check for a tap event if(this.GetMoveType(m_previousX, m_previousY) == MoveType.TAP) { HandleTap(m_previousX, m_previousY); } } else { // some other pointer was released, don't care result = false; } return result; } private boolean HandleTouchDown(MotionEvent event, int pointerId, int pointerIndex) { boolean result = false; if(!m_hasPrimaryTouch) { m_pointerId = pointerId; m_previousX = event.getX(pointerIndex); m_previousY = event.getY(pointerIndex); m_initialX = m_previousX; m_initialY = m_previousY; m_hasPrimaryTouch = true; m_isDragging = false; result = true; } else { // reject input if we are already tracking a pointer result = false; } return result; } private boolean HandleMove(MotionEvent event, int pointerId, int pointerIndex) { boolean result = false; if(m_hasPrimaryTouch && m_pointerId == pointerId) { // only handle the move if it is the primary touch index result = true; float newX = event.getX(pointerIndex); float newY = event.getY(pointerIndex); // determine move type (tap or drag) MoveType type = GetMoveType(newX, newY); // perform action if(type == MoveType.DRAG) { HandleDrag(newX, newY); } // ignoring tap until the tap is released m_previousX = newX; m_previousY = newY; } return result; } private boolean HandleCancel(MotionEvent event, int pointerId) { boolean result = false; if(m_hasPrimaryTouch && m_pointerId == pointerId) { m_hasPrimaryTouch = false; m_pointerId = 0; result = true; } else { // reject input if we are already tracking a pointer result = false; } return result; } private void HandleDrag(float currX, float currY) { m_isDragging = true; float deltaX = currX - m_previousX; float deltaY = currY - m_previousY; float newX = m_camera.GetXTarget() - deltaX; float newY = m_camera.GetYTarget() - deltaY; m_camera.LookAt(newX, newY); } private void HandleTap(float currX, float currY) { // early out if we are dragging if(m_isDragging) { return; } float cords[] = { currX, currY }; m_camera.ScreenCordsToWorldCords(cords); FragmentNode tappedNode = m_nodeGrid.GetNodeAtLocation((int)(cords[0]), (int)(cords[1])); if(tappedNode != null) { // the node was selected! if(m_selectionCallback != null) { m_selectionCallback.OnFragmentSelected(tappedNode.GetFragment()); } // else... I guess no one will ever know... } // else we just ignore the tap, cuz there is nothing there! } private MoveType GetMoveType(float currX, float currY) { if(GetDistanceFromStartSquared(currX, currY) > DRAG_MINIMUM_SQUARED) { return MoveType.DRAG; } else { return MoveType.TAP; } } private float GetDistanceFromStartSquared(float currX, float currY) { return (currX - m_initialX)*(currX - m_initialX) + (currY - m_initialY)*(currY - m_initialY); } }