commit 9361b337a158d4730c991d2bb5fb74265dc879f9
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Fri Jun 3 16:38:07 2016 +0100

    Provide support to add any class derived from DistortedObject to DistortedNode.

diff --git a/src/main/java/org/distorted/library/DistortedBitmap.java b/src/main/java/org/distorted/library/DistortedBitmap.java
index 41d0ba0..ba27713 100644
--- a/src/main/java/org/distorted/library/DistortedBitmap.java
+++ b/src/main/java/org/distorted/library/DistortedBitmap.java
@@ -78,46 +78,20 @@ public class DistortedBitmap extends DistortedObject
      this(bmp.getWidth(), bmp.getHeight(), gridSize); 
      setBitmap(bmp);
      }
-   
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
- * Copy constructor used to create a DistortedBitmap based on various parts of another Bitmap.
+ * Copy constructor used to create a DistortedBitmap based on various parts of another object.
  * <p>
  * Whatever we do not clone gets created just like in the default constructor.
- *    
- * @param db    Source DistortedBitmap to create our object from
+ *
+ * @param db    Source object to create our object from
  * @param flags A bitmask of values specifying what to copy.
  *              For example, CLONE_BITMAP | CLONE_MATRIX.
  */
    public DistortedBitmap(DistortedBitmap db, int flags)
      {
-     initializeEffectLists(db,flags);  
-      
-     mID = DistortedObjectList.add(this);
-        
-     mSizeX = db.mSizeX;
-     mSizeY = db.mSizeY;
-     mSizeZ = db.mSizeZ;
-     mSize  = db.mSize;
-     mGrid  = db.mGrid;
-       
-     if( (flags & Distorted.CLONE_BITMAP) != 0 ) 
-       {
-       mTextureDataH = db.mTextureDataH;
- 	    mBmp          = db.mBmp;
- 	    mBitmapSet    = db.mBitmapSet;
- 	    }
-     else
-       {
-       mTextureDataH   = new int[1];
-       mTextureDataH[0]= 0;
-       mBitmapSet      = new boolean[1];
-       mBitmapSet[0]   = false;
-       mBmp            = new Bitmap[1];
-       mBmp[0]         = null;
-       
-       if( Distorted.isInitialized() ) resetTexture();
-       }
+     super(db,flags);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/DistortedCubes.java b/src/main/java/org/distorted/library/DistortedCubes.java
index 62c82ac..66469df 100644
--- a/src/main/java/org/distorted/library/DistortedCubes.java
+++ b/src/main/java/org/distorted/library/DistortedCubes.java
@@ -1,10 +1,8 @@
 package org.distorted.library;
 
-import android.graphics.Bitmap;
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
- * Instance of this class represents a connected, flat set of cubes optionally textured as a whole.
+ * Instance of this class represents a flat set of cubes optionally textured as a whole.
  * (a subset of a NxMx1 cuboid build with 1x1x1 cubes, i.e. the MxNx1 cuboid with arbitrary cubes missing)
  * <p>
  * General idea is as follows:
@@ -30,109 +28,82 @@ public class DistortedCubes extends DistortedObject
    
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // PUBLIC API
-/////////////////////////////////////////////////////////////////////////////////////////////////// 
- 
+///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
  * Creates internal memory representation of a cuboid subset.
- * 
+ *
  * @param cols Integer helping to parse the next parameter.
  * @param desc String describing the subset of a MxNx1 cuboid that we want to create.
  *             Its MxN characters - all 0 or 1 - decide of appropriate field is taken or not.
- *             
+ *
  *             For example, (cols=2, desc="111010") describes the following shape:
- *             
+ *
  *             XX
  *             X
  *             X
- *             
+ *
  *             whereas (cols=2,desc="110001") describes
- *             
+ *
  *             XX
- *              
+ *
  *              X
- *              
+ *
  * @param gridSize size, in pixels, of the single 1x1x1 cube our cuboid is built from
- *  
- */   
-   public DistortedCubes(int cols, String desc, int gridSize) 
-     {
-     this(cols,desc,gridSize,false);
-     }
-
-/**
  * @param frontOnly Only create the front wall or side and back as well?
  */
-   
-   public DistortedCubes(int cols, String desc, int gridSize, boolean frontOnly) 
-     {
-     int Rs = 0;
-     int Cs = 0;
+ public DistortedCubes(int cols, String desc, int gridSize, boolean frontOnly)
+   {
+   int Rs = 0;
+   int Cs = 0;
      
-     if( cols>0 )
-       {
-       int reallen = desc.length();
-       int len = reallen;
+   if( cols>0 )
+     {
+     int reallen = desc.length();
+     int len = reallen;
 
-       if( (reallen/cols)*cols != reallen )
-         {
-         len = ((reallen/cols)+1)*cols; 
-         for(int i=reallen; i<len; i++) desc += "0";
-         }
+     if( (reallen/cols)*cols != reallen )
+       {
+       len = ((reallen/cols)+1)*cols;
+       for(int i=reallen; i<len; i++) desc += "0";
+       }
     
-       if( desc.indexOf("1")>=0 )
-         {
-         Cs = cols;
-         Rs = len/cols;
-         }
+     if( desc.indexOf("1")>=0 )
+       {
+       Cs = cols;
+       Rs = len/cols;
        }
-     
-     mSizeX= gridSize*Cs;
-     mSizeY= gridSize*Rs;
-     mSizeZ= frontOnly ? 0 : gridSize;
-     mGrid = new GridCubes(cols,desc, frontOnly);
-     initializeData(gridSize);
      }
-   
+     
+   mSizeX= gridSize*Cs;
+   mSizeY= gridSize*Rs;
+   mSizeZ= frontOnly ? 0 : gridSize;
+   mGrid = new GridCubes(cols,desc, frontOnly);
+   initializeData(gridSize);
+   }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Convenience constructor
+ */
+ public DistortedCubes(int cols, String desc, int gridSize)
+   {
+   this(cols,desc,gridSize,false);
+   }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
  * Copy constructor used to create a DistortedCubes based on various parts of another object.
  * <p>
  * Whatever we do not clone gets created just like in the default constructor.
- *    
+ *
  * @param dc    Source object to create our object from
  * @param flags A bitmask of values specifying what to copy.
  *              For example, CLONE_BITMAP | CLONE_MATRIX.
  */
-   public DistortedCubes(DistortedCubes dc, int flags)
-     {
-     initializeEffectLists(dc,flags);  
-      
-     mID = DistortedObjectList.add(this);
-        
-     mSizeX = dc.mSizeX;
-     mSizeY = dc.mSizeY;
-     mSizeZ = dc.mSizeZ;
-     mSize  = dc.mSize;
-     mGrid  = dc.mGrid;
-       
-     if( (flags & Distorted.CLONE_BITMAP) != 0 ) 
-       {
-       mTextureDataH = dc.mTextureDataH;
-       mBmp          = dc.mBmp;
-       mBitmapSet    = dc.mBitmapSet;
-       }
-     else
-       {
-       mTextureDataH   = new int[1];
-       mTextureDataH[0]= 0;
-       mBitmapSet      = new boolean[1];
-       mBitmapSet[0]   = false;
-       mBmp            = new Bitmap[1];
-       mBmp[0]         = null;
-       
-       if( Distorted.isInitialized() ) resetTexture(); 
-       }
-     }
+ public DistortedCubes(DistortedCubes dc, int flags)
+   {
+   super(dc,flags);
+   }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////   
-   }
+ }
diff --git a/src/main/java/org/distorted/library/DistortedNode.java b/src/main/java/org/distorted/library/DistortedNode.java
index 2a3f5c3..bfec658 100644
--- a/src/main/java/org/distorted/library/DistortedNode.java
+++ b/src/main/java/org/distorted/library/DistortedNode.java
@@ -18,14 +18,14 @@ public class DistortedNode
   private static final int TEXTURE_FAILED_TO_CREATE = -1;   
   private static final int TEXTURE_NOT_CREATED_YET  = -2;   
    
-  private DistortedBitmap mBitmap;
+  private DistortedObject mObject;
   private NodeData mData;
   
   private DistortedNode mParent;
   private ArrayList<DistortedNode> mChildren;
   private int[] mNumChildren;  // ==mChildren.length(), but we only create mChildren if the first one gets added
   
-  private static HashMap<ArrayList<Long>,NodeData> mMapNodeID = new HashMap<ArrayList<Long>,NodeData>();
+  private static HashMap<ArrayList<Long>,NodeData> mMapNodeID = new HashMap<>();
   private static long mNextNodeID =0;
 
   //////////////////////////////////////////////////////////////////
@@ -124,7 +124,7 @@ public class DistortedNode
     {
     if( mNumChildren[0]<=0 )
       {
-      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBitmap.mTextureDataH[0]); 
+      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mObject.mTextureDataH[0]);
       
       if( mData.mProjection!=null )
         {
@@ -144,10 +144,10 @@ public class DistortedNode
         GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
         GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
       
-        if( mBitmap.mBitmapSet[0] )
+        if( mObject.mBitmapSet[0] )
           {
-          GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBitmap.mTextureDataH[0]);        
-          mBitmap.drawNoEffectsPriv(mData.mProjection);
+          GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mObject.mTextureDataH[0]);
+          mObject.drawNoEffectsPriv(mData.mProjection);
           }
       
         synchronized(this)
