I have code like this:
public void handle(MouseEvent event) {
//if (event.getEventType() == MouseEvent.MOUSE_CLICKED) {
if ( ( event.getEventType() == MouseEvent.MOUSE_PRESSED )&&
(event.isPrimaryButtonDown()) ) {
x1 = x2 = event.getX();
y1 = y2 = event.getY();
line = new BoundLine(pane, event, x1, y1, x2, y2);
pane.getChildren().add(line);
//line.getEventDispatcher().dispatchEvent(event, null);
}
}
Is it possibile to propagate immediately the "MouseEvent event" to the javafx.scene.shape.Line (line in the code) object ? I have tried line.getEventDispatcher().dispatchEvent(event, null); but I've got this message error:
Exception in thread "JavaFX Application Thread"
java.lang.NullPointerException at
com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at
testjavafxapplication.LinesEditCtx02$MouseHandler.handle(LinesEditCtx02.java:243)
at
testjavafxapplication.LinesEditCtx02$MouseHandler.handle(LinesEditCtx02.java:105)
at
com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
at
com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
at
com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
at
com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
at
com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
at
com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at
com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at
com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33) at
javafx.event.Event.fireEvent(Event.java:171) at
javafx.scene.Scene$MouseHandler.process(Scene.java:3324) at
javafx.scene.Scene$MouseHandler.process(Scene.java:3164) at
javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3119) at
javafx.scene.Scene.impl_processMouseEvent(Scene.java:1559) at
javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2261) at
com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:228)
at com.sun.glass.ui.View.handleMouseEvent(View.java:528) at
com.sun.glass.ui.View.notifyMouse(View.java:922) at
com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) at
com.sun.glass.ui.gtk.GtkApplication$3$1.run(GtkApplication.java:82)
at java.lang.Thread.run(Thread.java:722)
The EventDispatchChain (second argument) that is being sent to #dispatchEvent cannot be null. Unfortunately there are no public implementations, or they are in com.sun packages so you would need to implement your own EventDispatchChain.
Related
Whenever i touch the event call and pointer index exception came and crash the app in android xamarin forms
/** Determine the space between the first two fingers */
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float)Math.sqrt(x * x + y * y);
}
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
ImageView view = (ImageView) v;
dumpEvent(event);
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG");
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
Log.d(TAG, "oldDist=" + oldDist);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
Log.d(TAG, "mode=ZOOM");
}
}
I thought I'd just finished an app, however when I build for iOS, there is a certain section that is returning a
"NullReferenceException: A null value was found where an object instance was required."
Here is the Xcode error:
NullReferenceException: A null value was found where an object instance was required.
at nextSetAmount.nextButtonCelestials (Boolean onOff) [0x00000] in <filename unknown>:0
at celestialDialogueInstantiator.setActive (Int32 indexToTurnOn) [0x00000] in <filename unknown>:0
at UnityEngine.Events.UnityEvent.Invoke () [0x00000] in <filename unknown>:0
at UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) [0x00000] in <filename unknown>:0
at UnityEngine.EventSystems.StandaloneInputModule.ProcessTouchPress (UnityEngine.EventSystems.PointerEventData pointerEvent, Boolean pressed, Boolean released) [0x00000] in <filename unknown>:0
at UnityEngine.EventSystems.StandaloneInputModule.ProcessTouchEvents () [0x00000] in <filename unknown>:0
at UnityEngine.EventSystems.StandaloneInputModule.Process () [0x00000] in <filename unknown>:0
UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
UnityEngine.EventSystems.StandaloneInputModule:Process()
(Filename: currently not available on il2cpp Line: -1)
NullReferenceException: A null value was found where an object instance was required.
at audioManagerCreate.Start () [0x00000] in <filename unknown>:0
and here are the respective scripts that it's talking about:
nextSetAmount
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class nextSetAmount : MonoBehaviour {
public GameObject slider;
public GameObject dialogueManager;
public GameObject celestialManager;
public GameObject audioManager;
public GameObject celestialObject;
// Use this for initialization
public void nextButtonDialogue (bool onOff) {
if(onOff == true)
{
dialogueManager.GetComponent<celestialDialogueInstantiator>().makeDialogue(Mathf.RoundToInt(slider.GetComponent<Slider>().value));
}
}
public void nextButtonCelestials (bool onOff) {
if(onOff == true)
{
audioManager.SetActive(true);
AudioListener.pause = true;
for(int i = 0; i < slider.GetComponent<Slider>().value; i++)
{
Transform celestialDialogue = GameObject.Find("celestialDialogue"+i).gameObject.transform;
string celestialName = celestialDialogue.GetChild(2).GetComponent<Text>().text;
float celestialBodyDistance = celestialDialogue.GetChild(4).GetComponent<Slider>().value;
float celestialOrbitalFrequency = celestialDialogue.GetChild(6).GetComponent<Slider>().value;
float celestialRotationalFrequency = celestialDialogue.GetChild(8).GetComponent<Slider>().value;
float celestialBodyDiameter = celestialDialogue.GetChild(10).GetComponent<Slider>().value;
float celestialBodyTemperature = celestialDialogue.GetChild(12).GetComponent<Slider>().value;
// Instantiate celestialObject prefab
var instantiatedCelestial = Instantiate(celestialObject, new Vector3(0,0,0),Quaternion.identity);
// Define properties script for ease of code
var celProps = instantiatedCelestial.GetComponent<celestialProperties>();
// Set name of instantiated prefab
instantiatedCelestial.gameObject.name = ("celestialObject"+i);
// Set parent of instantiated prefab
instantiatedCelestial.transform.SetParent(GameObject.Find("celestialManager").transform);
// Randomise properties of the instantiated celestialObject prefab
celProps.celestialName = celestialName;
celProps.celestialID = i;
// Set distance from centre as i (celestialObject number) + a float value. This ensures that 0 is closest, and x where x = amountOfCelestials is the furthest.
celProps.celestialBodyDistance = celestialBodyDistance;
celProps.celestialOrbitFrequency = celestialOrbitalFrequency;
celProps.celestialRotationalFrequency = celestialRotationalFrequency;
celProps.celestialBodyDiameter = celestialBodyDiameter;
celProps.celestialBodyTemperature = celestialBodyTemperature;
celProps.celestialOrbitAxis = new Vector3(0,1,0);
// Store initial values for these two so that scaling doesn't multiply by itself
celProps.celestialInitOrbitFrequency = celProps.celestialOrbitFrequency;
celProps.celestialInitRotationalFrequency = celProps.celestialRotationalFrequency;
}
}
}
}
celestialDialogueInstantiator
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
public class celestialDialogueInstantiator : MonoBehaviour {
// Define prefab to instantiate
public GameObject celestialDialogue;
public GameObject systemNameCreate;
public GameObject parent;
public int dialogueID;
public GameObject slider;
public GameObject[] celestialObjects;
// Use this for instantiation
public void makeDialogue (int sliderValue)
{
// For loop that instantiates x amount of dialogues where x = argument.
for(int i = 0; i < sliderValue; i++)
{
var instantiatedDialogue = Instantiate(celestialDialogue,transform.position, Quaternion.identity);
instantiatedDialogue.transform.SetParent(GameObject.Find("createDialogue").gameObject.transform, false);
instantiatedDialogue.SetActive(false);
instantiatedDialogue.name = "celestialDialogue"+i;
instantiatedDialogue.GetComponent<dialogueID>().ID = i;
if (i == 0)
{
instantiatedDialogue.SetActive(true);
}
}
}
public void setActive(int indexToTurnOn)
{
// Turn on next dialogue
if(indexToTurnOn != slider.GetComponent<Slider>().value)
{
GameObject.Find("createDialogue").gameObject.transform.GetChild(indexToTurnOn).gameObject.transform.localScale = new Vector3(0,0,0);
GameObject.Find("createDialogue").gameObject.transform.GetChild(1+indexToTurnOn).gameObject.SetActive(true);
}
// When the last next button is pressed.
else
{
// Set active createCelestials GUI panel
Resources.FindObjectsOfTypeAll<GameObject>().FirstOrDefault(g=>g.CompareTag("Finish")).gameObject.SetActive(true);
GameObject.Find("System Title").gameObject.GetComponent<Text>().text = GameObject.Find("dialogueManager").GetComponent<celestialDialogueInstantiator>().systemNameCreate.GetComponent<Text>().text;
this.gameObject.GetComponent<nextSetAmount>().nextButtonCelestials(true);
AudioListener.pause = false;
setAllInactive(parent.transform,true);
}
}
// Sets all inactive if value = true
public void setAllInactive (Transform transform, bool value)
{
foreach (Transform child in transform)
{
if(value == true)
{
child.gameObject.SetActive(!value);
}
}
}
}
audioManagerCreate
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Audio;
public class audioManagerCreate : MonoBehaviour {
public AudioMixer systemMixer;
public Slider slider;
// Use this for initialization
void Start ()
{
// Find amount of celestials in scene
// For each celestial, assign corresponding audio mixer group based on celestialID/i (essentially the same value)
for(int i = 0; i < slider.value; i++)
{
GameObject celestialObject = GameObject.Find("celestialObject"+i).gameObject;
string masterMix = "Master";
celestialObject.GetComponent<AudioSource>().outputAudioMixerGroup = systemMixer.FindMatchingGroups(masterMix)[i+1];
}
}
}
I'm not the best at troubleshooting, but I assume that the problem exists because it cannot find the gameObject that GameObject.Find() is pointing to. It works completely fine in Unity and finds the objects without fault.
The only constant that I can see is that I'm trying to find an object based on its name + i where i is the for-int loop ID. I need to do this because its looking for objects that don't exist until they're are instantiated, and whose names are based on their ID from the for-int loop in their instantiation script.
I faced a very similar problem and it was driving me crazy, since there was no sense on the fact that GameObject.Find was working pretty well on Simulator, but returning a NullReferenceException on iOS build. I had tried a lot of things and I had no success at all...
Then, I got an insight... the problem wasn't GameObject.Find method itself and I explain you why:
When we are about to generate a build in Build Settings, we need to include the Scenes we want to add to the build. Look at the picture below:
That is, SpaceScene scene was being executed on the code, but it wasn't included in the build... so its objects had not been loaded (of course). That's why GameObject.Find was returning null.
My solution was to include the scene SpaceScene in the build and everything ran as it was supposed to be.
As the center node of a gluon view I have a scrollpane which contains several textfields in a vbox. When one of these textfields becomes the focusowner and the keyboard shows up, the textfield doesn't get repositioned according to the layout of the keyboard, so it is left covered by the keyboard.
I tried putting
android:windowSoftInputMode="adjustResize"
in the AndroidManifest, but without any success.
As a workaround I translate the y-coordinates of the covered textfield to the visible area. When you press the android back button to hide the keyboard, the textfields position will be reset to its original state. The issue I'm getting here is that I don't get an event for the android back button, no matter where I add the listener:
view.addEventFilter(MobileEvent.BACK_BUTTON_PRESSED, evt -> eventFilter);
MobileApplication.getInstance().getGlassPane().addEventFilter(MobileEvent.BACK_BUTTON_PRESSED, evt -> eventFilter);
Is there any possibility to handle the positioning of a node under the keyboard, or to get a reference to the keyboard itself?
Only layers get the MobileEvent.BACK_BUTTON_PRESSED event. One solution is to go native and use the Android API.
This is the solution I could come up with so far:
public class PositionAdjuster {
public static void main(String[] args) { launch(args); }
private static final float SCALE = FXActivity.getInstance().getResources().getDisplayMetrics().density;
private Node nodeToAdjust;
private ObservableValue<Node> focusOwner;
private ViewGroup viewGroup;
private Rect currentBounds;
private DoubleProperty height;
private OnGlobalLayoutListener layoutListener;
public PositionAdjuster(Node nodeToAdjust, ObservableValue<Node> focusOwner) {
this.nodeToAdjust = nodeToAdjust;
this.focusOwner = focusOwner;
initLayoutListener();
}
private void initLayoutListener() {
double screenHeight = MobileApplication.getInstance().getScreenHeight();
height = new SimpleDoubleProperty(screenHeight);
height.addListener((ov, n, n1) -> onHeightChanged(n, n1));
layoutListener = () -> height.set(getCurrentHeigt());
viewGroup = FXActivity.getViewGroup();
viewGroup.getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
currentBounds = new Rect();
}
private float getCurrentHeigt() {
viewGroup.getRootView().getWindowVisibleDisplayFrame(currentBounds);
return currentBounds.height() / SCALE;
}
private void onHeightChanged(Number oldValue, Number newValue) {
double heightDelta = newValue.doubleValue() - oldValue.doubleValue();
if (heightDelta < 0) {
double maxY = getBoundsInScene(nodeToAdjust)).getMaxY();
double currentMaxY = heightDelta + maxY;
double result = currentMaxY- getBoundsInScene(focuseOwner.getValue()).getMaxY();
if (result < 0) {
nodeToAdjust.setTranslateY(result);
}
} else if (heightDelta > 0) {
nodeToAdjust.setTranslateY(0);
}
}
private Bounds getBoundsInScene(Node node) {
return node.localToScene(node.getBoundsInLocal());
}
public void removeListener() {
viewGroup.getViewTreeObserver().removeOnGlobalLayoutListener(layoutListener);
}
}
EDIT:
I think this is a more straightforward approach. The previous version was dependent on the maxY of noteToAdjust to be equal to the height of the screen, not taking into account e.g. the presence of a bottomBar. Now the maxY position of the focusedNode is validated against the visible screen height, and the difference is used to reposition its parent.
public AndroidPositionAdjuster(Node parent, ObservableValue<Node> focusOwner) {
this.parent = parent;
this.focusOwner = focusOwner;
initLayoutListener();
}
private void onHeightChanged(Number oldHeight, Number newHeight) {
double heightDelta = newHeight.doubleValue() - oldHeight.doubleValue();
if (heightDelta < 0) {
double maxY = newHeight.doubleValue();
double focusedNodeY = getBoundsInScene(focusOwner.getValue()).getMaxY();
double result = maxY - focusedNodeY;
if (result < 0) {
parent.setTranslateY(result);
}
} else if (heightDelta > 0) {
parent.setTranslateY(0);
}
}
I get this error just once in a while when libgdx ui renders:
09-25 17:50:26.779 31171-32670/se.company.app.android E/AndroidRuntime﹕ FATAL EXCEPTION: GLThread 1126
Process: se.company.app.android, PID: 31171
java.lang.IndexOutOfBoundsException: index can't be >= size: 36 >= 36
at com.badlogic.gdx.utils.FloatArray.get(FloatArray.java:104)
at com.badlogic.gdx.scenes.scene2d.ui.TextField.calculateOffsets(TextField.java:214)
at com.badlogic.gdx.scenes.scene2d.ui.TextArea.calculateOffsets(TextArea.java:266)
at com.badlogic.gdx.scenes.scene2d.ui.TextField.draw(TextField.java:294)
at com.badlogic.gdx.scenes.scene2d.Group.drawChildren(Group.java:123)
at com.badlogic.gdx.scenes.scene2d.Group.draw(Group.java:57)
at com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup.draw(WidgetGroup.java:154)
at com.badlogic.gdx.scenes.scene2d.ui.Table.draw(Table.java:117)
at com.badlogic.gdx.scenes.scene2d.Group.drawChildren(Group.java:110)
at com.badlogic.gdx.scenes.scene2d.Group.draw(Group.java:57)
at com.badlogic.gdx.scenes.scene2d.Stage.draw(Stage.java:128)
at se.company.app.screens.AbstractScreen.render(AbstractScreen.java:36)
at se.company.app.screens.InstructionsScreen.render(InstructionsScreen.java:80)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:422)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1522)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1239)
09-25 17:50:30.823 31171-31171/se.company.app.android E/AndroidGraphics﹕ waiting for pause synchronization took too long; assuming deadlock and killing
09-25 17:50:30.833 31171-31171/se.company.app.android I/Process﹕ Sending signal. PID: 31171 SIG: 9
I can't figure out what it is about. Threading issue? But what? When I set text I do it with Gdx.app.postRunnable().
I have classes:
public class InstructionsScreen extends AbstractScreen {
private InputProcessor inputProcessor = new InputAdapter() {
#Override
public boolean keyDown(int keycode) {
if ((keycode == Input.Keys.ESCAPE) || (keycode == Input.Keys.BACK) ) {
game.setScreen(new BeginGameOptionsScreen(game, resources));
}
return false;
}
};
private Table table;
private ScrollPane resultsTextAreaScrollPane;
private TextArea resultsTextArea;
private TextArea textArea;
private float maxX,maxY,maxZ;
private Sound sound;
private long timer=0;
public InstructionsScreen(GameClass game, Resources resources) {
super(game, resources);
}
#Override
public void resize(int width, int height) {
addInputProcessor(inputProcessor);
table = new Table();
table.setFillParent(true);
stage.addActor(table);
TextArea resultsTextAreaBool;
resultsTextAreaBool = new TextArea("", resources.getSkin());
resultsTextAreaBool.setDisabled(true);
resultsTextAreaBool.setText(String.valueOf(Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer)));
table.add(resultsTextAreaBool).width(GraphicUtils.widthOfScreen(90)).height(GraphicUtils.heightOfScreen(20)).pad(GraphicUtils.onePercentHeight, GraphicUtils.onePercentWidth, GraphicUtils.onePercentHeight, GraphicUtils.onePercentWidth);
table.row();
resultsTextArea = new TextArea("", resources.getSkin());
resultsTextArea.setDisabled(true);
resultsTextArea.setText("");
table.add(resultsTextArea).width(GraphicUtils.widthOfScreen(90)).height(GraphicUtils.heightOfScreen(40)).pad(GraphicUtils.onePercentHeight, GraphicUtils.onePercentWidth, GraphicUtils.onePercentHeight, GraphicUtils.onePercentWidth);
table.row();
sound=resources.getRobotBlip();
}
#Override
public void render(float delta) {
super.render(delta);
float accelX = Gdx.input.getAccelerometerX();
float accelY = Gdx.input.getAccelerometerY();
float accelZ = Gdx.input.getAccelerometerZ();
if(accelX>maxX)
maxX=accelX;
if(accelY>maxY)
maxY=accelY;
if(accelZ>maxZ)
maxZ=accelZ;
if(Math.abs(maxX)>19f) {
timer++;
}
if(timer==1) {
sound.play();
}
if(timer>20) {
timer=0;
maxX=0;
}
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
resultsTextArea.setText("x=" + String.valueOf(maxX) + "\ny=" + String.valueOf(maxY) + "\nz=" + String.valueOf(maxZ));
}
});
}
}
Problem seems to arise because of newlines "\n" in String above.
I use FreeTypeFontGenerator for font creation on the fly:
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("data/fonts/anonymous-pro/Anonymous_Pro.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter freeTypeFontParameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
freeTypeFontParameter.borderColor = Color.BLACK;
freeTypeFontParameter.borderWidth = 1;
freeTypeFontParameter.size = (int)(Gdx.graphics.getWidth()/25.0f);
anonymous_pro = generator.generateFont(freeTypeFontParameter);
generator.dispose();
Which I add with:
TextField.TextFieldStyle textFieldStyle=skin.get("default", TextField.TextFieldStyle.class);
textFieldStyle.font=anonymous_pro;
skin.add("default", textFieldStyle);
And retrieve with:
resultsTextArea = new TextArea("", resources.getSkin()); //Resources is my own class
I hope you'll excuse me for bumping this old issue, especially when there's already an answer. This page is one of very few references on Google to the subject matter and I found a different solution.
In short, I had to open up the .fnt file that I was using and remove the references to glyphs 0 and 10. I know you're using FreeTypeFontGenerator, but I suspect it's generating Glyph sizes for character codes 0 and 10, too. For the folks using Hiero or another generator, you can edit the .fnt file and change the following lines:
chars count=98
char id=0 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=0 xadvance=9 page=0 chnl=0
char id=10 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=0 xadvance=0 page=0 chnl=0
char id=32 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=0 xadvance=9 page=0 chnl=0
To
chars count=96
char id=32 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=0 xadvance=9 page=0 chnl=0
Note that id=0 and id=10 are gone and the count is updated.
This GitHub issue appears to address the root of the problem: https://github.com/libgdx/libgdx/issues/4570
I would like to know how I can use this matrix in my custom GL renderer to implement pinch zoom. I keep getting an error that is telling me I cannot set an opengl.Matrix which is type float[16] with the Matrix object I am changing in my activity below. What is the correct way to pass my graphics.matrix through such that it will update my view correctly? As a workaround I am passing the newDist value to my renderer, but then every time I touch the screen with 2 fingers, it resets the eyeZ value, so I think I really need to get this matrix to work so it holds my zoom values.
#Override public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG");
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
Log.d(TAG, "oldDist=" + oldDist);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
Log.d(TAG, "mode=ZOOM");
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
Log.d(TAG, "mode=NONE");
break;
case MotionEvent.ACTION_MOVE:
if (mode == ZOOM) {
final float newDist = spacing(event);
Log.d(TAG, "newDist=" + newDist);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
mGLSurfaceView.queueEvent(new Runnable() {
#Override
public void run() {
mGLSurfaceView.setMyMatrix(newDist);
Log.d(TAG, "runnable exists");
}
});
}
}
break;
}
return true; // indicate event was handled
}