Project

General

Profile

« Previous | Next » 

Revision 7c111294

Added by Leszek Koltunski over 2 years ago

Move PreRender to objectlib.
This code is now shared betweeen the Rubik and Tutorial activities.

View differences:

src/main/java/org/distorted/objectlib/helpers/BlockController.java
27 27

  
28 28
import org.distorted.library.message.EffectMessageSender;
29 29
import org.distorted.objectlib.BuildConfig;
30
import org.distorted.objectlib.main.ObjectPreRender;
30 31

  
31 32
///////////////////////////////////////////////////////////////////////////////////////////////////
32 33

  
......
140 141

  
141 142
        if( act!=null )
142 143
          {
143
          TwistyPreRender pre = act.getTwistyPreRender();
144
          ObjectPreRender pre = act.getPreRender();
144 145
          if( pre!=null )
145 146
            {
146 147
            reallyBlocked = pre.isTouchBlocked();
......
171 172

  
172 173
        if( act!=null )
173 174
          {
174
          TwistyPreRender pre = act.getTwistyPreRender();
175
          ObjectPreRender pre = act.getPreRender();
175 176
          if( pre!=null )
176 177
            {
177 178
            reallyBlocked = !pre.isUINotBlocked();
src/main/java/org/distorted/objectlib/helpers/ObjectSurfaceView.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 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.objectlib.helpers;
21

  
22
import org.distorted.library.main.DistortedScreen;
23
import org.distorted.library.type.Static4D;
24
import org.distorted.objectlib.main.Movement;
25

  
26
///////////////////////////////////////////////////////////////////////////////////////////////////
27

  
28
public interface ObjectSurfaceView
29
  {
30
  TwistyActivity getActivity();
31
  void setMovement(Movement move);
32
  Static4D getQuat();
33
  void setQuat();
34
  DistortedScreen getScreen();
35
  }
src/main/java/org/distorted/objectlib/helpers/TwistyActivity.java
21 21

  
22 22
import androidx.appcompat.app.AppCompatActivity;
23 23

  
24
import org.distorted.objectlib.main.ObjectPreRender;
25

  
24 26
///////////////////////////////////////////////////////////////////////////////////////////////////
25 27

  
26 28
abstract public class TwistyActivity extends AppCompatActivity
......
29 31

  
30 32
///////////////////////////////////////////////////////////////////////////////////////////////////
31 33

  
32
  public abstract TwistyPreRender getTwistyPreRender();
34
  public abstract ObjectPreRender getPreRender();
33 35

  
34 36
///////////////////////////////////////////////////////////////////////////////////////////////////
35 37

  
src/main/java/org/distorted/objectlib/helpers/TwistyPreRender.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 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.objectlib.helpers;
21

  
22
///////////////////////////////////////////////////////////////////////////////////////////////////
23

  
24
import org.distorted.objectlib.helpers.MovesFinished;
25

  
26
public interface TwistyPreRender
27
  {
28
  boolean isTouchBlocked();
29
  boolean isUINotBlocked();
30
  void blockTouch(int place);
31
  void unblockTouch();
32
  void blockEverything(int place);
33
  void unblockEverything();
34
  void unblockUI();
35
  void addRotation(MovesFinished listener, int axis, int rowBitmap, int angle, long duration);
36
  void solveObject();
37
  }
src/main/java/org/distorted/objectlib/main/ObjectPreRender.java
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.objectlib.main;
21

  
22
import android.content.SharedPreferences;
23
import android.content.res.Resources;
24

  
25
import org.distorted.objectlib.helpers.ObjectStateActioner;
26
import org.distorted.objectlib.helpers.ObjectSurfaceView;
27
import org.distorted.objectlib.effects.BaseEffect;
28
import org.distorted.objectlib.effects.EffectController;
29
import org.distorted.objectlib.effects.scramble.ScrambleEffect;
30
import org.distorted.objectlib.helpers.BlockController;
31
import org.distorted.objectlib.helpers.MovesFinished;
32

  
33
///////////////////////////////////////////////////////////////////////////////////////////////////
34

  
35
public class ObjectPreRender implements EffectController
36
  {
37
  private final ObjectSurfaceView mView;
38
  private ObjectType mNextObject;
39
  private TwistyObject mOldObject, mNewObject;
40
  private SharedPreferences mPreferences;
41
  private MovesFinished mAddActionListener;
42
  private final BlockController mBlockController;
43
  private final ObjectStateActioner mActioner;
44
  private String mDebug;
45

  
46
  private boolean mFinishRotation, mRemoveRotation, mRemovePatternRotation, mAddRotation,
47
                  mSetQuat, mChangeObject, mSetupObject, mSolveObject, mScrambleObject,
48
                  mInitializeObject, mSetTextureMap, mResetAllTextureMaps, mSolve;
49
  private boolean mUIBlocked, mTouchBlocked, mIsSolved;
50
  private long mRotationFinishedID;
51
  private final long[] mEffectID;
52
  private int mScreenWidth;
53
  private int[][] mNextMoves;
54
  private int mScrambleObjectNum;
55
  private int mAddRotationAxis, mAddRotationRowBitmap, mAddRotationAngle;
56
  private long mAddRotationDuration;
57
  private long mAddRotationID, mRemoveRotationID;
58
  private int mCubit, mFace, mNewColor;
59
  private int mNearestAngle;
60
  private long mDebugStartTime;
61

  
62
///////////////////////////////////////////////////////////////////////////////////////////////////
63

  
64
  public ObjectPreRender(ObjectSurfaceView view, ObjectStateActioner actioner)
65
    {
66
    mView = view;
67
    mActioner = actioner;
68

  
69
    mFinishRotation       = false;
70
    mRemoveRotation       = false;
71
    mRemovePatternRotation= false;
72
    mAddRotation          = false;
73
    mSetQuat              = false;
74
    mChangeObject         = false;
75
    mSetupObject          = false;
76
    mSolveObject          = false;
77
    mSolve                = false;
78
    mScrambleObject       = false;
79

  
80
    mOldObject = null;
81
    mNewObject = null;
82

  
83
    mDebug = "";
84

  
85
    mScreenWidth = 0;
86
    mScrambleObjectNum = 0;
87

  
88
    mEffectID = new long[BaseEffect.Type.LENGTH];
89

  
90
    mBlockController = new BlockController(mView.getActivity());
91
    unblockEverything();
92
    }
93

  
94
///////////////////////////////////////////////////////////////////////////////////////////////////
95

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

  
100
    if( mOldObject!=null ) mOldObject.releaseResources();
101
    mOldObject = mNewObject;
102
    Resources res = mView.getActivity().getResources();
103

  
104
    mNewObject = object.create(mView.getQuat(), moves, res, mScreenWidth);
105

  
106
    if( mNewObject!=null )
107
      {
108
      mView.setMovement(mNewObject.getMovement());
109
      if( firstTime ) mNewObject.restorePreferences(mPreferences);
110
      mIsSolved = mNewObject.isSolved();
111
      }
112
    }
113

  
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115
// do all 'adjustable' effects (SizeChange, Solve, Scramble)
116

  
117
  private void doEffectNow(BaseEffect.Type type)
118
    {
119
    try
120
      {
121
      int index = type.ordinal();
122
      mEffectID[index] = type.startEffect(mView.getScreen(),this);
123
      }
124
    catch( Exception ex )
125
      {
126
      android.util.Log.e("renderer", "exception starting effect: "+ex.getMessage());
127
      unblockEverything();
128
      }
129
    }
130

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

  
133
  private void removeRotationNow()
134
    {
135
    mRemoveRotation=false;
136
    mNewObject.removeRotationNow();
137

  
138
    boolean solved = mNewObject.isSolved();
139

  
140
    if( solved && !mIsSolved )
141
      {
142
      mActioner.onSolved();
143
      unblockEverything();
144
      doEffectNow( BaseEffect.Type.WIN );
145
      }
146
    else
147
      {
148
      unblockEverything();
149
      }
150

  
151
    mIsSolved = solved;
152
    }
153

  
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155

  
156
  private void removeRotation()
157
    {
158
    mRemoveRotation = true;
159
    }
160

  
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162

  
163
  private void removePatternRotation()
164
    {
165
    mRemovePatternRotation = true;
166
    }
167

  
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169

  
170
  private void removePatternRotationNow()
171
    {
172
    mRemovePatternRotation=false;
173
    mNewObject.removeRotationNow();
174
    mAddActionListener.onActionFinished(mRemoveRotationID);
175
    }
176

  
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178

  
179
  private void addRotationNow()
180
    {
181
    mAddRotation = false;
182
    mAddRotationID = mNewObject.addNewRotation( mAddRotationAxis, mAddRotationRowBitmap,
183
                                                mAddRotationAngle, mAddRotationDuration, this);
184

  
185
    if( mAddRotationID==0 ) // failed to add effect - should never happen
186
      {
187
      unblockEverything();
188
      }
189
    }
190

  
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192

  
193
  private void finishRotationNow()
194
    {
195
    mFinishRotation = false;
196
    blockEverything(BlockController.RUBIK_PLACE_0);
197
    mRotationFinishedID = mNewObject.finishRotationNow(this, mNearestAngle);
198

  
199
    if( mRotationFinishedID==0 ) // failed to add effect - should never happen
200
      {
201
      unblockEverything();
202
      }
203
    }
204

  
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

  
207
  private void changeObjectNow()
208
    {
209
    mChangeObject = false;
210

  
211
    if ( mNewObject==null || mNewObject.getObjectType()!=mNextObject )
212
      {
213
      blockEverything(BlockController.RUBIK_PLACE_1);
214
      createObjectNow(mNextObject, null);
215
      doEffectNow( BaseEffect.Type.SIZECHANGE );
216
      }
217
    }
218

  
219
///////////////////////////////////////////////////////////////////////////////////////////////////
220

  
221
  private void setupObjectNow()
222
    {
223
    mSetupObject = false;
224

  
225
    if ( mNewObject==null || mNewObject.getObjectType()!=mNextObject)
226
      {
227
      blockEverything(BlockController.RUBIK_PLACE_2);
228
      createObjectNow(mNextObject, mNextMoves);
229
      doEffectNow( BaseEffect.Type.SIZECHANGE );
230
      }
231
    else
232
      {
233
      mNewObject.initializeObject(mNextMoves);
234
      }
235
    }
236

  
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238

  
239
  private void scrambleObjectNow()
240
    {
241
    mScrambleObject = false;
242
    mIsSolved       = false;
243
    blockEverything(BlockController.RUBIK_PLACE_3);
244
    doEffectNow( BaseEffect.Type.SCRAMBLE );
245
    }
246

  
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248

  
249
  private void solveObjectNow()
250
    {
251
    mSolveObject = false;
252
    blockEverything(BlockController.RUBIK_PLACE_4);
253
    doEffectNow( BaseEffect.Type.SOLVE );
254
    }
255

  
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257

  
258
  private void solveNow()
259
    {
260
    mSolve = false;
261
    mNewObject.solve();
262
    }
263

  
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265

  
266
  private void initializeObjectNow()
267
    {
268
    mInitializeObject = false;
269
    mNewObject.initializeObject(mNextMoves);
270
    }
271

  
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273

  
274
  private void setTextureMapNow()
275
    {
276
    mSetTextureMap = false;
277

  
278
    if( mNewObject!=null ) mNewObject.setTextureMap(mCubit,mFace,mNewColor);
279
    }
280

  
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282

  
283
  private void resetAllTextureMapsNow()
284
    {
285
    mResetAllTextureMaps = false;
286
    if( mNewObject!=null ) mNewObject.resetAllTextureMaps();
287
    }
288

  
289
///////////////////////////////////////////////////////////////////////////////////////////////////
290

  
291
  private void setQuatNow()
292
    {
293
    mSetQuat = false;
294
    mView.setQuat();
295
    }
296

  
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298
// PUBLIC API
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

  
301
  public void rememberMove(int axis, int row, int angle)
302
    {
303
    mDebug += (" (m "+axis+" "+(1<<row)+" "+angle+" "+(System.currentTimeMillis()-mDebugStartTime)+")");
304
    }
305

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

  
308
  public void setScreenSize(int width)
309
    {
310
    if( mNewObject!=null )
311
      {
312
      mNewObject.createTexture();
313
      mNewObject.recomputeScaleFactor(width);
314
      }
315
    mScreenWidth = width;
316
    }
317

  
318
///////////////////////////////////////////////////////////////////////////////////////////////////
319

  
320
  public void savePreferences(SharedPreferences.Editor editor)
321
    {
322
    if( mNewObject!=null )
323
      {
324
      mNewObject.savePreferences(editor);
325
      }
326
    }
327

  
328
///////////////////////////////////////////////////////////////////////////////////////////////////
329

  
330
  public void restorePreferences(SharedPreferences preferences)
331
    {
332
    mPreferences = preferences;
333
    }
334

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

  
337
  public void finishRotation(int nearestAngle)
338
    {
339
    mNearestAngle   = nearestAngle;
340
    mFinishRotation = true;
341
    }
342

  
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

  
345
  public void changeObject(ObjectType object)
346
    {
347
    mChangeObject = true;
348
    mNextObject = object;
349
    }
350

  
351
///////////////////////////////////////////////////////////////////////////////////////////////////
352

  
353
  public void setupObject(ObjectType object, int[][] moves)
354
    {
355
    mSetupObject= true;
356
    mNextObject = object;
357
    mNextMoves  = moves;
358
    }
359

  
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361

  
362
  public void setTextureMap(int cubit, int face, int newColor)
363
    {
364
    mSetTextureMap = true;
365

  
366
    mCubit    = cubit;
367
    mFace     = face;
368
    mNewColor = newColor;
369
    }
370

  
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

  
373
  public boolean isTouchBlocked()
374
    {
375
    return mTouchBlocked;
376
    }
377

  
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379

  
380
  public boolean isUINotBlocked()
381
    {
382
    return !mUIBlocked;
383
    }
384

  
385
///////////////////////////////////////////////////////////////////////////////////////////////////
386

  
387
  public void blockEverything(int place)
388
    {
389
    mUIBlocked   = true;
390
    mTouchBlocked= true;
391
    mBlockController.touchBlocked(place);
392
    mBlockController.uiBlocked(place);
393
    }
394

  
395
///////////////////////////////////////////////////////////////////////////////////////////////////
396

  
397
  public void blockTouch(int place)
398
    {
399
    mTouchBlocked= true;
400
    mBlockController.touchBlocked(place);
401
    }
402

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

  
405
  public void unblockEverything()
406
    {
407
    mUIBlocked   = false;
408
    mTouchBlocked= false;
409
    mBlockController.touchUnblocked();
410
    mBlockController.uiUnblocked();
411
    }
412

  
413
///////////////////////////////////////////////////////////////////////////////////////////////////
414

  
415
  public void unblockTouch()
416
    {
417
    mTouchBlocked= false;
418
    mBlockController.touchUnblocked();
419
    }
420

  
421
///////////////////////////////////////////////////////////////////////////////////////////////////
422

  
423
  public void unblockUI()
424
    {
425
    mUIBlocked= false;
426
    mBlockController.uiUnblocked();
427
    }
428

  
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430

  
431
  public void setQuatOnNextRender()
432
    {
433
    mSetQuat = true;
434
    }
435

  
436
///////////////////////////////////////////////////////////////////////////////////////////////////
437

  
438
  public void preRender()
439
    {
440
    if( mSolve                 ) solveNow();
441
    if( mSetQuat               ) setQuatNow();
442
    if( mFinishRotation        ) finishRotationNow();
443
    if( mRemoveRotation        ) removeRotationNow();
444
    if( mRemovePatternRotation ) removePatternRotationNow();
445
    if( mChangeObject          ) changeObjectNow();
446
    if( mSetupObject           ) setupObjectNow();
447
    if( mSolveObject           ) solveObjectNow();
448
    if( mScrambleObject        ) scrambleObjectNow();
449
    if( mAddRotation           ) addRotationNow();
450
    if( mInitializeObject      ) initializeObjectNow();
451
    if( mResetAllTextureMaps   ) resetAllTextureMapsNow();
452
    if( mSetTextureMap         ) setTextureMapNow();
453
    }
454

  
455
///////////////////////////////////////////////////////////////////////////////////////////////////
456

  
457
  public void addRotation(MovesFinished listener, int axis, int rowBitmap, int angle, long duration)
458
    {
459
    mAddRotation = true;
460

  
461
    mAddActionListener    = listener;
462
    mAddRotationAxis      = axis;
463
    mAddRotationRowBitmap = rowBitmap;
464
    mAddRotationAngle     = angle;
465
    mAddRotationDuration  = duration;
466

  
467
    if( listener instanceof ScrambleEffect )
468
      {
469
      mDebug += (" (a "+axis+" "+rowBitmap+" "+angle+" "+(System.currentTimeMillis()-mDebugStartTime)+")");
470
      }
471
    }
472

  
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474

  
475
  public void initializeObject(int[][] moves)
476
    {
477
    mInitializeObject = true;
478
    mNextMoves = moves;
479
    }
480

  
481
///////////////////////////////////////////////////////////////////////////////////////////////////
482

  
483
  public void scrambleObject(int num)
484
    {
485
    if( !mUIBlocked )
486
      {
487
      mScrambleObject = true;
488
      mScrambleObjectNum = num;
489
      mDebug = "";
490
      mDebugStartTime = System.currentTimeMillis();
491
      }
492
    }
493

  
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495
// this starts the Solve Effect
496

  
497
  public void solveObject()
498
    {
499
    if( !mUIBlocked )
500
      {
501
      mSolveObject = true;
502
      }
503
    }
504

  
505
///////////////////////////////////////////////////////////////////////////////////////////////////
506
// this only sets the cubits state to solved
507

  
508
  public void solve()
509
    {
510
    mSolve = true;
511
    }
512

  
513
///////////////////////////////////////////////////////////////////////////////////////////////////
514

  
515
  public void resetAllTextureMaps()
516
    {
517
    mResetAllTextureMaps = true;
518
    }
519

  
520
///////////////////////////////////////////////////////////////////////////////////////////////////
521

  
522
  public TwistyObject getObject()
523
    {
524
    return mNewObject;
525
    }
526

  
527
///////////////////////////////////////////////////////////////////////////////////////////////////
528

  
529
  public TwistyObject getOldObject()
530
    {
531
    return mOldObject;
532
    }
533

  
534
///////////////////////////////////////////////////////////////////////////////////////////////////
535

  
536
  public int getNumScrambles()
537
    {
538
    return mScrambleObjectNum;
539
    }
540

  
541
///////////////////////////////////////////////////////////////////////////////////////////////////
542

  
543
  public void effectFinished(final long effectID)
544
    {
545
    if( effectID == mRotationFinishedID )
546
      {
547
      mRotationFinishedID = 0;
548
      removeRotation();
549
      }
550
    else if( effectID == mAddRotationID )
551
      {
552
      mAddRotationID = 0;
553
      mRemoveRotationID = effectID;
554
      removePatternRotation();
555
      }
556
    else
557
      {
558
      for(int i=0; i<BaseEffect.Type.LENGTH; i++)
559
        {
560
        if( effectID == mEffectID[i] )
561
          {
562
          if( i!=BaseEffect.Type.WIN.ordinal() ) unblockEverything();
563
          if( i==BaseEffect.Type.SCRAMBLE.ordinal() ) mActioner.onScrambleEffectFinished(mView.getActivity());
564
          if( i==BaseEffect.Type.WIN.ordinal()      ) mActioner.onWinEffectFinished(mView.getActivity(),mDebug,mScrambleObjectNum);
565
          break;
566
          }
567
        }
568
      }
569
    }
570
  }
src/main/java/org/distorted/objectlib/main/TwistyObject.java
891 891
    }
892 892

  
893 893
///////////////////////////////////////////////////////////////////////////////////////////////////
894
// PUBLIC API
894
// INTERNAL API
895 895
///////////////////////////////////////////////////////////////////////////////////////////////////
896 896

  
897
  public boolean isSolved()
897
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
898 898
    {
899
    if( mSolvedFunctionIndex==0 ) return isSolved0();
900
    if( mSolvedFunctionIndex==1 ) return isSolved1();
901
    if( mSolvedFunctionIndex==2 ) return isSolved2();
902
    if( mSolvedFunctionIndex==3 ) return isSolved3();
903

  
904
    return false;
899
    mScrambler.randomizeNewScramble(scramble,rnd,curr,total);
905 900
    }
906 901

  
907 902
///////////////////////////////////////////////////////////////////////////////////////////////////
908
// the getFaceColors + final black in a grid (so that we do not exceed the maximum texture size)
909 903

  
910
  public void createTexture()
904
  public int getNodeSize()
911 905
    {
912
    Bitmap bitmap;
906
    return mNodeSize;
907
    }
913 908

  
914
    Paint paint = new Paint();
915
    bitmap = Bitmap.createBitmap( mNumTexCols*TEXTURE_HEIGHT, mNumTexRows*TEXTURE_HEIGHT, Bitmap.Config.ARGB_8888);
916
    Canvas canvas = new Canvas(bitmap);
909
///////////////////////////////////////////////////////////////////////////////////////////////////
917 910

  
918
    paint.setAntiAlias(true);
919
    paint.setTextAlign(Paint.Align.CENTER);
920
    paint.setStyle(Paint.Style.FILL);
911
  public void initializeObject(int[][] moves)
912
    {
913
    solve();
914
    setupPosition(moves);
915
    }
921 916

  
922
    paint.setColor(COLOR_BLACK);
923
    canvas.drawRect(0, 0, mNumTexCols*TEXTURE_HEIGHT, mNumTexRows*TEXTURE_HEIGHT, paint);
917
///////////////////////////////////////////////////////////////////////////////////////////////////
924 918

  
925
    int face = 0;
926
    FactorySticker factory = FactorySticker.getInstance();
919
  public synchronized void removeRotationNow()
920
    {
921
    float angle = getAngle();
922
    double nearestAngleInRadians = angle*Math.PI/180;
923
    float sinA =-(float)Math.sin(nearestAngleInRadians*0.5);
924
    float cosA = (float)Math.cos(nearestAngleInRadians*0.5);
925
    float axisX = mAxis[mRotAxis].get0();
926
    float axisY = mAxis[mRotAxis].get1();
927
    float axisZ = mAxis[mRotAxis].get2();
928
    Static4D quat = new Static4D( axisX*sinA, axisY*sinA, axisZ*sinA, cosA);
927 929

  
928
    for(int row=0; row<mNumTexRows; row++)
929
      for(int col=0; col<mNumTexCols; col++)
930
    mRotationAngle.removeAll();
931
    mRotationAngleStatic.set0(0);
932

  
933
    for(int i=0; i<NUM_CUBITS; i++)
934
      if( belongsToRotation(i,mRotAxis,mRotRowBitmap) )
930 935
        {
931
        if( face>=NUM_TEXTURES ) break;
932
        ObjectSticker sticker = retSticker(face);
933
        factory.drawRoundedPolygon(canvas, paint, col*TEXTURE_HEIGHT, row*TEXTURE_HEIGHT, getColor(face%NUM_FACE_COLORS), sticker);
934
        face++;
936
        int index = CUBITS[i].removeRotationNow(quat);
937
        mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(),index);
935 938
        }
936

  
937
    if( !mTexture.setTexture(bitmap) )
938
      {
939
      int max = DistortedLibrary.getMaxTextureSize();
940
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
941
      crashlytics.log("failed to set texture of size "+bitmap.getWidth()+"x"+bitmap.getHeight()+" max is "+max);
942
      }
943 939
    }
944 940

  
945 941
///////////////////////////////////////////////////////////////////////////////////////////////////
946 942

  
947
  public void setObjectRatio(float sizeChange)
943
  public long finishRotationNow(EffectListener listener, int nearestAngleInDegrees)
948 944
    {
949
    mObjectScreenRatio *= (1.0f+sizeChange)/2;
950

  
951
    if( mObjectScreenRatio>MAX_SIZE_CHANGE) mObjectScreenRatio = MAX_SIZE_CHANGE;
952
    if( mObjectScreenRatio<MIN_SIZE_CHANGE) mObjectScreenRatio = MIN_SIZE_CHANGE;
945
    if( wasRotateApplied() )
946
      {
947
      float angle = getAngle();
948
      mRotationAngleStatic.set0(angle);
949
      mRotationAngleFinal.set0(nearestAngleInDegrees);
950
      mRotationAngleMiddle.set0( nearestAngleInDegrees + (nearestAngleInDegrees-angle)*0.2f );
953 951

  
954
    float scale = mObjectScreenRatio*mInitScreenRatio*mNodeSize/mRealSize;
955
    mObjectScale.set(scale,scale,scale);
956
    }
952
      mRotationAngle.setDuration(POST_ROTATION_MILLISEC);
953
      mRotationAngle.resetToBeginning();
954
      mRotationAngle.removeAll();
955
      mRotationAngle.add(mRotationAngleStatic);
956
      mRotationAngle.add(mRotationAngleMiddle);
957
      mRotationAngle.add(mRotationAngleFinal);
958
      mRotateEffect.notifyWhenFinished(listener);
957 959

  
958
///////////////////////////////////////////////////////////////////////////////////////////////////
960
      return mRotateEffect.getID();
961
      }
959 962

  
960
  public float getObjectRatio()
961
    {
962
    return mObjectScreenRatio*mInitScreenRatio;
963
    return 0;
963 964
    }
964 965

  
965 966
///////////////////////////////////////////////////////////////////////////////////////////////////
966 967

  
967
  public int getCubitFaceColorIndex(int cubit, int face)
968
  public synchronized long addNewRotation( int axis, int rowBitmap, int angle, long durationMillis, EffectListener listener )
968 969
    {
969
    Static4D texMap = mMesh.getTextureMap(NUM_FACE_COLORS*cubit + face);
970
    if( wasRotateApplied() )
971
      {
972
      mRotAxis     = axis;
973
      mRotRowBitmap= computeBitmapFromRow( rowBitmap,axis );
970 974

  
971
    int x = (int)(texMap.get0()/texMap.get2());
972
    int y = (int)(texMap.get1()/texMap.get3());
975
      mRotationAngleStatic.set0(0.0f);
976
      mRotationAxis.set( mAxis[axis] );
977
      mRotationAngle.setDuration(durationMillis);
978
      mRotationAngle.resetToBeginning();
979
      mRotationAngle.add(new Static1D(0));
980
      mRotationAngle.add(new Static1D(angle));
981
      mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis*ObjectType.MAX_OBJECT_SIZE) , -1);
982
      mRotateEffect.notifyWhenFinished(listener);
973 983

  
974
    return (mNumTexRows-1-y)*NUM_STICKERS_IN_ROW + x;
984
      return mRotateEffect.getID();
985
      }
