Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / main / ObjectControl.java @ 644c217a

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
    private float mCurrentAngle, mCurrRotSpeed;
62
    private final float[] mLastX;
63
    private final float[] mLastY;
64
    private final long[] mLastT;
65
    private int mFirstIndex, mLastIndex;
66
    private final int mDensity;
67
68
    private float mX1, mY1, mX2, mY2, mX, mY;
69 046104f5 Leszek Koltunski
    private final boolean mIsAutomatic;
70 880beeea Leszek Koltunski
71 b9956428 Leszek Koltunski
    private boolean mIsLocked, mRemLocked;
72 57ef6378 Leszek Koltunski
    private final int[] mBuffer;
73
    private final float[] mAxis;
74 3bf19410 Leszek Koltunski
    private int mMeshState, mIconMode;
75 4a389a4e Leszek Koltunski
    private boolean mRotateOnCreation;
76 a76330cc Leszek Koltunski
    private final Static4D mQuat,mTemp;
77 644c217a Leszek Koltunski
    private boolean mRotAxisIsNormal;
78
    private final float[] mNormalTouchPoint;
79
    private float mNormalRotAngle;
80 880beeea Leszek Koltunski
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82
83
    private void addSpeedProbe(float x, float y)
84
      {
85
      long currTime = System.currentTimeMillis();
86
      boolean theSame = mLastIndex==mFirstIndex;
87
88
      mLastIndex++;
89
      if( mLastIndex>=NUM_SPEED_PROBES ) mLastIndex=0;
90
91
      mLastT[mLastIndex] = currTime;
92
      mLastX[mLastIndex] = x;
93
      mLastY[mLastIndex] = y;
94
95
      if( mLastIndex==mFirstIndex)
96
        {
97
        mFirstIndex++;
98
        if( mFirstIndex>=NUM_SPEED_PROBES ) mFirstIndex=0;
99
        }
100
101
      if( theSame )
102
        {
103
        mLastT[mFirstIndex] = currTime;
104
        mLastX[mFirstIndex] = x;
105
        mLastY[mFirstIndex] = y;
106
        }
107
      }
108
109
///////////////////////////////////////////////////////////////////////////////////////////////////
110
111
    private void computeCurrentSpeedInInchesPerSecond()
112
      {
113
      long firstTime = mLastT[mFirstIndex];
114
      long lastTime  = mLastT[mLastIndex];
115
      float fX = mLastX[mFirstIndex];
116
      float fY = mLastY[mFirstIndex];
117
      float lX = mLastX[mLastIndex];
118
      float lY = mLastY[mLastIndex];
119
120
      long timeDiff = lastTime-firstTime;
121
122
      mLastIndex = 0;
123
      mFirstIndex= 0;
124
125 78108318 Leszek Koltunski
      mCurrRotSpeed = timeDiff>0 ? 1000*retFingerDragDistanceInInches(fX-lX,fY-lY)/timeDiff : 0;
126 880beeea Leszek Koltunski
      }
127
128
///////////////////////////////////////////////////////////////////////////////////////////////////
129
130 78108318 Leszek Koltunski
    private float retFingerDragDistanceInInches(float xd, float yd)
131 880beeea Leszek Koltunski
      {
132 78108318 Leszek Koltunski
      float xDist = mScreenWidth*xd;
133
      float yDist = mScreenHeight*yd;
134 880beeea Leszek Koltunski
      float distInPixels = (float)Math.sqrt(xDist*xDist + yDist*yDist);
135
136
      return distInPixels/mDensity;
137
      }
138
139 3d093961 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
140
141 57ef6378 Leszek Koltunski
    private void replaceMode(boolean down)
142 3d093961 Leszek Koltunski
      {
143
      mBeginningRotation= false;
144
145
      if( down )
146
        {
147 11fa413d Leszek Koltunski
        int cubit = mTouchControl.getTouchedCubit();
148
        int face  = mTouchControl.getTouchedCubitFace();
149
        mInterface.onReplaceModeDown(cubit,face);
150 3d093961 Leszek Koltunski
        }
151
      }
152
153 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
154
155 11fa413d Leszek Koltunski
    private void setUpDragOrRotate(boolean down, float x, float y)
