Project

General

Profile

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

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

1 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6 4c87f159 Leszek Koltunski
// 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 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10
package org.distorted.objectlib.main;
11
12 82b0cf8e Leszek Koltunski
import static org.distorted.objectlib.helpers.OperatingSystemInterface.*;
13
14 880beeea Leszek Koltunski
import org.distorted.library.main.QuatHelper;
15
import org.distorted.library.type.Static4D;
16
17 8e66157b Leszek Koltunski
import org.distorted.objectlib.effects.BaseEffect;
18 2fca02cf Leszek Koltunski
import org.distorted.objectlib.helpers.BlockController;
19 9276dced Leszek Koltunski
import org.distorted.objectlib.helpers.MovesFinished;
20 b3fff6fb Leszek Koltunski
import org.distorted.objectlib.helpers.ObjectLibInterface;
21 51c25e4e Leszek Koltunski
import org.distorted.objectlib.helpers.OperatingSystemInterface;
22 c9c71c3f Leszek Koltunski
import org.distorted.objectlib.touchcontrol.TouchControl;
23 11fa413d Leszek Koltunski
import org.distorted.objectlib.touchcontrol.TouchControlShapeChanging;
24 880beeea Leszek Koltunski
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26
27
public class ObjectControl
28
{
29 da57aa64 Leszek Koltunski
    public static final int MAX_MOVING_PARTS = 242; // Gigaminx
30
    public static final int MAX_QUATS = 60;         // Gigaminx: 60 quats group.
31
32 880beeea Leszek Koltunski
    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 611940ac Leszek Koltunski
    public static final int MODE_NOTHING = 3;
38 880beeea Leszek Koltunski
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 b3fff6fb Leszek Koltunski
    private final ObjectLibInterface mInterface;
48 51c25e4e Leszek Koltunski
    private final OperatingSystemInterface mOS;
49 880beeea Leszek Koltunski
    private final ObjectPreRender mPreRender;
50 7c546131 Leszek Koltunski
    private TouchControl mTouchControl;
51 7ba38dd4 Leszek Koltunski
    private TwistyObjectNode mObjectNode;
52 880beeea Leszek Koltunski
    private boolean mDragging, mBeginningRotation, mContinuingRotation;
53 30bd2f96 Leszek Koltunski
    private int mScreenWidth, mScreenHeight, mScalingSize;
54 72d6857c Leszek Koltunski
    private float mMoveX, mMoveY;
55 11fa413d Leszek Koltunski
    private int mLastMode;
56 880beeea Leszek Koltunski
57
    private float mRotAngle, mInitDistance;
58
    private float mStartRotX, mStartRotY;
59
    private float mRotationFactor;
60
    private int mCurrentAxis, mCurrentRow;
61 092e257b Leszek Koltunski
    private float mCurrentAngle, mAvgRotSpeed;
62
    private final float[] mLastA;
63 880beeea Leszek Koltunski
    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 046104f5 Leszek Koltunski
    private final boolean mIsAutomatic;
69 880beeea Leszek Koltunski
70 b9956428 Leszek Koltunski
    private boolean mIsLocked, mRemLocked;
71 57ef6378 Leszek Koltunski
    private final int[] mBuffer;
72
    private final float[] mAxis;
73 3bf19410 Leszek Koltunski
    private int mMeshState, mIconMode;
74 4a389a4e Leszek Koltunski
    private boolean mRotateOnCreation;
75 a76330cc Leszek Koltunski
    private final Static4D mQuat,mTemp;
76 644c217a Leszek Koltunski
    private boolean mRotAxisIsNormal;
77
    private final float[] mNormalTouchPoint;
78
    private float mNormalRotAngle;
79 880beeea Leszek Koltunski
80
///////////////////////////////////////////////////////////////////////////////////////////////////
81
82 092e257b Leszek Koltunski
    private void addSpeedProbe(float angle)
83 880beeea Leszek Koltunski
      {
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 092e257b Leszek Koltunski
      mLastA[mLastIndex] = angle;
92 880beeea Leszek Koltunski
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 092e257b Leszek Koltunski
        mLastA[mFirstIndex] = angle;
103 880beeea Leszek Koltunski
        }
104
      }
105
106
///////////////////////////////////////////////////////////////////////////////////////////////////
107
108
    private void computeCurrentSpeedInInchesPerSecond()
