commit 296d2e73d2256ad4f46ba6338da9137e8833240c
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Tue Jan 1 01:36:33 2019 +0000

    Advances with the Earth app - prepare it to checking if any FRAGMENT or VERTEX effect correctly works on a Sphere mesh.

diff --git a/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRendererPicker.java b/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRendererPicker.java
index 8188962..0ee5668 100644
--- a/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRendererPicker.java
+++ b/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRendererPicker.java
@@ -103,7 +103,8 @@ class AroundTheWorldRendererPicker implements GLSurfaceView.Renderer
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-	@Override public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+	@Override
+	public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
 	  {
 		GLES31.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
 
@@ -220,7 +221,8 @@ class AroundTheWorldRendererPicker implements GLSurfaceView.Renderer
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-	@Override public void onSurfaceChanged(GL10 glUnused, int width, int height)
+	@Override
+  public void onSurfaceChanged(GL10 glUnused, int width, int height)
 	  {
 	  mHeight = height;
 	  mWidth  = width;
@@ -241,7 +243,8 @@ class AroundTheWorldRendererPicker implements GLSurfaceView.Renderer
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-	@Override public void onDrawFrame(GL10 glUnused)
+	@Override
+  public void onDrawFrame(GL10 glUnused)
 	  {
 		GLES31.glClear(GLES31.GL_DEPTH_BUFFER_BIT | GLES31.GL_COLOR_BUFFER_BIT);
     GLES31.glUniformMatrix4fv(mMVPMatrixH, 1, false, mMVPTriangleMatrix, 0);
diff --git a/src/main/java/org/distorted/examples/earth/EarthActivity.java b/src/main/java/org/distorted/examples/earth/EarthActivity.java
index b2f085e..0adb40e 100644
--- a/src/main/java/org/distorted/examples/earth/EarthActivity.java
+++ b/src/main/java/org/distorted/examples/earth/EarthActivity.java
@@ -22,31 +22,33 @@ package org.distorted.examples.earth;
 import android.app.Activity;
 import android.opengl.GLSurfaceView;
 import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
 import android.widget.SeekBar;
+import android.widget.Spinner;
 
 import org.distorted.examples.R;
+import org.distorted.library.effect.EffectName;
+import org.distorted.library.effect.EffectType;
 import org.distorted.library.main.Distorted;
-import org.distorted.library.main.DistortedTexture;
-import org.distorted.library.mesh.MeshBase;
-import org.distorted.library.mesh.MeshSphere;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-public class EarthActivity extends Activity implements SeekBar.OnSeekBarChangeListener
+public class EarthActivity extends Activity implements SeekBar.OnSeekBarChangeListener, AdapterView.OnItemSelectedListener
 {
-    private static final int SIZE = 100;
-    private static final int LEVEL=  32;
-
-    private DistortedTexture mTexture;
-    private MeshBase mMesh;
+    private EffectName[] mEffectNames;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-    
+
     @Override
     protected void onPause() 
       {
-      GLSurfaceView mView = this.findViewById(R.id.earthSurfaceView);
-      if( mView!=null ) mView.onPause();
+      GLSurfaceView view = this.findViewById(R.id.earthSurfaceView);
+      if( view!=null ) view.onPause();
+
+      EarthSurfaceViewPicker pick = this.findViewById(R.id.earthSurfaceViewPicker);
+      if( pick!=null ) pick.onPause();
 
       Distorted.onPause();
       super.onPause();
@@ -59,8 +61,11 @@ public class EarthActivity extends Activity implements SeekBar.OnSeekBarChangeLi
       {
       super.onResume();
       
-      GLSurfaceView mView = this.findViewById(R.id.earthSurfaceView);
-      if( mView!=null ) mView.onResume();  
+      GLSurfaceView view = this.findViewById(R.id.earthSurfaceView);
+      if( view!=null ) view.onResume();
+
+      EarthSurfaceViewPicker pick = this.findViewById(R.id.earthSurfaceViewPicker);
+      if( pick!=null ) pick.onResume();
       }
     
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -79,14 +84,41 @@ public class EarthActivity extends Activity implements SeekBar.OnSeekBarChangeLi
       {
       super.onCreate(savedState);
 
-      mMesh = new MeshSphere(LEVEL);
-      mTexture= new DistortedTexture(SIZE,SIZE);
-
       setContentView(R.layout.earthlayout);
 
       SeekBar levelBar = findViewById(R.id.earthInflateLevel);
       levelBar.setOnSeekBarChangeListener(this);
       levelBar.setProgress(50);
+
+      Spinner renderSpinner  = findViewById(R.id.earthSpinnerEffect);
+      renderSpinner.setOnItemSelectedListener(this);
+
+      ArrayAdapter<String> adapterBitmap = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, createEffectNames() );
+      adapterBitmap.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+      renderSpinner.setAdapter(adapterBitmap);
+      }
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public void onSaveInstanceState(Bundle savedInstanceState)
+      {
+      super.onSaveInstanceState(savedInstanceState);
+
+      EarthSurfaceViewPicker pick = this.findViewById(R.id.earthSurfaceViewPicker);
+      pick.save(savedInstanceState);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public void onRestoreInstanceState(Bundle savedInstanceState)
+      {
+      super.onRestoreInstanceState(savedInstanceState);
+
+      EarthSurfaceViewPicker pick = this.findViewById(R.id.earthSurfaceViewPicker);
+      pick.restore(savedInstanceState);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -111,15 +143,72 @@ public class EarthActivity extends Activity implements SeekBar.OnSeekBarChangeLi
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public DistortedTexture getTexture()
+    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id)
       {
-      return mTexture;
+      EarthSurfaceViewPicker mPick = this.findViewById(R.id.earthSurfaceViewPicker);
+      mPick.setEffectMode(mEffectNames[pos]);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public MeshBase getMesh()
+    public void onNothingSelected(AdapterView<?> parent) { }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void Remove(View v)
       {
-      return mMesh;
+      EarthSurfaceViewPicker mPick = this.findViewById(R.id.earthSurfaceViewPicker);
+      mPick.clearPoints();
+
+      EarthSurfaceView view = this.findViewById(R.id.earthSurfaceView);
+      EarthRenderer renderer = view.getRenderer();
+
+      renderer.removeAll();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    void addNewPoint(float x, float y, EffectName effect)
+      {
+      EarthSurfaceView view = this.findViewById(R.id.earthSurfaceView);
+      EarthRenderer renderer = view.getRenderer();
+
+      renderer.addNewPoint(x,y,effect);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private String[] createEffectNames()
+      {
+      EffectType type;
+      EffectName[] names = EffectName.values();
+
+      int numEffects=0;
+
+      for(int i=0; i<names.length; i++)
+        {
+        type = names[i].getType();
+        if (type == EffectType.FRAGMENT || type == EffectType.VERTEX) numEffects++;
+        }
+
+      mEffectNames = new EffectName[numEffects];
+      String[] effectStrings = new String[numEffects];
+
+      numEffects=0;
+
+      for(int i=0; i<names.length; i++)
+        {
+        type = names[i].getType();
+
+        if (type == EffectType.FRAGMENT || type == EffectType.VERTEX)
+          {
+          mEffectNames[numEffects]  = names[i];
+          effectStrings[numEffects] = names[i].name();
+
+          numEffects++;
+          }
+        }
+
+      return effectStrings;
       }
 }
diff --git a/src/main/java/org/distorted/examples/earth/EarthRenderer.java b/src/main/java/org/distorted/examples/earth/EarthRenderer.java
index 67b338a..6cc5073 100644
--- a/src/main/java/org/distorted/examples/earth/EarthRenderer.java
+++ b/src/main/java/org/distorted/examples/earth/EarthRenderer.java
@@ -24,6 +24,8 @@ import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
 
 import org.distorted.examples.R;
+import org.distorted.library.effect.EffectName;
+import org.distorted.library.effect.EffectType;
 import org.distorted.library.effect.MatrixEffectMove;
 import org.distorted.library.effect.MatrixEffectQuaternion;
 import org.distorted.library.effect.MatrixEffectScale;
@@ -32,6 +34,7 @@ import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedScreen;
 import org.distorted.library.main.DistortedTexture;
 import org.distorted.library.mesh.MeshBase;
+import org.distorted.library.mesh.MeshSphere;
 import org.distorted.library.type.DynamicQuat;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
@@ -46,8 +49,10 @@ import javax.microedition.khronos.opengles.GL10;
 
 class EarthRenderer implements GLSurfaceView.Renderer
 {
-    private static final float FOV = 30.0f;
-    private static final float NEAR = 0.1f;
+    private static final int   SIZE =   100;
+    private static final int   LEVEL=    32;
+    private static final float FOV  = 30.0f;
+    private static final float NEAR =  0.1f;
 
     private GLSurfaceView mView;
     private DistortedTexture mTexture;
@@ -70,10 +75,8 @@ class EarthRenderer implements GLSurfaceView.Renderer
       mScale= new Static3D(1,1,1);
       mCenter=new Static3D(0,0,0);
 
-      EarthActivity act = (EarthActivity)v.getContext();
-
-      mTexture = act.getTexture();
-      mMesh    = act.getMesh();
+      mMesh   = new MeshSphere(LEVEL);
+      mTexture= new DistortedTexture(SIZE,SIZE);
 
       mObjWidth = mTexture.getWidth();
       mObjHeight= mTexture.getHeight();
@@ -127,6 +130,21 @@ class EarthRenderer implements GLSurfaceView.Renderer
       mMesh.setInflate(inflateLevel);
       }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    void addNewPoint(float x, float y, EffectName effect)
+      {
+
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    void removeAll()
+      {
+      mEffects.abortByType(EffectType.VERTEX);
+      mEffects.abortByType(EffectType.FRAGMENT);
+      }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
     public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
diff --git a/src/main/java/org/distorted/examples/earth/EarthSurfaceViewPicker.java b/src/main/java/org/distorted/examples/earth/EarthSurfaceViewPicker.java
new file mode 100644
index 0000000..a58167e
--- /dev/null
+++ b/src/main/java/org/distorted/examples/earth/EarthSurfaceViewPicker.java
@@ -0,0 +1,319 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2016 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.examples.earth;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import org.distorted.examples.R;
+import org.distorted.library.effect.EffectName;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class EarthSurfaceViewPicker extends SurfaceView implements SurfaceHolder.Callback
+{
+    private static final int FRAME_INTERVAL = 70;
+    private static final int MULTIPLIER   = 1000;
+
+    private static boolean refreshScreen = true;
+    private GraphicsThread mThread;
+    private EffectName mCurrentEffect;
+    private ArrayList<Integer> mPointsX, mPointsY, mPointsE;
+    private WeakReference<EarthActivity> mAct;
+    private int mRadius;
+    private Bitmap mBitmap;
+    private Paint mPointPaint;
+    private Rect mDst;
+    private int mWidth, mHeight;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+    private class GraphicsThread extends Thread
+      {
+      private final SurfaceHolder mSurfaceHolder;
+      private final EarthSurfaceViewPicker mPicker;
+      private boolean mRun = false;
+
+      ///////////////////////////////////////////////////////////////////////////////////////
+
+      GraphicsThread(SurfaceHolder surfaceHolder, EarthSurfaceViewPicker p)
+        {
+        mSurfaceHolder = surfaceHolder;
+        mPicker = p;
+        }
+
+      ///////////////////////////////////////////////////////////////////////////////////////
+
+      void setRunning(boolean run)
+        {
+        mRun = run;
+        }
+
+      ///////////////////////////////////////////////////////////////////////////////////////
+
+      public void run()
+        {
+        Canvas c;
+        long time;
+
+        while (mRun)
+          {
+          c = null;
+          time = 0;
+
+          if( refreshScreen )
+            {
+            refreshScreen=false;
+            time = System.currentTimeMillis();
+
+            try
+              {
+              c = mSurfaceHolder.lockCanvas(null);
+              synchronized (mSurfaceHolder) { mPicker.render(c); }
+              }
+            finally
+              {
+              if (c != null)  mSurfaceHolder.unlockCanvasAndPost(c);
+              }
+
+            time = System.currentTimeMillis() -time;
+            }
+
+          if( time<FRAME_INTERVAL )
+            {
+            try { Thread.sleep(FRAME_INTERVAL-time); }
+            catch(InterruptedException ex) {}
+            }
+          }
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public EarthSurfaceViewPicker(Context context, AttributeSet attrs)
+      {
+      super(context,attrs);
+
+      InputStream is = context.getResources().openRawResource(R.raw.world);
+
+      try
+        {
+        mBitmap = BitmapFactory.decodeStream(is);
+        }
+      finally
+        {
+        try
+          {
+          is.close();
+          }
+        catch(IOException e) { }
+        }
+
+      EarthActivity act = (EarthActivity)context;
+      mAct = new WeakReference<>(act);
+
+      mDst = new Rect();
+      mPointsX = new ArrayList<>();
+      mPointsY = new ArrayList<>();
+      mPointsE = new ArrayList<>();
+
+      mPointPaint = new Paint();
+      mPointPaint.setARGB(255,0,0,0);
+
+      getHolder().addCallback(this);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void stopThread()
+      {
+      if( mThread!=null )
+        {
+        boolean retry = true;
+        mThread.setRunning(false);
+
+        while (retry)
+          {
+          try
+            {
+            mThread.join();
+            retry = false;
+            }
+          catch (InterruptedException e) { android.util.Log.e( "EarthPicker", "Joining thread interrupted!"); }
+          }
+
+        mThread=null;
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    void setEffectMode(EffectName effect)
+      {
+      mCurrentEffect = effect;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void addNewPoint(int x, int y)
+      {
+      float xf = (float)x/mWidth;
+      float yf = (float)y/mHeight;
+
+      mPointsX.add( (int)(MULTIPLIER*xf) );
+      mPointsY.add( (int)(MULTIPLIER*yf) );
+      mPointsE.add(mCurrentEffect.ordinal());
+
+      mAct.get().addNewPoint(xf,yf,mCurrentEffect);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    void save(Bundle bundle)
+      {
+      bundle.putIntegerArrayList("x", mPointsX);
+      bundle.putIntegerArrayList("y", mPointsY);
+      bundle.putIntegerArrayList("e", mPointsE);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    void restore(Bundle bundle)
+      {
+      mPointsX = bundle.getIntegerArrayList("x");
+      mPointsY = bundle.getIntegerArrayList("y");
+      mPointsE = bundle.getIntegerArrayList("e");
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    void clearPoints()
+      {
+      mPointsX.clear();
+      mPointsY.clear();
+      mPointsE.clear();
+
+      refreshScreen = true;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void render(Canvas c)
+      {
+      if( c!=null )
+        {
+        c.drawBitmap(mBitmap, null, mDst, null);
+
+        int x,y,size = mPointsX.size();
+
+        for(int point=0; point<size; point++)
+          {
+          x = (int)(((float)mPointsX.get(point)/MULTIPLIER)*mWidth );
+          y = (int)(((float)mPointsY.get(point)/MULTIPLIER)*mHeight);
+
+          c.drawCircle( x, y, mRadius, mPointPaint);
+          }
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    void onPause()
+      {
+      if( mThread!=null ) mThread.setRunning(false);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    void onResume()
+      {
+      if( mThread!=null ) mThread.setRunning(true);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
+      {
+      mWidth = width;
+      mHeight= height;
+
+      mDst.bottom = height;
+      mDst.right  = width;
+      mDst.left   = 0;
+      mDst.top    = 0;
+
+      mRadius = (width+height)/60;
+
+      refreshScreen = true;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public void surfaceCreated(SurfaceHolder holder)
+      {
+      mThread = new GraphicsThread(getHolder(), this);
+      mThread.setRunning(true);
+      mThread.start();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder)
+      {
+      stopThread();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event)
+      {
+      int action = event.getAction();
+      int x = (int)event.getX();
+      int y = (int)event.getY();
+           
+      switch(action)
+         {
+         case MotionEvent.ACTION_DOWN: addNewPoint(x,y);
+                                       refreshScreen = true;
+                                       break;
+         }
+             
+      return true;
+      }
+}
+
diff --git a/src/main/java/org/distorted/examples/inflate/InflateActivity2.java b/src/main/java/org/distorted/examples/inflate/InflateActivity2.java
index 24df472..b3568a8 100644
--- a/src/main/java/org/distorted/examples/inflate/InflateActivity2.java
+++ b/src/main/java/org/distorted/examples/inflate/InflateActivity2.java
@@ -108,14 +108,10 @@ public class InflateActivity2 extends Activity implements SeekBar.OnSeekBarChang
 
       switch(objectType)
         {
-        case 0: mMesh = new MeshCubes(mNumCols, str, mNumSlic);
-          break;
-        case 1: mMesh = new MeshFlat(mNumCols,mNumRows);
-          break;
-        case 2: mMesh = new MeshSphere(mNumRows);
-          break;
-        case 3: mMesh = new MeshQuad();
-          break;
+        case 0: mMesh = new MeshCubes(mNumCols, str, mNumSlic); break;
+        case 1: mMesh = new MeshFlat(mNumCols,mNumRows)       ; break;
+        case 2: mMesh = new MeshSphere(mNumRows)              ; break;
+        case 3: mMesh = new MeshQuad()                        ; break;
         }
 
       mTexture = new DistortedTexture(mNumCols,mNumRows);
diff --git a/src/main/res/layout/earthlayout.xml b/src/main/res/layout/earthlayout.xml
index 8f70ce6..b543da1 100644
--- a/src/main/res/layout/earthlayout.xml
+++ b/src/main/res/layout/earthlayout.xml
@@ -9,7 +9,7 @@
         android:id="@+id/earthSurfaceView"
         android:layout_width="match_parent"
         android:layout_height="0dp"
-        android:layout_weight="1.00" />
+        android:layout_weight="0.60" />
 
     <LinearLayout
         android:id="@+id/linearLayout"
@@ -28,4 +28,34 @@
 
     </LinearLayout>
 
+    <org.distorted.examples.earth.EarthSurfaceViewPicker
+        android:id="@+id/earthSurfaceViewPicker"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="0.40" />
+
+    <LinearLayout
+        android:id="@+id/linearLayout2"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center|fill_horizontal"
+        android:orientation="horizontal"
+        android:background="@color/blue">
+
+        <Button
+            android:id="@+id/button"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="0.3"
+            android:onClick="Remove"
+            android:text="@string/removebut" />
+
+        <Spinner
+            android:layout_width="0dp"
+            android:layout_height="50dp"
+            android:layout_weight="0.7"
+            android:id="@+id/earthSpinnerEffect" />
+
+    </LinearLayout>
+
 </LinearLayout>