156 880beeea Leszek Koltunski
      {
157 11fa413d Leszek Koltunski
      if( mLastMode==MODE_DRAG )
158 880beeea Leszek Koltunski
        {
159
        mDragging           = true;
160
        mBeginningRotation  = false;
161
        mContinuingRotation = false;
162
        }
163
      else
164
        {
165 57ef6378 Leszek Koltunski
        CAMERA_POINT.set2( mObjectNode.getCameraDist() );
166 880beeea Leszek Koltunski
        Static4D touchPoint = new Static4D(x, y, 0, 0);
167
        Static4D rotatedTouchPoint= QuatHelper.rotateVectorByInvertedQuat(touchPoint, mQuat);
168
        Static4D rotatedCamera= QuatHelper.rotateVectorByInvertedQuat(CAMERA_POINT, mQuat);
169
170 57ef6378 Leszek Koltunski
        if( mTouchControl!=null && mTouchControl.objectTouched(rotatedTouchPoint,rotatedCamera) )
171 880beeea Leszek Koltunski
          {
172
          mDragging           = false;
173
          mContinuingRotation = false;
174
175 7205c655 Leszek Koltunski
               if( mLastMode==MODE_ROTATE  ) mBeginningRotation = !mPreRender.isRotationBlocked();
176 11fa413d Leszek Koltunski
          else if( mLastMode==MODE_REPLACE ) replaceMode(down);
177 880beeea Leszek Koltunski
          }
178
        else
179
          {
180 b9956428 Leszek Koltunski
          mDragging           = (!mIsLocked || mIsAutomatic);
181 880beeea Leszek Koltunski
          mBeginningRotation  = false;
182
          mContinuingRotation = false;
183 b3fff6fb Leszek Koltunski
          if( !mDragging ) mInterface.failedToDrag();
184 880beeea Leszek Koltunski
          }
185
        }
186
      }
187
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189
190
    private void drag(float x, float y)
191
      {
192 82b0cf8e Leszek Koltunski
      if( mOS.isFirstPressed() && mOS.isSecondPressed() )
193 880beeea Leszek Koltunski
        {
194 30bd2f96 Leszek Koltunski
        float x2 = (mX2 - mScreenWidth*0.5f)/ mScalingSize;
195
        float y2 = (mScreenHeight*0.5f - mY2)/ mScalingSize;
196 880beeea Leszek Koltunski
197
        float angleNow = getAngle(x,y,x2,y2);
198
        float angleDiff = angleNow-mRotAngle;
199
        float sinA =-(float)Math.sin(angleDiff);
200
        float cosA = (float)Math.cos(angleDiff);
201
202
        Static4D dragQuat = QuatHelper.quatMultiply(new Static4D(0,0,sinA,cosA), mQuat);
203
        mTemp.set(dragQuat);
204
205
        mRotAngle = angleNow;
206
207
        float distNow  = (float)Math.sqrt( (x-x2)*(x-x2) + (y-y2)*(y-y2) );
208
        float distQuot = mInitDistance<0 ? 1.0f : distNow/ mInitDistance;
209
        mInitDistance = distNow;
210
        TwistyObject object = mPreRender.getObject();
211 7c82e1c6 Leszek Koltunski
        if( object!=null )
212
          {
213 30bd2f96 Leszek Koltunski
          object.setObjectRatio(distQuot, mScalingSize );
214 7c82e1c6 Leszek Koltunski
          float ratio = object.getObjectRatio();
215
          if( mLastMode==MODE_REPLACE ) mTouchControl.setObjectRatio(ratio);
216
          }
217 880beeea Leszek Koltunski
        }
218
      else
219
        {
220
        Static4D dragQuat = QuatHelper.quatMultiply(QuatHelper.quatFromDrag(mX-x,y-mY), mQuat);
221
        mTemp.set(dragQuat);
222
        }
223
224
      mPreRender.setQuatOnNextRender();
225
      mX = x;
226
      mY = y;
227
      }
228
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230
231
    private void finishRotation()
232
      {
233 2df35810 Leszek Koltunski
      TwistyObject object = mPreRender.getObject();
234 beee90ab Leszek Koltunski
      int[][] angles = object.getBasicAngles();
235 880beeea Leszek Koltunski
236 d5411af4 Leszek Koltunski
      if( mCurrentAxis<angles.length && mCurrentRow<angles[mCurrentAxis].length )
237 880beeea Leszek Koltunski
        {
238 a1bcb301 Leszek Koltunski
        computeCurrentSpeedInInchesPerSecond();
239 beee90ab Leszek Koltunski
        int basic = angles[mCurrentAxis][mCurrentRow];
240
        int angle = object.computeNearestAngle(basic,mCurrentAngle, mCurrRotSpeed);
241 a1bcb301 Leszek Koltunski
        mPreRender.finishRotation(angle);
242
        mPreRender.rememberMove(mCurrentAxis,mCurrentRow,angle);
243
244
        if( angle!=0 )
245
          {
246 beee90ab Leszek Koltunski
          int realAngle = (angle*basic)/360;
247 a1bcb301 Leszek Koltunski
          mInterface.onFinishRotation(mCurrentAxis,mCurrentRow,realAngle);
248
          }
249 880beeea Leszek Koltunski
250 a1bcb301 Leszek Koltunski
        mContinuingRotation = false;
251
        mBeginningRotation  = false;
252
        mDragging           = true;
253
        }
254 880beeea Leszek Koltunski
      }
255
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257
258
    private void continueRotation(float x, float y)