109
      {
110 092e257b Leszek Koltunski
      long timeDiff = mLastT[mLastIndex]-mLastT[mFirstIndex];
111
      float sum = 0;
112
      for(int i=mFirstIndex; i<=mLastIndex; i++) sum += mLastA[i];
113 880beeea Leszek Koltunski
114
      mLastIndex = 0;
115
      mFirstIndex= 0;
116
117 092e257b Leszek Koltunski
      mAvgRotSpeed = timeDiff>0 ? sum/timeDiff : 0;
118
      if( mAvgRotSpeed<0 ) mAvgRotSpeed = -mAvgRotSpeed;
119 880beeea Leszek Koltunski
      }
120
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122
123 78108318 Leszek Koltunski
    private float retFingerDragDistanceInInches(float xd, float yd)
124 880beeea Leszek Koltunski
      {
125 78108318 Leszek Koltunski
      float xDist = mScreenWidth*xd;
126
      float yDist = mScreenHeight*yd;
127 880beeea Leszek Koltunski
      float distInPixels = (float)Math.sqrt(xDist*xDist + yDist*yDist);
128
129
      return distInPixels/mDensity;
130
      }
131
132 3d093961 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
133
134 57ef6378 Leszek Koltunski
    private void replaceMode(boolean down)
135 3d093961 Leszek Koltunski
      {
136
      mBeginningRotation= false;
137
138
      if( down )
139
        {
140 11fa413d Leszek Koltunski
        int cubit = mTouchControl.getTouchedCubit();
141
        int face  = mTouchControl.getTouchedCubitFace();
142
        mInterface.onReplaceModeDown(cubit,face);
143 3d093961 Leszek Koltunski
        }
144
      }
145
146 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
147
148 11fa413d Leszek Koltunski
    private void setUpDragOrRotate(boolean down, float x, float y)
149 880beeea Leszek Koltunski
      {
150 11fa413d Leszek Koltunski
      if( mLastMode==MODE_DRAG )
151 880beeea Leszek Koltunski
        {
152
        mDragging           = true;
153
        mBeginningRotation  = false;
154
        mContinuingRotation = false;
155
        }
156
      else
157
        {
158 57ef6378 Leszek Koltunski
        CAMERA_POINT.set2( mObjectNode.getCameraDist() );
159 880beeea Leszek Koltunski
        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 57ef6378 Leszek Koltunski
        if( mTouchControl!=null && mTouchControl.objectTouched(rotatedTouchPoint,rotatedCamera) )
164 880beeea Leszek Koltunski
          {
165
          mDragging           = false;
166
          mContinuingRotation = false;
167
168 7205c655 Leszek Koltunski
               if( mLastMode==MODE_ROTATE  ) mBeginningRotation = !mPreRender.isRotationBlocked();
169 11fa413d Leszek Koltunski
          else if( mLastMode==MODE_REPLACE ) replaceMode(down);
170 880beeea Leszek Koltunski
          }
171
        else
172
          {
173 b9956428 Leszek Koltunski
          mDragging           = (!mIsLocked || mIsAutomatic);
174 880beeea Leszek Koltunski
          mBeginningRotation  = false;
175
          mContinuingRotation = false;
176 b3fff6fb Leszek Koltunski
          if( !mDragging ) mInterface.failedToDrag();
177 880beeea Leszek Koltunski
          }
178
        }
179
      }
180
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182
183
    private void drag(float x, float y)
