commit 40c41d1ed7562bed34c02a5b3624112bc5943f6d
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Tue Oct 27 23:57:05 2020 +0000

    Remove all traces of tutorials from the new 1.5.4.
    This is a bigger job; tutorials will only come in 1.6.0.

diff --git a/build.gradle b/build.gradle
index 2ba00d86..723ff43a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -15,8 +15,8 @@ android {
         applicationId "org.distorted.magic"
         minSdkVersion 21
         targetSdkVersion 29
-        versionCode 21
-        versionName "1.5.3"
+        versionCode 22
+        versionName "1.5.4"
     }
 
     buildTypes {
@@ -35,9 +35,9 @@ android {
 
 dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
-    implementation 'com.google.firebase:firebase-analytics:17.6.0'
+    implementation 'com.google.firebase:firebase-analytics:18.0.0'
     implementation 'com.google.firebase:firebase-crashlytics:17.2.2'
-    implementation 'com.google.android.play:core:1.8.2'
+    implementation 'com.google.android.play:core:1.8.3'
 
     api project(':distorted-library')
     implementation 'androidx.appcompat:appcompat:1.2.0'
diff --git a/src/main/java/org/distorted/dialogs/RubikDialogInfo.java b/src/main/java/org/distorted/dialogs/RubikDialogInfo.java
index 8762d67f..020a6aac 100644
--- a/src/main/java/org/distorted/dialogs/RubikDialogInfo.java
+++ b/src/main/java/org/distorted/dialogs/RubikDialogInfo.java
@@ -39,7 +39,6 @@ import androidx.fragment.app.FragmentActivity;
 import org.distorted.main.R;
 import org.distorted.main.RubikActivity;
 import org.distorted.objects.TwistyObject;
-import org.distorted.tutorial.TutorialActivity;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -74,11 +73,7 @@ public class RubikDialogInfo extends AppCompatDialogFragment
       @Override
       public void onClick(DialogInterface dialog, int which)
         {
-        RubikActivity ract = (RubikActivity)getContext();
-        Intent myIntent = new Intent(ract, TutorialActivity.class);
-        //myIntent.putExtra("", value); //Optional parameters
 
-        if( ract!=null ) ract.startActivity(myIntent);
         }
       });
 
diff --git a/src/main/java/org/distorted/states/RubikStateBase.java b/src/main/java/org/distorted/states/RubikStateBase.java
index aaffdd94..504ea28c 100644
--- a/src/main/java/org/distorted/states/RubikStateBase.java
+++ b/src/main/java/org/distorted/states/RubikStateBase.java
@@ -133,8 +133,10 @@ abstract class RubikStateBase extends RubikStateAbstract implements RubikPreRend
     layoutLeft.addView(mPrevButton);
     setupLockButton(act,width);
     layoutMid.addView(mLockButton);
+    /*
     setupInfoButton(act,width);
     layoutMid.addView(mInfoButton);
+     */
     layoutRight.addView(button);
 
     layoutBot.addView(layoutLeft);
