commit 51f51f8319cb507a3c87cb70e56aeef6c596f988
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Fri May 7 00:19:48 2021 +0200

    Progress with RubikControl.

diff --git a/src/main/java/org/distorted/control/RubikControl.java b/src/main/java/org/distorted/control/RubikControl.java
index e9b9f7bd..fcbad39d 100644
--- a/src/main/java/org/distorted/control/RubikControl.java
+++ b/src/main/java/org/distorted/control/RubikControl.java
@@ -19,79 +19,89 @@
 
 package org.distorted.control;
 
+import org.distorted.library.main.DistortedNode;
 import org.distorted.library.message.EffectListener;
 import org.distorted.main.RubikActivity;
+import org.distorted.main.RubikPreRender;
+import org.distorted.objects.TwistyObject;
 
 import java.lang.ref.WeakReference;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-public class RubikControl implements EffectListener, Runnable
+public class RubikControl implements EffectListener
   {
   WeakReference<RubikActivity> mRefAct;
-  long mWholeID, mRotateID;
   boolean mWholeReturned, mRotateReturned;
 
-long mRetID;
+  RubikControlWhole mWhole;
+  RubikControlRotate mRotate;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void addWholeObjects()
+  private TwistyObject getObject()
     {
-    mWholeID = 0;
+    RubikActivity act = mRefAct.get();
 
-    mRetID = mWholeID;
+    if( act!=null )
+      {
+      RubikPreRender pre = act.getPreRender();
+      return pre!=null ? pre.getObject() : null;
+      }
 
-    Thread networkThrd = new Thread(this);
-    networkThrd.start();
+    return null;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void addWholeEffects()
+  private void addWholeObjects()
     {
+    TwistyObject object = getObject();
+    DistortedNode[] nodes = mWhole.getNodes();
 
+    if( object!=null && nodes!=null )
+      {
+      for (DistortedNode node : nodes) object.attach(node);
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void removeWholeObjects()
     {
+    TwistyObject object = getObject();
+    DistortedNode[] nodes = mWhole.returnNodes();
 
+    if( object!=null && nodes!=null )
+      {
+      for (DistortedNode node : nodes) object.detach(node);
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void addRotateObjects()
     {
-    mRotateID = 1;
-
-    mRetID = mRotateID;
-
-    Thread networkThrd = new Thread(this);
-    networkThrd.start();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void addRotateEffects()
-    {
+    TwistyObject object = getObject();
+    DistortedNode[] nodes = mRotate.getNodes();
 
+    if( object!=null && nodes!=null )
+      {
+      for (DistortedNode node : nodes) object.attach(node);
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void removeRotateObjects()
     {
+    TwistyObject object = getObject();
+    DistortedNode[] nodes = mRotate.returnNodes();
 
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void animateCubeWhole()
-    {
-    addWholeObjects();
-    addWholeEffects();
+    if( object!=null && nodes!=null )
+      {
+      for (DistortedNode node : nodes) object.detach(node);
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -102,15 +112,7 @@ long mRetID;
 
     mWholeReturned = true;
 
-    if( !mRotateReturned ) animateCubeRotate();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void animateCubeRotate()
-    {
-    addRotateObjects();
-    addRotateEffects();
+    if( !mRotateReturned ) addRotateObjects();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -126,33 +128,27 @@ long mRetID;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC
 
-  @Override
-  public void run()
+  RubikActivity getActivity()
     {
-    android.util.Log.e("D", "running...");
-
-    try
-      {
-      Thread.sleep(4000);
-      }
-    catch(InterruptedException ex)
-      {
-      // ignore
-      }
+    return mRefAct.get();
+    }
 
-    android.util.Log.e("D", "end running...");
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC
 
-    effectFinished(mRetID);
+  public RubikControl()
+    {
+    mWhole = new RubikControlWhole(this);
+    mRotate= new RubikControlRotate(this);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void effectFinished(long effectID)
     {
-    if( effectID==mWholeID  ) finishWhole();
-    if( effectID==mRotateID ) finishRotate();
+    if( effectID==mWhole.getEffectID()  ) finishWhole();
+    if( effectID==mRotate.getEffectID() ) finishRotate();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -165,7 +161,7 @@ long mRetID;
     mWholeReturned = false;
     mRotateReturned= false;
 
-    animateCubeWhole();
+    addWholeObjects();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -178,6 +174,6 @@ long mRetID;
     mWholeReturned = true;
     mRotateReturned= false;
 
-    animateCubeRotate();
+    addRotateObjects();
     }
   }
diff --git a/src/main/java/org/distorted/control/RubikControlRotate.java b/src/main/java/org/distorted/control/RubikControlRotate.java
new file mode 100644
index 00000000..389ae399
--- /dev/null
+++ b/src/main/java/org/distorted/control/RubikControlRotate.java
@@ -0,0 +1,120 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2021 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.control;
+
+import org.distorted.library.effect.MatrixEffectScale;
+import org.distorted.library.main.DistortedEffects;
+import org.distorted.library.main.DistortedNode;
+import org.distorted.library.main.DistortedTexture;
+import org.distorted.library.mesh.MeshQuad;
+import org.distorted.library.type.Dynamic;
+import org.distorted.library.type.Dynamic3D;
+import org.distorted.library.type.Static3D;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class RubikControlRotate
+  {
+  private static final int NUM_NODE = 1;
+
+  private final RubikControl mControl;
+  private DistortedEffects[] mEffects;
+  private DistortedNode[] mNodes;
+  private long mEffectID;
+
+  private Dynamic3D mDynamic;
+  private MatrixEffectScale mScale;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void createEffects()
+    {
+    if( mEffects==null )
+      {
+      mEffects   = new DistortedEffects[NUM_NODE];
+      mEffects[0]= new DistortedEffects();
+
+      Static3D scaleStart= new Static3D(1,1,1);
+      Static3D scaleEnd  = new Static3D(1000,1000,1000);
+
+      mDynamic = new Dynamic3D(10000,0.5f);
+      mDynamic.add(scaleStart);
+      mDynamic.add(scaleEnd  );
+      mDynamic.add(scaleStart);
+      mDynamic.setMode(Dynamic.MODE_PATH);
+
+      mScale = new MatrixEffectScale(mDynamic);
+      mScale.notifyWhenFinished(mControl);
+      mEffectID = mScale.getID();
+      mEffects[0].apply(mScale);
+      }
+    else
+      {
+      mDynamic.resetToBeginning();
+      mScale.notifyWhenFinished(mControl);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void createNodes()
+    {
+    if( mNodes==null )
+      {
+      mNodes = new DistortedNode[NUM_NODE];
+      MeshQuad mesh = new MeshQuad();
+      DistortedTexture texture = new DistortedTexture();
+      texture.setColorARGB(0xff00ff00);
+
+      mNodes[0]= new DistortedNode(texture,mEffects[0],mesh);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  long getEffectID()
+    {
+    return mEffectID;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  DistortedNode[] getNodes()
+    {
+    createEffects();
+    createNodes();
+
+    return mNodes;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  DistortedNode[] returnNodes()
+    {
+    return mNodes;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  RubikControlRotate(RubikControl control)
+    {
+    mControl = control;
+    }
+  }
diff --git a/src/main/java/org/distorted/control/RubikControlWhole.java b/src/main/java/org/distorted/control/RubikControlWhole.java
new file mode 100644
index 00000000..e9b6f546
--- /dev/null
+++ b/src/main/java/org/distorted/control/RubikControlWhole.java
@@ -0,0 +1,120 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2021 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.control;
+
+import org.distorted.library.effect.MatrixEffectScale;
+import org.distorted.library.main.DistortedEffects;
+import org.distorted.library.main.DistortedNode;
+import org.distorted.library.main.DistortedTexture;
+import org.distorted.library.mesh.MeshQuad;
+import org.distorted.library.type.Dynamic;
+import org.distorted.library.type.Dynamic3D;
+import org.distorted.library.type.Static3D;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class RubikControlWhole
+  {
+  private static final int NUM_NODE = 1;
+
+  private final RubikControl mControl;
+  private DistortedEffects[] mEffects;
+  private DistortedNode[] mNodes;
+  private long mEffectID;
+
+  private Dynamic3D mDynamic;
+  private MatrixEffectScale mScale;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void createEffects()
+    {
+    if( mEffects==null )
+      {
+      mEffects   = new DistortedEffects[NUM_NODE];
+      mEffects[0]= new DistortedEffects();
+
+      Static3D scaleStart= new Static3D(1,1,1);
+      Static3D scaleEnd  = new Static3D(1000,1000,1000);
+
+      mDynamic = new Dynamic3D(10000,0.5f);
+      mDynamic.add(scaleStart);
+      mDynamic.add(scaleEnd  );
+      mDynamic.add(scaleStart);
+      mDynamic.setMode(Dynamic.MODE_PATH);
+
+      mScale = new MatrixEffectScale(mDynamic);
+      mScale.notifyWhenFinished(mControl);
+      mEffectID = mScale.getID();
+      mEffects[0].apply(mScale);
+      }
+    else
+      {
+      mDynamic.resetToBeginning();
+      mScale.notifyWhenFinished(mControl);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void createNodes()
+    {
+    if( mNodes==null )
+      {
+      mNodes = new DistortedNode[NUM_NODE];
+      MeshQuad mesh = new MeshQuad();
+      DistortedTexture texture = new DistortedTexture();
+      texture.setColorARGB(0xffff0000);
+
+      mNodes[0]= new DistortedNode(texture,mEffects[0],mesh);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  long getEffectID()
+    {
+    return mEffectID;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  DistortedNode[] getNodes()
+    {
+    createEffects();
+    createNodes();
+
+    return mNodes;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  DistortedNode[] returnNodes()
+    {
+    return mNodes;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  RubikControlWhole(RubikControl control)
+    {
+    mControl = control;
+    }
+  }