259
      {
260 644c217a Leszek Koltunski
      if( !mRotAxisIsNormal )
261
        {
262
        float dx = x-mStartRotX;
263
        float dy = y-mStartRotY;
264
        float alpha = dx*mAxis[0] + dy*mAxis[1];
265
        float x2 = dx - alpha*mAxis[0];
266
        float y2 = dy - alpha*mAxis[1];
267 880beeea Leszek Koltunski
268 644c217a Leszek Koltunski
        float len = (float)Math.sqrt(x2*x2 + y2*y2);
269 880beeea Leszek Koltunski
270 644c217a Leszek Koltunski
        // we have the length of 1D vector 'angle', now the direction:
271
        float tmp = mAxis[1]==0 ? -mAxis[0]*y2 : mAxis[1]*x2;
272 880beeea Leszek Koltunski
273 644c217a Leszek Koltunski
        float angle = (tmp>0 ? 1:-1)*len*mRotationFactor;
274
        mCurrentAngle = SWIPING_SENSITIVITY*angle;
275
        mPreRender.getObject().continueRotation(mCurrentAngle);
276 880beeea Leszek Koltunski
277 644c217a Leszek Koltunski
        addSpeedProbe(x2,y2);
278
        }
279
      else
280
        {
281
        float rotAngle = computeNormalRotAngle(mNormalTouchPoint[0]-x,mNormalTouchPoint[1]-y);
282
        mCurrentAngle = rotAngle - mNormalRotAngle;
283
        mPreRender.getObject().continueRotation(mCurrentAngle);
284
        }
285
      }
286
287
///////////////////////////////////////////////////////////////////////////////////////////////////
288
289
    private void correctRotationAxis()
290
      {
291
      if( mAxis[0]==0 && mAxis[1]==0 )
292
        {
293
        mRotAxisIsNormal = true;
294
295
        // 0. get face center in object space
296
        // 1. multiply it by mQuat
297
        // 2. multiply if by mObjectRatio. Let the result be (x,y,z)
298
        // 3. let D be CAMERA_POINT.Z
299
        // 4. then compute the point on the screen (X,Y) the face center maps to:
300
        //    (X,Y) = (Ax,Ay) where A = D/(D-z)
301
302
        float[] faceCenter = mTouchControl.getTouchedPuzzleCenter();
303
        float D = CAMERA_POINT.get2();
304
        float[] rotated = new float[4];
305
        QuatHelper.rotateVectorByQuat(rotated, faceCenter[0],faceCenter[1],faceCenter[2],faceCenter[3],mQuat);
306
        TwistyObject object = getObject();
307
        float ratio = object.getObjectRatio();
308
309
        float x = rotated[0] * ratio;
310
        float y = rotated[1] * ratio;
311
        float z = rotated[2] * ratio;
312
313
        float A = D / (D-z);
314
        mNormalTouchPoint[0] = A*x;
315
        mNormalTouchPoint[1] = A*y;
316
        }
317
      else
318
        {
319
        mRotAxisIsNormal = false;
320
        }
321
      }
322
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324
// in degrees
325
326
    private float computeNormalRotAngle(float vx, float vy)
327
      {
328
      return 0;  // TODO
329 880beeea Leszek Koltunski
      }
330
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332
333
    private void beginRotation(float x, float y)
334
      {
335 31ed545f Leszek Koltunski
      mStartRotX = x;
336
      mStartRotY = y;
337
338 880beeea Leszek Koltunski
      TwistyObject object = mPreRender.getObject();
339 a57e6870 Leszek Koltunski
      int[] numLayers = object.getNumLayers();
340 43a4ccff Leszek Koltunski
      Static4D touchPoint = new Static4D(x, y, 0, 0);
341
      Static4D rotatedTouchPoint= QuatHelper.rotateVectorByInvertedQuat(touchPoint, mQuat);
342 880beeea Leszek Koltunski
343 31ed545f Leszek Koltunski
      mTouchControl.newRotation(mBuffer,rotatedTouchPoint,mQuat);
344 880beeea Leszek Koltunski
345 31ed545f Leszek Koltunski
      mCurrentAxis = mBuffer[0];
346
      mCurrentRow  = mBuffer[1];
347 880beeea Leszek Koltunski
348 31ed545f Leszek Koltunski
      mTouchControl.getCastedRotAxis(mAxis,mQuat,mCurrentAxis);
349 644c217a Leszek Koltunski
      correctRotationAxis();
350 31ed545f Leszek Koltunski
      mRotationFactor = mTouchControl.returnRotationFactor(numLayers,mCurrentRow);
351 644c217a Leszek Koltunski
      if( mRotAxisIsNormal ) mNormalRotAngle = computeNormalRotAngle(mNormalTouchPoint[0]-x,mNormalTouchPoint[1]-y);
352 605f319b Leszek Koltunski
353
      if( object.beginNewRotation( mCurrentAxis, mCurrentRow ) )
354
        {
355
        mInterface.onBeginRotation();
356
        addSpeedProbe(x,y);
357
        mBeginningRotation = false;
358
        mContinuingRotation= true;
359
        }
360 880beeea Leszek Koltunski
      }
