Project

General

Profile

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

magiccube / src / main / java / org / distorted / main / RubikPostRender.java @ 4d23405c

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.SharedPreferences;
23
import android.os.Bundle;
24

    
25
import org.distorted.dialogs.RubikDialogNewRecord;
26
import org.distorted.dialogs.RubikDialogSolved;
27
import org.distorted.effects.BaseEffect;
28
import org.distorted.library.message.EffectListener;
29
import org.distorted.objects.RubikObject;
30
import org.distorted.objects.RubikObjectList;
31
import org.distorted.scores.RubikScores;
32
import org.distorted.states.RubikState;
33
import org.distorted.states.RubikStateSolving;
34

    
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36

    
37
public class RubikPostRender implements EffectListener
38
  {
39
  public interface ActionFinishedListener
40
    {
41
    void onActionFinished(long effectID);
42
    }
43

    
44
  private RubikSurfaceView mView;
45
  private boolean mFinishRotation, mRemoveRotation, mRemovePatternRotation, mAddRotation,
46
                  mSetQuatCurrent, mSetQuatAccumulated, mChangeObject, mSolveObject,
47
                  mScrambleObject, mInitializeObject, mSetTextureMap, mResetAllTextureMaps;
48
  private boolean mCanRotate, mCanPlay;
49
  private boolean mIsSolved;
50
  private RubikObjectList mNextObject;
51
  private int mNextSize;
52
  private long mRotationFinishedID;
53
  private long[] mEffectID;
54
  private boolean mIsNewRecord;
55
  private long mNewRecord;
56
  private int mScreenWidth, mScreenHeight;
57
  private SharedPreferences mPreferences;
58
  private int[][] mNextMoves;
59
  private RubikObject mOldObject, mNewObject;
60
  private int mScrambleObjectNum;
61
  private int mAddRotationAxis, mAddRotationRowBitmap, mAddRotationAngle;
62
  private long mAddRotationDuration;
63
  private ActionFinishedListener mAddActionListener;
64
  private long mAddRotationID, mRemoveRotationID;
65
  private int mCubit, mFace, mNewColor;
66

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

    
69
  RubikPostRender(RubikSurfaceView view)
70
    {
71
    mView = view;
72

    
73
    mFinishRotation       = false;
74
    mRemoveRotation       = false;
75
    mRemovePatternRotation= false;
76
    mAddRotation          = false;
77
    mSetQuatCurrent       = false;
78
    mSetQuatAccumulated   = false;
79
    mChangeObject         = false;
80
    mSolveObject          = false;
81
    mScrambleObject       = false;
82

    
83
    mCanRotate = true;
84
    mCanPlay   = true;
85

    
86
    mOldObject = null;
87
    mNewObject = null;
88

    
89
    mScreenWidth = mScreenHeight = 0;
90
    mScrambleObjectNum = 0;
91

    
92
    mEffectID = new long[BaseEffect.Type.LENGTH];
93
    }
94

    
95
///////////////////////////////////////////////////////////////////////////////////////////////////
96

    
97
  private void createObjectNow(RubikObjectList object, int size, int[][] moves)
98
    {
99
    boolean firstTime = (mNewObject==null);
100

    
101
    if( mOldObject!=null ) mOldObject.releaseResources();
102
    mOldObject = mNewObject;
103

    
104
    mNewObject = object.create(size, mView.getQuatCurrent(), mView.getQuatAccumulated(), moves);
105
    mNewObject.createTexture();
106
    mView.setMovement(object.getObjectMovementClass());
107

    
108
    if( firstTime ) mNewObject.restorePreferences(mPreferences);
109

    
110
    if( mScreenWidth!=0 )
111
      {
112
      mNewObject.recomputeScaleFactor(mScreenWidth, mScreenHeight);
113
      }
114

    
115
    mIsSolved = mNewObject.isSolved();
116
    }
117

    
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119
// do all 'adjustable' effects (SizeChange, Solve, Scramble)
120

    
121
  private void doEffectNow(BaseEffect.Type type)
122
    {
123
    int index = type.ordinal();
124

    
125
    try
126
      {
127
      mEffectID[index] = type.startEffect(mView.getRenderer().getScreen(),this);
128
      }
129
    catch( Exception ex )
130
      {
131
      android.util.Log.e("renderer", "exception starting effect: "+ex.getMessage());
132

    
133
      mCanPlay   = true;
134
      mCanRotate = true;
135
      }
136
    }
137

    
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139

    
140
  private void removeRotationNow()
141
    {
142
    mRemoveRotation=false;
143
    mNewObject.removeRotationNow();
144

    
145
    boolean solved = mNewObject.isSolved();
146

    
147
    if( solved && !mIsSolved )
148
      {
149
      if( RubikState.getCurrentState()==RubikState.SOLV )
150
        {
151
        RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass();
152
        mNewRecord = solving.stopCounting((RubikActivity)mView.getContext());
153

    
154
        if( mNewRecord< 0 )
155
          {
156
          mNewRecord = -mNewRecord;
157
          mIsNewRecord = false;
158
          }
159
        else
160
          {
161
          mIsNewRecord = true;
162
          }
163
        }
164

    
165
      mCanRotate = false;
166
      mCanPlay = false;
167
      doEffectNow( BaseEffect.Type.WIN );
168
      }
169
    else
170
      {
171
      mCanRotate = true;
172
      mCanPlay = true;
173
      }
174

    
175
    mIsSolved = solved;
176
    }
177

    
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179

    
180
  private void removeRotation()
181
    {
182
    mRemoveRotation = true;
183
    }
184

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

    
187
  private void removePatternRotation()
188
    {
189
    mRemovePatternRotation = true;
190
    }
191

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

    
194
  private void removePatternRotationNow()
195
    {
196
    mRemovePatternRotation=false;
197
    mNewObject.removeRotationNow();
198
    mAddActionListener.onActionFinished(mRemoveRotationID);
199
    }
200

    
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202

    
203
  private void addRotationNow()
204
    {
205
    mAddRotation = false;
206
    mAddRotationID = mNewObject.addNewRotation( mAddRotationAxis, mAddRotationRowBitmap,
207
                                                mAddRotationAngle, mAddRotationDuration, this);
208
    }
209

    
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211

    
212
  private void finishRotationNow()
213
    {
214
    mFinishRotation = false;
215
    mCanRotate      = false;
216
    mCanPlay        = false;
217
    mRotationFinishedID = mNewObject.finishRotationNow(this);
218

    
219
    if( mRotationFinishedID==0 ) // failed to add effect - should never happen
220
      {
221
      mCanRotate = true;
222
      mCanPlay   = true;
223
      }
224
    }
225

    
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227

    
228
  private void changeObjectNow()
229
    {
230
    mChangeObject = false;
231

    
232
    if ( mNewObject==null || mNewObject.getObjectList()!=mNextObject || mNewObject.getSize()!=mNextSize)
233
      {
234
      mCanRotate= false;
235
      mCanPlay  = false;
236
      createObjectNow(mNextObject, mNextSize, mNextMoves);
237
      doEffectNow( BaseEffect.Type.SIZECHANGE );
238
      }
239
    else
240
      {
241
      mNewObject.initializeObject(mNextMoves);
242
      }
243
    }
244

    
245
///////////////////////////////////////////////////////////////////////////////////////////////////
246

    
247
  private void scrambleObjectNow()
248
    {
249
    mScrambleObject = false;
250
    mCanRotate      = false;
251
    mCanPlay        = false;
252
    mIsSolved       = false;
253
    RubikScores.getInstance().incrementNumPlays();
254
    doEffectNow( BaseEffect.Type.SCRAMBLE );
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258

    
259
  private void solveObjectNow()
260
    {
261
    mSolveObject = false;
262
    mCanRotate   = false;
263
    mCanPlay     = false;
264
    doEffectNow( BaseEffect.Type.SOLVE );
265
    }
266

    
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268

    
269
  private void initializeObjectNow()
270
    {
271
    mInitializeObject = false;
272
    mNewObject.initializeObject(mNextMoves);
273
    }
274

    
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276

    
277
  private void setTextureMapNow()
278
    {
279
    mSetTextureMap = false;
280

    
281
    mNewObject.setTextureMap(mCubit,mFace,mNewColor);
282
    }
283

    
284
///////////////////////////////////////////////////////////////////////////////////////////////////
285

    
286
  private void resetAllTextureMapsNow()
287
    {
288
    mResetAllTextureMaps = false;
289

    
290
    mNewObject.resetAllTextureMaps();
291
    }
292

    
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294

    
295
  private void setQuatCurrentNow()
296
    {
297
    mSetQuatCurrent = false;
298
    mView.setQuatCurrent();
299
    }
300

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

    
303
  private void setQuatAccumulatedNow()
304
    {
305
    mSetQuatAccumulated = false;
306
    mView.setQuatAccumulated();
307
    }
308

    
309
///////////////////////////////////////////////////////////////////////////////////////////////////
310
//
311
///////////////////////////////////////////////////////////////////////////////////////////////////
312

    
313
  void setScreenSize(int width, int height)
314
    {
315
    if( mNewObject!=null )
316
      {
317
      mNewObject.createTexture();
318
      mNewObject.recomputeScaleFactor(width,height);
319
      }
320

    
321
    mScreenHeight = height;
322
    mScreenWidth  = width;
323
    }
324

    
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326

    
327
  void savePreferences(SharedPreferences.Editor editor)
328
    {
329
    if( mNewObject!=null )
330
      {
331
      mNewObject.savePreferences(editor);
332
      }
333
    }
334

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

    
337
  void restorePreferences(SharedPreferences preferences)
338
    {
339
    mPreferences = preferences;
340
    }
341

    
342
///////////////////////////////////////////////////////////////////////////////////////////////////
343

    
344
  void finishRotation()
345
    {
346
    mFinishRotation = true;
347
    }
348

    
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350

    
351
  void changeObject(RubikObjectList object, int size, int[][] moves)
352
    {
353
    if( size>0 )
354
      {
355
      mChangeObject = true;
356
      mNextObject = object;
357
      mNextSize   = size;
358
      mNextMoves  = moves;
359
      }
360
    }
361

    
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363

    
364
  void setTextureMap(int cubit, int face, int newColor)
365
    {
366
    mSetTextureMap = true;
367

    
368
    mCubit    = cubit;
369
    mFace     = face;
370
    mNewColor = newColor;
371
    }
372

    
373
///////////////////////////////////////////////////////////////////////////////////////////////////
374

    
375
  boolean canRotate()
376
    {
377
    return mCanRotate;
378
    }
379

    
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381

    
382
  public boolean canPlay()
383
    {
384
    return mCanPlay;
385
    }
386

    
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388

    
389
  void setQuatCurrentOnNextRender()
390
    {
391
    mSetQuatCurrent = true;
392
    }
393

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

    
396
  void setQuatAccumulatedOnNextRender()
397
    {
398
    mSetQuatAccumulated = true;
399
    }
400

    
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

    
403
  void postRender()
404
    {
405
    if( mSetQuatCurrent        ) setQuatCurrentNow();
406
    if( mSetQuatAccumulated    ) setQuatAccumulatedNow();
407
    if( mFinishRotation        ) finishRotationNow();
408
    if( mRemoveRotation        ) removeRotationNow();
409
    if( mRemovePatternRotation ) removePatternRotationNow();
410
    if( mChangeObject          ) changeObjectNow();
411
    if( mSolveObject           ) solveObjectNow();
412
    if( mScrambleObject        ) scrambleObjectNow();
413
    if( mAddRotation           ) addRotationNow();
414
    if( mInitializeObject      ) initializeObjectNow();
415
    if( mResetAllTextureMaps   ) resetAllTextureMapsNow();
416
    if( mSetTextureMap         ) setTextureMapNow();
417
    }
418

    
419
///////////////////////////////////////////////////////////////////////////////////////////////////
420
// PUBLIC API
421
///////////////////////////////////////////////////////////////////////////////////////////////////
422

    
423
  public void addRotation(ActionFinishedListener listener, int axis, int rowBitmap, int angle, long duration)
424
    {
425
    mAddRotation = true;
426

    
427
    mAddActionListener    = listener;
428
    mAddRotationAxis      = axis;
429
    mAddRotationRowBitmap = rowBitmap;
430
    mAddRotationAngle     = angle;
431
    mAddRotationDuration  = duration;
432
    }
433

    
434
///////////////////////////////////////////////////////////////////////////////////////////////////
435

    
436
  public void initializeObject(int[][] moves)
437
    {
438
    mInitializeObject = true;
439
    mNextMoves = moves;
440
    }
441

    
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443

    
444
  public void scrambleObject(int num)
445
    {
446
    if( mCanPlay )
447
      {
448
      mScrambleObject = true;
449
      mScrambleObjectNum = num;
450
      }
451
    }
452

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

    
455
  public void solveObject()
456
    {
457
    if( mCanPlay )
458
      {
459
      mSolveObject = true;
460
      }
461
    }
462

    
463
///////////////////////////////////////////////////////////////////////////////////////////////////
464

    
465
  public void resetAllTextureMaps()
466
    {
467
    mResetAllTextureMaps = true;
468
    }
469

    
470
///////////////////////////////////////////////////////////////////////////////////////////////////
471

    
472
  public RubikObject getObject()
473
    {
474
    return mNewObject;
475
    }
476

    
477
///////////////////////////////////////////////////////////////////////////////////////////////////
478

    
479
  public RubikObject getOldObject()
480
    {
481
    return mOldObject;
482
    }
483

    
484
///////////////////////////////////////////////////////////////////////////////////////////////////
485

    
486
  public int getNumScrambles()
487
    {
488
    return mScrambleObjectNum;
489
    }
490

    
491
///////////////////////////////////////////////////////////////////////////////////////////////////
492

    
493
  public void effectFinished(final long effectID)
494
    {
495
    if( effectID == mRotationFinishedID )
496
      {
497
      mRotationFinishedID = 0;
498
      removeRotation();
499
      }
500
    else if( effectID == mAddRotationID )
501
      {
502
      mAddRotationID = 0;
503
      mRemoveRotationID = effectID;
504
      removePatternRotation();
505
      }
506
    else
507
      {
508
      for(int i=0; i<BaseEffect.Type.LENGTH; i++)
509
        {
510
        if( effectID == mEffectID[i] )
511
          {
512
          mCanRotate = true;
513
          mCanPlay   = true;
514

    
515
          if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
516
            {
517
            final RubikActivity act = (RubikActivity)mView.getContext();
518
            RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass();
519
            solving.resetUpperText();
520

    
521
            act.runOnUiThread(new Runnable()
522
              {
523
              @Override
524
              public void run()
525
                {
526
                RubikState.switchState( act, RubikState.SOLV);
527
                }
528
              });
529
            }
530

    
531
          if( i==BaseEffect.Type.WIN.ordinal() )
532
            {
533
            if( RubikState.getCurrentState()==RubikState.SOLV )
534
              {
535
              final RubikActivity act = (RubikActivity)mView.getContext();
536
              Bundle bundle = new Bundle();
537
              bundle.putLong("time", mNewRecord );
538

    
539
              if( mIsNewRecord )
540
                {
541
                RubikDialogNewRecord dialog = new RubikDialogNewRecord();
542
                dialog.setArguments(bundle);
543
                dialog.show( act.getSupportFragmentManager(), null);
544
                }
545
              else
546
                {
547
                RubikDialogSolved dialog = new RubikDialogSolved();
548
                dialog.setArguments(bundle);
549
                dialog.show( act.getSupportFragmentManager(), null);
550
                }
551
              }
552
            }
553

    
554
          break;
555
          }
556
        }
557
      }
558
    }
559
  }
(2-2/4)