Project

General

Profile

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

magiccube / src / main / java / org / distorted / magic / RubikRenderer.java @ 84ddf691

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 mScrambleObjectNum;
48
    private long mRotationFinishedID;
49
    private long[] mEffectID;
50
    private boolean mFinishRotation, mRemoveRotation, mSetQuatCurrent, mSetQuatAccumulated;
51
    private boolean mChangeObject, mSolveObject, mScrambleObject;
52
    private boolean mCanRotate, mCanDrag, mCanUI;
53
    private boolean mIsSolved;
54
    private RubikObject mOldObject, mNewObject;
55
    private int mScreenWidth, mScreenHeight;
56
    private SharedPreferences mPreferences;
57

    
58
///////////////////////////////////////////////////////////////////////////////////////////////////
59

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

    
65
      mOldObject = null;
66
      mNewObject = null;
67

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

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

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

    
83
      mEffectID = new long[BaseEffect.Type.LENGTH];
84
      }
85

    
86
///////////////////////////////////////////////////////////////////////////////////////////////////
87

    
88
   private void createObjectNow(RubikObjectList object)
89
     {
90
     boolean firstTime = (mNewObject==null);
91

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

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

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

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

    
106
     mIsSolved = true;
107
     }
108

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

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

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

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

    
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131

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

    
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141

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

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

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

    
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156

    
157
   boolean createObject(RubikObjectList object)
158
     {
159
     if( mCanDrag && mCanRotate && object!=mNextObject )
160
       {
161
       mChangeObject = true;
162
       mNextObject = object;
163
       return true;
164
       }
165

    
166
     return false;
167
     }
168

    
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170

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

    
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181

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

    
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191

    
192
   boolean canRotate()
193
     {
194
     return mCanRotate;
195
     }
196

    
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198

    
199
   boolean canDrag()
200
     {
201
     return mCanDrag;
202
     }
203

    
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205

    
206
   void setQuatCurrentOnNextRender()
207
     {
208
     mSetQuatCurrent = true;
209
     }
210

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

    
213
   void setQuatAccumulatedOnNextRender()
214
     {
215
     mSetQuatAccumulated = true;
216
     }
217

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

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

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

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

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

    
247
     if( mRemoveRotation )
248
       {
249
       mRemoveRotation=false;
250
       mNewObject.removeRotationNow();
251

    
252
       boolean solved = mNewObject.isSolved();
253

    
254
       if( solved && !mIsSolved )
255
         {
256
         if( RubikState.getCurrentState()==RubikState.SOLV )
257
           {
258
           RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass();
259
           long time = solving.stopCounting();
260
           android.util.Log.e("renderer", "solving time: "+time+" milliseconds");
261
           }
262

    
263
         mCanDrag   = true;
264
         mCanRotate = false;
265
         mCanUI     = false;
266
         doEffectNow( BaseEffect.Type.WIN );
267
         }
268
       else
269
         {
270
         mCanRotate = true;
271
         mCanUI     = true;
272
         }
273

    
274
       mIsSolved = solved;
275
       }
276

    
277
     if( mChangeObject )
278
       {
279
       mChangeObject = false;
280
       mCanDrag      = false;
281
       mCanRotate    = false;
282
       mCanUI        = false;
283
       createObjectNow(mNextObject);
284
       doEffectNow( BaseEffect.Type.SIZECHANGE );
285
       }
286

    
287
     if( mSolveObject )
288
       {
289
       mSolveObject    = false;
290
       mCanDrag        = false;
291
       mCanRotate      = false;
292
       mCanUI          = false;
293
       doEffectNow( BaseEffect.Type.SOLVE );
294
       }
295

    
296
     if( mScrambleObject )
297
       {
298
       mScrambleObject = false;
299
       mCanDrag        = false;
300
       mCanRotate      = false;
301
       mCanUI          = false;
302
       doEffectNow( BaseEffect.Type.SCRAMBLE );
303
       }
304
     }
305

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

    
308
   @Override
309
   public void onSurfaceChanged(GL10 glUnused, int width, int height)
310
      {
311
      if( mNewObject!=null ) mNewObject.createTexture();
312

    
313
      mScreen.resize(width, height);
314
      mView.setScreenSize(width,height);
315

    
316
      if( mNewObject!=null )
317
        {
318
        mNewObject.recomputeScaleFactor(width,height);
319
        }
320

    
321
      mScreenHeight = height;
322
      mScreenWidth  = width;
323
      }
324

    
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326

    
327
   @Override
328
   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
329
      {
330
      VertexEffectSink.enable();
331
      BaseEffect.Type.enableEffects();
332

    
333
      try
334
        {
335
        DistortedLibrary.onCreate(mView.getContext());
336
        }
337
      catch(Exception ex)
338
        {
339
        android.util.Log.e("Rubik", ex.getMessage() );
340
        }
341
      }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344
// PUBLIC API
345
///////////////////////////////////////////////////////////////////////////////////////////////////
346

    
347
   public void effectFinished(final long effectID)
348
     {
349
     if( effectID == mRotationFinishedID )
350
       {
351
       mRemoveRotation = true;
352
       }
353
     else
354
       {
355
       for(int i=0; i<BaseEffect.Type.LENGTH; i++)
356
         {
357
         if( effectID == mEffectID[i] )
358
           {
359
           mCanRotate   = true;
360
           mCanDrag     = true;
361
           mCanUI       = true;
362

    
363
           if( i==BaseEffect.Type.SCRAMBLE.ordinal() )
364
             {
365
             final RubikActivity act = (RubikActivity)mView.getContext();
366

    
367
             act.runOnUiThread(new Runnable()
368
               {
369
               @Override
370
               public void run()
371
                 {
372
                 RubikState.switchState( act, RubikState.SOLV);
373
                 }
374
               });
375
             }
376
           break;
377
           }
378
         }
379
       }
380
     }
381

    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383

    
384
   public RubikObject getObject()
385
     {
386
     return mNewObject;
387
     }
388

    
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390

    
391
   public RubikObject getOldObject()
392
     {
393
     return mOldObject;
394
     }
395

    
396
///////////////////////////////////////////////////////////////////////////////////////////////////
397

    
398
   public DistortedScreen getScreen()
399
     {
400
     return mScreen;
401
     }
402

    
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404

    
405
   public int getNumScrambles()
406
     {
407
     return mScrambleObjectNum;
408
     }
409
}
(2-2/3)