commit 8ba7aeb14d72dd7253c3b7373ac09f32779f8efc
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed May 19 15:45:27 2021 +0200

    RubikControl: rotate the cube.

diff --git a/src/main/java/org/distorted/control/RubikControl.java b/src/main/java/org/distorted/control/RubikControl.java
index 9f556e61..9059db6c 100644
--- a/src/main/java/org/distorted/control/RubikControl.java
+++ b/src/main/java/org/distorted/control/RubikControl.java
@@ -23,6 +23,7 @@ import org.distorted.library.main.DistortedNode;
 import org.distorted.library.main.DistortedScreen;
 import org.distorted.library.message.EffectListener;
 import org.distorted.main.RubikActivity;
+import org.distorted.main.RubikSurfaceView;
 
 import java.lang.ref.WeakReference;
 
@@ -46,6 +47,14 @@ public class RubikControl implements EffectListener
     return act!=null ? act.getScreen() : null;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  RubikSurfaceView getSurfaceView()
+    {
+    RubikActivity act = mRefAct.get();
+    return act!=null ? act.getSurfaceView() : null;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void addWholeObjects()
diff --git a/src/main/java/org/distorted/control/RubikControlWhole.java b/src/main/java/org/distorted/control/RubikControlWhole.java
index e8e7b9b8..b6f1a61f 100644
--- a/src/main/java/org/distorted/control/RubikControlWhole.java
+++ b/src/main/java/org/distorted/control/RubikControlWhole.java
@@ -34,6 +34,7 @@ import org.distorted.library.type.Dynamic3D;
 import org.distorted.library.type.Static3D;
 import org.distorted.main.R;
 import org.distorted.main.RubikActivity;
+import org.distorted.main.RubikSurfaceView;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -55,6 +56,7 @@ class RubikControlWhole
   private static final int[] DYN = { 2, 1, 1, 1, 2, 2, 4, 2, 2, 2, 2, 2, 4};
 
   private float X0, X1, X2, Y1, D, s001, s014, s033, F;
+  private int mWidth, mHeight;
 
   private final RubikControl mControl;
   private DistortedEffects[] mEffects;
@@ -274,6 +276,12 @@ class RubikControlWhole
 
     mDynMoveHand1.add(mPosition1);
     mDynMoveShad1.add(mPosition1);
+
+    RubikSurfaceView view = mControl.getSurfaceView();
+    float x = point1.get0() + mWidth*0.5f;
+    float y = mHeight*0.5f - point1.get1();
+    view.prepareDown();
+    view.actionDown(x,y);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -767,17 +775,17 @@ class RubikControlWhole
     mEffects[3].apply(moveHand2);
 
     DistortedScreen screen = mControl.getScreen();
-    int wid= screen.getWidth();
-    int hei= screen.getHeight();
-
-    X0   = wid*0.55f;
-    X1   = wid*0.45f;
-    X2   = wid*0.35f;
-    Y1   = hei*0.28f;
-    D    = wid*0.01f;
-    s001 = wid*0.0001f;
-    s014 = wid*0.14f;
-    s033 = wid*0.33f;
+    mWidth = screen.getWidth();
+    mHeight= screen.getHeight();
+
+    X0   = mWidth*0.65f;
+    X1   = mWidth*0.50f;
+    X2   = mWidth*0.35f;
+    Y1   = mHeight*0.28f;
+    D    = mWidth*0.01f;
+    s001 = mWidth*0.0001f;
+    s014 = mWidth*0.14f;
+    s033 = mWidth*0.33f;
     F    = 0.60f;
     }
 
