Package com.badlogic.gdx.backends.iosrobovm

Source Code of com.badlogic.gdx.backends.iosrobovm.IOSInput$TouchEvent

/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/

package com.badlogic.gdx.backends.iosrobovm;

import com.badlogic.gdx.graphics.Pixmap;
import org.robovm.cocoatouch.coregraphics.CGPoint;
import org.robovm.cocoatouch.foundation.NSArray;
import org.robovm.cocoatouch.foundation.NSSet;
import org.robovm.cocoatouch.uikit.UIAcceleration;
import org.robovm.cocoatouch.uikit.UIAccelerometer;
import org.robovm.cocoatouch.uikit.UIAccelerometerDelegate;
import org.robovm.cocoatouch.uikit.UIAlertView;
import org.robovm.cocoatouch.uikit.UIAlertViewDelegate;
import org.robovm.cocoatouch.uikit.UIAlertViewStyle;
import org.robovm.cocoatouch.uikit.UIApplication;
import org.robovm.cocoatouch.uikit.UIEvent;
import org.robovm.cocoatouch.uikit.UIInterfaceOrientation;
import org.robovm.cocoatouch.uikit.UITextField;
import org.robovm.cocoatouch.uikit.UITouch;
import org.robovm.cocoatouch.uikit.UITouchPhase;
import org.robovm.cocoatouch.uikit.UIView;
import org.robovm.objc.ObjCClass;

import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.Pool;

public class IOSInput implements Input {
  static final int MAX_TOUCHES = 20;

  static {
    // HACK: Make sure UITouch has been registered
    ObjCClass.getByType(UITouch.class);
  }
 
  IOSApplication app;
  IOSApplicationConfiguration config;
  int[] deltaX = new int[MAX_TOUCHES];
  int[] deltaY = new int[MAX_TOUCHES];
  int[] touchX = new int[MAX_TOUCHES];
  int[] touchY = new int[MAX_TOUCHES];
  // we store the pointer to the UITouch struct here, or 0
  long[] touchDown = new long[MAX_TOUCHES];
  int numTouched = 0;
  boolean justTouched = false;
  Pool<TouchEvent> touchEventPool = new Pool<TouchEvent>() {
    @Override
    protected TouchEvent newObject() {
      return new TouchEvent();
    }
  };
  Array<TouchEvent> touchEvents = new Array<TouchEvent>();
  TouchEvent currentEvent = null;
  float[] acceleration = new float[3];
  InputProcessor inputProcessor = null;
  // We need to hold on to the reference to this delegate or else its
  // ObjC peer will get released when the Java peer is GCed.
  UIAccelerometerDelegate accelerometerDelegate;
 
  public IOSInput(IOSApplication app) {
    this.app = app;
    this.config = app.config;
  }
 
  void setupPeripherals() {
    setupAccelerometer();
    setupCompass();
  }

  private void setupCompass () {
    if(config.useCompass) {
      // FIXME implement compass
    }
  }

  private void setupAccelerometer() {
    if(config.useAccelerometer) {
      accelerometerDelegate = new UIAccelerometerDelegate.Adapter() {

        @Override
        public void didAccelerate(UIAccelerometer accelerometer, UIAcceleration values) {
          float x = (float)values.getX() * 10;
          float y = (float)values.getY() * 10;
          float z = (float)values.getZ() * 10;

          UIInterfaceOrientation orientation = app.graphics.viewController != null
                                    ? app.graphics.viewController.getInterfaceOrientation()
                                    : UIApplication.getSharedApplication().getStatusBarOrientation();
                   
          acceleration[0] = -x;
          acceleration[1] = -y;
          acceleration[2] = -z;
        }
      };
      UIAccelerometer.getSharedAccelerometer().setDelegate(accelerometerDelegate);
      UIAccelerometer.getSharedAccelerometer().setUpdateInterval(config.accelerometerUpdate);
    }
  }

  @Override
  public float getAccelerometerX() {
    return acceleration[0];
  }

  @Override
  public float getAccelerometerY() {
    return acceleration[1];
  }

  @Override
  public float getAccelerometerZ() {
    return acceleration[2];
  }

  @Override
  public float getAzimuth() {
    // FIXME implement this
    return 0;
  }

  @Override
  public float getPitch() {
    // FIXME implement this
    return 0;
  }

  @Override
  public float getRoll() {
    // FIXME implement this
    return 0;
  }

  @Override
  public void getRotationMatrix(float[] matrix) {
    // FIXME implement this
  }