diff --git a/src/main/java/org/distorted/tutorial/TutorialActivity.java b/src/main/java/org/distorted/tutorial/TutorialActivity.java
deleted file mode 100644
index 5a2b5ba0..00000000
--- a/src/main/java/org/distorted/tutorial/TutorialActivity.java
+++ /dev/null
@@ -1,325 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2019 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is free software: you can redistribute it and/or modify                            //
-// it under the terms of the GNU General Public License as published by                          //
-// the Free Software Foundation, either version 2 of the License, or                             //
-// (at your option) any later version.                                                           //
-//                                                                                               //
-// Magic Cube is distributed in the hope that it will be useful,                                 //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
-// GNU General Public License for more details.                                                  //
-//                                                                                               //
-// You should have received a copy of the GNU General Public License                             //
-// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.tutorial;
-
-import android.os.Build;
-import android.os.Bundle;
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.webkit.WebView;
-import android.widget.LinearLayout;
-
-import androidx.appcompat.app.AppCompatActivity;
-
-import com.google.firebase.analytics.FirebaseAnalytics;
-
-import org.distorted.dialogs.RubikDialogError;
-import org.distorted.main.R;
-import org.distorted.objects.ObjectList;
-import org.distorted.objects.TwistyObject;
-import org.distorted.states.RubikStatePlay;
-import org.distorted.states.StateList;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class TutorialActivity extends AppCompatActivity
-{
-    public static final float DIALOG_BUTTON_SIZE  = 0.06f;
-    public static final float MENU_BIG_TEXT_SIZE  = 0.05f;
-
-    public static final int FLAGS =  View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
-                                   | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
-                                   | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
-                                   | View.SYSTEM_UI_FLAG_FULLSCREEN
-                                   | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
-
-    public static final int FLAGS2=  View.SYSTEM_UI_FLAG_LAYOUT_STABLE
-                                   | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
-
-    private boolean mIsLocked;
-    private FirebaseAnalytics mFirebaseAnalytics;
-    private static int mScreenWidth, mScreenHeight;
-    private int mCurrentApiVersion;
-    private WebView mWebView;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    @Override
-    protected void onCreate(Bundle savedState)
-      {
-      super.onCreate(savedState);
-      setTheme(R.style.CustomActivityThemeNoActionBar);
-      setContentView(R.layout.tutorial);
-
-      mIsLocked = false;
-      mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
-
-      DisplayMetrics displaymetrics = new DisplayMetrics();
-      getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
-      mScreenWidth =displaymetrics.widthPixels;
-      mScreenHeight=displaymetrics.heightPixels;
-
-      hideNavigationBar();
-      cutoutHack();
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void hideNavigationBar()
-      {
-      mCurrentApiVersion = Build.VERSION.SDK_INT;
-
-      if(mCurrentApiVersion >= Build.VERSION_CODES.KITKAT)
-        {
-        final View decorView = getWindow().getDecorView();
-
-        decorView.setSystemUiVisibility(FLAGS);
-
-        decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener()
-          {
-          @Override
-          public void onSystemUiVisibilityChange(int visibility)
-            {
-            if((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0)
-              {
-              decorView.setSystemUiVisibility(FLAGS);
-              }
-            }
-          });
-        }
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    @Override
-    public void onAttachedToWindow()
-      {
-      super.onAttachedToWindow();
-
-      final float RATIO = 0.10f;
-      float width = getScreenWidthInPixels();
-      LinearLayout layout = findViewById(R.id.rightBar);
-      ViewGroup.LayoutParams params = layout.getLayoutParams();
-      params.width = (int)(width*RATIO);
-      layout.setLayoutParams(params);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// do not avoid cutouts
-
-    private void cutoutHack()
-      {
-      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
-        {
-        getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
-        }
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    @Override
-    public void onWindowFocusChanged(boolean hasFocus)
-      {
-      super.onWindowFocusChanged(hasFocus);
-
-      if(mCurrentApiVersion >= Build.VERSION_CODES.KITKAT && hasFocus)
-        {
-        getWindow().getDecorView().setSystemUiVisibility(FLAGS);
-        }
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-    @Override
-    protected void onPause() 
-      {
-      super.onPause();
-      TutorialSurfaceView view = findViewById(R.id.tutorialSurfaceView);
-      view.onPause();
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-    @Override
-    protected void onResume() 
-      {
-      super.onResume();
-      TutorialSurfaceView view = findViewById(R.id.tutorialSurfaceView);
-      view.onResume();
-      view.initialize();
-
-      boolean success = false;
-      RubikStatePlay play = (RubikStatePlay) StateList.PLAY.getStateClass();
-      int object = play.getObject();
-      int size   = play.getSize();
-
-      if( object>=0 && object< ObjectList.NUM_OBJECTS )
-        {
-        ObjectList obj = ObjectList.getObject(object);
-        int[] sizes = obj.getSizes();
-        int sizeIndex = ObjectList.getSizeIndex(object,size);
-
-        if( sizeIndex>=0 && sizeIndex<sizes.length )
-          {
-          success = true;
-          view.getPreRender().changeObject(obj,size);
-          }
-        }
-/*
-      if( !success )
-        {
-        ObjectList obj = ObjectList.getObject(RubikStatePlay.DEF_OBJECT);
-        int s = RubikStatePlay.DEF_SIZE;
-
-        play.setObjectAndSize(this,obj,s);
-        view.getPreRender().changeObject(obj,s);
-        }
- */
-      }
-    
-///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-    @Override
-    protected void onDestroy() 
-      {
-      super.onDestroy();
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    void OpenGLError()
-      {
-      RubikDialogError errDiag = new RubikDialogError();
-      errDiag.show(getSupportFragmentManager(), null);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public FirebaseAnalytics getAnalytics()
-      {
-      return mFirebaseAnalytics;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public TwistyObject getObject()
-      {
-      TutorialSurfaceView view = findViewById(R.id.rubikSurfaceView);
-      TutorialPreRender pre = view.getPreRender();
-      return pre.getObject();
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public int getScreenWidthInPixels()
-      {
-      return mScreenWidth;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public int getScreenHeightInPixels()
-      {
-      return mScreenHeight;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public TutorialPreRender getPreRender()
-      {
-      TutorialSurfaceView view = findViewById(R.id.tutorialSurfaceView);
-      return view.getPreRender();
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public static int getDrawableSize()
-      {
-      if( mScreenHeight<1000 )
-        {
-        return 0;
-        }
-      if( mScreenHeight<1600 )
-        {
-        return 1;
-        }
-      if( mScreenHeight<1900 )
-        {
-        return 2;
-        }
-
-      return 3;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public static int getDrawable(int small, int medium, int big, int huge)
-      {
-      int size = getDrawableSize();
-
-      switch(size)
-        {
-        case 0 : return small;
-        case 1 : return medium;
-        case 2 : return big;
-        default: return huge;
-        }
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public boolean isVertical()
-      {
-      TutorialSurfaceView view = findViewById(R.id.tutorialSurfaceView);
-      return view.isVertical();
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void toggleLock()
-      {
-      mIsLocked = !mIsLocked;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public boolean isLocked()
-      {
-      StateList state = StateList.getCurrentState();
-
-      if( state== StateList.PLAY || state== StateList.READ || state== StateList.SOLV )
-        {
-        return mIsLocked;
-        }
-
-      return false;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public boolean retLocked()
-      {
-      return mIsLocked;
-      }
-}
diff --git a/src/main/java/org/distorted/tutorial/TutorialPreRender.java b/src/main/java/org/distorted/tutorial/TutorialPreRender.java
deleted file mode 100644
index 88071911..00000000
--- a/src/main/java/org/distorted/tutorial/TutorialPreRender.java
+++ /dev/null
@@ -1,386 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2020 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is free software: you can redistribute it and/or modify                            //
-// it under the terms of the GNU General Public License as published by                          //
-// the Free Software Foundation, either version 2 of the License, or                             //
-// (at your option) any later version.                                                           //
-//                                                                                               //
-// Magic Cube is distributed in the hope that it will be useful,                                 //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
-// GNU General Public License for more details.                                                  //
-//                                                                                               //
-// You should have received a copy of the GNU General Public License                             //
-// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.tutorial;
-
-import android.content.Context;
-import android.content.res.Resources;
-
-import org.distorted.effects.BaseEffect;
-import org.distorted.effects.EffectController;
-import org.distorted.objects.ObjectList;
-import org.distorted.objects.TwistyObject;
-import org.distorted.main.RubikPreRender.ActionFinishedListener;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class TutorialPreRender implements EffectController
-  {
-  private ActionFinishedListener mAddActionListener;
-  private TutorialSurfaceView mView;
-  private boolean mFinishRotation, mRemoveRotation, mAddRotation,
-                  mSetQuat, mChangeObject, mSetupObject, mSolveObject,
-                  mInitializeObject, mResetAllTextureMaps, mRemovePatternRotation;
-  private boolean mCanPlay;
-  private boolean mIsSolved;
-  private ObjectList mNextObject;
-  private int mNextSize;
-  private long mRotationFinishedID;
-  private int mScreenWidth;
-  private int[][] mNextMoves;
-  private TwistyObject mOldObject, mNewObject;
-  private int mAddRotationAxis, mAddRotationRowBitmap, mAddRotationAngle;
-  private long mAddRotationDuration;
-  private long mAddRotationID, mRemoveRotationID;
-  private int mNearestAngle;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  TutorialPreRender(TutorialSurfaceView view)
-    {
-    mView = view;
-
-    mFinishRotation = false;
-    mRemoveRotation = false;
-    mAddRotation    = false;
-    mSetQuat        = false;
-    mChangeObject   = false;
-    mSetupObject    = false;
-    mSolveObject    = false;
-    mCanPlay        = true;
-    mOldObject      = null;
-    mNewObject      = null;
-    mScreenWidth    = 0;
-
-    mRemovePatternRotation= false;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void createObjectNow(ObjectList object, int size, int[][] moves)
-    {
-    if( mOldObject!=null ) mOldObject.releaseResources();
-    mOldObject = mNewObject;
-
-    Context con = mView.getContext();
-    Resources res = con.getResources();
-
-    mNewObject = object.create(size, mView.getQuat(), moves, res, mScreenWidth);
-
-    if( mNewObject!=null )
-      {
-      mNewObject.createTexture();
-      mView.setMovement(object.getObjectMovementClass());
-
-      if( mScreenWidth!=0 )
-        {
-        mNewObject.recomputeScaleFactor(mScreenWidth);
-        }
-
-      mIsSolved = mNewObject.isSolved();
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void doEffectNow(BaseEffect.Type type)
-    {
-    try
-      {
-      type.startEffect(mView.getRenderer().getScreen(),this);
-      }
-    catch( Exception ex )
-      {
-      mCanPlay= true;
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void removePatternRotation()
-    {
-    mRemovePatternRotation = true;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void removePatternRotationNow()
-    {
-    mRemovePatternRotation=false;
-    mNewObject.removeRotationNow();
-    mAddActionListener.onActionFinished(mRemoveRotationID);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void removeRotationNow()
-    {
-    mRemoveRotation=false;
-    mNewObject.removeRotationNow();
-
-    boolean solved = mNewObject.isSolved();
-
-    if( solved && !mIsSolved )
-      {
-      doEffectNow( BaseEffect.Type.WIN );
-      }
-    else
-      {
-      mCanPlay = true;
-      }
-
-    mIsSolved = solved;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void removeRotation()
-    {
-    mRemoveRotation = true;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void addRotationNow()
-    {
-    mAddRotation = false;
-    mAddRotationID = mNewObject.addNewRotation( mAddRotationAxis, mAddRotationRowBitmap,
-                                                mAddRotationAngle, mAddRotationDuration, this);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void finishRotationNow()
-    {
-    mFinishRotation = false;
-    mCanPlay        = false;
-    mRotationFinishedID = mNewObject.finishRotationNow(this, mNearestAngle);
-
-    if( mRotationFinishedID==0 ) // failed to add effect - should never happen
-      {
-      mCanPlay   = true;
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void changeObjectNow()
-    {
-    mChangeObject = false;
-
-    if ( mNewObject==null || mNewObject.getObjectList()!=mNextObject || mNewObject.getNumLayers()!=mNextSize)
-      {
-      mCanPlay  = false;
-      createObjectNow(mNextObject, mNextSize, null);
-      doEffectNow( BaseEffect.Type.SIZECHANGE );
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void setupObjectNow()
-    {
-    mSetupObject = false;
-
-    if ( mNewObject==null || mNewObject.getObjectList()!=mNextObject || mNewObject.getNumLayers()!=mNextSize)
-      {
-      mCanPlay  = false;
-      createObjectNow(mNextObject, mNextSize, mNextMoves);
-      doEffectNow( BaseEffect.Type.SIZECHANGE );
-      }
-    else
-      {
-      mNewObject.initializeObject(mNextMoves);
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void solveObjectNow()
-    {
-    mSolveObject = false;
-    mCanPlay     = false;
-    doEffectNow( BaseEffect.Type.SOLVE );
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void initializeObjectNow()
-    {
-    mInitializeObject = false;
-    mNewObject.initializeObject(mNextMoves);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void resetAllTextureMapsNow()
-    {
-    mResetAllTextureMaps = false;
-
-    if( mNewObject!=null ) mNewObject.resetAllTextureMaps();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void setQuatNow()
-    {
-    mSetQuat = false;
-    mView.setQuat();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-//
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  void setScreenSize(int width)
-    {
-    if( mNewObject!=null )
-      {
-      mNewObject.createTexture();
-      mNewObject.recomputeScaleFactor(width);
-      }
-
-    mScreenWidth  = width;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  void finishRotation(int nearestAngle)
-    {
-    mNearestAngle   = nearestAngle;
-    mFinishRotation = true;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  void changeObject(ObjectList object, int size)
-    {
-    if( size>0 )
-      {
-      mChangeObject = true;
-      mNextObject = object;
-      mNextSize   = size;
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  void setQuatOnNextRender()
-    {
-    mSetQuat = true;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  void preRender()
-    {
-    if( mSetQuat               ) setQuatNow();
-    if( mFinishRotation        ) finishRotationNow();
-    if( mRemoveRotation        ) removeRotationNow();
-    if( mChangeObject          ) changeObjectNow();
-    if( mSetupObject           ) setupObjectNow();
-    if( mSolveObject           ) solveObjectNow();
-    if( mAddRotation           ) addRotationNow();
-    if( mInitializeObject      ) initializeObjectNow();
-    if( mResetAllTextureMaps   ) resetAllTextureMapsNow();
-    if( mRemovePatternRotation ) removePatternRotationNow();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void addRotation(ActionFinishedListener listener, int axis, int rowBitmap, int angle, long duration)
-    {
-    mAddRotation = true;
-
-    mAddActionListener    = listener;
-    mAddRotationAxis      = axis;
-    mAddRotationRowBitmap = rowBitmap;
-    mAddRotationAngle     = angle;
-    mAddRotationDuration  = duration;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void initializeObject(int[][] moves)
-    {
-    mInitializeObject = true;
-    mNextMoves = moves;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int getNumScrambles()
-    {
-    return 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void solveObject()
-    {
-    if( mCanPlay )
-      {
-      mSolveObject = true;
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void resetAllTextureMaps()
-    {
-    mResetAllTextureMaps = true;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public TwistyObject getObject()
-    {
-    return mNewObject;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public TwistyObject getOldObject()
-    {
-    return null;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void effectFinished(final long effectID)
-    {
-    if( effectID == mRotationFinishedID )
-      {
-      mRotationFinishedID = 0;
-      removeRotation();
-      }
-    else if( effectID == mAddRotationID )
-      {
-      mAddRotationID = 0;
-      mRemoveRotationID = effectID;
-      removePatternRotation();
-      }
-    else
-      {
-      mCanPlay   = true;
-      }
-    }
-  }
diff --git a/src/main/java/org/distorted/tutorial/TutorialRenderer.java b/src/main/java/org/distorted/tutorial/TutorialRenderer.java
deleted file mode 100644
index c2a2424f..00000000
--- a/src/main/java/org/distorted/tutorial/TutorialRenderer.java
+++ /dev/null
@@ -1,81 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2019 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is free software: you can redistribute it and/or modify                            //
-// it under the terms of the GNU General Public License as published by                          //
-// the Free Software Foundation, either version 2 of the License, or                             //
-// (at your option) any later version.                                                           //
-//                                                                                               //
-// Magic Cube is distributed in the hope that it will be useful,                                 //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
-// GNU General Public License for more details.                                                  //
-//                                                                                               //
-// You should have received a copy of the GNU General Public License                             //
-// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.tutorial;
-
-import android.opengl.GLSurfaceView;
-
-import org.distorted.library.main.DistortedScreen;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class TutorialRenderer implements GLSurfaceView.Renderer
-{
-   private TutorialSurfaceView mView;
-   private DistortedScreen mScreen;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-   TutorialRenderer(TutorialSurfaceView v)
-     {
-     final float BRIGHTNESS = 0.30f;
-
-     mView = v;
-     mScreen = new DistortedScreen();
-     mScreen.glClearColor(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS, 1.0f);
-     }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-   @Override
-   public void onDrawFrame(GL10 glUnused)
-     {
-     long time = System.currentTimeMillis();
-     mView.getPreRender().preRender();
-     mScreen.render(time);
-     }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-   @Override
-   public void onSurfaceChanged(GL10 glUnused, int width, int height)
-      {
-      mScreen.resize(width,height);
-      mView.setScreenSize(width,height);
-      mView.getPreRender().setScreenSize(width);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-   @Override
-   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
-      {
-
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-   DistortedScreen getScreen()
-     {
-     return mScreen;
-     }
-}
diff --git a/src/main/java/org/distorted/tutorial/TutorialSurfaceView.java b/src/main/java/org/distorted/tutorial/TutorialSurfaceView.java
deleted file mode 100644
index 679d66e4..00000000
--- a/src/main/java/org/distorted/tutorial/TutorialSurfaceView.java
+++ /dev/null
@@ -1,710 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Copyright 2019 Leszek Koltunski                                                               //
-//                                                                                               //
-// This file is part of Magic Cube.                                                              //
-//                                                                                               //
-// Magic Cube is free software: you can redistribute it and/or modify                            //
-// it under the terms of the GNU General Public License as published by                          //
-// the Free Software Foundation, either version 2 of the License, or                             //
-// (at your option) any later version.                                                           //
-//                                                                                               //
-// Magic Cube is distributed in the hope that it will be useful,                                 //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
-// GNU General Public License for more details.                                                  //
-//                                                                                               //
-// You should have received a copy of the GNU General Public License                             //
-// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-package org.distorted.tutorial;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.pm.ConfigurationInfo;
-import android.opengl.GLES30;
-import android.opengl.GLSurfaceView;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.view.MotionEvent;
-
-import com.google.firebase.crashlytics.FirebaseCrashlytics;
-
-import org.distorted.library.type.Static2D;
-import org.distorted.library.type.Static4D;
-import org.distorted.objects.Movement;
-import org.distorted.objects.TwistyObject;
-import org.distorted.states.RubikStateSolving;
-import org.distorted.states.StateList;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class TutorialSurfaceView extends GLSurfaceView
-{
-    private static final int NUM_SPEED_PROBES = 10;
-    private static final int INVALID_POINTER_ID = -1;
-
-    // Moving the finger from the middle of the vertical screen to the right edge will rotate a
-    // given face by SWIPING_SENSITIVITY/2 degrees.
-    private final static int SWIPING_SENSITIVITY  = 240;
-    // Moving the finger by 0.3 of an inch will start a Rotation.
-    private final static float ROTATION_SENSITIVITY = 0.3f;
-
-    private final Static4D CAMERA_POINT = new Static4D(0, 0, 1, 0);
-
-    private TutorialRenderer mRenderer;
-    private TutorialPreRender mPreRender;
-    private Movement mMovement;
-    private boolean mDragging, mBeginningRotation, mContinuingRotation;
-    private int mScreenWidth, mScreenHeight, mScreenMin;
-
-    private float mRotAngle, mInitDistance;
-    private int mPtrID1, mPtrID2;
-    private float mX, mY;
-    private float mStartRotX, mStartRotY;
-    private float mAxisX, mAxisY;
-    private float mRotationFactor;
-    private int mCurrentAxis, mCurrentRow;
-    private float mCurrentAngle, mCurrRotSpeed;
-    private float[] mLastX;
-    private float[] mLastY;
-    private long[] mLastT;
-    private int mFirstIndex, mLastIndex;
-    private int mDensity;
-
-    private static Static4D mQuat= new Static4D(-0.25189602f,0.3546389f,0.009657208f,0.90038127f);
-    private static Static4D mTemp= new Static4D(0,0,0,1);
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    void setScreenSize(int width, int height)
-      {
-      mScreenWidth = width;
-      mScreenHeight= height;
-
-      mScreenMin = Math.min(width, height);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    boolean isVertical()
-      {
-      return mScreenHeight>mScreenWidth;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    TutorialRenderer getRenderer()
-      {
-      return mRenderer;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    TutorialPreRender getPreRender()
-      {
-      return mPreRender;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    void setQuat()
-      {
-      mQuat.set(mTemp);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    Static4D getQuat()
-      {
-      return mQuat;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    void setMovement(Movement movement)
-      {
-      mMovement = movement;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private Static4D quatFromDrag(float dragX, float dragY)
-      {
-      float axisX = dragY;  // inverted X and Y - rotation axis is perpendicular to (dragX,dragY)
-      float axisY = dragX;  // Why not (-dragY, dragX) ? because Y axis is also inverted!
-      float axisZ = 0;
-      float axisL = (float)Math.sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);
-
-      if( axisL>0 )
-        {
-        axisX /= axisL;
-        axisY /= axisL;
-        axisZ /= axisL;
-
-        float ratio = axisL;
-        ratio = ratio - (int)ratio;     // the cos() is only valid in (0,Pi)
-
-        float cosA = (float)Math.cos(Math.PI*ratio);
-        float sinA = (float)Math.sqrt(1-cosA*cosA);
-
-        return new Static4D(axisX*sinA, axisY*sinA, axisZ*sinA, cosA);
-        }
-
-      return new Static4D(0f, 0f, 0f, 1f);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// cast the 3D axis we are currently rotating along (which is already casted to the surface of the
-// currently touched face AND converted into a 4D vector - fourth 0) to a 2D in-screen-surface axis
-
-    private void computeCurrentAxis(Static4D axis)
-      {
-      Static4D result = rotateVectorByQuat(axis, mQuat);
-
-      mAxisX =result.get0();
-      mAxisY =result.get1();
-
-      float len = (float)Math.sqrt(mAxisX*mAxisX + mAxisY*mAxisY);
-      mAxisX /= len;
-      mAxisY /= len;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// return quat1*quat2
-
-    public static Static4D quatMultiply( Static4D quat1, Static4D quat2 )
-      {
-      float qx = quat1.get0();
-      float qy = quat1.get1();
-      float qz = quat1.get2();
-      float qw = quat1.get3();
-
-      float rx = quat2.get0();
-      float ry = quat2.get1();
-      float rz = quat2.get2();
-      float rw = quat2.get3();
-
-      float tx = rw*qx - rz*qy + ry*qz + rx*qw;
-      float ty = rw*qy + rz*qx + ry*qw - rx*qz;
-      float tz = rw*qz + rz*qw - ry*qx + rx*qy;
-      float tw = rw*qw - rz*qz - ry*qy - rx*qx;
-
-      return new Static4D(tx,ty,tz,tw);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// rotate 'vector' by quat  ( i.e. return quat*vector*(quat^-1) )
-
-    public static Static4D rotateVectorByQuat(Static4D vector, Static4D quat)
-      {
-      float qx = quat.get0();
-      float qy = quat.get1();
-      float qz = quat.get2();
-      float qw = quat.get3();
-
-      Static4D quatInverted= new Static4D(-qx,-qy,-qz,qw);
-      Static4D tmp = quatMultiply(quat,vector);
-
-      return quatMultiply(tmp,quatInverted);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// rotate 'vector' by quat^(-1)  ( i.e. return (quat^-1)*vector*quat )
-
-    public static Static4D rotateVectorByInvertedQuat(Static4D vector, Static4D quat)
-      {
-      float qx = quat.get0();
-      float qy = quat.get1();
-      float qz = quat.get2();
-      float qw = quat.get3();
-
-      Static4D quatInverted= new Static4D(-qx,-qy,-qz,qw);
-      Static4D tmp = quatMultiply(quatInverted,vector);
-
-      return quatMultiply(tmp,quat);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void addSpeedProbe(float x, float y)
-      {
-      long currTime = System.currentTimeMillis();
-      boolean theSame = mLastIndex==mFirstIndex;
-
-      mLastIndex++;
-      if( mLastIndex>=NUM_SPEED_PROBES ) mLastIndex=0;
-
-      mLastT[mLastIndex] = currTime;
-      mLastX[mLastIndex] = x;
-      mLastY[mLastIndex] = y;
-
-      if( mLastIndex==mFirstIndex)
-        {
-        mFirstIndex++;
-        if( mFirstIndex>=NUM_SPEED_PROBES ) mFirstIndex=0;
-        }
-
-      if( theSame )
-        {
-        mLastT[mFirstIndex] = currTime;
-        mLastX[mFirstIndex] = x;
-        mLastY[mFirstIndex] = y;
-        }
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void computeCurrentSpeedInInchesPerSecond()
-      {
-      long firstTime = mLastT[mFirstIndex];
-      long lastTime  = mLastT[mLastIndex];
-      float fX = mLastX[mFirstIndex];
-      float fY = mLastY[mFirstIndex];
-      float lX = mLastX[mLastIndex];
-      float lY = mLastY[mLastIndex];
-
-      long timeDiff = lastTime-firstTime;
-
-      mLastIndex = 0;
-      mFirstIndex= 0;
-
-      mCurrRotSpeed = timeDiff>0 ? 1000*retFingerDragDistanceInInches(fX,fY,lX,lY)/timeDiff : 0;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private float retFingerDragDistanceInInches(float xFrom, float yFrom, float xTo, float yTo)
-      {
-      float xDist = mScreenWidth*(xFrom-xTo);
-      float yDist = mScreenHeight*(yFrom-yTo);
-      float distInPixels = (float)Math.sqrt(xDist*xDist + yDist*yDist);
-
-      return distInPixels/mDensity;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void setUpDragOrRotate(float x, float y)
-      {
-        Static4D touchPoint = new Static4D(x, y, 0, 0);
-        Static4D rotatedTouchPoint= rotateVectorByInvertedQuat(touchPoint, mQuat);
-        Static4D rotatedCamera= rotateVectorByInvertedQuat(CAMERA_POINT, mQuat);
-
-        if( mMovement!=null && mMovement.faceTouched(rotatedTouchPoint,rotatedCamera) )
-          {
-          mDragging           = false;
-          mContinuingRotation = false;
-          mBeginningRotation  = true;
-          }
-        else
-          {
-          final TutorialActivity act = (TutorialActivity)getContext();
-          mDragging           = !act.isLocked();
-          mContinuingRotation = false;
-          mBeginningRotation  = false;
-          }
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void drag(MotionEvent event, float x, float y)
-      {
-      if( mPtrID1!=INVALID_POINTER_ID && mPtrID2!=INVALID_POINTER_ID)
-        {
-        int pointer = event.findPointerIndex(mPtrID2);
-        float pX,pY;
-
-        try
-          {
-          pX = event.getX(pointer);
-          pY = event.getY(pointer);
-          }
-        catch(IllegalArgumentException ex)
-          {
-          mPtrID1=INVALID_POINTER_ID;
-          mPtrID2=INVALID_POINTER_ID;
-
-          FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
-          crashlytics.setCustomKey("DragError", "pointer="+pointer );
-          crashlytics.recordException(ex);
-
-          return;
-          }
-
-        float x2 = (pX - mScreenWidth*0.5f)/mScreenMin;
-        float y2 = (mScreenHeight*0.5f -pY)/mScreenMin;
-
-        float angleNow = getAngle(x,y,x2,y2);
-        float angleDiff = angleNow-mRotAngle;
-        float sinA =-(float)Math.sin(angleDiff);
-        float cosA = (float)Math.cos(angleDiff);
-
-        Static4D dragQuat = quatMultiply(new Static4D(0,0,sinA,cosA), mQuat);
-        mTemp.set(dragQuat);
-
-        mRotAngle = angleNow;
-
-        float distNow  = (float)Math.sqrt( (x-x2)*(x-x2) + (y-y2)*(y-y2) );
-        float distQuot = mInitDistance<0 ? 1.0f : distNow/ mInitDistance;
-        mInitDistance = distNow;
-
-        TwistyObject object = mPreRender.getObject();
-        if( object!=null ) object.setObjectRatio(distQuot);
-        }
-      else
-        {
-        Static4D dragQuat = quatMultiply(quatFromDrag(mX-x,y-mY), mQuat);
-        mTemp.set(dragQuat);
-        }
-
-      mPreRender.setQuatOnNextRender();
-      mX = x;
-      mY = y;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void finishRotation()
-      {
-      computeCurrentSpeedInInchesPerSecond();
-      int angle = mPreRender.getObject().computeNearestAngle(mCurrentAngle, mCurrRotSpeed);
-      mPreRender.finishRotation(angle);
-
-////////////
-// TODO
-      if( angle!=0 )
-        {
-        if( StateList.getCurrentState()== StateList.SOLV )
-          {
-          RubikStateSolving solving = (RubikStateSolving) StateList.SOLV.getStateClass();
-          solving.addMove(mCurrentAxis, mCurrentRow, angle);
-          }
-        }
-///////////
-
-      mContinuingRotation = false;
-      mBeginningRotation  = false;
-      mDragging           = true;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void continueRotation(float x, float y)
-      {
-      float dx = x-mStartRotX;
-      float dy = y-mStartRotY;
-      float alpha = dx*mAxisX + dy*mAxisY;
-      float x2 = dx - alpha*mAxisX;
-      float y2 = dy - alpha*mAxisY;
-
-      float len = (float)Math.sqrt(x2*x2 + y2*y2);
-
-      // we have the length of 1D vector 'angle', now the direction:
-      float tmp = mAxisY==0 ? -mAxisX*y2 : mAxisY*x2;
-
-      float angle = (tmp>0 ? 1:-1)*len*mRotationFactor;
-      mCurrentAngle = SWIPING_SENSITIVITY*angle;
-      mPreRender.getObject().continueRotation(mCurrentAngle);
-
-      addSpeedProbe(x2,y2);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void beginRotation(float x, float y)
-      {
-      mStartRotX = x;
-      mStartRotY = y;
-
-      TwistyObject object = mPreRender.getObject();
-      int numLayers = object.getNumLayers();
-
-      Static4D touchPoint2 = new Static4D(x, y, 0, 0);
-      Static4D rotatedTouchPoint2= rotateVectorByInvertedQuat(touchPoint2, mQuat);
-      Static2D res = mMovement.newRotation(numLayers,rotatedTouchPoint2);
-
-      mCurrentAxis = (int)res.get0();
-      mCurrentRow  = (int)res.get1();
-
-      computeCurrentAxis( mMovement.getCastedRotAxis(mCurrentAxis) );
-      mRotationFactor = mMovement.returnRotationFactor(numLayers,mCurrentRow);
-
-      object.beginNewRotation( mCurrentAxis, mCurrentRow );
-
-      addSpeedProbe(x,y);
-
-      mBeginningRotation = false;
-      mContinuingRotation= true;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private float getAngle(float x1, float y1, float x2, float y2)
-      {
-      return (float) Math.atan2(y1-y2, x1-x2);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void actionMove(MotionEvent event)
-      {
-      int pointer = event.findPointerIndex(mPtrID1 != INVALID_POINTER_ID ? mPtrID1:mPtrID2);
-
-      if( pointer<0 ) return;
-
-      float pX = event.getX(pointer);
-      float pY = event.getY(pointer);
-
-      float x = (pX - mScreenWidth*0.5f)/mScreenMin;
-      float y = (mScreenHeight*0.5f -pY)/mScreenMin;
-
-      if( mBeginningRotation )
-        {
-        if( retFingerDragDistanceInInches(mX,mY,x,y) > ROTATION_SENSITIVITY )
-          {
-          beginRotation(x,y);
-          }
-        }
-      else if( mContinuingRotation )
-        {
-        continueRotation(x,y);
-        }
-      else if( mDragging )
-        {
-        drag(event,x,y);
-        }
-      else
-        {
-        setUpDragOrRotate(x,y);
-        }
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void actionDown(MotionEvent event)
-      {
-      mPtrID1 = event.getPointerId(0);
-
-      float x = event.getX();
-      float y = event.getY();
-
-      mX = (x - mScreenWidth*0.5f)/mScreenMin;
-      mY = (mScreenHeight*0.5f -y)/mScreenMin;
-
-      setUpDragOrRotate(mX,mY);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void actionUp(MotionEvent event)
-      {
-      mPtrID1 = INVALID_POINTER_ID;
-      mPtrID2 = INVALID_POINTER_ID;
-
-      if( mContinuingRotation )
-        {
-        finishRotation();
-        }
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void actionDown2(MotionEvent event)
-      {
-      int index = event.getActionIndex();
-
-      if( mPtrID1==INVALID_POINTER_ID )
-        {
-        mPtrID1 = event.getPointerId(index);
-        float x = event.getX();
-        float y = event.getY();
-
-        if( mPtrID2 != INVALID_POINTER_ID )
-          {
-          int pointer = event.findPointerIndex(mPtrID2);
-
-          try
-            {
-            float x2 = event.getX(pointer);
-            float y2 = event.getY(pointer);
-
-            mRotAngle = getAngle(x,-y,x2,-y2);
-            mInitDistance = -1;
-            }
-          catch(IllegalArgumentException ex)
-            {
-            mPtrID1=INVALID_POINTER_ID;
-            mPtrID2=INVALID_POINTER_ID;
-
-            FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
-            crashlytics.setCustomKey("DragError", "pointer="+pointer );
-            crashlytics.recordException(ex);
-
-            return;
-            }
-          }
-
-        mX = (x - mScreenWidth*0.5f)/mScreenMin;
-        mY = (mScreenHeight*0.5f -y)/mScreenMin;
-        }
-      else if( mPtrID2==INVALID_POINTER_ID )
-        {
-        mPtrID2 = event.getPointerId(index);
-
-        float x = event.getX();
-        float y = event.getY();
-
-        if( mPtrID2 != INVALID_POINTER_ID )
-          {
-          int pointer = event.findPointerIndex(mPtrID2);
-
-          try
-            {
-            float x2 = event.getX(pointer);
-            float y2 = event.getY(pointer);
-
-            mRotAngle = getAngle(x,-y,x2,-y2);
-            mInitDistance = -1;
-            }
-          catch(IllegalArgumentException ex)
-            {
-            mPtrID1=INVALID_POINTER_ID;
-            mPtrID2=INVALID_POINTER_ID;
-
-            FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
-            crashlytics.setCustomKey("DragError", "pointer="+pointer );
-            crashlytics.recordException(ex);
-
-            return;
-            }
-          }
-
-        if( mBeginningRotation || mContinuingRotation )
-          {
-          mX = (x - mScreenWidth*0.5f)/mScreenMin;
-          mY = (mScreenHeight*0.5f -y)/mScreenMin;
-          }
-        }
-
-      if( mBeginningRotation )
-        {
-        mContinuingRotation = false;
-        mBeginningRotation  = false;
-        mDragging           = true;
-        }
-      else if( mContinuingRotation )
-        {
-        finishRotation();
-        }
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    private void actionUp2(MotionEvent event)
-      {
-      int index = event.getActionIndex();
-
-      if( index==event.findPointerIndex(mPtrID1) )
-        {
-        mPtrID1 = INVALID_POINTER_ID;
-        int pointer = event.findPointerIndex(mPtrID2);
-
-        if( pointer>=0 )
-          {
-          float x1 = event.getX(pointer);
-          float y1 = event.getY(pointer);
-
-          mX = (x1 - mScreenWidth*0.5f)/mScreenMin;
-          mY = (mScreenHeight*0.5f -y1)/mScreenMin;
-          }
-        }
-      else if( index==event.findPointerIndex(mPtrID2) )
-        {
-        mPtrID2 = INVALID_POINTER_ID;
-        }
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    void initialize()
-      {
-      mPtrID1 = INVALID_POINTER_ID;
-      mPtrID2 = INVALID_POINTER_ID;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC API
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public TutorialSurfaceView(Context context, AttributeSet attrs)
-      {
-      super(context,attrs);
-
-      if(!isInEditMode())
-        {
-        mCurrRotSpeed= 0.0f;
-
-        mLastX = new float[NUM_SPEED_PROBES];
-        mLastY = new float[NUM_SPEED_PROBES];
-        mLastT = new long[NUM_SPEED_PROBES];
-        mFirstIndex =0;
-        mLastIndex  =0;
-
-        mRenderer  = new TutorialRenderer(this);
-        mPreRender = new TutorialPreRender(this);
-
-        TutorialActivity act = (TutorialActivity)context;
-        DisplayMetrics dm = new DisplayMetrics();
-        act.getWindowManager().getDefaultDisplay().getMetrics(dm);
-
-        mDensity = dm.densityDpi;
-
-        final ActivityManager activityManager= (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
-
-        try
-          {
-          final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
-          int esVersion = configurationInfo.reqGlEsVersion>>16;
-          setEGLContextClientVersion(esVersion);
-          setRenderer(mRenderer);
-          }
-        catch(Exception ex)
-          {
-          act.OpenGLError();
-
-          String shading = GLES30.glGetString(GLES30.GL_SHADING_LANGUAGE_VERSION);
-          String version = GLES30.glGetString(GLES30.GL_VERSION);
-          String vendor  = GLES30.glGetString(GLES30.GL_VENDOR);
-          String renderer= GLES30.glGetString(GLES30.GL_RENDERER);
-
-          FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
-          crashlytics.setCustomKey("GLSL Version"  , shading );
-          crashlytics.setCustomKey("GLversion"     , version );
-          crashlytics.setCustomKey("GL Vendor "    , vendor  );
-          crashlytics.setCustomKey("GLSLrenderer"  , renderer);
-          crashlytics.recordException(ex);
-          }
-        }
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event)
-      {
-      int action = event.getActionMasked();
-
-      switch(action)
-         {
-         case MotionEvent.ACTION_DOWN        : actionDown(event) ; break;
-         case MotionEvent.ACTION_MOVE        : actionMove(event) ; break;
-         case MotionEvent.ACTION_UP          : actionUp(event)   ; break;
-         case MotionEvent.ACTION_POINTER_DOWN: actionDown2(event); break;
-         case MotionEvent.ACTION_POINTER_UP  : actionUp2(event)  ; break;
-         }
-
-      return true;
-      }
-}
-
