Project

General

Profile

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

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

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, mAddRotation, mSetQuatCurrent, mSetQuatAccumulated;
46
  private boolean mChangeObject, mSolveObject, mScrambleObject;
47
  private boolean mCanRotate, mCanDrag, mCanUI;
48
  private boolean mIsSolved;
49
  private RubikObjectList mNextObject;
50
  private int mNextSize;
51
  private long mRotationFinishedID;
52
  private long[] mEffectID;
53
  private boolean mIsNewRecord;
54
  private long mNewRecord;
55
  private int mScreenWidth, mScreenHeight;
56
  private SharedPreferences mPreferences;
57
  private int[][] mNextMoves;
58
  private RubikObject mOldObject, mNewObject;
59
  private int mScrambleObjectNum;
60
  private int mAddRotationAxis, mAddRotationRowBitmap, mAddRotationAngle;
61
  private long mAddRotationDuration;
62
  private ActionFinishedListener mAddActionListener;
63
  private long mAddRotationID;
64

    
65
///////////////////////////////////////////////////////////////////////////////////////////////////
66

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

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

    
80
    mCanRotate   = true;
81
    mCanDrag     = true;
82
    mCanUI       = true;
83

    
84
    mOldObject = null;
85
    mNewObject = null;
86

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

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

    
93
///////////////////////////////////////////////////////////////////////////////////////////////////
94

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

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

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

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

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

    
113
    mIsSolved = true;
114
    }
115

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

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

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

    
131
      mCanUI     = true;
132
      mCanRotate = true;
133
      mCanDrag   = 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
      mCanDrag   = true;
165
      mCanRotate = false;
166
      mCanUI     = false;
167
      doEffectNow( BaseEffect.Type.WIN );
168
      }
169
    else
