Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikRenderer.java @ e41e7dc3

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