Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / main / ObjectPreRender.java @ e8d8c12a

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 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 java.io.InputStream;
13

    
14
import android.app.Activity;
15
import android.content.SharedPreferences;
16

    
17
import org.distorted.library.message.EffectListener;
18
import org.distorted.library.type.Static3D;
19

    
20
import org.distorted.library.type.Static4D;
21
import org.distorted.objectlib.helpers.ObjectLibInterface;
22
import org.distorted.objectlib.effects.BaseEffect;
23
import org.distorted.objectlib.effects.scramble.ScrambleEffect;
24
import org.distorted.objectlib.helpers.BlockController;
25
import org.distorted.objectlib.helpers.MovesFinished;
26
import org.distorted.objectlib.shape.ShapeDodecahedron;
27
import org.distorted.objectlib.shape.ShapeHexahedron;
28
import org.distorted.objectlib.shape.ShapeOctahedron;
29
import org.distorted.objectlib.shape.ShapeTetrahedron;
30

    
31
///////////////////////////////////////////////////////////////////////////////////////////////////
32

    
33
public class ObjectPreRender implements EffectListener
34
  {
35
  private static final int MAX_SLOW_SCRAMBLE = 50;
36

    
37
  private final ObjectControl mController;
38
  private InputStream mJsonStream, mMeshStream;
39
  private int mOrdinal;
40
  private TwistyObject mOldObject, mNewObject;
41
  private SharedPreferences mPreferences;
42
  private MovesFinished mAddActionListener;
43
  private final BlockController mBlockController;
44
  private final ObjectLibInterface mInterface;
45
  private String mDebug;
46
  private float mMoveX, mMoveY;
47
  private float mScale;
48

    
49
  private boolean mFinishRotation, mRemoveRotation, mRemovePatternRotation, mAddRotation,
50
                  mSetQuat, mChangeObject, mSolveObject, mScrambleObject, mFastScrambleObject, mPresentObject,
51
                  mInitializeObject, mSetTextureMap, mResetAllTextureMaps, mSolve, mApplyScrambles;
52
  private boolean mScramblingAndSolvingBlocked, mRotationBlocked, mIsSolved;
53
  private long mRotationFinishedID;
54
  private final long[] mEffectID;
55
  private int[][] mNextMoves;
56
  private int mScrambleObjectNum, mScrambleObjectDuration;
57
  private int mAddRotationAxis, mAddRotationRowBitmap, mAddRotationAngle;
58
  private long mAddRotationDuration;
59
  private int mPresentDuration;
60
  private long mAddRotationID, mRemoveRotationID;
61
  private int mCubit, mFace, mNewColor;
62
  private int mNearestAngle;
63
  private long mScrambleStartTime, mScrambleEndTime;
64
  private int mMeshState, mIconMode;
65

    
66
  // debugging only
67
  private long mAddRotationTime;
68

    
69
///////////////////////////////////////////////////////////////////////////////////////////////////
70

    
71
  public ObjectPreRender(Activity act, ObjectControl controller, ObjectLibInterface actioner)
72
    {
73
    mInterface = actioner;
74
    mController = controller;
75

    
76
    mFinishRotation       = false;
77
    mRemoveRotation       = false;
78
    mRemovePatternRotation= false;
79
    mAddRotation          = false;
80
    mSetQuat              = false;
81
    mChangeObject         = false;
82
    mSolveObject          = false;
83
    mSolve                = false;
84
    mScrambleObject       = false;
85
    mFastScrambleObject   = false;
86
    mPresentObject        = false;
87

    
88
    mOldObject = null;
89
    mNewObject = null;
90

    
91
    mDebug = "";
92
    mScrambleObjectNum = 0;
93
    mScale = 1.0f;
94

    
95
    mEffectID = new long[BaseEffect.Type.LENGTH];
96

    
97
    mBlockController = new BlockController(act,this);
98
    unblockEverything();
99
    }
100

    
101
///////////////////////////////////////////////////////////////////////////////////////////////////
102

    
103
  private void createObjectNow(int ordinal, int meshState, int iconMode, InputStream jsonStream, InputStream meshStream)
104
    {
105
    long time1 = System.currentTimeMillis();
106
    Static3D move = new Static3D(mMoveX,mMoveY,0);
107
    Static4D quat = mController.getQuat();
108
    TwistyObject tmp;
109
    boolean error = false;
110

    
111
    if( jsonStream==null )
112
      {
113
      tmp = ObjectType.create( ordinal, meshState, iconMode, quat, move, mScale, meshStream);
114
      }
115
    else
116
      {
117
      tmp = new TwistyJson( jsonStream, meshState, iconMode, quat, move, mScale, meshStream);
118
      error = tmp.getError();
119
      }
120

    
121
    if( error )
122
      {
123
      String errorString = tmp.getErrorString();
124
      mInterface.reportJSONError(errorString,ordinal);
125
      }
126
    else
127
      {
128
      if( mOldObject!=null ) mOldObject.releaseResources();
129
      mOldObject = mNewObject;
130
      mNewObject = tmp;
131

    
132
      long time2 = System.currentTimeMillis();
133
      mInterface.onObjectCreated(time2-time1);
134

    
135
      if( mNewObject!=null )
136
        {
137
        mNewObject.setLibInterface(mInterface);
138
        mController.setTouchControl(mNewObject);
139
        mNewObject.setObjectRatioNow(mScale, mController.getScalingSize() );
140

    
141
        if( mPreferences!=null )
142
          {
143
          mNewObject.restorePreferences(mPreferences);
144
          mPreferences = null;
145
          }
146

    
147
        mIsSolved = mNewObject.isSolved();
148
        }
149
      }
150
    }
151

    
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153
// do all 'adjustable' effects (SizeChange, Solve, Scramble)
154

    
155
  private void doEffectNow(BaseEffect.Type type, int duration)
156
    {
157
    try
158
      {
159
      int index = type.ordinal();
160
      mEffectID[index] = type.startEffect(this,duration);
161
      }
162
    catch( Exception ex )
163
      {
164
      android.util.Log.e("renderer", "exception starting effect: "+ex.getMessage());
165
      unblockEverything();
166
      }
167
    }
168

    
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170

    
171
  private void removeRotationNow()
172
    {
173
    mRemoveRotation=false;
174
    mNewObject.removeRotationNow();
175

    
176
    boolean solved = mNewObject.isSolved();
177

    
178
    if( solved && !mIsSolved )
179
      {
180
      mInterface.onSolved();
181
      unblockEverything();
182
      int duration = BaseEffect.Type.WIN.getDuration();
183
      doEffectNow( BaseEffect.Type.WIN, duration );
184
      }
185
    else
186
      {
187
      unblockEverything();
188
      }
189

    
190
    mIsSolved = solved;
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

    
195
  private void removeRotation()
196
    {
197
    mRemoveRotation = true;
198
    }
199

    
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201

    
202
  private void removePatternRotation()
203
    {
204
    mRemovePatternRotation = true;
205
    }
206

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

    
209
  private void removePatternRotationNow()
210
    {
211
    mRemovePatternRotation=false;
212
    mNewObject.removeRotationNow();
213
    mAddActionListener.onActionFinished(mRemoveRotationID);
214
    }
215

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

    
218
  private void addRotationNow()
219
    {
220
    mAddRotation = false;
221

    
222
    if( mNewObject.getNumAxis() > mAddRotationAxis )
223
      {
224
      mAddRotationID = mNewObject.addNewRotation( mAddRotationAxis, mAddRotationRowBitmap,
225
                                                  mAddRotationAngle, mAddRotationDuration, this);
226

    
227
      if( mAddRotationID==0 ) // failed to add effect - should never happen
228
        {
229
        unblockEverything();
230
        }
231
      }
232
    else // should never happen but Firebase says it sometimes does
233
      {
234
      long timeNow = System.currentTimeMillis();
235
      Class<? extends MovesFinished> clazz = mAddActionListener.getClass();
236
      String name = clazz.getSimpleName();
237

    
238
      String error = "time now: "+timeNow+" add time: "+mAddRotationTime+" axis="+mAddRotationAxis+
239
                      "object: "+mNewObject.getShortName()+" "+name;
240

    
241
      mInterface.reportProblem(error,true);
242
      unblockEverything();
243
      }
244
    }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247

    
248
  private void finishRotationNow()
249
    {
250
    mFinishRotation = false;
251
    blockEverything(BlockController.PLACE_0);
252
    mRotationFinishedID = mNewObject.finishRotationNow(this, mNearestAngle);
253

    
254
    if( mRotationFinishedID==0 ) // failed to add effect - should never happen
255
      {
256
      unblockEverything();
257
      }
258
    }
259

    
260
///////////////////////////////////////////////////////////////////////////////////////////////////
261

    
262
  private void changeObjectNow()
263
    {
264
    mChangeObject = false;
265
    blockEverything(BlockController.PLACE_1);
266
    createObjectNow(mOrdinal,mMeshState,mIconMode,mJsonStream,mMeshStream);
267
    int duration = BaseEffect.Type.SIZECHANGE.getDuration();
268
    doEffectNow( BaseEffect.Type.SIZECHANGE, duration );
269
    }
270

    
271
///////////////////////////////////////////////////////////////////////////////////////////////////
272

    
273
  private void scrambleObjectNow()
274
    {
275
    mScrambleObject = false;
276
    mIsSolved       = false;
277
    blockEverything(BlockController.PLACE_3);
278

    
279
    if( mScrambleObjectNum<MAX_SLOW_SCRAMBLE )
280
      {
281
      int duration = BaseEffect.Type.SCRAMBLE.getDuration();
282
      doEffectNow( BaseEffect.Type.SCRAMBLE, duration );
283
      }
284
    else
285
      {
286
      int duration = BaseEffect.Type.FAST_SCRAMBLE.getDuration();
287
      doEffectNow( BaseEffect.Type.FAST_SCRAMBLE, duration );
288
      }
289
    }
290

    
291
///////////////////////////////////////////////////////////////////////////////////////////////////
292

    
293
  private void fastScrambleObjectNow()
294
    {
295
    mFastScrambleObject = false;
296
    mIsSolved           = false;
297
    blockEverything(BlockController.PLACE_5);
298
    doEffectNow( BaseEffect.Type.FAST_SCRAMBLE, mScrambleObjectDuration );
299
    }
300

    
301
///////////////////////////////////////////////////////////////////////////////////////////////////
302

    
303
  private void presentObjectNow()
304
    {
305
    mPresentObject = false;
306
    doEffectNow( BaseEffect.Type.PRESENT, mPresentDuration );
307
    }
308

    
309
///////////////////////////////////////////////////////////////////////////////////////////////////
310

    
311
  private void solveObjectNow()
312
    {
313
    mSolveObject = false;
314
    blockEverything(BlockController.PLACE_4);
315
    int duration = BaseEffect.Type.SOLVE.getDuration();
316
    doEffectNow( BaseEffect.Type.SOLVE, duration );
317
    }
318

    
319
///////////////////////////////////////////////////////////////////////////////////////////////////
320

    
321
  private void solveNow()
322
    {
323
    mSolve = false;
324
    if( mNewObject!=null ) mNewObject.solve();
325
    }
326

    
327
///////////////////////////////////////////////////////////////////////////////////////////////////
328

    
329
  private void initializeObjectNow()
330
    {
331
    mInitializeObject = false;
332
    mNewObject.initializeObject(mNextMoves);
333
    }
334

    
335
///////////////////////////////////////////////////////////////////////////////////////////////////
336

    
337
  private void applyScramblesNow()
338
    {
339
    mApplyScrambles = false;
340
    mNewObject.applyScrambles(mNextMoves);
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

    
345
  private void setTextureMapNow()
346
    {
347
    mSetTextureMap = false;
348

    
349
    if( mNewObject!=null ) mNewObject.setTextureMap(mCubit,mFace,mNewColor);
350
    }
351

    
352
///////////////////////////////////////////////////////////////////////////////////////////////////
353

    
354
  private void resetAllTextureMapsNow()
355
    {
356
    mResetAllTextureMaps = false;
357
    if( mNewObject!=null ) mNewObject.resetAllTextureMaps();
358
    }
359

    
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361

    
362
  private void setQuatNow()
363
    {
364
    mSetQuat = false;
365
    mController.setQuat();
366
    }
367

    
368
///////////////////////////////////////////////////////////////////////////////////////////////////
369

    
370
  private int computeRowFromBitmap(int rowBitmap)
371
    {
372
    int index = 0;
373

    
374
    while(index<32)
375
      {
376
      if( (rowBitmap&0x1) != 0 ) return index;
377
      rowBitmap>>=1;
378
      index++;
379
      }
380

    
381
    return 0;
382
    }
383

    
384
///////////////////////////////////////////////////////////////////////////////////////////////////
385

    
386
  private void blockEverything(int place)
387
    {
388
    mScramblingAndSolvingBlocked = true;
389
    mRotationBlocked = true;
390
    mBlockController.rotationBlocked(place);
391
    mBlockController.scramblingAndSolvingBlocked(place);
392
    }
393

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

    
396
  private void unblockEverything()
397
    {
398
    mScramblingAndSolvingBlocked = false;
399
    mRotationBlocked = false;
400
    mBlockController.rotationUnblocked();
401
    mBlockController.scramblingAndSolvingUnblocked();
402
    }
403

    
404
///////////////////////////////////////////////////////////////////////////////////////////////////
405

    
406
  void rememberMove(int axis, int row, int angle)
407
    {
408
    mDebug += (mNewObject==null ? "[null]" : mNewObject.reportState() );
409
    mDebug += ("(m "+axis+" "+(1<<row)+" "+angle+" "+(System.currentTimeMillis()-mScrambleEndTime))+")";
410
    }
411

    
412
///////////////////////////////////////////////////////////////////////////////////////////////////
413

    
414
  void finishRotation(int nearestAngle)
415
    {
416
    mNearestAngle   = nearestAngle;
417
    mFinishRotation = true;
418
    }
419

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

    
422
  void setTextureMap(int cubit, int face, int newColor)
423
    {
424
    mSetTextureMap = true;
425

    
426
    mCubit    = cubit;
427
    mFace     = face;
428
    mNewColor = newColor;
429
    }
430

    
431
///////////////////////////////////////////////////////////////////////////////////////////////////
432

    
433
  void setQuatOnNextRender()
434
    {
435
    mSetQuat = true;
436
    }
437

    
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439

    
440
  void setMove(float xmove, float ymove)
441
    {
442
    mMoveX = xmove;
443
    mMoveY = ymove;
444
    }
445

    
446
///////////////////////////////////////////////////////////////////////////////////////////////////
447

    
448
  void setScale(float scale)
449
    {
450
    mScale = scale;
451
    }
452

    
453
///////////////////////////////////////////////////////////////////////////////////////////////////
454
// INTERNAL API
455
///////////////////////////////////////////////////////////////////////////////////////////////////
456

    
457
  public int getNumScrambles()
458
    {
459
    return mScrambleObjectNum;
460
    }
461

    
462
///////////////////////////////////////////////////////////////////////////////////////////////////
463

    
464
  public TwistyObject getOldObject()
465
    {
466
    return mOldObject;
467
    }
468

    
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470

    
471
  public float getMoveX()
472
    {
473
    return mMoveX;
474
    }
475

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

    
478
  public float getMoveY()
479
    {
480
    return mMoveY;
481
    }
482

    
483
///////////////////////////////////////////////////////////////////////////////////////////////////
484

    
485
  public ObjectLibInterface getInterface()
486
    {
487
    return mInterface;
488
    }
489

    
490
///////////////////////////////////////////////////////////////////////////////////////////////////
491
// PUBLIC API
492
///////////////////////////////////////////////////////////////////////////////////////////////////
493

    
494
  public void savePreferences(SharedPreferences.Editor editor)
495
    {
496
    if( mNewObject!=null )
497
      {
498
      mNewObject.savePreferences(editor);
499
      }
500
    }
501

    
502
///////////////////////////////////////////////////////////////////////////////////////////////////
503

    
504
  public void restorePreferences(SharedPreferences preferences)
505
    {
506
    mPreferences = preferences;
507
    }
508

    
509
///////////////////////////////////////////////////////////////////////////////////////////////////
510

    
511
  public void changeObject(int ordinal, int meshState, int iconMode, InputStream jsonStream, InputStream meshStream)
512
    {
513
    mChangeObject = true;
514
    mOrdinal    = ordinal;
515
    mMeshState  = meshState;
516
    mIconMode   = iconMode;
517
    mJsonStream = jsonStream;
518
    mMeshStream = meshStream;
519
    }
520

    
521
///////////////////////////////////////////////////////////////////////////////////////////////////
522

    
523
  public void setDefaultRotation(int numFaces)
524
    {
525
    if( mController!=null && mController.getRotateOnCreation() )
526
      {
527
      switch(numFaces)
528
        {
529
        case  4: mController.rotateNow(ShapeTetrahedron.DEFAULT_ROT ); break;
530
        case  6: mController.rotateNow(ShapeHexahedron.DEFAULT_ROT  ); break;
531
        case  8: mController.rotateNow(ShapeOctahedron.DEFAULT_ROT  ); break;
532
        case 12: mController.rotateNow(ShapeDodecahedron.DEFAULT_ROT); break;
533
        }
534
      }
535
    }
536

    
537
///////////////////////////////////////////////////////////////////////////////////////////////////
538

    
539
  public boolean isRotationBlocked()
540
    {
541
    return mRotationBlocked;
542
    }
543

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

    
546
  public boolean isScramblingAndSolvingNotBlocked()
547
    {
548
    return !mScramblingAndSolvingBlocked;
549
    }
550

    
551
///////////////////////////////////////////////////////////////////////////////////////////////////
552

    
553
  public void blockRotation(int place)
554
    {
555
    mRotationBlocked = true;
556
    mBlockController.rotationBlocked(place);
557
    }
558

    
559
///////////////////////////////////////////////////////////////////////////////////////////////////
560

    
561
  public void unblockRotation()
562
    {
563
    mRotationBlocked = false;
564
    mBlockController.rotationUnblocked();
565
    }
566

    
567
///////////////////////////////////////////////////////////////////////////////////////////////////
568

    
569
  public void unblockScramblingAndSolving()
570
    {
571
    mScramblingAndSolvingBlocked = false;
572
    mBlockController.scramblingAndSolvingUnblocked();
573
    }
574

    
575
///////////////////////////////////////////////////////////////////////////////////////////////////
576

    
577
  public void preRender()
578
    {
579
    if( mSolve                 ) solveNow();
580
    if( mSetQuat               ) setQuatNow();
581
    if( mFinishRotation        ) finishRotationNow();
582
    if( mRemoveRotation        ) removeRotationNow();
583
    if( mRemovePatternRotation ) removePatternRotationNow();
584
    if( mChangeObject          ) changeObjectNow();
585
    if( mSolveObject           ) solveObjectNow();
586
    if( mScrambleObject        ) scrambleObjectNow();
587
    if( mFastScrambleObject    ) fastScrambleObjectNow();
588
    if( mPresentObject         ) presentObjectNow();
589
    if( mAddRotation           ) addRotationNow();
590
    if( mInitializeObject      ) initializeObjectNow();
591
    if( mApplyScrambles        ) applyScramblesNow();
592
    if( mResetAllTextureMaps   ) resetAllTextureMapsNow();
593
    if( mSetTextureMap         ) setTextureMapNow();
594
    }
595

    
596
///////////////////////////////////////////////////////////////////////////////////////////////////
597

    
598
  public void addRotation(MovesFinished listener, int axis, int rowBitmap, int bareAngle, int millPreDegree)
599
    {
600
    int[][] basicAngles = mNewObject==null ? null : mNewObject.getBasicAngles();
601
    int length = basicAngles==null ? 0 : basicAngles.length;
602

    
603
    if( axis<length )
604
      {
605
      mAddRotation = true;
606
      int row = computeRowFromBitmap(rowBitmap);
607

    
608
      if( row<basicAngles[axis].length )
609
        {
610
        int basicAngle= basicAngles[axis][row];
611
        int angle     = bareAngle*(360/basicAngle);
612
        int duration  = Math.abs(angle)*millPreDegree;
613

    
614
        mAddActionListener    = listener;
615
        mAddRotationAxis      = axis;
616
        mAddRotationRowBitmap = rowBitmap;
617
        mAddRotationAngle     = angle;
618
        mAddRotationDuration  = duration;
619
        mAddRotationTime      = System.currentTimeMillis();
620

    
621
        if( listener instanceof ScrambleEffect )
622
          {
623
          mDebug += (mNewObject==null ? "null" : mNewObject.reportState() );
624
          mDebug += ("(a "+axis+" "+rowBitmap+" "+angle+" "+(mAddRotationTime-mScrambleStartTime))+")";
625
          }
626
        }
627
      }
628
    }
629

    
630
///////////////////////////////////////////////////////////////////////////////////////////////////
631

    
632
  public void initializeObject(int[][] moves)
633
    {
634
    mInitializeObject = true;
635
    mNextMoves = moves;
636
    }
637

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

    
640
  public void applyScrambles(int[][] moves)
641
    {
642
    mApplyScrambles = true;
643
    mNextMoves = moves;
644
    }
645

    
646
///////////////////////////////////////////////////////////////////////////////////////////////////
647

    
648
  public void scrambleObject(int num)
649
    {
650
    if( !mScramblingAndSolvingBlocked )
651
      {
652
      mScrambleObject = true;
653
      mScrambleObjectNum = num;
654
      mDebug = "";
655
      mScrambleStartTime = System.currentTimeMillis();
656
      }
657
    }
658

    
659
///////////////////////////////////////////////////////////////////////////////////////////////////
660

    
661
  public void fastScrambleObject(int duration, int num)
662
    {
663
    if( !mScramblingAndSolvingBlocked )
664
      {
665
      mFastScrambleObject = true;
666
      mScrambleObjectNum = num;
667
      mScrambleObjectDuration = duration;
668
      mDebug = "";
669
      mScrambleStartTime = System.currentTimeMillis();
670
      }
671
    }
672

    
673
///////////////////////////////////////////////////////////////////////////////////////////////////
674

    
675
  public void presentObject(int num, int duration)
676
    {
677
    mScrambleObjectNum = num;
678
    mPresentDuration = duration;
679
    mPresentObject = true;
680
    }
681

    
682
///////////////////////////////////////////////////////////////////////////////////////////////////
683
// this starts the Solve Effect
684

    
685
  public void solveObject()
686
    {
687
    if( !mScramblingAndSolvingBlocked )
688
      {
689
      mSolveObject = true;
690
      }
691
    }
692

    
693
///////////////////////////////////////////////////////////////////////////////////////////////////
694
// this only sets the cubits state to solved
695

    
696
  public void solveOnly()
697
    {
698
    mSolve = true;
699
    }
700

    
701
///////////////////////////////////////////////////////////////////////////////////////////////////
702

    
703
  public void resetAllTextureMaps()
704
    {
705
    mResetAllTextureMaps = true;
706
    }
707

    
708
///////////////////////////////////////////////////////////////////////////////////////////////////
709

    
710
  public TwistyObject getObject()
711
    {
712
    return mNewObject;
713
    }
714

    
715
///////////////////////////////////////////////////////////////////////////////////////////////////
716

    
717
  public TwistyObjectNode getObjectNode()
718
    {
719
    return mController.getNode();
720
    }
721

    
722
///////////////////////////////////////////////////////////////////////////////////////////////////
723

    
724
  public void effectFinished(final long effectID)
725
    {
726
    if( effectID == mRotationFinishedID )
727
      {
728
      mRotationFinishedID = 0;
729
      removeRotation();
730
      }
731
    else if( effectID == mAddRotationID )
732
      {
733
      mAddRotationID = 0;
734
      mRemoveRotationID = effectID;
735
      removePatternRotation();
736
      }
737
    else
738
      {
739
      for(int i=0; i<BaseEffect.Type.LENGTH; i++)
740
        {
741
        if( effectID == mEffectID[i] )
742
          {
743
          if( i!=BaseEffect.Type.WIN.ordinal()      )
744
            {
745
            unblockEverything();
746
            }
747
          if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
748
            {
749
            mScrambleEndTime = System.currentTimeMillis();
750
            mInterface.onScrambleEffectFinished();
751
            }
752
          if( i==BaseEffect.Type.WIN.ordinal()      )
753
            {
754
            mInterface.onWinEffectFinished(mScrambleStartTime,mScrambleEndTime-mScrambleStartTime,mDebug,mScrambleObjectNum);
755
            }
756
          break;
757
          }
758
        }
759
      }
760
    }
761
  }
(4-4/9)