mirror of https://github.com/axmolengine/axmol.git
Merge branch 'master' of https://github.com/cocos2d/cocos2d-x into 439
Conflicts: cocos2dx/platform/ios/CCFileUtils_ios.mm
This commit is contained in:
commit
7e81c56231
|
@ -8,4 +8,4 @@
|
|||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-8
|
||||
target=android-7
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
# it is needed for ndk-r5
|
||||
APP_STL := stlport_static
|
||||
APP_STL := stlport_static
|
||||
|
||||
APP_MODULES := cocos2d cocosdenshion helloworld
|
|
@ -1,119 +1,139 @@
|
|||
package org.cocos2dx.lib;
|
||||
|
||||
import org.cocos2dx.lib.touch.metalev.multitouch.controller.MultiTouchController;
|
||||
import org.cocos2dx.lib.touch.metalev.multitouch.controller.MultiTouchController.MultiTouchObjectCanvas;
|
||||
import org.cocos2dx.lib.touch.metalev.multitouch.controller.MultiTouchController.PointInfo;
|
||||
import org.cocos2dx.lib.touch.metalev.multitouch.controller.MultiTouchController.PositionAndScale;
|
||||
|
||||
import android.content.Context;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class Cocos2dxGLSurfaceView extends GLSurfaceView implements
|
||||
MultiTouchObjectCanvas {
|
||||
public class Cocos2dxGLSurfaceView extends GLSurfaceView{
|
||||
private static final String TAG = Cocos2dxGLSurfaceView.class
|
||||
.getCanonicalName();
|
||||
private MultiTouchController<Void> mTouchController;
|
||||
private Cocos2dxRenderer mRenderer;
|
||||
private final boolean debug = false;
|
||||
|
||||
public Cocos2dxGLSurfaceView(Context context) {
|
||||
super(context);
|
||||
mRenderer = new Cocos2dxRenderer();
|
||||
setRenderer(mRenderer);
|
||||
|
||||
mTouchController = new MultiTouchController<Void>(this);
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(final MotionEvent event) {
|
||||
if (mTouchController.onTouchEvent(event)) {
|
||||
final PointInfo pt = mTouchController.mCurrPt;
|
||||
final int ids[] = new int[pt.getNumTouchPoints()];
|
||||
final float xs[] = new float[pt.getNumTouchPoints()];
|
||||
final float ys[] = new float[pt.getNumTouchPoints()];
|
||||
// these data are used in ACTION_MOVE and ACTION_CANCEL
|
||||
final int pointerNumber = event.getPointerCount();
|
||||
final int[] ids = new int[pointerNumber];
|
||||
final float[] xs = new float[pointerNumber];
|
||||
final float[] ys = new float[pointerNumber];
|
||||
|
||||
for (int i = 0; i < pt.getNumTouchPoints(); i++) {
|
||||
ids[i] = pt.getPointerIds()[i];
|
||||
xs[i] = pt.getXs()[i];
|
||||
ys[i] = pt.getYs()[i];
|
||||
Log.d(TAG,
|
||||
"ACTION: " + pt.getAction() + "id[i]="
|
||||
+ pt.getPointerIds()[i] + "x[i]= "
|
||||
+ pt.getXs()[i] + " y[i]= " + pt.getYs()[i]);
|
||||
}
|
||||
|
||||
switch (pt.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case 261:
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
Log.d(TAG, "ACTION_DOWN");
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionDown(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
Log.d(TAG, "ACTION_MOVE");
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionMove(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
Log.d(TAG, "ACTION_UP");
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionUp(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionCancel(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
for (int i = 0; i < pointerNumber; i++) {
|
||||
ids[i] = event.getPointerId(i);
|
||||
xs[i] = event.getX(i);
|
||||
ys[i] = event.getY(i);
|
||||
}
|
||||
return false;
|
||||
|
||||
switch (event.getAction() & MotionEvent.ACTION_MASK) {
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
final int idPointerDown = event.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
|
||||
final float xPointerDown = event.getX(idPointerDown);
|
||||
final float yPointerDown = event.getY(idPointerDown);
|
||||
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionDown(idPointerDown, xPointerDown, yPointerDown);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
// there are only one finger on the screen
|
||||
final int idDown = event.getPointerId(0);
|
||||
final float xDown = event.getX(idDown);
|
||||
final float yDown = event.getY(idDown);
|
||||
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionDown(idDown, xDown, yDown);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionMove(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
final int idPointerUp = event.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
|
||||
final float xPointerUp = event.getX(idPointerUp);
|
||||
final float yPointerUp = event.getY(idPointerUp);
|
||||
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionUp(idPointerUp, xPointerUp, yPointerUp);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
// there are only one finger on the screen
|
||||
final int idUp = event.getPointerId(0);
|
||||
final float xUp = event.getX(idUp);
|
||||
final float yUp = event.getY(idUp);
|
||||
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionUp(idUp, xUp, yUp);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionCancel(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
if (debug){
|
||||
dumpEvent(event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDraggableObjectAtPoint(PointInfo touchPoint) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getPositionAndScale(Object obj,
|
||||
PositionAndScale objPosAndScaleOut) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setPositionAndScale(Object obj,
|
||||
PositionAndScale newObjPosAndScale, PointInfo touchPoint) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectObject(Object obj, PointInfo touchPoint) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
|
||||
/** Show an event in the LogCat view, for debugging */
|
||||
private void dumpEvent(MotionEvent event) {
|
||||
String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" ,
|
||||
"POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int action = event.getAction();
|
||||
int actionCode = action & MotionEvent.ACTION_MASK;
|
||||
sb.append("event ACTION_" ).append(names[actionCode]);
|
||||
if (actionCode == MotionEvent.ACTION_POINTER_DOWN
|
||||
|| actionCode == MotionEvent.ACTION_POINTER_UP) {
|
||||
sb.append("(pid " ).append(
|
||||
action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
|
||||
sb.append(")" );
|
||||
}
|
||||
sb.append("[" );
|
||||
for (int i = 0; i < event.getPointerCount(); i++) {
|
||||
sb.append("#" ).append(i);
|
||||
sb.append("(pid " ).append(event.getPointerId(i));
|
||||
sb.append(")=" ).append((int) event.getX(i));
|
||||
sb.append("," ).append((int) event.getY(i));
|
||||
if (i + 1 < event.getPointerCount())
|
||||
sb.append(";" );
|
||||
}
|
||||
sb.append("]" );
|
||||
Log.d(TAG, sb.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,12 +39,12 @@ public class Cocos2dxRenderer implements GLSurfaceView.Renderer {
|
|||
last = now;
|
||||
}
|
||||
|
||||
public void handleActionDown(int[] id, float[] x, float[] y)
|
||||
public void handleActionDown(int id, float x, float y)
|
||||
{
|
||||
nativeTouchesBegin(id, x, y);
|
||||
}
|
||||
|
||||
public void handleActionUp(int[] id, float[] x, float[] y)
|
||||
public void handleActionUp(int id, float x, float y)
|
||||
{
|
||||
nativeTouchesEnd(id, x, y);
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ public class Cocos2dxRenderer implements GLSurfaceView.Renderer {
|
|||
animationInterval = (long)(interval * NANOSECONDSPERSECOND);
|
||||
}
|
||||
|
||||
private static native void nativeTouchesBegin(int[] id, float[] x, float[] y);
|
||||
private static native void nativeTouchesEnd(int[] id, float[] x, float[] y);
|
||||
private static native void nativeTouchesBegin(int id, float x, float y);
|
||||
private static native void nativeTouchesEnd(int id, float x, float y);
|
||||
private static native void nativeTouchesMove(int[] id, float[] x, float[] y);
|
||||
private static native void nativeTouchesCancel(int[] id, float[] x, float[] y);
|
||||
private static native void nativeRender();
|
||||
|
|
|
@ -1,812 +0,0 @@
|
|||
package org.cocos2dx.lib.touch.metalev.multitouch.controller;
|
||||
|
||||
/**
|
||||
* MultiTouchController.java
|
||||
*
|
||||
* Author: Luke Hutchison (luke.hutch@mit.edu)
|
||||
* Please drop me an email if you use this code so I can list your project here!
|
||||
*
|
||||
* Usage:
|
||||
* <code>
|
||||
* public class MyMTView extends View implements MultiTouchObjectCanvas<PinchWidgetType> {
|
||||
*
|
||||
* private MultiTouchController<PinchWidgetType> multiTouchController = new MultiTouchController<PinchWidgetType>(this);
|
||||
*
|
||||
* // Pass touch events to the MT controller
|
||||
* public boolean onTouchEvent(MotionEvent event) {
|
||||
* return multiTouchController.onTouchEvent(event);
|
||||
* }
|
||||
*
|
||||
* // ... then implement the MultiTouchObjectCanvas interface here, see details in the comments of that interface.
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* Changelog:
|
||||
* 2010-06-09 v1.5.1 Some API changes to make it possible to selectively update or not update scale / rotation.
|
||||
* Fixed anisotropic zoom. Cleaned up rotation code. Added more comments. Better var names. (LH)
|
||||
* 2010-06-09 v1.4 Added ability to track pinch rotation (Mickael Despesse, author of "Face Frenzy") and anisotropic pinch-zoom (LH)
|
||||
* 2010-06-09 v1.3.3 Bugfixes for Android-2.1; added optional debug info (LH)
|
||||
* 2010-06-09 v1.3 Ported to Android-2.2 (handle ACTION_POINTER_* actions); fixed several bugs; refactoring; documentation (LH)
|
||||
* 2010-05-17 v1.2.1 Dual-licensed under Apache and GPL licenses
|
||||
* 2010-02-18 v1.2 Support for compilation under Android 1.5/1.6 using introspection (mmin, author of handyCalc)
|
||||
* 2010-01-08 v1.1.1 Bugfixes to Cyanogen's patch that only showed up in more complex uses of controller (LH)
|
||||
* 2010-01-06 v1.1 Modified for official level 5 MT API (Cyanogen)
|
||||
* 2009-01-25 v1.0 Original MT controller, released for hacked G1 kernel (LH)
|
||||
*
|
||||
* Planned features:
|
||||
* - Add inertia (flick-pinch-zoom or flick-scroll)
|
||||
*
|
||||
* Known usages:
|
||||
* - Mickael Despesse's "Face Frenzy" face distortion app, to be published to the Market soon
|
||||
* - Yuan Chin's fork of ADW Launcher to support multitouch
|
||||
* - David Byrne's fractal viewing app Fractoid
|
||||
* - mmin's handyCalc calculator
|
||||
* - My own "MultiTouch Visualizer 2" in the Market
|
||||
* - Formerly: The browser in cyanogenmod (and before that, JesusFreke), and other firmwares like dwang5. This usage has been
|
||||
* replaced with official pinch/zoom in Maps, Browser and Gallery[3D] as of API level 5.
|
||||
*
|
||||
* License:
|
||||
* Dual-licensed under the Apache License v2 and the GPL v2.
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* A class that simplifies the implementation of multitouch in applications. Subclass this and read the fields here as needed in subclasses.
|
||||
*
|
||||
* @author Luke Hutchison
|
||||
*/
|
||||
public class MultiTouchController<T> {
|
||||
|
||||
/**
|
||||
* Time in ms required after a change in event status (e.g. putting down or lifting off the second finger) before events actually do anything --
|
||||
* helps eliminate noisy jumps that happen on change of status
|
||||
*/
|
||||
private static final long EVENT_SETTLE_TIME_INTERVAL = 20;
|
||||
|
||||
/**
|
||||
* The biggest possible abs val of the change in x or y between multitouch events (larger dx/dy events are ignored) -- helps eliminate jumps in
|
||||
* pointer position on finger 2 up/down.
|
||||
*/
|
||||
private static final float MAX_MULTITOUCH_POS_JUMP_SIZE = 30.0f;
|
||||
|
||||
/**
|
||||
* The biggest possible abs val of the change in multitouchWidth or multitouchHeight between multitouch events (larger-jump events are ignored) --
|
||||
* helps eliminate jumps in pointer position on finger 2 up/down.
|
||||
*/
|
||||
private static final float MAX_MULTITOUCH_DIM_JUMP_SIZE = 40.0f;
|
||||
|
||||
/** The smallest possible distance between multitouch points (used to avoid div-by-zero errors and display glitches) */
|
||||
private static final float MIN_MULTITOUCH_SEPARATION = 30.0f;
|
||||
|
||||
/** The max number of touch points that can be present on the screen at once */
|
||||
public static final int MAX_TOUCH_POINTS = 5;
|
||||
|
||||
/** Generate tons of log entries for debugging */
|
||||
public static final boolean DEBUG = false;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
MultiTouchObjectCanvas<T> objectCanvas;
|
||||
|
||||
/** The current touch point */
|
||||
public PointInfo mCurrPt;
|
||||
|
||||
/** The previous touch point */
|
||||
private PointInfo mPrevPt;
|
||||
|
||||
/** Fields extracted from mCurrPt */
|
||||
private float mCurrPtX, mCurrPtY, mCurrPtDiam, mCurrPtWidth, mCurrPtHeight, mCurrPtAng;
|
||||
|
||||
/**
|
||||
* Extract fields from mCurrPt, respecting the update* fields of mCurrPt. This just avoids code duplication. I hate that Java doesn't support
|
||||
* higher-order functions, tuples or multiple return values from functions.
|
||||
*/
|
||||
private void extractCurrPtInfo() {
|
||||
// Get new drag/pinch params. Only read multitouch fields that are needed,
|
||||
// to avoid unnecessary computation (diameter and angle are expensive operations).
|
||||
mCurrPtX = mCurrPt.getX();
|
||||
mCurrPtY = mCurrPt.getY();
|
||||
mCurrPtDiam = Math.max(MIN_MULTITOUCH_SEPARATION * .71f, !mCurrXform.updateScale ? 0.0f : mCurrPt.getMultiTouchDiameter());
|
||||
mCurrPtWidth = Math.max(MIN_MULTITOUCH_SEPARATION, !mCurrXform.updateScaleXY ? 0.0f : mCurrPt.getMultiTouchWidth());
|
||||
mCurrPtHeight = Math.max(MIN_MULTITOUCH_SEPARATION, !mCurrXform.updateScaleXY ? 0.0f : mCurrPt.getMultiTouchHeight());
|
||||
mCurrPtAng = !mCurrXform.updateAngle ? 0.0f : mCurrPt.getMultiTouchAngle();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** Whether to handle single-touch events/drags before multi-touch is initiated or not; if not, they are handled by subclasses */
|
||||
private boolean handleSingleTouchEvents;
|
||||
|
||||
/** The object being dragged/stretched */
|
||||
private T selectedObject = null;
|
||||
|
||||
/** Current position and scale of the dragged object */
|
||||
private PositionAndScale mCurrXform = new PositionAndScale();
|
||||
|
||||
/** Drag/pinch start time and time to ignore spurious events until (to smooth over event noise) */
|
||||
private long mSettleStartTime, mSettleEndTime;
|
||||
|
||||
/** Conversion from object coords to screen coords */
|
||||
private float startPosX, startPosY;
|
||||
|
||||
/** Conversion between scale and width, and object angle and start pinch angle */
|
||||
private float startScaleOverPinchDiam, startAngleMinusPinchAngle;
|
||||
|
||||
/** Conversion between X scale and width, and Y scale and height */
|
||||
private float startScaleXOverPinchWidth, startScaleYOverPinchHeight;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** No touch points down. */
|
||||
private static final int MODE_NOTHING = 0;
|
||||
|
||||
/** One touch point down, dragging an object. */
|
||||
private static final int MODE_DRAG = 1;
|
||||
|
||||
/** Two or more touch points down, stretching/rotating an object using the first two touch points. */
|
||||
private static final int MODE_PINCH = 2;
|
||||
|
||||
/** Current drag mode */
|
||||
private int mMode = MODE_NOTHING;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** Constructor that sets handleSingleTouchEvents to true */
|
||||
public MultiTouchController(MultiTouchObjectCanvas<T> objectCanvas) {
|
||||
this(objectCanvas, true);
|
||||
}
|
||||
|
||||
/** Full constructor */
|
||||
public MultiTouchController(MultiTouchObjectCanvas<T> objectCanvas, boolean handleSingleTouchEvents) {
|
||||
this.mCurrPt = new PointInfo();
|
||||
this.mPrevPt = new PointInfo();
|
||||
this.handleSingleTouchEvents = handleSingleTouchEvents;
|
||||
this.objectCanvas = objectCanvas;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Whether to handle single-touch events/drags before multi-touch is initiated or not; if not, they are handled by subclasses. Default: true
|
||||
*/
|
||||
protected void setHandleSingleTouchEvents(boolean handleSingleTouchEvents) {
|
||||
this.handleSingleTouchEvents = handleSingleTouchEvents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to handle single-touch events/drags before multi-touch is initiated or not; if not, they are handled by subclasses. Default: true
|
||||
*/
|
||||
protected boolean getHandleSingleTouchEvents() {
|
||||
return handleSingleTouchEvents;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
public static final boolean multiTouchSupported;
|
||||
private static Method m_getPointerCount;
|
||||
private static Method m_getPointerId;
|
||||
private static Method m_getPressure;
|
||||
private static Method m_getHistoricalX;
|
||||
private static Method m_getHistoricalY;
|
||||
private static Method m_getHistoricalPressure;
|
||||
private static Method m_getX;
|
||||
private static Method m_getY;
|
||||
private static int ACTION_POINTER_UP = 6;
|
||||
private static int ACTION_POINTER_INDEX_SHIFT = 8;
|
||||
|
||||
static {
|
||||
boolean succeeded = false;
|
||||
try {
|
||||
// Android 2.0.1 stuff:
|
||||
m_getPointerCount = MotionEvent.class.getMethod("getPointerCount");
|
||||
m_getPointerId = MotionEvent.class.getMethod("getPointerId", Integer.TYPE);
|
||||
m_getPressure = MotionEvent.class.getMethod("getPressure", Integer.TYPE);
|
||||
m_getHistoricalX = MotionEvent.class.getMethod("getHistoricalX", Integer.TYPE, Integer.TYPE);
|
||||
m_getHistoricalY = MotionEvent.class.getMethod("getHistoricalY", Integer.TYPE, Integer.TYPE);
|
||||
m_getHistoricalPressure = MotionEvent.class.getMethod("getHistoricalPressure", Integer.TYPE, Integer.TYPE);
|
||||
m_getX = MotionEvent.class.getMethod("getX", Integer.TYPE);
|
||||
m_getY = MotionEvent.class.getMethod("getY", Integer.TYPE);
|
||||
succeeded = true;
|
||||
} catch (Exception e) {
|
||||
Log.e("MultiTouchController", "static initializer failed", e);
|
||||
}
|
||||
multiTouchSupported = succeeded;
|
||||
if (multiTouchSupported) {
|
||||
// Android 2.2+ stuff (the original Android 2.2 consts are declared above,
|
||||
// and these actions aren't used previous to Android 2.2):
|
||||
try {
|
||||
ACTION_POINTER_UP = MotionEvent.class.getField("ACTION_POINTER_UP").getInt(null);
|
||||
ACTION_POINTER_INDEX_SHIFT = MotionEvent.class.getField("ACTION_POINTER_INDEX_SHIFT").getInt(null);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
private static final float[] xVals = new float[MAX_TOUCH_POINTS];
|
||||
private static final float[] yVals = new float[MAX_TOUCH_POINTS];
|
||||
private static final float[] pressureVals = new float[MAX_TOUCH_POINTS];
|
||||
private static final int[] pointerIds = new int[MAX_TOUCH_POINTS];
|
||||
|
||||
/** Process incoming touch events */
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
try {
|
||||
int pointerCount = multiTouchSupported ? (Integer) m_getPointerCount.invoke(event) : 1;
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 1 - " + multiTouchSupported + " " + mMode + " " + handleSingleTouchEvents + " " + pointerCount);
|
||||
if (mMode == MODE_NOTHING && !handleSingleTouchEvents && pointerCount == 1)
|
||||
// Not handling initial single touch events, just pass them on
|
||||
return false;
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 2");
|
||||
|
||||
// Handle history first (we sometimes get history with ACTION_MOVE events)
|
||||
int action = event.getAction();
|
||||
int histLen = event.getHistorySize() / pointerCount;
|
||||
for (int histIdx = 0; histIdx <= histLen; histIdx++) {
|
||||
// Read from history entries until histIdx == histLen, then read from current event
|
||||
boolean processingHist = histIdx < histLen;
|
||||
if (!multiTouchSupported || pointerCount == 1) {
|
||||
// Use single-pointer methods -- these are needed as a special case (for some weird reason) even if
|
||||
// multitouch is supported but there's only one touch point down currently -- event.getX(0) etc. throw
|
||||
// an exception if there's only one point down.
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 3");
|
||||
xVals[0] = processingHist ? event.getHistoricalX(histIdx) : event.getX();
|
||||
yVals[0] = processingHist ? event.getHistoricalY(histIdx) : event.getY();
|
||||
pressureVals[0] = processingHist ? event.getHistoricalPressure(histIdx) : event.getPressure();
|
||||
} else {
|
||||
// Read x, y and pressure of each pointer
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 4");
|
||||
int numPointers = Math.min(pointerCount, MAX_TOUCH_POINTS);
|
||||
if (DEBUG && pointerCount > MAX_TOUCH_POINTS)
|
||||
Log.i("MultiTouch", "Got more pointers than MAX_TOUCH_POINTS");
|
||||
for (int ptrIdx = 0; ptrIdx < numPointers; ptrIdx++) {
|
||||
int ptrId = (Integer) m_getPointerId.invoke(event, ptrIdx);
|
||||
pointerIds[ptrIdx] = ptrId;
|
||||
// N.B. if pointerCount == 1, then the following methods throw an array index out of range exception,
|
||||
// and the code above is therefore required not just for Android 1.5/1.6 but also for when there is
|
||||
// only one touch point on the screen -- pointlessly inconsistent :(
|
||||
xVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalX.invoke(event, ptrIdx, histIdx) : m_getX.invoke(event, ptrIdx));
|
||||
yVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalY.invoke(event, ptrIdx, histIdx) : m_getY.invoke(event, ptrIdx));
|
||||
pressureVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalPressure.invoke(event, ptrIdx, histIdx) : m_getPressure
|
||||
.invoke(event, ptrIdx));
|
||||
}
|
||||
}
|
||||
// Decode event
|
||||
decodeTouchEvent(pointerCount, xVals, yVals, pressureVals, pointerIds, //
|
||||
/* action = */processingHist ? MotionEvent.ACTION_MOVE : action, //
|
||||
/* down = */processingHist ? true : action != MotionEvent.ACTION_UP //
|
||||
&& (action & ((1 << ACTION_POINTER_INDEX_SHIFT) - 1)) != ACTION_POINTER_UP //
|
||||
&& action != MotionEvent.ACTION_CANCEL, //
|
||||
processingHist ? event.getHistoricalEventTime(histIdx) : event.getEventTime());
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
// In case any of the introspection stuff fails (it shouldn't)
|
||||
Log.e("MultiTouchController", "onTouchEvent() failed", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void decodeTouchEvent(int pointerCount, float[] x, float[] y, float[] pressure, int[] pointerIds, int action, boolean down, long eventTime) {
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 5 - " + pointerCount + " " + action + " " + down);
|
||||
|
||||
// Swap curr/prev points
|
||||
PointInfo tmp = mPrevPt;
|
||||
mPrevPt = mCurrPt;
|
||||
mCurrPt = tmp;
|
||||
// Overwrite old prev point
|
||||
mCurrPt.set(pointerCount, x, y, pressure, pointerIds, action, down, eventTime);
|
||||
multiTouchController();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
/** Start dragging/pinching, or reset drag/pinch to current point if something goes out of range */
|
||||
private void anchorAtThisPositionAndScale() {
|
||||
if (selectedObject == null)
|
||||
return;
|
||||
|
||||
// Get selected object's current position and scale
|
||||
objectCanvas.getPositionAndScale(selectedObject, mCurrXform);
|
||||
|
||||
// Figure out the object coords of the drag start point's screen coords.
|
||||
// All stretching should be around this point in object-coord-space.
|
||||
// Also figure out out ratio between object scale factor and multitouch
|
||||
// diameter at beginning of drag; same for angle and optional anisotropic
|
||||
// scale.
|
||||
float currScaleInv = 1.0f / (!mCurrXform.updateScale ? 1.0f : mCurrXform.scale == 0.0f ? 1.0f : mCurrXform.scale);
|
||||
extractCurrPtInfo();
|
||||
startPosX = (mCurrPtX - mCurrXform.xOff) * currScaleInv;
|
||||
startPosY = (mCurrPtY - mCurrXform.yOff) * currScaleInv;
|
||||
startScaleOverPinchDiam = mCurrXform.scale / mCurrPtDiam;
|
||||
startScaleXOverPinchWidth = mCurrXform.scaleX / mCurrPtWidth;
|
||||
startScaleYOverPinchHeight = mCurrXform.scaleY / mCurrPtHeight;
|
||||
startAngleMinusPinchAngle = mCurrXform.angle - mCurrPtAng;
|
||||
}
|
||||
|
||||
/** Drag/stretch/rotate the selected object using the current touch position(s) relative to the anchor position(s). */
|
||||
private void performDragOrPinch() {
|
||||
// Don't do anything if we're not dragging anything
|
||||
if (selectedObject == null)
|
||||
return;
|
||||
|
||||
// Calc new position of dragged object
|
||||
float currScale = !mCurrXform.updateScale ? 1.0f : mCurrXform.scale == 0.0f ? 1.0f : mCurrXform.scale;
|
||||
extractCurrPtInfo();
|
||||
float newPosX = mCurrPtX - startPosX * currScale;
|
||||
float newPosY = mCurrPtY - startPosY * currScale;
|
||||
float newScale = startScaleOverPinchDiam * mCurrPtDiam;
|
||||
float newScaleX = startScaleXOverPinchWidth * mCurrPtWidth;
|
||||
float newScaleY = startScaleYOverPinchHeight * mCurrPtHeight;
|
||||
float newAngle = startAngleMinusPinchAngle + mCurrPtAng;
|
||||
|
||||
// Set the new obj coords, scale, and angle as appropriate (notifying the subclass of the change).
|
||||
mCurrXform.set(newPosX, newPosY, newScale, newScaleX, newScaleY, newAngle);
|
||||
|
||||
boolean success = objectCanvas.setPositionAndScale(selectedObject, mCurrXform, mCurrPt);
|
||||
if (!success)
|
||||
; // If we could't set those params, do nothing currently
|
||||
}
|
||||
|
||||
/**
|
||||
* State-based controller for tracking switches between no-touch, single-touch and multi-touch situations. Includes logic for cleaning up the
|
||||
* event stream, as events around touch up/down are noisy at least on early Synaptics sensors.
|
||||
*/
|
||||
private void multiTouchController() {
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 6 - " + mMode + " " + mCurrPt.getNumTouchPoints() + " " + mCurrPt.isDown() + mCurrPt.isMultiTouch());
|
||||
|
||||
switch (mMode) {
|
||||
case MODE_NOTHING:
|
||||
// Not doing anything currently
|
||||
if (mCurrPt.isDown()) {
|
||||
// Start a new single-point drag
|
||||
selectedObject = objectCanvas.getDraggableObjectAtPoint(mCurrPt);
|
||||
if (selectedObject != null) {
|
||||
// Started a new single-point drag
|
||||
mMode = MODE_DRAG;
|
||||
objectCanvas.selectObject(selectedObject, mCurrPt);
|
||||
anchorAtThisPositionAndScale();
|
||||
// Don't need any settling time if just placing one finger, there is no noise
|
||||
mSettleStartTime = mSettleEndTime = mCurrPt.getEventTime();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MODE_DRAG:
|
||||
// Currently in a single-point drag
|
||||
if (!mCurrPt.isDown()) {
|
||||
// First finger was released, stop dragging
|
||||
mMode = MODE_NOTHING;
|
||||
objectCanvas.selectObject((selectedObject = null), mCurrPt);
|
||||
|
||||
} else if (mCurrPt.isMultiTouch()) {
|
||||
// Point 1 was already down and point 2 was just placed down
|
||||
mMode = MODE_PINCH;
|
||||
// Restart the drag with the new drag position (that is at the midpoint between the touchpoints)
|
||||
anchorAtThisPositionAndScale();
|
||||
// Need to let events settle before moving things, to help with event noise on touchdown
|
||||
mSettleStartTime = mCurrPt.getEventTime();
|
||||
mSettleEndTime = mSettleStartTime + EVENT_SETTLE_TIME_INTERVAL;
|
||||
|
||||
} else {
|
||||
// Point 1 is still down and point 2 did not change state, just do single-point drag to new location
|
||||
if (mCurrPt.getEventTime() < mSettleEndTime) {
|
||||
// Ignore the first few events if we just stopped stretching, because if finger 2 was kept down while
|
||||
// finger 1 is lifted, then point 1 gets mapped to finger 2. Restart the drag from the new position.
|
||||
anchorAtThisPositionAndScale();
|
||||
} else {
|
||||
// Keep dragging, move to new point
|
||||
performDragOrPinch();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MODE_PINCH:
|
||||
// Two-point pinch-scale/rotate/translate
|
||||
if (!mCurrPt.isMultiTouch() || !mCurrPt.isDown()) {
|
||||
// Dropped one or both points, stop stretching
|
||||
|
||||
if (!mCurrPt.isDown()) {
|
||||
// Dropped both points, go back to doing nothing
|
||||
mMode = MODE_NOTHING;
|
||||
objectCanvas.selectObject((selectedObject = null), mCurrPt);
|
||||
|
||||
} else {
|
||||
// Just dropped point 2, downgrade to a single-point drag
|
||||
mMode = MODE_DRAG;
|
||||
// Restart the pinch with the single-finger position
|
||||
anchorAtThisPositionAndScale();
|
||||
// Ignore the first few events after the drop, in case we dropped finger 1 and left finger 2 down
|
||||
mSettleStartTime = mCurrPt.getEventTime();
|
||||
mSettleEndTime = mSettleStartTime + EVENT_SETTLE_TIME_INTERVAL;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Still pinching
|
||||
if (Math.abs(mCurrPt.getX() - mPrevPt.getX()) > MAX_MULTITOUCH_POS_JUMP_SIZE
|
||||
|| Math.abs(mCurrPt.getY() - mPrevPt.getY()) > MAX_MULTITOUCH_POS_JUMP_SIZE
|
||||
|| Math.abs(mCurrPt.getMultiTouchWidth() - mPrevPt.getMultiTouchWidth()) * .5f > MAX_MULTITOUCH_DIM_JUMP_SIZE
|
||||
|| Math.abs(mCurrPt.getMultiTouchHeight() - mPrevPt.getMultiTouchHeight()) * .5f > MAX_MULTITOUCH_DIM_JUMP_SIZE) {
|
||||
// Jumped too far, probably event noise, reset and ignore events for a bit
|
||||
anchorAtThisPositionAndScale();
|
||||
mSettleStartTime = mCurrPt.getEventTime();
|
||||
mSettleEndTime = mSettleStartTime + EVENT_SETTLE_TIME_INTERVAL;
|
||||
|
||||
} else if (mCurrPt.eventTime < mSettleEndTime) {
|
||||
// Events have not yet settled, reset
|
||||
anchorAtThisPositionAndScale();
|
||||
} else {
|
||||
// Stretch to new position and size
|
||||
performDragOrPinch();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 7 - " + mMode + " " + mCurrPt.getNumTouchPoints() + " " + mCurrPt.isDown() + mCurrPt.isMultiTouch());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
/** A class that packages up all MotionEvent information with all derived multitouch information (if available) */
|
||||
public static class PointInfo {
|
||||
// Multitouch information
|
||||
private int numPoints;
|
||||
private float[] xs = new float[MAX_TOUCH_POINTS];
|
||||
private float[] ys = new float[MAX_TOUCH_POINTS];
|
||||
private float[] pressures = new float[MAX_TOUCH_POINTS];
|
||||
private int[] pointerIds = new int[MAX_TOUCH_POINTS];
|
||||
|
||||
// Midpoint of pinch operations
|
||||
private float xMid, yMid, pressureMid;
|
||||
|
||||
// Width/diameter/angle of pinch operations
|
||||
private float dx, dy, diameter, diameterSq, angle;
|
||||
|
||||
// Whether or not there is at least one finger down (isDown) and/or at least two fingers down (isMultiTouch)
|
||||
private boolean isDown, isMultiTouch;
|
||||
|
||||
// Whether or not these fields have already been calculated, for caching purposes
|
||||
private boolean diameterSqIsCalculated, diameterIsCalculated, angleIsCalculated;
|
||||
|
||||
// Event action code and event time
|
||||
private int action;
|
||||
private long eventTime;
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** Set all point info */
|
||||
private void set(int numPoints, float[] x, float[] y, float[] pressure, int[] pointerIds, int action, boolean isDown, long eventTime) {
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 8 - " + +numPoints + " " + x[0] + " " + y[0] + " " + (numPoints > 1 ? x[1] : x[0]) + " "
|
||||
+ (numPoints > 1 ? y[1] : y[0]) + " " + action + " " + isDown);
|
||||
this.eventTime = eventTime;
|
||||
this.action = action;
|
||||
this.numPoints = numPoints;
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
this.xs[i] = x[i];
|
||||
this.ys[i] = y[i];
|
||||
this.pressures[i] = pressure[i];
|
||||
this.pointerIds[i] = pointerIds[i];
|
||||
}
|
||||
this.isDown = isDown;
|
||||
this.isMultiTouch = numPoints >= 2;
|
||||
|
||||
if (isMultiTouch) {
|
||||
xMid = (x[0] + x[1]) * .5f;
|
||||
yMid = (y[0] + y[1]) * .5f;
|
||||
pressureMid = (pressure[0] + pressure[1]) * .5f;
|
||||
dx = Math.abs(x[1] - x[0]);
|
||||
dy = Math.abs(y[1] - y[0]);
|
||||
|
||||
} else {
|
||||
// Single-touch event
|
||||
xMid = x[0];
|
||||
yMid = y[0];
|
||||
pressureMid = pressure[0];
|
||||
dx = dy = 0.0f;
|
||||
}
|
||||
// Need to re-calculate the expensive params if they're needed
|
||||
diameterSqIsCalculated = diameterIsCalculated = angleIsCalculated = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy all fields from one PointInfo class to another. PointInfo objects are volatile so you should use this if you want to keep track of the
|
||||
* last touch event in your own code.
|
||||
*/
|
||||
public void set(PointInfo other) {
|
||||
this.numPoints = other.numPoints;
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
this.xs[i] = other.xs[i];
|
||||
this.ys[i] = other.ys[i];
|
||||
this.pressures[i] = other.pressures[i];
|
||||
this.pointerIds[i] = other.pointerIds[i];
|
||||
}
|
||||
this.xMid = other.xMid;
|
||||
this.yMid = other.yMid;
|
||||
this.pressureMid = other.pressureMid;
|
||||
this.dx = other.dx;
|
||||
this.dy = other.dy;
|
||||
this.diameter = other.diameter;
|
||||
this.diameterSq = other.diameterSq;
|
||||
this.angle = other.angle;
|
||||
this.isDown = other.isDown;
|
||||
this.action = other.action;
|
||||
this.isMultiTouch = other.isMultiTouch;
|
||||
this.diameterIsCalculated = other.diameterIsCalculated;
|
||||
this.diameterSqIsCalculated = other.diameterSqIsCalculated;
|
||||
this.angleIsCalculated = other.angleIsCalculated;
|
||||
this.eventTime = other.eventTime;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** True if number of touch points >= 2. */
|
||||
public boolean isMultiTouch() {
|
||||
return isMultiTouch;
|
||||
}
|
||||
|
||||
/** Difference between x coords of touchpoint 0 and 1. */
|
||||
public float getMultiTouchWidth() {
|
||||
return isMultiTouch ? dx : 0.0f;
|
||||
}
|
||||
|
||||
/** Difference between y coords of touchpoint 0 and 1. */
|
||||
public float getMultiTouchHeight() {
|
||||
return isMultiTouch ? dy : 0.0f;
|
||||
}
|
||||
|
||||
/** Fast integer sqrt, by Jim Ulery. Much faster than Math.sqrt() for integers. */
|
||||
private int julery_isqrt(int val) {
|
||||
int temp, g = 0, b = 0x8000, bshft = 15;
|
||||
do {
|
||||
if (val >= (temp = (((g << 1) + b) << bshft--))) {
|
||||
g += b;
|
||||
val -= temp;
|
||||
}
|
||||
} while ((b >>= 1) > 0);
|
||||
return g;
|
||||
}
|
||||
|
||||
/** Calculate the squared diameter of the multitouch event, and cache it. Use this if you don't need to perform the sqrt. */
|
||||
public float getMultiTouchDiameterSq() {
|
||||
if (!diameterSqIsCalculated) {
|
||||
diameterSq = (isMultiTouch ? dx * dx + dy * dy : 0.0f);
|
||||
diameterSqIsCalculated = true;
|
||||
}
|
||||
return diameterSq;
|
||||
}
|
||||
|
||||
/** Calculate the diameter of the multitouch event, and cache it. Uses fast int sqrt but gives accuracy to 1/16px. */
|
||||
public float getMultiTouchDiameter() {
|
||||
if (!diameterIsCalculated) {
|
||||
if (!isMultiTouch) {
|
||||
diameter = 0.0f;
|
||||
} else {
|
||||
// Get 1/16 pixel's worth of subpixel accuracy, works on screens up to 2048x2048
|
||||
// before we get overflow (at which point you can reduce or eliminate subpix
|
||||
// accuracy, or use longs in julery_isqrt())
|
||||
float diamSq = getMultiTouchDiameterSq();
|
||||
diameter = (diamSq == 0.0f ? 0.0f : (float) julery_isqrt((int) (256 * diamSq)) / 16.0f);
|
||||
// Make sure diameter is never less than dx or dy, for trig purposes
|
||||
if (diameter < dx)
|
||||
diameter = dx;
|
||||
if (diameter < dy)
|
||||
diameter = dy;
|
||||
}
|
||||
diameterIsCalculated = true;
|
||||
}
|
||||
return diameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the angle of a multitouch event, and cache it. Actually gives the smaller of the two angles between the x axis and the line
|
||||
* between the two touchpoints, so range is [0,Math.PI/2]. Uses Math.atan2().
|
||||
*/
|
||||
public float getMultiTouchAngle() {
|
||||
if (!angleIsCalculated) {
|
||||
if (!isMultiTouch)
|
||||
angle = 0.0f;
|
||||
else
|
||||
angle = (float) Math.atan2(ys[1] - ys[0], xs[1] - xs[0]);
|
||||
angleIsCalculated = true;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** Return the total number of touch points */
|
||||
public int getNumTouchPoints() {
|
||||
return numPoints;
|
||||
}
|
||||
|
||||
/** Return the X coord of the first touch point if there's only one, or the midpoint between first and second touch points if two or more. */
|
||||
public float getX() {
|
||||
return xMid;
|
||||
}
|
||||
|
||||
/** Return the array of X coords -- only the first getNumTouchPoints() of these is defined. */
|
||||
public float[] getXs() {
|
||||
return xs;
|
||||
}
|
||||
|
||||
/** Return the X coord of the first touch point if there's only one, or the midpoint between first and second touch points if two or more. */
|
||||
public float getY() {
|
||||
return yMid;
|
||||
}
|
||||
|
||||
/** Return the array of Y coords -- only the first getNumTouchPoints() of these is defined. */
|
||||
public float[] getYs() {
|
||||
return ys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the array of pointer ids -- only the first getNumTouchPoints() of these is defined. These don't have to be all the numbers from 0 to
|
||||
* getNumTouchPoints()-1 inclusive, numbers can be skipped if a finger is lifted and the touch sensor is capable of detecting that that
|
||||
* particular touch point is no longer down. Note that a lot of sensors do not have this capability: when finger 1 is lifted up finger 2
|
||||
* becomes the new finger 1. However in theory these IDs can correct for that. Convert back to indices using MotionEvent.findPointerIndex().
|
||||
*/
|
||||
public int[] getPointerIds() {
|
||||
return pointerIds;
|
||||
}
|
||||
|
||||
/** Return the pressure the first touch point if there's only one, or the average pressure of first and second touch points if two or more. */
|
||||
public float getPressure() {
|
||||
return pressureMid;
|
||||
}
|
||||
|
||||
/** Return the array of pressures -- only the first getNumTouchPoints() of these is defined. */
|
||||
public float[] getPressures() {
|
||||
return pressures;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
public boolean isDown() {
|
||||
return isDown;
|
||||
}
|
||||
|
||||
public int getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public long getEventTime() {
|
||||
return eventTime;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A class that is used to store scroll offsets and scale information for objects that are managed by the multitouch controller
|
||||
*/
|
||||
public static class PositionAndScale {
|
||||
private float xOff, yOff, scale, scaleX, scaleY, angle;
|
||||
private boolean updateScale, updateScaleXY, updateAngle;
|
||||
|
||||
/**
|
||||
* Set position and optionally scale, anisotropic scale, and/or angle. Where if the corresponding "update" flag is set to false, the field's
|
||||
* value will not be changed during a pinch operation. If the value is not being updated *and* the value is not used by the client
|
||||
* application, then the value can just be zero. However if the value is not being updated but the value *is* being used by the client
|
||||
* application, the value should still be specified and the update flag should be false (e.g. angle of the object being dragged should still
|
||||
* be specified even if the program is in "resize" mode rather than "rotate" mode).
|
||||
*/
|
||||
public void set(float xOff, float yOff, boolean updateScale, float scale, boolean updateScaleXY, float scaleX, float scaleY,
|
||||
boolean updateAngle, float angle) {
|
||||
this.xOff = xOff;
|
||||
this.yOff = yOff;
|
||||
this.updateScale = updateScale;
|
||||
this.scale = scale == 0.0f ? 1.0f : scale;
|
||||
this.updateScaleXY = updateScaleXY;
|
||||
this.scaleX = scaleX == 0.0f ? 1.0f : scaleX;
|
||||
this.scaleY = scaleY == 0.0f ? 1.0f : scaleY;
|
||||
this.updateAngle = updateAngle;
|
||||
this.angle = angle;
|
||||
}
|
||||
|
||||
/** Set position and optionally scale, anisotropic scale, and/or angle, without changing the "update" flags. */
|
||||
protected void set(float xOff, float yOff, float scale, float scaleX, float scaleY, float angle) {
|
||||
this.xOff = xOff;
|
||||
this.yOff = yOff;
|
||||
this.scale = scale == 0.0f ? 1.0f : scale;
|
||||
this.scaleX = scaleX == 0.0f ? 1.0f : scaleX;
|
||||
this.scaleY = scaleY == 0.0f ? 1.0f : scaleY;
|
||||
this.angle = angle;
|
||||
}
|
||||
|
||||
public float getXOff() {
|
||||
return xOff;
|
||||
}
|
||||
|
||||
public float getYOff() {
|
||||
return yOff;
|
||||
}
|
||||
|
||||
public float getScale() {
|
||||
return !updateScale ? 1.0f : scale;
|
||||
}
|
||||
|
||||
/** Included in case you want to support anisotropic scaling */
|
||||
public float getScaleX() {
|
||||
return !updateScaleXY ? 1.0f : scaleX;
|
||||
}
|
||||
|
||||
/** Included in case you want to support anisotropic scaling */
|
||||
public float getScaleY() {
|
||||
return !updateScaleXY ? 1.0f : scaleY;
|
||||
}
|
||||
|
||||
public float getAngle() {
|
||||
return !updateAngle ? 0.0f : angle;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
public static interface MultiTouchObjectCanvas<T> {
|
||||
|
||||
/**
|
||||
* See if there is a draggable object at the current point. Returns the object at the point, or null if nothing to drag. To start a multitouch
|
||||
* drag/stretch operation, this routine must return some non-null reference to an object. This object is passed into the other methods in this
|
||||
* interface when they are called.
|
||||
*
|
||||
* @param touchPoint
|
||||
* The point being tested (in object coordinates). Return the topmost object under this point, or if dragging/stretching the whole
|
||||
* canvas, just return a reference to the canvas.
|
||||
* @return a reference to the object under the point being tested, or null to cancel the drag operation. If dragging/stretching the whole
|
||||
* canvas (e.g. in a photo viewer), always return non-null, otherwise the stretch operation won't work.
|
||||
*/
|
||||
public T getDraggableObjectAtPoint(PointInfo touchPoint);
|
||||
|
||||
/**
|
||||
* Get the screen coords of the dragged object's origin, and scale multiplier to convert screen coords to obj coords. The job of this routine
|
||||
* is to call the .set() method on the passed PositionAndScale object to record the initial position and scale of the object (in object
|
||||
* coordinates) before any dragging/stretching takes place.
|
||||
*
|
||||
* @param obj
|
||||
* The object being dragged/stretched.
|
||||
* @param objPosAndScaleOut
|
||||
* Output parameter: You need to call objPosAndScaleOut.set() to record the current position and scale of obj.
|
||||
*/
|
||||
public void getPositionAndScale(T obj, PositionAndScale objPosAndScaleOut);
|
||||
|
||||
/**
|
||||
* Callback to update the position and scale (in object coords) of the currently-dragged object.
|
||||
*
|
||||
* @param obj
|
||||
* The object being dragged/stretched.
|
||||
* @param newObjPosAndScale
|
||||
* The new position and scale of the object, in object coordinates. Use this to move/resize the object before returning.
|
||||
* @param touchPoint
|
||||
* Info about the current touch point, including multitouch information and utilities to calculate and cache multitouch pinch
|
||||
* diameter etc. (Note: touchPoint is volatile, if you want to keep any fields of touchPoint, you must copy them before the method
|
||||
* body exits.)
|
||||
* @return true if setting the position and scale of the object was successful, or false if the position or scale parameters are out of range
|
||||
* for this object.
|
||||
*/
|
||||
public boolean setPositionAndScale(T obj, PositionAndScale newObjPosAndScale, PointInfo touchPoint);
|
||||
|
||||
/**
|
||||
* Select an object at the given point. Can be used to bring the object to top etc. Only called when first touchpoint goes down, not when
|
||||
* multitouch is initiated. Also called with null on touch-up.
|
||||
*
|
||||
* @param obj
|
||||
* The object being selected by single-touch, or null on touch-up.
|
||||
* @param touchPoint
|
||||
* The current touch point.
|
||||
*/
|
||||
public void selectObject(T obj, PointInfo touchPoint);
|
||||
}
|
||||
}
|
|
@ -1 +1 @@
|
|||
fe4815b00d6e0564ee73979cc062a3b81ee0ae79
|
||||
d09725f4302ca8fa1f0ce71afbe4ad0ab9418713
|
|
@ -45,6 +45,7 @@ files
|
|||
("cocos2dx/cocoa")
|
||||
[cocoa]
|
||||
"*.cpp"
|
||||
"*.h"
|
||||
|
||||
("cocos2dx/effects")
|
||||
[effects]
|
||||
|
|
|
@ -25,6 +25,7 @@ cocoa/CCAffineTransform.cpp \
|
|||
cocoa/CCGeometry.cpp \
|
||||
cocoa/CCAutoreleasePool.cpp \
|
||||
cocoa/CCData.cpp \
|
||||
cocoa/CCNS.cpp \
|
||||
cocoa/CCObject.cpp \
|
||||
cocoa/CCSet.cpp \
|
||||
cocoa/CCZone.cpp \
|
||||
|
@ -64,7 +65,6 @@ platform/CCCommon.cpp \
|
|||
platform/CCParticleSystemPoint_mobile.cpp \
|
||||
platform/CCTransition_mobile.cpp \
|
||||
platform/platform.cpp \
|
||||
platform/android/CCNS_android.cpp \
|
||||
platform/android/CCEGLView_android.cpp \
|
||||
platform/android/CCAccelerometer_android.cpp \
|
||||
platform/android/CCApplication_android.cpp \
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2010 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "CCNS.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef std::vector<std::string> strArray;
|
||||
|
||||
// string toolkit
|
||||
void split(std::string src, const char* token, strArray& vect)
|
||||
{
|
||||
int nend=0;
|
||||
int nbegin=0;
|
||||
while(nend != -1)
|
||||
{
|
||||
nend = src.find(token, nbegin);
|
||||
if(nend == -1)
|
||||
vect.push_back(src.substr(nbegin, src.length()-nbegin));
|
||||
else
|
||||
vect.push_back(src.substr(nbegin, nend-nbegin));
|
||||
nbegin = nend + strlen(token);
|
||||
}
|
||||
}
|
||||
|
||||
// first, judge whether the form of the string like this: {x,y}
|
||||
// if the form is right,the string will be splited into the parameter strs;
|
||||
// or the parameter strs will be empty.
|
||||
// if the form is right return true,else return false.
|
||||
bool splitWithForm(const char* pStr, strArray& strs)
|
||||
{
|
||||
bool bRet = false;
|
||||
|
||||
do
|
||||
{
|
||||
CC_BREAK_IF(!pStr);
|
||||
|
||||
// string is empty
|
||||
std::string content = pStr;
|
||||
CC_BREAK_IF(content.length() == 0);
|
||||
|
||||
int nPosLeft = content.find('{');
|
||||
int nPosRight = content.find('}');
|
||||
|
||||
// don't have '{' and '}'
|
||||
CC_BREAK_IF(nPosLeft == std::string::npos || nPosRight == std::string::npos);
|
||||
// '}' is before '{'
|
||||
CC_BREAK_IF(nPosLeft > nPosRight);
|
||||
|
||||
std::string pointStr = content.substr(nPosLeft + 1, nPosRight - nPosLeft - 1);
|
||||
// nothing between '{' and '}'
|
||||
CC_BREAK_IF(pointStr.length() == 0);
|
||||
|
||||
int nPos1 = pointStr.find('{');
|
||||
int nPos2 = pointStr.find('}');
|
||||
// contain '{' or '}'
|
||||
CC_BREAK_IF(nPos1 != std::string::npos || nPos2 != std::string::npos);
|
||||
|
||||
split(pointStr, ",", strs);
|
||||
if (strs.size() != 2 || strs[0].length() == 0 || strs[1].length() == 0)
|
||||
{
|
||||
strs.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
bRet = true;
|
||||
} while (0);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
// implement the functions
|
||||
namespace cocos2d
|
||||
{
|
||||
CCRect CCRectFromString(const char* pszContent)
|
||||
{
|
||||
CCRect result = CCRectZero;
|
||||
|
||||
do
|
||||
{
|
||||
CC_BREAK_IF(!pszContent);
|
||||
std::string content = pszContent;
|
||||
|
||||
// find the first '{' and the third '}'
|
||||
int nPosLeft = content.find('{');
|
||||
int nPosRight = content.find('}');
|
||||
for (int i = 1; i < 3; ++i)
|
||||
{
|
||||
if (nPosRight == std::string::npos)
|
||||
{
|
||||
break;
|
||||
}
|
||||
nPosRight = content.find('}', nPosRight + 1);
|
||||
}
|
||||
CC_BREAK_IF(nPosLeft == std::string::npos || nPosRight == std::string::npos);
|
||||
|
||||
content = content.substr(nPosLeft + 1, nPosRight - nPosLeft - 1);
|
||||
int nPointEnd = content.find('}');
|
||||
CC_BREAK_IF(nPointEnd == std::string::npos);
|
||||
nPointEnd = content.find(',', nPointEnd);
|
||||
CC_BREAK_IF(nPointEnd == std::string::npos);
|
||||
|
||||
// get the point string and size string
|
||||
std::string pointStr = content.substr(0, nPointEnd);
|
||||
std::string sizeStr = content.substr(nPointEnd + 1, content.length() - nPointEnd);
|
||||
|
||||
// split the string with ','
|
||||
strArray pointInfo;
|
||||
CC_BREAK_IF(!splitWithForm(pointStr.c_str(), pointInfo));
|
||||
strArray sizeInfo;
|
||||
CC_BREAK_IF(!splitWithForm(sizeStr.c_str(), sizeInfo));
|
||||
|
||||
float x = (float) atof(pointInfo[0].c_str());
|
||||
float y = (float) atof(pointInfo[1].c_str());
|
||||
float width = (float) atof(sizeInfo[0].c_str());
|
||||
float height = (float) atof(sizeInfo[1].c_str());
|
||||
|
||||
result = CCRectMake(x, y, width, height);
|
||||
} while (0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CCPoint CCPointFromString(const char* pszContent)
|
||||
{
|
||||
CCPoint ret = CCPointZero;
|
||||
|
||||
do
|
||||
{
|
||||
strArray strs;
|
||||
CC_BREAK_IF(!splitWithForm(pszContent, strs));
|
||||
|
||||
float x = (float) atof(strs[0].c_str());
|
||||
float y = (float) atof(strs[1].c_str());
|
||||
|
||||
ret = CCPointMake(x, y);
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CCSize CCSizeFromString(const char* pszContent)
|
||||
{
|
||||
CCSize ret = CCSizeZero;
|
||||
|
||||
do
|
||||
{
|
||||
strArray strs;
|
||||
CC_BREAK_IF(!splitWithForm(pszContent, strs));
|
||||
|
||||
float width = (float) atof(strs[0].c_str());
|
||||
float height = (float) atof(strs[1].c_str());
|
||||
|
||||
ret = CCSizeMake(width, height);
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2010 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __PLATFOMR_CCNS_H__
|
||||
#define __PLATFOMR_CCNS_H__
|
||||
|
||||
#include "CCGeometry.h"
|
||||
|
||||
namespace cocos2d
|
||||
{
|
||||
/**
|
||||
@brief Returns a Core Graphics rectangle structure corresponding to the data in a given string.
|
||||
@param pszContent A string object whose contents are of the form "{{x,y},{w, h}}",
|
||||
where x is the x coordinate, y is the y coordinate, w is the width, and h is the height.
|
||||
These components can represent integer or float values.
|
||||
An example of a valid string is "{{3,2},{4,5}}".
|
||||
The string is not localized, so items are always separated with a comma.
|
||||
@return A Core Graphics structure that represents a rectangle.
|
||||
If the string is not well-formed, the function returns CCRectZero.
|
||||
*/
|
||||
CCRect CCRectFromString(const char* pszContent);
|
||||
|
||||
/**
|
||||
@brief Returns a Core Graphics point structure corresponding to the data in a given string.
|
||||
@param pszContent A string object whose contents are of the form "{x,y}",
|
||||
where x is the x coordinate and y is the y coordinate.
|
||||
The x and y values can represent integer or float values.
|
||||
An example of a valid string is "{3.0,2.5}".
|
||||
The string is not localized, so items are always separated with a comma.
|
||||
@return A Core Graphics structure that represents a point.
|
||||
If the string is not well-formed, the function returns CCPointZero.
|
||||
*/
|
||||
CCPoint CCPointFromString(const char* pszContent);
|
||||
|
||||
/**
|
||||
@brief Returns a Core Graphics size structure corresponding to the data in a given string.
|
||||
@param pszContent A string object whose contents are of the form "{w, h}",
|
||||
where w is the width and h is the height.
|
||||
The w and h values can be integer or float values.
|
||||
An example of a valid string is "{3.0,2.5}".
|
||||
The string is not localized, so items are always separated with a comma.
|
||||
@return A Core Graphics structure that represents a size.
|
||||
If the string is not well-formed, the function returns CCSizeZero.
|
||||
*/
|
||||
CCSize CCSizeFromString(const char* pszContent);
|
||||
}
|
||||
|
||||
#endif // __PLATFOMR_CCNS_H__
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ private:
|
|||
|
||||
protected:
|
||||
CCDictionary<std::string, CCSpriteFrame*> *m_pSpriteFrames;
|
||||
CCDictionary<std::string, CCSpriteFrame*> *m_pSpriteFramesAliases;
|
||||
CCDictionary<std::string, CCString*> *m_pSpriteFramesAliases;
|
||||
};
|
||||
}//namespace cocos2d
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "platform/CCNS.h"
|
||||
#include "cocoa/CCNS.h"
|
||||
#include "CCDirector.h"
|
||||
#include "CCScene.h"
|
||||
#include "CCMutableArray.h"
|
||||
|
|
|
@ -24,7 +24,7 @@ THE SOFTWARE.
|
|||
|
||||
#include "CCFileUtils.h"
|
||||
|
||||
#if (CC_TARGET_PLATFORM != CC_PLATFORM_IOS && CC_TARGET_PLATFORM != CC_PLATFORM_AIRPLAY)
|
||||
#if (CC_TARGET_PLATFORM != CC_PLATFORM_IOS) && (CC_TARGET_PLATFORM != CC_PLATFORM_AIRPLAY)
|
||||
|
||||
#include <stack>
|
||||
#include <libxml/parser.h>
|
||||
|
@ -55,12 +55,18 @@ public:
|
|||
std::stack<CCDictionary<std::string, CCObject*>*> m_tDictStack;
|
||||
std::string m_sCurKey;///< parsed key
|
||||
CCSAXState m_tState;
|
||||
bool m_bInArray;
|
||||
CCMutableArray<CCObject*> *m_pArray;
|
||||
|
||||
public:
|
||||
CCDictMaker()
|
||||
{
|
||||
m_pRootDict = NULL;
|
||||
m_pCurDict = NULL;
|
||||
m_tState = SAX_NONE;
|
||||
|
||||
m_pArray = NULL;
|
||||
m_bInArray = false;
|
||||
}
|
||||
~CCDictMaker()
|
||||
{
|
||||
|
@ -119,6 +125,11 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
if (sName == "array")
|
||||
{
|
||||
m_bInArray = true;
|
||||
m_pArray = new CCMutableArray<CCObject*>();
|
||||
}
|
||||
m_tState = SAX_NONE;
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +145,14 @@ public:
|
|||
m_pCurDict = (CCDictionary<std::string, CCObject*>*)(m_tDictStack.top());
|
||||
}
|
||||
}
|
||||
else if (sName == "array")
|
||||
{
|
||||
CCAssert(m_bInArray, "The plist file is wrong!");
|
||||
m_pCurDict->setObject(m_pArray, m_sCurKey);
|
||||
m_pArray->release();
|
||||
m_pArray = NULL;
|
||||
m_bInArray = false;
|
||||
}
|
||||
m_tState = SAX_NONE;
|
||||
}
|
||||
|
||||
|
@ -156,7 +175,15 @@ public:
|
|||
case SAX_STRING:
|
||||
{
|
||||
CCAssert(!m_sCurKey.empty(), "not found key : <integet/real>");
|
||||
m_pCurDict->setObject(pText, m_sCurKey);
|
||||
|
||||
if (m_bInArray)
|
||||
{
|
||||
m_pArray->addObject(pText);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pCurDict->setObject(pText, m_sCurKey);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2010 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __PLATFOMR_CCNS_H__
|
||||
#define __PLATFOMR_CCNS_H__
|
||||
|
||||
#include "CCGeometry.h"
|
||||
|
||||
namespace cocos2d
|
||||
{
|
||||
CCRect CCRectFromString(const char* pszContent);
|
||||
CCPoint CCPointFromString(const char* pszContent);
|
||||
CCSize CCSizeFromString(const char* pszContent);
|
||||
}
|
||||
|
||||
#endif // __PLATFOMR_CCNS_H__
|
||||
|
||||
|
|
@ -53,6 +53,8 @@ public:
|
|||
std::stack<CCDictionary<std::string, CCObject*>*> m_tDictStack;
|
||||
std::string m_sCurKey;///< parsed key
|
||||
CCSAXState m_tState;
|
||||
bool m_bInArray;
|
||||
CCMutableArray<CCObject*> *m_pArray;
|
||||
|
||||
public:
|
||||
CCDictMaker()
|
||||
|
@ -60,6 +62,9 @@ public:
|
|||
m_pRootDict = NULL;
|
||||
m_pCurDict = NULL;
|
||||
m_tState = SAX_NONE;
|
||||
|
||||
m_pArray = NULL;
|
||||
m_bInArray = false;
|
||||
}
|
||||
~CCDictMaker()
|
||||
{
|
||||
|
@ -80,91 +85,115 @@ public:
|
|||
|
||||
void startElement(void *ctx, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
CCDictMaker *pMaker = this;
|
||||
std::string sName((char*)name);
|
||||
if( sName == "dict" )
|
||||
{
|
||||
CCDictionary<std::string, CCObject*> *pNewDict = new CCDictionary<std::string, CCObject*>();
|
||||
if(! pMaker->m_pRootDict)
|
||||
if(! m_pRootDict)
|
||||
{
|
||||
pMaker->m_pRootDict = pNewDict;
|
||||
m_pRootDict = pNewDict;
|
||||
pNewDict->autorelease();
|
||||
}
|
||||
else
|
||||
{
|
||||
CCAssert(pMaker->m_pCurDict && !pMaker->m_sCurKey.empty(), "");
|
||||
pMaker->m_pCurDict->setObject(pNewDict, pMaker->m_sCurKey);
|
||||
CCAssert(m_pCurDict && !m_sCurKey.empty(), "");
|
||||
m_pCurDict->setObject(pNewDict, m_sCurKey);
|
||||
pNewDict->release();
|
||||
pMaker->m_sCurKey.clear();
|
||||
m_sCurKey.clear();
|
||||
}
|
||||
pMaker->m_pCurDict = pNewDict;
|
||||
pMaker->m_tDictStack.push(pMaker->m_pCurDict);
|
||||
pMaker->m_tState = SAX_DICT;
|
||||
m_pCurDict = pNewDict;
|
||||
m_tDictStack.push(m_pCurDict);
|
||||
m_tState = SAX_DICT;
|
||||
}
|
||||
else if(sName == "key")
|
||||
{
|
||||
pMaker->m_tState = SAX_KEY;
|
||||
m_tState = SAX_KEY;
|
||||
}
|
||||
else if(sName == "integer")
|
||||
{
|
||||
pMaker->m_tState = SAX_INT;
|
||||
m_tState = SAX_INT;
|
||||
}
|
||||
else if(sName == "real")
|
||||
{
|
||||
pMaker->m_tState = SAX_REAL;
|
||||
m_tState = SAX_REAL;
|
||||
}
|
||||
else if(sName == "string")
|
||||
{
|
||||
pMaker->m_tState = SAX_STRING;
|
||||
m_tState = SAX_STRING;
|
||||
}
|
||||
else
|
||||
{
|
||||
pMaker->m_tState = SAX_NONE;
|
||||
if (sName == "array")
|
||||
{
|
||||
m_bInArray = true;
|
||||
m_pArray = new CCMutableArray<CCObject*>();
|
||||
}
|
||||
m_tState = SAX_NONE;
|
||||
}
|
||||
}
|
||||
void endElement(void *ctx, const XML_Char *name)
|
||||
{
|
||||
CCDictMaker * pMaker = this;
|
||||
std::string sName((char*)name);
|
||||
if( sName == "dict" )
|
||||
{
|
||||
pMaker->m_tDictStack.pop();
|
||||
if ( !pMaker->m_tDictStack.empty() )
|
||||
m_tDictStack.pop();
|
||||
if ( !m_tDictStack.empty() )
|
||||
{
|
||||
pMaker->m_pCurDict = (CCDictionary<std::string, CCObject*>*)(pMaker->m_tDictStack.top());
|
||||
m_pCurDict = (CCDictionary<std::string, CCObject*>*)(m_tDictStack.top());
|
||||
}
|
||||
}
|
||||
pMaker->m_tState = SAX_NONE;
|
||||
else if (sName == "array")
|
||||
{
|
||||
CCAssert(m_bInArray, "The plist file is wrong!");
|
||||
m_pCurDict->setObject(m_pArray, m_sCurKey);
|
||||
m_pArray->release();
|
||||
m_pArray = NULL;
|
||||
m_bInArray = false;
|
||||
}
|
||||
m_tState = SAX_NONE;
|
||||
}
|
||||
|
||||
void textHandler(void *ctx, const XML_Char *ch, int len)
|
||||
{
|
||||
CCDictMaker * pMaker = this;
|
||||
if (pMaker->m_tState == SAX_NONE)
|
||||
if (m_tState == SAX_NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
CCString *pText = new CCString();
|
||||
pText->m_sString = std::string((char*)ch,0,len);
|
||||
|
||||
switch(pMaker->m_tState)
|
||||
switch(m_tState)
|
||||
{
|
||||
case SAX_KEY:
|
||||
{
|
||||
pMaker->m_sCurKey = pText->m_sString;
|
||||
m_sCurKey = pText->m_sString;
|
||||
}
|
||||
break;
|
||||
case SAX_INT:
|
||||
case SAX_REAL:
|
||||
{
|
||||
CCAssert(!pMaker->m_sCurKey.empty(), "not found real : <integet/real>");
|
||||
pMaker->m_pCurDict->setObject(pText, pMaker->m_sCurKey);
|
||||
CCAssert(!m_sCurKey.empty(), "not found real : <integet/real>");
|
||||
if (m_bInArray)
|
||||
{
|
||||
m_pArray->addObject(pText);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pCurDict->setObject(pText, m_sCurKey);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SAX_STRING:
|
||||
{
|
||||
CCAssert(!pMaker->m_sCurKey.empty(), "not found string");
|
||||
pMaker->m_pCurDict->setObject(pText, pMaker->m_sCurKey);
|
||||
CCAssert(!m_sCurKey.empty(), "not found string");
|
||||
if (m_bInArray)
|
||||
{
|
||||
m_pArray->addObject(pText);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pCurDict->setObject(pText, m_sCurKey);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2011 cocos2d-x.org http://cocos2d-x.org
|
||||
Copyright (c) 2011 Максим Аксенов
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "platform/CCNS.h"
|
||||
|
||||
///@todo implement the functions
|
||||
NS_CC_BEGIN;
|
||||
CCRect CCRectFromString(const char* pszContent)
|
||||
{
|
||||
return CCRectZero;
|
||||
}
|
||||
|
||||
CCPoint CCPointFromString(const char* pszContent)
|
||||
{
|
||||
return CCPointZero;
|
||||
}
|
||||
|
||||
CCSize CCSizeFromString(const char* pszContent)
|
||||
{
|
||||
return CCSizeZero;
|
||||
}
|
||||
NS_CC_END;
|
|
@ -1,43 +0,0 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2010 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "platform/CCNS.h"
|
||||
|
||||
///@todo implement the functions
|
||||
namespace cocos2d
|
||||
{
|
||||
CCRect CCRectFromString(const char* pszContent)
|
||||
{
|
||||
return CCRectZero;
|
||||
}
|
||||
|
||||
CCPoint CCPointFromString(const char* pszContent)
|
||||
{
|
||||
return CCPointZero;
|
||||
}
|
||||
|
||||
CCSize CCSizeFromString(const char* pszContent)
|
||||
{
|
||||
return CCSizeZero;
|
||||
}
|
||||
}
|
|
@ -30,11 +30,13 @@ THE SOFTWARE.
|
|||
#include "CCGeometry.h"
|
||||
#include "platform/android/CCAccelerometer_android.h"
|
||||
#include <android/log.h>
|
||||
#define LOG_TAG "Cocos2dJni"
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
|
||||
|
||||
#if 0
|
||||
#define LOG_TAG "Cocos2dJni"
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
|
||||
#else
|
||||
#define LOGD(...)
|
||||
#endif
|
||||
|
||||
using namespace cocos2d;
|
||||
|
||||
|
@ -42,8 +44,7 @@ extern "C"
|
|||
{
|
||||
|
||||
#define MAX_TOUCHES 5
|
||||
static cocos2d::CCTouch *s_pTouches[MAX_TOUCHES] = { NULL };
|
||||
static cocos2d::CCSet s_set;
|
||||
static CCTouch *s_pTouches[MAX_TOUCHES] = { NULL };
|
||||
|
||||
// handle accelerometer changes
|
||||
|
||||
|
@ -58,84 +59,54 @@ extern "C"
|
|||
timeStamp);
|
||||
}
|
||||
|
||||
// handle touch event
|
||||
|
||||
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesBegin(JNIEnv* env, jobject thiz, jintArray ids, jfloatArray xs, jfloatArray ys)
|
||||
// handle touch event
|
||||
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesBegin(JNIEnv* env, jobject thiz, jint id, jfloat x, jfloat y)
|
||||
{
|
||||
int size = env->GetArrayLength(ids);
|
||||
jint id[size];
|
||||
jfloat x[size];
|
||||
jfloat y[size];
|
||||
CCRect rcRect = CCEGLView::sharedOpenGLView().getViewPort();
|
||||
float fScreenScaleFactor = CCEGLView::sharedOpenGLView().getScreenScaleFactor();
|
||||
CCSet set;
|
||||
|
||||
env->GetIntArrayRegion(ids, 0, size, id);
|
||||
env->GetFloatArrayRegion(xs, 0, size, x);
|
||||
env->GetFloatArrayRegion(ys, 0, size, y);
|
||||
CCTouch *pTouch = s_pTouches[id];
|
||||
if (! pTouch)
|
||||
{
|
||||
LOGD("Beginning touches with id: %d, x=%f, y=%f", id, x, y);
|
||||
|
||||
for( int i = 0 ; i < size ; i++ ) {
|
||||
cocos2d::CCTouch* pTouch = s_pTouches[id[i]];
|
||||
LOGD("Should create new pTouch if null: %d", pTouch);
|
||||
if (!pTouch)
|
||||
{
|
||||
pTouch = new cocos2d::CCTouch;
|
||||
}
|
||||
pTouch = new CCTouch();
|
||||
pTouch->SetTouchInfo(0, (x - rcRect.origin.x) / fScreenScaleFactor, (y - rcRect.origin.y) / fScreenScaleFactor);
|
||||
s_pTouches[id] = pTouch;
|
||||
set.addObject(pTouch);
|
||||
|
||||
LOGD("Beginning touches with id: %d, x=%f, y=%f", id[i], x[i], y[i]);
|
||||
pTouch->SetTouchInfo(0, (x[i] - rcRect.origin.x) / fScreenScaleFactor ,
|
||||
(y[i] - rcRect.origin.y) / fScreenScaleFactor);
|
||||
|
||||
s_set.addObject(pTouch);
|
||||
s_pTouches[id[i]] = pTouch;
|
||||
cocos2d::CCDirector::sharedDirector()->getOpenGLView()->getDelegate()->touchesBegan(&set, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGD("Beginnig touches with id: %d error", id);
|
||||
}
|
||||
|
||||
cocos2d::CCDirector::sharedDirector()->getOpenGLView()->getDelegate()->touchesBegan(&s_set, NULL);
|
||||
}
|
||||
|
||||
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesEnd(JNIEnv* env, jobject thiz, jintArray ids, jfloatArray xs, jfloatArray ys)
|
||||
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesEnd(JNIEnv* env, jobject thiz, jint id, jfloat x, jfloat y)
|
||||
{
|
||||
|
||||
int size = env->GetArrayLength(ids);
|
||||
jint id[size];
|
||||
jfloat x[size];
|
||||
jfloat y[size];
|
||||
CCRect rcRect = CCEGLView::sharedOpenGLView().getViewPort();
|
||||
float fScreenScaleFactor = CCEGLView::sharedOpenGLView().getScreenScaleFactor();
|
||||
|
||||
env->GetIntArrayRegion(ids, 0, size, id);
|
||||
env->GetFloatArrayRegion(xs, 0, size, x);
|
||||
env->GetFloatArrayRegion(ys, 0, size, y);
|
||||
CCSet set;
|
||||
|
||||
/* Add to the set to send to the director */
|
||||
for( int i = 0 ; i < size ; i++ ) {
|
||||
cocos2d::CCTouch* pTouch = s_pTouches[id[i]];
|
||||
LOGD("Ending touches with id: %d, x=%f, y=%f", id[i], x[i], y[i]);
|
||||
if (pTouch)
|
||||
{
|
||||
pTouch->SetTouchInfo(0, (x[i] - rcRect.origin.x) / fScreenScaleFactor ,
|
||||
(y[i] - rcRect.origin.y) / fScreenScaleFactor);
|
||||
s_set.addObject(pTouch);
|
||||
} else {
|
||||
LOGD("Error adding the touch to remove");
|
||||
}
|
||||
}
|
||||
CCTouch* pTouch = s_pTouches[id];
|
||||
if (pTouch)
|
||||
{
|
||||
LOGD("Ending touches with id: %d, x=%f, y=%f", id, x, y);
|
||||
|
||||
cocos2d::CCDirector::sharedDirector()->getOpenGLView()->getDelegate()->touchesEnded(&s_set, NULL);
|
||||
pTouch->SetTouchInfo(0, (x - rcRect.origin.x) / fScreenScaleFactor , (y - rcRect.origin.y) / fScreenScaleFactor);
|
||||
set.addObject(pTouch);
|
||||
|
||||
/* Update the set status */
|
||||
for( int i = 0 ; i < size ; i++ ) {
|
||||
cocos2d::CCTouch* pTouch = s_pTouches[id[i]];
|
||||
LOGD("Ending touches with id: %d, x=%f, y=%f", id[i], x[i], y[i]);
|
||||
if (pTouch)
|
||||
{
|
||||
s_set.removeObject(pTouch);
|
||||
pTouch->release();
|
||||
s_pTouches[id[i]] = NULL;
|
||||
} else {
|
||||
LOGD("Error removing from the set!");
|
||||
}
|
||||
// release the object
|
||||
pTouch->release();
|
||||
s_pTouches[id] = NULL;
|
||||
|
||||
}
|
||||
cocos2d::CCDirector::sharedDirector()->getOpenGLView()->getDelegate()->touchesEnded(&set, NULL);
|
||||
} else {
|
||||
LOGD("Ending touches with id: %d error", id);
|
||||
}
|
||||
}
|
||||
|
||||
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesMove(JNIEnv* env, jobject thiz, jintArray ids, jfloatArray xs, jfloatArray ys)
|
||||
|
@ -146,6 +117,7 @@ extern "C"
|
|||
jfloat y[size];
|
||||
CCRect rcRect = CCEGLView::sharedOpenGLView().getViewPort();
|
||||
float fScreenScaleFactor = CCEGLView::sharedOpenGLView().getScreenScaleFactor();
|
||||
CCSet set;
|
||||
|
||||
env->GetIntArrayRegion(ids, 0, size, id);
|
||||
env->GetFloatArrayRegion(xs, 0, size, x);
|
||||
|
@ -158,11 +130,17 @@ extern "C"
|
|||
{
|
||||
pTouch->SetTouchInfo(0, (x[i] - rcRect.origin.x) / fScreenScaleFactor ,
|
||||
(y[i] - rcRect.origin.y) / fScreenScaleFactor);
|
||||
s_set.addObject(pTouch);
|
||||
set.addObject(pTouch);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It is error, should return.
|
||||
LOGD("Moving touches with id: %d error", id[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cocos2d::CCDirector::sharedDirector()->getOpenGLView()->getDelegate()->touchesMoved(&s_set, NULL);
|
||||
cocos2d::CCDirector::sharedDirector()->getOpenGLView()->getDelegate()->touchesMoved(&set, NULL);
|
||||
}
|
||||
|
||||
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesCancel(JNIEnv* env, jobject thiz, jintArray ids, jfloatArray xs, jfloatArray ys)
|
||||
|
@ -173,6 +151,7 @@ extern "C"
|
|||
jfloat y[size];
|
||||
CCRect rcRect = CCEGLView::sharedOpenGLView().getViewPort();
|
||||
float fScreenScaleFactor = CCEGLView::sharedOpenGLView().getScreenScaleFactor();
|
||||
CCSet set;
|
||||
|
||||
env->GetIntArrayRegion(ids, 0, size, id);
|
||||
env->GetFloatArrayRegion(xs, 0, size, x);
|
||||
|
@ -184,12 +163,13 @@ extern "C"
|
|||
{
|
||||
pTouch->SetTouchInfo(0, (x[i] - rcRect.origin.x) / fScreenScaleFactor ,
|
||||
(y[i] - rcRect.origin.y) / fScreenScaleFactor);
|
||||
s_set.addObject(pTouch);
|
||||
set.addObject(pTouch);
|
||||
s_pTouches[id[i]] = NULL;
|
||||
pTouch->release();
|
||||
}
|
||||
}
|
||||
|
||||
cocos2d::CCDirector::sharedDirector()->getOpenGLView()->getDelegate()->touchesCancelled(&s_set, NULL);
|
||||
cocos2d::CCDirector::sharedDirector()->getOpenGLView()->getDelegate()->touchesCancelled(&set, NULL);
|
||||
}
|
||||
|
||||
void Java_org_cocos2dx_lib_Cocos2dxActivity_nativeSetPaths(JNIEnv* env, jobject thiz, jstring apkPath)
|
||||
|
|
|
@ -115,155 +115,208 @@ static const char* static_fullPathFromRelativePath(const char *pszRelativePath)
|
|||
// do not convert an absolute path (starting with '/')
|
||||
NSString *relPath = [NSString stringWithUTF8String: pszRelativePath];
|
||||
NSString *fullpath = nil;
|
||||
|
||||
// only if it is not an absolute path
|
||||
if( ! [relPath isAbsolutePath] )
|
||||
{
|
||||
NSString *file = [relPath lastPathComponent];
|
||||
NSString *imageDirectory = [relPath stringByDeletingLastPathComponent];
|
||||
|
||||
fullpath = [[NSBundle mainBundle] pathForResource:file
|
||||
ofType:nil
|
||||
inDirectory:imageDirectory];
|
||||
}
|
||||
|
||||
if (fullpath == nil)
|
||||
fullpath = relPath;
|
||||
|
||||
fullpath = getDoubleResolutionImage(fullpath);
|
||||
|
||||
return [fullpath UTF8String];
|
||||
|
||||
// only if it is not an absolute path
|
||||
if( ! [relPath isAbsolutePath] )
|
||||
{
|
||||
NSString *file = [relPath lastPathComponent];
|
||||
NSString *imageDirectory = [relPath stringByDeletingLastPathComponent];
|
||||
|
||||
fullpath = [[NSBundle mainBundle] pathForResource:file
|
||||
ofType:nil
|
||||
inDirectory:imageDirectory];
|
||||
}
|
||||
|
||||
if (fullpath == nil)
|
||||
fullpath = relPath;
|
||||
|
||||
fullpath = getDoubleResolutionImage(fullpath);
|
||||
|
||||
return [fullpath UTF8String];
|
||||
}
|
||||
|
||||
namespace cocos2d {
|
||||
|
||||
typedef enum
|
||||
typedef enum
|
||||
{
|
||||
SAX_NONE = 0,
|
||||
SAX_KEY,
|
||||
SAX_DICT,
|
||||
SAX_INT,
|
||||
SAX_REAL,
|
||||
SAX_STRING
|
||||
}CCSAXState;
|
||||
|
||||
class CCDictMaker : public CCSAXDelegator
|
||||
{
|
||||
public:
|
||||
CCDictionary<std::string, CCObject*> *m_pRootDict;
|
||||
CCDictionary<std::string, CCObject*> *m_pCurDict;
|
||||
std::stack<CCDictionary<std::string, CCObject*>*> m_tDictStack;
|
||||
std::string m_sCurKey;///< parsed key
|
||||
CCSAXState m_tState;
|
||||
bool m_bInArray;
|
||||
CCMutableArray<CCObject*> *m_pArray;
|
||||
|
||||
public:
|
||||
CCDictMaker()
|
||||
{
|
||||
SAX_NONE = 0,
|
||||
SAX_KEY,
|
||||
SAX_DICT,
|
||||
SAX_INT,
|
||||
SAX_REAL,
|
||||
SAX_STRING
|
||||
}CCSAXState;
|
||||
m_pRootDict = NULL;
|
||||
m_pCurDict = NULL;
|
||||
m_tState = SAX_NONE;
|
||||
|
||||
class CCDictMaker : public CCSAXDelegator
|
||||
m_pArray = NULL;
|
||||
m_bInArray = false;
|
||||
}
|
||||
~CCDictMaker()
|
||||
{
|
||||
public:
|
||||
CCDictionary<std::string, CCObject*> *m_pRootDict;
|
||||
CCDictionary<std::string, CCObject*> *m_pCurDict;
|
||||
std::stack<CCDictionary<std::string, CCObject*>*> m_tDictStack;
|
||||
std::string m_sCurKey;///< parsed key
|
||||
CCSAXState m_tState;
|
||||
public:
|
||||
CCDictMaker()
|
||||
{
|
||||
m_pRootDict = NULL;
|
||||
m_pCurDict = NULL;
|
||||
m_tState = SAX_NONE;
|
||||
}
|
||||
~CCDictMaker()
|
||||
{
|
||||
}
|
||||
CCDictionary<std::string, CCObject*> *dictionaryWithContentsOfFile(const char *pFileName)
|
||||
{
|
||||
CCSAXParser parser;
|
||||
}
|
||||
CCDictionary<std::string, CCObject*> *dictionaryWithContentsOfFile(const char *pFileName)
|
||||
{
|
||||
CCSAXParser parser;
|
||||
|
||||
if (false == parser.init("UTF-8"))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
parser.setDelegator(this);
|
||||
|
||||
parser.parse(pFileName);
|
||||
return m_pRootDict;
|
||||
}
|
||||
|
||||
void startElement(void *ctx, const char *name, const char **atts)
|
||||
if (false == parser.init("UTF-8"))
|
||||
{
|
||||
std::string sName((char*)name);
|
||||
if( sName == "dict" )
|
||||
return NULL;
|
||||
}
|
||||
parser.setDelegator(this);
|
||||
|
||||
parser.parse(pFileName);
|
||||
return m_pRootDict;
|
||||
}
|
||||
|
||||
void startElement(void *ctx, const char *name, const char **atts)
|
||||
{
|
||||
std::string sName((char*)name);
|
||||
if( sName == "dict" )
|
||||
{
|
||||
CCDictionary<std::string, CCObject*> *pNewDict = new CCDictionary<std::string, CCObject*>();
|
||||
if(! m_pRootDict)
|
||||
{
|
||||
CCDictionary<std::string, CCObject*> *pNewDict = new CCDictionary<std::string, CCObject*>();
|
||||
if(! m_pRootDict)
|
||||
{
|
||||
m_pRootDict = pNewDict;
|
||||
pNewDict->autorelease();
|
||||
}
|
||||
else
|
||||
{
|
||||
CCAssert(m_pCurDict && !m_sCurKey.empty(), "");
|
||||
m_pCurDict->setObject(pNewDict, m_sCurKey);
|
||||
pNewDict->release();
|
||||
m_sCurKey.clear();
|
||||
}
|
||||
m_pCurDict = pNewDict;
|
||||
m_tDictStack.push(m_pCurDict);
|
||||
m_tState = SAX_DICT;
|
||||
}
|
||||
else if(sName == "key")
|
||||
{
|
||||
m_tState = SAX_KEY;
|
||||
}
|
||||
else if(sName == "integer")
|
||||
{
|
||||
m_tState = SAX_INT;
|
||||
}
|
||||
else if(sName == "real")
|
||||
{
|
||||
m_tState = SAX_REAL;
|
||||
}
|
||||
else if(sName == "string")
|
||||
{
|
||||
m_tState = SAX_STRING;
|
||||
m_pRootDict = pNewDict;
|
||||
pNewDict->autorelease();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tState = SAX_NONE;
|
||||
CCAssert(m_pCurDict && !m_sCurKey.empty(), "");
|
||||
m_pCurDict->setObject(pNewDict, m_sCurKey);
|
||||
pNewDict->release();
|
||||
m_sCurKey.clear();
|
||||
}
|
||||
m_pCurDict = pNewDict;
|
||||
m_tDictStack.push(m_pCurDict);
|
||||
m_tState = SAX_DICT;
|
||||
}
|
||||
|
||||
void endElement(void *ctx, const char *name)
|
||||
else if(sName == "key")
|
||||
{
|
||||
std::string sName((char*)name);
|
||||
if( sName == "dict" )
|
||||
m_tState = SAX_KEY;
|
||||
}
|
||||
else if(sName == "integer")
|
||||
{
|
||||
m_tState = SAX_INT;
|
||||
}
|
||||
else if(sName == "real")
|
||||
{
|
||||
m_tState = SAX_REAL;
|
||||
}
|
||||
else if(sName == "string")
|
||||
{
|
||||
m_tState = SAX_STRING;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sName == "array")
|
||||
{
|
||||
m_tDictStack.pop();
|
||||
if ( !m_tDictStack.empty() )
|
||||
{
|
||||
m_pCurDict = (CCDictionary<std::string, CCObject*>*)(m_tDictStack.top());
|
||||
}
|
||||
m_bInArray = true;
|
||||
m_pArray = new CCMutableArray<CCObject*>();
|
||||
}
|
||||
m_tState = SAX_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void textHandler(void *ctx, const char *ch, int len)
|
||||
void endElement(void *ctx, const char *name)
|
||||
{
|
||||
std::string sName((char*)name);
|
||||
if( sName == "dict" )
|
||||
{
|
||||
if (m_tState == SAX_NONE)
|
||||
m_tDictStack.pop();
|
||||
if ( !m_tDictStack.empty() )
|
||||
{
|
||||
return;
|
||||
m_pCurDict = (CCDictionary<std::string, CCObject*>*)(m_tDictStack.top());
|
||||
}
|
||||
CCString *pText = new CCString();
|
||||
pText->m_sString = std::string((char*)ch,0,len);
|
||||
|
||||
switch(m_tState)
|
||||
{
|
||||
case SAX_KEY:
|
||||
m_sCurKey = pText->m_sString;
|
||||
break;
|
||||
case SAX_INT:
|
||||
case SAX_REAL:
|
||||
case SAX_STRING:
|
||||
{
|
||||
CCAssert(!m_sCurKey.empty(), "not found key : <integet/real>");
|
||||
m_pCurDict->setObject(pText, m_sCurKey);
|
||||
break;
|
||||
}
|
||||
}
|
||||
pText->release();
|
||||
}
|
||||
};
|
||||
else if (sName == "array")
|
||||
{
|
||||
CCAssert(m_bInArray, "The plist file is wrong!");
|
||||
m_pCurDict->setObject(m_pArray, m_sCurKey);
|
||||
m_pArray->release();
|
||||
m_pArray = NULL;
|
||||
m_bInArray = false;
|
||||
}
|
||||
else if (sName == "true")
|
||||
{
|
||||
CCString *str = new CCString("1");
|
||||
if (m_bInArray)
|
||||
{
|
||||
m_pArray->addObject(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pCurDict->setObject(str, m_sCurKey);
|
||||
}
|
||||
str->release();
|
||||
}
|
||||
else if (sName == "false")
|
||||
{
|
||||
CCString *str = new CCString("0");
|
||||
if (m_bInArray)
|
||||
{
|
||||
m_pArray->addObject(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pCurDict->setObject(str, m_sCurKey);
|
||||
}
|
||||
str->release();
|
||||
}
|
||||
m_tState = SAX_NONE;
|
||||
}
|
||||
|
||||
void textHandler(void *ctx, const char *ch, int len)
|
||||
{
|
||||
if (m_tState == SAX_NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
CCString *pText = new CCString();
|
||||
pText->m_sString = std::string((char*)ch,0,len);
|
||||
|
||||
switch(m_tState)
|
||||
{
|
||||
case SAX_KEY:
|
||||
m_sCurKey = pText->m_sString;
|
||||
break;
|
||||
case SAX_INT:
|
||||
case SAX_REAL:
|
||||
case SAX_STRING:
|
||||
{
|
||||
CCAssert(!m_sCurKey.empty(), "not found key : <integet/real>");
|
||||
|
||||
if (m_bInArray)
|
||||
{
|
||||
m_pArray->addObject(pText);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pCurDict->setObject(pText, m_sCurKey);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
pText->release();
|
||||
}
|
||||
};
|
||||
|
||||
// record the resource path
|
||||
static char s_pszResourcePath[MAX_PATH] = {0};
|
||||
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2010 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#import <Availability.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#include "platform/CCNS.h"
|
||||
|
||||
static cocos2d::CCRect static_CCRectFromString(const char* pszContent)
|
||||
{
|
||||
CGRect rect = CGRectFromString([NSString stringWithUTF8String: pszContent]);
|
||||
cocos2d::CCRect ret(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static cocos2d::CCPoint static_CCPointFromString(const char* pszContent)
|
||||
{
|
||||
CGPoint point = CGPointFromString([NSString stringWithUTF8String: pszContent]);
|
||||
cocos2d::CCPoint ret(point.x, point.y);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static cocos2d::CCSize static_CCSizeFromString(const char* pszContent)
|
||||
{
|
||||
CGSize size = CGSizeFromString([NSString stringWithUTF8String: pszContent]);
|
||||
cocos2d::CCSize ret(size.width, size.height);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
///@todo implement the functions
|
||||
namespace cocos2d
|
||||
{
|
||||
CCRect CCRectFromString(const char* pszContent)
|
||||
{
|
||||
return static_CCRectFromString(pszContent);
|
||||
}
|
||||
|
||||
CCPoint CCPointFromString(const char* pszContent)
|
||||
{
|
||||
return static_CCPointFromString(pszContent);
|
||||
}
|
||||
|
||||
CCSize CCSizeFromString(const char* pszContent)
|
||||
{
|
||||
return static_CCSizeFromString(pszContent);
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2010 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "platform/CCNS.h"
|
||||
|
||||
///@todo implement the functions
|
||||
namespace cocos2d
|
||||
{
|
||||
CCRect CCRectFromString(const char* pszContent)
|
||||
{
|
||||
return CCRectZero;
|
||||
}
|
||||
|
||||
CCPoint CCPointFromString(const char* pszContent)
|
||||
{
|
||||
return CCPointZero;
|
||||
}
|
||||
|
||||
CCSize CCSizeFromString(const char* pszContent)
|
||||
{
|
||||
return CCSizeZero;
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2010 cocos2d-x.org
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "platform/CCNS.h"
|
||||
|
||||
///@todo implement the functions
|
||||
namespace cocos2d
|
||||
{
|
||||
CCRect CCRectFromString(const char* pszContent)
|
||||
{
|
||||
return CCRectZero;
|
||||
}
|
||||
|
||||
CCPoint CCPointFromString(const char* pszContent)
|
||||
{
|
||||
return CCPointZero;
|
||||
}
|
||||
|
||||
CCSize CCSizeFromString(const char* pszContent)
|
||||
{
|
||||
return CCSizeZero;
|
||||
}
|
||||
}
|
|
@ -211,6 +211,14 @@
|
|||
RelativePath="..\cocoa\CCGeometry.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\cocoa\CCNS.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\cocoa\CCNS.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\cocoa\CCObject.cpp"
|
||||
>
|
||||
|
@ -775,10 +783,6 @@
|
|||
RelativePath="..\platform\CCNode_mobile.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\platform\CCNS.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\platform\CCParticleSystemPoint_mobile.cpp"
|
||||
>
|
||||
|
@ -858,10 +862,6 @@
|
|||
RelativePath="..\platform\win32\CCEGLView_win32.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\platform\win32\CCNS_win32.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
|
|
@ -53,6 +53,7 @@ OBJECTS = \
|
|||
$(OBJECTS_DIR)/CCAutoreleasePool.o \
|
||||
$(OBJECTS_DIR)/CCData.o \
|
||||
$(OBJECTS_DIR)/CCGeometry.o \
|
||||
$(OBJECTS_DIR)/CCNS.o \
|
||||
$(OBJECTS_DIR)/CCObject.o \
|
||||
$(OBJECTS_DIR)/CCSet.o \
|
||||
$(OBJECTS_DIR)/CCZone.o \
|
||||
|
@ -95,7 +96,6 @@ OBJECTS = \
|
|||
$(OBJECTS_DIR)/CCAccelerometer_wophone.o \
|
||||
$(OBJECTS_DIR)/CCApplication_wophone.o \
|
||||
$(OBJECTS_DIR)/CCEGLView_wophone.o \
|
||||
$(OBJECTS_DIR)/CCNS_wophone.o \
|
||||
$(OBJECTS_DIR)/CCAnimation.o \
|
||||
$(OBJECTS_DIR)/CCAnimationCache.o \
|
||||
$(OBJECTS_DIR)/CCSprite.o \
|
||||
|
@ -204,6 +204,9 @@ $(OBJECTS_DIR)/CCData.o : ../cocoa/CCData.cpp
|
|||
$(OBJECTS_DIR)/CCGeometry.o : ../cocoa/CCGeometry.cpp
|
||||
$(CXX) -c $(CXX_FLAGS) $(INCLUDE_PATH) $(LAST_INCLUDE_PATH) -o $(OBJECTS_DIR)/CCGeometry.o ../cocoa/CCGeometry.cpp
|
||||
|
||||
$(OBJECTS_DIR)/CCNS.o : ../cocoa/CCNS.cpp
|
||||
$(CXX) -c $(CXX_FLAGS) $(INCLUDE_PATH) $(LAST_INCLUDE_PATH) -o $(OBJECTS_DIR)/CCNS.o ../cocoa/CCNS.cpp
|
||||
|
||||
$(OBJECTS_DIR)/CCObject.o : ../cocoa/CCObject.cpp
|
||||
$(CXX) -c $(CXX_FLAGS) $(INCLUDE_PATH) $(LAST_INCLUDE_PATH) -o $(OBJECTS_DIR)/CCObject.o ../cocoa/CCObject.cpp
|
||||
|
||||
|
@ -330,9 +333,6 @@ $(OBJECTS_DIR)/CCApplication_wophone.o : ../platform/wophone/CCApplication_wopho
|
|||
$(OBJECTS_DIR)/CCEGLView_wophone.o : ../platform/wophone/CCEGLView_wophone.cpp
|
||||
$(CXX) -c $(CXX_FLAGS) $(INCLUDE_PATH) $(LAST_INCLUDE_PATH) -o $(OBJECTS_DIR)/CCEGLView_wophone.o ../platform/wophone/CCEGLView_wophone.cpp
|
||||
|
||||
$(OBJECTS_DIR)/CCNS_wophone.o : ../platform/wophone/CCNS_wophone.cpp
|
||||
$(CXX) -c $(CXX_FLAGS) $(INCLUDE_PATH) $(LAST_INCLUDE_PATH) -o $(OBJECTS_DIR)/CCNS_wophone.o ../platform/wophone/CCNS_wophone.cpp
|
||||
|
||||
$(OBJECTS_DIR)/CCAnimation.o : ../sprite_nodes/CCAnimation.cpp
|
||||
$(CXX) -c $(CXX_FLAGS) $(INCLUDE_PATH) $(LAST_INCLUDE_PATH) -o $(OBJECTS_DIR)/CCAnimation.o ../sprite_nodes/CCAnimation.cpp
|
||||
|
||||
|
|
|
@ -880,6 +880,14 @@
|
|||
RelativePath="..\cocoa\CCGeometry.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\cocoa\CCNS.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\cocoa\CCNS.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\cocoa\CCObject.cpp"
|
||||
>
|
||||
|
@ -968,10 +976,6 @@
|
|||
RelativePath="..\platform\CCNode_mobile.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\platform\CCNS.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\platform\CCParticleSystemPoint_mobile.h"
|
||||
>
|
||||
|
@ -1051,10 +1055,6 @@
|
|||
RelativePath="..\platform\wophone\CCEGLView_wophone.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\platform\wophone\CCNS_wophone.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\platform\wophone\NewDeleteOp.cpp"
|
||||
>
|
||||
|
|
|
@ -25,7 +25,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "platform/CCNS.h"
|
||||
#include "cocoa/CCNS.h"
|
||||
#include "ccMacros.h"
|
||||
#include "CCTextureCache.h"
|
||||
#include "CCSpriteFrameCache.h"
|
||||
|
@ -58,7 +58,7 @@ void CCSpriteFrameCache::purgeSharedSpriteFrameCache(void)
|
|||
bool CCSpriteFrameCache::init(void)
|
||||
{
|
||||
m_pSpriteFrames= new CCDictionary<std::string, CCSpriteFrame*>();
|
||||
m_pSpriteFramesAliases = new CCDictionary<std::string, CCSpriteFrame*>();
|
||||
m_pSpriteFramesAliases = new CCDictionary<std::string, CCString*>();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -155,10 +155,6 @@ void CCSpriteFrameCache::addSpriteFramesWithDictionary(CCDictionary<std::string,
|
|||
} else
|
||||
if (format == 3)
|
||||
{
|
||||
/// @todo what's the format look like?
|
||||
assert(false);
|
||||
return;
|
||||
/*
|
||||
// get values
|
||||
CCSize spriteSize = CCSizeFromString(valueForKey("spriteSize", frameDict));
|
||||
CCPoint spriteOffset = CCPointFromString(valueForKey("spriteOffset", frameDict));
|
||||
|
@ -167,19 +163,28 @@ void CCSpriteFrameCache::addSpriteFramesWithDictionary(CCDictionary<std::string,
|
|||
bool textureRotated = atoi(valueForKey("textureRotated", frameDict)) == 0;
|
||||
|
||||
// get aliases
|
||||
CCMutableArray<CCString*> *aliases = CCMutableArray<CCString*>dictionary->objectForKey(std::string("aliases"));
|
||||
CCMutableArray<CCString*> *aliases = (CCMutableArray<CCString*> *) (frameDict->objectForKey(std::string("aliases")));
|
||||
CCMutableArray<CCString*>::CCMutableArrayIterator iter;
|
||||
|
||||
while( alias = (CCDictionary<std::string, CCObject*>*)aliases->next(&key) )
|
||||
{
|
||||
std::string value = ((CCString*)alias->objectForKey(key))->m_sString();
|
||||
if (m_pSpriteFramesAliases->objectForKey(value))
|
||||
{
|
||||
CCLOG("cocos2d: WARNING: an alias with name %s already exists", value.c_str());
|
||||
}
|
||||
CCString * frameKey = new CCString(key.c_str());
|
||||
for (iter = aliases->begin(); iter != aliases->end(); iter++)
|
||||
{
|
||||
std::string oneAlias = ((CCString*) (*iter))->m_sString;
|
||||
if (m_pSpriteFramesAliases->objectForKey(oneAlias))
|
||||
{
|
||||
CCLOG("cocos2d: WARNING: an alias with name %s already exists", oneAlias.c_str());
|
||||
}
|
||||
|
||||
m_pSpriteFramesAliases->setObject(frameDict, value);
|
||||
}
|
||||
*/
|
||||
m_pSpriteFramesAliases->setObject(frameKey, oneAlias);
|
||||
}
|
||||
frameKey->release();
|
||||
// create frame
|
||||
spriteFrame = new CCSpriteFrame();
|
||||
spriteFrame->initWithTexture(pobTexture,
|
||||
CCRectMake(textureRect.origin.x, textureRect.origin.y, spriteSize.width, spriteSize.height),
|
||||
textureRotated,
|
||||
spriteOffset,
|
||||
spriteSourceSize);
|
||||
}
|
||||
|
||||
// add sprite frame
|
||||
|
|
|
@ -1 +1 @@
|
|||
130df27ea38ccc20118cc71eeebcccba4db470a4
|
||||
f02925523f965e430f8e881c5244ee080899fb99
|
|
@ -1 +1 @@
|
|||
8c07d2ef5449fd386fca2f52f4347112006db602
|
||||
96413c22c2a8542a63d1887b42fb9ec2ab1b15d3
|
|
@ -1 +1 @@
|
|||
2b6d1b09f7d781bb57632c801d23aec310bfe676
|
||||
3a2dfc8ad67562d58622125a30fa53a55c717e23
|
|
@ -8,4 +8,4 @@
|
|||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-8
|
||||
target=android-7
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# it is needed for ndk-r5
|
||||
APP_STL := stlport_static
|
||||
APP_ABI := armeabi armeabi-v7a
|
||||
|
||||
APP_MODULES := cocos2d cocosdenshion chipmunk box2d tests
|
||||
|
|
|
@ -1,119 +1,139 @@
|
|||
package org.cocos2dx.lib;
|
||||
|
||||
import org.cocos2dx.lib.touch.metalev.multitouch.controller.MultiTouchController;
|
||||
import org.cocos2dx.lib.touch.metalev.multitouch.controller.MultiTouchController.MultiTouchObjectCanvas;
|
||||
import org.cocos2dx.lib.touch.metalev.multitouch.controller.MultiTouchController.PointInfo;
|
||||
import org.cocos2dx.lib.touch.metalev.multitouch.controller.MultiTouchController.PositionAndScale;
|
||||
|
||||
import android.content.Context;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class Cocos2dxGLSurfaceView extends GLSurfaceView implements
|
||||
MultiTouchObjectCanvas {
|
||||
public class Cocos2dxGLSurfaceView extends GLSurfaceView{
|
||||
private static final String TAG = Cocos2dxGLSurfaceView.class
|
||||
.getCanonicalName();
|
||||
private MultiTouchController<Void> mTouchController;
|
||||
private Cocos2dxRenderer mRenderer;
|
||||
private final boolean debug = false;
|
||||
|
||||
public Cocos2dxGLSurfaceView(Context context) {
|
||||
super(context);
|
||||
mRenderer = new Cocos2dxRenderer();
|
||||
setRenderer(mRenderer);
|
||||
|
||||
mTouchController = new MultiTouchController<Void>(this);
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(final MotionEvent event) {
|
||||
if (mTouchController.onTouchEvent(event)) {
|
||||
final PointInfo pt = mTouchController.mCurrPt;
|
||||
final int ids[] = new int[pt.getNumTouchPoints()];
|
||||
final float xs[] = new float[pt.getNumTouchPoints()];
|
||||
final float ys[] = new float[pt.getNumTouchPoints()];
|
||||
// these data are used in ACTION_MOVE and ACTION_CANCEL
|
||||
final int pointerNumber = event.getPointerCount();
|
||||
final int[] ids = new int[pointerNumber];
|
||||
final float[] xs = new float[pointerNumber];
|
||||
final float[] ys = new float[pointerNumber];
|
||||
|
||||
for (int i = 0; i < pt.getNumTouchPoints(); i++) {
|
||||
ids[i] = pt.getPointerIds()[i];
|
||||
xs[i] = pt.getXs()[i];
|
||||
ys[i] = pt.getYs()[i];
|
||||
Log.d(TAG,
|
||||
"ACTION: " + pt.getAction() + "id[i]="
|
||||
+ pt.getPointerIds()[i] + "x[i]= "
|
||||
+ pt.getXs()[i] + " y[i]= " + pt.getYs()[i]);
|
||||
}
|
||||
|
||||
switch (pt.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case 261:
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
Log.d(TAG, "ACTION_DOWN");
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionDown(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
Log.d(TAG, "ACTION_MOVE");
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionMove(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
Log.d(TAG, "ACTION_UP");
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionUp(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionCancel(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
for (int i = 0; i < pointerNumber; i++) {
|
||||
ids[i] = event.getPointerId(i);
|
||||
xs[i] = event.getX(i);
|
||||
ys[i] = event.getY(i);
|
||||
}
|
||||
return false;
|
||||
|
||||
switch (event.getAction() & MotionEvent.ACTION_MASK) {
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
final int idPointerDown = event.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
|
||||
final float xPointerDown = event.getX(idPointerDown);
|
||||
final float yPointerDown = event.getY(idPointerDown);
|
||||
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionDown(idPointerDown, xPointerDown, yPointerDown);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
// there are only one finger on the screen
|
||||
final int idDown = event.getPointerId(0);
|
||||
final float xDown = event.getX(idDown);
|
||||
final float yDown = event.getY(idDown);
|
||||
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionDown(idDown, xDown, yDown);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionMove(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
final int idPointerUp = event.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
|
||||
final float xPointerUp = event.getX(idPointerUp);
|
||||
final float yPointerUp = event.getY(idPointerUp);
|
||||
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionUp(idPointerUp, xPointerUp, yPointerUp);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
// there are only one finger on the screen
|
||||
final int idUp = event.getPointerId(0);
|
||||
final float xUp = event.getX(idUp);
|
||||
final float yUp = event.getY(idUp);
|
||||
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionUp(idUp, xUp, yUp);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mRenderer.handleActionCancel(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
if (debug){
|
||||
dumpEvent(event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDraggableObjectAtPoint(PointInfo touchPoint) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getPositionAndScale(Object obj,
|
||||
PositionAndScale objPosAndScaleOut) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setPositionAndScale(Object obj,
|
||||
PositionAndScale newObjPosAndScale, PointInfo touchPoint) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectObject(Object obj, PointInfo touchPoint) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
|
||||
// Show an event in the LogCat view, for debugging
|
||||
private void dumpEvent(MotionEvent event) {
|
||||
String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" ,
|
||||
"POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int action = event.getAction();
|
||||
int actionCode = action & MotionEvent.ACTION_MASK;
|
||||
sb.append("event ACTION_" ).append(names[actionCode]);
|
||||
if (actionCode == MotionEvent.ACTION_POINTER_DOWN
|
||||
|| actionCode == MotionEvent.ACTION_POINTER_UP) {
|
||||
sb.append("(pid " ).append(
|
||||
action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
|
||||
sb.append(")" );
|
||||
}
|
||||
sb.append("[" );
|
||||
for (int i = 0; i < event.getPointerCount(); i++) {
|
||||
sb.append("#" ).append(i);
|
||||
sb.append("(pid " ).append(event.getPointerId(i));
|
||||
sb.append(")=" ).append((int) event.getX(i));
|
||||
sb.append("," ).append((int) event.getY(i));
|
||||
if (i + 1 < event.getPointerCount())
|
||||
sb.append(";" );
|
||||
}
|
||||
sb.append("]" );
|
||||
Log.d(TAG, sb.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,12 +39,12 @@ public class Cocos2dxRenderer implements GLSurfaceView.Renderer {
|
|||
last = now;
|
||||
}
|
||||
|
||||
public void handleActionDown(int[] id, float[] x, float[] y)
|
||||
public void handleActionDown(int id, float x, float y)
|
||||
{
|
||||
nativeTouchesBegin(id, x, y);
|
||||
}
|
||||
|
||||
public void handleActionUp(int[] id, float[] x, float[] y)
|
||||
public void handleActionUp(int id, float x, float y)
|
||||
{
|
||||
nativeTouchesEnd(id, x, y);
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ public class Cocos2dxRenderer implements GLSurfaceView.Renderer {
|
|||
animationInterval = (long)(interval * NANOSECONDSPERSECOND);
|
||||
}
|
||||
|
||||
private static native void nativeTouchesBegin(int[] id, float[] x, float[] y);
|
||||
private static native void nativeTouchesEnd(int[] id, float[] x, float[] y);
|
||||
private static native void nativeTouchesBegin(int id, float x, float y);
|
||||
private static native void nativeTouchesEnd(int id, float x, float y);
|
||||
private static native void nativeTouchesMove(int[] id, float[] x, float[] y);
|
||||
private static native void nativeTouchesCancel(int[] id, float[] x, float[] y);
|
||||
private static native void nativeRender();
|
||||
|
|
|
@ -1,812 +0,0 @@
|
|||
package org.cocos2dx.lib.touch.metalev.multitouch.controller;
|
||||
|
||||
/**
|
||||
* MultiTouchController.java
|
||||
*
|
||||
* Author: Luke Hutchison (luke.hutch@mit.edu)
|
||||
* Please drop me an email if you use this code so I can list your project here!
|
||||
*
|
||||
* Usage:
|
||||
* <code>
|
||||
* public class MyMTView extends View implements MultiTouchObjectCanvas<PinchWidgetType> {
|
||||
*
|
||||
* private MultiTouchController<PinchWidgetType> multiTouchController = new MultiTouchController<PinchWidgetType>(this);
|
||||
*
|
||||
* // Pass touch events to the MT controller
|
||||
* public boolean onTouchEvent(MotionEvent event) {
|
||||
* return multiTouchController.onTouchEvent(event);
|
||||
* }
|
||||
*
|
||||
* // ... then implement the MultiTouchObjectCanvas interface here, see details in the comments of that interface.
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* Changelog:
|
||||
* 2010-06-09 v1.5.1 Some API changes to make it possible to selectively update or not update scale / rotation.
|
||||
* Fixed anisotropic zoom. Cleaned up rotation code. Added more comments. Better var names. (LH)
|
||||
* 2010-06-09 v1.4 Added ability to track pinch rotation (Mickael Despesse, author of "Face Frenzy") and anisotropic pinch-zoom (LH)
|
||||
* 2010-06-09 v1.3.3 Bugfixes for Android-2.1; added optional debug info (LH)
|
||||
* 2010-06-09 v1.3 Ported to Android-2.2 (handle ACTION_POINTER_* actions); fixed several bugs; refactoring; documentation (LH)
|
||||
* 2010-05-17 v1.2.1 Dual-licensed under Apache and GPL licenses
|
||||
* 2010-02-18 v1.2 Support for compilation under Android 1.5/1.6 using introspection (mmin, author of handyCalc)
|
||||
* 2010-01-08 v1.1.1 Bugfixes to Cyanogen's patch that only showed up in more complex uses of controller (LH)
|
||||
* 2010-01-06 v1.1 Modified for official level 5 MT API (Cyanogen)
|
||||
* 2009-01-25 v1.0 Original MT controller, released for hacked G1 kernel (LH)
|
||||
*
|
||||
* Planned features:
|
||||
* - Add inertia (flick-pinch-zoom or flick-scroll)
|
||||
*
|
||||
* Known usages:
|
||||
* - Mickael Despesse's "Face Frenzy" face distortion app, to be published to the Market soon
|
||||
* - Yuan Chin's fork of ADW Launcher to support multitouch
|
||||
* - David Byrne's fractal viewing app Fractoid
|
||||
* - mmin's handyCalc calculator
|
||||
* - My own "MultiTouch Visualizer 2" in the Market
|
||||
* - Formerly: The browser in cyanogenmod (and before that, JesusFreke), and other firmwares like dwang5. This usage has been
|
||||
* replaced with official pinch/zoom in Maps, Browser and Gallery[3D] as of API level 5.
|
||||
*
|
||||
* License:
|
||||
* Dual-licensed under the Apache License v2 and the GPL v2.
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* A class that simplifies the implementation of multitouch in applications. Subclass this and read the fields here as needed in subclasses.
|
||||
*
|
||||
* @author Luke Hutchison
|
||||
*/
|
||||
public class MultiTouchController<T> {
|
||||
|
||||
/**
|
||||
* Time in ms required after a change in event status (e.g. putting down or lifting off the second finger) before events actually do anything --
|
||||
* helps eliminate noisy jumps that happen on change of status
|
||||
*/
|
||||
private static final long EVENT_SETTLE_TIME_INTERVAL = 20;
|
||||
|
||||
/**
|
||||
* The biggest possible abs val of the change in x or y between multitouch events (larger dx/dy events are ignored) -- helps eliminate jumps in
|
||||
* pointer position on finger 2 up/down.
|
||||
*/
|
||||
private static final float MAX_MULTITOUCH_POS_JUMP_SIZE = 30.0f;
|
||||
|
||||
/**
|
||||
* The biggest possible abs val of the change in multitouchWidth or multitouchHeight between multitouch events (larger-jump events are ignored) --
|
||||
* helps eliminate jumps in pointer position on finger 2 up/down.
|
||||
*/
|
||||
private static final float MAX_MULTITOUCH_DIM_JUMP_SIZE = 40.0f;
|
||||
|
||||
/** The smallest possible distance between multitouch points (used to avoid div-by-zero errors and display glitches) */
|
||||
private static final float MIN_MULTITOUCH_SEPARATION = 30.0f;
|
||||
|
||||
/** The max number of touch points that can be present on the screen at once */
|
||||
public static final int MAX_TOUCH_POINTS = 5;
|
||||
|
||||
/** Generate tons of log entries for debugging */
|
||||
public static final boolean DEBUG = false;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
MultiTouchObjectCanvas<T> objectCanvas;
|
||||
|
||||
/** The current touch point */
|
||||
public PointInfo mCurrPt;
|
||||
|
||||
/** The previous touch point */
|
||||
private PointInfo mPrevPt;
|
||||
|
||||
/** Fields extracted from mCurrPt */
|
||||
private float mCurrPtX, mCurrPtY, mCurrPtDiam, mCurrPtWidth, mCurrPtHeight, mCurrPtAng;
|
||||
|
||||
/**
|
||||
* Extract fields from mCurrPt, respecting the update* fields of mCurrPt. This just avoids code duplication. I hate that Java doesn't support
|
||||
* higher-order functions, tuples or multiple return values from functions.
|
||||
*/
|
||||
private void extractCurrPtInfo() {
|
||||
// Get new drag/pinch params. Only read multitouch fields that are needed,
|
||||
// to avoid unnecessary computation (diameter and angle are expensive operations).
|
||||
mCurrPtX = mCurrPt.getX();
|
||||
mCurrPtY = mCurrPt.getY();
|
||||
mCurrPtDiam = Math.max(MIN_MULTITOUCH_SEPARATION * .71f, !mCurrXform.updateScale ? 0.0f : mCurrPt.getMultiTouchDiameter());
|
||||
mCurrPtWidth = Math.max(MIN_MULTITOUCH_SEPARATION, !mCurrXform.updateScaleXY ? 0.0f : mCurrPt.getMultiTouchWidth());
|
||||
mCurrPtHeight = Math.max(MIN_MULTITOUCH_SEPARATION, !mCurrXform.updateScaleXY ? 0.0f : mCurrPt.getMultiTouchHeight());
|
||||
mCurrPtAng = !mCurrXform.updateAngle ? 0.0f : mCurrPt.getMultiTouchAngle();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** Whether to handle single-touch events/drags before multi-touch is initiated or not; if not, they are handled by subclasses */
|
||||
private boolean handleSingleTouchEvents;
|
||||
|
||||
/** The object being dragged/stretched */
|
||||
private T selectedObject = null;
|
||||
|
||||
/** Current position and scale of the dragged object */
|
||||
private PositionAndScale mCurrXform = new PositionAndScale();
|
||||
|
||||
/** Drag/pinch start time and time to ignore spurious events until (to smooth over event noise) */
|
||||
private long mSettleStartTime, mSettleEndTime;
|
||||
|
||||
/** Conversion from object coords to screen coords */
|
||||
private float startPosX, startPosY;
|
||||
|
||||
/** Conversion between scale and width, and object angle and start pinch angle */
|
||||
private float startScaleOverPinchDiam, startAngleMinusPinchAngle;
|
||||
|
||||
/** Conversion between X scale and width, and Y scale and height */
|
||||
private float startScaleXOverPinchWidth, startScaleYOverPinchHeight;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** No touch points down. */
|
||||
private static final int MODE_NOTHING = 0;
|
||||
|
||||
/** One touch point down, dragging an object. */
|
||||
private static final int MODE_DRAG = 1;
|
||||
|
||||
/** Two or more touch points down, stretching/rotating an object using the first two touch points. */
|
||||
private static final int MODE_PINCH = 2;
|
||||
|
||||
/** Current drag mode */
|
||||
private int mMode = MODE_NOTHING;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** Constructor that sets handleSingleTouchEvents to true */
|
||||
public MultiTouchController(MultiTouchObjectCanvas<T> objectCanvas) {
|
||||
this(objectCanvas, true);
|
||||
}
|
||||
|
||||
/** Full constructor */
|
||||
public MultiTouchController(MultiTouchObjectCanvas<T> objectCanvas, boolean handleSingleTouchEvents) {
|
||||
this.mCurrPt = new PointInfo();
|
||||
this.mPrevPt = new PointInfo();
|
||||
this.handleSingleTouchEvents = handleSingleTouchEvents;
|
||||
this.objectCanvas = objectCanvas;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Whether to handle single-touch events/drags before multi-touch is initiated or not; if not, they are handled by subclasses. Default: true
|
||||
*/
|
||||
protected void setHandleSingleTouchEvents(boolean handleSingleTouchEvents) {
|
||||
this.handleSingleTouchEvents = handleSingleTouchEvents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to handle single-touch events/drags before multi-touch is initiated or not; if not, they are handled by subclasses. Default: true
|
||||
*/
|
||||
protected boolean getHandleSingleTouchEvents() {
|
||||
return handleSingleTouchEvents;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
public static final boolean multiTouchSupported;
|
||||
private static Method m_getPointerCount;
|
||||
private static Method m_getPointerId;
|
||||
private static Method m_getPressure;
|
||||
private static Method m_getHistoricalX;
|
||||
private static Method m_getHistoricalY;
|
||||
private static Method m_getHistoricalPressure;
|
||||
private static Method m_getX;
|
||||
private static Method m_getY;
|
||||
private static int ACTION_POINTER_UP = 6;
|
||||
private static int ACTION_POINTER_INDEX_SHIFT = 8;
|
||||
|
||||
static {
|
||||
boolean succeeded = false;
|
||||
try {
|
||||
// Android 2.0.1 stuff:
|
||||
m_getPointerCount = MotionEvent.class.getMethod("getPointerCount");
|
||||
m_getPointerId = MotionEvent.class.getMethod("getPointerId", Integer.TYPE);
|
||||
m_getPressure = MotionEvent.class.getMethod("getPressure", Integer.TYPE);
|
||||
m_getHistoricalX = MotionEvent.class.getMethod("getHistoricalX", Integer.TYPE, Integer.TYPE);
|
||||
m_getHistoricalY = MotionEvent.class.getMethod("getHistoricalY", Integer.TYPE, Integer.TYPE);
|
||||
m_getHistoricalPressure = MotionEvent.class.getMethod("getHistoricalPressure", Integer.TYPE, Integer.TYPE);
|
||||
m_getX = MotionEvent.class.getMethod("getX", Integer.TYPE);
|
||||
m_getY = MotionEvent.class.getMethod("getY", Integer.TYPE);
|
||||
succeeded = true;
|
||||
} catch (Exception e) {
|
||||
Log.e("MultiTouchController", "static initializer failed", e);
|
||||
}
|
||||
multiTouchSupported = succeeded;
|
||||
if (multiTouchSupported) {
|
||||
// Android 2.2+ stuff (the original Android 2.2 consts are declared above,
|
||||
// and these actions aren't used previous to Android 2.2):
|
||||
try {
|
||||
ACTION_POINTER_UP = MotionEvent.class.getField("ACTION_POINTER_UP").getInt(null);
|
||||
ACTION_POINTER_INDEX_SHIFT = MotionEvent.class.getField("ACTION_POINTER_INDEX_SHIFT").getInt(null);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
private static final float[] xVals = new float[MAX_TOUCH_POINTS];
|
||||
private static final float[] yVals = new float[MAX_TOUCH_POINTS];
|
||||
private static final float[] pressureVals = new float[MAX_TOUCH_POINTS];
|
||||
private static final int[] pointerIds = new int[MAX_TOUCH_POINTS];
|
||||
|
||||
/** Process incoming touch events */
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
try {
|
||||
int pointerCount = multiTouchSupported ? (Integer) m_getPointerCount.invoke(event) : 1;
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 1 - " + multiTouchSupported + " " + mMode + " " + handleSingleTouchEvents + " " + pointerCount);
|
||||
if (mMode == MODE_NOTHING && !handleSingleTouchEvents && pointerCount == 1)
|
||||
// Not handling initial single touch events, just pass them on
|
||||
return false;
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 2");
|
||||
|
||||
// Handle history first (we sometimes get history with ACTION_MOVE events)
|
||||
int action = event.getAction();
|
||||
int histLen = event.getHistorySize() / pointerCount;
|
||||
for (int histIdx = 0; histIdx <= histLen; histIdx++) {
|
||||
// Read from history entries until histIdx == histLen, then read from current event
|
||||
boolean processingHist = histIdx < histLen;
|
||||
if (!multiTouchSupported || pointerCount == 1) {
|
||||
// Use single-pointer methods -- these are needed as a special case (for some weird reason) even if
|
||||
// multitouch is supported but there's only one touch point down currently -- event.getX(0) etc. throw
|
||||
// an exception if there's only one point down.
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 3");
|
||||
xVals[0] = processingHist ? event.getHistoricalX(histIdx) : event.getX();
|
||||
yVals[0] = processingHist ? event.getHistoricalY(histIdx) : event.getY();
|
||||
pressureVals[0] = processingHist ? event.getHistoricalPressure(histIdx) : event.getPressure();
|
||||
} else {
|
||||
// Read x, y and pressure of each pointer
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 4");
|
||||
int numPointers = Math.min(pointerCount, MAX_TOUCH_POINTS);
|
||||
if (DEBUG && pointerCount > MAX_TOUCH_POINTS)
|
||||
Log.i("MultiTouch", "Got more pointers than MAX_TOUCH_POINTS");
|
||||
for (int ptrIdx = 0; ptrIdx < numPointers; ptrIdx++) {
|
||||
int ptrId = (Integer) m_getPointerId.invoke(event, ptrIdx);
|
||||
pointerIds[ptrIdx] = ptrId;
|
||||
// N.B. if pointerCount == 1, then the following methods throw an array index out of range exception,
|
||||
// and the code above is therefore required not just for Android 1.5/1.6 but also for when there is
|
||||
// only one touch point on the screen -- pointlessly inconsistent :(
|
||||
xVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalX.invoke(event, ptrIdx, histIdx) : m_getX.invoke(event, ptrIdx));
|
||||
yVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalY.invoke(event, ptrIdx, histIdx) : m_getY.invoke(event, ptrIdx));
|
||||
pressureVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalPressure.invoke(event, ptrIdx, histIdx) : m_getPressure
|
||||
.invoke(event, ptrIdx));
|
||||
}
|
||||
}
|
||||
// Decode event
|
||||
decodeTouchEvent(pointerCount, xVals, yVals, pressureVals, pointerIds, //
|
||||
/* action = */processingHist ? MotionEvent.ACTION_MOVE : action, //
|
||||
/* down = */processingHist ? true : action != MotionEvent.ACTION_UP //
|
||||
&& (action & ((1 << ACTION_POINTER_INDEX_SHIFT) - 1)) != ACTION_POINTER_UP //
|
||||
&& action != MotionEvent.ACTION_CANCEL, //
|
||||
processingHist ? event.getHistoricalEventTime(histIdx) : event.getEventTime());
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
// In case any of the introspection stuff fails (it shouldn't)
|
||||
Log.e("MultiTouchController", "onTouchEvent() failed", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void decodeTouchEvent(int pointerCount, float[] x, float[] y, float[] pressure, int[] pointerIds, int action, boolean down, long eventTime) {
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 5 - " + pointerCount + " " + action + " " + down);
|
||||
|
||||
// Swap curr/prev points
|
||||
PointInfo tmp = mPrevPt;
|
||||
mPrevPt = mCurrPt;
|
||||
mCurrPt = tmp;
|
||||
// Overwrite old prev point
|
||||
mCurrPt.set(pointerCount, x, y, pressure, pointerIds, action, down, eventTime);
|
||||
multiTouchController();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
/** Start dragging/pinching, or reset drag/pinch to current point if something goes out of range */
|
||||
private void anchorAtThisPositionAndScale() {
|
||||
if (selectedObject == null)
|
||||
return;
|
||||
|
||||
// Get selected object's current position and scale
|
||||
objectCanvas.getPositionAndScale(selectedObject, mCurrXform);
|
||||
|
||||
// Figure out the object coords of the drag start point's screen coords.
|
||||
// All stretching should be around this point in object-coord-space.
|
||||
// Also figure out out ratio between object scale factor and multitouch
|
||||
// diameter at beginning of drag; same for angle and optional anisotropic
|
||||
// scale.
|
||||
float currScaleInv = 1.0f / (!mCurrXform.updateScale ? 1.0f : mCurrXform.scale == 0.0f ? 1.0f : mCurrXform.scale);
|
||||
extractCurrPtInfo();
|
||||
startPosX = (mCurrPtX - mCurrXform.xOff) * currScaleInv;
|
||||
startPosY = (mCurrPtY - mCurrXform.yOff) * currScaleInv;
|
||||
startScaleOverPinchDiam = mCurrXform.scale / mCurrPtDiam;
|
||||
startScaleXOverPinchWidth = mCurrXform.scaleX / mCurrPtWidth;
|
||||
startScaleYOverPinchHeight = mCurrXform.scaleY / mCurrPtHeight;
|
||||
startAngleMinusPinchAngle = mCurrXform.angle - mCurrPtAng;
|
||||
}
|
||||
|
||||
/** Drag/stretch/rotate the selected object using the current touch position(s) relative to the anchor position(s). */
|
||||
private void performDragOrPinch() {
|
||||
// Don't do anything if we're not dragging anything
|
||||
if (selectedObject == null)
|
||||
return;
|
||||
|
||||
// Calc new position of dragged object
|
||||
float currScale = !mCurrXform.updateScale ? 1.0f : mCurrXform.scale == 0.0f ? 1.0f : mCurrXform.scale;
|
||||
extractCurrPtInfo();
|
||||
float newPosX = mCurrPtX - startPosX * currScale;
|
||||
float newPosY = mCurrPtY - startPosY * currScale;
|
||||
float newScale = startScaleOverPinchDiam * mCurrPtDiam;
|
||||
float newScaleX = startScaleXOverPinchWidth * mCurrPtWidth;
|
||||
float newScaleY = startScaleYOverPinchHeight * mCurrPtHeight;
|
||||
float newAngle = startAngleMinusPinchAngle + mCurrPtAng;
|
||||
|
||||
// Set the new obj coords, scale, and angle as appropriate (notifying the subclass of the change).
|
||||
mCurrXform.set(newPosX, newPosY, newScale, newScaleX, newScaleY, newAngle);
|
||||
|
||||
boolean success = objectCanvas.setPositionAndScale(selectedObject, mCurrXform, mCurrPt);
|
||||
if (!success)
|
||||
; // If we could't set those params, do nothing currently
|
||||
}
|
||||
|
||||
/**
|
||||
* State-based controller for tracking switches between no-touch, single-touch and multi-touch situations. Includes logic for cleaning up the
|
||||
* event stream, as events around touch up/down are noisy at least on early Synaptics sensors.
|
||||
*/
|
||||
private void multiTouchController() {
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 6 - " + mMode + " " + mCurrPt.getNumTouchPoints() + " " + mCurrPt.isDown() + mCurrPt.isMultiTouch());
|
||||
|
||||
switch (mMode) {
|
||||
case MODE_NOTHING:
|
||||
// Not doing anything currently
|
||||
if (mCurrPt.isDown()) {
|
||||
// Start a new single-point drag
|
||||
selectedObject = objectCanvas.getDraggableObjectAtPoint(mCurrPt);
|
||||
if (selectedObject != null) {
|
||||
// Started a new single-point drag
|
||||
mMode = MODE_DRAG;
|
||||
objectCanvas.selectObject(selectedObject, mCurrPt);
|
||||
anchorAtThisPositionAndScale();
|
||||
// Don't need any settling time if just placing one finger, there is no noise
|
||||
mSettleStartTime = mSettleEndTime = mCurrPt.getEventTime();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MODE_DRAG:
|
||||
// Currently in a single-point drag
|
||||
if (!mCurrPt.isDown()) {
|
||||
// First finger was released, stop dragging
|
||||
mMode = MODE_NOTHING;
|
||||
objectCanvas.selectObject((selectedObject = null), mCurrPt);
|
||||
|
||||
} else if (mCurrPt.isMultiTouch()) {
|
||||
// Point 1 was already down and point 2 was just placed down
|
||||
mMode = MODE_PINCH;
|
||||
// Restart the drag with the new drag position (that is at the midpoint between the touchpoints)
|
||||
anchorAtThisPositionAndScale();
|
||||
// Need to let events settle before moving things, to help with event noise on touchdown
|
||||
mSettleStartTime = mCurrPt.getEventTime();
|
||||
mSettleEndTime = mSettleStartTime + EVENT_SETTLE_TIME_INTERVAL;
|
||||
|
||||
} else {
|
||||
// Point 1 is still down and point 2 did not change state, just do single-point drag to new location
|
||||
if (mCurrPt.getEventTime() < mSettleEndTime) {
|
||||
// Ignore the first few events if we just stopped stretching, because if finger 2 was kept down while
|
||||
// finger 1 is lifted, then point 1 gets mapped to finger 2. Restart the drag from the new position.
|
||||
anchorAtThisPositionAndScale();
|
||||
} else {
|
||||
// Keep dragging, move to new point
|
||||
performDragOrPinch();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MODE_PINCH:
|
||||
// Two-point pinch-scale/rotate/translate
|
||||
if (!mCurrPt.isMultiTouch() || !mCurrPt.isDown()) {
|
||||
// Dropped one or both points, stop stretching
|
||||
|
||||
if (!mCurrPt.isDown()) {
|
||||
// Dropped both points, go back to doing nothing
|
||||
mMode = MODE_NOTHING;
|
||||
objectCanvas.selectObject((selectedObject = null), mCurrPt);
|
||||
|
||||
} else {
|
||||
// Just dropped point 2, downgrade to a single-point drag
|
||||
mMode = MODE_DRAG;
|
||||
// Restart the pinch with the single-finger position
|
||||
anchorAtThisPositionAndScale();
|
||||
// Ignore the first few events after the drop, in case we dropped finger 1 and left finger 2 down
|
||||
mSettleStartTime = mCurrPt.getEventTime();
|
||||
mSettleEndTime = mSettleStartTime + EVENT_SETTLE_TIME_INTERVAL;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Still pinching
|
||||
if (Math.abs(mCurrPt.getX() - mPrevPt.getX()) > MAX_MULTITOUCH_POS_JUMP_SIZE
|
||||
|| Math.abs(mCurrPt.getY() - mPrevPt.getY()) > MAX_MULTITOUCH_POS_JUMP_SIZE
|
||||
|| Math.abs(mCurrPt.getMultiTouchWidth() - mPrevPt.getMultiTouchWidth()) * .5f > MAX_MULTITOUCH_DIM_JUMP_SIZE
|
||||
|| Math.abs(mCurrPt.getMultiTouchHeight() - mPrevPt.getMultiTouchHeight()) * .5f > MAX_MULTITOUCH_DIM_JUMP_SIZE) {
|
||||
// Jumped too far, probably event noise, reset and ignore events for a bit
|
||||
anchorAtThisPositionAndScale();
|
||||
mSettleStartTime = mCurrPt.getEventTime();
|
||||
mSettleEndTime = mSettleStartTime + EVENT_SETTLE_TIME_INTERVAL;
|
||||
|
||||
} else if (mCurrPt.eventTime < mSettleEndTime) {
|
||||
// Events have not yet settled, reset
|
||||
anchorAtThisPositionAndScale();
|
||||
} else {
|
||||
// Stretch to new position and size
|
||||
performDragOrPinch();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 7 - " + mMode + " " + mCurrPt.getNumTouchPoints() + " " + mCurrPt.isDown() + mCurrPt.isMultiTouch());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
/** A class that packages up all MotionEvent information with all derived multitouch information (if available) */
|
||||
public static class PointInfo {
|
||||
// Multitouch information
|
||||
private int numPoints;
|
||||
private float[] xs = new float[MAX_TOUCH_POINTS];
|
||||
private float[] ys = new float[MAX_TOUCH_POINTS];
|
||||
private float[] pressures = new float[MAX_TOUCH_POINTS];
|
||||
private int[] pointerIds = new int[MAX_TOUCH_POINTS];
|
||||
|
||||
// Midpoint of pinch operations
|
||||
private float xMid, yMid, pressureMid;
|
||||
|
||||
// Width/diameter/angle of pinch operations
|
||||
private float dx, dy, diameter, diameterSq, angle;
|
||||
|
||||
// Whether or not there is at least one finger down (isDown) and/or at least two fingers down (isMultiTouch)
|
||||
private boolean isDown, isMultiTouch;
|
||||
|
||||
// Whether or not these fields have already been calculated, for caching purposes
|
||||
private boolean diameterSqIsCalculated, diameterIsCalculated, angleIsCalculated;
|
||||
|
||||
// Event action code and event time
|
||||
private int action;
|
||||
private long eventTime;
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** Set all point info */
|
||||
private void set(int numPoints, float[] x, float[] y, float[] pressure, int[] pointerIds, int action, boolean isDown, long eventTime) {
|
||||
if (DEBUG)
|
||||
Log.i("MultiTouch", "Got here 8 - " + +numPoints + " " + x[0] + " " + y[0] + " " + (numPoints > 1 ? x[1] : x[0]) + " "
|
||||
+ (numPoints > 1 ? y[1] : y[0]) + " " + action + " " + isDown);
|
||||
this.eventTime = eventTime;
|
||||
this.action = action;
|
||||
this.numPoints = numPoints;
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
this.xs[i] = x[i];
|
||||
this.ys[i] = y[i];
|
||||
this.pressures[i] = pressure[i];
|
||||
this.pointerIds[i] = pointerIds[i];
|
||||
}
|
||||
this.isDown = isDown;
|
||||
this.isMultiTouch = numPoints >= 2;
|
||||
|
||||
if (isMultiTouch) {
|
||||
xMid = (x[0] + x[1]) * .5f;
|
||||
yMid = (y[0] + y[1]) * .5f;
|
||||
pressureMid = (pressure[0] + pressure[1]) * .5f;
|
||||
dx = Math.abs(x[1] - x[0]);
|
||||
dy = Math.abs(y[1] - y[0]);
|
||||
|
||||
} else {
|
||||
// Single-touch event
|
||||
xMid = x[0];
|
||||
yMid = y[0];
|
||||
pressureMid = pressure[0];
|
||||
dx = dy = 0.0f;
|
||||
}
|
||||
// Need to re-calculate the expensive params if they're needed
|
||||
diameterSqIsCalculated = diameterIsCalculated = angleIsCalculated = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy all fields from one PointInfo class to another. PointInfo objects are volatile so you should use this if you want to keep track of the
|
||||
* last touch event in your own code.
|
||||
*/
|
||||
public void set(PointInfo other) {
|
||||
this.numPoints = other.numPoints;
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
this.xs[i] = other.xs[i];
|
||||
this.ys[i] = other.ys[i];
|
||||
this.pressures[i] = other.pressures[i];
|
||||
this.pointerIds[i] = other.pointerIds[i];
|
||||
}
|
||||
this.xMid = other.xMid;
|
||||
this.yMid = other.yMid;
|
||||
this.pressureMid = other.pressureMid;
|
||||
this.dx = other.dx;
|
||||
this.dy = other.dy;
|
||||
this.diameter = other.diameter;
|
||||
this.diameterSq = other.diameterSq;
|
||||
this.angle = other.angle;
|
||||
this.isDown = other.isDown;
|
||||
this.action = other.action;
|
||||
this.isMultiTouch = other.isMultiTouch;
|
||||
this.diameterIsCalculated = other.diameterIsCalculated;
|
||||
this.diameterSqIsCalculated = other.diameterSqIsCalculated;
|
||||
this.angleIsCalculated = other.angleIsCalculated;
|
||||
this.eventTime = other.eventTime;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** True if number of touch points >= 2. */
|
||||
public boolean isMultiTouch() {
|
||||
return isMultiTouch;
|
||||
}
|
||||
|
||||
/** Difference between x coords of touchpoint 0 and 1. */
|
||||
public float getMultiTouchWidth() {
|
||||
return isMultiTouch ? dx : 0.0f;
|
||||
}
|
||||
|
||||
/** Difference between y coords of touchpoint 0 and 1. */
|
||||
public float getMultiTouchHeight() {
|
||||
return isMultiTouch ? dy : 0.0f;
|
||||
}
|
||||
|
||||
/** Fast integer sqrt, by Jim Ulery. Much faster than Math.sqrt() for integers. */
|
||||
private int julery_isqrt(int val) {
|
||||
int temp, g = 0, b = 0x8000, bshft = 15;
|
||||
do {
|
||||
if (val >= (temp = (((g << 1) + b) << bshft--))) {
|
||||
g += b;
|
||||
val -= temp;
|
||||
}
|
||||
} while ((b >>= 1) > 0);
|
||||
return g;
|
||||
}
|
||||
|
||||
/** Calculate the squared diameter of the multitouch event, and cache it. Use this if you don't need to perform the sqrt. */
|
||||
public float getMultiTouchDiameterSq() {
|
||||
if (!diameterSqIsCalculated) {
|
||||
diameterSq = (isMultiTouch ? dx * dx + dy * dy : 0.0f);
|
||||
diameterSqIsCalculated = true;
|
||||
}
|
||||
return diameterSq;
|
||||
}
|
||||
|
||||
/** Calculate the diameter of the multitouch event, and cache it. Uses fast int sqrt but gives accuracy to 1/16px. */
|
||||
public float getMultiTouchDiameter() {
|
||||
if (!diameterIsCalculated) {
|
||||
if (!isMultiTouch) {
|
||||
diameter = 0.0f;
|
||||
} else {
|
||||
// Get 1/16 pixel's worth of subpixel accuracy, works on screens up to 2048x2048
|
||||
// before we get overflow (at which point you can reduce or eliminate subpix
|
||||
// accuracy, or use longs in julery_isqrt())
|
||||
float diamSq = getMultiTouchDiameterSq();
|
||||
diameter = (diamSq == 0.0f ? 0.0f : (float) julery_isqrt((int) (256 * diamSq)) / 16.0f);
|
||||
// Make sure diameter is never less than dx or dy, for trig purposes
|
||||
if (diameter < dx)
|
||||
diameter = dx;
|
||||
if (diameter < dy)
|
||||
diameter = dy;
|
||||
}
|
||||
diameterIsCalculated = true;
|
||||
}
|
||||
return diameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the angle of a multitouch event, and cache it. Actually gives the smaller of the two angles between the x axis and the line
|
||||
* between the two touchpoints, so range is [0,Math.PI/2]. Uses Math.atan2().
|
||||
*/
|
||||
public float getMultiTouchAngle() {
|
||||
if (!angleIsCalculated) {
|
||||
if (!isMultiTouch)
|
||||
angle = 0.0f;
|
||||
else
|
||||
angle = (float) Math.atan2(ys[1] - ys[0], xs[1] - xs[0]);
|
||||
angleIsCalculated = true;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** Return the total number of touch points */
|
||||
public int getNumTouchPoints() {
|
||||
return numPoints;
|
||||
}
|
||||
|
||||
/** Return the X coord of the first touch point if there's only one, or the midpoint between first and second touch points if two or more. */
|
||||
public float getX() {
|
||||
return xMid;
|
||||
}
|
||||
|
||||
/** Return the array of X coords -- only the first getNumTouchPoints() of these is defined. */
|
||||
public float[] getXs() {
|
||||
return xs;
|
||||
}
|
||||
|
||||
/** Return the X coord of the first touch point if there's only one, or the midpoint between first and second touch points if two or more. */
|
||||
public float getY() {
|
||||
return yMid;
|
||||
}
|
||||
|
||||
/** Return the array of Y coords -- only the first getNumTouchPoints() of these is defined. */
|
||||
public float[] getYs() {
|
||||
return ys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the array of pointer ids -- only the first getNumTouchPoints() of these is defined. These don't have to be all the numbers from 0 to
|
||||
* getNumTouchPoints()-1 inclusive, numbers can be skipped if a finger is lifted and the touch sensor is capable of detecting that that
|
||||
* particular touch point is no longer down. Note that a lot of sensors do not have this capability: when finger 1 is lifted up finger 2
|
||||
* becomes the new finger 1. However in theory these IDs can correct for that. Convert back to indices using MotionEvent.findPointerIndex().
|
||||
*/
|
||||
public int[] getPointerIds() {
|
||||
return pointerIds;
|
||||
}
|
||||
|
||||
/** Return the pressure the first touch point if there's only one, or the average pressure of first and second touch points if two or more. */
|
||||
public float getPressure() {
|
||||
return pressureMid;
|
||||
}
|
||||
|
||||
/** Return the array of pressures -- only the first getNumTouchPoints() of these is defined. */
|
||||
public float[] getPressures() {
|
||||
return pressures;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
public boolean isDown() {
|
||||
return isDown;
|
||||
}
|
||||
|
||||
public int getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public long getEventTime() {
|
||||
return eventTime;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A class that is used to store scroll offsets and scale information for objects that are managed by the multitouch controller
|
||||
*/
|
||||
public static class PositionAndScale {
|
||||
private float xOff, yOff, scale, scaleX, scaleY, angle;
|
||||
private boolean updateScale, updateScaleXY, updateAngle;
|
||||
|
||||
/**
|
||||
* Set position and optionally scale, anisotropic scale, and/or angle. Where if the corresponding "update" flag is set to false, the field's
|
||||
* value will not be changed during a pinch operation. If the value is not being updated *and* the value is not used by the client
|
||||
* application, then the value can just be zero. However if the value is not being updated but the value *is* being used by the client
|
||||
* application, the value should still be specified and the update flag should be false (e.g. angle of the object being dragged should still
|
||||
* be specified even if the program is in "resize" mode rather than "rotate" mode).
|
||||
*/
|
||||
public void set(float xOff, float yOff, boolean updateScale, float scale, boolean updateScaleXY, float scaleX, float scaleY,
|
||||
boolean updateAngle, float angle) {
|
||||
this.xOff = xOff;
|
||||
this.yOff = yOff;
|
||||
this.updateScale = updateScale;
|
||||
this.scale = scale == 0.0f ? 1.0f : scale;
|
||||
this.updateScaleXY = updateScaleXY;
|
||||
this.scaleX = scaleX == 0.0f ? 1.0f : scaleX;
|
||||
this.scaleY = scaleY == 0.0f ? 1.0f : scaleY;
|
||||
this.updateAngle = updateAngle;
|
||||
this.angle = angle;
|
||||
}
|
||||
|
||||
/** Set position and optionally scale, anisotropic scale, and/or angle, without changing the "update" flags. */
|
||||
protected void set(float xOff, float yOff, float scale, float scaleX, float scaleY, float angle) {
|
||||
this.xOff = xOff;
|
||||
this.yOff = yOff;
|
||||
this.scale = scale == 0.0f ? 1.0f : scale;
|
||||
this.scaleX = scaleX == 0.0f ? 1.0f : scaleX;
|
||||
this.scaleY = scaleY == 0.0f ? 1.0f : scaleY;
|
||||
this.angle = angle;
|
||||
}
|
||||
|
||||
public float getXOff() {
|
||||
return xOff;
|
||||
}
|
||||
|
||||
public float getYOff() {
|
||||
return yOff;
|
||||
}
|
||||
|
||||
public float getScale() {
|
||||
return !updateScale ? 1.0f : scale;
|
||||
}
|
||||
|
||||
/** Included in case you want to support anisotropic scaling */
|
||||
public float getScaleX() {
|
||||
return !updateScaleXY ? 1.0f : scaleX;
|
||||
}
|
||||
|
||||
/** Included in case you want to support anisotropic scaling */
|
||||
public float getScaleY() {
|
||||
return !updateScaleXY ? 1.0f : scaleY;
|
||||
}
|
||||
|
||||
public float getAngle() {
|
||||
return !updateAngle ? 0.0f : angle;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
public static interface MultiTouchObjectCanvas<T> {
|
||||
|
||||
/**
|
||||
* See if there is a draggable object at the current point. Returns the object at the point, or null if nothing to drag. To start a multitouch
|
||||
* drag/stretch operation, this routine must return some non-null reference to an object. This object is passed into the other methods in this
|
||||
* interface when they are called.
|
||||
*
|
||||
* @param touchPoint
|
||||
* The point being tested (in object coordinates). Return the topmost object under this point, or if dragging/stretching the whole
|
||||
* canvas, just return a reference to the canvas.
|
||||
* @return a reference to the object under the point being tested, or null to cancel the drag operation. If dragging/stretching the whole
|
||||
* canvas (e.g. in a photo viewer), always return non-null, otherwise the stretch operation won't work.
|
||||
*/
|
||||
public T getDraggableObjectAtPoint(PointInfo touchPoint);
|
||||
|
||||
/**
|
||||
* Get the screen coords of the dragged object's origin, and scale multiplier to convert screen coords to obj coords. The job of this routine
|
||||
* is to call the .set() method on the passed PositionAndScale object to record the initial position and scale of the object (in object
|
||||
* coordinates) before any dragging/stretching takes place.
|
||||
*
|
||||
* @param obj
|
||||
* The object being dragged/stretched.
|
||||
* @param objPosAndScaleOut
|
||||
* Output parameter: You need to call objPosAndScaleOut.set() to record the current position and scale of obj.
|
||||
*/
|
||||
public void getPositionAndScale(T obj, PositionAndScale objPosAndScaleOut);
|
||||
|
||||
/**
|
||||
* Callback to update the position and scale (in object coords) of the currently-dragged object.
|
||||
*
|
||||
* @param obj
|
||||
* The object being dragged/stretched.
|
||||
* @param newObjPosAndScale
|
||||
* The new position and scale of the object, in object coordinates. Use this to move/resize the object before returning.
|
||||
* @param touchPoint
|
||||
* Info about the current touch point, including multitouch information and utilities to calculate and cache multitouch pinch
|
||||
* diameter etc. (Note: touchPoint is volatile, if you want to keep any fields of touchPoint, you must copy them before the method
|
||||
* body exits.)
|
||||
* @return true if setting the position and scale of the object was successful, or false if the position or scale parameters are out of range
|
||||
* for this object.
|
||||
*/
|
||||
public boolean setPositionAndScale(T obj, PositionAndScale newObjPosAndScale, PointInfo touchPoint);
|
||||
|
||||
/**
|
||||
* Select an object at the given point. Can be used to bring the object to top etc. Only called when first touchpoint goes down, not when
|
||||
* multitouch is initiated. Also called with null on touch-up.
|
||||
*
|
||||
* @param obj
|
||||
* The object being selected by single-touch, or null on touch-up.
|
||||
* @param touchPoint
|
||||
* The current touch point.
|
||||
*/
|
||||
public void selectObject(T obj, PointInfo touchPoint);
|
||||
}
|
||||
}
|
|
@ -1 +1 @@
|
|||
338236875114a0bacedc941ed640ad725f71e061
|
||||
2950d252aeb110a0d262811b794bdd2ff25c03b6
|
|
@ -1 +1 @@
|
|||
1df0bf26583b2b3cfde43364d98d925393dddb51
|
||||
9e16647d99e1705b6436f4764cfacc6a478d3715
|
Loading…
Reference in New Issue