361
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363
364
    private float getAngle(float x1, float y1, float x2, float y2)
365
      {
366
      return (float) Math.atan2(y1-y2, x1-x2);
367
      }
368
369
///////////////////////////////////////////////////////////////////////////////////////////////////
370
371 82b0cf8e Leszek Koltunski
    private void prepareDown()
372 880beeea Leszek Koltunski
      {
373 82b0cf8e Leszek Koltunski
      mOS.pressFirst();
374
      mOS.unpressSecond();
375
376
      mX1 = mOS.getFirstX() - mMoveX;
377
      mY1 = mOS.getFirstY() + mMoveY;
378 880beeea Leszek Koltunski
      }
379
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381
382 82b0cf8e Leszek Koltunski
    private void prepareMove()
383 880beeea Leszek Koltunski
      {
384 c0dcc0c1 Leszek Koltunski
      int index1 = mOS.getFirstPointerIndex();
385
386
      if( index1>=0 )
387 880beeea Leszek Koltunski
        {
388 c0dcc0c1 Leszek Koltunski
        mX1 = mOS.getX(index1) - mMoveX;
389
        mY1 = mOS.getY(index1) + mMoveY;
390 880beeea Leszek Koltunski
        }
391
392 c0dcc0c1 Leszek Koltunski
      int index2 = mOS.getSecondPointerIndex();
393
394
      if( index2>=0 )
395 880beeea Leszek Koltunski
        {
396 c0dcc0c1 Leszek Koltunski
        mX2 = mOS.getX(index2) - mMoveX;
397
        mY2 = mOS.getY(index2) + mMoveY;
398 880beeea Leszek Koltunski
        }
399
      }
400
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402
403 82b0cf8e Leszek Koltunski
    private void prepareUp()
404 880beeea Leszek Koltunski
      {
405 82b0cf8e Leszek Koltunski
      mOS.unpressFirst();
406
      mOS.unpressSecond();
407 880beeea Leszek Koltunski
      }
408
409
///////////////////////////////////////////////////////////////////////////////////////////////////
410
411 82b0cf8e Leszek Koltunski
    private void prepareDown2()
412 880beeea Leszek Koltunski
      {
413 82b0cf8e Leszek Koltunski
      if( !mOS.isFirstPressed() )
414 880beeea Leszek Koltunski
        {
415 82b0cf8e Leszek Koltunski
        mOS.pressFirst();
416
        mX1 = mOS.getFirstX() - mMoveX;
417
        mY1 = mOS.getFirstY() + mMoveY;
418 880beeea Leszek Koltunski
        }
419 82b0cf8e Leszek Koltunski
      else if( !mOS.isSecondPressed() )
420 880beeea Leszek Koltunski
        {
421 82b0cf8e Leszek Koltunski
        mOS.pressSecond();
422
        mX2 = mOS.getSecondX() - mMoveX;
423
        mY2 = mOS.getSecondY() + mMoveY;
424 880beeea Leszek Koltunski
        }
425
      }
426
427
///////////////////////////////////////////////////////////////////////////////////////////////////
428
429 82b0cf8e Leszek Koltunski
    private void prepareUp2()
430 880beeea Leszek Koltunski
      {
431 dfa958c7 Leszek Koltunski
      mOS.upOneOfThem();
432 880beeea Leszek Koltunski
      }
433
434
///////////////////////////////////////////////////////////////////////////////////////////////////
435
436 11fa413d Leszek Koltunski
    private void actionMove(float x1, float y1, float x2, float y2)
437 880beeea Leszek Koltunski
      {
438 82b0cf8e Leszek Koltunski
      float pX,pY;
439
440
      if( mOS.isFirstPressed() ) { pX = x1; pY=y1; }
441
      else                       { pX = x2; pY=y2; }
442 880beeea Leszek Koltunski
443 30bd2f96 Leszek Koltunski
      float x = (pX - mScreenWidth*0.5f)/ mScalingSize;
444
      float y = (mScreenHeight*0.5f -pY)/ mScalingSize;
445 880beeea Leszek Koltunski
446
      if( mBeginningRotation )
447
        {
448 78108318 Leszek Koltunski
        if( retFingerDragDistanceInInches(mX-x,mY-y) > ROTATION_SENSITIVITY )
449 880beeea Leszek Koltunski
          {
450
          beginRotation(x,y);
451
          }
452
        }
453
      else if( mContinuingRotation )
454
        {
455
        continueRotation(x,y);
456
        }
457
      else if( mDragging )
458
        {
459
        drag(x,y);
460
        }
461
      else
462
        {
463 11fa413d Leszek Koltunski
        setUpDragOrRotate(false,x,y);
464 880beeea Leszek Koltunski
        }
465
      }
466
467
///////////////////////////////////////////////////////////////////////////////////////////////////
468
469 11fa413d Leszek Koltunski
    private void actionDown(float x, float y)
