Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikPostRender.java @ fb6a40c8

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.magic;
21

    
22
import android.content.SharedPreferences;
23
import android.os.Bundle;
24

    
25
import org.distorted.dialog.RubikDialogNewRecord;
26
import org.distorted.dialog.RubikDialogSolved;
27
import org.distorted.effect.BaseEffect;
28
import org.distorted.library.message.EffectListener;
29
import org.distorted.object.RubikObject;
30
import org.distorted.object.RubikObjectList;
31
import org.distorted.scores.RubikScores;
32
import org.distorted.uistate.RubikState;
33
import org.distorted.uistate.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;
48
  private boolean mCanRotate, mCanDrag, mCanUI;
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

    
66
///////////////////////////////////////////////////////////////////////////////////////////////////
67

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

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

    
82
    mCanRotate   = true;
83
    mCanDrag     = true;
84
    mCanUI       = 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
      mCanUI     = true;
134
      mCanRotate = true;
135
      mCanDrag   = true;
136
      }
137
    }
138

    
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140

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

    
146
    boolean solved = mNewObject.isSolved();
147

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

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

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

    
177
    mIsSolved = solved;
178
    }
179

    
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181

    
182
  private void removeRotation()
183
    {
184
    mRemoveRotation = true;
185
    }
186

    
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

    
189
  private void removePatternRotation()
190
    {
191
    mRemovePatternRotation = true;
192
    }
193

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

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

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

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

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

    
214
  private void finishRotationNow()
