Project

General

Profile

Download (29.3 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / main / ObjectControl.java @ 092e257b

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.main;
11

    
12
import static org.distorted.objectlib.helpers.OperatingSystemInterface.*;
13

    
14
import org.distorted.library.main.QuatHelper;
15
import org.distorted.library.type.Static4D;
16

    
17
import org.distorted.objectlib.effects.BaseEffect;
18
import org.distorted.objectlib.helpers.BlockController;
19
import org.distorted.objectlib.helpers.MovesFinished;
20
import org.distorted.objectlib.helpers.ObjectLibInterface;
21
import org.distorted.objectlib.helpers.OperatingSystemInterface;
22
import org.distorted.objectlib.touchcontrol.TouchControl;
23
import org.distorted.objectlib.touchcontrol.TouchControlShapeChanging;
24

    
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

    
27
public class ObjectControl
28
{
29
    public static final int MAX_MOVING_PARTS = 242; // Gigaminx
30
    public static final int MAX_QUATS = 60;         // Gigaminx: 60 quats group.
31

    
32
    public static final int NUM_SPEED_PROBES = 10;
33

    
34
    public static final int MODE_ROTATE  = 0;
35
    public static final int MODE_DRAG    = 1;
36
    public static final int MODE_REPLACE = 2;
37
    public static final int MODE_NOTHING = 3;
38

    
39
    // Moving the finger from the middle of the vertical screen to the right edge will rotate a
40
    // given face by SWIPING_SENSITIVITY/2 degrees.
41
    public final static int SWIPING_SENSITIVITY  = 240;
42
    // Moving the finger by 0.3 of an inch will start a Rotation.
43
    public final static float ROTATION_SENSITIVITY = 0.3f;
44

    
45
    private final Static4D CAMERA_POINT = new Static4D(0, 0, 0, 0);
46

    
47
    private final ObjectLibInterface mInterface;
48
    private final OperatingSystemInterface mOS;
49
    private final ObjectPreRender mPreRender;
50
    private TouchControl mTouchControl;
51
    private TwistyObjectNode mObjectNode;
52
    private boolean mDragging, mBeginningRotation, mContinuingRotation;
53
    private int mScreenWidth, mScreenHeight, mScalingSize;
54
    private float mMoveX, mMoveY;
55
    private int mLastMode;
56

    
57
    private float mRotAngle, mInitDistance;
58
    private float mStartRotX, mStartRotY;
59
    private float mRotationFactor;
60
    private int mCurrentAxis, mCurrentRow;
61
    private float mCurrentAngle, mAvgRotSpeed;
62
    private final float[] mLastA;
63
    private final long[] mLastT;
64
    private int mFirstIndex, mLastIndex;
65
    private final int mDensity;
66

    
67
    private float mX1, mY1, mX2, mY2, mX, mY;
68
    private final boolean mIsAutomatic;
69

    
70
    private boolean mIsLocked, mRemLocked;
71
    private final int[] mBuffer;
72
    private final float[] mAxis;
73
    private int mMeshState, mIconMode;
74
    private boolean mRotateOnCreation;
75
    private final Static4D mQuat,mTemp;
76
    private boolean mRotAxisIsNormal;
77
    private final float[] mNormalTouchPoint;
78
    private float mNormalRotAngle;
79

    
80
///////////////////////////////////////////////////////////////////////////////////////////////////
81

    
82
    private void addSpeedProbe(float angle)
83
      {
84
      long currTime = System.currentTimeMillis();
85
      boolean theSame = mLastIndex==mFirstIndex;
86

    
87
      mLastIndex++;
88
      if( mLastIndex>=NUM_SPEED_PROBES ) mLastIndex=0;
89

    
90
      mLastT[mLastIndex] = currTime;
91
      mLastA[mLastIndex] = angle;
92

    
93
      if( mLastIndex==mFirstIndex)
94
        {
95
        mFirstIndex++;
96
        if( mFirstIndex>=NUM_SPEED_PROBES ) mFirstIndex=0;
97
        }
98

    
99
      if( theSame )
100
        {
101
        mLastT[mFirstIndex] = currTime;
102
        mLastA[mFirstIndex] = angle;
103
        }
104
      }
105

    
106
///////////////////////////////////////////////////////////////////////////////////////////////////
107

    
108
    private void computeCurrentSpeedInInchesPerSecond()
109
      {
110
      long timeDiff = mLastT[mLastIndex]-mLastT[mFirstIndex];
111
      float sum = 0;
112
      for(int i=mFirstIndex; i<=mLastIndex; i++) sum += mLastA[i];
113

    
114
      mLastIndex = 0;
115
      mFirstIndex= 0;
116

    
117
      mAvgRotSpeed = timeDiff>0 ? sum/timeDiff : 0;
118
      if( mAvgRotSpeed<0 ) mAvgRotSpeed = -mAvgRotSpeed;
119
      }
120

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

    
123
    private float retFingerDragDistanceInInches(float xd, float yd)
124
      {
125
      float xDist = mScreenWidth*xd;
126
      float yDist = mScreenHeight*yd;
127
      float distInPixels = (float)Math.sqrt(xDist*xDist + yDist*yDist);
128

    
129
      return distInPixels/mDensity;
130
      }
131

    
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133

    
134
    private void replaceMode(boolean down)
135
      {
136
      mBeginningRotation= false;
137

    
138
      if( down )
139
        {
140
        int cubit = mTouchControl.getTouchedCubit();
141
        int face  = mTouchControl.getTouchedCubitFace();
142
        mInterface.onReplaceModeDown(cubit,face);
143
        }
144
      }
145

    
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147

    
148
    private void setUpDragOrRotate(boolean down, float x, float y)
149
      {
150
      if( mLastMode==MODE_DRAG )
151
        {
152
        mDragging           = true;
153
        mBeginningRotation  = false;
154
        mContinuingRotation = false;
155
        }
156
      else
157
        {
158
        CAMERA_POINT.set2( mObjectNode.getCameraDist() );
159
        Static4D touchPoint = new Static4D(x, y, 0, 0);
160
        Static4D rotatedTouchPoint= QuatHelper.rotateVectorByInvertedQuat(touchPoint, mQuat);
161
        Static4D rotatedCamera= QuatHelper.rotateVectorByInvertedQuat(CAMERA_POINT, mQuat);
162

    
163
        if( mTouchControl!=null && mTouchControl.objectTouched(rotatedTouchPoint,rotatedCamera) )
164
          {
165
          mDragging           = false;
166
          mContinuingRotation = false;
167

    
168
               if( mLastMode==MODE_ROTATE  ) mBeginningRotation = !mPreRender.isRotationBlocked();
169
          else if( mLastMode==MODE_REPLACE ) replaceMode(down);
170
          }
171
        else
172
          {
173
          mDragging           = (!mIsLocked || mIsAutomatic);
174
          mBeginningRotation  = false;
175
          mContinuingRotation = false;
176
          if( !mDragging ) mInterface.failedToDrag();
177
          }
178
        }
179
      }
180

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

    
183
    private void drag(float x, float y)
184
      {
185
      if( mOS.isFirstPressed() && mOS.isSecondPressed() )
186
        {
187
        float x2 = (mX2 - mScreenWidth*0.5f)/ mScalingSize;
188
        float y2 = (mScreenHeight*0.5f - mY2)/ mScalingSize;
189

    
190
        float angleNow = getAngle(x,y,x2,y2);
191
        float angleDiff = angleNow-mRotAngle;
192
        float sinA =-(float)Math.sin(angleDiff);
193
        float cosA = (float)Math.cos(angleDiff);
194

    
195
        Static4D dragQuat = QuatHelper.quatMultiply(new Static4D(0,0,sinA,cosA), mQuat);
196
        mTemp.set(dragQuat);
197

    
198
        mRotAngle = angleNow;
199

    
200
        float distNow  = (float)Math.sqrt( (x-x2)*(x-x2) + (y-y2)*(y-y2) );
201
        float distQuot = mInitDistance<0 ? 1.0f : distNow/ mInitDistance;
202
        mInitDistance = distNow;
203
        TwistyObject object = mPreRender.getObject();
204
        if( object!=null )
205
          {
206
          object.setObjectRatio(distQuot, mScalingSize );
207
          float ratio = object.getObjectRatio();
208
          if( mLastMode==MODE_REPLACE ) mTouchControl.setObjectRatio(ratio);
209
          }
210
        }
211
      else
212
        {
213
        Static4D dragQuat = QuatHelper.quatMultiply(QuatHelper.quatFromDrag(mX-x,y-mY), mQuat);
214
        mTemp.set(dragQuat);
215
        }
216

    
217
      mPreRender.setQuatOnNextRender();
218
      mX = x;
219
      mY = y;
220
      }
221

    
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223

    
224
    private void finishRotation()
225
      {
226
      TwistyObject object = mPreRender.getObject();
227
      int[][] angles = object.getBasicAngles();
228

    
229
      if( mCurrentAxis<angles.length && mCurrentRow<angles[mCurrentAxis].length )
230
        {
231
        computeCurrentSpeedInInchesPerSecond();
232
        int basic = angles[mCurrentAxis][mCurrentRow];
233
        int angle = object.computeNearestAngle(basic,mCurrentAngle, mAvgRotSpeed);
234
        mPreRender.finishRotation(angle);
235
        mPreRender.rememberMove(mCurrentAxis,mCurrentRow,angle);
236

    
237
        if( angle!=0 )
238
          {
239
          int realAngle = (angle*basic)/360;
240
          mInterface.onFinishRotation(mCurrentAxis,mCurrentRow,realAngle);
241
          }
242

    
243
        mContinuingRotation = false;
244
        mBeginningRotation  = false;
245
        mDragging           = true;
246
        }
247
      }
248

    
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250

    
251
    private void continueRotation(float x, float y)
252
      {
253
      if( !mRotAxisIsNormal )
254
        {
255
        float dx = x-mStartRotX;
256
        float dy = y-mStartRotY;
257
        float alpha = dx*mAxis[0] + dy*mAxis[1];
258
        float x2 = dx - alpha*mAxis[0];
259
        float y2 = dy - alpha*mAxis[1];
260

    
261
        float len = (float)Math.sqrt(x2*x2 + y2*y2);
262

    
263
        // we have the length of 1D vector 'angle', now the direction:
264
        float tmp = mAxis[1]==0 ? -mAxis[0]*y2 : mAxis[1]*x2;
265

    
266
        float angle = (tmp>0 ? 1:-1)*len*mRotationFactor;
267
        mCurrentAngle = SWIPING_SENSITIVITY*angle;
268
        mPreRender.getObject().continueRotation(mCurrentAngle);
269
        addSpeedProbe(mCurrentAngle);
270
        }
271
      else
272
        {
273
        float rotAngle = computeNormalRotAngle(mNormalTouchPoint[0]-x,mNormalTouchPoint[1]-y);
274
        mCurrentAngle = mNormalRotAngle - rotAngle;
275
        mPreRender.getObject().continueRotation(mCurrentAngle);
276
        addSpeedProbe(mCurrentAngle);
277
        }
278
      }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281

    
282
    private void correctRotationAxis()
283
      {
284
      if( mAxis[0]==0 && mAxis[1]==0 )
285
        {
286
        mRotAxisIsNormal = true;
287

    
288
        // 0. get face center in object space
289
        // 1. multiply it by mQuat
290
        // 2. multiply if by mObjectRatio. Let the result be (x,y,z)
291
        // 3. let D be CAMERA_POINT.Z
292
        // 4. then compute the point on the screen (X,Y) the face center maps to:
293
        //    (X,Y) = (Ax,Ay) where A = D/(D-z)
294

    
295
        float[] faceCenter = mTouchControl.getTouchedPuzzleCenter();
296
        float D = CAMERA_POINT.get2();
297
        float[] rotated = new float[4];
298
        QuatHelper.rotateVectorByQuat(rotated, faceCenter[0],faceCenter[1],faceCenter[2],faceCenter[3],mQuat);
299
        TwistyObject object = getObject();
300
        float ratio = object.getObjectRatio();
301

    
302
        float x = rotated[0] * ratio;
303
        float y = rotated[1] * ratio;
304
        float z = rotated[2] * ratio;
305

    
306
        float A = D / (D-z);
307
        mNormalTouchPoint[0] = A*x;
308
        mNormalTouchPoint[1] = A*y;
309
        }
310
      else
311
        {
312
        mRotAxisIsNormal = false;
313
        }
314
      }
315

    
316
///////////////////////////////////////////////////////////////////////////////////////////////////
317
// in degrees
318

    
319
    private float computeNormalRotAngle(float vx, float vy)
320
      {
321
      return (float)((180*Math.atan2(vy,vx))/Math.PI);
322
      }
323

    
324
///////////////////////////////////////////////////////////////////////////////////////////////////
325

    
326
    private void beginRotation(float x, float y)
327
      {
328
      mStartRotX = x;
329
      mStartRotY = y;
330

    
331
      TwistyObject object = mPreRender.getObject();
332
      int[] numLayers = object.getNumLayers();
333
      Static4D touchPoint = new Static4D(x, y, 0, 0);
334
      Static4D rotatedTouchPoint= QuatHelper.rotateVectorByInvertedQuat(touchPoint, mQuat);
335

    
336
      mTouchControl.newRotation(mBuffer,rotatedTouchPoint,mQuat);
337

    
338
      mCurrentAxis = mBuffer[0];
339
      mCurrentRow  = mBuffer[1];
340

    
341
      mTouchControl.getCastedRotAxis(mAxis,mQuat,mCurrentAxis);
342
      correctRotationAxis();
343
      mRotationFactor = mTouchControl.returnRotationFactor(numLayers,mCurrentRow);
344
      if( mRotAxisIsNormal ) mNormalRotAngle = computeNormalRotAngle(mNormalTouchPoint[0]-x,mNormalTouchPoint[1]-y);
345

    
346
      if( object.beginNewRotation( mCurrentAxis, mCurrentRow ) )
347
        {
348
        mInterface.onBeginRotation();
349
        addSpeedProbe(0);
350
        mBeginningRotation = false;
351
        mContinuingRotation= true;
352
        }
353
      }
354

    
355
///////////////////////////////////////////////////////////////////////////////////////////////////
356

    
357
    private float getAngle(float x1, float y1, float x2, float y2)
358
      {
359
      return (float) Math.atan2(y1-y2, x1-x2);
360
      }
361

    
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363

    
364
    private void prepareDown()
365
      {
366
      mOS.pressFirst();
367
      mOS.unpressSecond();
368

    
369
      mX1 = mOS.getFirstX() - mMoveX;
370
      mY1 = mOS.getFirstY() + mMoveY;
371
      }
372

    
373
///////////////////////////////////////////////////////////////////////////////////////////////////
374

    
375
    private void prepareMove()
376
      {
377
      int index1 = mOS.getFirstPointerIndex();
378

    
379
      if( index1>=0 )
380
        {
381
        mX1 = mOS.getX(index1) - mMoveX;
382
        mY1 = mOS.getY(index1) + mMoveY;
383
        }
384

    
385
      int index2 = mOS.getSecondPointerIndex();
386

    
387
      if( index2>=0 )
388
        {
389
        mX2 = mOS.getX(index2) - mMoveX;
390
        mY2 = mOS.getY(index2) + mMoveY;
391
        }
392
      }
393

    
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395

    
396
    private void prepareUp()
397
      {
398
      mOS.unpressFirst();
399
      mOS.unpressSecond();
400
      }
401

    
402
///////////////////////////////////////////////////////////////////////////////////////////////////
403

    
404
    private void prepareDown2()
405
      {
406
      if( !mOS.isFirstPressed() )
407
        {
408
        mOS.pressFirst();
409
        mX1 = mOS.getFirstX() - mMoveX;
410
        mY1 = mOS.getFirstY() + mMoveY;
411
        }
412
      else if( !mOS.isSecondPressed() )
413
        {
414
        mOS.pressSecond();
415
        mX2 = mOS.getSecondX() - mMoveX;
416
        mY2 = mOS.getSecondY() + mMoveY;
417
        }
418
      }
419

    
420
///////////////////////////////////////////////////////////////////////////////////////////////////
421

    
422
    private void prepareUp2()
423
      {
424
      mOS.upOneOfThem();
425
      }
426

    
427
///////////////////////////////////////////////////////////////////////////////////////////////////
428

    
429
    private void actionMove(float x1, float y1, float x2, float y2)
430
      {
431
      float pX,pY;
432

    
433
      if( mOS.isFirstPressed() ) { pX = x1; pY=y1; }
434
      else                       { pX = x2; pY=y2; }
435

    
436
      float x = (pX - mScreenWidth*0.5f)/ mScalingSize;
437
      float y = (mScreenHeight*0.5f -pY)/ mScalingSize;
438

    
439
      if( mBeginningRotation )
440
        {
441
        if( retFingerDragDistanceInInches(mX-x,mY-y) > ROTATION_SENSITIVITY )
442
          {
443
          beginRotation(x,y);
444
          }
445
        }
446
      else if( mContinuingRotation )
447
        {
448
        continueRotation(x,y);
449
        }
450
      else if( mDragging )
451
        {
452
        drag(x,y);
453
        }
454
      else
455
        {
456
        setUpDragOrRotate(false,x,y);
457
        }
458
      }
459

    
460
///////////////////////////////////////////////////////////////////////////////////////////////////
461

    
462
    private void actionDown(float x, float y)
463
      {
464
      mX = (x -  mScreenWidth*0.5f)/ mScalingSize;
465
      mY = (mScreenHeight*0.5f - y)/ mScalingSize;
466

    
467
      setUpDragOrRotate(true,mX,mY);
468
      }
469

    
470
///////////////////////////////////////////////////////////////////////////////////////////////////
471

    
472
    private void actionUp()
473
      {
474
      if( mContinuingRotation )
475
        {
476
        finishRotation();
477
        }
478

    
479
      if( mLastMode==MODE_REPLACE ) mInterface.onReplaceModeUp();
480
      }
481

    
482
///////////////////////////////////////////////////////////////////////////////////////////////////
483

    
484
    private void actionDown2(float x1, float y1, float x2, float y2)
485
      {
486
      mRotAngle = getAngle(x1,-y1, x2,-y2);
487
      mInitDistance = -1;
488

    
489
      mX = (x1 - mScreenWidth*0.5f )/ mScalingSize;
490
      mY = (mScreenHeight*0.5f - y1)/ mScalingSize;
491

    
492
      if( mBeginningRotation )
493
        {
494
        mContinuingRotation = false;
495
        mBeginningRotation  = false;
496
        mDragging           = true;
497
        }
498
      else if( mContinuingRotation )
499
        {
500
        finishRotation();
501
        }
502
      }
503

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

    
506
    private void actionUp2(boolean p1isUp, float x1, float y1, boolean p2isUp, float x2, float y2)
507
      {
508
      if( p1isUp )
509
        {
510
        mX = (x2 -  mScreenWidth*0.5f)/ mScalingSize;
511
        mY = (mScreenHeight*0.5f - y2)/ mScalingSize;
512
        }
513
      if( p2isUp )
514
        {
515
        mX = (x1 -  mScreenWidth*0.5f)/ mScalingSize;
516
        mY = (mScreenHeight*0.5f - y1)/ mScalingSize;
517
        }
518
      }
519

    
520
///////////////////////////////////////////////////////////////////////////////////////////////////
521

    
522
    int getScalingSize()
523
      {
524
      return mScalingSize;
525
      }
526

    
527
///////////////////////////////////////////////////////////////////////////////////////////////////
528

    
529
    void setTouchControl(TwistyObject object)
530
      {
531
      if( mLastMode!=MODE_REPLACE ) mTouchControl = object.getTouchControl();
532
      else                          mTouchControl = new TouchControlShapeChanging(object);
533
      }
534

    
535
///////////////////////////////////////////////////////////////////////////////////////////////////
536
// INTERNAL API (for AutomaticControl)
537
///////////////////////////////////////////////////////////////////////////////////////////////////
538

    
539
    public ObjectPreRender getPreRender()
540
      {
541
      return mPreRender;
542
      }
543

    
544
///////////////////////////////////////////////////////////////////////////////////////////////////
545

    
546
    public ObjectLibInterface getInterface()
547
      {
548
      return mInterface;
549
      }
550

    
551
///////////////////////////////////////////////////////////////////////////////////////////////////
552
// PUBLIC API
553
///////////////////////////////////////////////////////////////////////////////////////////////////
554

    
555
    public ObjectControl(OperatingSystemInterface os)
556
      {
557
      mIsAutomatic = false;
558

    
559
      mBuffer = new int[2];
560
      mAxis   = new float[2];
561

    
562
      mQuat= new Static4D(-0.25189602f,0.3546389f,0.009657208f,0.90038127f);
563
      mTemp= new Static4D(0,0,0,1);
564

    
565
      mAvgRotSpeed = 0.0f;
566
      mLastMode    = -1;
567
      mRotateOnCreation = false;
568

    
569
      mNormalTouchPoint = new float[2];
570

    
571
      mLastA = new float[NUM_SPEED_PROBES];
572
      mLastT = new long[NUM_SPEED_PROBES];
573
      mFirstIndex= 0;
574
      mLastIndex = 0;
575
      mMeshState =-1;
576
      mIconMode  =-1;
577

    
578
      mInterface = os.getInterface();
579
      mOS = os;
580

    
581
      mDensity = mOS.getScreenDensity();
582
      mPreRender = new ObjectPreRender(this,mInterface);
583
      }
584

    
585
///////////////////////////////////////////////////////////////////////////////////////////////////
586

    
587
    public void setRotateOnCreation(boolean rotate)
588
      {
589
      mRotateOnCreation = rotate;
590
      }
591

    
592
///////////////////////////////////////////////////////////////////////////////////////////////////
593

    
594
    public boolean getRotateOnCreation()
595
      {
596
      return mRotateOnCreation;
597
      }
598

    
599
///////////////////////////////////////////////////////////////////////////////////////////////////
600

    
601
    public TwistyObjectNode getNode()
602
      {
603
      return mObjectNode;
604
      }
605

    
606
///////////////////////////////////////////////////////////////////////////////////////////////////
607

    
608
    public void createNode(int width, int height)
609
      {
610
      if( mObjectNode==null ) mObjectNode = new TwistyObjectNode(width,height);
611
      }
612

    
613
///////////////////////////////////////////////////////////////////////////////////////////////////
614

    
615
    public void setScreenSizeAndScaling(int width, int height, int scaling)
616
      {
617
      mScreenWidth = width;
618
      mScreenHeight= height;
619
      mScalingSize = scaling;
620

    
621
      if( mObjectNode!=null ) mObjectNode.setSize(width,height);
622

    
623
      TwistyObject object = mPreRender.getObject();
624

    
625
      if( object!=null )
626
        {
627
        object.setTexture();
628
        object.setNodeSize(mScalingSize);
629
        }
630
      }
631

    
632
///////////////////////////////////////////////////////////////////////////////////////////////////
633

    
634
    public void setObjectMove(int xmove, int ymove)
635
      {
636
      mMoveX = xmove;
637
      mMoveY = ymove;
638

    
639
      mPreRender.setMove(xmove,ymove);
640
      }
641

    
642
///////////////////////////////////////////////////////////////////////////////////////////////////
643

    
644
    public void setObjectScale(float scale)
645
      {
646
      mPreRender.setScale(scale);
647
      }
648

    
649
///////////////////////////////////////////////////////////////////////////////////////////////////
650

    
651
    public void onPause()
652
      {
653
      BlockController.onPause();
654
      }
655

    
656
///////////////////////////////////////////////////////////////////////////////////////////////////
657

    
658
    public void onResume()
659
      {
660
      mOS.unpressFirst();
661
      mOS.unpressSecond();
662

    
663
      unlock();
664

    
665
      BlockController.onResume();
666
      }
667

    
668
///////////////////////////////////////////////////////////////////////////////////////////////////
669

    
670
    public void rotateNow(Static4D quat)
671
      {
672
      mTemp.set(quat);
673
      mQuat.set(mTemp);
674
      }
675

    
676
///////////////////////////////////////////////////////////////////////////////////////////////////
677

    
678
    public void scaleNow(float scale)
679
      {
680
      mPreRender.getObject().setObjectRatioNow(scale,mScalingSize );
681
      }
682

    
683
///////////////////////////////////////////////////////////////////////////////////////////////////
684

    
685
    public void setQuat()
686
      {
687
      mQuat.set(mTemp);
688
      }
689

    
690
///////////////////////////////////////////////////////////////////////////////////////////////////
691

    
692
    public Static4D getQuat()
693
      {
694
      return mQuat;
695
      }
696

    
697
///////////////////////////////////////////////////////////////////////////////////////////////////
698

    
699
    public void preRender()
700
      {
701
      mPreRender.preRender();
702
      }
703

    
704
///////////////////////////////////////////////////////////////////////////////////////////////////
705

    
706
    public void blockTouch(int place)
707
      {
708
      setLock(true);
709
      mPreRender.blockRotation(place);
710
      }
711

    
712
///////////////////////////////////////////////////////////////////////////////////////////////////
713

    
714
    public void unblockRotation()
715
      {
716
      unsetLock();
717
      mPreRender.unblockRotation();
718
      }
719

    
720
///////////////////////////////////////////////////////////////////////////////////////////////////
721

    
722
    public void unblockEverything()
723
      {
724
      mPreRender.unblockEverything();
725
      }
726

    
727
///////////////////////////////////////////////////////////////////////////////////////////////////
728

    
729
    public boolean isScramblingAndSolvingNotBlocked()
730
      {
731
      return mPreRender.isScramblingAndSolvingNotBlocked();
732
      }
733

    
734
///////////////////////////////////////////////////////////////////////////////////////////////////
735

    
736
    public void initializeObject(int[][] moves)
737
      {
738
      mPreRender.initializeObject(moves);
739
      }
740

    
741
///////////////////////////////////////////////////////////////////////////////////////////////////
742

    
743
    public void changeObject(int ordinal, int meshState, int iconMode, InitAssets asset)
744
      {
745
      mPreRender.changeObject(ordinal, meshState, iconMode, asset);
746
      }
747

    
748
///////////////////////////////////////////////////////////////////////////////////////////////////
749

    
750
    public void changeIfDifferent(int ordinal, String newName, int meshState, int iconMode, InitAssets asset)
751
      {
752
      TwistyObject object = mPreRender.getObject();
753
      String oldName = object==null ? "" : object.getShortName();
754

    
755
      if( !oldName.equals(newName) || mMeshState!=meshState || mIconMode!=iconMode )
756
        {
757
        mMeshState = meshState;
758
        mIconMode  = iconMode;
759
        mPreRender.changeObject(ordinal, meshState, iconMode, asset);
760
        }
761
      }
762

    
763
///////////////////////////////////////////////////////////////////////////////////////////////////
764
// if one or more fingers currently touch the screen, and we just pressed the 'scramble' button, do
765
// not scramble - otherwise a kind of a cheat is possible where user touches the screen, starts
766
// scrambling, then lifts the finger and the act of lifting screws the scrambling - no further
767
// scrambles take any effect!
768

    
769
    public boolean scrambleObject(int num)
770
      {
771
      if( !mBeginningRotation && !mContinuingRotation )
772
        {
773
        return mPreRender.scrambleObject(num);
774
        }
775
      return false;
776
      }
777

    
778
///////////////////////////////////////////////////////////////////////////////////////////////////
779
// ditto
780

    
781
    public boolean fastScrambleObject(int duration, int num)
782
      {
783
      if( !mBeginningRotation && !mContinuingRotation )
784
        {
785
        return mPreRender.fastScrambleObject(duration,num);
786
        }
787
      return false;
788
      }
789

    
790
///////////////////////////////////////////////////////////////////////////////////////////////////
791

    
792
    public void presentObject(int num, int duration)
793
      {
794
      mPreRender.presentObject(num,duration);
795
      }
796

    
797
///////////////////////////////////////////////////////////////////////////////////////////////////
798

    
799
    public void solveObject()
800
      {
801
      mPreRender.solveObject();
802
      }
803

    
804
///////////////////////////////////////////////////////////////////////////////////////////////////
805

    
806
    public void solveOnly()
807
      {
808
      mPreRender.solveOnly();
809
      }
810

    
811
///////////////////////////////////////////////////////////////////////////////////////////////////
812

    
813
    public void resetTextureMapsEffect(int duration)
814
      {
815
      mPreRender.resetTextureMapsEffect(duration);
816
      }
817

    
818
///////////////////////////////////////////////////////////////////////////////////////////////////
819

    
820
    public void addRotation(MovesFinished listener, int axis, int rowBitmap, int angle, int duration)
821
      {
822
      mPreRender.addRotation(listener,axis,rowBitmap,angle,duration);
823
      }
824

    
825
///////////////////////////////////////////////////////////////////////////////////////////////////
826

    
827
    public void resetAllTextureMaps()
828
      {
829
      mPreRender.resetAllTextureMaps();
830
      }
831

    
832
///////////////////////////////////////////////////////////////////////////////////////////////////
833

    
834
    public TwistyObject getObject()
835
      {
836
      return mPreRender.getObject();
837
      }
838

    
839
///////////////////////////////////////////////////////////////////////////////////////////////////
840

    
841
    public OperatingSystemInterface getOS()
842
      {
843
      return mOS;
844
      }
845

    
846
///////////////////////////////////////////////////////////////////////////////////////////////////
847

    
848
    public void savePreferences()
849
      {
850
      mPreRender.savePreferences(mOS);
851

    
852
      for( int i=0; i< BaseEffect.Type.LENGTH; i++ )
853
        {
854
        BaseEffect.Type.getType(i).savePreferences(mOS);
855
        }
856
      }
857

    
858
///////////////////////////////////////////////////////////////////////////////////////////////////
859

    
860
    public void restorePreferences()
861
      {
862
      mPreRender.restorePreferences(mOS);
863

    
864
      for (int i=0; i<BaseEffect.Type.LENGTH; i++)
865
        {
866
        BaseEffect.Type.getType(i).restorePreferences(mOS);
867
        }
868
      }
869

    
870
///////////////////////////////////////////////////////////////////////////////////////////////////
871

    
872
    public boolean retLocked()
873
      {
874
      return mIsLocked;
875
      }
876

    
877
///////////////////////////////////////////////////////////////////////////////////////////////////
878

    
879
    public void toggleLock()
880
      {
881
      mIsLocked = !mIsLocked;
882
      }
883

    
884
///////////////////////////////////////////////////////////////////////////////////////////////////
885

    
886
    public void unlock()
887
      {
888
      mIsLocked = false;
889
      }
890

    
891
///////////////////////////////////////////////////////////////////////////////////////////////////
892

    
893
    public void setLock(boolean value)
894
      {
895
      mRemLocked = mIsLocked;
896
      mIsLocked = value;
897
      }
898

    
899
///////////////////////////////////////////////////////////////////////////////////////////////////
900

    
901
    public void unsetLock()
902
      {
903
      mIsLocked = mRemLocked;
904
      }
905

    
906
///////////////////////////////////////////////////////////////////////////////////////////////////
907

    
908
    public void setTextureMap(int cubit, int face, int newColor)
909
      {
910
      mPreRender.setTextureMap(cubit,face,newColor);
911
      }
912

    
913
///////////////////////////////////////////////////////////////////////////////////////////////////
914

    
915
    public boolean onTouchEvent(int mode)
916
      {
917
      if( mode!=MODE_NOTHING )
918
        {
919
        if( mObjectNode==null ) return true;
920

    
921
        if( mode!=mLastMode )
922
          {
923
          TwistyObject object = getObject();
924

    
925
          if( object!=null )
926
            {
927
            mLastMode = mode;
928
            setTouchControl(object);
929
            }
930
          else return true;
931
          }
932

    
933
        int action = mOS.getAction();
934

    
935
        switch(action)
936
          {
937
          case ACTION_DOWN_1: prepareDown();
938
                              actionDown(mX1, mY1);
939
                              break;
940
          case ACTION_MOVE  : prepareMove();
941
                              actionMove(mX1, mY1, mX2, mY2);
942
                              break;
943
          case ACTION_UP_1  : prepareUp();
944
                              actionUp();
945
                              break;
946
          case ACTION_DOWN_2: prepareDown2();
947
                              actionDown2(mX1, mY1, mX2, mY2);
948
                              break;
949
          case ACTION_UP_2  : prepareUp2();
950
                              boolean p1isUp = !mOS.isFirstPressed();
951
                              boolean p2isUp = !mOS.isSecondPressed();
952
                              actionUp2(p1isUp, mX1, mY1, p2isUp, mX2, mY2);
953
                              break;
954
          }
955
        }
956

    
957
      return true;
958
      }
959
}
960

    
(3-3/11)