470 880beeea Leszek Koltunski
      {
471 30bd2f96 Leszek Koltunski
      mX = (x -  mScreenWidth*0.5f)/ mScalingSize;
472
      mY = (mScreenHeight*0.5f - y)/ mScalingSize;
473 880beeea Leszek Koltunski
474 11fa413d Leszek Koltunski
      setUpDragOrRotate(true,mX,mY);
475 880beeea Leszek Koltunski
      }
476
477
///////////////////////////////////////////////////////////////////////////////////////////////////
478
479
    private void actionUp()
480
      {
481
      if( mContinuingRotation )
482
        {
483
        finishRotation();
484
        }
485
486 11fa413d Leszek Koltunski
      if( mLastMode==MODE_REPLACE ) mInterface.onReplaceModeUp();
487 880beeea Leszek Koltunski
      }
488
489
///////////////////////////////////////////////////////////////////////////////////////////////////
490
491
    private void actionDown2(float x1, float y1, float x2, float y2)
492
      {
493
      mRotAngle = getAngle(x1,-y1, x2,-y2);
494
      mInitDistance = -1;
495
496 30bd2f96 Leszek Koltunski
      mX = (x1 - mScreenWidth*0.5f )/ mScalingSize;
497
      mY = (mScreenHeight*0.5f - y1)/ mScalingSize;
498 880beeea Leszek Koltunski
499
      if( mBeginningRotation )
500
        {
501
        mContinuingRotation = false;
502
        mBeginningRotation  = false;
503
        mDragging           = true;
504
        }
505
      else if( mContinuingRotation )
506
        {
507
        finishRotation();
508
        }
509
      }
510
511
///////////////////////////////////////////////////////////////////////////////////////////////////
512
513
    private void actionUp2(boolean p1isUp, float x1, float y1, boolean p2isUp, float x2, float y2)
514
      {
515
      if( p1isUp )
516
        {
517 30bd2f96 Leszek Koltunski
        mX = (x2 -  mScreenWidth*0.5f)/ mScalingSize;
518
        mY = (mScreenHeight*0.5f - y2)/ mScalingSize;
519 880beeea Leszek Koltunski
        }
520
      if( p2isUp )
521
        {
522 30bd2f96 Leszek Koltunski
        mX = (x1 -  mScreenWidth*0.5f)/ mScalingSize;
523
        mY = (mScreenHeight*0.5f - y1)/ mScalingSize;
524 880beeea Leszek Koltunski
        }
525
      }
526
527 30bd2f96 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
528
529
    int getScalingSize()
530
      {
531
      return mScalingSize;
532
      }
533
534 e32d318a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
535
536 11fa413d Leszek Koltunski
    void setTouchControl(TwistyObject object)
537 e32d318a Leszek Koltunski
      {
538 7c546131 Leszek Koltunski
      if( mLastMode!=MODE_REPLACE ) mTouchControl = object.getTouchControl();
539
      else                          mTouchControl = new TouchControlShapeChanging(object);
540 e32d318a Leszek Koltunski
      }
541
542 9276dced Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
543
// INTERNAL API (for AutomaticControl)
544
///////////////////////////////////////////////////////////////////////////////////////////////////
545
546
    public ObjectPreRender getPreRender()
547
      {
548
      return mPreRender;
549
      }
550
551 b3fff6fb Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
552
553
    public ObjectLibInterface getInterface()
554
      {
555
      return mInterface;
556
      }
557
558 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
559
// PUBLIC API
560
///////////////////////////////////////////////////////////////////////////////////////////////////
561
562 621d55ac Leszek Koltunski
    public ObjectControl(OperatingSystemInterface os)
563 880beeea Leszek Koltunski
      {
564
      mIsAutomatic = false;
565
566 57ef6378 Leszek Koltunski
      mBuffer = new int[2];
567
      mAxis   = new float[2];
568
569 a76330cc Leszek Koltunski
      mQuat= new Static4D(-0.25189602f,0.3546389f,0.009657208f,0.90038127f);
570
      mTemp= new Static4D(0,0,0,1);
571
572 11fa413d Leszek Koltunski
      mCurrRotSpeed= 0.0f;
573
      mLastMode    = -1;
574 4a389a4e Leszek Koltunski
      mRotateOnCreation = false;
575 880beeea Leszek Koltunski
576 644c217a Leszek Koltunski
      mNormalTouchPoint = new float[2];
577
578 880beeea Leszek Koltunski
      mLastX = new float[NUM_SPEED_PROBES];
579
      mLastY = new float[NUM_SPEED_PROBES];
580
      mLastT = new long[NUM_SPEED_PROBES];
581 c3a033e9 Leszek Koltunski
      mFirstIndex= 0;
582
      mLastIndex = 0;
583
      mMeshState =-1;
584 3bf19410 Leszek Koltunski
      mIconMode  =-1;
585 880beeea Leszek Koltunski
586 621d55ac Leszek Koltunski
      mInterface = os.getInterface();
587 51c25e4e Leszek Koltunski
      mOS = os;
588 880beeea Leszek Koltunski
589 51c25e4e Leszek Koltunski
      mDensity = mOS.getScreenDensity();
590 621d55ac Leszek Koltunski
      mPreRender = new ObjectPreRender(this,mInterface);
591 880beeea Leszek Koltunski
      }