215
    {
216
    mFinishRotation = false;
217
    mCanRotate      = false;
218
    mCanUI          = false;
219
    mRotationFinishedID = mNewObject.finishRotationNow(this);
220

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

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  private void changeObjectNow()
231
    {
232
    mChangeObject = false;
233

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

    
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249

    
250
  private void scrambleObjectNow()
251
    {
252
    mScrambleObject = false;
253
    mCanDrag        = false;
254
    mCanRotate      = false;
255
    mCanUI          = false;
256
    mIsSolved       = false;
257
    RubikScores.getInstance().incrementNumPlays();
258
    doEffectNow( BaseEffect.Type.SCRAMBLE );
259
    }
260

    
261
///////////////////////////////////////////////////////////////////////////////////////////////////
262

    
263
  private void solveObjectNow()
264
    {
265
    mSolveObject    = false;
266
    mCanDrag        = false;
267
    mCanRotate      = false;
268
    mCanUI          = false;
269
    doEffectNow( BaseEffect.Type.SOLVE );
270
    }
271

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

    
274
  private void initializeObjectNow()
275
    {
276
    mInitializeObject = false;
277
    mNewObject.initializeObject(mNextMoves);
278
    }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281

    
282
  private void setQuatCurrentNow()
283
    {
284
    mSetQuatCurrent = false;
285
    mView.setQuatCurrent();
286
    }
287

    
288
///////////////////////////////////////////////////////////////////////////////////////////////////
289

    
290
  private void setQuatAccumulatedNow()
291
    {
292
    mSetQuatAccumulated = false;
293
    mView.setQuatAccumulated();
294
    }
295

    
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297
//
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299

    
300
  void setScreenSize(int width, int height)
301
    {
302
    if( mNewObject!=null )
303
      {
304
      mNewObject.createTexture();
305
      mNewObject.recomputeScaleFactor(width,height);
306
      }
307

    
308
    mScreenHeight = height;
309
    mScreenWidth  = width;
310
    }
311

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

    
314
  void savePreferences(SharedPreferences.Editor editor)
315
    {
316
    if( mNewObject!=null )
317
      {
318
      mNewObject.savePreferences(editor);
319
      }
320
    }
321

    
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323

    
324
  void restorePreferences(SharedPreferences preferences)
325
    {
326
    mPreferences = preferences;
327
    }
328

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

    
331
  void finishRotation()
332
    {
333
    mFinishRotation = true;
334
    }
335

    
336
///////////////////////////////////////////////////////////////////////////////////////////////////
337

    
338
  void changeObject(RubikObjectList object, int size, int[][] moves)
339
    {
340
    if( size>0 )
341
      {
342
      mChangeObject = true;
343
      mNextObject = object;
344
      mNextSize   = size;
345
      mNextMoves  = moves;
346
      }
347
    }
348

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

    
351
  void scrambleObject(int num)
352
    {
353
    if( mCanUI )
354
      {
355
      mScrambleObject = true;
356
      mScrambleObjectNum = num;
357
      }
358
    }
359

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

    
362
  void solveObject()
363
    {
364
    if( mCanUI )
365
      {
366
      mSolveObject = true;
367
      }
368
    }
369

    
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371

    
372
  boolean canRotate()
373
    {
374
    return mCanRotate;
375
    }
376

    
377
///////////////////////////////////////////////////////////////////////////////////////////////////
378

    
379
  boolean canDrag()
380
    {
381
    return mCanDrag;
382
    }
383

    
384
///////////////////////////////////////////////////////////////////////////////////////////////////
385

    
386
  void setQuatCurrentOnNextRender()
387
    {
388
    mSetQuatCurrent = true;
389
    }
390

    
391
///////////////////////////////////////////////////////////////////////////////////////////////////
392

    
393
  void setQuatAccumulatedOnNextRender()
394
    {
395
    mSetQuatAccumulated = true;
396
    }
397

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

    
400
  void postRender()
401
    {
402
    if( mSetQuatCurrent        ) setQuatCurrentNow();
403
    if( mSetQuatAccumulated    ) setQuatAccumulatedNow();
404
    if( mFinishRotation        ) finishRotationNow();
405
    if( mRemoveRotation        ) removeRotationNow();
406
    if( mRemovePatternRotation ) removePatternRotationNow();
407
    if( mChangeObject          ) changeObjectNow();
408
    if( mSolveObject           ) solveObjectNow();
409
    if( mScrambleObject        ) scrambleObjectNow();
410
    if( mAddRotation           ) addRotationNow();
411
    if( mInitializeObject      ) initializeObjectNow();
412
    }
413

    
414
///////////////////////////////////////////////////////////////////////////////////////////////////
415
// PUBLIC API
416
///////////////////////////////////////////////////////////////////////////////////////////////////
417

    
418
  public void addRotation(ActionFinishedListener listener, int axis, int rowBitmap, int angle, long duration)
419
    {
420
    mAddRotation = true;
421

    
422
    mAddActionListener    = listener;
423
    mAddRotationAxis      = axis;
424
    mAddRotationRowBitmap = rowBitmap;
425
    mAddRotationAngle     = angle;
426
    mAddRotationDuration  = duration;
427
    }
428

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430

    
431
  public void initializeObject(int[][] moves)
432
    {
433
    mInitializeObject = true;
434
    mNextMoves = moves;
435
    }
436

    
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438

    
439
  public RubikObject getObject()
440
    {
441
    return mNewObject;
442
    }
443

    
444
///////////////////////////////////////////////////////////////////////////////////////////////////
445

    
446
  public RubikObject getOldObject()
447
    {
448
    return mOldObject;
449
    }
450

    
451
///////////////////////////////////////////////////////////////////////////////////////////////////
452

    
453
  public int getNumScrambles()
454
    {
455
    return mScrambleObjectNum;
456
    }
457

    
458
///////////////////////////////////////////////////////////////////////////////////////////////////
459

    
460
  public void effectFinished(final long effectID)
461
    {
462
    if( effectID == mRotationFinishedID )
463
      {
464
      mRotationFinishedID = 0;
465
      removeRotation();
466
      }
467
    else if( effectID == mAddRotationID )
468
      {
469
      mAddRotationID = 0;
470
      mRemoveRotationID = effectID;
471
      removePatternRotation();
472
      }
473
    else
474
      {
475
      for(int i=0; i<BaseEffect.Type.LENGTH; i++)
476
        {
477
        if( effectID == mEffectID[i] )
478
          {
479
          mCanRotate   = true;
480
          mCanDrag     = true;
481
          mCanUI       = true;
482

    
483
          if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
484
            {
485
            final RubikActivity act = (RubikActivity)mView.getContext();
486

    
487
            act.runOnUiThread(new Runnable()
488
              {
489
              @Override
490
              public void run()
491
                {
492
                RubikState.switchState( act, RubikState.SOLV);
493
                }
494
              });
495
            }
496

    
497
          if( i==BaseEffect.Type.WIN.ordinal() )
498
            {
499
            if( RubikState.getCurrentState()==RubikState.SOLV )
500
              {
501
              final RubikActivity act = (RubikActivity)mView.getContext();
502
              Bundle bundle = new Bundle();
503
              bundle.putLong("time", mNewRecord );
504

    
505
              if( mIsNewRecord )
506
                {
507
                RubikDialogNewRecord dialog = new RubikDialogNewRecord();
508
                dialog.setArguments(bundle);
509
                dialog.show( act.getSupportFragmentManager(), null);
510
                }
511
              else
512
                {
513
                RubikDialogSolved dialog = new RubikDialogSolved();
514
                dialog.setArguments(bundle);
515
                dialog.show( act.getSupportFragmentManager(), null);
516
                }
517
              }
518
            }
519

    
520
          break;
521
          }
522
        }
523
      }
524
    }
525
  }
(2-2/4)