Project

General

Profile

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

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

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, 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

    
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
    mCanPlay   = true;
84

    
85
    mOldObject = null;
86
    mNewObject = null;
87

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

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

    
94
///////////////////////////////////////////////////////////////////////////////////////////////////
95

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

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

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

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

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

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

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

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

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

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

    
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

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

    
144
    boolean solved = mNewObject.isSolved();
145

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

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

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

    
174
    mIsSolved = solved;
175
    }
176

    
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178

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

    
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

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

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

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

    
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201

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

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

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

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

    
225
///////////////////////////////////////////////////////////////////////////////////////////////////
226

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

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

    
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245

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

    
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257

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

    
266
///////////////////////////////////////////////////////////////////////////////////////////////////
267

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

    
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275

    
276
  private void setQuatCurrentNow()
277
    {
278
    mSetQuatCurrent = false;
279
    mView.setQuatCurrent();
280
    }
281

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

    
284
  private void setQuatAccumulatedNow()
285
    {
286
    mSetQuatAccumulated = false;
287
    mView.setQuatAccumulated();
288
    }
289

    
290
///////////////////////////////////////////////////////////////////////////////////////////////////
291
//
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293

    
294
  void setScreenSize(int width, int height)
295
    {
296
    if( mNewObject!=null )
297
      {
298
      mNewObject.createTexture();
299
      mNewObject.recomputeScaleFactor(width,height);
300
      }
301

    
302
    mScreenHeight = height;
303
    mScreenWidth  = width;
304
    }
305

    
306
///////////////////////////////////////////////////////////////////////////////////////////////////
307

    
308
  void savePreferences(SharedPreferences.Editor editor)
309
    {
310
    if( mNewObject!=null )
311
      {
312
      mNewObject.savePreferences(editor);
313
      }
314
    }
315

    
316
///////////////////////////////////////////////////////////////////////////////////////////////////
317

    
318
  void restorePreferences(SharedPreferences preferences)
319
    {
320
    mPreferences = preferences;
321
    }
322

    
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324

    
325
  void finishRotation()
326
    {
327
    mFinishRotation = true;
328
    }
329

    
330
///////////////////////////////////////////////////////////////////////////////////////////////////
331

    
332
  void changeObject(RubikObjectList object, int size, int[][] moves)
333
    {
334
    if( size>0 )
335
      {
336
      mChangeObject = true;
337
      mNextObject = object;
338
      mNextSize   = size;
339
      mNextMoves  = moves;
340
      }
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

    
345
  void scrambleObject(int num)
346
    {
347
    if( mCanPlay )
348
      {
349
      mScrambleObject = true;
350
      mScrambleObjectNum = num;
351
      }
352
    }
353

    
354
///////////////////////////////////////////////////////////////////////////////////////////////////
355

    
356
  void solveObject()
357
    {
358
    if( mCanPlay )
359
      {
360
      mSolveObject = true;
361
      }
362
    }
363

    
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365

    
366
  boolean canRotate()
367
    {
368
    return mCanRotate;
369
    }
370

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

    
373
  public boolean canPlay()
374
    {
375
    return mCanPlay;
376
    }
377

    
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379

    
380
  void setQuatCurrentOnNextRender()
381
    {
382
    mSetQuatCurrent = true;
383
    }
384

    
385
///////////////////////////////////////////////////////////////////////////////////////////////////
386

    
387
  void setQuatAccumulatedOnNextRender()
388
    {
389
    mSetQuatAccumulated = true;
390
    }
391

    
392
///////////////////////////////////////////////////////////////////////////////////////////////////
393

    
394
  void postRender()
395
    {
396
    if( mSetQuatCurrent        ) setQuatCurrentNow();
397
    if( mSetQuatAccumulated    ) setQuatAccumulatedNow();
398
    if( mFinishRotation        ) finishRotationNow();
399
    if( mRemoveRotation        ) removeRotationNow();
400
    if( mRemovePatternRotation ) removePatternRotationNow();
401
    if( mChangeObject          ) changeObjectNow();
402
    if( mSolveObject           ) solveObjectNow();
403
    if( mScrambleObject        ) scrambleObjectNow();
404
    if( mAddRotation           ) addRotationNow();
405
    if( mInitializeObject      ) initializeObjectNow();
406
    }
407

    
408
///////////////////////////////////////////////////////////////////////////////////////////////////
409
// PUBLIC API
410
///////////////////////////////////////////////////////////////////////////////////////////////////
411

    
412
  public void addRotation(ActionFinishedListener listener, int axis, int rowBitmap, int angle, long duration)
413
    {
414
    mAddRotation = true;
415

    
416
    mAddActionListener    = listener;
417
    mAddRotationAxis      = axis;
418
    mAddRotationRowBitmap = rowBitmap;
419
    mAddRotationAngle     = angle;
420
    mAddRotationDuration  = duration;
421
    }
422

    
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424

    
425
  public void initializeObject(int[][] moves)
426
    {
427
    mInitializeObject = true;
428
    mNextMoves = moves;
429
    }
430

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

    
433
  public RubikObject getObject()
434
    {
435
    return mNewObject;
436
    }
437

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

    
440
  public RubikObject getOldObject()
441
    {
442
    return mOldObject;
443
    }
444

    
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446

    
447
  public int getNumScrambles()
448
    {
449
    return mScrambleObjectNum;
450
    }
451

    
452
///////////////////////////////////////////////////////////////////////////////////////////////////
453

    
454
  public void effectFinished(final long effectID)
455
    {
456
    if( effectID == mRotationFinishedID )
457
      {
458
      mRotationFinishedID = 0;
459
      removeRotation();
460
      }
461
    else if( effectID == mAddRotationID )
462
      {
463
      mAddRotationID = 0;
464
      mRemoveRotationID = effectID;
465
      removePatternRotation();
466
      }
467
    else
468
      {
469
      for(int i=0; i<BaseEffect.Type.LENGTH; i++)
470
        {
471
        if( effectID == mEffectID[i] )
472
          {
473
          mCanRotate = true;
474
          mCanPlay   = true;
475

    
476
          if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
477
            {
478
            final RubikActivity act = (RubikActivity)mView.getContext();
479

    
480
            act.runOnUiThread(new Runnable()
481
              {
482
              @Override
483
              public void run()
484
                {
485
                RubikState.switchState( act, RubikState.SOLV);
486
                }
487
              });
488
            }
489

    
490
          if( i==BaseEffect.Type.WIN.ordinal() )
491
            {
492
            if( RubikState.getCurrentState()==RubikState.SOLV )
493
              {
494
              final RubikActivity act = (RubikActivity)mView.getContext();
495
              Bundle bundle = new Bundle();
496
              bundle.putLong("time", mNewRecord );
497

    
498
              if( mIsNewRecord )
499
                {
500
                RubikDialogNewRecord dialog = new RubikDialogNewRecord();
501
                dialog.setArguments(bundle);
502
                dialog.show( act.getSupportFragmentManager(), null);
503
                }
504
              else
505
                {
506
                RubikDialogSolved dialog = new RubikDialogSolved();
507
                dialog.setArguments(bundle);
508
                dialog.show( act.getSupportFragmentManager(), null);
509
                }
510
              }
511
            }
512

    
513
          break;
514
          }
515
        }
516
      }
517
    }
518
  }
(2-2/4)