commit bcdecc9ff23d9da7ac8bf5b09f7587443948134d
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Tue Jan 31 23:47:03 2023 +0100

    Make it impossible to addNewRotation() (i.e. the automatic rotations triggered from backMove, scrambleEffect etc) or beginNewRotation() (by swiping a finger) when we are currently finishing a previous rotation and haven't removed it yet.

diff --git a/src/main/java/org/distorted/objectlib/main/ObjectControl.java b/src/main/java/org/distorted/objectlib/main/ObjectControl.java
index 4c41a65e..ad2b862d 100644
--- a/src/main/java/org/distorted/objectlib/main/ObjectControl.java
+++ b/src/main/java/org/distorted/objectlib/main/ObjectControl.java
@@ -280,9 +280,6 @@ public class ObjectControl
 
     private void beginRotation(float x, float y)
       {
-      mStartRotX = x;
-      mStartRotY = y;
-
       TwistyObject object = mPreRender.getObject();
       int[] numLayers = object.getNumLayers();
 
@@ -290,20 +287,25 @@ public class ObjectControl
       Static4D rotatedTouchPoint= QuatHelper.rotateVectorByInvertedQuat(touchPoint, mQuat);
       mTouchControl.newRotation(mBuffer,rotatedTouchPoint,mQuat);
 
-      mCurrentAxis = mBuffer[0];
-      mCurrentRow  = mBuffer[1];
-
-      mTouchControl.getCastedRotAxis(mAxis,mQuat,mCurrentAxis);
-      mRotationFactor = mTouchControl.returnRotationFactor(numLayers,mCurrentRow);
+      int currentAxis = mBuffer[0];
+      int currentRow  = mBuffer[1];
 
-      object.beginNewRotation( mCurrentAxis, mCurrentRow );
+      mTouchControl.getCastedRotAxis(mAxis,mQuat,currentAxis);
+      mRotationFactor = mTouchControl.returnRotationFactor(numLayers,currentRow);
 
-      mInterface.onBeginRotation();
+      if( object.beginNewRotation( currentAxis, currentRow ) )
+        {
+        mInterface.onBeginRotation();
 
-      addSpeedProbe(x,y);
+        addSpeedProbe(x,y);
 
-      mBeginningRotation = false;
-      mContinuingRotation= true;
+        mBeginningRotation = false;
+        mContinuingRotation= true;
+        mStartRotX = x;
+        mStartRotY = y;
+        mCurrentAxis = currentAxis;
+        mCurrentRow  = currentRow;
+        }
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objectlib/main/ObjectPreRender.java b/src/main/java/org/distorted/objectlib/main/ObjectPreRender.java
index 8d0f4e96..8c7f0776 100644
--- a/src/main/java/org/distorted/objectlib/main/ObjectPreRender.java
+++ b/src/main/java/org/distorted/objectlib/main/ObjectPreRender.java
@@ -224,8 +224,8 @@ public class ObjectPreRender implements EffectListener
       mAddRotationID = mNewObject.addNewRotation( mAddRotationAxis, mAddRotationRowBitmap,
                                                   mAddRotationAngle, mAddRotationDuration, this);
 
-      if( mAddRotationID==0 ) // failed to add effect - should never happen
-        {
+      if( mAddRotationID==0 ) // failed to add effect - can happen if we are finishing
+        {                     // previous rotation and haven't removed it yet
         unblockEverything();
         }
       }
diff --git a/src/main/java/org/distorted/objectlib/main/TwistyObject.java b/src/main/java/org/distorted/objectlib/main/TwistyObject.java
index df9cdb62..d036065e 100644
--- a/src/main/java/org/distorted/objectlib/main/TwistyObject.java
+++ b/src/main/java/org/distorted/objectlib/main/TwistyObject.java
@@ -1436,9 +1436,6 @@ public abstract class TwistyObject
     float axisZ = mAxis[mCurrentRotAxis].get2();
     Static4D quat = new Static4D( axisX*sinA, axisY*sinA, axisZ*sinA, cosA);
 
-    mRotationAngle.removeAll();
-    mRotationAngleStatic.set0(0);
-
     for(int i=0; i<mNumCubits; i++)
       {
       mBelongs[i] = belongsToRotation(i, mCurrentRotAxis,mRotRowBitmap);
@@ -1464,6 +1461,9 @@ public abstract class TwistyObject
         setCubitQuat(i,mCubits[i].computeAssociation(),mCubits[i].mQuatIndex);
         }
       }
+
+    mRotationAngleStatic.set0(0);
+    mRotationAngle.removeAll();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1519,19 +1519,24 @@ public abstract class TwistyObject
     {
     if( wasRotateApplied() )
       {
-      mCurrentRotAxis = axis;
-      mRotRowBitmap= computeBitmapFromRow( rowBitmap,axis );
-
-      mRotationAngleStatic.set0(0.0f);
-      mRotationAxis.set( mAxis[axis] );
-      mRotationAngle.setDuration(durationMillis);
-      mRotationAngle.resetToBeginning();
-      mRotationAngle.add(new Static1D(0));
-      mRotationAngle.add(new Static1D(angle));
-      mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis*mMaxNumLayers) , -1);
-      mRotateEffect.notifyWhenFinished(listener);
+      int numPoints = mRotationAngle.getNumPoints();
 
-      return mRotateEffect.getID();
+      if( numPoints==0 )
+        {
+        mCurrentRotAxis = axis;
+        mRotRowBitmap= computeBitmapFromRow( rowBitmap,axis );
+
+        mRotationAngleStatic.set0(0.0f);
+        mRotationAxis.set( mAxis[axis] );
+        mRotationAngle.setDuration(durationMillis);
+        mRotationAngle.resetToBeginning();
+        mRotationAngle.add(new Static1D(0));
+        mRotationAngle.add(new Static1D(angle));
+        mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis*mMaxNumLayers) , -1);
+        mRotateEffect.notifyWhenFinished(listener);
+
+        return mRotateEffect.getID();
+        }
       }
 
     return 0;
@@ -1546,25 +1551,32 @@ public abstract class TwistyObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  synchronized void beginNewRotation(int axis, int row )
+  synchronized boolean beginNewRotation(int axis, int row )
     {
     if( axis<0 || axis>=mNumAxis )
       {
       android.util.Log.e("object", "invalid rotation axis: "+axis);
-      return;
+      return false;
       }
     if( row<0 || row>=mNumLayers[axis] )
       {
       android.util.Log.e("object", "invalid rotation row: "+row);
-      return;
+      return false;
       }
 
-    mCurrentRotAxis = axis;
-    mRotRowBitmap= computeBitmapFromRow( (1<<row),axis );
-    mRotationAngleStatic.set0(0.0f);
-    mRotationAxis.set( mAxis[axis] );
-    mRotationAngle.add(mRotationAngleStatic);
-    mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis*mMaxNumLayers) , -1);
+    int numPoints = mRotationAngle.getNumPoints();
+
+    if( numPoints==0 )
+      {
+      mCurrentRotAxis = axis;
+      mRotRowBitmap= computeBitmapFromRow( (1<<row),axis );
+      mRotationAngleStatic.set0(0.0f);
+      mRotationAxis.set( mAxis[axis] );
+      mRotationAngle.add(mRotationAngleStatic);
+      mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis*mMaxNumLayers) , -1);
+      return true;
+      }
+    return false;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