184
      {
185 82b0cf8e Leszek Koltunski
      if( mOS.isFirstPressed() && mOS.isSecondPressed() )
186 880beeea Leszek Koltunski
        {
187 30bd2f96 Leszek Koltunski
        float x2 = (mX2 - mScreenWidth*0.5f)/ mScalingSize;
188
        float y2 = (mScreenHeight*0.5f - mY2)/ mScalingSize;
189 880beeea Leszek Koltunski
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 7c82e1c6 Leszek Koltunski
        if( object!=null )
205
          {
206 30bd2f96 Leszek Koltunski
          object.setObjectRatio(distQuot, mScalingSize );
207 7c82e1c6 Leszek Koltunski
          float ratio = object.getObjectRatio();
208
          if( mLastMode==MODE_REPLACE ) mTouchControl.setObjectRatio(ratio);
209
          }
210 880beeea Leszek Koltunski
        }
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 2df35810 Leszek Koltunski
      TwistyObject object = mPreRender.getObject();
227 beee90ab Leszek Koltunski
      int[][] angles = object.getBasicAngles();
228 880beeea Leszek Koltunski
229 d5411af4 Leszek Koltunski
      if( mCurrentAxis<angles.length && mCurrentRow<angles[mCurrentAxis].length )
230 880beeea Leszek Koltunski
        {
231 a1bcb301 Leszek Koltunski
        computeCurrentSpeedInInchesPerSecond();
232 beee90ab Leszek Koltunski
        int basic = angles[mCurrentAxis][mCurrentRow];
233 092e257b Leszek Koltunski
        int angle = object.computeNearestAngle(basic,mCurrentAngle, mAvgRotSpeed);
234 a1bcb301 Leszek Koltunski
        mPreRender.finishRotation(angle);
235
        mPreRender.rememberMove(mCurrentAxis,mCurrentRow,angle);
236
237
        if( angle!=0 )
238
          {
239 beee90ab Leszek Koltunski
          int realAngle = (angle*basic)/360;
240 a1bcb301 Leszek Koltunski
          mInterface.onFinishRotation(mCurrentAxis,mCurrentRow,realAngle);
241
          }
242 880beeea Leszek Koltunski
243 a1bcb301 Leszek Koltunski
        mContinuingRotation = false;
244
        mBeginningRotation  = false;
245
        mDragging           = true;
246
        }
247 880beeea Leszek Koltunski
      }
248
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250
251
    private void continueRotation(float x, float y)
252
      {
253 644c217a Leszek Koltunski
      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 880beeea Leszek Koltunski
261 644c217a Leszek Koltunski
        float len = (float)Math.sqrt(x2*x2 + y2*y2);
262 880beeea Leszek Koltunski
263 644c217a Leszek Koltunski
        // we have the length of 1D vector 'angle', now the direction:
264
        float tmp = mAxis[1]==0 ? -mAxis[0]*y2 : mAxis[1]*x2;
265 880beeea Leszek Koltunski
266 644c217a Leszek Koltunski
        float angle = (tmp>0 ? 1:-1)*len*mRotationFactor;
267
        mCurrentAngle = SWIPING_SENSITIVITY*angle;
268
        mPreRender.getObject().continueRotation(mCurrentAngle);
269 092e257b Leszek Koltunski
        addSpeedProbe(mCurrentAngle);
270 644c217a Leszek Koltunski
        }
271
      else
272
        {
273
        float rotAngle = computeNormalRotAngle(mNormalTouchPoint[0]-x,mNormalTouchPoint[1]-y);
274 09ff1631 Leszek Koltunski
        mCurrentAngle = mNormalRotAngle - rotAngle;
275 644c217a Leszek Koltunski
        mPreRender.getObject().continueRotation(mCurrentAngle);
276 092e257b Leszek Koltunski
        addSpeedProbe(mCurrentAngle);
277 644c217a Leszek Koltunski
        }
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 09ff1631 Leszek Koltunski
      return (float)((180*Math.atan2(vy,vx))/Math.PI);
322 880beeea Leszek Koltunski
      }
323
324
///////////////////////////////////////////////////////////////////////////////////////////////////
325
326
    private void beginRotation(float x, float y)
327
      {
328 31ed545f Leszek Koltunski
      mStartRotX = x;
329
      mStartRotY = y;
330
331 880beeea Leszek Koltunski
      TwistyObject object = mPreRender.getObject();
332 a57e6870 Leszek Koltunski
      int[] numLayers = object.getNumLayers();
333 43a4ccff Leszek Koltunski
      Static4D touchPoint = new Static4D(x, y, 0, 0);
334
      Static4D rotatedTouchPoint= QuatHelper.rotateVectorByInvertedQuat(touchPoint, mQuat);
335 880beeea Leszek Koltunski
336 31ed545f Leszek Koltunski
      mTouchControl.newRotation(mBuffer,rotatedTouchPoint,mQuat);
337 880beeea Leszek Koltunski
338 31ed545f Leszek Koltunski
      mCurrentAxis = mBuffer[0];
339
      mCurrentRow  = mBuffer[1];
340 880beeea Leszek Koltunski
341 31ed545f Leszek Koltunski
      mTouchControl.getCastedRotAxis(mAxis,mQuat,mCurrentAxis);
342 644c217a Leszek Koltunski
      correctRotationAxis();
343 31ed545f Leszek Koltunski
      mRotationFactor = mTouchControl.returnRotationFactor(numLayers,mCurrentRow);
344 644c217a Leszek Koltunski
      if( mRotAxisIsNormal ) mNormalRotAngle = computeNormalRotAngle(mNormalTouchPoint[0]-x,mNormalTouchPoint[1]-y);
345 605f319b Leszek Koltunski
346
      if( object.beginNewRotation( mCurrentAxis, mCurrentRow ) )
347
        {
348
        mInterface.onBeginRotation();
349 092e257b Leszek Koltunski
        addSpeedProbe(0);
350 605f319b Leszek Koltunski
        mBeginningRotation = false;
351
        mContinuingRotation= true;
352
        }
353 880beeea Leszek Koltunski
      }
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 82b0cf8e Leszek Koltunski
    private void prepareDown()