986

  
987
    return 0;
975 988
    }
976 989

  
977 990
///////////////////////////////////////////////////////////////////////////////////////////////////
978 991

  
979
  public int getNumLayers()
992
  public void setTextureMap(int cubit, int face, int newColor)
980 993
    {
981
    return mNumLayers;
994
    final float ratioW = 1.0f/mNumTexCols;
995
    final float ratioH = 1.0f/mNumTexRows;
996
    final Static4D[] maps = new Static4D[mNumCubitFaces];
997
    int row = (mNumTexRows-1) - newColor/mNumTexCols;
998
    int col = newColor%mNumTexCols;
999

  
1000
    maps[face] = new Static4D( col*ratioW, row*ratioH, ratioW, ratioH);
1001
    mMesh.setTextureMap(maps,mNumCubitFaces*cubit);
982 1002
    }
983 1003

  
984 1004
///////////////////////////////////////////////////////////////////////////////////////////////////
985 1005

  
986
  public void continueRotation(float angleInDegrees)
1006
  public void resetAllTextureMaps()
987 1007
    {
988
    mRotationAngleStatic.set0(angleInDegrees);
989
    }
990

  
991
///////////////////////////////////////////////////////////////////////////////////////////////////
1008
    final float ratioW = 1.0f/mNumTexCols;
