Project

General

Profile

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

magiccube / src / main / java / org / distorted / main / RubikPreRender.java @ 168b6b56

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
  private int mNearestAngle;
69

    
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71

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

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

    
87
    mCanRotate = true;
88
    mCanPlay   = true;
89

    
90
    mOldObject = null;
91
    mNewObject = null;
92

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

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

    
99
///////////////////////////////////////////////////////////////////////////////////////////////////
100

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

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

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

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

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

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

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

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

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

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

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

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

    
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150

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

    
156
    boolean solved = mNewObject.isSolved();
157

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

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

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

    
186
    mIsSolved = solved;
187
    }
188

    
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190

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

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

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

    
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204

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

    
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213

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

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

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

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

    
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238

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

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

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

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

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

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

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

    
283
///////////////////////////////////////////////////////////////////////////////////////////////////
284

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

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

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

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

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

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

    
310
///////////////////////////////////////////////////////////////////////////////////////////////////
311

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

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

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

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

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

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

    
335
///////////////////////////////////////////////////////////////////////////////////////////////////
336
//
337
///////////////////////////////////////////////////////////////////////////////////////////////////
338

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

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

    
351
///////////////////////////////////////////////////////////////////////////////////////////////////
352

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

    
361
///////////////////////////////////////////////////////////////////////////////////////////////////
362

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

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

    
370
  void finishRotation(int nearestAngle)
371
    {
372
    mNearestAngle   = nearestAngle;
373
    mFinishRotation = true;
374
    }
375

    
376
///////////////////////////////////////////////////////////////////////////////////////////////////
377

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

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

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

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

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

    
407
    mCubit    = cubit;
408
    mFace     = face;
409
    mNewColor = newColor;
410
    }
411

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

    
414
  boolean canRotate()
415
    {
416
    return mCanRotate;
417
    }
418

    
419
///////////////////////////////////////////////////////////////////////////////////////////////////
420

    
421
  public boolean canPlay()
422
    {
423
    return mCanPlay;
424
    }
425

    
426
///////////////////////////////////////////////////////////////////////////////////////////////////
427

    
428
  void setQuatCurrentOnNextRender()
429
    {
430
    mSetQuatCurrent = true;
431
    }
432

    
433
///////////////////////////////////////////////////////////////////////////////////////////////////
434

    
435
  void setQuatAccumulatedOnNextRender()
436
    {
437
    mSetQuatAccumulated = true;
438
    }
439

    
440
///////////////////////////////////////////////////////////////////////////////////////////////////
441

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

    
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460
// PUBLIC API
461
///////////////////////////////////////////////////////////////////////////////////////////////////
462

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

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

    
474
///////////////////////////////////////////////////////////////////////////////////////////////////
475

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

    
482
///////////////////////////////////////////////////////////////////////////////////////////////////
483

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

    
493
///////////////////////////////////////////////////////////////////////////////////////////////////
494

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

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

    
505
  public void resetAllTextureMaps()
506
    {
507
    mResetAllTextureMaps = true;
508
    }
509

    
510
///////////////////////////////////////////////////////////////////////////////////////////////////
511

    
512
  public RubikObject getObject()
513
    {
514
    return mNewObject;
515
    }
516

    
517
///////////////////////////////////////////////////////////////////////////////////////////////////
518

    
519
  public RubikObject getOldObject()
520
    {
521
    return mOldObject;
522
    }
523

    
524
///////////////////////////////////////////////////////////////////////////////////////////////////
525

    
526
  public int getNumScrambles()
527
    {
528
    return mScrambleObjectNum;
529
    }
530

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

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

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

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

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

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

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

    
601
          break;
602
          }
603
        }
604
      }
605
    }
606
  }
(2-2/4)