365 880beeea Leszek Koltunski
      {
366 82b0cf8e Leszek Koltunski
      mOS.pressFirst();
367
      mOS.unpressSecond();
368
369
      mX1 = mOS.getFirstX() - mMoveX;
370
      mY1 = mOS.getFirstY() + mMoveY;
371 880beeea Leszek Koltunski
      }
372
373
///////////////////////////////////////////////////////////////////////////////////////////////////
374
375 82b0cf8e Leszek Koltunski
    private void prepareMove()
376 880beeea Leszek Koltunski
      {
377 c0dcc0c1 Leszek Koltunski
      int index1 = mOS.getFirstPointerIndex();
378
379
      if( index1>=0 )
380 880beeea Leszek Koltunski
        {
381 c0dcc0c1 Leszek Koltunski
        mX1 = mOS.getX(index1) - mMoveX;
382
        mY1 = mOS.getY(index1) + mMoveY;
383 880beeea Leszek Koltunski
        }
384
385 c0dcc0c1 Leszek Koltunski
      int index2 = mOS.getSecondPointerIndex();
386
387
      if( index2>=0 )
388 880beeea Leszek Koltunski
        {
389 c0dcc0c1 Leszek Koltunski
        mX2 = mOS.getX(index2) - mMoveX;
390
        mY2 = mOS.getY(index2) + mMoveY;
391 880beeea Leszek Koltunski
        }
392
      }
393
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395
396 82b0cf8e Leszek Koltunski
    private void prepareUp()
397 880beeea Leszek Koltunski
      {
398 82b0cf8e Leszek Koltunski
      mOS.unpressFirst();
399
      mOS.unpressSecond();
400 880beeea Leszek Koltunski
      }
401
402
///////////////////////////////////////////////////////////////////////////////////////////////////
403
404 82b0cf8e Leszek Koltunski
    private void prepareDown2()
405 880beeea Leszek Koltunski
      {
406 82b0cf8e Leszek Koltunski
      if( !mOS.isFirstPressed() )
407 880beeea Leszek Koltunski
        {
408 82b0cf8e Leszek Koltunski
        mOS.pressFirst();
409
        mX1 = mOS.getFirstX() - mMoveX;
410
        mY1 = mOS.getFirstY() + mMoveY;
411 880beeea Leszek Koltunski
        }
412 82b0cf8e Leszek Koltunski
      else if( !mOS.isSecondPressed() )
413 880beeea Leszek Koltunski
        {
414 82b0cf8e Leszek Koltunski
        mOS.pressSecond();
415
        mX2 = mOS.getSecondX() - mMoveX;
416
        mY2 = mOS.getSecondY() + mMoveY;
417 880beeea Leszek Koltunski
        }
418
      }
419
420
///////////////////////////////////////////////////////////////////////////////////////////////////
421
422 82b0cf8e Leszek Koltunski
    private void prepareUp2()
423 880beeea Leszek Koltunski
      {
424 dfa958c7 Leszek Koltunski
      mOS.upOneOfThem();
425 880beeea Leszek Koltunski
      }
426
427
///////////////////////////////////////////////////////////////////////////////////////////////////
428
429 11fa413d Leszek Koltunski
    private void actionMove(float x1, float y1, float x2, float y2)