1009
    final float ratioH = 1.0f/mNumTexRows;
1010
    int color, row, col;
992 1011

  
993
  public Static4D getRotationQuat()
1012
    for(int cubit=0; cubit<NUM_CUBITS; cubit++)
994 1013
      {
995
      return mQuat;
996
      }
1014
      final Static4D[] maps = new Static4D[mNumCubitFaces];
997 1015

  
998
///////////////////////////////////////////////////////////////////////////////////////////////////
1016
      for(int cubitface=0; cubitface<mNumCubitFaces; cubitface++)
1017
        {
1018
        color = getFaceColor(cubit,cubitface,mNumLayers);
1019
        row = (mNumTexRows-1) - color/mNumTexCols;
1020
        col = color%mNumTexCols;
1021
        maps[cubitface] = new Static4D( col*ratioW, row*ratioH, ratioW, ratioH);
1022
        }
999 1023

  
1000
  public void recomputeScaleFactor(int scrWidth)
1001
    {
1002
    mNodeScale.set(scrWidth,NODE_RATIO*scrWidth,scrWidth);
1024
      mMesh.setTextureMap(maps,mNumCubitFaces*cubit);
1025
      }
1003 1026
    }
1004 1027

  
1005 1028
///////////////////////////////////////////////////////////////////////////////////////////////////
1006 1029

  
1007
  public void savePreferences(SharedPreferences.Editor editor)
