commit 0e65f4dac8e96785ef2038536d6e4a6f2aa1d578
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed Dec 14 23:50:12 2022 +0100

    New Flat Blur unit test.

diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index 0e4ff7b..dfb8476 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -61,5 +61,6 @@
         <activity android:name=".deferredjob.DeferredJobActivity"/>
         <activity android:name=".singlemesh.SingleMeshActivity"/>
         <activity android:name=".meshfile.MeshFileActivity"/>
+        <activity android:name=".flatblur.FlatBlurActivity"/>
     </application>
 </manifest>
diff --git a/src/main/java/org/distorted/examples/TableOfContents.java b/src/main/java/org/distorted/examples/TableOfContents.java
index cbd6c5c..eca4f50 100644
--- a/src/main/java/org/distorted/examples/TableOfContents.java
+++ b/src/main/java/org/distorted/examples/TableOfContents.java
@@ -36,6 +36,7 @@ import android.widget.SimpleAdapter;
 
 import org.distorted.examples.deferredjob.DeferredJobActivity;
 import org.distorted.examples.monalisa.MonaLisaActivity;
+import org.distorted.examples.flatblur.FlatBlurActivity;
 import org.distorted.examples.sink.SinkActivity;
 import org.distorted.examples.projection.ProjectionActivity;
 import org.distorted.examples.deform.DeformActivity;
