Project

General

Profile

Download (24.4 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / main / RubikSurfaceView.java @ 4946b635

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.main;
21

    
22
import android.app.ActivityManager;
23
import android.content.Context;
24
import android.content.pm.ConfigurationInfo;
25
import android.opengl.GLES30;
26
import android.opengl.GLSurfaceView;
27
import android.util.AttributeSet;
28
import android.util.DisplayMetrics;
29
import android.view.MotionEvent;
30

    
31
import com.google.firebase.crashlytics.FirebaseCrashlytics;
32

    
33
import org.distorted.helpers.QuatHelper;
34
import org.distorted.library.type.Static2D;
35
import org.distorted.library.type.Static4D;
36
import org.distorted.objects.TwistyObject;
37
import org.distorted.objects.Movement;
38
import org.distorted.screens.RubikScreenReady;
39
import org.distorted.solvers.SolverMain;
40
import org.distorted.screens.ScreenList;
41
import org.distorted.screens.RubikScreenPlay;
42
import org.distorted.screens.RubikScreenSolver;
43
import org.distorted.screens.RubikScreenSolving;
44

    
45
///////////////////////////////////////////////////////////////////////////////////////////////////
46

    
47
public class RubikSurfaceView extends GLSurfaceView
48
{
49
    public static final int NUM_SPEED_PROBES = 10;
50
    public static final int INVALID_POINTER_ID = -1;
51

    
52
    public static final int MODE_ROTATE  = 0;
53
    public static final int MODE_DRAG    = 1;
54
    public static final int MODE_REPLACE = 2;
55

    
56
    // Moving the finger from the middle of the vertical screen to the right edge will rotate a
57
    // given face by SWIPING_SENSITIVITY/2 degrees.
58
    public final static int SWIPING_SENSITIVITY  = 240;
59
    // Moving the finger by 0.3 of an inch will start a Rotation.
60
    public final static float ROTATION_SENSITIVITY = 0.3f;
61

    
62
    private final Static4D CAMERA_POINT = new Static4D(0, 0, 0, 0);
63

    
64
    private RubikRenderer mRenderer;
65
    private RubikPreRender mPreRender;
66
    private Movement mMovement;
67
    private boolean mDragging, mBeginningRotation, mContinuingRotation;
68
    private int mScreenWidth, mScreenHeight, mScreenMin;
69

    
70
    private float mRotAngle, mInitDistance;
71
    private float mStartRotX, mStartRotY;
72
    private float mAxisX, mAxisY;
73
    private float mRotationFactor;
74
    private int mLastCubitColor, mLastCubitFace, mLastCubit;
75
    private int mCurrentAxis, mCurrentRow;
76
    private float mCurrentAngle, mCurrRotSpeed;
77
    private float[] mLastX;
78
    private float[] mLastY;
79
    private long[] mLastT;
80
    private int mFirstIndex, mLastIndex;
81
    private int mDensity;
82

    
83
    private int mPointer1, mPointer2;
84
    private float mX1, mY1, mX2, mY2, mX, mY;
85
    private boolean mIsAutomatic;
86

    
87
    private static final Static4D mQuat= new Static4D(-0.25189602f,0.3546389f,0.009657208f,0.90038127f);
88
    private static final Static4D mTemp= new Static4D(0,0,0,1);
89

    
90
///////////////////////////////////////////////////////////////////////////////////////////////////
91

    
92
    void setScreenSize(int width, int height)
93
      {
94
      mScreenWidth = width;
95
      mScreenHeight= height;
96

    
97
      mScreenMin = Math.min(width, height);
98
      }
99

    
100
///////////////////////////////////////////////////////////////////////////////////////////////////
101

    
102
    boolean isVertical()
103
      {
104
      return mScreenHeight>mScreenWidth;
105
      }
106

    
107
///////////////////////////////////////////////////////////////////////////////////////////////////
108

    
109
    RubikRenderer getRenderer()
110
      {
111
      return mRenderer;
112
      }
113

    
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115

    
116
    RubikPreRender getPreRender()
117
      {
118
      return mPreRender;
119
      }
120

    
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122

    
123
    void setQuat()
124
      {
125
      mQuat.set(mTemp);
126
      }
127

    
128
///////////////////////////////////////////////////////////////////////////////////////////////////
129

    
130
    Static4D getQuat()
131
      {
132
      return mQuat;
133
      }
134

    
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

    
137
    void setMovement(Movement movement)
138
      {
139
      mMovement = movement;
140
      }
141

    
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143
// cast the 3D axis we are currently rotating along (which is already casted to the surface of the
144
// currently touched face AND converted into a 4D vector - fourth 0) to a 2D in-screen-surface axis
145

    
146
    private void computeCurrentAxis(Static4D axis)
147
      {
148
      Static4D result = QuatHelper.rotateVectorByQuat(axis, mQuat);
149

    
150
      mAxisX =result.get0();
151
      mAxisY =result.get1();
152

    
153
      float len = (float)Math.sqrt(mAxisX*mAxisX + mAxisY*mAxisY);
154
      mAxisX /= len;
155
      mAxisY /= len;
156
      }
157

    
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159

    
160
    private void addSpeedProbe(float x, float y)
161
      {
162
      long currTime = System.currentTimeMillis();
163
      boolean theSame = mLastIndex==mFirstIndex;
164

    
165
      mLastIndex++;
166
      if( mLastIndex>=NUM_SPEED_PROBES ) mLastIndex=0;
167

    
168
      mLastT[mLastIndex] = currTime;
169
      mLastX[mLastIndex] = x;
170
      mLastY[mLastIndex] = y;
171

    
172
      if( mLastIndex==mFirstIndex)
173
        {
174
        mFirstIndex++;
175
        if( mFirstIndex>=NUM_SPEED_PROBES ) mFirstIndex=0;
176
        }
177

    
178
      if( theSame )
179
        {
180
        mLastT[mFirstIndex] = currTime;
181
        mLastX[mFirstIndex] = x;
182
        mLastY[mFirstIndex] = y;
183
        }
184
      }
185

    
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

    
188
    private void computeCurrentSpeedInInchesPerSecond()
189
      {
190
      long firstTime = mLastT[mFirstIndex];
191
      long lastTime  = mLastT[mLastIndex];
192
      float fX = mLastX[mFirstIndex];
193
      float fY = mLastY[mFirstIndex];
194
      float lX = mLastX[mLastIndex];
195
      float lY = mLastY[mLastIndex];
196

    
197
      long timeDiff = lastTime-firstTime;
198

    
199
      mLastIndex = 0;
200
      mFirstIndex= 0;
201

    
202
      mCurrRotSpeed = timeDiff>0 ? 1000*retFingerDragDistanceInInches(fX,fY,lX,lY)/timeDiff : 0;
203
      }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

    
207
    private float retFingerDragDistanceInInches(float xFrom, float yFrom, float xTo, float yTo)
208
      {
209
      float xDist = mScreenWidth*(xFrom-xTo);
210
      float yDist = mScreenHeight*(yFrom-yTo);
211
      float distInPixels = (float)Math.sqrt(xDist*xDist + yDist*yDist);
212

    
213
      return distInPixels/mDensity;
214
      }
215

    
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217

    
218
    private void setUpDragOrRotate(boolean down, float x, float y)
219
      {
220
      int mode = ScreenList.getMode();
221

    
222
      if( mode==MODE_DRAG )
223
        {
224
        mDragging           = true;
225
        mBeginningRotation  = false;
226
        mContinuingRotation = false;
227
        }
228
      else
229
        {
230
        TwistyObject object = mPreRender.getObject();
231
        CAMERA_POINT.set2( object==null ? 1.21f : object.getCameraDist() );
232

    
233
        Static4D touchPoint = new Static4D(x, y, 0, 0);
234
        Static4D rotatedTouchPoint= QuatHelper.rotateVectorByInvertedQuat(touchPoint, mQuat);
235
        Static4D rotatedCamera= QuatHelper.rotateVectorByInvertedQuat(CAMERA_POINT, mQuat);
236

    
237
        if( mMovement!=null && mMovement.faceTouched(rotatedTouchPoint,rotatedCamera,object.getObjectRatio() ) )
238
          {
239
          mDragging           = false;
240
          mContinuingRotation = false;
241

    
242
          if( mode==MODE_ROTATE )
243
            {
244
            mBeginningRotation= !mPreRender.isTouchBlocked();
245
            }
246
          else if( mode==MODE_REPLACE )
247
            {
248
            mBeginningRotation= false;
249

    
250
            if( down )
251
              {
252
              RubikScreenSolver solver = (RubikScreenSolver) ScreenList.SVER.getScreenClass();
253
              mLastCubitFace = mMovement.getTouchedFace();
254
              float[] point = mMovement.getTouchedPoint3D();
255
              int color = solver.getCurrentColor();
256
              mLastCubit = object.getCubit(point);
257
              mPreRender.setTextureMap( mLastCubit, mLastCubitFace, color );
258
              mLastCubitColor = SolverMain.cubitIsLocked(object.getObjectList(), object.getNumLayers(), mLastCubit);
259
              }
260
            }
261
          }
262
        else
263
          {
264
          final RubikActivity act = (RubikActivity)getContext();
265
          final boolean locked= act.isLocked();
266
          mDragging           = (!locked || mIsAutomatic);
267
          mBeginningRotation  = false;
268
          mContinuingRotation = false;
269
          if( !mDragging ) reddenLockIcon(act);
270
          }
271
        }
272
      }
273

    
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275

    
276
    private void reddenLockIcon(RubikActivity act)
277
      {
278
      ScreenList curr = ScreenList.getCurrentScreen();
279

    
280
      if( curr==ScreenList.PLAY )
281
        {
282
        RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
283
        play.reddenLock(act);
284
        }
285
      else if( curr==ScreenList.READ )
286
        {
287
        RubikScreenReady read = (RubikScreenReady) ScreenList.READ.getScreenClass();
288
        read.reddenLock(act);
289
        }
290
      else if( curr==ScreenList.SOLV )
291
        {
292
        RubikScreenSolving solv = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
293
        solv.reddenLock(act);
294
        }
295
      }
296

    
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298

    
299
    private void drag(float x, float y)
300
      {
301
      if( mPointer1!=INVALID_POINTER_ID && mPointer2!=INVALID_POINTER_ID)
302
        {
303
        float x2 = (mX2 - mScreenWidth*0.5f)/mScreenMin;
304
        float y2 = (mScreenHeight*0.5f - mY2)/mScreenMin;
305

    
306
        float angleNow = getAngle(x,y,x2,y2);
307
        float angleDiff = angleNow-mRotAngle;
308
        float sinA =-(float)Math.sin(angleDiff);
309
        float cosA = (float)Math.cos(angleDiff);
310

    
311
        Static4D dragQuat = QuatHelper.quatMultiply(new Static4D(0,0,sinA,cosA), mQuat);
312
        mTemp.set(dragQuat);
313

    
314
        mRotAngle = angleNow;
315

    
316
        float distNow  = (float)Math.sqrt( (x-x2)*(x-x2) + (y-y2)*(y-y2) );
317
        float distQuot = mInitDistance<0 ? 1.0f : distNow/ mInitDistance;
318
        mInitDistance = distNow;
319
        TwistyObject object = mPreRender.getObject();
320
        if( object!=null ) object.setObjectRatio(distQuot);
321
        }
322
      else
323
        {
324
        Static4D dragQuat = QuatHelper.quatMultiply(QuatHelper.quatFromDrag(mX-x,y-mY), mQuat);
325
        mTemp.set(dragQuat);
326
        }
327

    
328
      mPreRender.setQuatOnNextRender();
329
      mX = x;
330
      mY = y;
331
      }
332

    
333
///////////////////////////////////////////////////////////////////////////////////////////////////
334

    
335
    private void finishRotation()
336
      {
337
      computeCurrentSpeedInInchesPerSecond();
338
      int angle = mPreRender.getObject().computeNearestAngle(mCurrentAxis,mCurrentAngle, mCurrRotSpeed);
339
      mPreRender.finishRotation(angle);
340
      mPreRender.rememberMove(mCurrentAxis,mCurrentRow,angle);
341

    
342
      if( angle!=0 )
343
        {
344
        if( ScreenList.getCurrentScreen()== ScreenList.SOLV )
345
          {
346
          RubikActivity act = (RubikActivity)getContext();
347
          RubikScreenSolving solving = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
348
          solving.addMove(act, mCurrentAxis, mCurrentRow, angle);
349
          }
350
        if( ScreenList.getCurrentScreen()== ScreenList.PLAY )
351
          {
352
          RubikActivity act = (RubikActivity)getContext();
353
          RubikScreenPlay play = (RubikScreenPlay) ScreenList.PLAY.getScreenClass();
354
          play.addMove(act, mCurrentAxis, mCurrentRow, angle);
355
          }
356
        }
357

    
358
      mContinuingRotation = false;
359
      mBeginningRotation  = false;
360
      mDragging           = true;
361
      }
362

    
363
///////////////////////////////////////////////////////////////////////////////////////////////////
364

    
365
    private void continueRotation(float x, float y)
366
      {
367
      float dx = x-mStartRotX;
368
      float dy = y-mStartRotY;
369
      float alpha = dx*mAxisX + dy*mAxisY;
370
      float x2 = dx - alpha*mAxisX;
371
      float y2 = dy - alpha*mAxisY;
372

    
373
      float len = (float)Math.sqrt(x2*x2 + y2*y2);
374

    
375
      // we have the length of 1D vector 'angle', now the direction:
376
      float tmp = mAxisY==0 ? -mAxisX*y2 : mAxisY*x2;
377

    
378
      float angle = (tmp>0 ? 1:-1)*len*mRotationFactor;
379
      mCurrentAngle = SWIPING_SENSITIVITY*angle;
380
      mPreRender.getObject().continueRotation(mCurrentAngle);
381

    
382
      addSpeedProbe(x2,y2);
383
      }
384

    
385
///////////////////////////////////////////////////////////////////////////////////////////////////
386

    
387
    private void beginRotation(float x, float y)
388
      {
389
      mStartRotX = x;
390
      mStartRotY = y;
391

    
392
      TwistyObject object = mPreRender.getObject();
393
      int numLayers = object.getNumLayers();
394

    
395
      Static4D touchPoint2 = new Static4D(x, y, 0, 0);
396
      Static4D rotatedTouchPoint2= QuatHelper.rotateVectorByInvertedQuat(touchPoint2, mQuat);
397
      Static2D res = mMovement.newRotation(rotatedTouchPoint2,object.getObjectRatio());
398

    
399
      mCurrentAxis = (int)res.get0();
400
      mCurrentRow  = (int)res.get1();
401

    
402
      computeCurrentAxis( mMovement.getCastedRotAxis(mCurrentAxis) );
403
      mRotationFactor = mMovement.returnRotationFactor(numLayers,mCurrentRow);
404

    
405
      object.beginNewRotation( mCurrentAxis, mCurrentRow );
406

    
407
      if( ScreenList.getCurrentScreen()== ScreenList.READ )
408
        {
409
        RubikScreenSolving solving = (RubikScreenSolving) ScreenList.SOLV.getScreenClass();
410
        solving.resetElapsed();
411

    
412
        final RubikActivity act = (RubikActivity)getContext();
413

    
414
        act.runOnUiThread(new Runnable()
415
          {
416
          @Override
417
          public void run()
418
            {
419
            ScreenList.switchScreen( act, ScreenList.SOLV);
420
            }
421
          });
422
        }
423

    
424
      addSpeedProbe(x,y);
425

    
426
      mBeginningRotation = false;
427
      mContinuingRotation= true;
428
      }
429

    
430
///////////////////////////////////////////////////////////////////////////////////////////////////
431

    
432
    private float getAngle(float x1, float y1, float x2, float y2)
433
      {
434
      return (float) Math.atan2(y1-y2, x1-x2);
435
      }
436

    
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438

    
439
    void initialize()
440
      {
441
      mPointer1 = INVALID_POINTER_ID;
442
      mPointer2 = INVALID_POINTER_ID;
443
      }
444

    
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446

    
447
    private void prepareDown(MotionEvent event)
448
      {
449
      mPointer1 = event.getPointerId(0);
450
      mX1 = event.getX();
451
      mY1 = event.getY();
452
      mPointer2 = INVALID_POINTER_ID;
453
      }
454

    
455
///////////////////////////////////////////////////////////////////////////////////////////////////
456

    
457
    private void prepareMove(MotionEvent event)
458
      {
459
      int index1 = event.findPointerIndex(mPointer1);
460

    
461
      if( index1>=0 )
462
        {
463
        mX1 = event.getX(index1);
464
        mY1 = event.getY(index1);
465
        }
466

    
467
      int index2 = event.findPointerIndex(mPointer2);
468

    
469
      if( index2>=0 )
470
        {
471
        mX2 = event.getX(index2);
472
        mY2 = event.getY(index2);
473
        }
474
      }
475

    
476
///////////////////////////////////////////////////////////////////////////////////////////////////
477

    
478
    private void prepareUp(MotionEvent event)
479
      {
480
      mPointer1 = INVALID_POINTER_ID;
481
      mPointer2 = INVALID_POINTER_ID;
482
      }
483

    
484
///////////////////////////////////////////////////////////////////////////////////////////////////
485

    
486
    private void prepareDown2(MotionEvent event)
487
      {
488
      int index = event.getActionIndex();
489

    
490
      if( mPointer1==INVALID_POINTER_ID )
491
        {
492
        mPointer1 = event.getPointerId(index);
493
        mX1 = event.getX(index);
494
        mY1 = event.getY(index);
495
        }
496
      else if( mPointer2==INVALID_POINTER_ID )
497
        {
498
        mPointer2 = event.getPointerId(index);
499
        mX2 = event.getX(index);
500
        mY2 = event.getY(index);
501
        }
502
      }
503

    
504
///////////////////////////////////////////////////////////////////////////////////////////////////
505

    
506
    private void prepareUp2(MotionEvent event)
507
      {
508
      int index = event.getActionIndex();
509

    
510
           if( index==event.findPointerIndex(mPointer1) ) mPointer1 = INVALID_POINTER_ID;
511
      else if( index==event.findPointerIndex(mPointer2) ) mPointer2 = INVALID_POINTER_ID;
512
      }
513

    
514
///////////////////////////////////////////////////////////////////////////////////////////////////
515
// PUBLIC API
516
///////////////////////////////////////////////////////////////////////////////////////////////////
517

    
518
    public RubikSurfaceView(Context context, AttributeSet attrs)
519
      {
520
      super(context,attrs);
521

    
522
      if(!isInEditMode())
523
        {
524
        mIsAutomatic = false;
525

    
526
        mLastCubitColor = -1;
527
        mCurrRotSpeed   = 0.0f;
528

    
529
        mLastX = new float[NUM_SPEED_PROBES];
530
        mLastY = new float[NUM_SPEED_PROBES];
531
        mLastT = new long[NUM_SPEED_PROBES];
532
        mFirstIndex =0;
533
        mLastIndex  =0;
534

    
535
        mRenderer  = new RubikRenderer(this);
536
        mPreRender = new RubikPreRender(this);
537

    
538
        RubikActivity act = (RubikActivity)context;
539
        DisplayMetrics dm = new DisplayMetrics();
540
        act.getWindowManager().getDefaultDisplay().getMetrics(dm);
541

    
542
        mDensity = dm.densityDpi;
543

    
544
        final ActivityManager activityManager= (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
545

    
546
        try
547
          {
548
          final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
549
          int esVersion = configurationInfo.reqGlEsVersion>>16;
550
          setEGLContextClientVersion(esVersion);
551
          setRenderer(mRenderer);
552
          }
553
        catch(Exception ex)
554
          {
555
          act.OpenGLError();
556

    
557
          String shading = GLES30.glGetString(GLES30.GL_SHADING_LANGUAGE_VERSION);
558
          String version = GLES30.glGetString(GLES30.GL_VERSION);
559
          String vendor  = GLES30.glGetString(GLES30.GL_VENDOR);
560
          String renderer= GLES30.glGetString(GLES30.GL_RENDERER);
561

    
562
          FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
563
          crashlytics.setCustomKey("GLSL Version"  , shading );
564
          crashlytics.setCustomKey("GL version"    , version );
565
          crashlytics.setCustomKey("GL Vendor "    , vendor  );
566
          crashlytics.setCustomKey("GLSL renderer" , renderer);
567
          crashlytics.recordException(ex);
568
          }
569
        }
570
      }
571

    
572
///////////////////////////////////////////////////////////////////////////////////////////////////
573

    
574
    public void prepareDown()
575
      {
576
      mIsAutomatic = true;
577
      mPointer1 = 0;
578
      mPointer2 = INVALID_POINTER_ID;
579
      }
580

    
581
///////////////////////////////////////////////////////////////////////////////////////////////////
582

    
583
    public void prepareDown2()
584
      {
585
      mPointer2 = 0;
586
      }
587

    
588
///////////////////////////////////////////////////////////////////////////////////////////////////
589

    
590
    public void prepareMove(float x1, float y1, float x2, float y2)
591
      {
592
      mX1 = x1;
593
      mY1 = y1;
594
      mX2 = x2;
595
      mY2 = y2;
596
      }
597

    
598
///////////////////////////////////////////////////////////////////////////////////////////////////
599

    
600
    public void prepareUp()
601
      {
602
      mIsAutomatic = false;
603
      mPointer1 = INVALID_POINTER_ID;
604
      mPointer2 = INVALID_POINTER_ID;
605
      }
606

    
607
///////////////////////////////////////////////////////////////////////////////////////////////////
608

    
609
    public void actionMove(float x1, float y1, float x2, float y2)
610
      {
611
      float pX = mPointer1 != INVALID_POINTER_ID ? x1 : x2;
612
      float pY = mPointer1 != INVALID_POINTER_ID ? y1 : y2;
613

    
614
      float x = (pX - mScreenWidth*0.5f)/mScreenMin;
615
      float y = (mScreenHeight*0.5f -pY)/mScreenMin;
616

    
617
      if( mBeginningRotation )
618
        {
619
        if( retFingerDragDistanceInInches(mX,mY,x,y) > ROTATION_SENSITIVITY )
620
          {
621
          beginRotation(x,y);
622
          }
623
        }
624
      else if( mContinuingRotation )
625
        {
626
        continueRotation(x,y);
627
        }
628
      else if( mDragging )
629
        {
630
        drag(x,y);
631
        }
632
      else
633
        {
634
        setUpDragOrRotate(false,x,y);
635
        }
636
      }
637

    
638
///////////////////////////////////////////////////////////////////////////////////////////////////
639

    
640
    public void actionDown(float x, float y)
641
      {
642
      mX = (x -  mScreenWidth*0.5f)/mScreenMin;
643
      mY = (mScreenHeight*0.5f - y)/mScreenMin;
644

    
645
      setUpDragOrRotate(true,mX,mY);
646
      }
647

    
648
///////////////////////////////////////////////////////////////////////////////////////////////////
649

    
650
    public void actionUp()
651
      {
652
      if( mContinuingRotation )
653
        {
654
        finishRotation();
655
        }
656

    
657
      if( mLastCubitColor>=0 )
658
        {
659
        mPreRender.setTextureMap( mLastCubit, mLastCubitFace, mLastCubitColor );
660
        mLastCubitColor = -1;
661
        }
662
      }
663

    
664
///////////////////////////////////////////////////////////////////////////////////////////////////
665

    
666
    public void actionDown2(float x1, float y1, float x2, float y2)
667
      {
668
      mRotAngle = getAngle(x1,-y1, x2,-y2);
669
      mInitDistance = -1;
670

    
671
      mX = (x1 - mScreenWidth*0.5f )/mScreenMin;
672
      mY = (mScreenHeight*0.5f - y1)/mScreenMin;
673

    
674
      if( mBeginningRotation )
675
        {
676
        mContinuingRotation = false;
677
        mBeginningRotation  = false;
678
        mDragging           = true;
679
        }
680
      else if( mContinuingRotation )
681
        {
682
        finishRotation();
683
        }
684
      }
685

    
686
///////////////////////////////////////////////////////////////////////////////////////////////////
687

    
688
    public void actionUp2(boolean p1isUp, float x1, float y1, boolean p2isUp, float x2, float y2)
689
      {
690
      if( p1isUp )
691
        {
692
        mX = (x2 -  mScreenWidth*0.5f)/mScreenMin;
693
        mY = (mScreenHeight*0.5f - y2)/mScreenMin;
694
        }
695
      if( p2isUp )
696
        {
697
        mX = (x1 -  mScreenWidth*0.5f)/mScreenMin;
698
        mY = (mScreenHeight*0.5f - y1)/mScreenMin;
699
        }
700
      }
701

    
702
///////////////////////////////////////////////////////////////////////////////////////////////////
703

    
704
    @Override
705
    public boolean onTouchEvent(MotionEvent event)
706
      {
707
      int action = event.getActionMasked();
708

    
709
      switch(action)
710
         {
711
         case MotionEvent.ACTION_DOWN        : prepareDown(event);
712
                                               actionDown(mX1, mY1);
713
                                               break;
714
         case MotionEvent.ACTION_MOVE        : prepareMove(event);
715
                                               actionMove(mX1, mY1, mX2, mY2);
716
                                               break;
717
         case MotionEvent.ACTION_UP          : prepareUp(event);
718
                                               actionUp();
719
                                               break;
720
         case MotionEvent.ACTION_POINTER_DOWN: prepareDown2(event);
721
                                               actionDown2(mX1, mY1, mX2, mY2);
722
                                               break;
723
         case MotionEvent.ACTION_POINTER_UP  : prepareUp2(event);
724
                                               boolean p1isUp = mPointer1==INVALID_POINTER_ID;
725
                                               boolean p2isUp = mPointer2==INVALID_POINTER_ID;
726
                                               actionUp2(p1isUp, mX1, mY1, p2isUp, mX2, mY2);
727
                                               break;
728
         }
729

    
730
      return true;
731
      }
732
}
733

    
(4-4/4)