430 880beeea Leszek Koltunski
      {
431 82b0cf8e Leszek Koltunski
      float pX,pY;
432
433
      if( mOS.isFirstPressed() ) { pX = x1; pY=y1; }
434
      else                       { pX = x2; pY=y2; }
435 880beeea Leszek Koltunski
436 30bd2f96 Leszek Koltunski
      float x = (pX - mScreenWidth*0.5f)/ mScalingSize;
437
      float y = (mScreenHeight*0.5f -pY)/ mScalingSize;
438 880beeea Leszek Koltunski
439
      if( mBeginningRotation )
440
        {
441 78108318 Leszek Koltunski
        if( retFingerDragDistanceInInches(mX-x,mY-y) > ROTATION_SENSITIVITY )
442 880beeea Leszek Koltunski
          {
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 11fa413d Leszek Koltunski
        setUpDragOrRotate(false,x,y);
457 880beeea Leszek Koltunski
        }
458
      }
459
460
///////////////////////////////////////////////////////////////////////////////////////////////////
461
462 11fa413d Leszek Koltunski
    private void actionDown(float x, float y)
463 880beeea Leszek Koltunski
      {
464 30bd2f96 Leszek Koltunski
      mX = (x -  mScreenWidth*0.5f)/ mScalingSize;
465
      mY = (mScreenHeight*0.5f - y)/ mScalingSize;
466 880beeea Leszek Koltunski
467 11fa413d Leszek Koltunski
      setUpDragOrRotate(true,mX,mY);
468 880beeea Leszek Koltunski
      }
469
470
///////////////////////////////////////////////////////////////////////////////////////////////////
471
472
    private void actionUp()
473
      {
474
      if( mContinuingRotation )
475
        {
476
        finishRotation();
477
        }
478
479 11fa413d Leszek Koltunski
      if( mLastMode==MODE_REPLACE ) mInterface.onReplaceModeUp();
480 880beeea Leszek Koltunski
      }
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 30bd2f96 Leszek Koltunski
      mX = (x1 - mScreenWidth*0.5f )/ mScalingSize;
490
      mY = (mScreenHeight*0.5f - y1)/ mScalingSize;
491 880beeea Leszek Koltunski
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 30bd2f96 Leszek Koltunski
        mX = (x2 -  mScreenWidth*0.5f)/ mScalingSize;
511
        mY = (mScreenHeight*0.5f - y2)/ mScalingSize;
512 880beeea Leszek Koltunski
        }
513
      if( p2isUp )
514
        {
515 30bd2f96 Leszek Koltunski
        mX = (x1 -  mScreenWidth*0.5f)/ mScalingSize;
516
        mY = (mScreenHeight*0.5f - y1)/ mScalingSize;
517 880beeea Leszek Koltunski
        }
518
      }
519
520 30bd2f96 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
521
522
    int getScalingSize()
523
      {
524
      return mScalingSize;
525
      }
526
527 e32d318a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
528
529 11fa413d Leszek Koltunski
    void setTouchControl(TwistyObject object)
530 e32d318a Leszek Koltunski
      {
531 7c546131 Leszek Koltunski
      if( mLastMode!=MODE_REPLACE ) mTouchControl = object.getTouchControl();
532
      else                          mTouchControl = new TouchControlShapeChanging(object);
533 e32d318a Leszek Koltunski
      }
534
535 9276dced Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
536
// INTERNAL API (for AutomaticControl)
537
///////////////////////////////////////////////////////////////////////////////////////////////////
538
539
    public ObjectPreRender getPreRender()
540
      {
541
      return mPreRender;
542
      }
543
544 b3fff6fb Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
545
546
    public ObjectLibInterface getInterface()
547
      {
548
      return mInterface;
549
      }
550
551 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
552
// PUBLIC API
553
///////////////////////////////////////////////////////////////////////////////////////////////////
554
555 621d55ac Leszek Koltunski
    public ObjectControl(OperatingSystemInterface os)
