commit 985f3dfaaaf70f0feac13591deb459b6d65bf51c
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed Feb 24 14:35:48 2021 +0100

    Do not block the UI if, for some reason, some of the effects failed to get added to the Queue. Just fail to rotate.

diff --git a/src/main/java/org/distorted/main/RubikPreRender.java b/src/main/java/org/distorted/main/RubikPreRender.java
index abd17412..65e0ff20 100644
--- a/src/main/java/org/distorted/main/RubikPreRender.java
+++ b/src/main/java/org/distorted/main/RubikPreRender.java
@@ -55,7 +55,7 @@ public class RubikPreRender implements EffectController
     void onActionFinished(long effectID);
     }
 
-  private RubikSurfaceView mView;
+  private final RubikSurfaceView mView;
   private boolean mFinishRotation, mRemoveRotation, mRemovePatternRotation, mAddRotation,
                   mSetQuat, mChangeObject, mSetupObject, mSolveObject, mScrambleObject,
                   mInitializeObject, mSetTextureMap, mResetAllTextureMaps;
@@ -64,7 +64,7 @@ public class RubikPreRender implements EffectController
   private ObjectList mNextObject;
   private int mNextSize;
   private long mRotationFinishedID;
-  private long[] mEffectID;
+  private final long[] mEffectID;
   private boolean mIsNewRecord;
   private long mNewRecord;
   private int mScreenWidth;
@@ -230,6 +230,12 @@ public class RubikPreRender implements EffectController
     mAddRotation = false;
     mAddRotationID = mNewObject.addNewRotation( mAddRotationAxis, mAddRotationRowBitmap,
                                                 mAddRotationAngle, mAddRotationDuration, this);
+
+    if( mAddRotationID==0 ) // failed to add effect - should never happen
+      {
+      mCanRotate = true;
+      mCanPlay   = true;
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objects/TwistyObject.java b/src/main/java/org/distorted/objects/TwistyObject.java
index 5eac8f87..0003d33d 100644
--- a/src/main/java/org/distorted/objects/TwistyObject.java
+++ b/src/main/java/org/distorted/objects/TwistyObject.java
@@ -290,6 +290,13 @@ public abstract class TwistyObject extends DistortedNode
     return NUM_CUTS;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private boolean wasRotateApplied()
+    {
+    return mEffects.exists(mRotateEffect.getID());
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private boolean belongsToRotation( int cubit, int axis, int rowBitmap)
@@ -618,42 +625,51 @@ public abstract class TwistyObject extends DistortedNode
 
   public synchronized long addNewRotation( int axis, int rowBitmap, int angle, long durationMillis, EffectListener listener )
     {
-    mRotAxis     = axis;
-    mRotRowBitmap= rowBitmap;
-
-    mRotationAngleStatic.set0(0.0f);
-    mRotationAxis.set( ROTATION_AXIS[axis] );
-    mRotationAngle.setDuration(durationMillis);
-    mRotationAngle.resetToBeginning();
-    mRotationAngle.add(new Static1D(0));
-    mRotationAngle.add(new Static1D(angle));
-    mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis* ObjectList.MAX_OBJECT_SIZE) , -1);
-    mRotateEffect.notifyWhenFinished(listener);
+    if( wasRotateApplied() )
+      {
+      mRotAxis     = axis;
+      mRotRowBitmap= rowBitmap;
+
+      mRotationAngleStatic.set0(0.0f);
+      mRotationAxis.set( ROTATION_AXIS[axis] );
+      mRotationAngle.setDuration(durationMillis);
+      mRotationAngle.resetToBeginning();
+      mRotationAngle.add(new Static1D(0));
+      mRotationAngle.add(new Static1D(angle));
+      mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis* ObjectList.MAX_OBJECT_SIZE) , -1);
+      mRotateEffect.notifyWhenFinished(listener);
+
+      return mRotateEffect.getID();
+      }
 
