Project

General

Profile

Download (18.6 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / main / RubikPreRender.java @ dca3888a

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.main;
21

    
22
import android.content.Context;
23
import android.content.SharedPreferences;
24
import android.content.res.Resources;
25
import android.os.Bundle;
26

    
27
import com.google.firebase.analytics.FirebaseAnalytics;
28

    
29
import org.distorted.dialogs.RubikDialogNewRecord;
30
import org.distorted.dialogs.RubikDialogSolved;
31
import org.distorted.effects.BaseEffect;
32
import org.distorted.library.message.EffectListener;
33
import org.distorted.objects.TwistyObject;
34
import org.distorted.objects.ObjectList;
35
import org.distorted.scores.RubikScores;
36
import org.distorted.states.RubikStatePlay;
37
import org.distorted.states.StateList;
38
import org.distorted.states.RubikStateSolving;
39

    
40
///////////////////////////////////////////////////////////////////////////////////////////////////
41

    
42
public class RubikPreRender implements EffectListener
43
  {
44
  public interface ActionFinishedListener
45
    {
46
    void onActionFinished(long effectID);
47
    }
48

    
49
  private RubikSurfaceView mView;
50
  private boolean mFinishRotation, mRemoveRotation, mRemovePatternRotation, mAddRotation,
51
                  mSetQuat, mChangeObject, mSetupObject, mSolveObject, mScrambleObject,
52
                  mInitializeObject, mSetTextureMap, mResetAllTextureMaps;
53
  private boolean mCanRotate, mCanPlay;
54
  private boolean mIsSolved;
55
  private ObjectList mNextObject;
56
  private int mNextSize;
57
  private long mRotationFinishedID;
58
  private long[] mEffectID;
59
  private boolean mIsNewRecord;
60
  private long mNewRecord;
61
  private int mScreenWidth, mScreenHeight;
62
  private SharedPreferences mPreferences;
63
  private int[][] mNextMoves;
64
  private TwistyObject mOldObject, mNewObject;
65
  private int mScrambleObjectNum;
66
  private int mAddRotationAxis, mAddRotationRowBitmap, mAddRotationAngle;
67
  private long mAddRotationDuration;
68
  private ActionFinishedListener mAddActionListener;
69
  private long mAddRotationID, mRemoveRotationID;
70
  private int mCubit, mFace, mNewColor;
71
  private int mNearestAngle;
72

    
73
///////////////////////////////////////////////////////////////////////////////////////////////////
74

    
75
  RubikPreRender(RubikSurfaceView view)
76
    {
77
    mView = view;
78

    
79
    mFinishRotation       = false;
80
    mRemoveRotation       = false;
81
    mRemovePatternRotation= false;
82
    mAddRotation          = false;
83
    mSetQuat              = false;
84
    mChangeObject         = false;
85
    mSetupObject          = false;
86
    mSolveObject          = false;
87
    mScrambleObject       = false;
88

    
89
    mCanRotate = true;
90
    mCanPlay   = true;
91

    
92
    mOldObject = null;
93
    mNewObject = null;
94

    
95
    mScreenWidth = mScreenHeight = 0;
96
    mScrambleObjectNum = 0;
97

    
98
    mEffectID = new long[BaseEffect.Type.LENGTH];
99
    }
100

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

    
103
  private void createObjectNow(ObjectList object, int size, int[][] moves)
104
    {
105
    boolean firstTime = (mNewObject==null);
106

    
107
    if( mOldObject!=null ) mOldObject.releaseResources();
108
    mOldObject = mNewObject;
109

    
110
    Context con = mView.getContext();
111
    Resources res = con.getResources();
112

    
113
    mNewObject = object.create(size, mView.getQuat(), moves, res, mScreenWidth);
114

    
115
    if( mNewObject!=null )
116
      {
117
      mNewObject.createTexture();
118
      mView.setMovement(object.getObjectMovementClass());
119

    
120
      if( firstTime ) mNewObject.restorePreferences(mPreferences);
121

    
122
      if( mScreenWidth!=0 )
123
        {
124
        mNewObject.recomputeScaleFactor(mScreenWidth, mScreenHeight);
125
        }
126

    
127
      mIsSolved = mNewObject.isSolved();
128
      }
129
    }
130

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132
// do all 'adjustable' effects (SizeChange, Solve, Scramble)
133

    
134
  private void doEffectNow(BaseEffect.Type type)
135
    {
136
    int index = type.ordinal();
137

    
138
    try
139
      {
140
      mEffectID[index] = type.startEffect(mView.getRenderer().getScreen(),this);
141
      }
142
    catch( Exception ex )
143
      {
144
      android.util.Log.e("renderer", "exception starting effect: "+ex.getMessage());
145

    
146
      mCanPlay   = true;
147
      mCanRotate = true;
148
      }
149
    }
150

    
151
///////////////////////////////////////////////////////////////////////////////////////////////////
152

    
153
  private void removeRotationNow()
154
    {
155
    mRemoveRotation=false;
156
    mNewObject.removeRotationNow();
157

    
158
    boolean solved = mNewObject.isSolved();
159

    
160
    if( solved && !mIsSolved )
161
      {
162
      if( StateList.getCurrentState()== StateList.SOLV )
163
        {
164
        RubikStateSolving solving = (RubikStateSolving) StateList.SOLV.getStateClass();
165
        mNewRecord = solving.getRecord();
166

    
167
        if( mNewRecord< 0 )
168
          {
169
          mNewRecord = -mNewRecord;
170
          mIsNewRecord = false;
171
          }
172
        else
173
          {
174
          mIsNewRecord = true;
175
          }
176
        }
177

    
178
      mCanRotate = true;
179
      mCanPlay = false;
180
      doEffectNow( BaseEffect.Type.WIN );
181
      }
182
    else
183
      {
184
      mCanRotate = true;
185
      mCanPlay = true;
186
      }
187

    
188
    mIsSolved = solved;
189
    }
190

    
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192

    
193
  private void removeRotation()
194
    {
195
    mRemoveRotation = true;
196
    }
197

    
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199

    
200
  private void removePatternRotation()
201
    {
202
    mRemovePatternRotation = true;
203
    }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

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

    
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215

    
216
  private void addRotationNow()
217
    {
218
    mAddRotation = false;
219
    mAddRotationID = mNewObject.addNewRotation( mAddRotationAxis, mAddRotationRowBitmap,
220
                                                mAddRotationAngle, mAddRotationDuration, this);
221
    }
222

    
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224

    
225
  private void finishRotationNow()
226
    {
227
    mFinishRotation = false;
228
    mCanRotate      = false;
229
    mCanPlay        = false;
230
    mRotationFinishedID = mNewObject.finishRotationNow(this, mNearestAngle);
231

    
232
    if( mRotationFinishedID==0 ) // failed to add effect - should never happen
233
      {
234
      mCanRotate = true;
235
      mCanPlay   = true;
236
      }
237
    }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240

    
241
  private void changeObjectNow()
242
    {
243
    mChangeObject = false;
244

    
245
    if ( mNewObject==null || mNewObject.getObjectList()!=mNextObject || mNewObject.getSize()!=mNextSize)
246
      {
247
      mCanRotate= false;
248
      mCanPlay  = false;
249
      createObjectNow(mNextObject, mNextSize, null);
250
      doEffectNow( BaseEffect.Type.SIZECHANGE );
251
      }
252
    }
253

    
254
///////////////////////////////////////////////////////////////////////////////////////////////////
255

    
256
  private void setupObjectNow()
257
    {
258
    mSetupObject = false;
259

    
260
    if ( mNewObject==null || mNewObject.getObjectList()!=mNextObject || mNewObject.getSize()!=mNextSize)
261
      {
262
      mCanRotate= false;
263
      mCanPlay  = false;
264
      createObjectNow(mNextObject, mNextSize, mNextMoves);
265
      doEffectNow( BaseEffect.Type.SIZECHANGE );
266
      }
267
    else
268
      {
269
      mNewObject.initializeObject(mNextMoves);
270
      }
271
    }
272

    
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274

    
275
  private void scrambleObjectNow()
276
    {
277
    mScrambleObject = false;
278
    mCanRotate      = false;
279
    mCanPlay        = false;
280
    mIsSolved       = false;
281
    RubikScores.getInstance().incrementNumPlays();
282
    doEffectNow( BaseEffect.Type.SCRAMBLE );
283
    }
284

    
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286

    
287
  private void solveObjectNow()
288
    {
289
    mSolveObject = false;
290
    mCanRotate   = false;
291
    mCanPlay     = false;
292
    doEffectNow( BaseEffect.Type.SOLVE );
293
    }
294

    
295
///////////////////////////////////////////////////////////////////////////////////////////////////
296

    
297
  private void initializeObjectNow()
298
    {
299
    mInitializeObject = false;
300
    mNewObject.initializeObject(mNextMoves);
301
    }
302

    
303
///////////////////////////////////////////////////////////////////////////////////////////////////
304

    
305
  private void setTextureMapNow()
306
    {
307
    mSetTextureMap = false;
308

    
309
    if( mNewObject!=null ) mNewObject.setTextureMap(mCubit,mFace,mNewColor);
310
    }
311

    
312
///////////////////////////////////////////////////////////////////////////////////////////////////
313

    
314
  private void resetAllTextureMapsNow()
315
    {
316
    mResetAllTextureMaps = false;
317

    
318
    if( mNewObject!=null ) mNewObject.resetAllTextureMaps();
319
    }
320

    
321
///////////////////////////////////////////////////////////////////////////////////////////////////
322

    
323
  private void setQuatNow()
324
    {
325
    mSetQuat = false;
326
    mView.setQuat();
327
    }
328

    
329
///////////////////////////////////////////////////////////////////////////////////////////////////
330

    
331
  private void reportRecord()
332
    {
333
    RubikStatePlay play = (RubikStatePlay) StateList.PLAY.getStateClass();
334
    RubikScores scores = RubikScores.getInstance();
335

    
336
    int object      = play.getObject();
337
    int size        = play.getSize();
338
    int level       = play.getLevel();
339
    ObjectList list = ObjectList.getObject(object);
340
    String name     = scores.getName();
341

    
342
    String record = list.name()+"_"+size+" level "+level+" time "+mNewRecord+" isNew: "+mIsNewRecord+" name: "+name;
343

    
344
    final RubikActivity act = (RubikActivity)mView.getContext();
345
    FirebaseAnalytics analytics = act.getAnalytics();
346

    
347
    if( analytics!=null )
348
      {
349
      Bundle bundle = new Bundle();
350
      bundle.putString(FirebaseAnalytics.Param.LEVEL, record);
351
      analytics.logEvent(FirebaseAnalytics.Event.LEVEL_END, bundle);
352
      }
353
    }
354

    
355
///////////////////////////////////////////////////////////////////////////////////////////////////
356
//
357
///////////////////////////////////////////////////////////////////////////////////////////////////
358

    
359
  void setScreenSize(int width, int height)
360
    {
361
    if( mNewObject!=null )
362
      {
363
      mNewObject.createTexture();
364
      mNewObject.recomputeScaleFactor(width,height);
365
      }
366

    
367
    mScreenHeight = height;
368
    mScreenWidth  = width;
369
    }
370

    
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

    
373
  void savePreferences(SharedPreferences.Editor editor)
374
    {
375
    if( mNewObject!=null )
376
      {
377
      mNewObject.savePreferences(editor);
378
      }
379
    }
380

    
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

    
383
  void restorePreferences(SharedPreferences preferences)
384
    {
385
    mPreferences = preferences;
386
    }
387

    
388
///////////////////////////////////////////////////////////////////////////////////////////////////
389

    
390
  void finishRotation(int nearestAngle)
391
    {
392
    mNearestAngle   = nearestAngle;
393
    mFinishRotation = true;
394
    }
395

    
396
///////////////////////////////////////////////////////////////////////////////////////////////////
397

    
398
  void changeObject(ObjectList object, int size)
399
    {
400
    if( size>0 )
401
      {
402
      mChangeObject = true;
403
      mNextObject = object;
404
      mNextSize   = size;
405
      }
406
    }
407

    
408
///////////////////////////////////////////////////////////////////////////////////////////////////
409

    
410
  void setupObject(ObjectList object, int size, int[][] moves)
411
    {
412
    if( size>0 )
413
      {
414
      mSetupObject= true;
415
      mNextObject = object;
416
      mNextSize   = size;
417
      mNextMoves  = moves;
418
      }
419
    }
420

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

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

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

    
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433

    
434
  boolean canRotate()
435
    {
436
    return mCanRotate;
437
    }
438

    
439
///////////////////////////////////////////////////////////////////////////////////////////////////
440

    
441
  public boolean canPlay()
442
    {
443
    return mCanPlay;
444
    }
445

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

    
448
  void setQuatOnNextRender()
449
    {
450
    mSetQuat = true;
451
    }
452

    
453
///////////////////////////////////////////////////////////////////////////////////////////////////
454

    
455
  void preRender()
456
    {
457
    if( mSetQuat               ) setQuatNow();
458
    if( mFinishRotation        ) finishRotationNow();
459
    if( mRemoveRotation        ) removeRotationNow();
460
    if( mRemovePatternRotation ) removePatternRotationNow();
461
    if( mChangeObject          ) changeObjectNow();
462
    if( mSetupObject           ) setupObjectNow();
463
    if( mSolveObject           ) solveObjectNow();
464
    if( mScrambleObject        ) scrambleObjectNow();
465
    if( mAddRotation           ) addRotationNow();
466
    if( mInitializeObject      ) initializeObjectNow();
467
    if( mResetAllTextureMaps   ) resetAllTextureMapsNow();
468
    if( mSetTextureMap         ) setTextureMapNow();
469
    }
470

    
471
///////////////////////////////////////////////////////////////////////////////////////////////////
472
// PUBLIC API
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474

    
475
  public void addRotation(ActionFinishedListener listener, int axis, int rowBitmap, int angle, long duration)
476
    {
477
    mAddRotation = true;
478

    
479
    mAddActionListener    = listener;
480
    mAddRotationAxis      = axis;
481
    mAddRotationRowBitmap = rowBitmap;
482
    mAddRotationAngle     = angle;
483
    mAddRotationDuration  = duration;
484
    }
485

    
486
///////////////////////////////////////////////////////////////////////////////////////////////////
487

    
488
  public void initializeObject(int[][] moves)
489
    {
490
    mInitializeObject = true;
491
    mNextMoves = moves;
492
    }
493

    
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495

    
496
  public void scrambleObject(int num)
497
    {
498
    if( mCanPlay )
499
      {
500
      mScrambleObject = true;
501
      mScrambleObjectNum = num;
502
      }
503
    }
504

    
505
///////////////////////////////////////////////////////////////////////////////////////////////////
506

    
507
  public void solveObject()
508
    {
509
    if( mCanPlay )
510
      {
511
      mSolveObject = true;
512
      }
513
    }
514

    
515
///////////////////////////////////////////////////////////////////////////////////////////////////
516

    
517
  public void resetAllTextureMaps()
518
    {
519
    mResetAllTextureMaps = true;
520
    }
521

    
522
///////////////////////////////////////////////////////////////////////////////////////////////////
523

    
524
  public TwistyObject getObject()
525
    {
526
    return mNewObject;
527
    }
528

    
529
///////////////////////////////////////////////////////////////////////////////////////////////////
530

    
531
  public TwistyObject getOldObject()
532
    {
533
    return mOldObject;
534
    }
535

    
536
///////////////////////////////////////////////////////////////////////////////////////////////////
537

    
538
  public int getNumScrambles()
539
    {
540
    return mScrambleObjectNum;
541
    }
542

    
543
///////////////////////////////////////////////////////////////////////////////////////////////////
544

    
545
  public void effectFinished(final long effectID)
546
    {
547
    if( effectID == mRotationFinishedID )
548
      {
549
      mRotationFinishedID = 0;
550
      removeRotation();
551
      }
552
    else if( effectID == mAddRotationID )
553
      {
554
      mAddRotationID = 0;
555
      mRemoveRotationID = effectID;
556
      removePatternRotation();
557
      }
558
    else
559
      {
560
      for(int i=0; i<BaseEffect.Type.LENGTH; i++)
561
        {
562
        if( effectID == mEffectID[i] )
563
          {
564
          mCanRotate = true;
565
          mCanPlay   = true;
566

    
567
          if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
568
            {
569
            final RubikActivity act = (RubikActivity)mView.getContext();
570

    
571
            act.runOnUiThread(new Runnable()
572
              {
573
              @Override
574
              public void run()
575
                {
576
                StateList.switchState( act, StateList.READ);
577
                }
578
              });
579
            }
580

    
581
          if( i==BaseEffect.Type.WIN.ordinal() )
582
            {
583
            if( StateList.getCurrentState()== StateList.SOLV )
584
              {
585
              final RubikActivity act = (RubikActivity)mView.getContext();
586
              Bundle bundle = new Bundle();
587
              bundle.putLong("time", mNewRecord );
588

    
589
              reportRecord();
590

    
591
              if( mIsNewRecord )
592
                {
593
                RubikDialogNewRecord dialog = new RubikDialogNewRecord();
594
                dialog.setArguments(bundle);
595
                dialog.show( act.getSupportFragmentManager(), RubikDialogNewRecord.getDialogTag() );
596
                }
597
              else
598
                {
599
                RubikDialogSolved dialog = new RubikDialogSolved();
600
                dialog.setArguments(bundle);
601
                dialog.show( act.getSupportFragmentManager(), RubikDialogSolved.getDialogTag() );
602
                }
603

    
604
              act.runOnUiThread(new Runnable()
605
                {
606
                @Override
607
                public void run()
608
                  {
609
                  StateList.switchState( act, StateList.DONE);
610
                  }
611
                });
612
              }
613
            }
614

    
615
          break;
616
          }
617
        }
618
      }
619
    }
620
  }
(2-2/4)