1030
  public void releaseResources()
1008 1031
    {
1009
    for(int i=0; i<NUM_CUBITS; i++) CUBITS[i].savePreferences(editor);
1032
    mTexture.markForDeletion();
1033
    mMesh.markForDeletion();
1034
    mEffects.markForDeletion();
1035

  
1036
    for(int j=0; j<NUM_CUBITS; j++)
1037
      {
1038
      CUBITS[j].releaseResources();
1039
      }
1010 1040
    }
1011 1041

  
1012 1042
///////////////////////////////////////////////////////////////////////////////////////////////////
......
1043 1073

  
1044 1074
///////////////////////////////////////////////////////////////////////////////////////////////////
1045 1075

  
1046
  public void releaseResources()
1047
    {
1048
    mTexture.markForDeletion();
1049
    mMesh.markForDeletion();
1050
    mEffects.markForDeletion();
1051

  
1052
    for(int j=0; j<NUM_CUBITS; j++)
1053
      {
1054
      CUBITS[j].releaseResources();
1055
      }
1056
    }
1057

  
1058
///////////////////////////////////////////////////////////////////////////////////////////////////
1059

  
1060
  public void apply(Effect effect, int position)
1076
  public void savePreferences(SharedPreferences.Editor editor)
1061 1077
    {
1062
    mEffects.apply(effect, position);
1078
    for(int i=0; i<NUM_CUBITS; i++) CUBITS[i].savePreferences(editor);
1063 1079
    }
