ZoomProcessor.java :  » Java-2D » mt4j » org » mt4j » input » inputProcessors » componentProcessors » zoomProcessor » Java Open Source

Java Open Source » Java 2D » mt4j 
mt4j » org » mt4j » input » inputProcessors » componentProcessors » zoomProcessor » ZoomProcessor.java
/***********************************************************************
 * mt4j Copyright (c) 2008 - 2009 C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
 *  
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 ***********************************************************************/
package org.mt4j.input.inputProcessors.componentProcessors.zoomProcessor;

import java.util.List;

import org.mt4j.components.interfaces.IMTComponent3D;
import org.mt4j.input.inputData.AbstractCursorInputEvt;
import org.mt4j.input.inputData.InputCursor;
import org.mt4j.input.inputProcessors.IInputProcessor;
import org.mt4j.input.inputProcessors.MTGestureEvent;
import org.mt4j.input.inputProcessors.componentProcessors.AbstractComponentProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.AbstractCursorProcessor;
import org.mt4j.util.math.Vector3D;

import processing.core.PApplet;

/**
 * The Class ZoomProcessor.
 * Multitouch background zoom gesture. This will change the scene's CAMERA if the DefaultZoomAction gesture listener is added to the canvas.
 * Fires ZoomEvent gesture events.
 * <br><strong>NOTE:</strong> Should only be used in combination with a MTCanvas component. 
 * @author Christopher Ruff
 */
public class ZoomProcessor extends AbstractCursorProcessor {
  
  /** The zoom detect radius. */
  private float zoomDetectRadius;
  
  /** The old distance. */
  private float oldDistance;
  

  /**
   * Instantiates a new zoom processor.
   * 
   * @param graphicsContext the graphics context
   */
  public ZoomProcessor(PApplet graphicsContext){
    this(graphicsContext, graphicsContext.width/2);
  }
  
  /**
   * Instantiates a new zoom processor.
   * 
   * @param graphicsContext the graphics context
   * @param zoomDetectRadius the zoom detect radius
   */
  public ZoomProcessor(PApplet graphicsContext, float zoomDetectRadius){
    this.zoomDetectRadius = zoomDetectRadius;
    this.setLockPriority(2);
  }

  
  @Override
  public void cursorStarted(InputCursor c, AbstractCursorInputEvt positionEvent) {
    InputCursor[] locked = getLockedCursorsArray();
    if (locked.length >= 2){ //gesture with 2 fingers already in progress
      logger.debug(this.getName() + " has already enough cursors for this gesture - adding to unused ID:" + c.getId());
    }else{//not in progress yet
      List<InputCursor> availableCursors = getFreeComponentCursors();
      logger.debug(this.getName() + " Available cursors: " + availableCursors.size());
      
      if (availableCursors.size() >= 2){
        InputCursor otherCursor = (availableCursors.get(0).equals(c))? availableCursors.get(1) : availableCursors.get(0);
        
        //See if we can obtain a lock on both cursors
        if (this.canLock(otherCursor, c)){
          float newDistance = Vector3D.distance(otherCursor.getPosition(), c.getPosition());
          if (newDistance < zoomDetectRadius) {
            this.oldDistance = newDistance;
            this.getLock(otherCursor, c);
            logger.debug(this.getName() + " we could lock both cursors! And fingers in zoom distance!");
            this.fireGestureEvent(new ZoomEvent(this, MTGestureEvent.GESTURE_STARTED, positionEvent.getCurrentTarget(), c, otherCursor, 0f, positionEvent.getCurrentTarget().getViewingCamera() ));
          }else{
            logger.debug(this.getName() + " cursors not close enough to start gesture. Distance: " + newDistance);
          }
        }else{
          logger.debug(this.getName() + " we could NOT lock both cursors!");
        }
      }
    }
  }

  @Override
  public void cursorUpdated(InputCursor c, AbstractCursorInputEvt positionEvent) {
    List<InputCursor> locked = getLockedCursors();
    if (locked.contains(c)){ //in progress with this cursors
      InputCursor firstCursor = locked.get(0);
      InputCursor secondCursor = locked.get(1);
      float fingerDistance = Vector3D.distance(firstCursor.getPosition(), secondCursor.getPosition());
      float camZoomAmount = fingerDistance - oldDistance;
      oldDistance = fingerDistance;
      if (c.equals(firstCursor)){
        this.fireGestureEvent(new ZoomEvent(this, MTGestureEvent.GESTURE_UPDATED, positionEvent.getCurrentTarget(), firstCursor, secondCursor, camZoomAmount, positionEvent.getCurrentTarget().getViewingCamera()));
      }else{
        this.fireGestureEvent(new ZoomEvent(this, MTGestureEvent.GESTURE_UPDATED, positionEvent.getCurrentTarget(), firstCursor, secondCursor, camZoomAmount, positionEvent.getCurrentTarget().getViewingCamera()));
      }
    }
  }