592
593 4a389a4e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
594
595
    public void setRotateOnCreation(boolean rotate)
596
      {
597
      mRotateOnCreation = rotate;
598
      }
599
600
///////////////////////////////////////////////////////////////////////////////////////////////////
601
602
    public boolean getRotateOnCreation()
603
      {
604
      return mRotateOnCreation;
605
      }
606
607 7ba38dd4 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
608
609
    public TwistyObjectNode getNode()
610
      {
611
      return mObjectNode;
612
      }
613
614
///////////////////////////////////////////////////////////////////////////////////////////////////
615
616
    public void createNode(int width, int height)
617
      {
618
      if( mObjectNode==null ) mObjectNode = new TwistyObjectNode(width,height);
619
      }
620
621 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
622
623 30bd2f96 Leszek Koltunski
    public void setScreenSizeAndScaling(int width, int height, int scaling)
624 880beeea Leszek Koltunski
      {
625
      mScreenWidth = width;
626
      mScreenHeight= height;
627 30bd2f96 Leszek Koltunski
      mScalingSize = scaling;
628 7ba38dd4 Leszek Koltunski
629 45e0065d Leszek Koltunski
      if( mObjectNode!=null ) mObjectNode.setSize(width,height);
630
631 7fe64077 Leszek Koltunski
      TwistyObject object = mPreRender.getObject();
632 fd6e2b3b Leszek Koltunski
633
      if( object!=null )
634
        {
635
        object.setTexture();
636 30bd2f96 Leszek Koltunski
        object.setNodeSize(mScalingSize);
637 fd6e2b3b Leszek Koltunski
        }
638 880beeea Leszek Koltunski
      }
639
640 ecf3d6e3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
641
642 64c209f5 Leszek Koltunski
    public void setObjectMove(int xmove, int ymove)
643 ecf3d6e3 Leszek Koltunski
      {
644 72d6857c Leszek Koltunski
      mMoveX = xmove;
645
      mMoveY = ymove;
646
647
      mPreRender.setMove(xmove,ymove);
648 ecf3d6e3 Leszek Koltunski
      }
649
650 64c209f5 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
651
652
    public void setObjectScale(float scale)
653
      {
654
      mPreRender.setScale(scale);
655
      }
656
657 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
658
659 2fca02cf Leszek Koltunski
    public void onPause()
660
      {
661
      BlockController.onPause();
662
      }
663
664
///////////////////////////////////////////////////////////////////////////////////////////////////
665
666
    public void onResume()
667 880beeea Leszek Koltunski
      {
668 82b0cf8e Leszek Koltunski
      mOS.unpressFirst();
669
      mOS.unpressSecond();
670 b9956428 Leszek Koltunski
671
      unlock();
672 2fca02cf Leszek Koltunski
673
      BlockController.onResume();
674 880beeea Leszek Koltunski
      }
675
676 2289cab1 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
677
678
    public void rotateNow(Static4D quat)
679
      {
680
      mTemp.set(quat);
681
      mQuat.set(mTemp);
682
      }
683
684 ee6bb8d7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
685
686
    public void scaleNow(float scale)
687
      {
688 30bd2f96 Leszek Koltunski
      mPreRender.getObject().setObjectRatioNow(scale,mScalingSize );
689 ee6bb8d7 Leszek Koltunski
      }
690
691 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
692
693
    public void setQuat()
694
      {
695
      mQuat.set(mTemp);
696
      }
697
698
///////////////////////////////////////////////////////////////////////////////////////////////////
699
700
    public Static4D getQuat()
701
      {
702
      return mQuat;
703
      }
704
705
///////////////////////////////////////////////////////////////////////////////////////////////////
706
707 9276dced Leszek Koltunski
    public void preRender()
708 880beeea Leszek Koltunski
      {
709 9276dced Leszek Koltunski
      mPreRender.preRender();
710
      }
711
712
///////////////////////////////////////////////////////////////////////////////////////////////////
713
714
    public void blockTouch(int place)
715
      {
716 b9956428 Leszek Koltunski
      setLock(true);
717 7205c655 Leszek Koltunski
      mPreRender.blockRotation(place);
718 9276dced Leszek Koltunski
      }
719
720
///////////////////////////////////////////////////////////////////////////////////////////////////
721
722 7205c655 Leszek Koltunski
    public void unblockRotation()
723 9276dced Leszek Koltunski
      {
724 b9956428 Leszek Koltunski
      unsetLock();
725 7205c655 Leszek Koltunski
      mPreRender.unblockRotation();
726 9276dced Leszek Koltunski
      }
727
728 060b445e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
729
730
    public void unblockEverything()