1064 1080

  
1065 1081
///////////////////////////////////////////////////////////////////////////////////////////////////
1066 1082

  
1067
  public void remove(long effectID)
1083
  public void recomputeScaleFactor(int scrWidth)
1068 1084
    {
1069
    mEffects.abortById(effectID);
1085
    mNodeScale.set(scrWidth,NODE_RATIO*scrWidth,scrWidth);
1070 1086
    }
1071 1087

  
1072 1088
///////////////////////////////////////////////////////////////////////////////////////////////////
1073 1089

  
1074
  public synchronized void solve()
1075
    {
1076
    for(int i=0; i<NUM_CUBITS; i++)
1090
  public Static4D getRotationQuat()
1077 1091
      {
1078
      CUBITS[i].solve();
1079
      mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(), 0);
1092
      return mQuat;
1080 1093
      }
1081
    }
1082 1094

  
1083 1095
///////////////////////////////////////////////////////////////////////////////////////////////////
1096
// the getFaceColors + final black in a grid (so that we do not exceed the maximum texture size)
1084 1097

  
1085
  public void resetAllTextureMaps()
1098
  public void createTexture()
1086 1099
    {
1087
    final float ratioW = 1.0f/mNumTexCols;
1088
    final float ratioH = 1.0f/mNumTexRows;
1089
    int color, row, col;
1100
    Bitmap bitmap;
1090 1101

  
1091
    for(int cubit=0; cubit<NUM_CUBITS; cubit++)
1092
      {
1093
      final Static4D[] maps = new Static4D[mNumCubitFaces];
1102
    Paint paint = new Paint();
1103
    bitmap = Bitmap.createBitmap( mNumTexCols*TEXTURE_HEIGHT, mNumTexRows*TEXTURE_HEIGHT, Bitmap.Config.ARGB_8888);
1104
    Canvas canvas = new Canvas(bitmap);
1094 1105

  
1095
      for(int cubitface=0; cubitface<mNumCubitFaces; cubitface++)
1106
    paint.setAntiAlias(true);
1107
    paint.setTextAlign(Paint.Align.CENTER);
1108
    paint.setStyle(Paint.Style.FILL);
1109

  
1110
    paint.setColor(COLOR_BLACK);
1111
    canvas.drawRect(0, 0, mNumTexCols*TEXTURE_HEIGHT, mNumTexRows*TEXTURE_HEIGHT, paint);
1112

  
1113
    int face = 0;
1114
    FactorySticker factory = FactorySticker.getInstance();
1115

  
1116
    for(int row=0; row<mNumTexRows; row++)
1117
      for(int col=0; col<mNumTexCols; col++)
1096 1118
        {
1097
        color = getFaceColor(cubit,cubitface,mNumLayers);
1098
        row = (mNumTexRows-1) - color/mNumTexCols;
1099
        col = color%mNumTexCols;
1100
        maps[cubitface] = new Static4D( col*ratioW, row*ratioH, ratioW, ratioH);
1119
        if( face>=NUM_TEXTURES ) break;
1120
        ObjectSticker sticker = retSticker(face);
1121
        factory.drawRoundedPolygon(canvas, paint, col*TEXTURE_HEIGHT, row*TEXTURE_HEIGHT, getColor(face%NUM_FACE_COLORS), sticker);
1122
        face++;
1101 1123
        }
1102 1124

  
1103
      mMesh.setTextureMap(maps,mNumCubitFaces*cubit);
1125
    if( !mTexture.setTexture(bitmap) )
1126
      {
1127
      int max = DistortedLibrary.getMaxTextureSize();
1128
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
1129
      crashlytics.log("failed to set texture of size "+bitmap.getWidth()+"x"+bitmap.getHeight()+" max is "+max);
1104 1130
      }
1105 1131
    }
1106 1132

  
1133
///////////////////////////////////////////////////////////////////////////////////////////////////
1134
// PUBLIC API
1107 1135
///////////////////////////////////////////////////////////////////////////////////////////////////
1108 1136

  
1109
  public void setTextureMap(int cubit, int face, int newColor)
1137
  public boolean isSolved()
1110 1138
    {
1111
    final float ratioW = 1.0f/mNumTexCols;
1112
    final float ratioH = 1.0f/mNumTexRows;
1113
    final Static4D[] maps = new Static4D[mNumCubitFaces];
1114
    int row = (mNumTexRows-1) - newColor/mNumTexCols;
1115
    int col = newColor%mNumTexCols;
1139
    if( mSolvedFunctionIndex==0 ) return isSolved0();
1140
    if( mSolvedFunctionIndex==1 ) return isSolved1();
1141
    if( mSolvedFunctionIndex==2 ) return isSolved2();
1142
    if( mSolvedFunctionIndex==3 ) return isSolved3();
1116 1143

  
1117
    maps[face] = new Static4D( col*ratioW, row*ratioH, ratioW, ratioH);
1118
    mMesh.setTextureMap(maps,mNumCubitFaces*cubit);
1144
    return false;
1119 1145
    }
1120 1146

  
1121 1147
///////////////////////////////////////////////////////////////////////////////////////////////////
1122 1148

  
1123
  public synchronized void beginNewRotation(int axis, int row )
1149
  public void setObjectRatio(float sizeChange)
1124 1150
    {
1125
    if( axis<0 || axis>=NUM_AXIS )
1126
      {
1127
      android.util.Log.e("object", "invalid rotation axis: "+axis);
1128
      return;
1129
      }
1130
    if( row<0 || row>=mNumLayers )
1131
      {
1132
      android.util.Log.e("object", "invalid rotation row: "+row);
1133
      return;
1134
      }
1151
    mObjectScreenRatio *= (1.0f+sizeChange)/2;
1135 1152

  
1136
    mRotAxis     = axis;
1137
    mRotRowBitmap= computeBitmapFromRow( (1<<row),axis );
1138
    mRotationAngleStatic.set0(0.0f);
1139
    mRotationAxis.set( mAxis[axis] );
1140
    mRotationAngle.add(mRotationAngleStatic);
1141
    mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis*ObjectType.MAX_OBJECT_SIZE) , -1);
