commit a62aa9d7d063e454b75201df2bb9fc7737c4015b
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed Dec 11 13:44:54 2019 +0000

    Progress with ScrambleEffects

diff --git a/src/main/java/org/distorted/effect/ScrambleEffect.java b/src/main/java/org/distorted/effect/ScrambleEffect.java
index 5ab79ee1..e46fe479 100644
--- a/src/main/java/org/distorted/effect/ScrambleEffect.java
+++ b/src/main/java/org/distorted/effect/ScrambleEffect.java
@@ -34,6 +34,7 @@ public abstract class ScrambleEffect implements EffectListener
   public enum Type
     {
     NONE         (ScrambleEffectNone.class        ),
+    ROTATIONS    (ScrambleEffectRotations.class   ),
     ;
 
     final Class<? extends ScrambleEffect> effect;
@@ -45,7 +46,6 @@ public abstract class ScrambleEffect implements EffectListener
     }
 
   private static int NUM_EFFECTS = Type.values().length;
-  private static final int NUM_PHASES  = 2;
   private static final int FAKE_EFFECT_ID  = -3;
   private static final Type[] types;
 
@@ -62,29 +62,31 @@ public abstract class ScrambleEffect implements EffectListener
 
   private EffectListener mListener;
   private int mDuration;
-  private int mEffectReturned;
-  private int[] mCubeEffectNumber, mNodeEffectNumber;
-  private int mPhase;
+  private int[] mEffectReturned;
   private RubikCube mCube;
   private DistortedScreen mScreen;
 
+  static final int EFFECT_FLAVOUR_BASE  = 0;
+  static final int EFFECT_FLAVOUR_PLUGIN= 1;
+  static final int NUM_EFFECT_FLAVOURS  = 2;
+
   Effect[][] mNodeEffects;
   int[][] mNodeEffectPosition;
   Effect[][] mCubeEffects;
   int[][] mCubeEffectPosition;