731
      {
732
      mPreRender.unblockEverything();
733
      }
734
735 9276dced Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
736
737 7205c655 Leszek Koltunski
    public boolean isScramblingAndSolvingNotBlocked()
738 9276dced Leszek Koltunski
      {
739 7205c655 Leszek Koltunski
      return mPreRender.isScramblingAndSolvingNotBlocked();
740 9276dced Leszek Koltunski
      }
741
742
///////////////////////////////////////////////////////////////////////////////////////////////////
743
744
    public void initializeObject(int[][] moves)
745
      {
746
      mPreRender.initializeObject(moves);
747
      }
748
749
///////////////////////////////////////////////////////////////////////////////////////////////////
750
751 cf93ea4e Leszek Koltunski
    public void changeObject(int ordinal, int meshState, int iconMode, InitAssets asset)
752 9276dced Leszek Koltunski
      {
753 cf93ea4e Leszek Koltunski
      mPreRender.changeObject(ordinal, meshState, iconMode, asset);
754 9276dced Leszek Koltunski
      }
755
756 568d4698 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
757
758 cf93ea4e Leszek Koltunski
    public void changeIfDifferent(int ordinal, String newName, int meshState, int iconMode, InitAssets asset)
759 568d4698 Leszek Koltunski
      {
760 e1a86bf2 Leszek Koltunski
      TwistyObject object = mPreRender.getObject();
761 958a6e81 Leszek Koltunski
      String oldName = object==null ? "" : object.getShortName();
762 e1a86bf2 Leszek Koltunski
763 3bf19410 Leszek Koltunski
      if( !oldName.equals(newName) || mMeshState!=meshState || mIconMode!=iconMode )
764 e1a86bf2 Leszek Koltunski
        {
765 c3a033e9 Leszek Koltunski
        mMeshState = meshState;
766 3bf19410 Leszek Koltunski
        mIconMode  = iconMode;
767 cf93ea4e Leszek Koltunski
        mPreRender.changeObject(ordinal, meshState, iconMode, asset);
768 e1a86bf2 Leszek Koltunski
        }
769 568d4698 Leszek Koltunski
      }
770
771 9276dced Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
772 a20e56fc Leszek Koltunski
// if one or more fingers currently touch the screen, and we just pressed the 'scramble' button, do
773
// not scramble - otherwise a kind of a cheat is possible where user touches the screen, starts
774
// scrambling, then lifts the finger and the act of lifting screws the scrambling - no further
775
// scrambles take any effect!
776 9276dced Leszek Koltunski
777 a396a7e1 Leszek Koltunski
    public boolean scrambleObject(int num)
778 9276dced Leszek Koltunski
      {
779 a20e56fc Leszek Koltunski
      if( !mBeginningRotation && !mContinuingRotation )
780
        {
781 36f6390b Leszek Koltunski
        return mPreRender.scrambleObject(num);
782 a20e56fc Leszek Koltunski
        }
783 a396a7e1 Leszek Koltunski
      return false;
784 9276dced Leszek Koltunski
      }
785
786 186bc982 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
787
// ditto
788
789 a396a7e1 Leszek Koltunski
    public boolean fastScrambleObject(int duration, int num)
790 186bc982 Leszek Koltunski
      {
791
      if( !mBeginningRotation && !mContinuingRotation )
792
        {
793 36f6390b Leszek Koltunski
        return mPreRender.fastScrambleObject(duration,num);
794 186bc982 Leszek Koltunski
        }
795 a396a7e1 Leszek Koltunski
      return false;
796 186bc982 Leszek Koltunski
      }
797
798 826d293e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
799
800 b1370e3b Leszek Koltunski
    public void presentObject(int num, int duration)
801 826d293e Leszek Koltunski
      {
802 b1370e3b Leszek Koltunski
      mPreRender.presentObject(num,duration);
803 826d293e Leszek Koltunski
      }
804
805 9276dced Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
806
807
    public void solveObject()
808
      {
809
      mPreRender.solveObject();
810
      }
811
812 17d623f1 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
813
814
    public void solveOnly()
815
      {
816
      mPreRender.solveOnly();
817
      }
818
819 4c2c0f44 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
820
821
    public void resetTextureMapsEffect(int duration)
822
      {
823
      mPreRender.resetTextureMapsEffect(duration);
824
      }
825
826 9276dced Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
827
828 2df35810 Leszek Koltunski
    public void addRotation(MovesFinished listener, int axis, int rowBitmap, int angle, int duration)
829 9276dced Leszek Koltunski
      {
830
      mPreRender.addRotation(listener,axis,rowBitmap,angle,duration);
831
      }
832
833
///////////////////////////////////////////////////////////////////////////////////////////////////
834
835
    public void resetAllTextureMaps()
836
      {
837
      mPreRender.resetAllTextureMaps();
838
      }
839
840
///////////////////////////////////////////////////////////////////////////////////////////////////
841
842
    public TwistyObject getObject()
843
      {
844
      return mPreRender.getObject();
845
      }
