Project

General

Profile

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

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

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

    
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28

    
29
public class ObjectPreRender implements EffectListener
30
  {
31
  private final ObjectControl mController;
32
  private InputStream mJsonStream, mMeshStream;
33
  private int mOrdinal;
34
  private TwistyObject mOldObject, mNewObject;
35
  private SharedPreferences mPreferences;
36
  private MovesFinished mAddActionListener;
37
  private final BlockController mBlockController;
38
  private final ObjectLibInterface mInterface;
39
  private String mDebug;
40
  private float mMoveX, mMoveY;
41
  private float mScale;
42

    
43
  private boolean mFinishRotation, mRemoveRotation, mRemovePatternRotation, mAddRotation,
44
                  mSetQuat, mChangeObject, mSolveObject, mScrambleObject, mFastScrambleObject,
45
                  mInitializeObject, mSetTextureMap, mResetAllTextureMaps, mSolve, mApplyScrambles;
46
  private boolean mUIBlocked, mTouchBlocked, mIsSolved;
47
  private long mRotationFinishedID;
48
  private final long[] mEffectID;
49
  private int[][] mNextMoves;
50
  private int mScrambleObjectNum;
51
  private int mAddRotationAxis, mAddRotationRowBitmap, mAddRotationAngle;
52
  private long mAddRotationDuration;
53
  private long mAddRotationID, mRemoveRotationID;
54
  private int mCubit, mFace, mNewColor;
55
  private int mNearestAngle;
56
  private long mScrambleStartTime, mScrambleEndTime;
57
  private int mMeshState, mIconMode;
58

    
59
  // debugging only
60
  private long mAddRotationTime;
61

    
62
///////////////////////////////////////////////////////////////////////////////////////////////////
63

    
64
  public ObjectPreRender(Activity act, ObjectControl controller, ObjectLibInterface actioner)
65
    {
66
    mInterface = actioner;
67
    mController = controller;
68

    
69
    mFinishRotation       = false;
70
    mRemoveRotation       = false;
71
    mRemovePatternRotation= false;
72
    mAddRotation          = false;
73
    mSetQuat              = false;
74
    mChangeObject         = false;
75
    mSolveObject          = false;
76
    mSolve                = false;
77
    mScrambleObject       = false;
78
    mFastScrambleObject   = false;
79

    
80
    mOldObject = null;
81
    mNewObject = null;
82

    
83
    mDebug = "";
84
    mScrambleObjectNum = 0;
85
    mScale = 1.0f;
86

    
87
    mEffectID = new long[BaseEffect.Type.LENGTH];
88

    
89
    mBlockController = new BlockController(act,this);
90
    unblockEverything();
91
    }
92

    
93
///////////////////////////////////////////////////////////////////////////////////////////////////
94

    
95
  private void createObjectNow(int ordinal, int meshState, int iconMode, InputStream jsonStream, InputStream meshStream)
96
    {
97
    long time1 = System.currentTimeMillis();
98
    Static3D move = new Static3D(mMoveX,mMoveY,0);
99
    Static4D quat = mController.getQuat();
100
    TwistyObject tmp;
101
    boolean error = false;
102

    
103
    if( jsonStream==null )
104
      {
105
      tmp = ObjectType.create( ordinal, meshState, iconMode, quat, move, mScale, meshStream);
106
      }
107
    else
108
      {
109
      tmp = new TwistyJson( jsonStream, meshState, iconMode, quat, move, mScale, meshStream);
110
      error = tmp.getError();
111
      }
112

    
113
    if( error )
114
      {
115
      String errorString = tmp.getErrorString();
116
      mInterface.reportJSONError(errorString,ordinal);
117
      }
118
    else
119
      {
120
      if( mOldObject!=null ) mOldObject.releaseResources();
121
      mOldObject = mNewObject;
122
      mNewObject = tmp;
123

    
124
      long time2 = System.currentTimeMillis();
125
      mInterface.onObjectCreated(time2-time1);
126

    
127
      if( mNewObject!=null )
128
        {
129
        mNewObject.setLibInterface(mInterface);
130
        mController.setTouchControl(mNewObject);
131
        TwistyObjectNode node = mController.getNode();
132
        if( node!=null ) mNewObject.setObjectRatioNow(mScale, node.getMinSize() );
133

    
134
        if( mPreferences!=null )
135
          {
136
          mNewObject.restorePreferences(mPreferences);
137
          mPreferences = null;
138
          }
139

    
140
        mIsSolved = mNewObject.isSolved();
141
        }
142
      }
143
    }
144

    
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146
// do all 'adjustable' effects (SizeChange, Solve, Scramble)
147

    
148
  private void doEffectNow(BaseEffect.Type type)
149
    {
150
    try
151
      {
152
      int index = type.ordinal();
153
      mEffectID[index] = type.startEffect(this);
154
      }
155
    catch( Exception ex )
156
      {
157
      android.util.Log.e("renderer", "exception starting effect: "+ex.getMessage());
158
      unblockEverything();
159
      }
160
    }
161

    
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163

    
164
  private void removeRotationNow()
165
    {
166
    mRemoveRotation=false;
167
    mNewObject.removeRotationNow();
168

    
169
    boolean solved = mNewObject.isSolved();
170

    
171
    if( solved && !mIsSolved )
172
      {
173
      mInterface.onSolved();
174
      unblockEverything();
175
      doEffectNow( BaseEffect.Type.WIN );
176
      }
177
    else
178
      {
179
      unblockEverything();
180
      }
181

    
182
    mIsSolved = solved;
183
    }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186

    
187
  private void removeRotation()
188
    {
189
    mRemoveRotation = true;
190
    }
191

    
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193

    
194
  private void removePatternRotation()
195
    {
196
    mRemovePatternRotation = true;
197
    }
198

    
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200

    
201
  private void removePatternRotationNow()
202
    {
203
    mRemovePatternRotation=false;
204
    mNewObject.removeRotationNow();
205
    mAddActionListener.onActionFinished(mRemoveRotationID);
206
    }
207

    
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

    
210
  private void addRotationNow()
211
    {
212
    mAddRotation = false;
213

    
214
    if( mNewObject.mNumAxis > mAddRotationAxis )
215
      {
216
      mAddRotationID = mNewObject.addNewRotation( mAddRotationAxis, mAddRotationRowBitmap,
217
                                                  mAddRotationAngle, mAddRotationDuration, this);
218

    
219
      if( mAddRotationID==0 ) // failed to add effect - should never happen
220
        {
221
        unblockEverything();
222
        }
223
      }
224
    else // should never happen but Firebase says it sometimes does
225
      {
226
      long timeNow = System.currentTimeMillis();
227
      Class<? extends MovesFinished> clazz = mAddActionListener.getClass();
228
      String name = clazz.getSimpleName();
229

    
230
      String error = "time now: "+timeNow+" add time: "+mAddRotationTime+" axis="+mAddRotationAxis+
231
                      "object: "+mNewObject.getShortName()+" "+name;
232

    
233
      mInterface.reportProblem(error,true);
234
      unblockEverything();
235
      }
236
    }
237

    
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239

    
240
  private void finishRotationNow()
241
    {
242
    mFinishRotation = false;
243
    blockEverything(BlockController.PLACE_0);
244
    mRotationFinishedID = mNewObject.finishRotationNow(this, mNearestAngle);
245

    
246
    if( mRotationFinishedID==0 ) // failed to add effect - should never happen
247
      {
248
      unblockEverything();
249
      }
250
    }
251

    
252
///////////////////////////////////////////////////////////////////////////////////////////////////
253

    
254
  private void changeObjectNow()
255
    {
256
    mChangeObject = false;
257
    blockEverything(BlockController.PLACE_1);
258
    createObjectNow(mOrdinal,mMeshState,mIconMode,mJsonStream,mMeshStream);
259
    doEffectNow( BaseEffect.Type.SIZECHANGE );
260
    }
261

    
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263

    
264
  private void scrambleObjectNow()
265
    {
266
    mScrambleObject = false;
267
    mIsSolved       = false;
268
    blockEverything(BlockController.PLACE_3);
269
    doEffectNow( BaseEffect.Type.SCRAMBLE );
270
    }
271

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273

    
274
  private void fastScrambleObjectNow()
275
    {
276
    mFastScrambleObject = false;
277
    mIsSolved           = false;
278
    blockEverything(BlockController.PLACE_5);
279
    doEffectNow( BaseEffect.Type.FAST_SCRAMBLE );
280
    }
281

    
282
///////////////////////////////////////////////////////////////////////////////////////////////////
283

    
284
  private void solveObjectNow()
285
    {
286
    mSolveObject = false;
287
    blockEverything(BlockController.PLACE_4);
288
    doEffectNow( BaseEffect.Type.SOLVE );
289
    }
290

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

    
293
  private void solveNow()
294
    {
295
    mSolve = false;
296
    if( mNewObject!=null ) mNewObject.solve();
297
    }
298

    
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

    
301
  private void initializeObjectNow()
302
    {
303
    mInitializeObject = false;
304
    mNewObject.initializeObject(mNextMoves);
305
    }
306

    
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308

    
309
  private void applyScramblesNow()
310
    {
311
    mApplyScrambles = false;
312
    mNewObject.applyScrambles(mNextMoves);
313
    }
314

    
315
///////////////////////////////////////////////////////////////////////////////////////////////////
316

    
317
  private void setTextureMapNow()
318
    {
319
    mSetTextureMap = false;
320

    
321
    if( mNewObject!=null ) mNewObject.setTextureMap(mCubit,mFace,mNewColor);
322
    }
323

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

    
326
  private void resetAllTextureMapsNow()
327
    {
328
    mResetAllTextureMaps = false;
329
    if( mNewObject!=null ) mNewObject.resetAllTextureMaps();
330
    }
331

    
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333

    
334
  private void setQuatNow()
335
    {
336
    mSetQuat = false;
337
    mController.setQuat();
338
    }
339

    
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341

    
342
  private int computeRowFromBitmap(int rowBitmap)
343
    {
344
    int index = 0;
345

    
346
    while(index<32)
347
      {
348
      if( (rowBitmap&0x1) != 0 ) return index;
349
      rowBitmap>>=1;
350
      index++;
351
      }
352

    
353
    return 0;
354
    }
355

    
356
///////////////////////////////////////////////////////////////////////////////////////////////////
357

    
358
  void rememberMove(int axis, int row, int angle)
359
    {
360
    mDebug += (mNewObject==null ? "[null]" : mNewObject.reportState() );
361
    mDebug += ("(m "+axis+" "+(1<<row)+" "+angle+" "+(System.currentTimeMillis()-mScrambleEndTime))+")";
362
    }
363

    
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365

    
366
  void finishRotation(int nearestAngle)
367
    {
368
    mNearestAngle   = nearestAngle;
369
    mFinishRotation = true;
370
    }
371

    
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373

    
374
  void setTextureMap(int cubit, int face, int newColor)
375
    {
376
    mSetTextureMap = true;
377

    
378
    mCubit    = cubit;
379
    mFace     = face;
380
    mNewColor = newColor;
381
    }
382

    
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384

    
385
  void setQuatOnNextRender()
386
    {
387
    mSetQuat = true;
388
    }
389

    
390
///////////////////////////////////////////////////////////////////////////////////////////////////
391

    
392
  void setMove(float xmove, float ymove)
393
    {
394
    mMoveX = xmove;
395
    mMoveY = ymove;
396
    }
397

    
398
///////////////////////////////////////////////////////////////////////////////////////////////////
399

    
400
  void setScale(float scale)
401
    {
402
    mScale = scale;
403
    }
404

    
405
///////////////////////////////////////////////////////////////////////////////////////////////////
406
// INTERNAL API
407
///////////////////////////////////////////////////////////////////////////////////////////////////
408

    
409
  public int getNumScrambles()
410
    {
411
    return mScrambleObjectNum;
412
    }
413

    
414
///////////////////////////////////////////////////////////////////////////////////////////////////
415

    
416
  public TwistyObject getOldObject()
417
    {
418
    return mOldObject;
419
    }
420

    
421
///////////////////////////////////////////////////////////////////////////////////////////////////
422

    
423
  public float getMoveX()
424
    {
425
    return mMoveX;
426
    }
427

    
428
///////////////////////////////////////////////////////////////////////////////////////////////////
429

    
430
  public float getMoveY()
431
    {
432
    return mMoveY;
433
    }
434

    
435
///////////////////////////////////////////////////////////////////////////////////////////////////
436

    
437
  public ObjectLibInterface getInterface()
438
    {
439
    return mInterface;
440
    }
441

    
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443
// PUBLIC API
444
///////////////////////////////////////////////////////////////////////////////////////////////////
445

    
446
  public void savePreferences(SharedPreferences.Editor editor)
447
    {
448
    if( mNewObject!=null )
449
      {
450
      mNewObject.savePreferences(editor);
451
      }
452
    }
453

    
454
///////////////////////////////////////////////////////////////////////////////////////////////////
455

    
456
  public void restorePreferences(SharedPreferences preferences)
457
    {
458
    mPreferences = preferences;
459
    }
460

    
461
///////////////////////////////////////////////////////////////////////////////////////////////////
462

    
463
  public void changeObject(int ordinal, int meshState, int iconMode, InputStream jsonStream, InputStream meshStream)
464
    {
465
    mChangeObject = true;
466
    mOrdinal    = ordinal;
467
    mMeshState  = meshState;
468
    mIconMode   = iconMode;
469
    mJsonStream = jsonStream;
470
    mMeshStream = meshStream;
471
    }
472

    
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474

    
475
  public void setDefaultRotation(int numFaces)
476
    {
477
    if( mController!=null && mController.getRotateOnCreation() )
478
      {
479
      switch(numFaces)
480
        {
481
        case  4: mController.rotateNow(ShapeTetrahedron.DEFAULT_ROT ); break;
482
        case  6: mController.rotateNow(ShapeHexahedron.DEFAULT_ROT  ); break;
483
        case  8: mController.rotateNow(ShapeOctahedron.DEFAULT_ROT  ); break;
484
        case 12: mController.rotateNow(ShapeDodecahedron.DEFAULT_ROT); break;
485
        }
486
      }
487
    }
488

    
489
///////////////////////////////////////////////////////////////////////////////////////////////////
490

    
491
  public boolean isTouchBlocked()
492
    {
493
    return mTouchBlocked;
494
    }
495

    
496
///////////////////////////////////////////////////////////////////////////////////////////////////
497

    
498
  public boolean isUINotBlocked()
499
    {
500
    return !mUIBlocked;
501
    }
502

    
503
///////////////////////////////////////////////////////////////////////////////////////////////////
504

    
505
  public void blockEverything(int place)
506
    {
507
    mUIBlocked   = true;
508
    mTouchBlocked= true;
509
    mBlockController.touchBlocked(place);
510
    mBlockController.uiBlocked(place);
511
    }
512

    
513
///////////////////////////////////////////////////////////////////////////////////////////////////
514

    
515
  public void blockTouch(int place)
516
    {
517
    mTouchBlocked= true;
518
    mBlockController.touchBlocked(place);
519
    }
520

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

    
523
  public void unblockEverything()
524
    {
525
    mUIBlocked   = false;
526
    mTouchBlocked= false;
527
    mBlockController.touchUnblocked();
528
    mBlockController.uiUnblocked();
529
    }
530

    
531
///////////////////////////////////////////////////////////////////////////////////////////////////
532

    
533
  public void unblockTouch()
534
    {
535
    mTouchBlocked= false;
536
    mBlockController.touchUnblocked();
537
    }
538

    
539
///////////////////////////////////////////////////////////////////////////////////////////////////
540

    
541
  public void unblockUI()
542
    {
543
    mUIBlocked= false;
544
    mBlockController.uiUnblocked();
545
    }
546

    
547
///////////////////////////////////////////////////////////////////////////////////////////////////
548

    
549
  public void preRender()
550
    {
551
    if( mSolve                 ) solveNow();
552
    if( mSetQuat               ) setQuatNow();
553
    if( mFinishRotation        ) finishRotationNow();
554
    if( mRemoveRotation        ) removeRotationNow();
555
    if( mRemovePatternRotation ) removePatternRotationNow();
556
    if( mChangeObject          ) changeObjectNow();
557
    if( mSolveObject           ) solveObjectNow();
558
    if( mScrambleObject        ) scrambleObjectNow();
559
    if( mFastScrambleObject    ) fastScrambleObjectNow();
560
    if( mAddRotation           ) addRotationNow();
561
    if( mInitializeObject      ) initializeObjectNow();
562
    if( mApplyScrambles        ) applyScramblesNow();
563
    if( mResetAllTextureMaps   ) resetAllTextureMapsNow();
564
    if( mSetTextureMap         ) setTextureMapNow();
565
    }
566

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

    
569
  public void addRotation(MovesFinished listener, int axis, int rowBitmap, int bareAngle, int millPreDegree)
570
    {
571
    int[][] basicAngles = mNewObject==null ? null : mNewObject.getBasicAngles();
572
    int length = basicAngles==null ? 0 : basicAngles.length;
573

    
574
    if( axis<length )
575
      {
576
      mAddRotation = true;
577
      int row = computeRowFromBitmap(rowBitmap);
578

    
579
      if( row<basicAngles[axis].length )
580
        {
581
        int basicAngle= basicAngles[axis][row];
582
        int angle     = bareAngle*(360/basicAngle);
583
        int duration  = Math.abs(angle)*millPreDegree;
584

    
585
        mAddActionListener    = listener;
586
        mAddRotationAxis      = axis;
587
        mAddRotationRowBitmap = rowBitmap;
588
        mAddRotationAngle     = angle;
589
        mAddRotationDuration  = duration;
590
        mAddRotationTime      = System.currentTimeMillis();
591

    
592
        if( listener instanceof ScrambleEffect )
593
          {
594
          mDebug += (mNewObject==null ? "null" : mNewObject.reportState() );
595
          mDebug += ("(a "+axis+" "+rowBitmap+" "+angle+" "+(mAddRotationTime-mScrambleStartTime))+")";
596
          }
597
        }
598
      }
599
    }
600

    
601
///////////////////////////////////////////////////////////////////////////////////////////////////
602

    
603
  public void initializeObject(int[][] moves)
604
    {
605
    mInitializeObject = true;
606
    mNextMoves = moves;
607
    }
608

    
609
///////////////////////////////////////////////////////////////////////////////////////////////////
610

    
611
  public void applyScrambles(int[][] moves)
612
    {
613
    mApplyScrambles = true;
614
    mNextMoves = moves;
615
    }
616

    
617
///////////////////////////////////////////////////////////////////////////////////////////////////
618

    
619
  public void scrambleObject(int num)
620
    {
621
    if( !mUIBlocked )
622
      {
623
      mScrambleObject = true;
624
      mScrambleObjectNum = num;
625
      mDebug = "";
626
      mScrambleStartTime = System.currentTimeMillis();
627
      }
628
    }
629

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

    
632
  public void fastScrambleObject(int num)
633
    {
634
    if( !mUIBlocked )
635
      {
636
      mFastScrambleObject = true;
637
      mScrambleObjectNum = num;
638
      mDebug = "";
639
      mScrambleStartTime = System.currentTimeMillis();
640
      }
641
    }
642

    
643
///////////////////////////////////////////////////////////////////////////////////////////////////
644
// this starts the Solve Effect
645

    
646
  public void solveObject()
647
    {
648
    if( !mUIBlocked )
649
      {
650
      mSolveObject = true;
651
      }
652
    }
653

    
654
///////////////////////////////////////////////////////////////////////////////////////////////////
655
// this only sets the cubits state to solved
656

    
657
  public void solveOnly()
658
    {
659
    mSolve = true;
660
    }
661

    
662
///////////////////////////////////////////////////////////////////////////////////////////////////
663

    
664
  public void resetAllTextureMaps()
665
    {
666
    mResetAllTextureMaps = true;
667
    }
668

    
669
///////////////////////////////////////////////////////////////////////////////////////////////////
670

    
671
  public TwistyObject getObject()
672
    {
673
    return mNewObject;
674
    }
675

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

    
678
  public TwistyObjectNode getObjectNode()
679
    {
680
    return mController.getNode();
681
    }
682

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

    
685
  public void effectFinished(final long effectID)
686
    {
687
    if( effectID == mRotationFinishedID )
688
      {
689
      mRotationFinishedID = 0;
690
      removeRotation();
691
      }
692
    else if( effectID == mAddRotationID )
693
      {
694
      mAddRotationID = 0;
695
      mRemoveRotationID = effectID;
696
      removePatternRotation();
697
      }
698
    else
699
      {
700
      for(int i=0; i<BaseEffect.Type.LENGTH; i++)
701
        {
702
        if( effectID == mEffectID[i] )
703
          {
704
          if( i!=BaseEffect.Type.WIN.ordinal()      )
705
            {
706
            unblockEverything();
707
            }
708
          if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
709
            {
710
            mScrambleEndTime = System.currentTimeMillis();
711
            mInterface.onScrambleEffectFinished();
712
            }
713
          if( i==BaseEffect.Type.WIN.ordinal()      )
714
            {
715
            mInterface.onWinEffectFinished(mScrambleStartTime,mScrambleEndTime-mScrambleStartTime,mDebug,mScrambleObjectNum);
716
            }
717
          break;
718
          }
719
        }
720
      }
721
    }
722
  }
(4-4/13)