commit beee90ab9175ed00409119da412b3c81b2cd27e1
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Fri Apr 22 17:32:23 2022 +0200

    Preparation for Mixup Cube: take advantage of the recent bump in MAJOR_VERSION number and change the format of basicAngles to int[][] 'per-axis-per-layer' [ Mixup Cube has different basicAngle in its middle layers (8) - and different in its edge layers (4) ]

diff --git a/src/main/java/org/distorted/objectlib/effects/scramble/ScrambleEffect.java b/src/main/java/org/distorted/objectlib/effects/scramble/ScrambleEffect.java
index 1bb2dcca..6f0280f9 100644
--- a/src/main/java/org/distorted/objectlib/effects/scramble/ScrambleEffect.java
+++ b/src/main/java/org/distorted/objectlib/effects/scramble/ScrambleEffect.java
@@ -69,7 +69,7 @@ public abstract class ScrambleEffect extends BaseEffect implements EffectListene
   private int mNumScramblesLeft;
   private int mDurationPerDegree;
   private final Random mRnd;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private boolean mRotReady, mPluginReady;
 
   ObjectPreRender mPre;
@@ -100,15 +100,16 @@ public abstract class ScrambleEffect extends BaseEffect implements EffectListene
   private void createBaseEffects(int duration, int numScrambles)
     {
     mNumScramblesLeft = numScrambles;
-    int absAngle, angle, axis, basicDegrees, totalDegrees = 0;
+    int absAngle, angle, axis, row, basicDegrees, totalDegrees = 0;
 
     for(int scramble=0; scramble<mNumScramblesLeft; scramble++)
       {
       mObject.randomizeNewScramble(mScrambles, mRnd, scramble, numScrambles);
       axis  = mScrambles[scramble][0];
+      row   = mScrambles[scramble][1];
       angle = mScrambles[scramble][2];
       absAngle = (angle<0 ? -angle : angle);
-      basicDegrees = 360/mBasicAngle[axis];
+      basicDegrees = 360/mBasicAngle[axis][row];
       totalDegrees += absAngle*basicDegrees;
       }
 
diff --git a/src/main/java/org/distorted/objectlib/helpers/QuatGroupGenerator.java b/src/main/java/org/distorted/objectlib/helpers/QuatGroupGenerator.java
index 02d17a52..91acaa77 100644
--- a/src/main/java/org/distorted/objectlib/helpers/QuatGroupGenerator.java
+++ b/src/main/java/org/distorted/objectlib/helpers/QuatGroupGenerator.java
@@ -121,7 +121,7 @@ public class QuatGroupGenerator
 // PUBLIC API
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public static Static4D[] computeGroup(Static3D[] rotAxis, int[] basicAngles)
+  public static Static4D[] computeGroup(Static3D[] rotAxis, int[][] basicAngles)
     {
     Static4D quat = new Static4D(0,0,0,1);
     int num,numAxis = rotAxis.length;
@@ -130,11 +130,20 @@ public class QuatGroupGenerator
     insertQuat(quat,mTable);
 
     for( int ax=0; ax<numAxis; ax++)
-      for(int angle=1; angle<basicAngles[ax]; angle++)
+      {
+      int numLayers = basicAngles[ax].length;
+
+      for( int layer=0; layer<numLayers; layer++)
         {
-        createQuat(rotAxis[ax], 2*PI*angle/basicAngles[ax], quat);
-        insertQuat(quat,mTable);
+        int numAngles = basicAngles[ax][layer];
+
+        for(int angle=1; angle<numAngles; angle++)
+          {
+          createQuat(rotAxis[ax], (2*PI*angle)/numAngles, quat);
+          insertQuat(quat,mTable);
+          }
         }
+      }
 
     do
       {
diff --git a/src/main/java/org/distorted/objectlib/json/JsonReader.java b/src/main/java/org/distorted/objectlib/json/JsonReader.java
index fd671a9a..9d9c6078 100644
--- a/src/main/java/org/distorted/objectlib/json/JsonReader.java
+++ b/src/main/java/org/distorted/objectlib/json/JsonReader.java
@@ -67,7 +67,7 @@ public class JsonReader
   private int[][] mVariantFaceColor, mCubitFaceColor;
   private ObjectSticker[] mObjectSticker;
   private Static3D[] mAxis;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private String mLongName, mShortName, mInventor;
   private int mYearOfInvention, mComplexity;
   private int[] mNumLayers;
@@ -334,11 +334,11 @@ public class JsonReader
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void parseAxis(JSONArray object) throws JSONException
+  private void parseAxis1(JSONArray object) throws JSONException
     {
     int numAxis = object.length();
 
-    mBasicAngle     = new int[numAxis];
+    mBasicAngle     = new int[numAxis][];
     mAxis           = new Static3D[numAxis];
     mCuts           = new float[numAxis][];
     mLayerRotatable = new boolean[numAxis][];
@@ -348,7 +348,45 @@ public class JsonReader
       {
       JSONObject jsonAx = object.getJSONObject(i);
 
-      mBasicAngle[i] = jsonAx.getInt("basicAngle");
+      float x = (float)jsonAx.getDouble("x");
+      float y = (float)jsonAx.getDouble("y");
+      float z = (float)jsonAx.getDouble("z");
+
+      mAxis[i] = new Static3D(x,y,z);
+
+      JSONArray jsonCuts = jsonAx.getJSONArray("cuts");
+      int numCuts = jsonCuts.length();
+      mCuts[i] = new float[numCuts];
+      for(int j=0; j<numCuts; j++) mCuts[i][j] = (float)jsonCuts.getDouble(j);
+
+      JSONArray jsonRota = jsonAx.getJSONArray("rotatable");
+      int numRota = jsonRota.length();
+      mLayerRotatable[i] = new boolean[numRota];
+      for(int j=0; j<numRota; j++) mLayerRotatable[i][j] = jsonRota.getBoolean(j);
+
+      mBasicAngle[i] = new int[numRota];
+      int basicAngle = jsonAx.getInt("basicAngle");
+      for(int j=0; j<numRota; j++) mBasicAngle[i][j] = basicAngle;
+
+      mNumLayers[i] = numRota;
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void parseAxis2(JSONArray object) throws JSONException
+    {
+    int numAxis = object.length();
+
+    mBasicAngle     = new int[numAxis][];
+    mAxis           = new Static3D[numAxis];
+    mCuts           = new float[numAxis][];
+    mLayerRotatable = new boolean[numAxis][];
+    mNumLayers      = new int[numAxis];
+
+    for(int i=0; i<numAxis; i++)
+      {
+      JSONObject jsonAx = object.getJSONObject(i);
 
       float x = (float)jsonAx.getDouble("x");
       float y = (float)jsonAx.getDouble("y");
@@ -356,6 +394,11 @@ public class JsonReader
 
       mAxis[i] = new Static3D(x,y,z);
 
+      JSONArray jsonAngles = jsonAx.getJSONArray("basicAngles");
+      int numAngles = jsonAngles.length();
+      mBasicAngle[i] = new int[numAngles];
+      for(int j=0; j<numAngles; j++) mBasicAngle[i][j] = jsonAngles.getInt(j);
+
       JSONArray jsonCuts = jsonAx.getJSONArray("cuts");
       int numCuts = jsonCuts.length();
       mCuts[i] = new float[numCuts];
@@ -515,7 +558,29 @@ public class JsonReader
     JSONObject mesh        = object.getJSONObject("mesh");
     parseMesh(mesh);
     JSONArray axis         = object.getJSONArray("axis");
-    parseAxis(axis);
+    parseAxis1(axis);
+    JSONArray quats        = object.getJSONArray("quats");
+    parseQuats(quats);
+    JSONObject scrambling  = object.getJSONObject("scrambling");
+    parseScrambling(scrambling);
+    JSONObject touchcontrol= object.getJSONObject("touchcontrol");
+    parseTouchcontrol(touchcontrol);
+    JSONArray colors       = object.getJSONArray("colors");
+    parseColors(colors);
+    JSONObject solved      = object.getJSONObject("solved");
+    parseSolved(solved);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void parseVersion2(JSONObject object) throws JSONException
+    {
+    JSONObject metadata    = object.getJSONObject("metadata");
+    parseMetadata(metadata);
+    JSONObject mesh        = object.getJSONObject("mesh");
+    parseMesh(mesh);
+    JSONArray axis         = object.getJSONArray("axis");
+    parseAxis2(axis);
     JSONArray quats        = object.getJSONArray("quats");
     parseQuats(quats);
     JSONObject scrambling  = object.getJSONObject("scrambling");
@@ -577,6 +642,10 @@ public class JsonReader
         {
         parseVersion1(object);
         }
+      if( major==2 )
+        {
+        parseVersion2(object);
+        }
       else
         {
         android.util.Log.e("readJsonFile", "Unknown version "+major);
@@ -609,7 +678,7 @@ public class JsonReader
       JSONObject object = new JSONObject(contents.toString());
       int major = object.getInt("major");
 
-      if( major==1 )
+      if( major==1 || major==2 )
         {
         parseVersion1Metadata(object);
         }
@@ -875,7 +944,7 @@ public class JsonReader
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngle()
+  public int[][] getBasicAngle()
     {
     return mBasicAngle;
     }
diff --git a/src/main/java/org/distorted/objectlib/json/JsonWriter.java b/src/main/java/org/distorted/objectlib/json/JsonWriter.java
index 21b7c9d5..d5b89489 100644
--- a/src/main/java/org/distorted/objectlib/json/JsonWriter.java
+++ b/src/main/java/org/distorted/objectlib/json/JsonWriter.java
@@ -395,7 +395,7 @@ public class JsonWriter
 
     Static3D[] rotAxis = object.getRotationAxis();
     int numAxis = rotAxis.length;
-    int[] basicAngle = object.getBasicAngles();
+    int[][] basicAngle = object.getBasicAngles();
     int[] numLayers = object.getNumLayers();
     float[][] cuts = object.getCuts(numLayers);
     boolean[][] rotatable = object.getLayerRotatable(numLayers);
@@ -408,8 +408,10 @@ public class JsonWriter
       axObject.put("x", ax.get0() );
       axObject.put("y", ax.get1() );
       axObject.put("z", ax.get2() );
-      axObject.put("basicAngle", basicAngle[i] );
 
+      JSONArray angleArray = new JSONArray();
+      for(float angle : basicAngle[i]) angleArray.put(angle);
+      axObject.put("basicAngles", angleArray);
       JSONArray cutsArray = new JSONArray();
       for(float cut : cuts[i]) cutsArray.put(cut);
       axObject.put("cuts", cutsArray);
diff --git a/src/main/java/org/distorted/objectlib/main/ObjectControl.java b/src/main/java/org/distorted/objectlib/main/ObjectControl.java
index 63dc72f9..57d629d7 100644
--- a/src/main/java/org/distorted/objectlib/main/ObjectControl.java
+++ b/src/main/java/org/distorted/objectlib/main/ObjectControl.java
@@ -235,20 +235,19 @@ public class ObjectControl
     private void finishRotation()
       {
       TwistyObject object = mPreRender.getObject();
-      int[] angles = object.getBasicAngles();
+      int[][] angles = object.getBasicAngles();
 
       if( mCurrentAxis<angles.length )
         {
         computeCurrentSpeedInInchesPerSecond();
-
-        int angle = object.computeNearestAngle(mCurrentAxis,mCurrentAngle, mCurrRotSpeed);
+        int basic = angles[mCurrentAxis][mCurrentRow];
+        int angle = object.computeNearestAngle(basic,mCurrentAngle, mCurrRotSpeed);
         mPreRender.finishRotation(angle);
         mPreRender.rememberMove(mCurrentAxis,mCurrentRow,angle);
 
         if( angle!=0 )
           {
-          int basicAngle= angles[mCurrentAxis];
-          int realAngle = (angle*basicAngle)/360;
+          int realAngle = (angle*basic)/360;
           mInterface.onFinishRotation(mCurrentAxis,mCurrentRow,realAngle);
           }
 
diff --git a/src/main/java/org/distorted/objectlib/main/ObjectPreRender.java b/src/main/java/org/distorted/objectlib/main/ObjectPreRender.java
index e87a093f..1f56fa3c 100644
--- a/src/main/java/org/distorted/objectlib/main/ObjectPreRender.java
+++ b/src/main/java/org/distorted/objectlib/main/ObjectPreRender.java
@@ -306,6 +306,22 @@ public class ObjectPreRender implements EffectListener
     mController.setQuat();
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private int computeRowFromBitmap(int rowBitmap)
+    {
+    int index = 0;
+
+    while(index<32)
+      {
+      if( (rowBitmap&0x1) != 0 ) return index;
+      rowBitmap>>=1;
+      index++;
+      }
+
+    return 0;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   void rememberMove(int axis, int row, int angle)
@@ -518,13 +534,14 @@ public class ObjectPreRender implements EffectListener
 
   public void addRotation(MovesFinished listener, int axis, int rowBitmap, int bareAngle, int millPreDegree)
     {
-    int[] angles = mNewObject.getBasicAngles();
+    int[][] basicAngles = mNewObject.getBasicAngles();
 
-    if( angles.length>axis )
+    if( basicAngles.length>axis )
       {
       mAddRotation = true;
 
-      int basicAngle= angles[axis];
+      int row       = computeRowFromBitmap(rowBitmap);
+      int basicAngle= basicAngles[axis][row];
       int angle     = bareAngle*(360/basicAngle);
       int duration  = Math.abs(angle)*millPreDegree;
 
diff --git a/src/main/java/org/distorted/objectlib/main/TwistyJson.java b/src/main/java/org/distorted/objectlib/main/TwistyJson.java
index 7288e724..8ff8b57c 100644
--- a/src/main/java/org/distorted/objectlib/main/TwistyJson.java
+++ b/src/main/java/org/distorted/objectlib/main/TwistyJson.java
@@ -270,7 +270,7 @@ public class TwistyJson extends TwistyObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
     return mReader.getBasicAngle();
     }
diff --git a/src/main/java/org/distorted/objectlib/main/TwistyObject.java b/src/main/java/org/distorted/objectlib/main/TwistyObject.java
index 20f97713..aa74ef3b 100644
--- a/src/main/java/org/distorted/objectlib/main/TwistyObject.java
+++ b/src/main/java/org/distorted/objectlib/main/TwistyObject.java
@@ -145,7 +145,7 @@ public abstract class TwistyObject
   private int mNumCubitVariants;
   private int[][] mCubitFaceColors;
   private int[][] mVariantFaceIsOuter;
-  private int[] mBasicAngles;
+  private int[][] mBasicAngles;
   private int mIconMode;
 
   //////////////////// SOLVED1 ////////////////////////
@@ -970,7 +970,11 @@ public abstract class TwistyObject
         {
         axis     = move[0];
         rowBitmap= computeBitmapFromRow( move[1],axis );
-        angle    = move[2]*(360/mBasicAngles[axis]);
+        angle    = move[2]*(360/mBasicAngles[axis][move[1]]);   // this assumes that all layers from
+                                                                // the bitmap have the same BasicAngle.
+                                                                // at the moment this is always true as
+                                                                // there are no bandaged objects with
+                                                                // different per-layer BasicAngles.
         quat     = makeQuaternion(axis,angle);
 
         for(int j=0; j<mNumCubits; j++)
@@ -1524,11 +1528,9 @@ public abstract class TwistyObject
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  int computeNearestAngle(int axis, float angle, float speed)
+  int computeNearestAngle(int basicAngle, float angle, float speed)
     {
-    int basicAngle   = mBasicAngles[axis>=mBasicAngles.length ? 0 : axis];
     int nearestAngle = 360/basicAngle;
-
     int tmp = (int)((angle+nearestAngle/2)/nearestAngle);
     if( angle< -(nearestAngle*0.5) ) tmp-=1;
 
@@ -1727,7 +1729,7 @@ public abstract class TwistyObject
 
   // not only for JSON
   public abstract Static3D[] getRotationAxis();
-  public abstract int[] getBasicAngles();
+  public abstract int[][] getBasicAngles();
   public abstract int getNumFaces();
   public abstract String getObjectName();
   public abstract String getInventor();
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyAxis.java b/src/main/java/org/distorted/objectlib/objects/TwistyAxis.java
index 1657728a..4c7ffd69 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyAxis.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyAxis.java
@@ -45,7 +45,7 @@ public class TwistyAxis extends ShapeHexahedron
          };
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private float[][] mCenters;
   private int[] mQuatIndex;
@@ -497,9 +497,16 @@ public class TwistyAxis extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 4;
+      mBasicAngle = new int[][] { tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyBandagedAbstract.java b/src/main/java/org/distorted/objectlib/objects/TwistyBandagedAbstract.java
index effdd804..f0ae93dd 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyBandagedAbstract.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyBandagedAbstract.java
@@ -64,7 +64,7 @@ abstract class TwistyBandagedAbstract extends ShapeHexahedron
          {2,2,2},
         };
 
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private Static4D[] mInitQuats;
   private float[][] mCuts;
   private ScrambleState[] mStates;
@@ -582,9 +582,16 @@ abstract class TwistyBandagedAbstract extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 4;
+      mBasicAngle = new int[][] { tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 }
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyContainer.java b/src/main/java/org/distorted/objectlib/objects/TwistyContainer.java
index 98226314..19380bb2 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyContainer.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyContainer.java
@@ -46,7 +46,7 @@ public class TwistyContainer extends ShapeHexahedron
          };
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private int[][] mFaceMap;
 
@@ -322,9 +322,16 @@ public class TwistyContainer extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 3;
+      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyCuboid.java b/src/main/java/org/distorted/objectlib/objects/TwistyCuboid.java
index 48708822..61239b3d 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyCuboid.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyCuboid.java
@@ -47,7 +47,7 @@ public class TwistyCuboid extends ShapeHexahedron
 
   private ScrambleState[] mStates;
   private float[][] mCuts;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -715,16 +715,27 @@ public class TwistyCuboid extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
     if( mBasicAngle==null )
       {
       int[] num = getNumLayers();
-      int x = num[1]==num[2] ? 4 : 2;
-      int y = num[0]==num[2] ? 4 : 2;
-      int z = num[0]==num[1] ? 4 : 2;
-
-      mBasicAngle = new int[] { x,y,z };
+      int numX = num[0];
+      int numY = num[1];
+      int numZ = num[2];
+
+      int x = numY==numZ ? 4 : 2;
+      int y = numX==numZ ? 4 : 2;
+      int z = numX==numY ? 4 : 2;
+
+      int[] tmpX = new int[numX];
+      for(int i=0; i<numX; i++) tmpX[i] = x;
+      int[] tmpY = new int[numY];
+      for(int i=0; i<numY; i++) tmpY[i] = y;
+      int[] tmpZ = new int[numZ];
+      for(int i=0; i<numZ; i++) tmpZ[i] = z;
+
+      mBasicAngle = new int[][] { tmpX,tmpY,tmpZ };
       }
     return mBasicAngle;
     }
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyDiamond.java b/src/main/java/org/distorted/objectlib/objects/TwistyDiamond.java
index 6c27d150..e4f63ddd 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyDiamond.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyDiamond.java
@@ -48,7 +48,7 @@ public class TwistyDiamond extends ShapeOctahedron
          };
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private int[] mTetraToFaceMap;
   private float[][] mPosition;
@@ -476,9 +476,15 @@ public class TwistyDiamond extends ShapeOctahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 3;
+      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
+      }
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyDino.java b/src/main/java/org/distorted/objectlib/objects/TwistyDino.java
index 1a252feb..fb67c075 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyDino.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyDino.java
@@ -45,7 +45,7 @@ abstract class TwistyDino extends ShapeHexahedron
            new Static3D(+SQ3/3,-SQ3/3,-SQ3/3)
          };
 
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private float[][] mCenters;
   ScrambleState[] mStates;
@@ -229,9 +229,16 @@ abstract class TwistyDino extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle==null ) mBasicAngle = new int[] { 3,3,3,3 };
+    if( mBasicAngle==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 3;
+      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyFisher.java b/src/main/java/org/distorted/objectlib/objects/TwistyFisher.java
index 012c490c..b65ab8ce 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyFisher.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyFisher.java
@@ -45,7 +45,7 @@ public class TwistyFisher extends ShapeHexahedron
          };
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private float[][] mCenters;
   private int[] mQuatIndex;
@@ -390,9 +390,16 @@ public class TwistyFisher extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
+    if( mBasicAngle==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 4;
+      mBasicAngle = new int[][] { tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyHelicopter.java b/src/main/java/org/distorted/objectlib/objects/TwistyHelicopter.java
index 2510feaf..9c5be3bf 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyHelicopter.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyHelicopter.java
@@ -49,7 +49,7 @@ public class TwistyHelicopter extends ShapeHexahedron
          };
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private float[][] mCenters;
   private int[] mQuatIndices;
@@ -311,9 +311,15 @@ public class TwistyHelicopter extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 2,2,2,2,2,2 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 2;
+      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp,tmp,tmp };
+      }
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyIvy.java b/src/main/java/org/distorted/objectlib/objects/TwistyIvy.java
index 673ef1be..54eae00d 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyIvy.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyIvy.java
@@ -50,7 +50,7 @@ public class TwistyIvy extends ShapeHexahedron
   private static final int  IVY_N = 8;
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private int[] mQuatIndex;
 
@@ -426,9 +426,16 @@ public class TwistyIvy extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 3;
+      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyJing.java b/src/main/java/org/distorted/objectlib/objects/TwistyJing.java
index 7023d954..2111b0d0 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyJing.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyJing.java
@@ -51,7 +51,7 @@ public class TwistyJing extends ShapeTetrahedron
                                  // tetrahedron is 2.0 (ie standard, equal to numLayers)
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private int[] mQuatIndex;
   private float[][] mCuts;
   private float[][] mCenters;
@@ -352,9 +352,16 @@ public class TwistyJing extends ShapeTetrahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 3;
+      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyMinx.java b/src/main/java/org/distorted/objectlib/objects/TwistyMinx.java
index 4d71956b..ef7fd239 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyMinx.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyMinx.java
@@ -57,7 +57,7 @@ abstract class TwistyMinx extends ShapeDodecahedron
            new Static3D( SIN54/LEN,    0     ,   -C2/LEN )
          };
 
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   float[][] mCenterCoords,mCorners;
   int[] mQuatEdgeIndices,mQuatCornerIndices;
@@ -489,9 +489,16 @@ abstract class TwistyMinx extends ShapeDodecahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 5,5,5,5,5,5 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 5;
+      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 }
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyMirror.java b/src/main/java/org/distorted/objectlib/objects/TwistyMirror.java
index 7517827e..c0e755c9 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyMirror.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyMirror.java
@@ -52,7 +52,7 @@ public class TwistyMirror extends ShapeHexahedron
 
   private ScrambleState[] mStates;
   private float[][] mCuts;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mPositions;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -368,9 +368,16 @@ public class TwistyMirror extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle==null ) mBasicAngle = new int[] { 4,4,4 };
+    if( mBasicAngle==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 4;
+      mBasicAngle = new int[][] { tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyMorphix.java b/src/main/java/org/distorted/objectlib/objects/TwistyMorphix.java
index c38ff0bd..20c6c9b7 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyMorphix.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyMorphix.java
@@ -45,7 +45,7 @@ public class TwistyMorphix extends ShapeTetrahedron
          };
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private float[][] mCenters;
   private int[] mQuatIndex;
@@ -279,9 +279,16 @@ public class TwistyMorphix extends ShapeTetrahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
+    if( mBasicAngle==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 4;
+      mBasicAngle = new int[][] { tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyPyraminx.java b/src/main/java/org/distorted/objectlib/objects/TwistyPyraminx.java
index 0a377282..a31f66fc 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyPyraminx.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyPyraminx.java
@@ -47,7 +47,7 @@ public class TwistyPyraminx extends ShapeTetrahedron
          };
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -357,9 +357,16 @@ public class TwistyPyraminx extends ShapeTetrahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 3;
+      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyRedi.java b/src/main/java/org/distorted/objectlib/objects/TwistyRedi.java
index 496c922e..41a4cfcf 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyRedi.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyRedi.java
@@ -47,7 +47,7 @@ public class TwistyRedi extends ShapeHexahedron
          };
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private float[][] mPosition;
 
@@ -355,9 +355,16 @@ public class TwistyRedi extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 3;
+      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyRex.java b/src/main/java/org/distorted/objectlib/objects/TwistyRex.java
index 3eae466d..cb311873 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyRex.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyRex.java
@@ -49,7 +49,7 @@ public class TwistyRex extends ShapeHexahedron
   public static final float REX_D = 0.2f;
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private float[][] mPosition;
   private int[] mQuatIndex;
@@ -354,9 +354,16 @@ public class TwistyRex extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
+    if( mBasicAngle==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 3;
+      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistySkewb.java b/src/main/java/org/distorted/objectlib/objects/TwistySkewb.java
index f678ce68..8918c417 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistySkewb.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistySkewb.java
@@ -47,7 +47,7 @@ public class TwistySkewb extends ShapeHexahedron
          };
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private float[][] mPositions;
 
@@ -481,9 +481,16 @@ public class TwistySkewb extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 3;
+      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistySquare.java b/src/main/java/org/distorted/objectlib/objects/TwistySquare.java
index 2c0e868f..161bfabc 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistySquare.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistySquare.java
@@ -48,7 +48,7 @@ abstract class TwistySquare extends ShapeHexahedron
       new Static3D(0,-1,0),
     };
 
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -70,7 +70,7 @@ abstract class TwistySquare extends ShapeHexahedron
 
   void initializeBasicAngle()
     {
-    mBasicAngle = new int[] {12,2,12};
+    mBasicAngle = new int[][] { {12,12,12},{2,2},{12,12,12} };
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -133,7 +133,7 @@ abstract class TwistySquare extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
     if( mBasicAngle ==null ) initializeBasicAngle();
     return mBasicAngle;
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyTrajber.java b/src/main/java/org/distorted/objectlib/objects/TwistyTrajber.java
index 6bf68ab6..a526a607 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyTrajber.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyTrajber.java
@@ -50,7 +50,7 @@ public class TwistyTrajber extends ShapeOctahedron
          };
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private float[][] mPositions;
   private int[] mQuatIndex;
@@ -588,9 +588,16 @@ public class TwistyTrajber extends ShapeOctahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 4;
+      mBasicAngle = new int[][] { tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyUltimate.java b/src/main/java/org/distorted/objectlib/objects/TwistyUltimate.java
index 14f07ca3..e2e18363 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyUltimate.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyUltimate.java
@@ -54,7 +54,7 @@ public class TwistyUltimate extends ShapeDodecahedron
          };
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private float[][] mPositions;
   private int[] mQuatIndex;
@@ -356,9 +356,16 @@ public class TwistyUltimate extends ShapeDodecahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 3;
+      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyVoid.java b/src/main/java/org/distorted/objectlib/objects/TwistyVoid.java
index 6f13e86d..b61c9bc5 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyVoid.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyVoid.java
@@ -45,7 +45,7 @@ public class TwistyVoid extends ShapeHexahedron
          };
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private float[][] mPositions;
   private int[] mQuatIndex;
@@ -392,9 +392,16 @@ public class TwistyVoid extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 4;
+      mBasicAngle = new int[][] { tmp,tmp,tmp };
+      }
+
     return mBasicAngle;
     }
 
diff --git a/src/main/java/org/distorted/objectlib/objects/TwistyWindmill.java b/src/main/java/org/distorted/objectlib/objects/TwistyWindmill.java
index fd5a9dbe..b1fe35c3 100644
--- a/src/main/java/org/distorted/objectlib/objects/TwistyWindmill.java
+++ b/src/main/java/org/distorted/objectlib/objects/TwistyWindmill.java
@@ -49,7 +49,7 @@ public class TwistyWindmill extends ShapeHexahedron
          };
 
   private ScrambleState[] mStates;
-  private int[] mBasicAngle;
+  private int[][] mBasicAngle;
   private float[][] mCuts;
   private float[][] mPositions;
   private int[] mQuatIndex;
@@ -403,9 +403,15 @@ public class TwistyWindmill extends ShapeHexahedron
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int[] getBasicAngles()
+  public int[][] getBasicAngles()
     {
-    if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
+    if( mBasicAngle ==null )
+      {
+      int num = getNumLayers()[0];
+      int[] tmp = new int[num];
+      for(int i=0; i<num; i++) tmp[i] = 4;
+      mBasicAngle = new int[][] { tmp,tmp,tmp };
+      }
     return mBasicAngle;
     }
 