846
847
///////////////////////////////////////////////////////////////////////////////////////////////////
848
849 79c7c950 Leszek Koltunski
    public OperatingSystemInterface getOS()
850
      {
851
      return mOS;
852
      }
853
854
///////////////////////////////////////////////////////////////////////////////////////////////////
855
856
    public void savePreferences()
857 9276dced Leszek Koltunski
      {
858 79c7c950 Leszek Koltunski
      mPreRender.savePreferences(mOS);
859 8e66157b Leszek Koltunski
860
      for( int i=0; i< BaseEffect.Type.LENGTH; i++ )
861
        {
862 79c7c950 Leszek Koltunski
        BaseEffect.Type.getType(i).savePreferences(mOS);
863 8e66157b Leszek Koltunski
        }
864 9276dced Leszek Koltunski
      }
865
866
///////////////////////////////////////////////////////////////////////////////////////////////////
867
868 79c7c950 Leszek Koltunski
    public void restorePreferences()
869 9276dced Leszek Koltunski
      {
870 79c7c950 Leszek Koltunski
      mPreRender.restorePreferences(mOS);
871 8e66157b Leszek Koltunski
872
      for (int i=0; i<BaseEffect.Type.LENGTH; i++)
873
        {
874 79c7c950 Leszek Koltunski
        BaseEffect.Type.getType(i).restorePreferences(mOS);
875 8e66157b Leszek Koltunski
        }
876 880beeea Leszek Koltunski
      }
877 c3a033e9 Leszek Koltunski
878 b9956428 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
879
880 81141862 Leszek Koltunski
    public boolean retLocked()
881 b9956428 Leszek Koltunski
      {
882
      return mIsLocked;
883
      }
884
885
///////////////////////////////////////////////////////////////////////////////////////////////////
886
887 81141862 Leszek Koltunski
    public void toggleLock()
888 b9956428 Leszek Koltunski
      {
889
      mIsLocked = !mIsLocked;
890
      }
891
892
///////////////////////////////////////////////////////////////////////////////////////////////////
893
894 81141862 Leszek Koltunski
    public void unlock()
895
      {
896
      mIsLocked = false;
897
      }
898 b9956428 Leszek Koltunski
899
///////////////////////////////////////////////////////////////////////////////////////////////////
900
901 81141862 Leszek Koltunski
    public void setLock(boolean value)
902
      {
903
      mRemLocked = mIsLocked;
904
      mIsLocked = value;
905
      }
906 b9956428 Leszek Koltunski
907
///////////////////////////////////////////////////////////////////////////////////////////////////
908
909 81141862 Leszek Koltunski
    public void unsetLock()
910
      {
911
      mIsLocked = mRemLocked;
912
      }
913 880beeea Leszek Koltunski
914 11fa413d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
915
916
    public void setTextureMap(int cubit, int face, int newColor)
917
      {
918
      mPreRender.setTextureMap(cubit,face,newColor);
919
      }
920
921 880beeea Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
922
923 82b0cf8e Leszek Koltunski
    public boolean onTouchEvent(int mode)
924 880beeea Leszek Koltunski
      {
925 611940ac Leszek Koltunski
      if( mode!=MODE_NOTHING )
926
        {
927
        if( mObjectNode==null ) return true;
928 53e85349 Leszek Koltunski
929 7c546131 Leszek Koltunski
        if( mode!=mLastMode )
930 611940ac Leszek Koltunski
          {
931 2832c2fa Leszek Koltunski
          TwistyObject object = getObject();
932
933
          if( object!=null )
934
            {
935
            mLastMode = mode;
936
            setTouchControl(object);
937
            }
938
          else return true;
939 611940ac Leszek Koltunski
          }
940 11fa413d Leszek Koltunski
941 82b0cf8e Leszek Koltunski
        int action = mOS.getAction();
942 92d6c2f1 Leszek Koltunski
943 611940ac Leszek Koltunski
        switch(action)
944
          {
945 82b0cf8e Leszek Koltunski
          case ACTION_DOWN_1: prepareDown();
946
                              actionDown(mX1, mY1);
947
                              break;
948
          case ACTION_MOVE  : prepareMove();
949
                              actionMove(mX1, mY1, mX2, mY2);
950
                              break;
951
          case ACTION_UP_1  : prepareUp();
952
                              actionUp();
953
                              break;
954
          case ACTION_DOWN_2: prepareDown2();
955
                              actionDown2(mX1, mY1, mX2, mY2);
956
                              break;
957
          case ACTION_UP_2  : prepareUp2();
958
                              boolean p1isUp = !mOS.isFirstPressed();
959
                              boolean p2isUp = !mOS.isSecondPressed();
960
                              actionUp2(p1isUp, mX1, mY1, p2isUp, mX2, mY2);
961
                              break;
962 611940ac Leszek Koltunski
          }
963
        }
964 880beeea Leszek Koltunski
965
      return true;
966
      }
967
}