-    return mRotateEffect.getID();
+    return 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public long finishRotationNow(EffectListener listener, int nearestAngleInDegrees)
     {
-    float angle = getAngle();
-    mRotationAngleStatic.set0(angle);
-    mRotationAngleFinal.set0(nearestAngleInDegrees);
-    mRotationAngleMiddle.set0( nearestAngleInDegrees + (nearestAngleInDegrees-angle)*0.2f );
-
-    mRotationAngle.setDuration(POST_ROTATION_MILLISEC);
-    mRotationAngle.resetToBeginning();
-    mRotationAngle.removeAll();
-    mRotationAngle.add(mRotationAngleStatic);
-    mRotationAngle.add(mRotationAngleMiddle);
-    mRotationAngle.add(mRotationAngleFinal);
-    mRotateEffect.notifyWhenFinished(listener);
+    if( wasRotateApplied() )
+      {
+      float angle = getAngle();
+      mRotationAngleStatic.set0(angle);
+      mRotationAngleFinal.set0(nearestAngleInDegrees);
+      mRotationAngleMiddle.set0( nearestAngleInDegrees + (nearestAngleInDegrees-angle)*0.2f );
+
+      mRotationAngle.setDuration(POST_ROTATION_MILLISEC);
+      mRotationAngle.resetToBeginning();
+      mRotationAngle.removeAll();
+      mRotationAngle.add(mRotationAngleStatic);
+      mRotationAngle.add(mRotationAngleMiddle);
+      mRotationAngle.add(mRotationAngleFinal);
+      mRotateEffect.notifyWhenFinished(listener);
+
+      return mRotateEffect.getID();
+      }
 
-    return mRotateEffect.getID();
+    return 0;
     }
 
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private float getAngle()
diff --git a/src/main/java/org/distorted/states/RubikStateBase.java b/src/main/java/org/distorted/states/RubikStateBase.java
index 5c602e03..792039a4 100644
--- a/src/main/java/org/distorted/states/RubikStateBase.java
+++ b/src/main/java/org/distorted/states/RubikStateBase.java
@@ -42,7 +42,7 @@ abstract class RubikStateBase extends RubikStateAbstract implements RubikPreRend
 
   private static class Move
     {
-    private int mAxis, mRow, mAngle;
+    private final int mAxis, mRow, mAngle;
 
     Move(int axis, int row, int angle)
       {
diff --git a/src/main/java/org/distorted/states/RubikStatePlay.java b/src/main/java/org/distorted/states/RubikStatePlay.java
index 522a50fc..e7252870 100644
--- a/src/main/java/org/distorted/states/RubikStatePlay.java
+++ b/src/main/java/org/distorted/states/RubikStatePlay.java
@@ -49,7 +49,7 @@ public class RubikStatePlay extends RubikStateBase
   public  static final int DEF_OBJECT= ObjectList.CUBE.ordinal();
   public  static final int DEF_SIZE  =  3;
 
-  private static int[] BUTTON_LABELS = { R.string.scores, R.string.patterns, R.string.solver, R.string.tutorials, R.string.about };
+  private static final int[] BUTTON_LABELS = { R.string.scores, R.string.patterns, R.string.solver, R.string.tutorials, R.string.about };
   private static final int NUM_BUTTONS = BUTTON_LABELS.length;
 
   private ImageButton mObjButton, mMenuButton, mSolveButton;
diff --git a/src/main/java/org/distorted/tutorial/TutorialPreRender.java b/src/main/java/org/distorted/tutorial/TutorialPreRender.java
index 3b212bed..cf032870 100644
--- a/src/main/java/org/distorted/tutorial/TutorialPreRender.java
+++ b/src/main/java/org/distorted/tutorial/TutorialPreRender.java
@@ -168,6 +168,11 @@ public class TutorialPreRender implements EffectController
     mAddRotation = false;
     mAddRotationID = mNewObject.addNewRotation( mAddRotationAxis, mAddRotationRowBitmap,
                                                 mAddRotationAngle, mAddRotationDuration, this);
+
+    if( mAddRotationID==0 ) // failed to add effect - should never happen
+      {
+      mCanPlay = true;
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -180,7 +185,7 @@ public class TutorialPreRender implements EffectController
 
     if( mRotationFinishedID==0 ) // failed to add effect - should never happen
       {
-      mCanPlay   = true;
+      mCanPlay = true;
       }
     }
 