  @Override
  public void cursorEnded(InputCursor c,  AbstractCursorInputEvt positionEvent) {
    logger.debug(this.getName() + " INPUT_ENDED RECIEVED - cursor: " + c.getId());
    List<InputCursor> locked = getLockedCursors();
    if (locked.contains(c)){
      InputCursor leftOverCursor = (locked.get(0).equals(c))? locked.get(1) : locked.get(0);
      InputCursor futureCursor = getFarthestFreeCursorToLimited(leftOverCursor, zoomDetectRadius);
      if (futureCursor != null){
        float newDistance = Vector3D.distance(leftOverCursor.getPosition(),  futureCursor.getPosition());
        if (newDistance < zoomDetectRadius) {//Check if other cursor is in distance 
          this.oldDistance = newDistance;
          this.getLock(futureCursor);
          logger.debug(this.getName() + " we could lock another cursor! (ID:" + futureCursor.getId() +")");
          logger.debug(this.getName() + " continue with different cursors (ID: " + futureCursor.getId() + ")" + " " + "(ID: " + leftOverCursor.getId() + ")");
        }else{
          this.endGesture(c, leftOverCursor, positionEvent.getCurrentTarget());
        }
      }else{
        this.endGesture(c, leftOverCursor, positionEvent.getCurrentTarget());
      }
    }
  }
  
  
  /**
   * End gesture.
   * 
   * @param inputEndedcursor the input ended cursor
   * @param leftOvercursor the left over cursor
   * @param comp the comp
   */
  private void endGesture(InputCursor inputEndedCursor, InputCursor leftOverCursor, IMTComponent3D comp){
    this.unLock(leftOverCursor);
    this.fireGestureEvent(new ZoomEvent(this, MTGestureEvent.GESTURE_ENDED, comp, inputEndedCursor, leftOverCursor, 0f, comp.getViewingCamera()));
  }
  
  
  
  @Override
  public void cursorLocked(InputCursor c, IInputProcessor lockingProcessor) {
    if (lockingProcessor instanceof AbstractComponentProcessor){
      logger.debug(this.getName() + " Recieved cursor LOCKED by (" + ((AbstractComponentProcessor)lockingProcessor).getName()  + ") - cursor ID: " + c.getId());
    }else{
      logger.debug(this.getName() + " Recieved cursor LOCKED by higher priority signal - cursor ID: " + c.getId());
    }
    
    List<InputCursor> locked = getLockedCursors();
    if (locked.contains(c)){
      this.fireGestureEvent(new ZoomEvent(this, MTGestureEvent.GESTURE_CANCELED, c.getCurrentTarget(), locked.get(0), locked.get(1), 0f, c.getCurrentTarget().getViewingCamera()));      
      this.unLockAllCursors();
      logger.debug(this.getName() + " cursor:" + c.getId() + " cursor LOCKED. Was an active cursor in this gesture - we therefor have to stop this gesture!");
    }
  }

  
  
  @Override
  public void cursorUnlocked(InputCursor c) {
    logger.debug(this.getName() + " Recieved UNLOCKED signal for cursor ID: " + c.getId());
    
    if (getLockedCursors().size() >= 2){ //we dont need the unlocked cursor, gesture still in progress
      return;
    }
    
    this.unLockAllCursors();
    
    List<InputCursor> availableCursors = getFreeComponentCursors();
    if (availableCursors.size() >= 2){ //we can try to resume the gesture
      InputCursor firstCursor = availableCursors.get(0);
      InputCursor secondCursor = getFarthestFreeCursorToLimited(firstCursor, zoomDetectRadius);

      //See if we can obtain a lock on both cursors
      if (this.canLock(firstCursor, secondCursor)){
        float newDistance = Vector3D.distance(firstCursor.getPosition(), secondCursor.getPosition());
        if (newDistance < zoomDetectRadius) {//Check if other cursor is in distance 
          this.oldDistance = newDistance;
          this.getLock(firstCursor, secondCursor);
          logger.debug(this.getName() + " we could lock cursors: " + firstCursor.getId() +", " + secondCursor.getId());
          logger.debug(this.getName() + " continue with different cursors (ID: " + firstCursor.getId() + ")" + " " + "(ID: " + secondCursor.getId() + ")");
          this.fireGestureEvent(new ZoomEvent(this, MTGestureEvent.GESTURE_RESUMED, c.getCurrentTarget(), firstCursor, secondCursor, 0f, c.getCurrentTarget().getViewingCamera() ));
        }else{
          logger.debug(this.getName() + " distance was too great between cursors: " + firstCursor.getId() +", " + secondCursor.getId() + " distance: " + newDistance);
        }
      }else{
        logger.debug(this.getName() + " we could NOT lock cursors: " + firstCursor.getId() +", " + secondCursor.getId());
      }
    }
  }
  
  
  @Override
  public String getName() {
    return "Zoom Processor";
  }
  

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.