commit e1a86bf279637d237294890d733b10731082ae67
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sat Oct 30 01:46:07 2021 +0200

    Move the main app to the 'J1M1' object creation mode, i.e. create them from the Json files and using the Dmesh fiels as well.
    
    Make it possible for any app descending from the 'objectlib' to use any of the J0M0, J0M1, J1M0, J1M1 modes.

diff --git a/build.gradle b/build.gradle
index 70d39451..664be15f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -24,6 +24,4 @@ android {
 
 dependencies {
     api project(':distorted-library')
-    implementation project(path: ':distorted-puzzle-dmesh')
-    implementation project(path: ':distorted-puzzle-jsons')
 }
\ No newline at end of file
diff --git a/src/main/java/org/distorted/objectlib/json/JsonReader.java b/src/main/java/org/distorted/objectlib/json/JsonReader.java
index a9f7b207..3e37ff6a 100644
--- a/src/main/java/org/distorted/objectlib/json/JsonReader.java
+++ b/src/main/java/org/distorted/objectlib/json/JsonReader.java
@@ -42,8 +42,6 @@ import org.distorted.objectlib.main.ObjectType;
 
 public class JsonReader
 {
-  private static JsonReader mThis;
-
   private ScrambleState[] mStates;
   private int[][] mSolvedQuats;
   private Static4D[] mQuats;
@@ -64,38 +62,29 @@ public class JsonReader
   private ObjectSticker[] mObjectSticker;
   private Static3D[] mAxis;
   private int[] mBasicAngle;
-  private String mLongName, mInventor;
+  private String mLongName, mShortName, mInventor;
   private int mYearOfInvention, mComplexity;
   private int[] mNumLayers;
   private float mSize;
-  private int mScrambleType;
+  private int mScrambleType, mNumScrambles;
   private int[] mColor;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private JsonReader()
-    {
-
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public static JsonReader getInstance()
-    {
-    if( mThis==null ) mThis = new JsonReader();
-    return mThis;
-    }
+  private ObjectType mType;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void parseMetadata(JSONObject object) throws JSONException
     {
     mLongName        = object.getString("longname");
+    mShortName       = object.getString("shortname");
     mInventor        = object.getString("inventor");
     mYearOfInvention = object.getInt("year");
     mComplexity      = object.getInt("complexity");
     mSize            = (float)object.getDouble("size");
     mSolvedFuncIndex = object.getInt("solved_func");
+    mNumScrambles    = object.getInt("scrambles");
+
+    int ordinal = ObjectType.getOrdinal(mShortName);
+    mType = ordinal>=0 ? ObjectType.getObject(ordinal) : null;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -655,6 +644,13 @@ public class JsonReader
     return mCubitFaceColor[cubit][face];
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getNumScrambles()
+    {
+    return mNumScrambles;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public ObjectSticker retSticker(int sticker)
@@ -680,7 +676,7 @@ public class JsonReader
 
   public ObjectType intGetObjectType()
     {
-    return null;
+    return mType;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -690,6 +686,13 @@ public class JsonReader
     return mLongName;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public String getShortName()
+    {
+    return mShortName;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public String getInventor()
diff --git a/src/main/java/org/distorted/objectlib/json/JsonWriter.java b/src/main/java/org/distorted/objectlib/json/JsonWriter.java
index 8b857278..63a2362f 100644
--- a/src/main/java/org/distorted/objectlib/json/JsonWriter.java
+++ b/src/main/java/org/distorted/objectlib/json/JsonWriter.java
@@ -36,6 +36,7 @@ import org.distorted.objectlib.helpers.ObjectShape;
 import org.distorted.objectlib.helpers.ObjectSticker;
 import org.distorted.objectlib.helpers.ScrambleState;
 import org.distorted.objectlib.main.TwistyObject;
+import org.distorted.objectlib.main.ObjectType;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -354,12 +355,16 @@ public class JsonWriter
     {
     JSONObject metadata = new JSONObject();
 
+    ObjectType type = object.getObjectType();
+
     metadata.put("longname"   , object.getObjectName() );
     metadata.put("inventor"   , object.getInventor());
     metadata.put("year"       , object.getYearOfInvention());
     metadata.put("complexity" , object.getComplexity());
     metadata.put("size"       , object.getSize() );
     metadata.put("solved_func", object.getSolvedFunctionIndex() );
+    metadata.put("scrambles"  , type.getNumScramble() );
+    metadata.put("shortname"  , type.name() );
 
     return metadata;
     }
diff --git a/src/main/java/org/distorted/objectlib/main/ObjectControl.java b/src/main/java/org/distorted/objectlib/main/ObjectControl.java
index 7fb413f6..f594f973 100644
--- a/src/main/java/org/distorted/objectlib/main/ObjectControl.java
+++ b/src/main/java/org/distorted/objectlib/main/ObjectControl.java
@@ -19,6 +19,8 @@
 
 package org.distorted.objectlib.main;
 
+import java.io.InputStream;
+
 import android.app.Activity;
 import android.content.SharedPreferences;
 import android.util.DisplayMetrics;
@@ -82,8 +84,6 @@ public class ObjectControl
     private static final Static4D mTemp= new Static4D(0,0,0,1);
 
     private static boolean mForcedIconMode = false;
-    private static boolean mForcedDmeshMode= false;
-    private static boolean mForcedJsonMode = false;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // cast the 3D axis we are currently rotating along (which is already casted to the surface of the
@@ -522,20 +522,6 @@ public class ObjectControl
       mForcedIconMode = mode;
       }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public static void setDmeshMode(boolean mode)
-      {
-      mForcedDmeshMode = mode;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public static void setJsonMode(boolean mode)
-      {
-      mForcedJsonMode = mode;
-      }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     public static boolean isInIconMode()
@@ -543,20 +529,6 @@ public class ObjectControl
       return mForcedIconMode;
       }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public static boolean isInDmeshMode()
-      {
-      return mForcedDmeshMode;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public static boolean isInJsonMode()
-      {
-      return mForcedJsonMode;
-      }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -736,16 +708,22 @@ public class ObjectControl
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public void changeObject(ObjectType newObject)
+    public void changeObject(int ordinal, InputStream jsonStream, InputStream meshStream)
       {
-      mPreRender.changeObject(newObject);
+      mPreRender.changeObject(ordinal, jsonStream, meshStream);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public void recreateObject()
+    public void changeIfDifferent(int ordinal, InputStream jsonStream, InputStream meshStream)
       {
-      mPreRender.recreateObject();
+      TwistyObject object = mPreRender.getObject();
+      ObjectType old = object==null ? null : object.getObjectType();
+
+      if( old==null || old.ordinal() != ordinal )
+        {
+        mPreRender.changeObject(ordinal, jsonStream, meshStream);
+        }
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/objectlib/main/ObjectPreRender.java b/src/main/java/org/distorted/objectlib/main/ObjectPreRender.java
index c075ffad..9da0c21d 100644
--- a/src/main/java/org/distorted/objectlib/main/ObjectPreRender.java
+++ b/src/main/java/org/distorted/objectlib/main/ObjectPreRender.java
@@ -20,15 +20,14 @@
 package org.distorted.objectlib.main;
 
 import java.io.InputStream;
-import java.lang.ref.WeakReference;
 
 import android.app.Activity;
 import android.content.SharedPreferences;
-import android.content.res.Resources;
 
 import org.distorted.library.message.EffectListener;
 import org.distorted.library.type.Static3D;
 
+import org.distorted.library.type.Static4D;
 import org.distorted.objectlib.helpers.ObjectLibInterface;
 import org.distorted.objectlib.effects.BaseEffect;
 import org.distorted.objectlib.effects.scramble.ScrambleEffect;
@@ -39,9 +38,9 @@ import org.distorted.objectlib.helpers.MovesFinished;
 
 public class ObjectPreRender implements EffectListener
   {
-  private final WeakReference<Activity> mAct;
   private final ObjectControl mController;
-  private ObjectType mNextObject;
+  private InputStream mJsonStream, mMeshStream;
+  private int mOrdinal;
   private TwistyObject mOldObject, mNewObject;
   private SharedPreferences mPreferences;
   private MovesFinished mAddActionListener;
@@ -51,7 +50,7 @@ public class ObjectPreRender implements EffectListener
   private float mMoveX, mMoveY;
 
   private boolean mFinishRotation, mRemoveRotation, mRemovePatternRotation, mAddRotation,
-                  mSetQuat, mChangeObject, mSolveObject, mScrambleObject, mRecreateObject,
+                  mSetQuat, mChangeObject, mSolveObject, mScrambleObject,
                   mInitializeObject, mSetTextureMap, mResetAllTextureMaps, mSolve;
   private boolean mUIBlocked, mTouchBlocked, mIsSolved;
   private long mRotationFinishedID;
@@ -69,7 +68,6 @@ public class ObjectPreRender implements EffectListener
 
   public ObjectPreRender(Activity act, ObjectControl controller, ObjectLibInterface actioner)
     {
-    mAct = new WeakReference<>(act);
     mInterface = actioner;
     mController = controller;
 
@@ -79,7 +77,6 @@ public class ObjectPreRender implements EffectListener
     mAddRotation          = false;
     mSetQuat              = false;
     mChangeObject         = false;
-    mRecreateObject       = false;
     mSolveObject          = false;
     mSolve                = false;
     mScrambleObject       = false;
@@ -98,30 +95,19 @@ public class ObjectPreRender implements EffectListener
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void createObjectNow(ObjectType object)
+  private void createObjectNow(int ordinal, InputStream jsonStream, InputStream meshStream)
     {
     boolean firstTime = (mNewObject==null);
 
     if( mOldObject!=null ) mOldObject.releaseResources();
     mOldObject = mNewObject;
     Static3D move = new Static3D(mMoveX,mMoveY,0);
-    Resources res = mAct.get().getResources();
+    Static4D quat = mController.getQuat();
 
     long time1 = System.currentTimeMillis();
 
-    int meshID = object.getMeshID();
-    InputStream meshStream = ( meshID!=0 && ObjectControl.isInDmeshMode() ) ? res.openRawResource(meshID) : null;
-
-    if( !ObjectControl.isInJsonMode() )
-      {
-      mNewObject = object.create( mController.getQuat(), move, meshStream);
-      }
-    else
-      {
-      int jsonID = object.getJsonID();
-      InputStream jsonStream = jsonID!=0 ? res.openRawResource(jsonID) : null;
-      mNewObject = new TwistyJson(jsonStream, mController.getQuat(), move, meshStream);
-      }
+    if( jsonStream==null ) mNewObject = ObjectType.create( ordinal, quat, move, meshStream);
+    else                   mNewObject = new TwistyJson( jsonStream, quat, move, meshStream);
 
     long time2 = System.currentTimeMillis();
     mInterface.onObjectCreated(time2-time1);
@@ -233,27 +219,9 @@ public class ObjectPreRender implements EffectListener
   private void changeObjectNow()
     {
     mChangeObject = false;
-
-    if ( mNewObject==null || mNewObject.getObjectType()!=mNextObject )
-      {
-      blockEverything(BlockController.PLACE_1);
-      createObjectNow(mNextObject);
-      doEffectNow( BaseEffect.Type.SIZECHANGE );
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void recreateObjectNow()
-    {
-    mRecreateObject = false;
-
-    if ( mNewObject!=null )
-      {
-      blockEverything(BlockController.PLACE_1);
-      createObjectNow(mNewObject.getObjectType());
-      doEffectNow( BaseEffect.Type.SIZECHANGE );
-      }
+    blockEverything(BlockController.PLACE_1);
+    createObjectNow(mOrdinal,mJsonStream,mMeshStream);
+    doEffectNow( BaseEffect.Type.SIZECHANGE );
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -422,17 +390,12 @@ public class ObjectPreRender implements EffectListener
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void changeObject(ObjectType object)
+  public void changeObject(int ordinal, InputStream jsonStream, InputStream meshStream)
     {
     mChangeObject = true;
-    mNextObject = object;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void recreateObject()
-    {
-    mRecreateObject = true;
+    mOrdinal    = ordinal;
+    mJsonStream = jsonStream;
+    mMeshStream = meshStream;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -503,7 +466,6 @@ public class ObjectPreRender implements EffectListener
     if( mRemoveRotation        ) removeRotationNow();
     if( mRemovePatternRotation ) removePatternRotationNow();
     if( mChangeObject          ) changeObjectNow();
-    if( mRecreateObject        ) recreateObjectNow();
     if( mSolveObject           ) solveObjectNow();
     if( mScrambleObject        ) scrambleObjectNow();
     if( mAddRotation           ) addRotationNow();
diff --git a/src/main/java/org/distorted/objectlib/main/ObjectType.java b/src/main/java/org/distorted/objectlib/main/ObjectType.java
index 9e644401..ede6d7ce 100644
--- a/src/main/java/org/distorted/objectlib/main/ObjectType.java
+++ b/src/main/java/org/distorted/objectlib/main/ObjectType.java
@@ -31,52 +31,50 @@ import org.distorted.objectlib.objects.*;
 
 public enum ObjectType
   {
-  CUBE_2 ( new int[] {2,2,2}      , 12, R.raw.json_cube_2, R.raw.cube_2, R.drawable.cube_2s, R.drawable.cube_2m, R.drawable.cube_2b, R.drawable.cube_2h),
-  CUBE_3 ( new int[] {3,3,3}      , 17, R.raw.json_cube_3, R.raw.cube_3, R.drawable.cube_3s, R.drawable.cube_3m, R.drawable.cube_3b, R.drawable.cube_3h),
-  CUBE_4 ( new int[] {4,4,4}      , 24, R.raw.json_cube_4, R.raw.cube_4, R.drawable.cube_4s, R.drawable.cube_4m, R.drawable.cube_4b, R.drawable.cube_4h),
-  CUBE_5 ( new int[] {5,5,5}      , 28, R.raw.json_cube_5, R.raw.cube_5, R.drawable.cube_5s, R.drawable.cube_5m, R.drawable.cube_5b, R.drawable.cube_5h),
-  CUBE_6 ( new int[] {6,6,6}      , 35, R.raw.json_cube_6, R.raw.cube_6, R.drawable.cube_6s, R.drawable.cube_6m, R.drawable.cube_6b, R.drawable.cube_6h),
-  DIAM_2 ( new int[] {2,2,2,2}    , 12, R.raw.json_diam_2, R.raw.diam_2, R.drawable.diam_2s, R.drawable.diam_2m, R.drawable.diam_2b, R.drawable.diam_2h),
-  DIAM_3 ( new int[] {3,3,3,3}    , 24, R.raw.json_diam_3, R.raw.diam_3, R.drawable.diam_3s, R.drawable.diam_3m, R.drawable.diam_3b, R.drawable.diam_3h),
-  DIAM_4 ( new int[] {4,4,4,4}    , 32, R.raw.json_diam_4, R.raw.diam_4, R.drawable.diam_4s, R.drawable.diam_4m, R.drawable.diam_4b, R.drawable.diam_4h),
-  JING_2 ( new int[] {2,2,2,2}    , 11, R.raw.json_jing_2, R.raw.jing_2, R.drawable.jing_2s, R.drawable.jing_2m, R.drawable.jing_2b, R.drawable.jing_2h),
-  PYRA_3 ( new int[] {3,3,3,3}    , 10, R.raw.json_pyra_3, R.raw.pyra_3, R.drawable.pyra_3s, R.drawable.pyra_3m, R.drawable.pyra_3b, R.drawable.pyra_3h),
-  PYRA_4 ( new int[] {4,4,4,4}    , 17, R.raw.json_pyra_4, R.raw.pyra_4, R.drawable.pyra_4s, R.drawable.pyra_4m, R.drawable.pyra_4b, R.drawable.pyra_4h),
-  PYRA_5 ( new int[] {5,5,5,5}    , 23, R.raw.json_pyra_5, R.raw.pyra_5, R.drawable.pyra_5s, R.drawable.pyra_5m, R.drawable.pyra_5b, R.drawable.pyra_5h),
-  KILO_3 ( new int[] {3,3,3,3,3,3}, 18, R.raw.json_kilo_3, R.raw.kilo_3, R.drawable.kilo_3s, R.drawable.kilo_3m, R.drawable.kilo_3b, R.drawable.kilo_3h),
-  KILO_5 ( new int[] {5,5,5,5,5,5}, 33, R.raw.json_kilo_5, R.raw.kilo_5, R.drawable.kilo_5s, R.drawable.kilo_5m, R.drawable.kilo_5b, R.drawable.kilo_5h),
-  MEGA_3 ( new int[] {3,3,3,3,3,3}, 21, R.raw.json_mega_3, R.raw.mega_3, R.drawable.mega_3s, R.drawable.mega_3m, R.drawable.mega_3b, R.drawable.mega_3h),
-  MEGA_5 ( new int[] {5,5,5,5,5,5}, 37, R.raw.json_mega_5, R.raw.mega_5, R.drawable.mega_5s, R.drawable.mega_5m, R.drawable.mega_5b, R.drawable.mega_5h),
-  ULTI_2 ( new int[] {2,2,2,2}    , 18, R.raw.json_ulti_2, R.raw.ulti_2, R.drawable.ulti_2s, R.drawable.ulti_2m, R.drawable.ulti_2b, R.drawable.ulti_2h),
-  DINO_3 ( new int[] {3,3,3,3}    , 10, R.raw.json_dino_3, R.raw.dino_3, R.drawable.dino_3s, R.drawable.dino_3m, R.drawable.dino_3b, R.drawable.dino_3h),
-  DIN4_3 ( new int[] {3,3,3,3}    ,  7, R.raw.json_din4_3, R.raw.dino_3, R.drawable.din4_3s, R.drawable.din4_3m, R.drawable.din4_3b, R.drawable.din4_3h),
-  REDI_3 ( new int[] {3,3,3,3}    , 16, R.raw.json_redi_3, R.raw.redi_3, R.drawable.redi_3s, R.drawable.redi_3m, R.drawable.redi_3b, R.drawable.redi_3h),
-  SKEW_2 ( new int[] {2,2,2,2}    , 11, R.raw.json_skew_2, R.raw.skew_2, R.drawable.skew_2s, R.drawable.skew_2m, R.drawable.skew_2b, R.drawable.skew_2h),
-  SKEW_3 ( new int[] {3,3,3,3}    , 21, R.raw.json_skew_3, R.raw.skew_3, R.drawable.skew_3s, R.drawable.skew_3m, R.drawable.skew_3b, R.drawable.skew_3h),
-  IVY_2  ( new int[] {2,2,2,2}    ,  8, R.raw.json_ivy_2 , R.raw.ivy_2 , R.drawable.ivy_2s , R.drawable.ivy_2m , R.drawable.ivy_2b , R.drawable.ivy_2h ),
-  REX_3  ( new int[] {3,3,3,3}    , 19, R.raw.json_rex_3 , R.raw.rex_3 , R.drawable.rex_3s , R.drawable.rex_3m , R.drawable.rex_3b , R.drawable.rex_3h ),
-  BAN1_3 ( new int[] {3,3,3}      , 16, R.raw.json_ban1_3, R.raw.ban1_3, R.drawable.ban1_3s, R.drawable.ban1_3m, R.drawable.ban1_3b, R.drawable.ban1_3h),
-  BAN2_3 ( new int[] {3,3,3}      , 16, R.raw.json_ban2_3, R.raw.ban2_3, R.drawable.ban2_3s, R.drawable.ban2_3m, R.drawable.ban2_3b, R.drawable.ban2_3h),
-  BAN3_3 ( new int[] {3,3,3}      , 16, R.raw.json_ban3_3, R.raw.ban3_3, R.drawable.ban3_3s, R.drawable.ban3_3m, R.drawable.ban3_3b, R.drawable.ban3_3h),
-  BAN4_3 ( new int[] {3,3,3}      , 16, R.raw.json_ban4_3, R.raw.ban4_3, R.drawable.ban4_3s, R.drawable.ban4_3m, R.drawable.ban4_3b, R.drawable.ban4_3h),
-  SQU1_3 ( new int[] {3,2,3}      , 24, R.raw.json_squ1_3, R.raw.squ1_3, R.drawable.squ1_3s, R.drawable.squ1_3m, R.drawable.squ1_3b, R.drawable.squ1_3h),
-  SQU2_3 ( new int[] {3,2,3}      , 24, R.raw.json_squ2_3, R.raw.squ2_3, R.drawable.squ2_3s, R.drawable.squ2_3m, R.drawable.squ2_3b, R.drawable.squ2_3h),
-  MIRR_2 ( new int[] {2,2,2}      , 12, R.raw.json_mirr_2, R.raw.mirr_2, R.drawable.mirr_2s, R.drawable.mirr_2m, R.drawable.mirr_2b, R.drawable.mirr_2h),
-  MIRR_3 ( new int[] {3,3,3}      , 17, R.raw.json_mirr_3, R.raw.mirr_3, R.drawable.mirr_3s, R.drawable.mirr_3m, R.drawable.mirr_3b, R.drawable.mirr_3h),
-  CU_323 ( new int[] {3,2,3}      , 15, R.raw.json_cu_323, R.raw.cu_323, R.drawable.cu_323s, R.drawable.cu_323m, R.drawable.cu_323b, R.drawable.cu_323h),
-  CU_232 ( new int[] {2,3,2}      , 16, R.raw.json_cu_232, R.raw.cu_232, R.drawable.cu_232s, R.drawable.cu_232m, R.drawable.cu_232b, R.drawable.cu_232h),
-  CU_343 ( new int[] {3,4,3}      , 23, R.raw.json_cu_343, R.raw.cu_343, R.drawable.cu_343s, R.drawable.cu_343m, R.drawable.cu_343b, R.drawable.cu_343h),
-  HELI_3 ( new int[] {3,3,3,3,3,3}, 20, R.raw.json_heli_3, R.raw.heli_3, R.drawable.heli_3s, R.drawable.heli_3m, R.drawable.heli_3b, R.drawable.heli_3h),
+  CUBE_2 ( new int[] {2,2,2}      , 12, R.drawable.cube_2s, R.drawable.cube_2m, R.drawable.cube_2b, R.drawable.cube_2h),
+  CUBE_3 ( new int[] {3,3,3}      , 17, R.drawable.cube_3s, R.drawable.cube_3m, R.drawable.cube_3b, R.drawable.cube_3h),
+  CUBE_4 ( new int[] {4,4,4}      , 24, R.drawable.cube_4s, R.drawable.cube_4m, R.drawable.cube_4b, R.drawable.cube_4h),
+  CUBE_5 ( new int[] {5,5,5}      , 28, R.drawable.cube_5s, R.drawable.cube_5m, R.drawable.cube_5b, R.drawable.cube_5h),
+  CUBE_6 ( new int[] {6,6,6}      , 35, R.drawable.cube_6s, R.drawable.cube_6m, R.drawable.cube_6b, R.drawable.cube_6h),
+  DIAM_2 ( new int[] {2,2,2,2}    , 12, R.drawable.diam_2s, R.drawable.diam_2m, R.drawable.diam_2b, R.drawable.diam_2h),
+  DIAM_3 ( new int[] {3,3,3,3}    , 24, R.drawable.diam_3s, R.drawable.diam_3m, R.drawable.diam_3b, R.drawable.diam_3h),
+  DIAM_4 ( new int[] {4,4,4,4}    , 32, R.drawable.diam_4s, R.drawable.diam_4m, R.drawable.diam_4b, R.drawable.diam_4h),
+  JING_2 ( new int[] {2,2,2,2}    , 11, R.drawable.jing_2s, R.drawable.jing_2m, R.drawable.jing_2b, R.drawable.jing_2h),
+  PYRA_3 ( new int[] {3,3,3,3}    , 10, R.drawable.pyra_3s, R.drawable.pyra_3m, R.drawable.pyra_3b, R.drawable.pyra_3h),
+  PYRA_4 ( new int[] {4,4,4,4}    , 17, R.drawable.pyra_4s, R.drawable.pyra_4m, R.drawable.pyra_4b, R.drawable.pyra_4h),
+  PYRA_5 ( new int[] {5,5,5,5}    , 23, R.drawable.pyra_5s, R.drawable.pyra_5m, R.drawable.pyra_5b, R.drawable.pyra_5h),
+  KILO_3 ( new int[] {3,3,3,3,3,3}, 18, R.drawable.kilo_3s, R.drawable.kilo_3m, R.drawable.kilo_3b, R.drawable.kilo_3h),
+  KILO_5 ( new int[] {5,5,5,5,5,5}, 33, R.drawable.kilo_5s, R.drawable.kilo_5m, R.drawable.kilo_5b, R.drawable.kilo_5h),
+  MEGA_3 ( new int[] {3,3,3,3,3,3}, 21, R.drawable.mega_3s, R.drawable.mega_3m, R.drawable.mega_3b, R.drawable.mega_3h),
+  MEGA_5 ( new int[] {5,5,5,5,5,5}, 37, R.drawable.mega_5s, R.drawable.mega_5m, R.drawable.mega_5b, R.drawable.mega_5h),
+  ULTI_2 ( new int[] {2,2,2,2}    , 18, R.drawable.ulti_2s, R.drawable.ulti_2m, R.drawable.ulti_2b, R.drawable.ulti_2h),
+  DINO_3 ( new int[] {3,3,3,3}    , 10, R.drawable.dino_3s, R.drawable.dino_3m, R.drawable.dino_3b, R.drawable.dino_3h),
+  DIN4_3 ( new int[] {3,3,3,3}    ,  7, R.drawable.din4_3s, R.drawable.din4_3m, R.drawable.din4_3b, R.drawable.din4_3h),
+  REDI_3 ( new int[] {3,3,3,3}    , 16, R.drawable.redi_3s, R.drawable.redi_3m, R.drawable.redi_3b, R.drawable.redi_3h),
+  SKEW_2 ( new int[] {2,2,2,2}    , 11, R.drawable.skew_2s, R.drawable.skew_2m, R.drawable.skew_2b, R.drawable.skew_2h),
+  SKEW_3 ( new int[] {3,3,3,3}    , 21, R.drawable.skew_3s, R.drawable.skew_3m, R.drawable.skew_3b, R.drawable.skew_3h),
+  IVY_2  ( new int[] {2,2,2,2}    ,  8, R.drawable.ivy_2s , R.drawable.ivy_2m , R.drawable.ivy_2b , R.drawable.ivy_2h ),
+  REX_3  ( new int[] {3,3,3,3}    , 19, R.drawable.rex_3s , R.drawable.rex_3m , R.drawable.rex_3b , R.drawable.rex_3h ),
+  BAN1_3 ( new int[] {3,3,3}      , 16, R.drawable.ban1_3s, R.drawable.ban1_3m, R.drawable.ban1_3b, R.drawable.ban1_3h),
+  BAN2_3 ( new int[] {3,3,3}      , 16, R.drawable.ban2_3s, R.drawable.ban2_3m, R.drawable.ban2_3b, R.drawable.ban2_3h),
+  BAN3_3 ( new int[] {3,3,3}      , 16, R.drawable.ban3_3s, R.drawable.ban3_3m, R.drawable.ban3_3b, R.drawable.ban3_3h),
+  BAN4_3 ( new int[] {3,3,3}      , 16, R.drawable.ban4_3s, R.drawable.ban4_3m, R.drawable.ban4_3b, R.drawable.ban4_3h),
+  SQU1_3 ( new int[] {3,2,3}      , 24, R.drawable.squ1_3s, R.drawable.squ1_3m, R.drawable.squ1_3b, R.drawable.squ1_3h),
+  SQU2_3 ( new int[] {3,2,3}      , 24, R.drawable.squ2_3s, R.drawable.squ2_3m, R.drawable.squ2_3b, R.drawable.squ2_3h),
+  MIRR_2 ( new int[] {2,2,2}      , 12, R.drawable.mirr_2s, R.drawable.mirr_2m, R.drawable.mirr_2b, R.drawable.mirr_2h),
+  MIRR_3 ( new int[] {3,3,3}      , 17, R.drawable.mirr_3s, R.drawable.mirr_3m, R.drawable.mirr_3b, R.drawable.mirr_3h),
+  CU_323 ( new int[] {3,2,3}      , 15, R.drawable.cu_323s, R.drawable.cu_323m, R.drawable.cu_323b, R.drawable.cu_323h),
+  CU_232 ( new int[] {2,3,2}      , 16, R.drawable.cu_232s, R.drawable.cu_232m, R.drawable.cu_232b, R.drawable.cu_232h),
+  CU_343 ( new int[] {3,4,3}      , 23, R.drawable.cu_343s, R.drawable.cu_343m, R.drawable.cu_343b, R.drawable.cu_343h),
+  HELI_3 ( new int[] {3,3,3,3,3,3}, 20, R.drawable.heli_3s, R.drawable.heli_3m, R.drawable.heli_3b, R.drawable.heli_3h),
   ;
 
   public static final int NUM_OBJECTS = values().length;
+  private static final ObjectType[] objects;
 
   private final int[] mNumLayers;
   private final int mNumScrambles;
   private final int mSmallIcon, mMediumIcon, mBigIcon, mHugeIcon;
-  private final int mMeshID, mJsonID;
-
-  private static final ObjectType[] objects;
 
   static
     {
@@ -106,25 +104,16 @@ public enum ObjectType
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  ObjectType(int[] numLayers, int scrambles, int jsonID, int meshID, int sIcon, int mIcon, int bIcon, int hIcon)
+  ObjectType(int[] numLayers, int scrambles, int sIcon, int mIcon, int bIcon, int hIcon)
     {
     mNumLayers   = numLayers;
     mNumScrambles= scrambles;
-    mJsonID      = jsonID;
-    mMeshID      = meshID;
     mSmallIcon   = sIcon;
     mMediumIcon  = mIcon;
     mBigIcon     = bIcon;
     mHugeIcon    = hIcon;
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int getNumScramble()
-    {
-    return mNumScrambles;
-    }
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getIconID(int size)
@@ -142,63 +131,55 @@ public enum ObjectType
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int getMeshID()
-    {
-    return mMeshID;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int getJsonID()
+  public int getNumScramble()
     {
-    return mJsonID;
+    return mNumScrambles;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public TwistyObject create(Static4D quat, Static3D move, InputStream stream)
+  public static TwistyObject create(int ordinal, Static4D quat, Static3D move, InputStream meshStream)
     {
-    int ord = ordinal();
-    int[] numL= objects[ord].mNumLayers;
+    int[] numL= objects[ordinal].mNumLayers;
 
-    switch(ord)
+    switch(ordinal)
       {
       case  0:
       case  1:
       case  2:
       case  3:
-      case  4: return new TwistyCuboid        (numL, quat, move, stream);
+      case  4: return new TwistyCuboid        (numL, quat, move, meshStream);
       case  5:
       case  6:
-      case  7: return new TwistyDiamond       (numL, quat, move, stream);
-      case  8: return new TwistyJing          (numL, quat, move, stream);
+      case  7: return new TwistyDiamond       (numL, quat, move, meshStream);
+      case  8: return new TwistyJing          (numL, quat, move, meshStream);
       case  9:
       case 10:
-      case 11: return new TwistyPyraminx      (numL, quat, move, stream);
+      case 11: return new TwistyPyraminx      (numL, quat, move, meshStream);
       case 12:
-      case 13: return new TwistyKilominx      (numL, quat, move, stream);
+      case 13: return new TwistyKilominx      (numL, quat, move, meshStream);
       case 14:
-      case 15: return new TwistyMegaminx      (numL, quat, move, stream);
-      case 16: return new TwistyUltimate      (numL, quat, move, stream);
-      case 17: return new TwistyDino6         (numL, quat, move, stream);
-      case 18: return new TwistyDino4         (numL, quat, move, stream);
-      case 19: return new TwistyRedi          (numL, quat, move, stream);
+      case 15: return new TwistyMegaminx      (numL, quat, move, meshStream);
+      case 16: return new TwistyUltimate      (numL, quat, move, meshStream);
+      case 17: return new TwistyDino6         (numL, quat, move, meshStream);
+      case 18: return new TwistyDino4         (numL, quat, move, meshStream);
+      case 19: return new TwistyRedi          (numL, quat, move, meshStream);
       case 20:
-      case 21: return new TwistySkewb         (numL, quat, move, stream);
-      case 22: return new TwistyIvy           (numL, quat, move, stream);
-      case 23: return new TwistyRex           (numL, quat, move, stream);
-      case 24: return new TwistyBandagedFused (numL, quat, move, stream);
-      case 25: return new TwistyBandaged2Bar  (numL, quat, move, stream);
-      case 26: return new TwistyBandaged3Plate(numL, quat, move, stream);
-      case 27: return new TwistyBandagedEvil  (numL, quat, move, stream);
-      case 28: return new TwistySquare1       (numL, quat, move, stream);
-      case 29: return new TwistySquare2       (numL, quat, move, stream);
+      case 21: return new TwistySkewb         (numL, quat, move, meshStream);
+      case 22: return new TwistyIvy           (numL, quat, move, meshStream);
+      case 23: return new TwistyRex           (numL, quat, move, meshStream);
+      case 24: return new TwistyBandagedFused (numL, quat, move, meshStream);
+      case 25: return new TwistyBandaged2Bar  (numL, quat, move, meshStream);
+      case 26: return new TwistyBandaged3Plate(numL, quat, move, meshStream);
+      case 27: return new TwistyBandagedEvil  (numL, quat, move, meshStream);
+      case 28: return new TwistySquare1       (numL, quat, move, meshStream);
+      case 29: return new TwistySquare2       (numL, quat, move, meshStream);
       case 30:
-      case 31: return new TwistyMirror        (numL, quat, move, stream);
+      case 31: return new TwistyMirror        (numL, quat, move, meshStream);
       case 32:
       case 33:
-      case 34: return new TwistyCuboid        (numL, quat, move, stream);
-      case 35: return new TwistyHelicopter    (numL, quat, move, stream);
+      case 34: return new TwistyCuboid        (numL, quat, move, meshStream);
+      case 35: return new TwistyHelicopter    (numL, quat, move, meshStream);
       }
 
     return null;
diff --git a/src/main/java/org/distorted/objectlib/main/TwistyJson.java b/src/main/java/org/distorted/objectlib/main/TwistyJson.java
index 6851f08f..fcfd9eed 100644
--- a/src/main/java/org/distorted/objectlib/main/TwistyJson.java
+++ b/src/main/java/org/distorted/objectlib/main/TwistyJson.java
@@ -266,6 +266,13 @@ public class TwistyJson extends TwistyObject
     return mReader.getColor(face);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public String getShortName()
+    {
+    return mReader.getShortName();
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public int getFOV()
diff --git a/src/main/java/org/distorted/objectlib/main/TwistyObject.java b/src/main/java/org/distorted/objectlib/main/TwistyObject.java
index 5bc3669f..d12fdfe9 100644
--- a/src/main/java/org/distorted/objectlib/main/TwistyObject.java
+++ b/src/main/java/org/distorted/objectlib/main/TwistyObject.java
@@ -146,7 +146,7 @@ public abstract class TwistyObject
 
   TwistyObject(InputStream jsonStream, Static4D quat, Static3D move, InputStream meshStream)
     {
-    JsonReader reader = JsonReader.getInstance();
+    JsonReader reader = new JsonReader();
     reader.parseJsonFile(jsonStream);
     setReader(reader);
 
@@ -1335,6 +1335,13 @@ public abstract class TwistyObject
     return mMovement;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public String getShortName()
+    {
+    return getObjectType().name();
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   protected void setReader(JsonReader reader)
