commit f2fe7e28567c62d4a2bacf704b46df0bfebc47eb
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Thu Jun 16 17:21:34 2016 +0100

    Major push towards simplifying DistortedObject's public API.
    Beginning of work  on VERTEX Effects - does not compile ATM!

diff --git a/src/main/java/org/distorted/library/DistortedObject.java b/src/main/java/org/distorted/library/DistortedObject.java
index 598561a..bb83569 100644
--- a/src/main/java/org/distorted/library/DistortedObject.java
+++ b/src/main/java/org/distorted/library/DistortedObject.java
@@ -25,6 +25,7 @@ import android.opengl.GLUtils;
 
 import org.distorted.library.message.EffectListener;
 import org.distorted.library.type.Data1D;
+import org.distorted.library.type.Data2D;
 import org.distorted.library.type.Data3D;
 import org.distorted.library.type.Data4D;
 import org.distorted.library.type.Dynamic;
@@ -762,539 +763,107 @@ public long scale(float scale)
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // Vertex-based effects  
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// DISTORT
 /**
  * Distort a (possibly changing in time) part of the Object by a (possibly changing in time) vector of force.
- * 
- * @param vector 2- or 3-dimensional Dynamic that returns a 2- or 3-dimensional Point which
- *               represents the vector the Center of the Effect is currently being dragged with.
- * @param region Region that masks the effect of the Distortion.
- * @param center 2-dimensional Dynamic that, at any given time, returns a Point2D representing
- *               the Center of the Effect.
- * @return       ID of the effect added, or -1 if we failed to add one. 
- */
-  public long distort(Dynamic vector, Static4D region, Dynamic2D center)
-    {  
-    return mV.add(EffectNames.DISTORT, vector, region, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Distort part of the Object by a (possibly changing in time) vector of force.
  * <p>
- * Difference between this and the previous method is that here the center of the Effect stays constant.
- *   
- * @param vector 2- or 3-dimensional Dynamic that returns a 2- or 3-dimensional Point which
- *               represents the vector the Center of the Effect is currently being dragged with.
- * @param region Region that masks the effect of the Distortion.
- * @param center Center of the Effect.
- * @return       ID of the effect added, or -1 if we failed to add one. 
+ * Only at most one of the 'center' and 'region' can be a Dynamic!
+ *
+ * @param vector 3-dimensional Vector which represents the force the Center of the Effect is
+ *               currently being dragged with.
+ * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
+ * @param region Region that masks the Effect.
+ * @return       ID of the effect added, or -1 if we failed to add one.
  */
-  public long distort(Dynamic vector, Static4D region, Static2D center)
+  public long distort(Data3D vector, Data2D center, Data4D region)
     {  
-    return mV.add(EffectNames.DISTORT, vector, region, center);
+    return mV.add(EffectNames.DISTORT, vector, center, region);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
  * Distort the whole Object by a (possibly changing in time) vector of force.
- * 
- * @param vector 2- or 3-dimensional Dynamic that returns a 2- or 3-dimensional Point which
- *               represents the vector the Center of the Effect is currently being dragged with.
- * @param center Center of the Effect.
+ *
+ * @param vector 3-dimensional Vector which represents the force the Center of the Effect is
+ *               currently being dragged with.
+ * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
  * @return       ID of the effect added, or -1 if we failed to add one.
  */
-  public long distort(Dynamic vector, Static2D center)
-    {
-    return mV.add(EffectNames.DISTORT, vector, null, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Distort part of the Object by a vector of force that changes from (0,0,0) to v.
- * 
- * @param vector   Maximum vector of force. 
- * @param region   Region that masks the effect of the Distortion.
- * @param center   Center of the Effect.
- * @param duration Time, in milliseconds, it takes to do one full interpolation.
- * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
- * @return         ID of the effect added, or -1 if we failed to add one. 
- */
-  public long distort(Static3D vector, Static4D region, Static2D center, int duration, float count)
-    {  
-    Dynamic3D di = new Dynamic3D();
-    di.setCount(count);
-    di.setDuration(duration);
-    di.add(new Static3D(0.0f,0.0f,0.0f));
-    di.add(vector);                                                  
-           
-    return mV.add(EffectNames.DISTORT, di, region, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Distort the whole Object by a vector of force that changes from (0,0,0) to v.
- * 
- * @param vector   Maximum vector of force.
- * @param center   Center of the Effect.
- * @param duration Time, in milliseconds, it takes to do one full interpolation.
- * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
- * @return         ID of the effect added, or -1 if we failed to add one. 
- */
-  public long distort(Static3D vector, Static2D center, int duration, float count)
-    {
-    Dynamic3D di = new Dynamic3D();
-    di.setCount(count);
-    di.setDuration(duration);
-    di.add(new Static3D(0.0f,0.0f,0.0f));
-    di.add(vector);                                                 
-           
-    return mV.add(EffectNames.DISTORT, di, null, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Distort the whole Object by a vector of force that changes from (0,0,0) to v.
- * <p>
- * Difference between this and the previous method is that here the vector of force will get interpolated
- * to the maximum v and the effect will end. We are thus limited to count=0.5.
- * 
- * @param vector   Maximum, final vector of force.
- * @param center   Center of the Effect.
- * @param duration Time, in milliseconds, it takes to do one full interpolation.
- * @return         ID of the effect added, or -1 if we failed to add one. 
- */
-  public long distort(Static3D vector, Static2D center, int duration)
-    {
-    Dynamic3D di = new Dynamic3D();
-    di.setCount(0.5f);
-    di.setDuration(duration);
-    di.add(new Static3D(0.0f,0.0f,0.0f));
-    di.add(vector);                 
-           
-    return mV.add(EffectNames.DISTORT, di, null, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Distort the whole Object by a vector of force v.
- * <p>
- * Here we apply a constant vector of force.
- * 
- * @param vector Vector of force.
- * @param center Center of the Effect.
- * @return       ID of the effect added, or -1 if we failed to add one. 
- */
-  public long distort(Static3D vector, Static2D center )
-    {
-    Dynamic3D di = new Dynamic3D();
-    di.setCount(0.5f);
-    di.setDuration(0);
-    di.add(new Static3D(0.0f,0.0f,0.0f));
-    di.add(vector);           
-           
-    return mV.add(EffectNames.DISTORT, di, null, center);
-    }
+public long distort(Data3D vector, Data2D center)
+  {
+  return mV.add(EffectNames.DISTORT, vector, center);
+  }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// DEFORM
 /**
  * Deform the shape of the whole Object with a (possibly changing in time) vector of force applied to
  * a (possibly changing in time) point on the Object.
  *     
- * @param vector Dynamic that, at any given time, returns a Static2D representing vector of
- *               force that deforms the shape of the whole Object.
- * @param center 2-dimensional Dynamic that, at any given time, returns a Point2D representing
- *               the Center of the Effect.
+ * @param vector Vector of force that deforms the shape of the whole Object.
+ * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
  * @return       ID of the effect added, or -1 if we failed to add one.
  */
-  public long deform(Dynamic vector, Dynamic2D center)
+  public long deform(Data3D vector, Data2D center)
     {  
-    return mV.add(EffectNames.DEFORM, vector, null, center);
+    return mV.add(EffectNames.DEFORM, vector, center);
     }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Deform the shape of the whole Object with a (possibly changing in time) vector of force applied to
- * a constant point on the Object.
- * 
- * @param vector Dynamic that, at any given time, returns a Static2D representing
- *               vector of force that deforms the shape of the whole Object.
- * @param center Center of the Effect.
- * @return       ID of the effect added, or -1 if we failed to add one.
- */
-  public long deform(Dynamic vector, Static2D center)
-    {
-    return mV.add(EffectNames.DEFORM, vector, null, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Deform the shape of the whole Object with a vector of force smoothly changing from (0,0,0) to v
- * applied to a constant point on the Object.
- * 
- * @param vector   Vector of force.
- * @param center   Center of the Effect.
- * @param duration Time, in milliseconds, it takes to do one full interpolation.
- * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
- * @return         ID of the effect added, or -1 if we failed to add one. 
- */
-  public long deform(Static3D vector, Static2D center, int duration, float count)
-    {
-    Dynamic3D di = new Dynamic3D();
-    di.setCount(count);
-    di.setDuration(duration);
-    di.add(new Static3D(0.0f,0.0f,0.0f));
-    di.add(vector);                
-           
-    return mV.add(EffectNames.DEFORM, di, null, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Deform the shape of the whole Object with a vector of force smoothly changing from (0,0,0) to v
- * applied to a constant point on the Object.
- * <p>
- * Identical to calling the previous method with count=0.5.
- * 
- * @param vector   Final vector of force.
- * @param center   Center of the Effect.
- * @param duration Time, in milliseconds, it takes to do one full interpolation.
- * @return         ID of the effect added, or -1 if we failed to add one. 
- */
-  public long deform(Static3D vector, Static2D center, int duration)
-    {
-    Dynamic3D di = new Dynamic3D();
-    di.setCount(0.5f);
-    di.setDuration(duration);
-    di.add(new Static3D(0.0f,0.0f,0.0f));
-    di.add(vector);             
-           
-    return mV.add(EffectNames.DEFORM, di, null, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Deform the shape of the whole Object with a constant vector of force applied to a constant
- * point on the Object.
- * 
- * @param vector Vector of force.
- * @param center Center of the Effect.
- * @return       ID of the effect added, or -1 if we failed to add one. 
- */
-  public long deform(Static3D vector, Static2D center )
-    {
-    Dynamic3D di = new Dynamic3D();
-    di.setCount(0.5f);
-    di.setDuration(0);
-    di.add(new Static3D(0.0f,0.0f,0.0f));
-    di.add(vector);            
-           
-    return mV.add(EffectNames.DEFORM, di, null, center);
-    }
-   
 ///////////////////////////////////////////////////////////////////////////////////////////////////  
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// SINK
 /**
- * Pull all points around the center of the effect towards the center (if degree>=1) or push them 
+ * Pull all points around the center of the Effect towards the center (if degree>=1) or push them
  * away from the center (degree<=1)
- *    
- * @param sink   1-dimensional Dynamic which, at any given time, returns a Point1D representing
- *               the current degree of the effect.
- * @param region Region that masks the effect of the Sink.
- * @param center 2-dimensional Dynamic that, at any given time, returns a Point2D representing
- *               the Center of the Effect.
- * @return       ID of the effect added, or -1 if we failed to add one. 
- */
-  public long sink(Dynamic1D sink, Static4D region, Dynamic2D center)
-    {
-    return mV.add(EffectNames.SINK, sink, region, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Pull all points around the center of the effect towards the center (if degree>=1) or push them 
- * away from the center (degree<=1).
- * <p>
- * Here the Center stays constant.
- *      
- * @param sink   1-dimensional Dynamic which, at any given time, returns a Point1D
- *               representing the current degree of the effect.
- * @param region Region that masks the effect of the Sink.
- * @param center Center of the Effect.
- * @return       ID of the effect added, or -1 if we failed to add one. 
- */
-  public long sink(Dynamic1D sink, Static4D region, Static2D center)
-    {
-    return mV.add(EffectNames.SINK, sink, region, center);
-    }
-  
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Pull all points around the center of the effect towards the center (if degree>=1) or push them 
- * away from the center (degree<=1).
  * <p>
- * Here we can only interpolate between 1 and degree.
- * 
- * @param sink     How much to push or pull. Between 0 and infinity.
- * @param region   Region that masks the effect of the Sink.
- * @param center   2-dimensional Dynamic that, at any given time, returns a Point2D representing
- *                 the Center of the Effect.
- * @param duration Time, in milliseconds, it takes to do one full interpolation.
- * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
- * @return         ID of the effect added, or -1 if we failed to add one. 
- */
-  public long sink(float sink, Static4D region, Dynamic2D center, int duration, float count)
-    {
-    Dynamic1D di = new Dynamic1D();
-    di.setCount(count);
-    di.setDuration(duration);
-    di.add(new Static1D(1));
-    di.add(new Static1D(sink));
-    
-    return mV.add(EffectNames.SINK, di, region, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Pull all points around the center of the effect towards the center (if degree>=1) or push them 
- * away from the center (degree<=1).
- *   
- * @param sink     How much to push or pull. Between 0 and infinity.
- * @param region   Region that masks the effect of the Sink.
- * @param center   Center of the Effect.
- * @param duration Time, in milliseconds, it takes to do one full interpolation.
- * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
- * @return         ID of the effect added, or -1 if we failed to add one. 
- */
-  public long sink(float sink, Static4D region, Static2D center, int duration, float count)
-    {
-    Dynamic1D di = new Dynamic1D();
-    di.setCount(count);
-    di.setDuration(duration);
-    di.add(new Static1D(1));
-    di.add(new Static1D(sink));
-    
-    return mV.add(EffectNames.SINK, di, region, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Pull all points of the Object towards the center of the Effect (if degree>=1) or push them
- * away from the center (degree<=1).
- * 
- * @param sink     How much to push or pull. Between 0 and infinity.
- * @param center   Center of the Effect.
- * @param duration Time, in milliseconds, it takes to do one full interpolation.
- * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
- * @return         ID of the effect added, or -1 if we failed to add one. 
+ * Only at most one of the 'center' and 'region' can be a Dynamic!
+ *
+ * @param sink   The current degree of the Effect.
+ * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
+ * @param region Region that masks the Effect.
+ * @return       ID of the effect added, or -1 if we failed to add one.
  */
-  public long sink(float sink, Static2D center, int duration, float count)
+  public long sink(Data1D sink, Data2D center, Data4D region)
     {
-    Dynamic1D di = new Dynamic1D();
-    di.setCount(count);
-    di.setDuration(duration);
-    di.add(new Static1D(1));
-    di.add(new Static1D(sink));
-         
-    return mV.add(EffectNames.SINK, di, null, center);
+    return mV.add(EffectNames.SINK, sink, center, region);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
- * Pull all points of the Object towards the center of the Effect (if degree>=1) or push them
- * away from the center (degree<=1).
- * <p>
- * Equivalent to calling the previous method with count=0.5.
- * 
- * @param sink     How much to push or pull. Between 0 and infinity.
- * @param center   Center of the Effect.
- * @param duration Time, in milliseconds, it takes to do one full interpolation.
- * @return         ID of the effect added, or -1 if we failed to add one. 
+ * Pull all points around the center of the Effect towards the center (if degree>=1) or push them
+ * away from the center (degree<=1)
+ *
+ * @param sink   The current degree of the Effect.
+ * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
+ * @return       ID of the effect added, or -1 if we failed to add one.
  */
-  public long sink(float sink, Static2D center, int duration)
-    {
-    Dynamic1D di = new Dynamic1D();
-    di.setCount(0.5f);
-    di.setDuration(duration);
-    di.add(new Static1D(1));
-    di.add(new Static1D(sink));
-        
-    return mV.add(EffectNames.SINK, di, null, center);
-    }
+public long sink(Data1D sink, Data2D center)
+  {
+  return mV.add(EffectNames.SINK, sink, center);
+  }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Pull all points of the Object towards the center of the Effect (if degree>=1) or push them
- * away from the center (degree<=1).
- * <p>
- * Equivalent of calling the previous method with duration=0; i.e. we pull immediately.
- * 
- * @param sink   How much to push or pull. Between 0 and infinity.
- * @param center Center of the Effect.
- * @return       ID of the effect added, or -1 if we failed to add one. 
- */
-  public long sink(float sink, Static2D center)
-    {
-    Dynamic1D di = new Dynamic1D();
-    di.setCount(0.5f);
-    di.setDuration(0);
-    di.add(new Static1D(1));
-    di.add(new Static1D(sink));
-        
-    return mV.add(EffectNames.SINK, di, null, center);
-    }
-  
 ///////////////////////////////////////////////////////////////////////////////////////////////////  
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// SWIRL
-/**
- * Rotate part of the Object around the Center of the Effect by a certain angle (as returned by the
- * Dynamic).
- *   
- * @param swirl  1-dimensional Dynamic which, at any given time, returns a Point1D representing
- *               the degree of Swirl.
- * @param region Region that masks the effect of the Swirl.
- * @param center 2-dimensional Dynamic that, at any given time, returns a Point2D representing
- *               the Center of the Effect.
- * @return       ID of the effect added, or -1 if we failed to add one. 
- */
-  public long swirl(Dynamic1D swirl, Static4D region, Dynamic2D center)
-    {    
-    return mV.add(EffectNames.SWIRL, swirl, region, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
- * Rotate part of the Object around the Center of the Effect by a certain angle (as returned by the
- * Dynamic).
+ * Rotate part of the Object around the Center of the Effect by a certain angle.
  * <p>
- * Here the Center stays constant.
- *      
- * @param swirl  1-dimensional Dynamic which, at any given time, returns a Point1D representing
- *               the degree of Swirl.
- * @param region Region that masks the effect of the Swirl.
- * @param center Center of the Effect.
- * @return       ID of the effect added, or -1 if we failed to add one. 
+ * Only at most one of the 'center' and 'region' can be a Dynamic!
+ *
+ * @param swirl  The degree of Swirl. Positive values swirl clockwise.
+ * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
+ * @param region Region that masks the Effect.
+ * @return       ID of the effect added, or -1 if we failed to add one.
  */
-  public long swirl(Dynamic1D swirl, Static4D region, Static2D center)
+  public long swirl(Data1D swirl, Data2D center, Data4D region)
     {    
-    return mV.add(EffectNames.SWIRL, swirl, region, center);
-    }
- 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Rotate part of the Object around the Center of the Effect by 'degree' angle.
- *   
- * @param swirl    Angle of rotation. Unit: degrees.
- * @param region   Region that masks the effect of the Swirl.
- * @param center   2-dimensional Dynamic that, at any given time, returns a Point2D representing
- *                 the Center of the Effect.
- * @return         ID of the effect added, or -1 if we failed to add one.
- */
-  public long swirl(int swirl, Static4D region, Dynamic2D center)
-    {
-    Dynamic1D di = new Dynamic1D();
-    di.setCount(0.5f);
-    di.setDuration(0);
-    di.add(new Static1D(0));
-    di.add(new Static1D(swirl));
-    
-    return mV.add(EffectNames.SWIRL, di, region, center);
+    return mV.add(EffectNames.SWIRL, swirl, center, region);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
- * Rotate part of the Object around the Center of the Effect by 'degree' angle.
- * <p>
- * Here the Center stays constant.
- *    
- * @param swirl    Angle of rotation. Unit: degrees.
- * @param region   Region that masks the effect of the Swirl.
- * @param center   Center of the Effect.
- * @param duration Time, in milliseconds, it takes to do one full interpolation.
- * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
- * @return         ID of the effect added, or -1 if we failed to add one. 
- */
-  public long swirl(int swirl, Static4D region, Static2D center, int duration, float count)
-    {
-    Dynamic1D di = new Dynamic1D();
-    di.setCount(count);
-    di.setDuration(duration);
-    di.add(new Static1D(0));
-    di.add(new Static1D(swirl));
-    
-    return mV.add(EffectNames.SWIRL, di, region, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Rotate the whole Object around the Center of the Effect by 'degree' angle.
- * 
- * @param swirl    Angle of rotation. Unit: degrees.
- * @param center   Center of the Effect.
- * @param duration Time, in milliseconds, it takes to do one full interpolation.
- * @param count    Controls how many interpolations we want to do. See {@link Dynamic#setCount(float)}
- * @return         ID of the effect added, or -1 if we failed to add one. 
- */
-  public long swirl(int swirl, Static2D center, int duration, float count)
-    {
-    Dynamic1D di = new Dynamic1D();
-    di.setCount(count);
-    di.setDuration(duration);
-    di.add(new Static1D(0));
-    di.add(new Static1D(swirl));
-         
-    return mV.add(EffectNames.SWIRL, di, null, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Rotate the whole Object around the Center of the Effect by 'degree' angle.
- * <p>
- * Equivalent to calling the previous method with count=0.5.
- * 
- * @param swirl    Angle of rotation. Unit: degrees.
- * @param center   Center of the Effect.
- * @param duration Time, in milliseconds, it takes to do one full interpolation.
- * @return         ID of the effect added, or -1 if we failed to add one. 
- */
-  public long swirl(int swirl, Static2D center, int duration)
-    {
-    Dynamic1D di = new Dynamic1D();
-    di.setCount(0.5f);
-    di.setDuration(duration);
-    di.add(new Static1D(0));
-    di.add(new Static1D(swirl));
-        
-    return mV.add(EffectNames.SWIRL, di, null, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * Rotate the whole Object around the Center of the Effect by 'degree' angle.
- * <p>
- * Equivalent to calling the previous method with duration=0.
- * 
- * @param swirl  Angle of rotation. Unit: degrees.
- * @param center Center of the Effect.
- * @return       ID of the effect added, or -1 if we failed to add one. 
+ * Rotate the whole Object around the Center of the Effect by a certain angle.
+ *
+ * @param swirl  The degree of Swirl. Positive values swirl clockwise.
+ * @param center 2-dimensional Data that, at any given time, returns the Center of the Effect.
+ * @return       ID of the effect added, or -1 if we failed to add one.
  */
-  public long swirl(int swirl, Static2D center)
-    {
-    Dynamic1D di = new Dynamic1D();
-    di.setCount(0.5f);
-    di.setDuration(0);
-    di.add(new Static1D(0));
-    di.add(new Static1D(swirl));
-        
-    return mV.add(EffectNames.SWIRL, di, null, center);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// WAVE
-
+public long swirl(Data1D swirl, Data2D center)
+  {
+  return mV.add(EffectNames.SWIRL, swirl, center);
+  }
 }
diff --git a/src/main/java/org/distorted/library/EffectQueueVertex.java b/src/main/java/org/distorted/library/EffectQueueVertex.java
index 1e95bcd..35f482b 100644
--- a/src/main/java/org/distorted/library/EffectQueueVertex.java
+++ b/src/main/java/org/distorted/library/EffectQueueVertex.java
@@ -22,8 +22,15 @@ package org.distorted.library;
 import android.opengl.GLES20;
 
 import org.distorted.library.message.EffectMessage;
+import org.distorted.library.type.Data1D;
+import org.distorted.library.type.Data2D;
+import org.distorted.library.type.Data3D;
+import org.distorted.library.type.Data4D;
 import org.distorted.library.type.Dynamic;
+import org.distorted.library.type.Dynamic1D;
 import org.distorted.library.type.Dynamic2D;
+import org.distorted.library.type.Dynamic4D;
+import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static4D;
 
@@ -154,7 +161,7 @@ class EffectQueueVertex extends EffectQueue
   
 ///////////////////////////////////////////////////////////////////////////////////////////////////
   
-  synchronized long add(EffectNames eln, Dynamic inter, Static4D region, Dynamic2D point)
+  synchronized long add(EffectNames eln, Data3D data, Data2D center, Data4D region)
     {
     if( mMax[INDEX]>mNumEffects )
       {
@@ -171,7 +178,7 @@ class EffectQueueVertex extends EffectQueue
    
 ///////////////////////////////////////////////////////////////////////////////////////////////////
   
-  synchronized long add(EffectNames eln, Dynamic inter, Static4D region, Static2D point)
+  synchronized long add(EffectNames eln, Data3D data, Data2D center)
     {
     if( mMax[INDEX]>mNumEffects )
       {
@@ -182,7 +189,7 @@ class EffectQueueVertex extends EffectQueue
       mUniforms[NUM_UNIFORMS*mNumEffects+7] = point.getX()-mObjHalfX;
       mUniforms[NUM_UNIFORMS*mNumEffects+8] =-point.getY()+mObjHalfY;
      
-      return addPriv(eln,region);
+      return addPriv(eln,null);
       }
       
     return -1;
@@ -190,7 +197,7 @@ class EffectQueueVertex extends EffectQueue
  
 ///////////////////////////////////////////////////////////////////////////////////////////////////
   
-  synchronized long add(EffectNames eln, float v1, float v2, float v3, Static4D region, Static2D point)
+  synchronized long add(EffectNames eln, Data1D data, Data2D center, Data4D region)
     {
     if( mMax[INDEX]>mNumEffects )
       {
@@ -209,19 +216,55 @@ class EffectQueueVertex extends EffectQueue
       
     return -1;
     }
-  
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// sink, swirl
+
+  synchronized long add(EffectNames eln, Data1D data, Data2D center)
+    {
+    if( mMax[INDEX]>mNumEffects )
+      {
+      EffectNames.fillWithUnities(eln.ordinal(), mUniforms, NUM_UNIFORMS*mNumEffects);
+
+      if( data instanceof Dynamic1D)
+        mInterI[mNumEffects] = (Dynamic1D)data;
+      else if( data instanceof Static1D)
+        {
+        mInterI[mNumEffects] = null;
+        mUniforms[NUM_UNIFORMS*mNumEffects] = ((Static1D)data).getX();
+        }
+
+      mUniforms[NUM_UNIFORMS*mNumEffects+7] = point.getX()-mObjHalfX;
+      mUniforms[NUM_UNIFORMS*mNumEffects+8] =-point.getY()+mObjHalfY;
+
+      return addPriv(eln,null);
+      }
+
+    return -1;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
   
-  private long addPriv(EffectNames eln, Static4D region)
+  private long addPriv(EffectNames eln, Data4D region)
     {    
     if( region!=null )
       {
-      float z = region.getZ();
+      if( region instanceof Dynamic4D)
+        {
+        mInterP[mNumEffects] = (Dynamic4D)region;
+        }
+      else if ( region instanceof Static4D)
+        {
+        Static4D tmp = (Static4D)region;
+
+        float z = tmp.getZ();
 
-      mUniforms[NUM_UNIFORMS*mNumEffects+3] = region.getX();
-      mUniforms[NUM_UNIFORMS*mNumEffects+4] =-region.getY();   // invert y already
-      mUniforms[NUM_UNIFORMS*mNumEffects+5] = z<=0.0f ? 1000*mObjHalfX : z;
-      mUniforms[NUM_UNIFORMS*mNumEffects+6] = region.getW();
+        mUniforms[NUM_UNIFORMS*mNumEffects+3] = tmp.getX();
+        mUniforms[NUM_UNIFORMS*mNumEffects+4] =-tmp.getY();   // invert y already
+        mUniforms[NUM_UNIFORMS*mNumEffects+5] = z<=0.0f ? 1000*mObjHalfX : z;
+        mUniforms[NUM_UNIFORMS*mNumEffects+6] = tmp.getW();
+        }
+      else return -1;
       }
     else
       {
diff --git a/src/main/res/raw/main_vertex_shader.glsl b/src/main/res/raw/main_vertex_shader.glsl
index 74d937e..ffba582 100644
--- a/src/main/res/raw/main_vertex_shader.glsl
+++ b/src/main/res/raw/main_vertex_shader.glsl
@@ -44,7 +44,7 @@ uniform int vNumEffects;                  // total number of vertex effects
 uniform int vType[NUM_VERTEX];            // their types.
 uniform vec3 vUniforms[3*NUM_VERTEX];     // i-th effect is 3 consecutive vec3's: [3*i], [3*i+1], [3*i+2]. 
                                           // The first 3 floats are the Interpolated values,
-                                          // next 4 are the Region, next 2 are the Point. 
+                                          // next 4 are the Region, next 2 are the Center.
 #endif
 
 #if NUM_VERTEX>0