  @Override
  public int getX() {
    return touchX[0];
  }

  @Override
  public int getX(int pointer) {
    return touchX[pointer];
  }

  @Override
  public int getDeltaX() {
    return deltaX[0];
  }

  @Override
  public int getDeltaX(int pointer) {
    return deltaX[pointer];
  }

  @Override
  public int getY() {
    return touchY[0];
  }

  @Override
  public int getY(int pointer) {
    return touchY[pointer];
  }

  @Override
  public int getDeltaY() {
    return deltaY[0];
  }

  @Override
  public int getDeltaY(int pointer) {
    return deltaY[pointer];
  }

  @Override
  public boolean isTouched() {
    return touchDown[0] != 0;
  }

  @Override
  public boolean justTouched() {
    return justTouched;
  }

  @Override
  public boolean isTouched(int pointer) {
    return touchDown[pointer] != 0;
  }

  @Override
  public boolean isButtonPressed(int button) {
    return button == Buttons.LEFT && numTouched > 0;
  }

  @Override
  public boolean isKeyPressed(int key) {
    return false;
  }

  @Override
  public void getTextInput(TextInputListener listener, String title, String text) {
    final UIAlertView uiAlertView = buildUIAlertView(listener, title, text, null);
    uiAlertView.show();
  }

  // Issue 773 indicates this may solve a premature GC issue
  UIAlertViewDelegate delegate;
 
  /** Builds an {@link UIAlertView} with an added {@link UITextField} for inputting text.
   * @param listener Text input listener
   * @param title Dialog title
   * @param text Text for text field
   * @return UiAlertView */
  private UIAlertView buildUIAlertView (final TextInputListener listener, String title, String text, String placeholder) {
    delegate = new UIAlertViewDelegate.Adapter() {
      @Override
      public void clicked (UIAlertView view, int clicked) {
        if (clicked == 0) {
          // user clicked "Cancel" button
          listener.canceled();
        } else if (clicked == 1) {
          // user clicked "Ok" button
          UITextField textField = view.getTextField(0);
          listener.input(textField.getText());
        }
        delegate = null;
      }

      @Override
      public void cancel (UIAlertView view) {
        listener.canceled();
        delegate = null;
      }
    };

    // build the view
    final UIAlertView uiAlertView = new UIAlertView();
    uiAlertView.setTitle(title);
    uiAlertView.addButton("Cancel");
    uiAlertView.addButton("Ok");
    uiAlertView.setAlertViewStyle(UIAlertViewStyle.PlainTextInput);
    uiAlertView.setDelegate(delegate);

    UITextField textField = uiAlertView.getTextField(0);
    textField.setPlaceholder(placeholder);
    textField.setText(text);

    return uiAlertView;
  }

  @Override
  public void getPlaceholderTextInput(TextInputListener listener, String title, String placeholder) {
    final UIAlertView uiAlertView = buildUIAlertView(listener, title, null, placeholder);
    uiAlertView.show();
  }

  @Override
  public void setOnscreenKeyboardVisible(boolean visible) {
  }

  @Override
  public void vibrate(int milliseconds) {
    // FIXME implement this
  }

  @Override
  public void vibrate(long[] pattern, int repeat) {
    // FIXME implement this
  }

  @Override
  public void cancelVibrate() {
    // FIXME implement this
  }

  @Override
  public long getCurrentEventTime() {
    return currentEvent.timestamp;
  }

  @Override
  public void setCatchBackKey(boolean catchBack) {
  }

  @Override
  public void setCatchMenuKey(boolean catchMenu) {
  }

  @Override
  public void setInputProcessor(InputProcessor processor) {
    this.inputProcessor = processor;
  }

  @Override
  public InputProcessor getInputProcessor() {
    return inputProcessor;
  }

  @Override
  public boolean isPeripheralAvailable(Peripheral peripheral) {
    if(peripheral == Peripheral.Accelerometer && config.useAccelerometer) return true;
    if(peripheral == Peripheral.MultitouchScreen) return true;
    // FIXME implement this (not sure if possible)
//    if(peripheral == Peripheral.OnscreenKeyboard) return true;
    // FIXME implement this
//    if(peripheral == Peripheral.Compass) return true;
   
    return false;
  }