1153
    if( mObjectScreenRatio>MAX_SIZE_CHANGE) mObjectScreenRatio = MAX_SIZE_CHANGE;
1154
    if( mObjectScreenRatio<MIN_SIZE_CHANGE) mObjectScreenRatio = MIN_SIZE_CHANGE;
1155

  
1156
    float scale = mObjectScreenRatio*mInitScreenRatio*mNodeSize/mRealSize;
1157
    mObjectScale.set(scale,scale,scale);
1142 1158
    }
1143 1159

  
1144 1160
///////////////////////////////////////////////////////////////////////////////////////////////////
1145 1161

  
1146
  public synchronized long addNewRotation( int axis, int rowBitmap, int angle, long durationMillis, EffectListener listener )
1162
  public float getObjectRatio()
1147 1163
    {
1148
    if( wasRotateApplied() )
1149
      {
1150
      mRotAxis     = axis;
1151
      mRotRowBitmap= computeBitmapFromRow( rowBitmap,axis );
1164
    return mObjectScreenRatio*mInitScreenRatio;
1165
    }
1152 1166

  
1153
      mRotationAngleStatic.set0(0.0f);
1154
      mRotationAxis.set( mAxis[axis] );
1155
      mRotationAngle.setDuration(durationMillis);
1156
      mRotationAngle.resetToBeginning();
1157
      mRotationAngle.add(new Static1D(0));
1158
      mRotationAngle.add(new Static1D(angle));
1159
      mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis*ObjectType.MAX_OBJECT_SIZE) , -1);