556 880beeea Leszek Koltunski
      {
557
      mIsAutomatic = false;
558
559 57ef6378 Leszek Koltunski
      mBuffer = new int[2];
560
      mAxis   = new float[2];
561
562 a76330cc Leszek Koltunski
      mQuat= new Static4D(-0.25189602f,0.3546389f,0.009657208f,0.90038127f);
563
      mTemp= new Static4D(0,0,0,1);
564
565 092e257b Leszek Koltunski
      mAvgRotSpeed = 0.0f;
566 11fa413d Leszek Koltunski
      mLastMode    = -1;
567 4a389a4e Leszek Koltunski
      mRotateOnCreation = false;
568 880beeea Leszek Koltunski
569 644c217a Leszek Koltunski
      mNormalTouchPoint = new float[2];
570
571 092e257b Leszek Koltunski
      mLastA = new float[NUM_SPEED_PROBES];
572 880beeea Leszek Koltunski
      mLastT = new long[NUM_SPEED_PROBES];
573 c3a033e9 Leszek Koltunski
      mFirstIndex= 0;
574
      mLastIndex = 0;
575
      mMeshState =-1;
576 3bf19410 Leszek Koltunski
      mIconMode  =-1;
577 880beeea Leszek Koltunski
578 621d55ac Leszek Koltunski
      mInterface = os.getInterface();
579 51c25e4e Leszek Koltunski
      mOS = os;
580 880beeea Leszek Koltunski
581 51c25e4e Leszek Koltunski
      mDensity = mOS.getScreenDensity();
582 621d55ac Leszek Koltunski
      mPreRender = new ObjectPreRender(this,mInterface);
583 880beeea Leszek Koltunski
      }
584
585 4a389a4e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 7ba38dd4 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
614
615 30bd2f96 Leszek Koltunski
    public void setScreenSizeAndScaling(int width, int height, int scaling)
616 880beeea Leszek Koltunski
      {
617
      mScreenWidth = width;
618
      mScreenHeight= height;
619 30bd2f96 Leszek Koltunski
      mScalingSize = scaling;
620 7ba38dd4 Leszek Koltunski
621 45e0065d Leszek Koltunski
      if( mObjectNode!=null ) mObjectNode.setSize(width,height);
622
623 7fe64077 Leszek Koltunski
      TwistyObject object = mPreRender.getObject();
624 fd6e2b3b Leszek Koltunski
625
      if( object!=null )
626
        {
627
        object.setTexture();
628 30bd2f96 Leszek Koltunski
        object.setNodeSize(mScalingSize);
629 fd6e2b3b Leszek Koltunski
        }
630 880beeea Leszek Koltunski
      }
631
632 ecf3d6e3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
633
634 64c209f5 Leszek Koltunski
    public void setObjectMove(int xmove, int ymove)
635 ecf3d6e3 Leszek Koltunski
      {
636 72d6857c Leszek Koltunski
      mMoveX = xmove;
637
      mMoveY = ymove;
638
639
      mPreRender.setMove(xmove,ymove);
640 ecf3d6e3 Leszek Koltunski
      }
641
642 64c209f5 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
643
644
    public void setObjectScale(float scale)
645
      {
646
      mPreRender.setScale(scale);
647
      }
648
649 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
650
651 2fca02cf Leszek Koltunski
    public void onPause()
652
      {
653
      BlockController.onPause();
654
      }
655
656
///////////////////////////////////////////////////////////////////////////////////////////////////
657
658
    public void onResume()
659 880beeea Leszek Koltunski
      {
660 82b0cf8e Leszek Koltunski
      mOS.unpressFirst();
661
      mOS.unpressSecond();
662 b9956428 Leszek Koltunski
663
      unlock();
664 2fca02cf Leszek Koltunski
665
      BlockController.onResume();
666 880beeea Leszek Koltunski
      }
667
668 2289cab1 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
669
670
    public void rotateNow(Static4D quat)
671
      {
672
      mTemp.set(quat);
673
      mQuat.set(mTemp);
674
      }
675
676 ee6bb8d7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
677
678
    public void scaleNow(float scale)
679
      {
680 30bd2f96 Leszek Koltunski
      mPreRender.getObject().setObjectRatioNow(scale,mScalingSize );
681 ee6bb8d7 Leszek Koltunski
      }
682
683 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 9276dced Leszek Koltunski
    public void preRender()
700 880beeea Leszek Koltunski
      {
701 9276dced Leszek Koltunski
      mPreRender.preRender();
702
      }
703
704
///////////////////////////////////////////////////////////////////////////////////////////////////
705
706
    public void blockTouch(int place)
707
      {
708 b9956428 Leszek Koltunski
      setLock(true);
709 7205c655 Leszek Koltunski
      mPreRender.blockRotation(place);
710 9276dced Leszek Koltunski
      }