@@ -86,9 +87,6 @@ public class TableOfContents extends ListActivity
 
   private enum Application
     {
-    MESHFILE          (R.drawable.icon_example_meshfile        , R.string.example_meshfile           , R.string.example_meshfile_subtitle           ,            MeshFileActivity.class),
-
-
     MONALISA          (R.drawable.icon_example_monalisa        , R.string.example_monalisa        , R.string.example_monalisa_subtitle        ,         MonaLisaActivity.class),
     SINK              (R.drawable.icon_example_sink            , R.string.example_sink            , R.string.example_sink_subtitle            ,             SinkActivity.class),
     BEAN              (R.drawable.icon_example_bean            , R.string.example_bean            , R.string.example_bean_subtitle            ,             BeanActivity.class),
@@ -129,6 +127,9 @@ public class TableOfContents extends ListActivity
     PREDEFORM         (R.drawable.icon_example_predeform       , R.string.example_predeform           , R.string.example_predeform_subtitle           ,            PredeformActivity.class),
     DEFERREDJOB       (R.drawable.icon_example_deferredjob     , R.string.example_deferredjob           , R.string.example_deferredjob_subtitle           ,            DeferredJobActivity.class),
     SINGLEMESH        (R.drawable.icon_example_singlemesh      , R.string.example_singlemesh           , R.string.example_singlemesh_subtitle           ,            SingleMeshActivity.class),
+    MESHFILE          (R.drawable.icon_example_meshfile        , R.string.example_meshfile           , R.string.example_meshfile_subtitle           ,            MeshFileActivity.class),
+    FLATBLUR          (R.drawable.icon_example_flatblur        , R.string.example_flatblur         , R.string.example_flatblur_subtitle         , FlatBlurActivity.class ),
+
     ;
 
     final int icon, title, subtitle;
diff --git a/src/main/java/org/distorted/examples/flatblur/FlatBlurActivity.java b/src/main/java/org/distorted/examples/flatblur/FlatBlurActivity.java
new file mode 100644
index 0000000..15f1946
--- /dev/null
+++ b/src/main/java/org/distorted/examples/flatblur/FlatBlurActivity.java
@@ -0,0 +1,106 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.flatblur;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.SeekBar;
+
+import org.distorted.examples.R;
+import org.distorted.library.main.DistortedLibrary;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class FlatBlurActivity extends Activity implements SeekBar.OnSeekBarChangeListener
+{
+    @Override
+    protected void onCreate(Bundle savedState) 
+      {
+      super.onCreate(savedState);
+      DistortedLibrary.onCreate();
+      setContentView(R.layout.flatblurlayout);
+
+      SeekBar barSize  = findViewById(R.id.flatblurBlurStrength);
+      barSize.setOnSeekBarChangeListener(this);
+      barSize.setProgress(0);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      super.onPause();
+      GLSurfaceView view = findViewById(R.id.flatblurSurfaceView);
+      view.onPause();
+      DistortedLibrary.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      GLSurfaceView view = findViewById(R.id.flatblurSurfaceView);
+      view.onResume();
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      DistortedLibrary.onDestroy();
+      super.onDestroy();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void enableBlur(View view)
+      {
+      CheckBox box = (CheckBox)view;
+      boolean checked = box.isChecked();
+
+      FlatBlurSurfaceView v = findViewById(R.id.flatblurSurfaceView);
+      FlatBlurRenderer renderer = v.getRenderer();
+      renderer.enableBlur(!checked);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void onProgressChanged(SeekBar bar, int progress, boolean fromUser)
+    {
+    FlatBlurSurfaceView v = findViewById(R.id.flatblurSurfaceView);
+    FlatBlurRenderer renderer = v.getRenderer();
+    renderer.setBlurStrength(progress);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void onStartTrackingTouch(SeekBar bar) { }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void onStopTrackingTouch(SeekBar bar)  { }
+}
diff --git a/src/main/java/org/distorted/examples/flatblur/FlatBlurRenderer.java b/src/main/java/org/distorted/examples/flatblur/FlatBlurRenderer.java
new file mode 100644
index 0000000..6203c31
--- /dev/null
+++ b/src/main/java/org/distorted/examples/flatblur/FlatBlurRenderer.java
@@ -0,0 +1,138 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.flatblur;
+
+import android.opengl.GLSurfaceView;
+
+import org.distorted.library.effect.EffectQuality;
+import org.distorted.library.effect.MatrixEffectMove;
+import org.distorted.library.effect.MatrixEffectScale;
+import org.distorted.library.effect.PostprocessEffectBlur;
+import org.distorted.library.main.DistortedEffects;
+import org.distorted.library.main.DistortedLibrary;
+import org.distorted.library.main.DistortedNode;
+import org.distorted.library.main.DistortedScreen;
+import org.distorted.library.main.DistortedTexture;
+import org.distorted.library.mesh.MeshQuad;
+import org.distorted.library.type.Static2D;
+import org.distorted.library.type.Static3D;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class FlatBlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
+{
+    private static final int HALO = 15;
+
+    private final GLSurfaceView mView;
+    private final DistortedScreen mScreen;
+    private final PostprocessEffectBlur mBlur;
+    private final DistortedNode mRedNode;
+    private final Static2D mBlurStrength;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    FlatBlurRenderer(GLSurfaceView v)
+      {
+      mView = v;
+      mScreen = new DistortedScreen();
+
+      int x = 50;
+      int scale = 200;
+      mRedNode = createNode(-x,0,1,scale,0xffff0000);
+      DistortedNode whiteNode = createNode(x,0,1,scale,0xffffffff);
+
+      mScreen.attach(mRedNode);
+      mScreen.attach(whiteNode);
+
+      mBlurStrength = new Static2D(HALO,0);
+      mBlur = new PostprocessEffectBlur(mBlurStrength);
+      mBlur.setQuality(EffectQuality.MEDIUM);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private DistortedNode createNode(int x, int y, int z, int scale, int color)
+      {
+      DistortedTexture texture = new DistortedTexture();
+      texture.setColorARGB(color);
+      MeshQuad mesh = new MeshQuad();
+      DistortedEffects effects = new DistortedEffects();
+
+      Static3D move = new Static3D(x,y,z);
+
+      MatrixEffectMove mainMove  = new MatrixEffectMove(move);
+      MatrixEffectScale mainScale= new MatrixEffectScale(scale);
+
+      effects.apply(mainScale);
+      effects.apply(mainMove);
+
+      return new DistortedNode(texture,effects,mesh);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      mScreen.render(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void onSurfaceChanged(GL10 glUnused, int width, int height)
+      {
+      mScreen.resize(width,height);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {
+      PostprocessEffectBlur.enable();
+      DistortedLibrary.onSurfaceCreated( mView.getContext(), this);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void distortedException(Exception ex)
+      {
+      android.util.Log.e("SetTexture", ex.getMessage() );
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void enableBlur(boolean enable)
+      {
+      DistortedEffects effects = mRedNode.getEffects();
+      long id = mBlur.getID();
+
+      if( enable ) effects.abortById(id);
+      else         effects.apply(mBlur);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void setBlurStrength(int strength)
+      {
+      mBlurStrength.set(HALO,strength*0.5f);
+      }
+}
diff --git a/src/main/java/org/distorted/examples/flatblur/FlatBlurSurfaceView.java b/src/main/java/org/distorted/examples/flatblur/FlatBlurSurfaceView.java
new file mode 100644
index 0000000..45f52b4
--- /dev/null
+++ b/src/main/java/org/distorted/examples/flatblur/FlatBlurSurfaceView.java
@@ -0,0 +1,61 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.flatblur;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ConfigurationInfo;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.widget.Toast;
+
+import org.distorted.examples.R;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class FlatBlurSurfaceView extends GLSurfaceView
+{
+    private FlatBlurRenderer mRenderer;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public FlatBlurSurfaceView(Context context, AttributeSet attrs)
+      {
+      super(context, attrs);
+
+      if(!isInEditMode())
+        {
+        mRenderer = new FlatBlurRenderer(this);
+        final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
+        setEGLContextClientVersion( (configurationInfo.reqGlEsVersion>>16) >= 3 ? 3:2 );
+        setRenderer(mRenderer);
+        Toast.makeText(context, R.string.example_rotate_toast , Toast.LENGTH_SHORT).show();
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public FlatBlurRenderer getRenderer()
+      {
+      return mRenderer;
+      }
+}
+
diff --git a/src/main/res/drawable-hdpi/icon_example_flatblur.png b/src/main/res/drawable-hdpi/icon_example_flatblur.png
new file mode 100644
index 0000000..fb3a612
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_flatblur.png differ
diff --git a/src/main/res/layout/flatblurlayout.xml b/src/main/res/layout/flatblurlayout.xml
new file mode 100644
index 0000000..528132c
--- /dev/null
+++ b/src/main/res/layout/flatblurlayout.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+
+    <org.distorted.examples.flatblur.FlatBlurSurfaceView
+        android:id="@+id/flatblurSurfaceView"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center">
+
+        <CheckBox
+                android:id="@+id/flatblurEnableBlur"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:onClick="enableBlur"
+                android:checked="false"/>
+
+        <SeekBar
+                android:id="@+id/flatblurBlurStrength"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="2"
+                android:layout_gravity="center_vertical"
+                android:layout_margin="5dp"/>
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 22fa91c..fc62ce7 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -215,6 +215,8 @@
     <string name="example_singlemesh_subtitle">Use the new MeshJoined + MeshBase.apply() to create a single, movable Mesh representing a 2x2x2 RubikCube.</string>
     <string name="example_meshfile">Mesh from File</string>
     <string name="example_meshfile_subtitle">Explore Distorted\'s own Mesh format, dmesh. Open .dmesh files and explore their contents.</string>
+    <string name="example_flatblur">Flat Blur</string>
+    <string name="example_flatblur_subtitle">Unit test to see two partially obstructing flat objects, one of them blurred.</string>
 
     <string name="example_movingeffects_toast">Click on \'RESET\' and define your path by touching the screen. Then click on one of the effects and see it move along your path.</string>
     <string name="example_rotate_toast">Rotate the scene by swiping the screen</string>