@@ -886,7 +894,26 @@ class RubikControlWhole
       {
       case 1: boolean finished1 = mDyn1.get( tmpBuffer,0, time, mDiffTime);
               mPosition1.set(tmpBuffer[0], tmpBuffer[1], tmpBuffer[2]);
-              if( finished1 ) stageFinished(mCurrentStage);
+
+              if( mCurrentStage==3 )
+                {
+                RubikSurfaceView view = mControl.getSurfaceView();
+                float x = tmpBuffer[0]+mWidth*0.5f;
+                float y = mHeight*0.5f-tmpBuffer[1];
+                view.actionMove(x,y);
+                }
+
+              if( finished1 )
+                {
+                if( mCurrentStage==3 )
+                  {
+                  RubikSurfaceView view = mControl.getSurfaceView();
+                  view.prepareUp();
+                  view.actionUp();
+                  }
+
+                stageFinished(mCurrentStage);
+                }
               break;
       case 2: boolean finished2_1 = mDyn1.get( tmpBuffer,0, time, mDiffTime);
               boolean finished2_2 = mDyn2.get( tmpBuffer,3, time, mDiffTime);
diff --git a/src/main/java/org/distorted/main/RubikActivity.java b/src/main/java/org/distorted/main/RubikActivity.java
index e8c0e34d..4d017c33 100644
--- a/src/main/java/org/distorted/main/RubikActivity.java
+++ b/src/main/java/org/distorted/main/RubikActivity.java
@@ -396,24 +396,31 @@ public class RubikActivity extends AppCompatActivity
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public int getScreenWidthInPixels()
+    public RubikPreRender getPreRender()
       {
-      return mScreenWidth;
+      RubikSurfaceView view = findViewById(R.id.rubikSurfaceView);
+      return view.getPreRender();
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public int getScreenHeightInPixels()
+    public RubikSurfaceView getSurfaceView()
       {
-      return mScreenHeight;
+      return findViewById(R.id.rubikSurfaceView);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public RubikPreRender getPreRender()
+    public int getScreenWidthInPixels()
       {
-      RubikSurfaceView view = findViewById(R.id.rubikSurfaceView);
-      return view.getPreRender();
+      return mScreenWidth;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int getScreenHeightInPixels()
+      {
+      return mScreenHeight;
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/main/RubikSurfaceView.java b/src/main/java/org/distorted/main/RubikSurfaceView.java
index 9ef274a3..8492796b 100644
--- a/src/main/java/org/distorted/main/RubikSurfaceView.java
+++ b/src/main/java/org/distorted/main/RubikSurfaceView.java
@@ -80,6 +80,7 @@ public class RubikSurfaceView extends GLSurfaceView
 
     private int mPointer1, mPointer2;
     private float mX1, mY1, mX2, mY2, mX, mY;
+    private boolean mIsAutomatic;
 
     private static final Static4D mQuat= new Static4D(-0.25189602f,0.3546389f,0.009657208f,0.90038127f);
     private static final Static4D mTemp= new Static4D(0,0,0,1);
@@ -342,7 +343,7 @@ public class RubikSurfaceView extends GLSurfaceView
           {
           final RubikActivity act = (RubikActivity)getContext();
 
-          mDragging           = !act.isLocked();
+          mDragging           = (!act.isLocked() || mIsAutomatic);
           mBeginningRotation  = false;
           mContinuingRotation = false;
           }
@@ -529,7 +530,7 @@ public class RubikSurfaceView extends GLSurfaceView
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    private void prepareUp()
+    private void prepareUp(MotionEvent event)
       {
       mPointer1 = INVALID_POINTER_ID;
       mPointer2 = INVALID_POINTER_ID;
@@ -575,6 +576,8 @@ public class RubikSurfaceView extends GLSurfaceView
 
       if(!isInEditMode())
         {
+        mIsAutomatic = false;
+
         mLastCubitColor = -1;
         mCurrRotSpeed   = 0.0f;
 
@@ -623,10 +626,27 @@ public class RubikSurfaceView extends GLSurfaceView
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public void actionMove(int p1, float x1, float y1, int p2, float x2, float y2)
+    public void prepareDown()
       {
-      float pX = p1 != INVALID_POINTER_ID ? x1 : x2;
-      float pY = p1 != INVALID_POINTER_ID ? y1 : y2;
+      mIsAutomatic = true;
+      mPointer1 = 0;
+      mPointer2 = INVALID_POINTER_ID;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void prepareUp()
+      {
+      mIsAutomatic = false;
+      mPointer1 = INVALID_POINTER_ID;
+      mPointer2 = INVALID_POINTER_ID;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void actionMove(float pX, float pY)
+      {
+      //android.util.Log.e("D", "ACTION MOVE x="+pX+" y="+pY+" mDragging="+mDragging);
 
       float x = (pX - mScreenWidth*0.5f)/mScreenMin;
       float y = (mScreenHeight*0.5f -pY)/mScreenMin;
@@ -654,10 +674,12 @@ public class RubikSurfaceView extends GLSurfaceView
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public void actionDown(float x1, float y1)
+    public void actionDown(float x, float y)
       {
-      mX = (x1 -  mScreenWidth*0.5f)/mScreenMin;
-      mY = (mScreenHeight*0.5f - y1)/mScreenMin;
+      //android.util.Log.e("D", "ACTION DOWN x="+x+" y="+y);
+
+      mX = (x -  mScreenWidth*0.5f)/mScreenMin;
+      mY = (mScreenHeight*0.5f - y)/mScreenMin;
 
       setUpDragOrRotate(true,mX,mY);
       }
@@ -666,6 +688,8 @@ public class RubikSurfaceView extends GLSurfaceView
 
     public void actionUp()
       {
+      //android.util.Log.e("D", "ACTION UP");
+
       if( mContinuingRotation )
         {
         finishRotation();
@@ -702,14 +726,14 @@ public class RubikSurfaceView extends GLSurfaceView
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public void actionUp2(int p1, float x1, float y1, int p2, float x2, float y2)
+    public void actionUp2(boolean p1isUp, float x1, float y1, boolean p2isUp, float x2, float y2)
       {
-      if( p1==INVALID_POINTER_ID )
+      if( p1isUp )
         {
         mX = (x2 -  mScreenWidth*0.5f)/mScreenMin;
         mY = (mScreenHeight*0.5f - y2)/mScreenMin;
         }
-      if( p2==INVALID_POINTER_ID )
+      if( p2isUp )
         {
         mX = (x1 -  mScreenWidth*0.5f)/mScreenMin;
         mY = (mScreenHeight*0.5f - y1)/mScreenMin;
@@ -729,16 +753,20 @@ public class RubikSurfaceView extends GLSurfaceView
                                                actionDown(mX1, mY1);
                                                break;
          case MotionEvent.ACTION_MOVE        : prepareMove(event);
-                                               actionMove(mPointer1, mX1, mY1, mPointer2, mX2, mY2);
+                                               float x = mPointer1 != INVALID_POINTER_ID ? mX1 : mX2;
+                                               float y = mPointer1 != INVALID_POINTER_ID ? mY1 : mY2;
+                                               actionMove(x,y);
                                                break;
-         case MotionEvent.ACTION_UP          : prepareUp();
+         case MotionEvent.ACTION_UP          : prepareUp(event);
                                                actionUp();
                                                break;
          case MotionEvent.ACTION_POINTER_DOWN: prepareDown2(event);
                                                actionDown2(mX1, mY1, mX2, mY2);
                                                break;
          case MotionEvent.ACTION_POINTER_UP  : prepareUp2(event);
-                                               actionUp2(mPointer1, mX1, mY1, mPointer2, mX2, mY2);
+                                               boolean p1isUp = mPointer1==INVALID_POINTER_ID;
+                                               boolean p2isUp = mPointer2==INVALID_POINTER_ID;
+                                               actionUp2(p1isUp, mX1, mY1, p2isUp, mX2, mY2);
                                                break;
          }
 