711
712
///////////////////////////////////////////////////////////////////////////////////////////////////
713
714 7205c655 Leszek Koltunski
    public void unblockRotation()
715 9276dced Leszek Koltunski
      {
716 b9956428 Leszek Koltunski
      unsetLock();
717 7205c655 Leszek Koltunski
      mPreRender.unblockRotation();
718 9276dced Leszek Koltunski
      }
719
720 060b445e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
721
722
    public void unblockEverything()
723
      {
724
      mPreRender.unblockEverything();
725
      }
726
727 9276dced Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
728
729 7205c655 Leszek Koltunski
    public boolean isScramblingAndSolvingNotBlocked()
730 9276dced Leszek Koltunski
      {
731 7205c655 Leszek Koltunski
      return mPreRender.isScramblingAndSolvingNotBlocked();
732 9276dced Leszek Koltunski
      }
733
734
///////////////////////////////////////////////////////////////////////////////////////////////////
735
736
    public void initializeObject(int[][] moves)
737
      {
738
      mPreRender.initializeObject(moves);
739
      }
740
741
///////////////////////////////////////////////////////////////////////////////////////////////////
742
743 cf93ea4e Leszek Koltunski
    public void changeObject(int ordinal, int meshState, int iconMode, InitAssets asset)
744 9276dced Leszek Koltunski
      {
745 cf93ea4e Leszek Koltunski
      mPreRender.changeObject(ordinal, meshState, iconMode, asset);
746 9276dced Leszek Koltunski
      }
747
748 568d4698 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
749
750 cf93ea4e Leszek Koltunski
    public void changeIfDifferent(int ordinal, String newName, int meshState, int iconMode, InitAssets asset)
751 568d4698 Leszek Koltunski
      {
752 e1a86bf2 Leszek Koltunski
      TwistyObject object = mPreRender.getObject();
753 958a6e81 Leszek Koltunski
      String oldName = object==null ? "" : object.getShortName();
754 e1a86bf2 Leszek Koltunski
755 3bf19410 Leszek Koltunski
      if( !oldName.equals(newName) || mMeshState!=meshState || mIconMode!=iconMode )
756 e1a86bf2 Leszek Koltunski
        {
757 c3a033e9 Leszek Koltunski
        mMeshState = meshState;
758 3bf19410 Leszek Koltunski
        mIconMode  = iconMode;
759 cf93ea4e Leszek Koltunski
        mPreRender.changeObject(ordinal, meshState, iconMode, asset);
760 e1a86bf2 Leszek Koltunski
        }
761 568d4698 Leszek Koltunski
      }
762
763 9276dced Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
764 a20e56fc Leszek Koltunski
// 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 9276dced Leszek Koltunski
769 a396a7e1 Leszek Koltunski
    public boolean scrambleObject(int num)
770 9276dced Leszek Koltunski
      {
771 a20e56fc Leszek Koltunski
      if( !mBeginningRotation && !mContinuingRotation )
772
        {
773 36f6390b Leszek Koltunski
        return mPreRender.scrambleObject(num);
774 a20e56fc Leszek Koltunski
        }
775 a396a7e1 Leszek Koltunski
      return false;
776 9276dced Leszek Koltunski
      }
777
778 186bc982 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
779
// ditto
780
781 a396a7e1 Leszek Koltunski
    public boolean fastScrambleObject(int duration, int num)
782 186bc982 Leszek Koltunski
      {
783
      if( !mBeginningRotation && !mContinuingRotation )
784
        {
785 36f6390b Leszek Koltunski
        return mPreRender.fastScrambleObject(duration,num);
786 186bc982 Leszek Koltunski
        }
787 a396a7e1 Leszek Koltunski
      return false;
788 186bc982 Leszek Koltunski
      }
789
790 826d293e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
791
792 b1370e3b Leszek Koltunski
    public void presentObject(int num, int duration)
793 826d293e Leszek Koltunski
      {
794 b1370e3b Leszek Koltunski
      mPreRender.presentObject(num,duration);
795 826d293e Leszek Koltunski
      }
796
797 9276dced Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
798
799
    public void solveObject()
800
      {
801
      mPreRender.solveObject();
802
      }
803
804 17d623f1 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
805
806
    public void solveOnly()
807
      {
808
      mPreRender.solveOnly();
809
      }
810
811 4c2c0f44 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
812
813
    public void resetTextureMapsEffect(int duration)
