Project

General

Profile

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

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

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 org.distorted.dialogs.RubikDialogNewRecord;
28
import org.distorted.dialogs.RubikDialogSolved;
29
import org.distorted.effects.BaseEffect;
30
import org.distorted.library.message.EffectListener;
31
import org.distorted.objects.RubikObject;
32
import org.distorted.objects.RubikObjectList;
33
import org.distorted.scores.RubikScores;
34
import org.distorted.states.RubikState;
35
import org.distorted.states.RubikStateSolving;
36

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

    
39
public class RubikPreRender implements EffectListener
40
  {
41
  public interface ActionFinishedListener
42
    {
43
    void onActionFinished(long effectID);
44
    }
45

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

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

    
71
  RubikPreRender(RubikSurfaceView view)
72
    {
73
    mView = view;
74

    
75
    mFinishRotation       = false;
76
    mRemoveRotation       = false;
77
    mRemovePatternRotation= false;
78
    mAddRotation          = false;
79
    mSetQuatCurrent       = false;
80
    mSetQuatAccumulated   = false;
81
    mChangeObject         = false;
82
    mSetupObject          = false;
83
    mSolveObject          = false;
84
    mScrambleObject       = false;
85

    
86
    mCanRotate = true;
87
    mCanPlay   = true;
88

    
89
    mOldObject = null;
90
    mNewObject = null;
91

    
92
    mScreenWidth = mScreenHeight = 0;
93
    mScrambleObjectNum = 0;
94

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

    
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99

    
100
  private void createObjectNow(RubikObjectList object, int size, int[][] moves)
101
    {
102
    boolean firstTime = (mNewObject==null);
103

    
104
    if( mOldObject!=null ) mOldObject.releaseResources();
105
    mOldObject = mNewObject;
106

    
107
    Context con = mView.getContext();
108
    Resources res = con.getResources();
109

    
110
    mNewObject = object.create(size, mView.getQuatCurrent(), mView.getQuatAccumulated(), moves, res);
111

    
112
    if( mNewObject!=null )
113
      {
114
      mNewObject.createTexture();
115
      mView.setMovement(object.getObjectMovementClass());
116

    
117
      if( firstTime ) mNewObject.restorePreferences(mPreferences);
118

    
119
      if( mScreenWidth!=0 )
120
        {
121
        mNewObject.recomputeScaleFactor(mScreenWidth, mScreenHeight);
122
        }
123

    
124
      mIsSolved = mNewObject.isSolved();
125
      }
126
    }
127

    
128
///////////////////////////////////////////////////////////////////////////////////////////////////
129
// do all 'adjustable' effects (SizeChange, Solve, Scramble)
130

    
131
  private void doEffectNow(BaseEffect.Type type)
132
    {
133
    int index = type.ordinal();
134

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

    
143
      mCanPlay   = true;
144
      mCanRotate = true;
145
      }
146
    }
147

    
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149

    
150
  private void removeRotationNow()
151
    {
152
    mRemoveRotation=false;
153
    mNewObject.removeRotationNow();
154

    
155
    boolean solved = mNewObject.isSolved();
156

    
157
    if( solved && !mIsSolved )
158
      {
159
      if( RubikState.getCurrentState()==RubikState.SOLV )
160
        {
161
        RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass();
162
        mNewRecord = solving.getRecord();
163

    
164
        if( mNewRecord< 0 )
165
          {
166
          mNewRecord = -mNewRecord;
167
          mIsNewRecord = false;
168
          }
169
        else
170
          {
171
          mIsNewRecord = true;
172
          }
173
        }
174

    
175
      mCanRotate = false;
176
      mCanPlay = false;
177
      doEffectNow( BaseEffect.Type.WIN );
178
      }
179
    else
180
      {
181
      mCanRotate = true;
182
      mCanPlay = true;
183
      }
184

    
185
    mIsSolved = solved;
186
    }
187

    
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

    
190
  private void removeRotation()
191
    {
192
    mRemoveRotation = true;
193
    }
194

    
195
///////////////////////////////////////////////////////////////////////////////////////////////////
196

    
197
  private void removePatternRotation()
198
    {
199
    mRemovePatternRotation = true;
200
    }
201

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203

    
204
  private void removePatternRotationNow()
205
    {
206
    mRemovePatternRotation=false;
207
    mNewObject.removeRotationNow();
208
    mAddActionListener.onActionFinished(mRemoveRotationID);
209
    }
210

    
211
///////////////////////////////////////////////////////////////////////////////////////////////////
212

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

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221

    
222
  private void finishRotationNow()
223
    {
224
    mFinishRotation = false;
225
    mCanRotate      = false;
226
    mCanPlay        = false;
227
    mRotationFinishedID = mNewObject.finishRotationNow(this);
228

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

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237

    
238
  private void changeObjectNow()
239
    {
240
    mChangeObject = false;
241

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

    
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252

    
253
  private void setupObjectNow()
254
    {
255
    mSetupObject = false;
256

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

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271

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

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

    
284
  private void solveObjectNow()
285
    {
286
    mSolveObject = false;
287
    mCanRotate   = false;
288
    mCanPlay     = false;
289
    doEffectNow( BaseEffect.Type.SOLVE );
290
    }
291

    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293

    
294
  private void initializeObjectNow()
295
    {
296
    mInitializeObject = false;
297
    mNewObject.initializeObject(mNextMoves);
298
    }
299

    
300
///////////////////////////////////////////////////////////////////////////////////////////////////
301

    
302
  private void setTextureMapNow()
303
    {
304
    mSetTextureMap = false;
305

    
306
    if( mNewObject!=null ) mNewObject.setTextureMap(mCubit,mFace,mNewColor);
307
    }
308

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

    
311
  private void resetAllTextureMapsNow()
312
    {
313
    mResetAllTextureMaps = false;
314

    
315
    if( mNewObject!=null ) mNewObject.resetAllTextureMaps();
316
    }
317

    
318
///////////////////////////////////////////////////////////////////////////////////////////////////
319

    
320
  private void setQuatCurrentNow()
321
    {
322
    mSetQuatCurrent = false;
323
    mView.setQuatCurrent();
324
    }
325

    
326
///////////////////////////////////////////////////////////////////////////////////////////////////
327

    
328
  private void setQuatAccumulatedNow()
329
    {
330
    mSetQuatAccumulated = false;
331
    mView.setQuatAccumulated();
332
    }
333

    
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335
//
336
///////////////////////////////////////////////////////////////////////////////////////////////////
337

    
338
  void setScreenSize(int width, int height)
339
    {
340
    if( mNewObject!=null )
341
      {
342
      mNewObject.createTexture();
343
      mNewObject.recomputeScaleFactor(width,height);
344
      }
345

    
346
    mScreenHeight = height;
347
    mScreenWidth  = width;
348
    }
349

    
350
///////////////////////////////////////////////////////////////////////////////////////////////////
351

    
352
  void savePreferences(SharedPreferences.Editor editor)
353
    {
354
    if( mNewObject!=null )
355
      {
356
      mNewObject.savePreferences(editor);
357
      }
358
    }
359

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

    
362
  void restorePreferences(SharedPreferences preferences)
363
    {
364
    mPreferences = preferences;
365
    }
366

    
367
///////////////////////////////////////////////////////////////////////////////////////////////////
368

    
369
  void finishRotation()
370
    {
371
    mFinishRotation = true;
372
    }
373

    
374
///////////////////////////////////////////////////////////////////////////////////////////////////
375

    
376
  void changeObject(RubikObjectList object, int size)
377
    {
378
    if( size>0 )
379
      {
380
      mChangeObject = true;
381
      mNextObject = object;
382
      mNextSize   = size;
383
      }
384
    }
385

    
386
///////////////////////////////////////////////////////////////////////////////////////////////////
387

    
388
  void setupObject(RubikObjectList object, int size, int[][] moves)
389
    {
390
    if( size>0 )
391
      {
392
      mSetupObject= true;
393
      mNextObject = object;
394
      mNextSize   = size;
395
      mNextMoves  = moves;
396
      }
397
    }
398

    
399
///////////////////////////////////////////////////////////////////////////////////////////////////
400

    
401
  void setTextureMap(int cubit, int face, int newColor)
402
    {
403
    mSetTextureMap = true;
404

    
405
    mCubit    = cubit;
406
    mFace     = face;
407
    mNewColor = newColor;
408
    }
409

    
410
///////////////////////////////////////////////////////////////////////////////////////////////////
411

    
412
  boolean canRotate()
413
    {
414
    return mCanRotate;
415
    }
416

    
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418

    
419
  public boolean canPlay()
420
    {
421
    return mCanPlay;
422
    }
423

    
424
///////////////////////////////////////////////////////////////////////////////////////////////////
425

    
426
  void setQuatCurrentOnNextRender()
427
    {
428
    mSetQuatCurrent = true;
429
    }
430

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

    
433
  void setQuatAccumulatedOnNextRender()
434
    {
435
    mSetQuatAccumulated = true;
436
    }
437

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

    
440
  void preRender()
441
    {
442
    if( mSetQuatCurrent        ) setQuatCurrentNow();
443
    if( mSetQuatAccumulated    ) setQuatAccumulatedNow();
444
    if( mFinishRotation        ) finishRotationNow();
445
    if( mRemoveRotation        ) removeRotationNow();
446
    if( mRemovePatternRotation ) removePatternRotationNow();
447
    if( mChangeObject          ) changeObjectNow();
448
    if( mSetupObject           ) setupObjectNow();
449
    if( mSolveObject           ) solveObjectNow();
450
    if( mScrambleObject        ) scrambleObjectNow();
451
    if( mAddRotation           ) addRotationNow();
452
    if( mInitializeObject      ) initializeObjectNow();
453
    if( mResetAllTextureMaps   ) resetAllTextureMapsNow();
454
    if( mSetTextureMap         ) setTextureMapNow();
455
    }
456

    
457
///////////////////////////////////////////////////////////////////////////////////////////////////
458
// PUBLIC API
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460

    
461
  public void addRotation(ActionFinishedListener listener, int axis, int rowBitmap, int angle, long duration)
462
    {
463
    mAddRotation = true;
464

    
465
    mAddActionListener    = listener;
466
    mAddRotationAxis      = axis;
467
    mAddRotationRowBitmap = rowBitmap;
468
    mAddRotationAngle     = angle;
469
    mAddRotationDuration  = duration;
470
    }
471

    
472
///////////////////////////////////////////////////////////////////////////////////////////////////
473

    
474
  public void initializeObject(int[][] moves)
475
    {
476
    mInitializeObject = true;
477
    mNextMoves = moves;
478
    }
479

    
480
///////////////////////////////////////////////////////////////////////////////////////////////////
481

    
482
  public void scrambleObject(int num)
483
    {
484
    if( mCanPlay )
485
      {
486
      mScrambleObject = true;
487
      mScrambleObjectNum = num;
488
      }
489
    }
490

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

    
493
  public void solveObject()
494
    {
495
    if( mCanPlay )
496
      {
497
      mSolveObject = true;
498
      }
499
    }
500

    
501
///////////////////////////////////////////////////////////////////////////////////////////////////
502

    
503
  public void resetAllTextureMaps()
504
    {
505
    mResetAllTextureMaps = true;
506
    }
507

    
508
///////////////////////////////////////////////////////////////////////////////////////////////////
509

    
510
  public RubikObject getObject()
511
    {
512
    return mNewObject;
513
    }
514

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

    
517
  public RubikObject getOldObject()
518
    {
519
    return mOldObject;
520
    }
521

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

    
524
  public int getNumScrambles()
525
    {
526
    return mScrambleObjectNum;
527
    }
528

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

    
531
  public void effectFinished(final long effectID)
532
    {
533
    if( effectID == mRotationFinishedID )
534
      {
535
      mRotationFinishedID = 0;
536
      removeRotation();
537
      }
538
    else if( effectID == mAddRotationID )
539
      {
540
      mAddRotationID = 0;
541
      mRemoveRotationID = effectID;
542
      removePatternRotation();
543
      }
544
    else
545
      {
546
      for(int i=0; i<BaseEffect.Type.LENGTH; i++)
547
        {
548
        if( effectID == mEffectID[i] )
549
          {
550
          mCanRotate = true;
551
          mCanPlay   = true;
552

    
553
          if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
554
            {
555
            final RubikActivity act = (RubikActivity)mView.getContext();
556

    
557
            act.runOnUiThread(new Runnable()
558
              {
559
              @Override
560
              public void run()
561
                {
562
                RubikState.switchState( act, RubikState.READ);
563
                }
564
              });
565
            }
566

    
567
          if( i==BaseEffect.Type.WIN.ordinal() )
568
            {
569
            if( RubikState.getCurrentState()==RubikState.SOLV )
570
              {
571
              final RubikActivity act = (RubikActivity)mView.getContext();
572
              Bundle bundle = new Bundle();
573
              bundle.putLong("time", mNewRecord );
574

    
575
              if( mIsNewRecord )
576
                {
577
                RubikDialogNewRecord dialog = new RubikDialogNewRecord();
578
                dialog.setArguments(bundle);
579
                dialog.show( act.getSupportFragmentManager(), null);
580
                }
581
              else
582
                {
583
                RubikDialogSolved dialog = new RubikDialogSolved();
584
                dialog.setArguments(bundle);
585
                dialog.show( act.getSupportFragmentManager(), null);
586
                }
587

    
588
              act.runOnUiThread(new Runnable()
589
                {
590
                @Override
591
                public void run()
592
                  {
593
                  RubikState.switchState( act, RubikState.DONE);
594
                  }
595
                });
596
              }
597
            }
598

    
599
          break;
600
          }
601
        }
602
      }
603
    }
604
  }
(2-2/4)