+  int[] mCubeEffectNumber, mNodeEffectNumber;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   ScrambleEffect()
     {
-    mPhase = 0;
-
-    mCubeEffectNumber   = new int[NUM_PHASES];
-    mNodeEffectNumber   = new int[NUM_PHASES];
-    mCubeEffectPosition = new int[NUM_PHASES][];
-    mNodeEffectPosition = new int[NUM_PHASES][];
-    mCubeEffects        = new Effect[NUM_PHASES][];
-    mNodeEffects        = new Effect[NUM_PHASES][];
+    mEffectReturned     = new int[NUM_EFFECT_FLAVOURS];
+    mCubeEffectNumber   = new int[NUM_EFFECT_FLAVOURS];
+    mNodeEffectNumber   = new int[NUM_EFFECT_FLAVOURS];
+    mCubeEffectPosition = new int[NUM_EFFECT_FLAVOURS][];
+    mNodeEffectPosition = new int[NUM_EFFECT_FLAVOURS][];
+    mCubeEffects        = new Effect[NUM_EFFECT_FLAVOURS][];
+    mNodeEffects        = new Effect[NUM_EFFECT_FLAVOURS][];
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -117,53 +119,75 @@ public abstract class ScrambleEffect implements EffectListener
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  abstract void createEffectsPhase0(int duration);
-  abstract void createEffectsPhase1(int duration);
+  abstract void createEffects(int duration);
+  abstract void effectFinishedPlugin(final long effectID);
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void effectFinished(final long effectID)
+// TODO
+  private void createBaseEffects(int duration, int numScrambles)
     {
-    int total = mCubeEffectNumber[mPhase]+mNodeEffectNumber[mPhase];
+    mCubeEffectNumber[EFFECT_FLAVOUR_BASE] = 0;
+    mNodeEffectNumber[EFFECT_FLAVOUR_BASE] = 0;
+    }
 
-    for(int i=0; i<mCubeEffectNumber[mPhase]; i++)
-      {
-      long id = mCubeEffects[mPhase][i].getID();
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// TODO
 
-      if( effectID == id )
-        {
-        if( ++mEffectReturned == total ) effectAction(mPhase);
-        mCube.remove(id);
-        return;
-        }
-      }
-    for(int i=0; i<mNodeEffectNumber[mPhase]; i++)
-      {
-      long id = mNodeEffects[mPhase][i].getID();
+  private void effectFinishedBase(final long effectID)
+    {
 
-      if( effectID == id )
-        {
-        if( ++mEffectReturned == total ) effectAction(mPhase);
-        mCube.getEffects().abortById(id);
-        return;
-        }
-      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void effectAction(int phase)
+  public void effectFinished(final long effectID)
     {
-    switch(phase)
+    for(int flavour=0; flavour<NUM_EFFECT_FLAVOURS; flavour++)
       {
-      case 0: mEffectReturned = 0;
-              mPhase          = 1;
-              mCube.unscramble();
-              createEffectsPhase1(mDuration);
-              assignEffects(mPhase);
-              break;
-      case 1: mListener.effectFinished(FAKE_EFFECT_ID);
-              break;
+      for(int i=0; i<mCubeEffectNumber[flavour]; i++)
+        {
+        long id = mCubeEffects[flavour][i].getID();
+
+        if( effectID == id )
+          {
+          mEffectReturned[flavour]++;
+
+          switch(flavour)
+            {
+            case EFFECT_FLAVOUR_BASE  : effectFinishedBase(  effectID); break;
+            case EFFECT_FLAVOUR_PLUGIN: effectFinishedPlugin(effectID); break;
+            }
+
+          if( mEffectReturned[flavour] == mCubeEffectNumber[flavour]+mNodeEffectNumber[flavour] )
+            {
+            disassignEffects(flavour);
+            }
+
+          return;
+          }
+        }
+      for(int i=0; i<mNodeEffectNumber[flavour]; i++)
+        {
+        long id = mNodeEffects[flavour][i].getID();
+
+        if( effectID == id )
+          {
+          mEffectReturned[flavour]++;
+
+          switch(flavour)
+            {
+            case EFFECT_FLAVOUR_BASE  : effectFinishedBase(  effectID); break;
+            case EFFECT_FLAVOUR_PLUGIN: effectFinishedPlugin(effectID); break;
+            }
+
+          if( mEffectReturned[flavour] == mCubeEffectNumber[flavour]+mNodeEffectNumber[flavour] )
+            {
+            disassignEffects(flavour);
+            }
+
+          return;
+          }
+        }
       }
     }
 
@@ -176,36 +200,63 @@ public abstract class ScrambleEffect implements EffectListener
     mListener = listener;
     mDuration = duration;
 
-    createEffectsPhase0(mDuration);
-    assignEffects(mPhase);
+    createBaseEffects(mDuration, numScrambles);
+    assignEffects(EFFECT_FLAVOUR_BASE);
+
+    createEffects(mDuration);
+
+    if( mCubeEffectNumber[EFFECT_FLAVOUR_PLUGIN]==0 && mNodeEffectNumber[EFFECT_FLAVOUR_PLUGIN]==0 )
+      {
+      throw new RuntimeException("Cube and Node Plugin Effects not created!");
+      }
+
+    assignEffects(EFFECT_FLAVOUR_PLUGIN);
 
     return FAKE_EFFECT_ID;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void assignEffects(int phase)
+  private void assignEffects(int flavour)
     {
-    mCubeEffectNumber[phase] = ( mCubeEffects[phase]!=null ) ? mCubeEffects[phase].length : 0;
-    mNodeEffectNumber[phase] = ( mNodeEffects[phase]!=null ) ? mNodeEffects[phase].length : 0;
+    for(int i=0; i<mCubeEffectNumber[flavour]; i++)
+      {
+      android.util.Log.e("scramble", "applying cube effect "+mCubeEffects[flavour][i].getName());
+
+      mCube.apply(mCubeEffects[flavour][i],mCubeEffectPosition[flavour][i]);
+      mCubeEffects[flavour][i].notifyWhenFinished(this);
+      }
+
+    DistortedEffects nodeEffects = mCube.getEffects();
 
-    if( mCubeEffectNumber[phase]==0 && mNodeEffectNumber[phase]==0 )
+    for(int i=0; i<mNodeEffectNumber[flavour]; i++)
       {
-      throw new RuntimeException("Cube and Node Effects ("+phase+" phase) both not created!");
+      nodeEffects.apply(mNodeEffects[flavour][i],mNodeEffectPosition[flavour][i]);
+      mNodeEffects[flavour][i].notifyWhenFinished(this);
       }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    for(int i=0; i<mCubeEffectNumber[phase]; i++)
+  private void disassignEffects(int flavour)
+    {
+    for(int i=0; i<mCubeEffectNumber[flavour]; i++)
       {
-      mCube.apply(mCubeEffects[phase][i],mCubeEffectPosition[phase][i]);
-      mCubeEffects[phase][i].notifyWhenFinished(this);
+      android.util.Log.e("scramble", "removing cube effect "+mCubeEffects[flavour][i].getName());
+
+      mCube.remove(mCubeEffects[flavour][i].getID());
       }
 
     DistortedEffects nodeEffects = mCube.getEffects();
 
-    for(int i=0; i<mNodeEffectNumber[phase]; i++)
+    for(int i=0; i<mNodeEffectNumber[flavour]; i++)
+      {
+      nodeEffects.abortById(mNodeEffects[flavour][i].getID());
+      }
+
+    if( flavour==EFFECT_FLAVOUR_PLUGIN )
       {
-      nodeEffects.apply(mNodeEffects[phase][i],mNodeEffectPosition[phase][i]);
-      mNodeEffects[phase][i].notifyWhenFinished(this);
+      mListener.effectFinished(FAKE_EFFECT_ID);
       }
     }
 
diff --git a/src/main/java/org/distorted/effect/ScrambleEffectNone.java b/src/main/java/org/distorted/effect/ScrambleEffectNone.java
index ab8e101b..b78d548f 100644
--- a/src/main/java/org/distorted/effect/ScrambleEffectNone.java
+++ b/src/main/java/org/distorted/effect/ScrambleEffectNone.java
@@ -28,26 +28,24 @@ import org.distorted.library.type.Static3D;
 
 public class ScrambleEffectNone extends ScrambleEffect
   {
-  public void createEffectsPhase0(int duration)
+  public void createEffects(int duration)
     {
     Dynamic3D d0 = new Dynamic3D(1,0.5f);
     d0.add(new Static3D(0,0,0));
 
-    mCubeEffectPosition[0] = new int[] {-1};
-    mCubeEffects[0]        = new Effect[mCubeEffectPosition[0].length];
-    mCubeEffects[0][0]     = new MatrixEffectMove(d0);
+    mCubeEffectNumber[EFFECT_FLAVOUR_PLUGIN]   = 1;
+    mNodeEffectNumber[EFFECT_FLAVOUR_PLUGIN]   = 0;
+
+    mCubeEffectPosition[EFFECT_FLAVOUR_PLUGIN] = new int[] {-1};
+    mCubeEffects[EFFECT_FLAVOUR_PLUGIN]        = new Effect[mCubeEffectPosition[EFFECT_FLAVOUR_PLUGIN].length];
+    mCubeEffects[EFFECT_FLAVOUR_PLUGIN][0]     = new MatrixEffectMove(d0);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void createEffectsPhase1(int duration)
+  public void effectFinishedPlugin(final long effectID)
     {
-    Dynamic3D d0 = new Dynamic3D(1,0.5f);
-    d0.add(new Static3D(0,0,0));
 
-    mCubeEffectPosition[1]  = new int[] {-1};
-    mCubeEffects[1]         = new Effect[mCubeEffectPosition[1].length];
-    mCubeEffects[1][0]      = new MatrixEffectMove(d0);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/effect/ScrambleEffectRotations.java b/src/main/java/org/distorted/effect/ScrambleEffectRotations.java
new file mode 100644
index 00000000..171998ef
--- /dev/null
+++ b/src/main/java/org/distorted/effect/ScrambleEffectRotations.java
@@ -0,0 +1,69 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2019 Leszek Koltunski                                                               //
+//                                                                                               //
+// This file is part of Distorted.                                                               //
+//                                                                                               //
+// Distorted 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.                                                           //
+//                                                                                               //
+// Distorted 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 Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.distorted.effect;
+
+import org.distorted.library.effect.Effect;
+import org.distorted.library.effect.MatrixEffectMove;
+import org.distorted.library.type.Dynamic;
+import org.distorted.library.type.Dynamic3D;
+import org.distorted.library.type.Static3D;
+
+import static org.distorted.magic.RubikRenderer.TEXTURE_SIZE;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class ScrambleEffectRotations extends ScrambleEffect
+  {
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void createEffects(int duration)
+    {
+    mCubeEffectNumber[EFFECT_FLAVOUR_PLUGIN]   = 1;
+    mNodeEffectNumber[EFFECT_FLAVOUR_PLUGIN]   = 0;
+    mCubeEffectPosition[EFFECT_FLAVOUR_PLUGIN] = new int[] {6};
+    mCubeEffects[EFFECT_FLAVOUR_PLUGIN]        = new Effect[mCubeEffectPosition[EFFECT_FLAVOUR_PLUGIN].length];
+
+    float Z = TEXTURE_SIZE/3;
+
+    Dynamic3D d0 = new Dynamic3D(duration, 0.5f);
+    d0.setMode(Dynamic.MODE_PATH);
+    d0.add(new Static3D( 0, 0, 0));
+    d0.add(new Static3D( 0, 0,-Z));
+    d0.add(new Static3D( 0, 0, 0));
+    mCubeEffects[EFFECT_FLAVOUR_PLUGIN][0] = new MatrixEffectMove(d0);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void effectFinishedPlugin(final long effectID)
+    {
+
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Enable all effects used in this Effect. Called by reflection from the parent class.
+
+  @SuppressWarnings("unused")
+  static void enable()
+    {
+
+    }
+  }