170
      {
171
      mCanRotate = true;
172
      mCanUI     = 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 addRotationNow()
188
    {
189
    mAddRotation = false;
190

    
191
    mAddRotationID = mNewObject.addNewRotation( mAddRotationAxis, mAddRotationRowBitmap,
192
                                                mAddRotationAngle, mAddRotationDuration, this);
193
    }
194

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

    
197
  private void finishRotationNow()
198
    {
199
    mFinishRotation = false;
200
    mCanRotate      = false;
201
    mCanUI          = false;
202
    mRotationFinishedID = mNewObject.finishRotationNow(this);
203

    
204
    if( mRotationFinishedID==0 ) // failed to add effect - should never happen
205
      {
206
      mCanRotate = true;
207
      mCanUI     = true;
208
      }
209
    }
210

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

    
213
  private void changeObjectNow()
214
    {
215
    mChangeObject = false;
216

    
217
    if ( mNewObject==null || mNewObject.getObjectList()!=mNextObject || mNewObject.getSize()!=mNextSize)
218
      {
219
      mCanDrag      = false;
220
      mCanRotate    = false;
221
      mCanUI        = false;
222
      createObjectNow(mNextObject, mNextSize, mNextMoves);
223
      doEffectNow( BaseEffect.Type.SIZECHANGE );
224
      }
225
    else
226
      {
227
      mNewObject.initializeObject(mNextMoves);
228
      }
229
    }
230

    
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232

    
233
  private void scrambleObjectNow()
234
    {
235
    mScrambleObject = false;
236
    mCanDrag        = false;
237
    mCanRotate      = false;
238
    mCanUI          = false;
239
    mIsSolved       = false;
240
    RubikScores.getInstance().incrementNumPlays();
241
    doEffectNow( BaseEffect.Type.SCRAMBLE );
242
    }
243

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

    
246
  private void solveObjectNow()
247
    {
248
    mSolveObject    = false;
249
    mCanDrag        = false;
250
    mCanRotate      = false;
251
    mCanUI          = false;
252
    doEffectNow( BaseEffect.Type.SOLVE );
253
    }
254

    
255
///////////////////////////////////////////////////////////////////////////////////////////////////
256

    
257
  private void setQuatCurrentNow()
258
    {
259
    mSetQuatCurrent = false;
260
    mView.setQuatCurrent();
261
    }
262

    
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264

    
265
  private void setQuatAccumulatedNow()
266
    {
267
    mSetQuatAccumulated = false;
268
    mView.setQuatAccumulated();
269
    }
270

    
271
///////////////////////////////////////////////////////////////////////////////////////////////////
272
//
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274

    
275
  void setScreenSize(int width, int height)
276
    {
277
    if( mNewObject!=null )
278
      {
279
      mNewObject.createTexture();
280
      mNewObject.recomputeScaleFactor(width,height);
281
      }
282

    
283
    mScreenHeight = height;
284
    mScreenWidth  = width;
285
    }
286

    
287
///////////////////////////////////////////////////////////////////////////////////////////////////
288

    
289
  void savePreferences(SharedPreferences.Editor editor)
290
    {
291
    if( mNewObject!=null )
292
      {
293
      mNewObject.savePreferences(editor);
294
      }
295
    }
296

    
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298

    
299
  void restorePreferences(SharedPreferences preferences)
300
    {
301
    mPreferences = preferences;
302
    }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

    
306
  void finishRotation()
307
    {
308
    mFinishRotation = true;
309
    }
310

    
311
///////////////////////////////////////////////////////////////////////////////////////////////////
312

    
313
  void changeObject(RubikObjectList object, int size, int[][] moves)
314
    {
315
    if( size>0 )
316
      {
317
      mChangeObject = true;
318
      mNextObject = object;
319
      mNextSize   = size;
320
      mNextMoves  = moves;
321
      }
322
    }
323

    
324
///////////////////////////////////////////////////////////////////////////////////////////////////
325

    
326
  void scrambleObject(int num)
327
    {
328
    if( mCanUI )
329
      {
330
      mScrambleObject = true;
331
      mScrambleObjectNum = num;
332
      }
333
    }
334

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

    
337
  void solveObject()
338
    {
339
    if( mCanUI )
340
      {
341
      mSolveObject = true;
342
      }
343
    }
344

    
345
///////////////////////////////////////////////////////////////////////////////////////////////////
346

    
347
  boolean canRotate()
348
    {
349
    return mCanRotate;
350
    }
351

    
352
///////////////////////////////////////////////////////////////////////////////////////////////////
353

    
354
  boolean canDrag()
355
    {
356
    return mCanDrag;
357
    }
358

    
359
///////////////////////////////////////////////////////////////////////////////////////////////////
360

    
361
  void setQuatCurrentOnNextRender()
362
    {
363
    mSetQuatCurrent = true;
364
    }
365

    
366
///////////////////////////////////////////////////////////////////////////////////////////////////
367

    
368
  void setQuatAccumulatedOnNextRender()
369
    {
370
    mSetQuatAccumulated = true;
371
    }
372

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

    
375
  void postRender()
376
    {
377
    if( mSetQuatCurrent     ) setQuatCurrentNow();
378
    if( mSetQuatAccumulated ) setQuatAccumulatedNow();
379
    if( mFinishRotation     ) finishRotationNow();
380
    if( mRemoveRotation     ) removeRotationNow();
381
    if( mChangeObject       ) changeObjectNow();
382
    if( mSolveObject        ) solveObjectNow();
383
    if( mScrambleObject     ) scrambleObjectNow();
384
    if( mAddRotation        ) addRotationNow();
385
    }
386

    
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388
// PUBLIC API
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390

    
391
  public void addRotation(ActionFinishedListener listener, int axis, int rowBitmap, int angle, long duration)
392
    {
393
    mAddRotation = true;
394

    
395
    mAddActionListener    = listener;
396
    mAddRotationAxis      = axis;
397
    mAddRotationRowBitmap = rowBitmap;
398
    mAddRotationAngle     = angle;
399
    mAddRotationDuration  = duration;
400
    }
401

    
402
///////////////////////////////////////////////////////////////////////////////////////////////////
403

    
404
  public RubikObject getObject()
405
    {
406
    return mNewObject;
407
    }
408

    
409
///////////////////////////////////////////////////////////////////////////////////////////////////
410

    
411
  public RubikObject getOldObject()
412
    {
413
    return mOldObject;
414
    }
415

    
416
///////////////////////////////////////////////////////////////////////////////////////////////////
417

    
418
  public int getNumScrambles()
419
    {
420
    return mScrambleObjectNum;
421
    }
422

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

    
425
  public void effectFinished(final long effectID)
426
    {
427
    if( effectID == mRotationFinishedID )
428
      {
429
      mRotationFinishedID = 0;
430
      removeRotation();
431
      }
432
    else if( effectID == mAddRotationID )
433
      {
434
      mAddRotationID = 0;
435
      mAddActionListener.onActionFinished(effectID);
436
      }
437
    else
438
      {
439
      for(int i=0; i<BaseEffect.Type.LENGTH; i++)
440
        {
441
        if( effectID == mEffectID[i] )
442
          {
443
          mCanRotate   = true;
444
          mCanDrag     = true;
445
          mCanUI       = true;
446

    
447
          if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
448
            {
449
            final RubikActivity act = (RubikActivity)mView.getContext();
450

    
451
            act.runOnUiThread(new Runnable()
452
              {
453
              @Override
454
              public void run()
455
                {
456
                RubikState.switchState( act, RubikState.SOLV);
457
                }
458
              });
459
            }
460

    
461
          if( i==BaseEffect.Type.WIN.ordinal() )
462
            {
463
            if( RubikState.getCurrentState()==RubikState.SOLV )
464
              {
465
              final RubikActivity act = (RubikActivity)mView.getContext();
466
              Bundle bundle = new Bundle();
467
              bundle.putLong("time", mNewRecord );
468

    
469
              if( mIsNewRecord )
470
                {
471
                RubikDialogNewRecord dialog = new RubikDialogNewRecord();
472
                dialog.setArguments(bundle);
473
                dialog.show( act.getSupportFragmentManager(), null);
474
                }
475
              else
476
                {
477
                RubikDialogSolved dialog = new RubikDialogSolved();
478
                dialog.setArguments(bundle);
479
                dialog.show( act.getSupportFragmentManager(), null);
480
                }
481
              }
482
            }
483

    
484
          break;
485
          }
486
        }
487
      }
488
    }
489
  }
(2-2/4)