Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikRenderer.java @ 53f23b64

1 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4 fdec60a3 Leszek Koltunski
// This file is part of Magic Cube.                                                              //
5 0c52af30 Leszek Koltunski
//                                                                                               //
6 fdec60a3 Leszek Koltunski
// Magic Cube is free software: you can redistribute it and/or modify                            //
7 0c52af30 Leszek Koltunski
// 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 fdec60a3 Leszek Koltunski
// Magic Cube is distributed in the hope that it will be useful,                                 //
12 0c52af30 Leszek Koltunski
// 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 fdec60a3 Leszek Koltunski
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20
package org.distorted.magic;
21
22 0333d81e Leszek Koltunski
import android.content.SharedPreferences;
23 0c52af30 Leszek Koltunski
import android.opengl.GLSurfaceView;
24 e41e7dc3 Leszek Koltunski
import android.os.Bundle;
25 0c52af30 Leszek Koltunski
26 bc511ea5 Leszek Koltunski
import org.distorted.dialog.RubikDialogNewRecord;
27 e41e7dc3 Leszek Koltunski
import org.distorted.dialog.RubikDialogSolved;
28 64975793 Leszek Koltunski
import org.distorted.effect.BaseEffect;
29 0c52af30 Leszek Koltunski
import org.distorted.library.effect.VertexEffectSink;
30 e1111500 Leszek Koltunski
import org.distorted.library.main.DistortedLibrary;
31 0c52af30 Leszek Koltunski
import org.distorted.library.main.DistortedScreen;
32
import org.distorted.library.message.EffectListener;
33 4f9f99a2 Leszek Koltunski
import org.distorted.object.RubikObject;
34 27a70eae Leszek Koltunski
import org.distorted.object.RubikObjectList;
35 c3ffcf58 Leszek Koltunski
import org.distorted.scores.RubikScores;
36 211b48f2 Leszek Koltunski
import org.distorted.uistate.RubikState;
37 0333d81e Leszek Koltunski
import org.distorted.uistate.RubikStateSolving;
38 0c52af30 Leszek Koltunski
39
import javax.microedition.khronos.egl.EGLConfig;
40
import javax.microedition.khronos.opengles.GL10;
41
42
///////////////////////////////////////////////////////////////////////////////////////////////////
43
44 9208e27b Leszek Koltunski
public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
45 0c52af30 Leszek Koltunski
{
46 ba740a0c Leszek Koltunski
    public static final int NODE_FBO_SIZE = 600;
47 0c52af30 Leszek Koltunski
48
    private RubikSurfaceView mView;
49
    private DistortedScreen mScreen;
50 27a70eae Leszek Koltunski
    private RubikObjectList mNextObject;
51 4888e97c Leszek Koltunski
    private int mNextSize;
52 27a70eae Leszek Koltunski
    private int mScrambleObjectNum;
53 64975793 Leszek Koltunski
    private long mRotationFinishedID;
54
    private long[] mEffectID;
55 05fa94d9 Leszek Koltunski
    private boolean mFinishRotation, mRemoveRotation, mSetQuatCurrent, mSetQuatAccumulated;
56 27a70eae Leszek Koltunski
    private boolean mChangeObject, mSolveObject, mScrambleObject;
57 45686da2 Leszek Koltunski
    private boolean mCanRotate, mCanDrag, mCanUI;
58 47ba5ddc Leszek Koltunski
    private boolean mIsSolved;
59 e41e7dc3 Leszek Koltunski
    private boolean mIsNewRecord;
60
    private long mNewRecord;
61 27a70eae Leszek Koltunski
    private RubikObject mOldObject, mNewObject;
62 d1484aba Leszek Koltunski
    private int mScreenWidth, mScreenHeight;
63 5bfc1b49 Leszek Koltunski
    private SharedPreferences mPreferences;
64 9208e27b Leszek Koltunski
65 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
66
67
    RubikRenderer(RubikSurfaceView v)
68
      {
69
      mView = v;
70
      mScreen = new DistortedScreen();
71
72 27a70eae Leszek Koltunski
      mOldObject = null;
73
      mNewObject = null;
74 434f2f5a Leszek Koltunski
75 d1484aba Leszek Koltunski
      mScreenWidth = mScreenHeight = 0;
76 27a70eae Leszek Koltunski
      mScrambleObjectNum = 0;
77 d1484aba Leszek Koltunski
78 05fa94d9 Leszek Koltunski
      mFinishRotation     = false;
79
      mRemoveRotation     = false;
80
      mSetQuatCurrent     = false;
81
      mSetQuatAccumulated = false;
82 27a70eae Leszek Koltunski
      mChangeObject       = false;
83
      mSolveObject        = false;
84
      mScrambleObject     = false;
85 0c52af30 Leszek Koltunski
86 2ecf0c21 Leszek Koltunski
      mCanRotate   = true;
87
      mCanDrag     = true;
88 45686da2 Leszek Koltunski
      mCanUI       = true;
89 9208e27b Leszek Koltunski
90 64975793 Leszek Koltunski
      mEffectID = new long[BaseEffect.Type.LENGTH];
91 0c52af30 Leszek Koltunski
      }
92
93 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
94
95 4888e97c Leszek Koltunski
   private void createObjectNow(RubikObjectList object, int size)
96 47ba5ddc Leszek Koltunski
     {
97 27a70eae Leszek Koltunski
     boolean firstTime = (mNewObject==null);
98 5bfc1b49 Leszek Koltunski
99 27a70eae Leszek Koltunski
     if( mOldObject!=null ) mOldObject.releaseResources();
100
     mOldObject = mNewObject;
101 47ba5ddc Leszek Koltunski
102 4888e97c Leszek Koltunski
     mNewObject = object.create(size, mView.getQuatCurrent(), mView.getQuatAccumulated());
103 27a70eae Leszek Koltunski
     mNewObject.createTexture();
104
     mView.setMovement(object.getObjectMovementClass());
105
106
     if( firstTime ) mNewObject.restorePreferences(mPreferences);
107 47ba5ddc Leszek Koltunski
108
     if( mScreenWidth!=0 )
109
       {
110 27a70eae Leszek Koltunski
       mNewObject.recomputeScaleFactor(mScreenWidth, mScreenHeight);
111 47ba5ddc Leszek Koltunski
       }
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 beb325a0 Leszek Koltunski
     try
124
       {
125
       mEffectID[index] = type.startEffect(this);
126
       }
127
     catch( Exception ex )
128 47ba5ddc Leszek Koltunski
       {
129 beb325a0 Leszek Koltunski
       android.util.Log.e("renderer", "exception starting effect: "+ex.getMessage());
130
131 47ba5ddc Leszek Koltunski
       mCanUI     = true;
132
       mCanRotate = true;
133
       mCanDrag   = true;
134
       }
135
     }
136
137 0333d81e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
138
139
   void savePreferences(SharedPreferences.Editor editor)
140
     {
141 3c4a326c Leszek Koltunski
     if( mNewObject!=null )
142
       {
143
       mNewObject.savePreferences(editor);
144
       }
145 0333d81e Leszek Koltunski
     }
146
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148
149
   void restorePreferences(SharedPreferences preferences)
150
     {
151 5bfc1b49 Leszek Koltunski
     mPreferences = preferences;
152 0333d81e Leszek Koltunski
     }
153
154 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
155
// no this will not race with onDrawFrame
156
157
   void finishRotation()
158
     {
159
     mFinishRotation = true;
160
     }
161
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163
164 53f23b64 Leszek Koltunski
   void createObject(RubikObjectList object, int size)
165 47ba5ddc Leszek Koltunski
     {
166 a6d3b158 Leszek Koltunski
     if( (object!=mNextObject || mNextSize!=size) && size>0 )
167 47ba5ddc Leszek Koltunski
       {
168 27a70eae Leszek Koltunski
       mChangeObject = true;
169
       mNextObject = object;
170 4888e97c Leszek Koltunski
       mNextSize   = size;
171 47ba5ddc Leszek Koltunski
       }
172
     }
173
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175
176 27a70eae Leszek Koltunski
   void scrambleObject(int num)
177 47ba5ddc Leszek Koltunski
     {
178
     if( mCanUI )
179
       {
180 27a70eae Leszek Koltunski
       mScrambleObject = true;
181
       mScrambleObjectNum = num;
182 47ba5ddc Leszek Koltunski
       }
183
     }
184
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186
187 27a70eae Leszek Koltunski
   void solveObject()
188 47ba5ddc Leszek Koltunski
     {
189
     if( mCanUI )
190
       {
191 27a70eae Leszek Koltunski
       mSolveObject = true;
192 47ba5ddc Leszek Koltunski
       }
193
     }
194
195 a6d3b158 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
196
197
   void setCanRotate(boolean can)
198
     {
199
     mCanRotate = can;
200
     }
201
202 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
203
204
   boolean canRotate()
205
     {
206
     return mCanRotate;
207
     }
208
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210
211
   boolean canDrag()
212
     {
213
     return mCanDrag;
214
     }
215
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217
218
   void setQuatCurrentOnNextRender()
219
     {
220
     mSetQuatCurrent = true;
221
     }
222
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224
225
   void setQuatAccumulatedOnNextRender()
226
     {
227
     mSetQuatAccumulated = true;
228
     }
229
230 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
231
// various things are done here delayed, 'after the next render' as not to be done mid-render and
232
// cause artifacts.
233
234 a7a7cc9c Leszek Koltunski
   @Override
235
   public void onDrawFrame(GL10 glUnused)
236
     {
237
     mScreen.render( System.currentTimeMillis() );
238
239
     if( mSetQuatCurrent )
240
       {
241
       mSetQuatCurrent = false;
242
       mView.setQuatCurrent();
243
       }
244
245
     if( mSetQuatAccumulated )
246
       {
247
       mSetQuatAccumulated = false;
248
       mView.setQuatAccumulated();
249
       }
250
251
     if( mFinishRotation )
252
       {
253
       mFinishRotation = false;
254
       mCanRotate      = false;
255
       mCanUI          = false;
256 27a70eae Leszek Koltunski
       mRotationFinishedID = mNewObject.finishRotationNow(this);
257 9cd7695f Leszek Koltunski
258
       if( mRotationFinishedID==0 ) // failed to add effect - should never happen
259
         {
260
         mCanRotate = true;
261
         mCanUI     = true;
262
         }
263 a7a7cc9c Leszek Koltunski
       }
264
265
     if( mRemoveRotation )
266
       {
267
       mRemoveRotation=false;
268 27a70eae Leszek Koltunski
       mNewObject.removeRotationNow();
269 a7a7cc9c Leszek Koltunski
270 27a70eae Leszek Koltunski
       boolean solved = mNewObject.isSolved();
271 a7a7cc9c Leszek Koltunski
272
       if( solved && !mIsSolved )
273
         {
274 0333d81e Leszek Koltunski
         if( RubikState.getCurrentState()==RubikState.SOLV )
275
           {
276
           RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass();
277 e41e7dc3 Leszek Koltunski
           mNewRecord = solving.stopCounting((RubikActivity)mView.getContext());
278
279
           if( mNewRecord< 0 )
280
             {
281
             mNewRecord = -mNewRecord;
282
             mIsNewRecord = false;
283
             }
284
           else
285
             {
286
             mIsNewRecord = true;
287
             }
288 0333d81e Leszek Koltunski
           }
289
290
         mCanDrag   = true;
291
         mCanRotate = false;
292
         mCanUI     = false;
293 a7a7cc9c Leszek Koltunski
         doEffectNow( BaseEffect.Type.WIN );
294
         }
295
       else
296
         {
297
         mCanRotate = true;
298
         mCanUI     = true;
299
         }
300
301
       mIsSolved = solved;
302
       }
303
304 27a70eae Leszek Koltunski
     if( mChangeObject )
305 a7a7cc9c Leszek Koltunski
       {
306 27a70eae Leszek Koltunski
       mChangeObject = false;
307
       mCanDrag      = false;
308
       mCanRotate    = false;
309
       mCanUI        = false;
310 4888e97c Leszek Koltunski
       createObjectNow(mNextObject, mNextSize);
311 a7a7cc9c Leszek Koltunski
       doEffectNow( BaseEffect.Type.SIZECHANGE );
312
       }
313
314 27a70eae Leszek Koltunski
     if( mSolveObject )
315 a7a7cc9c Leszek Koltunski
       {
316 27a70eae Leszek Koltunski
       mSolveObject    = false;
317 a7a7cc9c Leszek Koltunski
       mCanDrag        = false;
318
       mCanRotate      = false;
319
       mCanUI          = false;
320
       doEffectNow( BaseEffect.Type.SOLVE );
321
       }
322
323 27a70eae Leszek Koltunski
     if( mScrambleObject )
324 a7a7cc9c Leszek Koltunski
       {
325 27a70eae Leszek Koltunski
       mScrambleObject = false;
326
       mCanDrag        = false;
327
       mCanRotate      = false;
328
       mCanUI          = false;
329 fec72009 Leszek Koltunski
       mIsSolved       = false;
330 c3ffcf58 Leszek Koltunski
       RubikScores.getInstance().incrementNumPlays();
331 a7a7cc9c Leszek Koltunski
       doEffectNow( BaseEffect.Type.SCRAMBLE );
332
       }
333
     }
334 0c52af30 Leszek Koltunski
335
///////////////////////////////////////////////////////////////////////////////////////////////////
336 aa8b36aa Leszek Koltunski
337
   @Override
338
   public void onSurfaceChanged(GL10 glUnused, int width, int height)
339
      {
340 27a70eae Leszek Koltunski
      if( mNewObject!=null ) mNewObject.createTexture();
341 aa8b36aa Leszek Koltunski
342
      mScreen.resize(width, height);
343 123d6172 Leszek Koltunski
      mView.setScreenSize(width,height);
344 aa8b36aa Leszek Koltunski
345 27a70eae Leszek Koltunski
      if( mNewObject!=null )
346 beb325a0 Leszek Koltunski
        {
347 27a70eae Leszek Koltunski
        mNewObject.recomputeScaleFactor(width,height);
348 beb325a0 Leszek Koltunski
        }
349 aa8b36aa Leszek Koltunski
350
      mScreenHeight = height;
351
      mScreenWidth  = width;
352
      }
353
354
///////////////////////////////////////////////////////////////////////////////////////////////////
355
356
   @Override
357
   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
358
      {
359
      VertexEffectSink.enable();
360 64975793 Leszek Koltunski
      BaseEffect.Type.enableEffects();
361 aa8b36aa Leszek Koltunski
362
      try
363
        {
364
        DistortedLibrary.onCreate(mView.getContext());
365
        }
366
      catch(Exception ex)
367
        {
368
        android.util.Log.e("Rubik", ex.getMessage() );
369
        }
370
      }
371
372 ad9e8bb3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
373
// PUBLIC API
374 aa8b36aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
375 0c52af30 Leszek Koltunski
376 f647630d Leszek Koltunski
   public void effectFinished(final long effectID)
377 0c52af30 Leszek Koltunski
     {
378 45686da2 Leszek Koltunski
     if( effectID == mRotationFinishedID )
379 434f2f5a Leszek Koltunski
       {
380
       mRemoveRotation = true;
381
       }
382 45686da2 Leszek Koltunski
     else
383 3b12e641 Leszek Koltunski
       {
384 45686da2 Leszek Koltunski
       for(int i=0; i<BaseEffect.Type.LENGTH; i++)
385
         {
386
         if( effectID == mEffectID[i] )
387
           {
388
           mCanRotate   = true;
389
           mCanDrag     = true;
390
           mCanUI       = true;
391 ad9e8bb3 Leszek Koltunski
392
           if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
393
             {
394
             final RubikActivity act = (RubikActivity)mView.getContext();
395
396
             act.runOnUiThread(new Runnable()
397
               {
398
               @Override
399
               public void run()
400
                 {
401
                 RubikState.switchState( act, RubikState.SOLV);
402
                 }
403
               });
404
             }
405 e41e7dc3 Leszek Koltunski
406
           if( i==BaseEffect.Type.WIN.ordinal() )
407
             {
408
             if( RubikState.getCurrentState()==RubikState.SOLV )
409
               {
410
               final RubikActivity act = (RubikActivity)mView.getContext();
411 bc511ea5 Leszek Koltunski
               Bundle bundle = new Bundle();
412
               bundle.putLong("time", mNewRecord );
413 e41e7dc3 Leszek Koltunski
414
               if( mIsNewRecord )
415
                 {
416 bc511ea5 Leszek Koltunski
                 RubikDialogNewRecord dialog = new RubikDialogNewRecord();
417 e41e7dc3 Leszek Koltunski
                 dialog.setArguments(bundle);
418
                 dialog.show( act.getSupportFragmentManager(), null);
419
                 }
420
               else
421
                 {
422
                 RubikDialogSolved dialog = new RubikDialogSolved();
423
                 dialog.setArguments(bundle);
424
                 dialog.show( act.getSupportFragmentManager(), null);
425
                 }
426
               }
427
             }
428
429 45686da2 Leszek Koltunski
           break;
430
           }
431
         }
432 3b12e641 Leszek Koltunski
       }
433 34747dd1 Leszek Koltunski
     }
434 f291130e Leszek Koltunski
435 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
436
437 27a70eae Leszek Koltunski
   public RubikObject getObject()
438 8197c92d Leszek Koltunski
     {
439 27a70eae Leszek Koltunski
     return mNewObject;
440 8197c92d Leszek Koltunski
     }
441
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443
444 27a70eae Leszek Koltunski
   public RubikObject getOldObject()
445 8197c92d Leszek Koltunski
     {
446 27a70eae Leszek Koltunski
     return mOldObject;
447 8197c92d Leszek Koltunski
     }
448
449 434f2f5a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
450
451 64975793 Leszek Koltunski
   public DistortedScreen getScreen()
452 434f2f5a Leszek Koltunski
     {
453 64975793 Leszek Koltunski
     return mScreen;
454 434f2f5a Leszek Koltunski
     }
455
456 8197c92d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
457
458 64975793 Leszek Koltunski
   public int getNumScrambles()
459 8197c92d Leszek Koltunski
     {
460 27a70eae Leszek Koltunski
     return mScrambleObjectNum;
461 8197c92d Leszek Koltunski
     }
462 0c52af30 Leszek Koltunski
}