Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikRenderer.java @ 714292f1

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 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.opengl.GLSurfaceView;
24

    
25
import org.distorted.effect.BaseEffect;
26
import org.distorted.library.effect.VertexEffectSink;
27
import org.distorted.library.main.DistortedLibrary;
28
import org.distorted.library.main.DistortedScreen;
29
import org.distorted.library.message.EffectListener;
30
import org.distorted.object.RubikObject;
31
import org.distorted.object.RubikObjectList;
32
import org.distorted.uistate.RubikState;
33
import org.distorted.uistate.RubikStateSolving;
34

    
35
import javax.microedition.khronos.egl.EGLConfig;
36
import javax.microedition.khronos.opengles.GL10;
37

    
38
///////////////////////////////////////////////////////////////////////////////////////////////////
39

    
40
public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
41
{
42
    public static final int NODE_FBO_SIZE = 600;
43

    
44
    private RubikSurfaceView mView;
45
    private DistortedScreen mScreen;
46
    private RubikObjectList mNextObject;
47
    private int mNextSize;
48
    private int mScrambleObjectNum;
49
    private long mRotationFinishedID;
50
    private long[] mEffectID;
51
    private boolean mFinishRotation, mRemoveRotation, mSetQuatCurrent, mSetQuatAccumulated;
52
    private boolean mChangeObject, mSolveObject, mScrambleObject;
53
    private boolean mCanRotate, mCanDrag, mCanUI;
54
    private boolean mIsSolved;
55
    private RubikObject mOldObject, mNewObject;
56
    private int mScreenWidth, mScreenHeight;
57
    private SharedPreferences mPreferences;
58

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

    
61
    RubikRenderer(RubikSurfaceView v)
62
      {
63
      mView = v;
64
      mScreen = new DistortedScreen();
65

    
66
      mOldObject = null;
67
      mNewObject = null;
68

    
69
      mScreenWidth = mScreenHeight = 0;
70
      mScrambleObjectNum = 0;
71

    
72
      mFinishRotation     = false;
73
      mRemoveRotation     = 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
      mEffectID = new long[BaseEffect.Type.LENGTH];
85
      }
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

    
89
   private void createObjectNow(RubikObjectList object, int size)
90
     {
91
     boolean firstTime = (mNewObject==null);
92

    
93
     if( mOldObject!=null ) mOldObject.releaseResources();
94
     mOldObject = mNewObject;
95

    
96
     mNewObject = object.create(size, mView.getQuatCurrent(), mView.getQuatAccumulated());
97
     mNewObject.createTexture();
98
     mView.setMovement(object.getObjectMovementClass());
99

    
100
     if( firstTime ) mNewObject.restorePreferences(mPreferences);
101

    
102
     if( mScreenWidth!=0 )
103
       {
104
       mNewObject.recomputeScaleFactor(mScreenWidth, mScreenHeight);
105
       }
106

    
107
     mIsSolved = true;
108
     }
109

    
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111
// do all 'adjustable' effects (SizeChange, Solve, Scramble)
112

    
113
   private void doEffectNow(BaseEffect.Type type)
114
     {
115
     int index = type.ordinal();
116

    
117
     try
118
       {
119
       mEffectID[index] = type.startEffect(this);
120
       }
121
     catch( Exception ex )
122
       {
123
       android.util.Log.e("renderer", "exception starting effect: "+ex.getMessage());
124

    
125
       mCanUI     = true;
126
       mCanRotate = true;
127
       mCanDrag   = true;
128
       }
129
     }
130

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

    
133
   void savePreferences(SharedPreferences.Editor editor)
134
     {
135
     if( mNewObject!=null )
136
       {
137
       mNewObject.savePreferences(editor);
138
       }
139
     }
140

    
141
///////////////////////////////////////////////////////////////////////////////////////////////////
142

    
143
   void restorePreferences(SharedPreferences preferences)
144
     {
145
     mPreferences = preferences;
146
     }
147

    
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149
// no this will not race with onDrawFrame
150

    
151
   void finishRotation()
152
     {
153
     mFinishRotation = true;
154
     }
155

    
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157

    
158
   boolean createObject(RubikObjectList object, int size)
159
     {
160
     if( mCanDrag && mCanRotate && (object!=mNextObject || mNextSize!=size) && size>0 )
161
       {
162
       mChangeObject = true;
163
       mNextObject = object;
164
       mNextSize   = size;
165
       return true;
166
       }
167

    
168
     return false;
169
     }
170

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172

    
173
   void scrambleObject(int num)
174
     {
175
     if( mCanUI )
176
       {
177
       mScrambleObject = true;
178
       mScrambleObjectNum = num;
179
       }
180
     }
181

    
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183

    
184
   void solveObject()
185
     {
186
     if( mCanUI )
187
       {
188
       mSolveObject = true;
189
       }
190
     }
191

    
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193

    
194
   boolean canRotate()
195
     {
196
     return mCanRotate;
197
     }
198

    
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200

    
201
   boolean canDrag()
202
     {
203
     return mCanDrag;
204
     }
205

    
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207

    
208
   void setQuatCurrentOnNextRender()
209
     {
210
     mSetQuatCurrent = true;
211
     }
212

    
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214

    
215
   void setQuatAccumulatedOnNextRender()
216
     {
217
     mSetQuatAccumulated = true;
218
     }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221
// various things are done here delayed, 'after the next render' as not to be done mid-render and
222
// cause artifacts.
223

    
224
   @Override
225
   public void onDrawFrame(GL10 glUnused)
226
     {
227
     mScreen.render( System.currentTimeMillis() );
228

    
229
     if( mSetQuatCurrent )
230
       {
231
       mSetQuatCurrent = false;
232
       mView.setQuatCurrent();
233
       }
234

    
235
     if( mSetQuatAccumulated )
236
       {
237
       mSetQuatAccumulated = false;
238
       mView.setQuatAccumulated();
239
       }
240

    
241
     if( mFinishRotation )
242
       {
243
       mFinishRotation = false;
244
       mCanRotate      = false;
245
       mCanUI          = false;
246
       mRotationFinishedID = mNewObject.finishRotationNow(this);
247

    
248
       if( mRotationFinishedID==0 ) // failed to add effect - should never happen
249
         {
250
         mCanRotate = true;
251
         mCanUI     = true;
252
         }
253
       }
254

    
255
     if( mRemoveRotation )
256
       {
257
       mRemoveRotation=false;
258
       mNewObject.removeRotationNow();
259

    
260
       boolean solved = mNewObject.isSolved();
261

    
262
       if( solved && !mIsSolved )
263
         {
264
         if( RubikState.getCurrentState()==RubikState.SOLV )
265
           {
266
           RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass();
267
           solving.stopCounting();
268
           }
269

    
270
         mCanDrag   = true;
271
         mCanRotate = false;
272
         mCanUI     = false;
273
         doEffectNow( BaseEffect.Type.WIN );
274
         }
275
       else
276
         {
277
         mCanRotate = true;
278
         mCanUI     = true;
279
         }
280

    
281
       mIsSolved = solved;
282
       }
283

    
284
     if( mChangeObject )
285
       {
286
       mChangeObject = false;
287
       mCanDrag      = false;
288
       mCanRotate    = false;
289
       mCanUI        = false;
290
       createObjectNow(mNextObject, mNextSize);
291
       doEffectNow( BaseEffect.Type.SIZECHANGE );
292
       }
293

    
294
     if( mSolveObject )
295
       {
296
       mSolveObject    = false;
297
       mCanDrag        = false;
298
       mCanRotate      = false;
299
       mCanUI          = false;
300
       doEffectNow( BaseEffect.Type.SOLVE );
301
       }
302

    
303
     if( mScrambleObject )
304
       {
305
       mScrambleObject = false;
306
       mCanDrag        = false;
307
       mCanRotate      = false;
308
       mCanUI          = false;
309
       mIsSolved       = false;
310
       doEffectNow( BaseEffect.Type.SCRAMBLE );
311
       }
312
     }
313

    
314
///////////////////////////////////////////////////////////////////////////////////////////////////
315

    
316
   @Override
317
   public void onSurfaceChanged(GL10 glUnused, int width, int height)
318
      {
319
      if( mNewObject!=null ) mNewObject.createTexture();
320

    
321
      mScreen.resize(width, height);
322
      mView.setScreenSize(width,height);
323

    
324
      if( mNewObject!=null )
325
        {
326
        mNewObject.recomputeScaleFactor(width,height);
327
        }
328

    
329
      mScreenHeight = height;
330
      mScreenWidth  = width;
331
      }
332

    
333
///////////////////////////////////////////////////////////////////////////////////////////////////
334

    
335
   @Override
336
   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
337
      {
338
      VertexEffectSink.enable();
339
      BaseEffect.Type.enableEffects();
340

    
341
      try
342
        {
343
        DistortedLibrary.onCreate(mView.getContext());
344
        }
345
      catch(Exception ex)
346
        {
347
        android.util.Log.e("Rubik", ex.getMessage() );
348
        }
349
      }
350

    
351
///////////////////////////////////////////////////////////////////////////////////////////////////
352
// PUBLIC API
353
///////////////////////////////////////////////////////////////////////////////////////////////////
354

    
355
   public void effectFinished(final long effectID)
356
     {
357
     if( effectID == mRotationFinishedID )
358
       {
359
       mRemoveRotation = true;
360
       }
361
     else
362
       {
363
       for(int i=0; i<BaseEffect.Type.LENGTH; i++)
364
         {
365
         if( effectID == mEffectID[i] )
366
           {
367
           mCanRotate   = true;
368
           mCanDrag     = true;
369
           mCanUI       = true;
370

    
371
           if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
372
             {
373
             final RubikActivity act = (RubikActivity)mView.getContext();
374

    
375
             act.runOnUiThread(new Runnable()
376
               {
377
               @Override
378
               public void run()
379
                 {
380
                 RubikState.switchState( act, RubikState.SOLV);
381
                 }
382
               });
383
             }
384
           break;
385
           }
386
         }
387
       }
388
     }
389

    
390
///////////////////////////////////////////////////////////////////////////////////////////////////
391

    
392
   public RubikObject getObject()
393
     {
394
     return mNewObject;
395
     }
396

    
397
///////////////////////////////////////////////////////////////////////////////////////////////////
398

    
399
   public RubikObject getOldObject()
400
     {
401
     return mOldObject;
402
     }
403

    
404
///////////////////////////////////////////////////////////////////////////////////////////////////
405

    
406
   public DistortedScreen getScreen()
407
     {
408
     return mScreen;
409
     }
410

    
411
///////////////////////////////////////////////////////////////////////////////////////////////////
412

    
413
   public int getNumScrambles()
414
     {
415
     return mScrambleObjectNum;
416
     }
417
}
(2-2/3)