commit 8feb68c2f1ace952c1cb5d599658f5dc330eb392
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon Nov 14 13:53:22 2022 +0100

    Progress with Win effect + stars

diff --git a/src/main/java/org/distorted/objects/RubikObjectList.java b/src/main/java/org/distorted/objects/RubikObjectList.java
index 7dc91015..b6fde42f 100644
--- a/src/main/java/org/distorted/objects/RubikObjectList.java
+++ b/src/main/java/org/distorted/objects/RubikObjectList.java
@@ -151,7 +151,7 @@ public class RubikObjectList
 
   public static int computeNumStars(int level)
     {
-    return level>=LEVELS_SHOWN ? 50 : level+1;
+    return level>=LEVELS_SHOWN ? 50 : level;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/overlays/OverlayStars.java b/src/main/java/org/distorted/overlays/OverlayStars.java
index 39b75595..e09f2308 100644
--- a/src/main/java/org/distorted/overlays/OverlayStars.java
+++ b/src/main/java/org/distorted/overlays/OverlayStars.java
@@ -12,9 +12,14 @@ package org.distorted.overlays;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
 
+import org.distorted.library.effect.EffectQuality;
+import org.distorted.library.effect.MatrixEffectMove;
+import org.distorted.library.effect.MatrixEffectScale;
+import org.distorted.library.effect.PostprocessEffectGlow;
 import org.distorted.library.effect.VertexEffectMove;
-import org.distorted.library.effect.VertexEffectRotate;
 import org.distorted.library.effect.VertexEffectScale;
 import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedNode;
@@ -24,10 +29,13 @@ import org.distorted.library.main.InternalOutputSurface;
 import org.distorted.library.mesh.MeshJoined;
 import org.distorted.library.mesh.MeshQuad;
 import org.distorted.library.message.EffectListener;
-import org.distorted.library.type.Dynamic1D;
+import org.distorted.library.type.Dynamic;
+import org.distorted.library.type.Dynamic2D;
 import org.distorted.library.type.Dynamic3D;
-import org.distorted.library.type.Static1D;
+import org.distorted.library.type.Dynamic4D;
+import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
+import org.distorted.library.type.Static4D;
 import org.distorted.main.R;
 
 import java.util.Random;
@@ -36,54 +44,71 @@ import java.util.Random;
 
 public class OverlayStars extends OverlayGeneric implements EffectListener
 {
-   private static final int DUR_ALL = 10000;
-   private static final int DUR_MOV =  5000;
+   private static final int DUR_MOV =  4000;
+   private static final int DUR_GLO =  2000;
+
+   private static final int[] colors = new int[] {0,0,1,  1,0,1,  1,0,0,  1,1,0,  0,1,0,  1,1,1}; // blue, pink, red, yellow, green, white
+   private static final int INDEX = 5;
 
    private ListenerOverlay mListener;
-   private DistortedNode mNode;
+   private DistortedNode mStarsNode, mCountNode;
    private DistortedScreen mScreen;
-   private final Static3D mPointE = new Static3D(0,0,2);
+   private DistortedTexture mStarsTexture, mCountTexture;
+   private Bitmap mCountBitmap;
+   private Canvas mCountCanvas;
+   private Paint mPaint;
+   private int mBmpW, mBmpH;
    private float mWidth, mHeight;
    private Random mRandom;
+   private long mMoveID, mGlowID;
+   private int mTotalStars, mNewStars;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    private Dynamic3D createRandomMove()
       {
       Dynamic3D move = new Dynamic3D();
+      move.setMode(Dynamic.MODE_PATH);
       move.setDuration(DUR_MOV);
       move.setCount(0.5f);
 
-      float widthS = (mRandom.nextFloat()-0.5f)*mWidth;
+      float widthS = (mRandom.nextFloat()-0.5f)*mWidth*1.10f;
       float widthM = widthS + (mRandom.nextFloat()-0.5f)*mWidth*0.2f;
+      float heighS = mRandom.nextFloat()*mHeight*0.2f;
+      float heighM = (mRandom.nextFloat()-0.5f)*mHeight*0.2f;
 
-      Static3D pointS = new Static3D(widthS,mHeight/2,2);
-      Static3D pointM = new Static3D(widthM,mHeight/4,2);
+      Static3D pointS = new Static3D(widthS,mHeight*0.55f+heighS,0);
+      Static3D pointM = new Static3D(widthM,mHeight*0.25f+heighM,0);
+      Static3D pointE = new Static3D(0,0,0);
 
       move.add(pointS);
       move.add(pointM);
-      move.add(mPointE);
+      move.add(pointE);
 
       return move;
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-   private DistortedNode createNode(Resources res, int totS, int newS)
+   private DistortedNode createStarsNode(Resources res)
       {
       // texture /////////////////////////////////////////////////////
-      Bitmap bmp = BitmapFactory.decodeResource(res, R.drawable.star);
-      DistortedTexture texture = new DistortedTexture();
-      texture.setTexture(bmp);
+      if( mStarsTexture==null )
+         {
+         mStarsTexture = new DistortedTexture();
+         Bitmap star = BitmapFactory.decodeResource(res, R.drawable.star);
+         mBmpW = star.getWidth();
+         mBmpH = star.getHeight();
+         mStarsTexture.setTexture(star);
+         }
 
       // mesh ////////////////////////////////////////////////////////
+      MeshQuad[] mesh = new MeshQuad[mNewStars+1];
 
-      MeshQuad[] mesh = new MeshQuad[newS+1];
-
-      for(int i=0; i<newS+1; i++)
+      for(int i=0; i<mNewStars+1; i++)
          {
          mesh[i] = new MeshQuad();
-         mesh[i].setEffectAssociation(0,(i==0?0:1),i);
+         mesh[i].setEffectAssociation(0,(i>=mNewStars?2:1),i);
          }
 
       MeshJoined wholeMesh = new MeshJoined(mesh);
@@ -91,47 +116,86 @@ public class OverlayStars extends OverlayGeneric implements EffectListener
       // effects: main ///////////////////////////////////////////////
       DistortedEffects effects = new DistortedEffects();
 
-      float scaleM = mWidth*0.3f;
-      float scaleP = mWidth*0.1f;
-
-      Static3D moveM    = new Static3D(0,0,1);
-      Static1D point0   = new Static1D(0);
-      Static1D point360 = new Static1D(360);
-      Dynamic1D angle   = new Dynamic1D();
-      angle.add(point0);
-      angle.add(point360);
-      angle.setCount(0.5f);
-      angle.setDuration(DUR_ALL);
-      Static3D axis = new Static3D(0,0,1);
-      Static3D center = new Static3D(0,0,0);
+      float scaleM  = mWidth*0.40f;
+      float scaleP  = mWidth*0.15f;
+      Static3D moveM= new Static3D(0,0,1);
 
       VertexEffectMove mainMove     = new VertexEffectMove(moveM);
       VertexEffectScale mainScale   = new VertexEffectScale(scaleM);
-      VertexEffectRotate mainRotate = new VertexEffectRotate(angle,axis,center);
-      mainMove.setMeshAssociation(2,0);
-      mainScale.setMeshAssociation(2,0);
-      mainRotate.setMeshAssociation(2,0);
-      mainRotate.notifyWhenFinished(this);
+      mainMove.setMeshAssociation(2,-1);
+      mainScale.setMeshAssociation(2,-1);
 
       // effects: moving stars ///////////////////////////////////////
       VertexEffectScale scaleE = new VertexEffectScale(scaleP);
       scaleE.setMeshAssociation(1,-1);
       effects.apply(scaleE);
 
-      for(int i=1; i<newS+1; i++)
+      for(int i=0; i<mNewStars; i++)
         {
         Dynamic3D moveP = createRandomMove();
         VertexEffectMove moveE= new VertexEffectMove(moveP);
-        moveE.setMeshAssociation(2,i);
+        moveE.setMeshAssociation(0,i);
         effects.apply(moveE);
+
+        if( i==0 )
+           {
+           mMoveID = moveE.getID();
+           moveE.notifyWhenFinished(this);
+           }
         }
 
       // main effect queue ///////////////////////////////////////////
       effects.apply(mainMove);
       effects.apply(mainScale);
-      effects.apply(mainRotate);
 
-      return new DistortedNode(texture,effects,wholeMesh);
+      return new DistortedNode(mStarsTexture,effects,wholeMesh);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   private void renderStars(int numStars)
+      {
+      String txt = ""+numStars;
+      mCountCanvas.drawText(txt,mBmpW*0.5f,mBmpH*0.64f,mPaint);
+      mCountTexture.setTexture(mCountBitmap);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   private DistortedNode createCountNode()
+      {
+      // texture /////////////////////////////////////////////////////
+      if( mCountTexture==null )
+         {
+         mCountTexture = new DistortedTexture();
+
+         mCountBitmap = Bitmap.createBitmap(mBmpW,mBmpH,Bitmap.Config.ARGB_8888);
+         mCountCanvas = new Canvas(mCountBitmap);
+         mPaint = new Paint();
+         mPaint.setColor(0xff000000);
+         mPaint.setTextSize(mBmpH*0.28f);
+         mPaint.setAntiAlias(true);
+         mPaint.setTextAlign(Paint.Align.CENTER);
+         renderStars(mTotalStars);
+         }
+
+      // mesh ////////////////////////////////////////////////////////
+      MeshQuad mesh = new MeshQuad();
+
+      // effects: main ///////////////////////////////////////////////
+      DistortedEffects effects = new DistortedEffects();
+
+      float scaleM  = mWidth*0.40f;
+      Static3D moveM= new Static3D(0,0,1);
+
+      MatrixEffectMove mainMove  = new MatrixEffectMove(moveM);
+      MatrixEffectScale mainScale= new MatrixEffectScale(scaleM);
+
+      // main effect queue ///////////////////////////////////////////
+      effects.apply(mainMove);
+      effects.apply(mainScale);
+
+      return new DistortedNode(mCountTexture,effects,mesh);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -143,18 +207,24 @@ public class OverlayStars extends OverlayGeneric implements EffectListener
       mScreen = screen;
       mListener= listener;
       DataStars stars = (DataStars)data;
-      int totS = stars.getTotal();
-      int newS = stars.getNew();
+      mTotalStars = stars.getTotal();
+      mNewStars   = stars.getNew();
       Resources res = stars.getResources();
 
       mWidth = mScreen.getWidth();
       mHeight= mScreen.getHeight();
 
-      mNode = createNode(res,totS,newS);
-      mNode.glDepthMask(false);
-      mNode.glStencilMask(0);
-      mNode.enableDepthStencil(InternalOutputSurface.NO_DEPTH_NO_STENCIL);
-      mScreen.attach(mNode);
+      mStarsNode = createStarsNode(res);
+      mStarsNode.glDepthMask(false);
+      mStarsNode.glStencilMask(0);
+      mStarsNode.enableDepthStencil(InternalOutputSurface.NO_DEPTH_NO_STENCIL);
+      mScreen.attach(mStarsNode);
+
+      mCountNode = createCountNode();
+      mCountNode.glDepthMask(false);
+      mCountNode.glStencilMask(0);
+      mCountNode.enableDepthStencil(InternalOutputSurface.NO_DEPTH_NO_STENCIL);
+      mScreen.attach(mCountNode);
 
       return 0;
       }
@@ -163,8 +233,39 @@ public class OverlayStars extends OverlayGeneric implements EffectListener
 
    public void effectFinished(long id)
       {
-      mScreen.detach(mNode);
-      mListener.overlayFinished(id);
+      if( id==mMoveID )
+         {
+         Dynamic2D haloRadius = new Dynamic2D(DUR_GLO,1.0f);
+         haloRadius.add(new Static2D( 0, 0));
+         haloRadius.add(new Static2D(15,50));
+         haloRadius.add(new Static2D( 0, 0));
+
+         Dynamic4D color= new Dynamic4D(DUR_GLO,1.0f);
+         Static4D P1    = new Static4D(colors[3*INDEX],colors[3*INDEX+1], colors[3*INDEX+2], 0.0f);
+         Static4D P2    = new Static4D(colors[3*INDEX],colors[3*INDEX+1], colors[3*INDEX+2], 0.5f);
+         color.add(P1);
+         color.add(P2);
+         color.add(P1);
+
+         PostprocessEffectGlow glow = new PostprocessEffectGlow(haloRadius,color);
+         glow.setQuality(EffectQuality.MEDIUM);
+         mGlowID = glow.getID();
+         glow.notifyWhenFinished(this);
+         DistortedEffects effects = mStarsNode.getEffects();
+         effects.apply(glow);
+
+         renderStars(mTotalStars+mNewStars);
+         }
+      if( id==mGlowID )
+         {
+         mScreen.detach(mStarsNode);
+         mStarsNode.markForDeletion();
+         mStarsNode=null;
+         mScreen.detach(mCountNode);
+         mCountNode.markForDeletion();
+         mCountNode=null;
+         mListener.overlayFinished(id);
+         }
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -174,6 +275,6 @@ public class OverlayStars extends OverlayGeneric implements EffectListener
      {
      VertexEffectMove.enable();
      VertexEffectScale.enable();
-     VertexEffectRotate.enable();
+     PostprocessEffectGlow.enable();
      }
 }
\ No newline at end of file
diff --git a/src/main/res/drawable/star.png b/src/main/res/drawable/star.png
new file mode 100644
index 00000000..0abaa637
Binary files /dev/null and b/src/main/res/drawable/star.png differ
