commit d4374cd38ba3b426e19880c985480f5a00220d6f
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sun Apr 7 20:02:03 2019 +0100

    RubikCube: make the post-rotation effect 'nice'.

diff --git a/src/main/java/org/distorted/examples/rubik/RubikCube.java b/src/main/java/org/distorted/examples/rubik/RubikCube.java
index 66e9740..a63f33d 100644
--- a/src/main/java/org/distorted/examples/rubik/RubikCube.java
+++ b/src/main/java/org/distorted/examples/rubik/RubikCube.java
@@ -42,6 +42,7 @@ import org.distorted.library.type.Static4D;
 
 class RubikCube
 {
+    private static final int POST_ROTATION_MILLISEC = 500;
     private static final int TEXTURE_SIZE = 100;
 
     private static final Static3D VectX = new Static3D(1,0,0);
@@ -54,7 +55,7 @@ class RubikCube
     private Static3D[][][] mRotationAxis;
     private Dynamic1D[][][] mRotationAngle;
     private Static3D[][][] mCurrentPosition;
-    private Static1D mRotationAngleStatic, mRotationAngleNearest;
+    private Static1D mRotationAngleStatic, mRotationAngleMiddle, mRotationAngleFinal;
     private DistortedTexture mTexture;
     private DistortedEffects mEffectsListeningForNow;
 
@@ -67,8 +68,9 @@ class RubikCube
       {
       mSize = size;
 
-      mRotationAngleStatic  = new Static1D(0);
-      mRotationAngleNearest = new Static1D(0);
+      mRotationAngleStatic = new Static1D(0);
+      mRotationAngleMiddle = new Static1D(0);
+      mRotationAngleFinal  = new Static1D(0);
 
       mRotAxis= RubikSurfaceView.VECTX;
       mTexture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
@@ -218,13 +220,11 @@ class RubikCube
     void finishRotationCalledOnNextRender(EffectListener listener)
       {
       boolean first = true;
-      int nearestAngleInDegrees = computeNearestAngle(mRotationAngleStatic.get1());
-
-
-      android.util.Log.e("cube", "finish: angle="+((int)mRotationAngleStatic.get1())+" ret: "+nearestAngleInDegrees);
+      float startingAngle = mRotationAngleStatic.get1();
+      int nearestAngleInDegrees = computeNearestAngle(startingAngle);
 
-
-      mRotationAngleNearest.set1(nearestAngleInDegrees);
+      mRotationAngleFinal.set1(nearestAngleInDegrees);
+      mRotationAngleMiddle.set1( nearestAngleInDegrees + (nearestAngleInDegrees-startingAngle)*0.2f );
 
       for(int x=0; x<mSize; x++)
         for(int y=0; y<mSize; y++)
@@ -233,8 +233,9 @@ class RubikCube
               {
               if( belongsToRotation(x,y,z,mRotAxis,mRotRow) )
                 {
-                mRotationAngle[x][y][z].makeRunNowFor(2000);
-                mRotationAngle[x][y][z].add(mRotationAngleNearest);
+                mRotationAngle[x][y][z].makeRunNowFor(POST_ROTATION_MILLISEC);
+                mRotationAngle[x][y][z].add(mRotationAngleMiddle);
+                mRotationAngle[x][y][z].add(mRotationAngleFinal);
 
                 if( first )
                   {
@@ -257,10 +258,7 @@ class RubikCube
       float sinA =-(float)Math.sin(nearestAngleInRadians*0.5);
       float cosA = (float)Math.cos(nearestAngleInRadians*0.5);
 
-      android.util.Log.e("cube", "remove: angle="+((int)mRotationAngleStatic.get1())+" ret: "+nearestAngleInDegrees);
-
       mRotationAngleStatic.set1(0);
-      mRotationAngleNearest.set1(0);
 
       float qx=0,qy=0,qz=0;
 
diff --git a/src/main/java/org/distorted/examples/rubik/RubikRenderer.java b/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
index f691060..2b21b30 100644
--- a/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
+++ b/src/main/java/org/distorted/examples/rubik/RubikRenderer.java
@@ -47,6 +47,7 @@ class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
     private Static4D mTempCurrent, mTempAccumulated;
     private float mCubeSizeInScreenSpace;
     private boolean mFinishRotation, mRemoveRotation, mFinishDragCurrent, mFinishDragAccumulated;
+    private boolean mCanRotate;
     private RubikCube mCube;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -70,6 +71,8 @@ class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
       mFinishDragCurrent     = false;
       mFinishDragAccumulated = false;
 
+      mCanRotate = true;
+
       mCube = new RubikCube(NUM_CUBES, mMove, mScale, mQuatCurrent, mQuatAccumulated);
       }
 
@@ -95,6 +98,7 @@ class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
 
       if( mFinishRotation )
         {
+        mCanRotate = false;
         mFinishRotation=false;
         mCube.finishRotationCalledOnNextRender(this);
         }
@@ -103,6 +107,7 @@ class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
         {
         mRemoveRotation=false;
         mCube.removeRotationCalledOnNextRender(this);
+        mCanRotate = true;
         }
       }
 
@@ -181,6 +186,13 @@ class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
       return mCubeSizeInScreenSpace;
       }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    boolean canRotate()
+      {
+      return mCanRotate;
+      }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     RubikCube getCube()
diff --git a/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java b/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java
index 69ee161..c480782 100644
--- a/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java
+++ b/src/main/java/org/distorted/examples/rubik/RubikSurfaceView.java
@@ -45,7 +45,7 @@ class RubikSurfaceView extends GLSurfaceView
 
     private static final int[] VECT = {VECTX,VECTY,VECTZ};
 
-    private boolean mDragging, mBeginRot;
+    private boolean mDragging, mBeginningRotation, mContinuingRotation;
     private int mX, mY;
     private Static4D mQuatCurrent, mQuatAccumulated;
     private int mRotationVect;
@@ -107,34 +107,53 @@ class RubikSurfaceView extends GLSurfaceView
                                        mY = y;
                                        mLastTouchedFace = faceTouched(x,y);
 
-                                       if( mLastTouchedFace != NONE ) { mBeginRot = true; mDragging = false; }
-                                       else                           { mDragging = true; mBeginRot = false; }
+                                       if( mLastTouchedFace != NONE )
+                                         {
+                                         mDragging           = false;
+                                         mBeginningRotation  = mRenderer.canRotate();
+                                         mContinuingRotation = false;
+                                         }
+                                       else
+                                         {
+                                         mDragging           = true;
+                                         mBeginningRotation  = false;
+                                         mContinuingRotation = false;
+                                         }
                                        break;
          case MotionEvent.ACTION_MOVE: if( mDragging )
                                          {
                                          mQuatCurrent.set(quatFromDrag(mX-x,mY-y));
                                          mRenderer.setQuatCurrent(mQuatCurrent);
                                          }
-                                       else if( mBeginRot )
+                                       if( mBeginningRotation )
                                          {
                                          int minimumDistToStartRotating = (mScreenMin*mScreenMin)/100;
 
                                          if( (mX-x)*(mX-x)+(mY-y)*(mY-y) > minimumDistToStartRotating )
                                            {
                                            addNewRotation(x,y);
-                                           mBeginRot = false;
+                                           mBeginningRotation = false;
+                                           mContinuingRotation= true;
                                            }
                                          }
-                                       else
+                                       else if( mContinuingRotation )
                                          {
                                          continueRotation(x,y);
                                          }
                                        break;
-         case MotionEvent.ACTION_UP  : if( !mDragging ) finishRotation();
-                                       mQuatAccumulated.set(quatMultiply(mQuatCurrent, mQuatAccumulated));
-                                       mQuatCurrent.set(0f, 0f, 0f, 1f);
-                                       mRenderer.setQuatCurrent(mQuatCurrent);
-                                       mRenderer.setQuatAccumulated(mQuatAccumulated);
+         case MotionEvent.ACTION_UP  : if( mDragging )
+                                         {
+                                         mQuatAccumulated.set(quatMultiply(mQuatCurrent, mQuatAccumulated));
+                                         mQuatCurrent.set(0f, 0f, 0f, 1f);
+                                         mRenderer.setQuatCurrent(mQuatCurrent);
+                                         mRenderer.setQuatAccumulated(mQuatAccumulated);
+                                         }
+
+                                       if( mContinuingRotation )
+                                         {
+                                         finishRotation();
+                                         }
+
                                        break;
          }
 