814
      {
815
      mPreRender.resetTextureMapsEffect(duration);
816
      }
817
818 9276dced Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
819
820 2df35810 Leszek Koltunski
    public void addRotation(MovesFinished listener, int axis, int rowBitmap, int angle, int duration)
821 9276dced Leszek Koltunski
      {
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 79c7c950 Leszek Koltunski
    public OperatingSystemInterface getOS()
842
      {
843
      return mOS;
844
      }
845
846
///////////////////////////////////////////////////////////////////////////////////////////////////
847
848
    public void savePreferences()
849 9276dced Leszek Koltunski
      {
850 79c7c950 Leszek Koltunski
      mPreRender.savePreferences(mOS);
851 8e66157b Leszek Koltunski
852
      for( int i=0; i< BaseEffect.Type.LENGTH; i++ )
853
        {
854 79c7c950 Leszek Koltunski
        BaseEffect.Type.getType(i).savePreferences(mOS);
855 8e66157b Leszek Koltunski
        }
856 9276dced Leszek Koltunski
      }
857
858
///////////////////////////////////////////////////////////////////////////////////////////////////
859
860 79c7c950 Leszek Koltunski
    public void restorePreferences()
861 9276dced Leszek Koltunski
      {
862 79c7c950 Leszek Koltunski
      mPreRender.restorePreferences(mOS);
863 8e66157b Leszek Koltunski
864
      for (int i=0; i<BaseEffect.Type.LENGTH; i++)
865
        {
866 79c7c950 Leszek Koltunski
        BaseEffect.Type.getType(i).restorePreferences(mOS);
867 8e66157b Leszek Koltunski
        }
868 880beeea Leszek Koltunski
      }
869 c3a033e9 Leszek Koltunski
870 b9956428 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
871
872 81141862 Leszek Koltunski
    public boolean retLocked()
873 b9956428 Leszek Koltunski
      {
874
      return mIsLocked;
875
      }
876
877
///////////////////////////////////////////////////////////////////////////////////////////////////
878
879 81141862 Leszek Koltunski
    public void toggleLock()
880 b9956428 Leszek Koltunski
      {
881
      mIsLocked = !mIsLocked;
882
      }
883
884
///////////////////////////////////////////////////////////////////////////////////////////////////
885
886 81141862 Leszek Koltunski
    public void unlock()
887
      {
888
      mIsLocked = false;
889
      }
890 b9956428 Leszek Koltunski
891
///////////////////////////////////////////////////////////////////////////////////////////////////
892
893 81141862 Leszek Koltunski
    public void setLock(boolean value)
894
      {
895
      mRemLocked = mIsLocked;
896
      mIsLocked = value;
897
      }
898 b9956428 Leszek Koltunski
899
///////////////////////////////////////////////////////////////////////////////////////////////////
900
901 81141862 Leszek Koltunski
    public void unsetLock()
902
      {
903
      mIsLocked = mRemLocked;
904
      }
905 880beeea Leszek Koltunski
906 11fa413d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
907
908
    public void setTextureMap(int cubit, int face, int newColor)
909
      {
910
      mPreRender.setTextureMap(cubit,face,newColor);
911
      }
912
913 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
914
915 82b0cf8e Leszek Koltunski
    public boolean onTouchEvent(int mode)
916 880beeea Leszek Koltunski
      {
917 611940ac Leszek Koltunski
      if( mode!=MODE_NOTHING )
918
        {
919
        if( mObjectNode==null ) return true;
920 53e85349 Leszek Koltunski
921 7c546131 Leszek Koltunski
        if( mode!=mLastMode )
922 611940ac Leszek Koltunski
          {
923 2832c2fa Leszek Koltunski
          TwistyObject object = getObject();
924
925
          if( object!=null )
926
            {
927
            mLastMode = mode;
928
            setTouchControl(object);
929
            }
930
          else return true;
931 611940ac Leszek Koltunski
          }
932 11fa413d Leszek Koltunski
933 82b0cf8e Leszek Koltunski
        int action = mOS.getAction();
934 92d6c2f1 Leszek Koltunski
935 611940ac Leszek Koltunski
        switch(action)
936
          {
937 82b0cf8e Leszek Koltunski
          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 611940ac Leszek Koltunski
          }
955
        }
956 880beeea Leszek Koltunski
957
      return true;
958
      }
959
}