1160
      mRotateEffect.notifyWhenFinished(listener);
1167
///////////////////////////////////////////////////////////////////////////////////////////////////
1161 1168

  
1162
      return mRotateEffect.getID();
1163
      }
1169
  public int getCubitFaceColorIndex(int cubit, int face)
1170
    {
1171
    Static4D texMap = mMesh.getTextureMap(NUM_FACE_COLORS*cubit + face);
1164 1172

  
1165
    return 0;
1173
    int x = (int)(texMap.get0()/texMap.get2());
1174
    int y = (int)(texMap.get1()/texMap.get3());
1175

  
1176
    return (mNumTexRows-1-y)*NUM_STICKERS_IN_ROW + x;
1166 1177
    }
1167 1178

  
1168 1179
///////////////////////////////////////////////////////////////////////////////////////////////////
1169 1180

  
1170
  public long finishRotationNow(EffectListener listener, int nearestAngleInDegrees)
1181
  public int getNumLayers()
1171 1182
    {
1172
    if( wasRotateApplied() )
1173
      {
1174
      float angle = getAngle();
1175
      mRotationAngleStatic.set0(angle);
1176
      mRotationAngleFinal.set0(nearestAngleInDegrees);
1177
      mRotationAngleMiddle.set0( nearestAngleInDegrees + (nearestAngleInDegrees-angle)*0.2f );
1183
    return mNumLayers;
1184
    }
1178 1185

  
1179
      mRotationAngle.setDuration(POST_ROTATION_MILLISEC);
1180
      mRotationAngle.resetToBeginning();
1181
      mRotationAngle.removeAll();
1182
      mRotationAngle.add(mRotationAngleStatic);
1183
      mRotationAngle.add(mRotationAngleMiddle);
1184
      mRotationAngle.add(mRotationAngleFinal);
1185
      mRotateEffect.notifyWhenFinished(listener);
1186
///////////////////////////////////////////////////////////////////////////////////////////////////
1186 1187

  
1187
      return mRotateEffect.getID();
1188
      }
