commit 34747dd1f73d896276ac49348722587ebfd06e39
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed May 8 21:54:50 2019 +0100

    Major progress with DistortedCube:
    
    - split transition effect into separate 'appear' and 'disappear' effects
    - apply the 'appear' effects to a new cube being displayed at the start of the app
    - remember cube size across activity restarts

diff --git a/src/main/java/org/distorted/effect/AppearEffect.java b/src/main/java/org/distorted/effect/AppearEffect.java
new file mode 100644
index 00000000..368142bd
--- /dev/null
+++ b/src/main/java/org/distorted/effect/AppearEffect.java
@@ -0,0 +1,167 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.main.DistortedScreen;
+import org.distorted.library.message.EffectListener;
+import org.distorted.library.message.EffectMessage;
+import org.distorted.magic.RubikCube;
+
+import java.lang.reflect.Method;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public abstract class AppearEffect implements EffectListener
+  {
+  public enum Type
+    {
+    EMPTY         (AppearEffectEmpty.class       ),
+    TRANSPARENCY  (AppearEffectTransparency.class),
+    MOVE          (AppearEffectMove.class        ),
+    ROUND         (AppearEffectRound.class       ),
+    SCALE         (AppearEffectScale.class       ),
+    ;
+
+    private final Class<? extends AppearEffect> effectClass;
+
+    Type(Class<? extends AppearEffect> effectClass)
+      {
+      this.effectClass = effectClass;
+      }
+    }
+
+  private final int FAKE_EFFECT_ID = -1;
+
+  private int mCubeEffectNumber, mCubeEffectFinished, mCubeEffectReturned;
+
+  private EffectListener mListener;
+  private DistortedScreen mScreen;
+  private RubikCube mCube;
+
+  Effect[] mCubeEffects;
+  int[] mCubeEffectPosition;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  AppearEffect()
+    {
+    mCubeEffectReturned = 0;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  abstract int createEffects(int duration);
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void effectMessage(final EffectMessage em, final long effectID, final long objectID)
+    {
+    for(int i=0; i<mCubeEffectNumber; i++)
+      {
+      long id = mCubeEffects[i].getID();
+
+      if( effectID == id )
+        {
+        mCubeEffectReturned++;
+
+        if( mCubeEffectReturned == mCubeEffectFinished )
+          {
+          mListener.effectMessage(null, FAKE_EFFECT_ID, 0);
+          }
+
+        if( mCubeEffectReturned == mCubeEffectNumber )
+          {
+          mCube.deregisterForMessages(this);
+          }
+
+        mCube.remove(id);
+        break;
+        }
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public long start(DistortedScreen screen, RubikCube cube, EffectListener listener)
+    {
+    mScreen   = screen;
+    mCube     = cube;
+    mListener = listener;
+
+    mCubeEffectFinished = createEffects(2000);
+
+    if( mCubeEffects!=null )
+      {
+      mCubeEffectNumber = mCubeEffects.length;
+      }
+    else
+      {
+      throw new RuntimeException("Appear Cube Effects not created!");
+      }
+
+    for(int i=0; i<mCubeEffectNumber; i++)
+      {
+      mCube.apply(mCubeEffects[i],mCubeEffectPosition[i]);
+      }
+
+    mCube.registerForMessages(this);
+    mScreen.attach(mCube);
+
+    return FAKE_EFFECT_ID;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static AppearEffect create(Type type) throws InstantiationException, IllegalAccessException
+    {
+    return type.effectClass.newInstance();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void enableEffects()
+    {
+    Method method=null;
+
+    for(Type type: Type.values())
+      {
+      Class<? extends AppearEffect> cls = type.effectClass;
+
+      try
+        {
+        method = cls.getMethod("enable");
+        }
+      catch(NoSuchMethodException ex)
+        {
+        android.util.Log.e("transitionEffect", "exception getting method: "+ex.getMessage());
+        }
+
+      try
+        {
+        method.invoke(null);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("transitionEffect", "exception invoking method: "+ex.getMessage());
+        }
+      }
+    }
+  }
diff --git a/src/main/java/org/distorted/effect/AppearEffectEmpty.java b/src/main/java/org/distorted/effect/AppearEffectEmpty.java
new file mode 100644
index 00000000..dd049f60
--- /dev/null
+++ b/src/main/java/org/distorted/effect/AppearEffectEmpty.java
@@ -0,0 +1,51 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.Dynamic3D;
+import org.distorted.library.type.Static3D;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class AppearEffectEmpty extends AppearEffect
+  {
+  public int createEffects(int duration)
+    {
+    mCubeEffectPosition = new int[] {-1};
+    mCubeEffects        = new Effect[mCubeEffectPosition.length];
+
+    Dynamic3D oldCube0 = new Dynamic3D(1,0.5f);
+    oldCube0.add(new Static3D(0,0,0));
+    mCubeEffects[0] = new MatrixEffectMove(oldCube0);
+
+    return 1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// enable all effects used in this Appear (here: none).  Called by reflection from the parent class.
+
+  @SuppressWarnings("unused")
+  static void enable()
+    {
+
+    }
+  }
diff --git a/src/main/java/org/distorted/effect/AppearEffectMove.java b/src/main/java/org/distorted/effect/AppearEffectMove.java
new file mode 100644
index 00000000..23a30360
--- /dev/null
+++ b/src/main/java/org/distorted/effect/AppearEffectMove.java
@@ -0,0 +1,56 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.Dynamic3D;
+import org.distorted.library.type.Static3D;
+
+import static org.distorted.magic.RubikRenderer.TEXTURE_SIZE;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class AppearEffectMove extends AppearEffect
+  {
+  public int createEffects(int duration)
+    {
+    mCubeEffectPosition = new int[] {2};
+    mCubeEffects        = new Effect[mCubeEffectPosition.length];
+
+    Dynamic3D oldCube0 = new Dynamic3D(duration, 0.5f);
+    oldCube0.add(new Static3D(-TEXTURE_SIZE,0,0));
+    oldCube0.add(new Static3D(            0,0,0));
+    mCubeEffects[0] = new MatrixEffectMove(oldCube0);
+
+    return 1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Enable all effects used in this Appear. Called by reflection from the parent class.
+// Matrix Effects do not have to be enabled.
+
+  @SuppressWarnings("unused")
+  static void enable()
+    {
+
+    }
+  }
+
diff --git a/src/main/java/org/distorted/effect/AppearEffectRound.java b/src/main/java/org/distorted/effect/AppearEffectRound.java
new file mode 100644
index 00000000..15743117
--- /dev/null
+++ b/src/main/java/org/distorted/effect/AppearEffectRound.java
@@ -0,0 +1,62 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.effect.MatrixEffectScale;
+import org.distorted.library.type.Dynamic3D;
+import org.distorted.library.type.Static3D;
+
+import static org.distorted.magic.RubikRenderer.TEXTURE_SIZE;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class AppearEffectRound extends AppearEffect
+  {
+  public int createEffects(int duration)
+    {
+    mCubeEffectPosition = new int[] {2, 2};
+    mCubeEffects        = new Effect[mCubeEffectPosition.length];
+
+    Dynamic3D oldCube0 = new Dynamic3D(duration/2, 0.5f);
+    oldCube0.add(new Static3D(-TEXTURE_SIZE,0,0));
+    oldCube0.add(new Static3D(            0,0,0));
+    mCubeEffects[0] = new MatrixEffectMove(oldCube0);
+
+    Dynamic3D oldCube1 = new Dynamic3D(duration/2, 0.5f);
+    oldCube1.add(new Static3D(0.01f, 0.01f, 0.01f));
+    oldCube1.add(new Static3D(1.00f, 1.00f, 1.00f));
+    mCubeEffects[1] = new MatrixEffectScale(oldCube1);
+
+    return 2;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Enable all effects used in this Appear. Called by reflection from the parent class.
+// Matrix Effects do not have to be enabled.
+
+  @SuppressWarnings("unused")
+  static void enable()
+    {
+
+    }
+  }
+
diff --git a/src/main/java/org/distorted/effect/AppearEffectScale.java b/src/main/java/org/distorted/effect/AppearEffectScale.java
new file mode 100644
index 00000000..8ed71da0
--- /dev/null
+++ b/src/main/java/org/distorted/effect/AppearEffectScale.java
@@ -0,0 +1,54 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.MatrixEffectScale;
+import org.distorted.library.type.Dynamic3D;
+import org.distorted.library.type.Static3D;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class AppearEffectScale extends AppearEffect
+  {
+  public int createEffects(int duration)
+    {
+    mCubeEffectPosition = new int[] {5};
+    mCubeEffects        = new Effect[mCubeEffectPosition.length];
+
+    Dynamic3D oldCube0 = new Dynamic3D(duration, 0.5f);
+    oldCube0.add(new Static3D(0.01f, 0.01f, 0.01f));
+    oldCube0.add(new Static3D(1.00f, 1.00f, 1.00f));
+    mCubeEffects[0] = new MatrixEffectScale(oldCube0);
+
+    return 1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Enable all effects used in this Appear. Called by reflection from the parent class.
+// Matrix Effects do not have to be enabled.
+
+  @SuppressWarnings("unused")
+  static void enable()
+    {
+
+    }
+  }
+
diff --git a/src/main/java/org/distorted/effect/AppearEffectTransparency.java b/src/main/java/org/distorted/effect/AppearEffectTransparency.java
new file mode 100644
index 00000000..f1d5192b
--- /dev/null
+++ b/src/main/java/org/distorted/effect/AppearEffectTransparency.java
@@ -0,0 +1,52 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.FragmentEffectAlpha;
+import org.distorted.library.type.Dynamic1D;
+import org.distorted.library.type.Static1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class AppearEffectTransparency extends AppearEffect
+  {
+  public int createEffects(int duration)
+    {
+    mCubeEffectPosition = new int[] {-1};
+    mCubeEffects        = new Effect[mCubeEffectPosition.length];
+
+    Dynamic1D oldCube0 = new Dynamic1D(duration, 0.5f);
+    oldCube0.add(new Static1D(0.0f));
+    oldCube0.add(new Static1D(1.0f));
+    mCubeEffects[0] = new FragmentEffectAlpha(oldCube0);
+
+    return 1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Enable all effects used in this Appear. Called by reflection from the parent class.
+
+  @SuppressWarnings("unused")
+  static void enable()
+    {
+    FragmentEffectAlpha.enable();
+    }
+  }
diff --git a/src/main/java/org/distorted/effect/DisappearEffect.java b/src/main/java/org/distorted/effect/DisappearEffect.java
new file mode 100644
index 00000000..63ea9f63
--- /dev/null
+++ b/src/main/java/org/distorted/effect/DisappearEffect.java
@@ -0,0 +1,167 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.main.DistortedScreen;
+import org.distorted.library.message.EffectListener;
+import org.distorted.library.message.EffectMessage;
+import org.distorted.magic.RubikCube;
+
+import java.lang.reflect.Method;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public abstract class DisappearEffect implements EffectListener
+  {
+  public enum Type
+    {
+    EMPTY         (DisappearEffectEmpty.class       ),
+    TRANSPARENCY  (DisappearEffectTransparency.class),
+    MOVE          (DisappearEffectMove.class        ),
+    ROUND         (DisappearEffectRound.class       ),
+    SCALE         (DisappearEffectScale.class       ),
+    ;
+
+    private final Class<? extends DisappearEffect> effectClass;
+
+    Type(Class<? extends DisappearEffect> effectClass)
+      {
+      this.effectClass = effectClass;
+      }
+    }
+
+  private final int FAKE_EFFECT_ID = -2;
+
+  private int mCubeEffectNumber, mCubeEffectFinished, mCubeEffectReturned;
+
+  private EffectListener mListener;
+  private DistortedScreen mScreen;
+  private RubikCube mCube;
+
+  Effect[] mCubeEffects;
+  int[] mCubeEffectPosition;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  DisappearEffect()
+    {
+    mCubeEffectReturned = 0;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  abstract int createEffects(int duration);
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void effectMessage(final EffectMessage em, final long effectID, final long objectID)
+    {
+    for(int i=0; i<mCubeEffectNumber; i++)
+      {
+      long id = mCubeEffects[i].getID();
+
+      if( effectID == id )
+        {
+        mCubeEffectReturned++;
+
+        if( mCubeEffectReturned == mCubeEffectFinished )
+          {
+          mListener.effectMessage(null, FAKE_EFFECT_ID, 0);
+          }
+
+        if( mCubeEffectReturned == mCubeEffectNumber )
+          {
+          mScreen.detach(mCube);
+          mCube.deregisterForMessages(this);
+          }
+
+        mCube.remove(id);
+        break;
+        }
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public long start(DistortedScreen screen, RubikCube cube, EffectListener listener)
+    {
+    mScreen   = screen;
+    mCube     = cube;
+    mListener = listener;
+
+    mCubeEffectFinished = createEffects(2000);
+
+    if( mCubeEffects!=null )
+      {
+      mCubeEffectNumber = mCubeEffects.length;
+      }
+    else
+      {
+      throw new RuntimeException("Disappear Cube Effects not created!");
+      }
+
+    for(int i=0; i<mCubeEffectNumber; i++)
+      {
+      mCube.apply(mCubeEffects[i],mCubeEffectPosition[i]);
+      }
+
+    mCube.registerForMessages(this);
+
+    return FAKE_EFFECT_ID;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static DisappearEffect create(Type type) throws InstantiationException, IllegalAccessException
+    {
+    return type.effectClass.newInstance();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public static void enableEffects()
+    {
+    Method method=null;
+
+    for(Type type: Type.values())
+      {
+      Class<? extends DisappearEffect> cls = type.effectClass;
+
+      try
+        {
+        method = cls.getMethod("enable");
+        }
+      catch(NoSuchMethodException ex)
+        {
+        android.util.Log.e("transitionEffect", "exception getting method: "+ex.getMessage());
+        }
+
+      try
+        {
+        method.invoke(null);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("transitionEffect", "exception invoking method: "+ex.getMessage());
+        }
+      }
+    }
+  }
diff --git a/src/main/java/org/distorted/effect/DisappearEffectEmpty.java b/src/main/java/org/distorted/effect/DisappearEffectEmpty.java
new file mode 100644
index 00000000..a2499c4a
--- /dev/null
+++ b/src/main/java/org/distorted/effect/DisappearEffectEmpty.java
@@ -0,0 +1,51 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.Dynamic3D;
+import org.distorted.library.type.Static3D;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class DisappearEffectEmpty extends DisappearEffect
+  {
+  public int createEffects(int duration)
+    {
+    mCubeEffectPosition = new int[] {-1};
+    mCubeEffects        = new Effect[mCubeEffectPosition.length];
+
+    Dynamic3D oldCube0 = new Dynamic3D(1,0.5f);
+    oldCube0.add(new Static3D(0,0,0));
+    mCubeEffects[0] = new MatrixEffectMove(oldCube0);
+
+    return 1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// enable all effects used in this Appear (here: none).  Called by reflection from the parent class.
+
+  @SuppressWarnings("unused")
+  static void enable()
+    {
+
+    }
+  }
diff --git a/src/main/java/org/distorted/effect/DisappearEffectMove.java b/src/main/java/org/distorted/effect/DisappearEffectMove.java
new file mode 100644
index 00000000..a7fce5d6
--- /dev/null
+++ b/src/main/java/org/distorted/effect/DisappearEffectMove.java
@@ -0,0 +1,56 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.Dynamic3D;
+import org.distorted.library.type.Static3D;
+
+import static org.distorted.magic.RubikRenderer.TEXTURE_SIZE;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class DisappearEffectMove extends DisappearEffect
+  {
+  public int createEffects(int duration)
+    {
+    mCubeEffectPosition = new int[] {2};
+    mCubeEffects        = new Effect[mCubeEffectPosition.length];
+
+    Dynamic3D oldCube0 = new Dynamic3D(duration, 0.5f);
+    oldCube0.add(new Static3D(           0,0,0));
+    oldCube0.add(new Static3D(TEXTURE_SIZE,0,0));
+    mCubeEffects[0] = new MatrixEffectMove(oldCube0);
+
+    return 1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Enable all effects used in this Appear. Called by reflection from the parent class.
+// Matrix Effects do not have to be enabled.
+
+  @SuppressWarnings("unused")
+  static void enable()
+    {
+
+    }
+  }
+
diff --git a/src/main/java/org/distorted/effect/DisappearEffectRound.java b/src/main/java/org/distorted/effect/DisappearEffectRound.java
new file mode 100644
index 00000000..a31392ed
--- /dev/null
+++ b/src/main/java/org/distorted/effect/DisappearEffectRound.java
@@ -0,0 +1,62 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.effect.MatrixEffectScale;
+import org.distorted.library.type.Dynamic3D;
+import org.distorted.library.type.Static3D;
+
+import static org.distorted.magic.RubikRenderer.TEXTURE_SIZE;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class DisappearEffectRound extends DisappearEffect
+  {
+  public int createEffects(int duration)
+    {
+    mCubeEffectPosition = new int[] {2, 2};
+    mCubeEffects        = new Effect[mCubeEffectPosition.length];
+
+    Dynamic3D oldCube0 = new Dynamic3D(duration/2, 0.5f);
+    oldCube0.add(new Static3D(           0,0,0));
+    oldCube0.add(new Static3D(TEXTURE_SIZE,0,0));
+    mCubeEffects[0] = new MatrixEffectMove(oldCube0);
+
+    Dynamic3D oldCube1 = new Dynamic3D(duration/2, 0.5f);
+    oldCube1.add(new Static3D(1.0f, 1.0f, 1.0f));
+    oldCube1.add(new Static3D(0.01f, 0.01f, 0.01f));
+    mCubeEffects[1] = new MatrixEffectScale(oldCube1);
+
+    return 2;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Enable all effects used in this Appear. Called by reflection from the parent class.
+// Matrix Effects do not have to be enabled.
+
+  @SuppressWarnings("unused")
+  static void enable()
+    {
+
+    }
+  }
+
diff --git a/src/main/java/org/distorted/effect/DisappearEffectScale.java b/src/main/java/org/distorted/effect/DisappearEffectScale.java
new file mode 100644
index 00000000..b40fdf30
--- /dev/null
+++ b/src/main/java/org/distorted/effect/DisappearEffectScale.java
@@ -0,0 +1,54 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.MatrixEffectScale;
+import org.distorted.library.type.Dynamic3D;
+import org.distorted.library.type.Static3D;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class DisappearEffectScale extends DisappearEffect
+  {
+  public int createEffects(int duration)
+    {
+    mCubeEffectPosition = new int[] {5};
+    mCubeEffects        = new Effect[mCubeEffectPosition.length];
+
+    Dynamic3D oldCube0 = new Dynamic3D(duration, 0.5f);
+    oldCube0.add(new Static3D(1.00f, 1.00f, 1.00f));
+    oldCube0.add(new Static3D(0.01f, 0.01f, 0.01f));
+    mCubeEffects[0] = new MatrixEffectScale(oldCube0);
+
+    return 1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Enable all effects used in this Appear. Called by reflection from the parent class.
+// Matrix Effects do not have to be enabled.
+
+  @SuppressWarnings("unused")
+  static void enable()
+    {
+
+    }
+  }
+
diff --git a/src/main/java/org/distorted/effect/DisappearEffectTransparency.java b/src/main/java/org/distorted/effect/DisappearEffectTransparency.java
new file mode 100644
index 00000000..1501c4c5
--- /dev/null
+++ b/src/main/java/org/distorted/effect/DisappearEffectTransparency.java
@@ -0,0 +1,52 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.FragmentEffectAlpha;
+import org.distorted.library.type.Dynamic1D;
+import org.distorted.library.type.Static1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class DisappearEffectTransparency extends DisappearEffect
+  {
+  public int createEffects(int duration)
+    {
+    mCubeEffectPosition = new int[] {-1};
+    mCubeEffects        = new Effect[mCubeEffectPosition.length];
+
+    Dynamic1D oldCube0 = new Dynamic1D(duration, 0.5f);
+    oldCube0.add(new Static1D(1.0f));
+    oldCube0.add(new Static1D(0.0f));
+    mCubeEffects[0] = new FragmentEffectAlpha(oldCube0);
+
+    return 1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Enable all effects used in this Appear. Called by reflection from the parent class.
+
+  @SuppressWarnings("unused")
+  static void enable()
+    {
+    FragmentEffectAlpha.enable();
+    }
+  }
diff --git a/src/main/java/org/distorted/effect/TransitionEffect.java b/src/main/java/org/distorted/effect/TransitionEffect.java
deleted file mode 100644
index 1395b154..00000000
--- a/src/main/java/org/distorted/effect/TransitionEffect.java
+++ /dev/null
@@ -1,198 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// 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.main.DistortedScreen;
-import org.distorted.library.message.EffectListener;
-import org.distorted.library.message.EffectMessage;
-import org.distorted.magic.RubikCube;
-
-import java.lang.reflect.Method;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public abstract class TransitionEffect implements EffectListener
-  {
-  public enum Type
-    {
-    EMPTY      (TransitionEffectEmpty.class    ),
-    DISAPPEAR  (TransitionEffectDisappear.class),
-    MOVE       (TransitionEffectMove.class     ),
-    ROUND      (TransitionEffectRound.class    ),
-    SCALE      (TransitionEffectScale.class    ),
-    ;
-
-    private final Class<? extends TransitionEffect> effectClass;
-
-    Type(Class<? extends TransitionEffect> effectClass)
-      {
-      this.effectClass = effectClass;
-      }
-    }
-
-  private final int FAKE_EFFECT_ID = -1;
-
-  private int mOldCubeEffectNumber  , mNewCubeEffectNumber;
-  private int mOldCubeEffectReturned, mNewCubeEffectReturned;
-
-  private EffectListener mListener;
-  private DistortedScreen mScreen;
-  private RubikCube mOldCube, mNewCube;
-
-  Effect[] mOldCubeEffects, mNewCubeEffects;
-  int[] mOldCubeEffectPosition, mNewCubeEffectPosition;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  TransitionEffect()
-    {
-    mOldCubeEffectReturned = 0;
-    mNewCubeEffectReturned = 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void effectMessage(final EffectMessage em, final long effectID, final long objectID)
-    {
-    //android.util.Log.e("transition", "transition effect "+System.currentTimeMillis());
-
-    for(int i=0; i<mOldCubeEffectNumber; i++)
-      {
-      long id = mOldCubeEffects[i].getID();
-
-      if( effectID == id )
-        {
-        //android.util.Log.e("transition", i+" old effect "+System.currentTimeMillis());
-
-        mOldCubeEffectReturned++;
-        mOldCube.remove(id);
-
-        if( mOldCubeEffectReturned == mOldCubeEffectNumber )
-          {
-          mScreen.detach(mOldCube);
-          mOldCube.deregisterForMessages(this);
-
-          for(int j=0; j<mOldCubeEffectNumber; j++)
-            {
-            mNewCube.apply(mNewCubeEffects[j],mNewCubeEffectPosition[j]);
-            }
-          mScreen.attach(mNewCube);
-          }
-        break;
-        }
-      }
-
-    for(int i=0; i<mNewCubeEffectNumber; i++)
-      {
-      long id = mNewCubeEffects[i].getID();
-
-      if( effectID == id )
-        {
-        //android.util.Log.e("transition", i+" new effect "+System.currentTimeMillis());
-
-        mNewCubeEffectReturned++;
-        mNewCube.remove(id);
-
-        if( mNewCubeEffectReturned == mNewCubeEffectNumber )
-          {
-          mNewCube.deregisterForMessages(this);
-          mListener.effectMessage(null, FAKE_EFFECT_ID, 0);
-          }
-        break;
-        }
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public long start(DistortedScreen screen, RubikCube oldCube, RubikCube newCube,EffectListener listener)
-    {
-    mScreen   = screen;
-    mNewCube  = newCube;
-    mOldCube  = oldCube;
-    mListener = listener;
-
-    if( mOldCubeEffects!=null )
-      {
-      mOldCubeEffectNumber = mOldCubeEffects.length;
-      }
-    else
-      {
-      throw new RuntimeException("Old Cube Effects not created!");
-      }
-
-    if( mNewCubeEffects!=null )
-      {
-      mNewCubeEffectNumber = mNewCubeEffects.length;
-      }
-    else
-      {
-      throw new RuntimeException("New Cube Effects not created!");
-      }
-
-    for(int i=0; i<mOldCubeEffectNumber; i++)
-      {
-      mOldCube.apply(mOldCubeEffects[i],mOldCubeEffectPosition[i]);
-      }
-
-    mOldCube.registerForMessages(this);
-    mNewCube.registerForMessages(this);
-
-    return FAKE_EFFECT_ID;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public static TransitionEffect create(Type type) throws InstantiationException, IllegalAccessException
-    {
-    return type.effectClass.newInstance();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public static void enableEffects()
-    {
-    Method method=null;
-
-    for(Type type: Type.values())
-      {
-      Class<? extends TransitionEffect> cls = type.effectClass;
-
-      try
-        {
-        method = cls.getMethod("enable");
-        }
-      catch(NoSuchMethodException ex)
-        {
-        android.util.Log.e("transitionEffect", "exception getting method: "+ex.getMessage());
-        }
-
-      try
-        {
-        method.invoke(null);
-        }
-      catch(Exception ex)
-        {
-        android.util.Log.e("transitionEffect", "exception invoking method: "+ex.getMessage());
-        }
-      }
-    }
-  }
diff --git a/src/main/java/org/distorted/effect/TransitionEffectDisappear.java b/src/main/java/org/distorted/effect/TransitionEffectDisappear.java
deleted file mode 100644
index 1bef51aa..00000000
--- a/src/main/java/org/distorted/effect/TransitionEffectDisappear.java
+++ /dev/null
@@ -1,61 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// 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.FragmentEffectAlpha;
-import org.distorted.library.type.Dynamic1D;
-import org.distorted.library.type.Static1D;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-class TransitionEffectDisappear extends TransitionEffect
-  {
-  TransitionEffectDisappear()
-    {
-    final int DURATION_IN_MILLIS = 1000;
-
-    mOldCubeEffectPosition = new int[] {-1};
-    mOldCubeEffects        = new Effect[mOldCubeEffectPosition.length];
-
-    Dynamic1D oldCube0 = new Dynamic1D(DURATION_IN_MILLIS, 0.5f);
-    oldCube0.add(new Static1D(1.0f));
-    oldCube0.add(new Static1D(0.0f));
-    mOldCubeEffects[0] = new FragmentEffectAlpha(oldCube0);
-
-    mNewCubeEffectPosition = new int[] {-1};
-    mNewCubeEffects        = new Effect[mNewCubeEffectPosition.length];
-
-    Dynamic1D newCube0 = new Dynamic1D(DURATION_IN_MILLIS, 0.5f);
-    newCube0.add(new Static1D(0.0f));
-    newCube0.add(new Static1D(1.0f));
-    mNewCubeEffects[0] = new FragmentEffectAlpha(newCube0);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// enable all effects used in this Transition.
-// called by reflection from the parent class.
-
-  @SuppressWarnings("unused")
-  static void enable()
-    {
-    FragmentEffectAlpha.enable();
-    }
-  }
diff --git a/src/main/java/org/distorted/effect/TransitionEffectEmpty.java b/src/main/java/org/distorted/effect/TransitionEffectEmpty.java
deleted file mode 100644
index 7461d8c1..00000000
--- a/src/main/java/org/distorted/effect/TransitionEffectEmpty.java
+++ /dev/null
@@ -1,59 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// 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.Dynamic3D;
-import org.distorted.library.type.Static3D;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-class TransitionEffectEmpty extends TransitionEffect
-  {
-  TransitionEffectEmpty()
-    {
-    final int DURATION_IN_MILLIS = 1;
-
-    mOldCubeEffectPosition = new int[] {-1};
-    mOldCubeEffects        = new Effect[mOldCubeEffectPosition.length];
-
-    Dynamic3D oldCube0 = new Dynamic3D(DURATION_IN_MILLIS, 0.5f);
-    oldCube0.add(new Static3D(0,0,0));
-    mOldCubeEffects[0] = new MatrixEffectMove(oldCube0);
-
-    mNewCubeEffectPosition = new int[] {-1};
-    mNewCubeEffects        = new Effect[mNewCubeEffectPosition.length];
-
-    Dynamic3D newCube0 = new Dynamic3D(DURATION_IN_MILLIS, 0.5f);
-    newCube0.add(new Static3D(0,0,0));
-    mNewCubeEffects[0] = new MatrixEffectMove(newCube0);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// enable all effects used in this Transition (here: none).
-// called by reflection from the parent class.
-
-  @SuppressWarnings("unused")
-  static void enable()
-    {
-
-    }
-  }
diff --git a/src/main/java/org/distorted/effect/TransitionEffectMove.java b/src/main/java/org/distorted/effect/TransitionEffectMove.java
deleted file mode 100644
index 835374ed..00000000
--- a/src/main/java/org/distorted/effect/TransitionEffectMove.java
+++ /dev/null
@@ -1,64 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// 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.Dynamic3D;
-import org.distorted.library.type.Static3D;
-
-import static org.distorted.magic.RubikRenderer.TEXTURE_SIZE;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-class TransitionEffectMove extends TransitionEffect
-  {
-  TransitionEffectMove()
-    {
-    final int DURATION_IN_MILLIS = 1000;
-
-    mOldCubeEffectPosition = new int[] {2};
-    mOldCubeEffects        = new Effect[mOldCubeEffectPosition.length];
-
-    Dynamic3D oldCube0 = new Dynamic3D(DURATION_IN_MILLIS, 0.5f);
-    oldCube0.add(new Static3D(0,0,0));
-    oldCube0.add(new Static3D(TEXTURE_SIZE,0,0));
-    mOldCubeEffects[0] = new MatrixEffectMove(oldCube0);
-
-    mNewCubeEffectPosition = new int[] {2};
-    mNewCubeEffects        = new Effect[mNewCubeEffectPosition.length];
-
-    Dynamic3D newCube0 = new Dynamic3D(DURATION_IN_MILLIS, 0.5f);
-    newCube0.add(new Static3D(-TEXTURE_SIZE,0,0));
-    newCube0.add(new Static3D(0,0,0));
-    mNewCubeEffects[0] = new MatrixEffectMove(newCube0);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// enable all effects used in this Transition. Called by reflection from the parent class.
-// Matrix Effects do not have to be enabled.
-
-  @SuppressWarnings("unused")
-  static void enable()
-    {
-
-    }
-  }
-
diff --git a/src/main/java/org/distorted/effect/TransitionEffectRound.java b/src/main/java/org/distorted/effect/TransitionEffectRound.java
deleted file mode 100644
index 49b70740..00000000
--- a/src/main/java/org/distorted/effect/TransitionEffectRound.java
+++ /dev/null
@@ -1,78 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// 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.effect.MatrixEffectScale;
-import org.distorted.library.type.Dynamic3D;
-import org.distorted.library.type.Static3D;
-
-import static org.distorted.magic.RubikRenderer.TEXTURE_SIZE;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-class TransitionEffectRound extends TransitionEffect
-  {
-  TransitionEffectRound()
-    {
-    final int DURATION_IN_MILLIS = 10000;
-
-    mOldCubeEffectPosition = new int[] {2, 2};
-    mOldCubeEffects        = new Effect[mOldCubeEffectPosition.length];
-
-    Dynamic3D oldCube0 = new Dynamic3D(DURATION_IN_MILLIS, 0.5f);
-    oldCube0.add(new Static3D(0,0,0));
-    oldCube0.add(new Static3D(TEXTURE_SIZE,0,0));
-    oldCube0.add(new Static3D(0,0,0));
-    mOldCubeEffects[0] = new MatrixEffectMove(oldCube0);
-
-    Dynamic3D oldCube1 = new Dynamic3D(DURATION_IN_MILLIS, 0.5f);
-    oldCube1.add(new Static3D(1.0f, 1.0f, 1.0f));
-    oldCube1.add(new Static3D(0.01f, 0.01f, 0.01f));
-    mOldCubeEffects[1] = new MatrixEffectScale(oldCube1);
-
-
-    mNewCubeEffectPosition = new int[] {2, 2};
-    mNewCubeEffects        = new Effect[mNewCubeEffectPosition.length];
-
-    Dynamic3D newCube0 = new Dynamic3D(DURATION_IN_MILLIS, 0.5f);
-    newCube0.add(new Static3D(0,0,0));
-    newCube0.add(new Static3D(-TEXTURE_SIZE,0,0));
-    newCube0.add(new Static3D(0,0,0));
-    mNewCubeEffects[0] = new MatrixEffectMove(newCube0);
-
-    Dynamic3D newCube1 = new Dynamic3D(DURATION_IN_MILLIS, 0.5f);
-    newCube1.add(new Static3D(0.01f, 0.01f, 0.01f));
-    newCube1.add(new Static3D(1.0f, 1.0f, 1.0f));
-    mNewCubeEffects[1] = new MatrixEffectScale(newCube1);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// enable all effects used in this Transition. Called by reflection from the parent class.
-// Matrix Effects do not have to be enabled.
-
-  @SuppressWarnings("unused")
-  static void enable()
-    {
-
-    }
-  }
-
diff --git a/src/main/java/org/distorted/effect/TransitionEffectScale.java b/src/main/java/org/distorted/effect/TransitionEffectScale.java
deleted file mode 100644
index 71601df9..00000000
--- a/src/main/java/org/distorted/effect/TransitionEffectScale.java
+++ /dev/null
@@ -1,63 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// 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.MatrixEffectScale;
-import org.distorted.library.type.Dynamic3D;
-import org.distorted.library.type.Static3D;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-class TransitionEffectScale extends TransitionEffect
-  {
-  TransitionEffectScale()
-    {
-    final int DURATION_IN_MILLIS = 1000;
-
-    mOldCubeEffectPosition = new int[] {5};
-    mOldCubeEffects        = new Effect[mOldCubeEffectPosition.length];
-
-    Dynamic3D oldCube0 = new Dynamic3D(DURATION_IN_MILLIS, 0.5f);
-    oldCube0.add(new Static3D(1.0f, 1.0f, 1.0f));
-    oldCube0.add(new Static3D(0.01f, 0.01f, 0.01f));
-    mOldCubeEffects[0] = new MatrixEffectScale(oldCube0);
-
-
-    mNewCubeEffectPosition = new int[] {5};
-    mNewCubeEffects        = new Effect[mNewCubeEffectPosition.length];
-
-    Dynamic3D newCube0 = new Dynamic3D(DURATION_IN_MILLIS, 0.5f);
-    newCube0.add(new Static3D(0.01f, 0.01f, 0.01f));
-    newCube0.add(new Static3D(1.0f, 1.0f, 1.0f));
-    mNewCubeEffects[0] = new MatrixEffectScale(newCube0);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// enable all effects used in this Transition. Called by reflection from the parent class.
-// Matrix Effects do not have to be enabled.
-
-  @SuppressWarnings("unused")
-  static void enable()
-    {
-
-    }
-  }
-
diff --git a/src/main/java/org/distorted/magic/RubikActivity.java b/src/main/java/org/distorted/magic/RubikActivity.java
index 6a03bf77..564cc466 100644
--- a/src/main/java/org/distorted/magic/RubikActivity.java
+++ b/src/main/java/org/distorted/magic/RubikActivity.java
@@ -37,15 +37,20 @@ public class RubikActivity extends Activity
     private static final int SMALLEST_SIZE = 2;
     private static final int[] button_ids  = {R.id.rubikSize2, R.id.rubikSize3, R.id.rubikSize4};
 
+    static int mSize = DEFAULT_SIZE;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     @Override
-    protected void onCreate(Bundle icicle)
+    protected void onCreate(Bundle savedState)
       {
-      super.onCreate(icicle);
+      super.onCreate(savedState);
       setContentView(R.layout.layout);
 
-      markButton(DEFAULT_SIZE);
+      if( savedState==null )
+        {
+        markButton(DEFAULT_SIZE);
+        }
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -78,6 +83,33 @@ public class RubikActivity extends Activity
       super.onDestroy();
       }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public void onSaveInstanceState(Bundle savedInstanceState)
+      {
+      super.onSaveInstanceState(savedInstanceState);
+      savedInstanceState.putInt("size", mSize );
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public void onRestoreInstanceState(Bundle savedInstanceState)
+      {
+      super.onRestoreInstanceState(savedInstanceState);
+
+      int size = savedInstanceState.getInt("size");
+      markButton(size);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    static int getSize()
+      {
+      return mSize;
+      }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     public void Scramble(View v)
@@ -119,6 +151,8 @@ public class RubikActivity extends Activity
 
    private void markButton(int size)
      {
+     mSize = size;
+
      for(int b=0; b<button_ids.length; b++)
        {
        Drawable d = findViewById(button_ids[b]).getBackground();
diff --git a/src/main/java/org/distorted/magic/RubikRenderer.java b/src/main/java/org/distorted/magic/RubikRenderer.java
index 75c2843c..b2a88083 100644
--- a/src/main/java/org/distorted/magic/RubikRenderer.java
+++ b/src/main/java/org/distorted/magic/RubikRenderer.java
@@ -21,8 +21,8 @@ package org.distorted.magic;
 
 import android.opengl.GLSurfaceView;
 
-import org.distorted.effect.TransitionEffect;
-import org.distorted.library.effect.EffectType;
+import org.distorted.effect.AppearEffect;
+import org.distorted.effect.DisappearEffect;
 import org.distorted.library.effect.VertexEffectSink;
 import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedLibrary;
@@ -50,7 +50,7 @@ public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
     private Static4D mTempCurrent, mTempAccumulated;
     private float mCubeSizeInScreenSpace;
     private int mNextCubeSize;
-    private long mRotationFinishedID, mTransitionEffectID;
+    private long mRotationFinishedID, mDisappearEffectID, mAppearEffectID;
     private boolean mFinishRotation, mRemoveRotation, mFinishDragCurrent, mFinishDragAccumulated;
     private boolean mCanRotate, mCanDrag;
     private RubikCube mOldCube, mNewCube;
@@ -82,12 +82,11 @@ public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
       mFinishDragCurrent     = false;
       mFinishDragAccumulated = false;
 
-      mNextCubeSize= 0;
-
       mCanRotate = true;
       mCanDrag   = true;
 
       mMesh= new MeshQuad();
+      mNextCubeSize =RubikActivity.getSize();
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -126,21 +125,14 @@ public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
 
       if( mNextCubeSize!=0 )
         {
-        mCanDrag   = false;
-        mCanRotate = false;
         createCubeNow(mNextCubeSize);
 
-        try
-          {
-          TransitionEffect effect = TransitionEffect.create(TransitionEffect.Type.ROUND);
-          mTransitionEffectID = effect.start(mScreen,mOldCube,mNewCube,this);
-          }
-        catch(Exception ex)
-          {
-          android.util.Log.e("Renderer", "failed to create TransitionEffect, exception: "+ex.getMessage());
-          }
-
+        mCanDrag   = false;
+        mCanRotate = false;
         mNextCubeSize = 0;
+
+        if( mOldCube!=null ) disappearCube();
+        else                    appearCube();
         }
       }
 
@@ -151,36 +143,59 @@ public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
      {
      if(      effectID == mRotationFinishedID )
        {
-       //android.util.Log.e("renderer", "rotation finished");
-
        mRemoveRotation = true;
        }
-     else if( effectID == mTransitionEffectID )
+     else if( effectID == mDisappearEffectID )
+       {
+       appearCube();
+       }
+     else if( effectID == mAppearEffectID    )
        {
-       /*
-       int nM = mNewCube.getNumEffects(EffectType.MATRIX);
-       int nV = mNewCube.getNumEffects(EffectType.VERTEX);
-       int nF = mNewCube.getNumEffects(EffectType.FRAGMENT);
-       int nP = mNewCube.getNumEffects(EffectType.POSTPROCESS);
+       mCanRotate = true;
+       mCanDrag   = true;
+       }
+     }
 
-       android.util.Log.d("renderer", "transition finished, new cube effects= "+nM+","+nV+","+nF+","+nP);
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-       int oM = mOldCube.getNumEffects(EffectType.MATRIX);
-       int oV = mOldCube.getNumEffects(EffectType.VERTEX);
-       int oF = mOldCube.getNumEffects(EffectType.FRAGMENT);
-       int oP = mOldCube.getNumEffects(EffectType.POSTPROCESS);
+   private void disappearCube()
+     {
+     try
+       {
+       DisappearEffect effect = DisappearEffect.create(DisappearEffect.Type.ROUND);
+       mDisappearEffectID = effect.start(mScreen,mOldCube,this);
+       }
+     catch(Exception ex)
+       {
+       android.util.Log.e("Renderer", "failed to create DisappearEffect, exception: "+ex.getMessage());
+       }
+     }
 
-       android.util.Log.d("renderer", "transition finished, old cube effects= "+oM+","+oV+","+oF+","+oP);
-       */
-       mCanRotate = true;
-       mCanDrag   = true;
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   private void appearCube()
+     {
+     try
+       {
+       AppearEffect effect = AppearEffect.create(AppearEffect.Type.ROUND);
+       mAppearEffectID = effect.start(mScreen,mNewCube,this);
+       }
+     catch(Exception ex)
+       {
+       android.util.Log.e("Renderer", "failed to create AppearEffect, exception: "+ex.getMessage());
+
+       mScreen.attach(mNewCube); //
+       mCanRotate = true;        // just appear the cube
+       mCanDrag   = true;        //
        }
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+
+   public void onSurfaceChanged(GL10 glUnused, int width, int height)
       {
+      if( mNewCube!=null ) mNewCube.createTexture();
+
       float cameraDistance = CAMERA_DISTANCE*(width>height ? width:height);
       float fovInDegrees   = computeFOV(cameraDistance,height);
 
@@ -197,14 +212,11 @@ public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
-    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
       {
-      mNewCube.createTexture();
-      mScreen.detachAll();
-      mScreen.attach(mNewCube);
-
       VertexEffectSink.enable();
-      TransitionEffect.enableEffects();
+      AppearEffect.enableEffects();
+      DisappearEffect.enableEffects();
 
       try
         {
@@ -236,7 +248,7 @@ public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
 
    boolean createCube(int newSize)
      {
-     if( mCanDrag && mCanRotate && newSize != mNewCube.getSize() )
+     if( mCanDrag && mCanRotate && (mNewCube==null || newSize != mNewCube.getSize()) )
        {
        mNextCubeSize = newSize;
        return true;
@@ -247,7 +259,7 @@ public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-   void createCubeNow(int newSize)
+   private void createCubeNow(int newSize)
      {
      if( mOldCube!=null ) mOldCube.releaseResources();
      mOldCube = mNewCube;
@@ -269,7 +281,11 @@ public class RubikRenderer implements GLSurfaceView.Renderer, EffectListener
    private void recomputeScaleFactor(int screenWidth, int screenHeight)
      {
      mCubeSizeInScreenSpace = CUBE_SCREEN_RATIO*(screenWidth>screenHeight ? screenHeight:screenWidth);
-     mNewCube.recomputeScaleFactor(screenWidth, screenHeight, mCubeSizeInScreenSpace);
+
+     if( mNewCube!=null )
+       {
+       mNewCube.recomputeScaleFactor(screenWidth, screenHeight, mCubeSizeInScreenSpace);
+       }
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/magic/RubikSurfaceView.java b/src/main/java/org/distorted/magic/RubikSurfaceView.java
index 4532c131..68eaa84e 100644
--- a/src/main/java/org/distorted/magic/RubikSurfaceView.java
+++ b/src/main/java/org/distorted/magic/RubikSurfaceView.java
@@ -36,6 +36,9 @@ class RubikSurfaceView extends GLSurfaceView
     // given face by SWIPING_SENSITIVITY/2 degrees.
     private final static int SWIPING_SENSITIVITY = 240;
 
+    // Moving the finger by 1/12 the distance of min(scrWidth,scrHeight) will start a Rotation.
+    private final static int ROTATION_SENSITIVITY=  12;
+
     private final static int NONE   =-1;
     private final static int FRONT  = 0;  // has to be 6 consecutive ints
     private final static int BACK   = 1;  // FRONT ... BOTTOM
@@ -80,7 +83,6 @@ class RubikSurfaceView extends GLSurfaceView
         mScreenWidth = mScreenHeight = mScreenMin = 0;
 
         mRenderer = new RubikRenderer(this);
-        mRenderer.createCubeNow(RubikActivity.DEFAULT_SIZE);
 
         mQuatCurrent     = new Static4D(0,0,0,1);
         mQuatAccumulated = mRenderer.initializeQuat();
@@ -127,7 +129,7 @@ class RubikSurfaceView extends GLSurfaceView
                                          }
                                        if( mBeginningRotation )
                                          {
-                                         int minimumDistToStartRotating = (mScreenMin*mScreenMin)/100;
+                                         int minimumDistToStartRotating = (mScreenMin*mScreenMin)/(ROTATION_SENSITIVITY*ROTATION_SENSITIVITY);
 
                                          if( (mX-x)*(mX-x)+(mY-y)*(mY-y) > minimumDistToStartRotating )
                                            {