  @Override
  public int getRotation() {
    UIInterfaceOrientation orientation = app.graphics.viewController != null
          ? app.graphics.viewController.getInterfaceOrientation()
          : UIApplication.getSharedApplication().getStatusBarOrientation();
    // we measure orientation counter clockwise, just like on Android
    if(orientation == UIInterfaceOrientation.Portrait) return 0;
    if(orientation == UIInterfaceOrientation.LandscapeLeft) return 270;
    if(orientation == UIInterfaceOrientation.PortraitUpsideDown) return 180;
    if(orientation == UIInterfaceOrientation.LandscapeRight) return 90;
    return 0;
  }

  @Override
  public Orientation getNativeOrientation() {
    return Orientation.Portrait;
  }

  @Override
  public void setCursorCatched(boolean catched) {
  }

  @Override
  public boolean isCursorCatched() {
    return false;
  }

  @Override
  public void setCursorPosition(int x, int y) {
  }

  @Override
  public void setCursorImage(Pixmap pixmap, int xHotspot, int yHotspot) {
  }

  public void touchDown(NSSet touches, UIEvent event) {
    toTouchEvents(touches, event);
  }

  public void touchUp(NSSet touches, UIEvent event) {
    toTouchEvents(touches, event);
  }

  public void touchMoved(NSSet touches, UIEvent event) {
    toTouchEvents(touches, event);
  }
 
  void processEvents() {
    synchronized(touchEvents) {
      justTouched = false;
      for(TouchEvent event: touchEvents) {
        currentEvent = event;
        switch(event.phase) {
        case Began:
          if(inputProcessor != null) inputProcessor.touchDown(event.x, event.y, event.pointer, Buttons.LEFT);
          if(numTouched == 1)
            justTouched = true;
          break;
        case Cancelled:
        case Ended:
          if(inputProcessor != null) inputProcessor.touchUp(event.x, event.y, event.pointer, Buttons.LEFT);
          break;
        case Moved:
        case Stationary:
          if(inputProcessor != null) inputProcessor.touchDragged(event.x, event.y, event.pointer);
          break;
        }
      }
      touchEventPool.freeAll(touchEvents);
      touchEvents.clear();
    }
  }
 
  private int getFreePointer() {
    for(int i = 0; i < touchDown.length; i++) {
      if(touchDown[i] == 0) return i;
    }
    throw new GdxRuntimeException("Couldn't find free pointer id!");
  }
 
  private int findPointer(UITouch touch) {
    long ptr = touch.getHandle();
    for(int i = 0; i < touchDown.length; i++) {
      if(touchDown[i] == ptr) return i;
    }
    throw new GdxRuntimeException("Couldn't find pointer id for touch event!");
  }

  private void toTouchEvents(NSSet touches, UIEvent uiEvent) {
    for (UITouch touch : (NSSet<UITouch>) touches) {
      CGPoint loc = touch.getLocation(touch.getView());
      synchronized(touchEvents) {
        TouchEvent event = touchEventPool.obtain();
        event.x = (int)(loc.x() * app.displayScaleFactor);
        event.y = (int)(loc.y() * app.displayScaleFactor);
        event.phase = touch.getPhase();
        event.timestamp = (long)(touch.getTimestamp() * 1000000000);
        touchEvents.add(event);
       
        if(touch.getPhase() == UITouchPhase.Began) {         
          event.pointer = getFreePointer();
          touchDown[event.pointer] = (int) touch.getHandle();
          touchX[event.pointer] = event.x;
          touchY[event.pointer] = event.y;
          deltaX[event.pointer] = 0;
          deltaY[event.pointer] = 0;
          numTouched++;
        }
       
        if(touch.getPhase() == UITouchPhase.Moved ||
          touch.getPhase() == UITouchPhase.Stationary) {
          event.pointer = findPointer(touch);
          deltaX[event.pointer] = event.x - touchX[event.pointer];
          deltaY[event.pointer] = event.y - touchY[event.pointer];
          touchX[event.pointer] = event.x;
          touchY[event.pointer] = event.y;
        }
       
        if(touch.getPhase() == UITouchPhase.Cancelled ||
          touch.getPhase() == UITouchPhase.Ended) {         
          event.pointer = findPointer(touch);
          touchDown[event.pointer] = 0;
          touchX[event.pointer] = event.x;
          touchY[event.pointer] = event.y;
          deltaX[event.pointer] = 0;
          deltaY[event.pointer] = 0;
          numTouched--;
        }
      }
    }
  }
 
  static class TouchEvent {
    UITouchPhase phase;
    long timestamp;
    int x, y;
    int pointer;
  }
}
TOP

Related Classes of com.badlogic.gdx.backends.iosrobovm.IOSInput$TouchEvent

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.