@@ -163,7 +163,7 @@ public class DistortedNode
       GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mData.mTextureID);   // this is safe because we must have called createFBO() above before.     
       }
     
-    mBitmap.drawPriv(currTime, dp);
+    mObject.drawPriv(currTime, dp);
     }
   
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -189,9 +189,9 @@ public class DistortedNode
 
   private ArrayList<Long> generateIDList()
     {
-    ArrayList<Long> ret = new ArrayList<Long>();
+    ArrayList<Long> ret = new ArrayList<>();
      
-    ret.add( mNumChildren[0]>0 ? mBitmap.getBitmapID() : mBitmap.getID() );
+    ret.add( mNumChildren[0]>0 ? mObject.getBitmapID() : mObject.getID() );
     DistortedNode node;
    
     for(int i=0; i<mNumChildren[0]; i++)
@@ -220,7 +220,7 @@ public class DistortedNode
       if( newList.size()>1 && mData.mProjection==null )
         {     
         mData.mProjection = new DistortedProjection(true);
-        mData.mProjection.onSurfaceChanged(mBitmap.getWidth(), mBitmap.getHeight());
+        mData.mProjection.onSurfaceChanged(mObject.getWidth(), mObject.getHeight());
         mData.mFramebufferID = 0;
         mData.mTextureID = TEXTURE_NOT_CREATED_YET;
         }
@@ -260,18 +260,18 @@ public class DistortedNode
 /**
  * Constructs new Node of the Tree.
  *     
- * @param bmp DistortedBitmap to put into the new Node.
+ * @param obj DistortedObject to put into the new Node.
  */
-  public DistortedNode(DistortedBitmap bmp)
+  public DistortedNode(DistortedObject obj)
     {
-    mBitmap = bmp;
+    mObject = obj;
     mParent = null;
     mChildren = null;
     mNumChildren = new int[1];
     mNumChildren[0] = 0;
    
-    ArrayList<Long> list = new ArrayList<Long>();
-    list.add(bmp.getID());
+    ArrayList<Long> list = new ArrayList<>();
+    list.add(obj.getID());
       
     mData = mMapNodeID.get(list);
    
@@ -298,10 +298,14 @@ public class DistortedNode
  */
   public DistortedNode(DistortedNode node, int flags)
     {
-    mParent = null;  
-    mBitmap = new DistortedBitmap(node.mBitmap, flags);  
-   
-    if( (flags & Distorted.CLONE_CHILDREN) != 0 ) 
+    mParent = null;
+
+    if( node.mObject instanceof DistortedBitmap)
+      mObject = new DistortedBitmap( (DistortedBitmap)node.mObject, flags);
+    else if( node.mObject instanceof DistortedCubes)
+      mObject = new DistortedCubes( (DistortedCubes)node.mObject, flags);
+
+    if( (flags & Distorted.CLONE_CHILDREN) != 0 )
       {
       mChildren = node.mChildren;
       mNumChildren = node.mNumChildren;
@@ -338,7 +342,7 @@ public class DistortedNode
     {
     ArrayList<Long> prev = generateIDList(); 
    
-    if( mChildren==null ) mChildren = new ArrayList<DistortedNode>(2);
+    if( mChildren==null ) mChildren = new ArrayList<>(2);
      
     node.mParent = this;
     mChildren.add(node);
@@ -358,7 +362,7 @@ public class DistortedNode
     {
     ArrayList<Long> prev = generateIDList(); 
       
-    if( mChildren==null ) mChildren = new ArrayList<DistortedNode>(2);  
+    if( mChildren==null ) mChildren = new ArrayList<>(2);
     DistortedNode node = new DistortedNode(bmp);
     node.mParent = this;
     mChildren.add(node);
@@ -400,19 +404,19 @@ public class DistortedNode
 /**
  * Removes the first occurrence of a specified child from the list of children of our Node.
  * 
- * @param bmp The DistortedBitmap to remove.
+ * @param obj DistortedObject to remove.
  * @return <code>true</code> if the child was successfully removed.
  */
-  public synchronized boolean detach(DistortedBitmap bmp)
+  public synchronized boolean detach(DistortedObject obj)
     {
-    long id = bmp.getID();
+    long id = obj.getID();
     DistortedNode node;
    
     for(int i=0; i<mNumChildren[0]; i++)
       {
       node = mChildren.get(i);
      
-      if( node.mBitmap.getID()==id )
+      if( node.mObject.getID()==id )
         {
         ArrayList<Long> prev = generateIDList();   
      
@@ -468,13 +472,13 @@ public class DistortedNode
  
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
- * Returns the DistortedBitmap object that's in the Node.
+ * Returns the DistortedObject object that's in the Node.
  * 
- * @return The DistortedBitmap contained in the Node.
+ * @return The DistortedObject contained in the Node.
  */
-  public DistortedBitmap getBitmap()
+  public DistortedObject getObject()
     {
-    return mBitmap;  
+    return mObject;
     }
   
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/DistortedObject.java b/src/main/java/org/distorted/library/DistortedObject.java
index 1f440d8..44ba10f 100644
--- a/src/main/java/org/distorted/library/DistortedObject.java
+++ b/src/main/java/org/distorted/library/DistortedObject.java
@@ -27,7 +27,58 @@ public abstract class DistortedObject
     protected Bitmap[] mBmp= null; // 
     int[] mTextureDataH;           // have to be shared among all the cloned Objects
     boolean[] mBitmapSet;          // 
- 
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * Default empty constructor so that derived classes can call it
+   */
+    public DistortedObject()
+      {
+
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+  /**
+   * Copy constructor used to create a DistortedObject based on various parts of another object.
+   * <p>
+   * Whatever we do not clone gets created just like in the default constructor.
+   *
+   * @param dc    Source object to create our object from
+   * @param flags A bitmask of values specifying what to copy.
+   *              For example, CLONE_BITMAP | CLONE_MATRIX.
+   */
+    public DistortedObject(DistortedObject dc, int flags)
+      {
+      initializeEffectLists(dc,flags);
+
+      mID = DistortedObjectList.add(this);
+
+      mSizeX = dc.mSizeX;
+      mSizeY = dc.mSizeY;
+      mSizeZ = dc.mSizeZ;
+      mSize  = dc.mSize;
+      mGrid  = dc.mGrid;
+
+      if( (flags & Distorted.CLONE_BITMAP) != 0 )
+        {
+        mTextureDataH = dc.mTextureDataH;
+        mBmp          = dc.mBmp;
+        mBitmapSet    = dc.mBitmapSet;
+        }
+      else
+        {
+        mTextureDataH   = new int[1];
+        mTextureDataH[0]= 0;
+        mBitmapSet      = new boolean[1];
+        mBitmapSet[0]   = false;
+        mBmp            = new Bitmap[1];
+        mBmp[0]         = null;
+
+        if( Distorted.isInitialized() ) resetTexture();
+        }
+      }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     protected void initializeData(int size)
diff --git a/src/main/java/org/distorted/library/DistortedObjectList.java b/src/main/java/org/distorted/library/DistortedObjectList.java
index ad9d02b..d0eae7a 100644
--- a/src/main/java/org/distorted/library/DistortedObjectList.java
+++ b/src/main/java/org/distorted/library/DistortedObjectList.java
@@ -10,7 +10,7 @@ import java.util.HashMap;
 final class DistortedObjectList 
   {
   private static long id =0;  
-  private static HashMap<Long,DistortedObject> mBitmaps = new HashMap<Long,DistortedObject>();
+  private static HashMap<Long,DistortedObject> mBitmaps = new HashMap<>();
   
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