1188
  public void continueRotation(float angleInDegrees)
1189
    {
1190
    mRotationAngleStatic.set0(angleInDegrees);
1191
    }
1189 1192

  
1190
    return 0;
1193
///////////////////////////////////////////////////////////////////////////////////////////////////
1194

  
1195
  public void apply(Effect effect, int position)
1196
    {
1197
    mEffects.apply(effect, position);
1191 1198
    }
1192 1199

  
1193 1200
///////////////////////////////////////////////////////////////////////////////////////////////////
1194 1201

  
1195
  public synchronized void removeRotationNow()
1202
  public void remove(long effectID)
1196 1203
    {
1197
    float angle = getAngle();
1198
    double nearestAngleInRadians = angle*Math.PI/180;
1199
    float sinA =-(float)Math.sin(nearestAngleInRadians*0.5);
1200
    float cosA = (float)Math.cos(nearestAngleInRadians*0.5);
1201
    float axisX = mAxis[mRotAxis].get0();
1202
    float axisY = mAxis[mRotAxis].get1();
1203
    float axisZ = mAxis[mRotAxis].get2();
1204
    Static4D quat = new Static4D( axisX*sinA, axisY*sinA, axisZ*sinA, cosA);
1204
    mEffects.abortById(effectID);
1205
    }
1205 1206

  
1206
    mRotationAngle.removeAll();
1207
    mRotationAngleStatic.set0(0);
1207
///////////////////////////////////////////////////////////////////////////////////////////////////
1208 1208

  
1209
  public synchronized void solve()
1210
    {
1209 1211
    for(int i=0; i<NUM_CUBITS; i++)
1210
      if( belongsToRotation(i,mRotAxis,mRotRowBitmap) )
1211
        {
1212
        int index = CUBITS[i].removeRotationNow(quat);
1213
        mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(),index);
1214
        }
1212
      {
1213
      CUBITS[i].solve();
1214
      mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(), 0);
1215
      }
1215 1216
    }
1216 1217

  
1217 1218
///////////////////////////////////////////////////////////////////////////////////////////////////
1218 1219

  
1219
  public void initializeObject(int[][] moves)
1220
  public synchronized void beginNewRotation(int axis, int row )
1220 1221
    {
1221
    solve();
1222
    setupPosition(moves);
1222
    if( axis<0 || axis>=NUM_AXIS )
1223
      {
1224
      android.util.Log.e("object", "invalid rotation axis: "+axis);
1225
      return;
1226
      }
1227
    if( row<0 || row>=mNumLayers )
1228
      {
1229
      android.util.Log.e("object", "invalid rotation row: "+row);
1230
      return;
1231
      }
1232

  
1233
    mRotAxis     = axis;
1234
    mRotRowBitmap= computeBitmapFromRow( (1<<row),axis );
1235
    mRotationAngleStatic.set0(0.0f);
1236
    mRotationAxis.set( mAxis[axis] );
1237
    mRotationAngle.add(mRotationAngleStatic);
1238
    mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis*ObjectType.MAX_OBJECT_SIZE) , -1);
1223 1239
    }
1224 1240

  
1225 1241
///////////////////////////////////////////////////////////////////////////////////////////////////
......
1270 1286
    return mCameraDist;
1271 1287
    }
1272 1288

  
1273
///////////////////////////////////////////////////////////////////////////////////////////////////
1274

  
1275
  public int getNodeSize()
1276
    {
1277
    return mNodeSize;
1278
    }
1279

  
1280 1289
///////////////////////////////////////////////////////////////////////////////////////////////////
1281 1290

  
1282 1291
  public ObjectType getObjectType()
......
1284 1293
    return intGetObjectType(mNumLayers);
1285 1294
    }
1286 1295

  
1287
///////////////////////////////////////////////////////////////////////////////////////////////////
1288

  
1289
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
1290
    {
1291
    mScrambler.randomizeNewScramble(scramble,rnd,curr,total);
1292
    }
1293

  
1294 1296
///////////////////////////////////////////////////////////////////////////////////////////////////
1295 1297

  
1296 1298
  protected abstract int getFOV();
......
1314 1316
  protected abstract int getFaceColor(int cubit, int cubitface, int numLayers);
1315 1317
  protected abstract int getResource(int mNumLayers);
1316 1318
  protected abstract ObjectType intGetObjectType(int numLayers);
1319
  protected abstract Movement getMovement();
1317 1320

  
1318
  public abstract Movement getMovement();
1319 1321
  public abstract Static3D[] getRotationAxis();
1320 1322
  public abstract int[] getBasicAngle();
1321 1323
  public abstract int getObjectName(int numLayers);

Also available in: Unified diff