Project

General

Profile

Download (12.7 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / overlays / OverlayStars.java @ f404152d

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2022 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.overlays;
11

    
12
import android.content.res.Resources;
13
import android.graphics.Bitmap;
14
import android.graphics.BitmapFactory;
15
import android.graphics.Canvas;
16
import android.graphics.Paint;
17

    
18
import org.distorted.library.effect.EffectQuality;
19
import org.distorted.library.effect.FragmentEffectAlpha;
20
import org.distorted.library.effect.MatrixEffectMove;
21
import org.distorted.library.effect.MatrixEffectScale;
22
import org.distorted.library.effect.PostprocessEffectGlow;
23
import org.distorted.library.effect.VertexEffectMove;
24
import org.distorted.library.effect.VertexEffectScale;
25
import org.distorted.library.main.DistortedEffects;
26
import org.distorted.library.main.DistortedNode;
27
import org.distorted.library.main.DistortedScreen;
28
import org.distorted.library.main.DistortedTexture;
29
import org.distorted.library.main.InternalOutputSurface;
30
import org.distorted.library.mesh.MeshJoined;
31
import org.distorted.library.mesh.MeshQuad;
32
import org.distorted.library.message.EffectListener;
33
import org.distorted.library.type.Dynamic;
34
import org.distorted.library.type.Dynamic1D;
35
import org.distorted.library.type.Dynamic2D;
36
import org.distorted.library.type.Dynamic3D;
37
import org.distorted.library.type.Dynamic4D;
38
import org.distorted.library.type.Static1D;
39
import org.distorted.library.type.Static2D;
40
import org.distorted.library.type.Static3D;
41
import org.distorted.library.type.Static4D;
42
import org.distorted.main.R;
43

    
44
import java.util.Random;
45

    
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47

    
48
public class OverlayStars extends OverlayGeneric implements EffectListener
49
{
50
   private static final int DUR_APP =  1500;
51
   private static final int DUR_MOV =  3000;
52
   private static final int DUR_GLO =   600;
53

    
54
   private static final int MAX_FALLING = 50;
55

    
56
   private ListenerOverlay mListener;
57
   private DistortedNode mNodeFalling, mNodeCentral;
58
   private DistortedScreen mScreen;
59
   private DistortedTexture mTexture;
60
   private Bitmap mCountBitmap, mStarBitmap;
61
   private Canvas mCountCanvas;
62
   private Paint mPaint;
63
   private int mBmpW, mBmpH;
64
   private float mWidth, mHeight;
65
   private Random mRandom;
66
   private long mMoveID, mGlow1ID, mGlow2ID, mAlphaID;
67
   private int mTotalStars, mNewStars;
68
   private FragmentEffectAlpha mAlpha;
69
   private Dynamic1D mAlphaStrength;
70
   private boolean mIncrease;
71
   private float mTextHeight;
72

    
73
///////////////////////////////////////////////////////////////////////////////////////////////////
74

    
75
   private Dynamic3D createRandomMove(boolean increase)
76
      {
77
      Dynamic3D move = new Dynamic3D();
78
      move.setMode(Dynamic.MODE_PATH);
79
      move.setDuration(DUR_MOV);
80
      move.setCount( increase ? 0.40f : 0.50f );
81

    
82
      float widthS = (mRandom.nextFloat()-0.5f)*mWidth*1.10f;
83
      float widthM = widthS + (mRandom.nextFloat()-0.5f)*mWidth*0.2f;
84
      float heighS = mRandom.nextFloat()*mHeight*0.2f;
85
      float heighM = (mRandom.nextFloat()-0.5f)*mHeight*0.2f;
86

    
87
      Static3D pointS = new Static3D(widthS,mHeight*0.60f+heighS,0);
88
      Static3D pointM = new Static3D(widthM,mHeight*0.25f+heighM,0);
89
      Static3D pointE = new Static3D(0,0,0);
90
      Static3D pointF = new Static3D(0,0,-10000);
91

    
92
      if( increase )
93
         {
94
         move.add(pointS);
95
         move.add(pointM);
96
         move.add(pointE);
97
         move.add(pointF);
98
         }
99
      else
100
         {
101
         move.add(pointF);
102
         move.add(pointE);
103
         move.add(pointM);
104
         move.add(pointS);
105
         }
106

    
107
      return move;
108
      }
109

    
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111

    
112
   private void createAlphaEffect(boolean appear)
113
      {
114
      if( mAlpha==null )
115
         {
116
         mAlphaStrength = new Dynamic1D();
117
         mAlphaStrength.setMode(Dynamic.MODE_PATH);
118
         mAlphaStrength.setDuration( mNewStars==0 ? 3*DUR_APP : DUR_APP);
119
         mAlphaStrength.setCount(0.5f);
120
         equipAlpha(mAlphaStrength,appear);
121
         mAlpha = new FragmentEffectAlpha(mAlphaStrength);
122

    
123
         if( mNewStars==0 )
124
            {
125
            mMoveID = mAlpha.getID();
126
            mAlpha.notifyWhenFinished(this);
127
            }
128
         }
129
      else
130
         {
131
         mAlphaStrength.resetToBeginning();
132
         equipAlpha(mAlphaStrength,appear);
133
         }
134
      }
135

    
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

    
138
   private void equipAlpha(Dynamic1D alpha, boolean appear)
139
      {
140
      Static1D point0 = new Static1D(0.0f);
141
      Static1D point1 = new Static1D(1.0f);
142

    
143
      alpha.removeAll();
144

    
145
      if( appear )
146
        {
147
        alpha.add(point0);
148
        if( mNewStars==0 ) alpha.add(point1);
149
        alpha.add(point1);
150
        }
151
      else
152
        {
153
        alpha.add(point1);
154
        if( mNewStars==0 ) alpha.add(point1);
155
        alpha.add(point0);
156
        }
157
      }
158

    
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160

    
161
   private float computeQuotientAndTextHeight(int total)
162
      {
163
      if( total>=10000 )
164
         {
165
         mTextHeight = 0.610f;
166
         return 0.16f;
167
         }
168
      if( total>= 1000 )
169
         {
170
         mTextHeight = 0.625f;
171
         return 0.20f;
172
         }
173
      if( total>=  100 )
174
         {
175
         mTextHeight = 0.640f;
176
         return 0.26f;
177
         }
178

    
179
      mTextHeight = 0.655f;
180
      return 0.28f;
181
      }
182

    
183
///////////////////////////////////////////////////////////////////////////////////////////////////
184

    
185
   private void createBitmap(Resources res, int total)
186
      {
187
      mStarBitmap = BitmapFactory.decodeResource(res, R.drawable.star);
188
      mBmpW = mStarBitmap.getWidth();
189
      mBmpH = mStarBitmap.getHeight();
190
      mCountBitmap = Bitmap.createBitmap(mBmpW,mBmpH,Bitmap.Config.ARGB_8888);
191
      mCountCanvas = new Canvas(mCountBitmap);
192

    
193
      float quotient = computeQuotientAndTextHeight(total);
194

    
195
      mPaint = new Paint();
196
      mPaint.setColor(0xff000000);
197
      mPaint.setTextSize(mBmpH*quotient);
198
      mPaint.setAntiAlias(true);
199
      mPaint.setTextAlign(Paint.Align.CENTER);
200
      }
201

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203

    
204
   private DistortedNode createNodeFalling(boolean increase)
205
      {
206
      DistortedTexture texture = new DistortedTexture();
207
      texture.setTexture(mStarBitmap);
208
      int numFalling = Math.min(mNewStars,MAX_FALLING);
209

    
210
      MeshQuad[] mesh = new MeshQuad[numFalling];
211

    
212
      for(int i=0; i<numFalling; i++)
213
         {
214
         mesh[i] = new MeshQuad();
215
         mesh[i].setEffectAssociation(0,1,i+1);
216
         }
217

    
218
      MeshJoined wholeMesh = new MeshJoined(mesh);
219

    
220
      DistortedEffects effects = new DistortedEffects();
221
      VertexEffectScale scaleE = new VertexEffectScale(mHeight*0.10f);
222
      scaleE.setMeshAssociation(1,-1);
223
      effects.apply(scaleE);
224

    
225
      for(int i=0; i<numFalling; i++)
226
        {
227
        Dynamic3D moveP = createRandomMove(increase);
228
        VertexEffectMove moveE= new VertexEffectMove(moveP);
229
        moveE.setMeshAssociation(0,i+1);
230
        effects.apply(moveE);
231

    
232
        if( i==0 )
233
           {
234
           mMoveID = moveE.getID();
235
           moveE.notifyWhenFinished(this);
236
           }
237
        }
238

    
239
      return new DistortedNode(texture,effects,wholeMesh);
240
      }
241

    
242
///////////////////////////////////////////////////////////////////////////////////////////////////
243

    
244
   private DistortedNode createNodeCentral(int numStars)
245
      {
246
      mTexture = new DistortedTexture();
247
      renderStars(numStars);
248

    
249
      MeshQuad mesh = new MeshQuad();
250

    
251
      DistortedEffects effects = new DistortedEffects();
252
      float scaleM  = mHeight*0.22f;
253
      Static3D moveM= new Static3D(0,0,1);
254
      MatrixEffectMove move  = new MatrixEffectMove(moveM);
255
      MatrixEffectScale scale= new MatrixEffectScale(scaleM);
256
      effects.apply(move);
257
      effects.apply(scale);
258
      createAlphaEffect(true);
259
      effects.apply(mAlpha);
260

    
261
      return new DistortedNode(mTexture,effects,mesh);
262
      }
263

    
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265

    
266
   private void renderStars(int numStars)
267
      {
268
      String txt = ""+numStars;
269
      mCountBitmap.eraseColor(0x00000000);
270
      mCountCanvas.drawBitmap(mStarBitmap,0,0,null);
271
      mCountCanvas.drawText(txt,mBmpW*0.5f,mBmpH*mTextHeight,mPaint);
272
      mTexture.setTexture(mCountBitmap);
273
      }
274

    
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276

    
277
   public long startOverlay(DistortedScreen screen, ListenerOverlay listener, DataGeneric data)
278
      {
279
      mRandom = new Random();
280
      mScreen = screen;
281
      mListener= listener;
282
      DataStars stars = (DataStars)data;
283
      mTotalStars = stars.getTotal();
284
      mNewStars   = stars.getNew();
285
      Resources res = stars.getResources();
286
      mWidth = mScreen.getWidth();
287
      mHeight= mScreen.getHeight();
288
      mIncrease = mNewStars>0;
289
      if( !mIncrease ) mNewStars = -mNewStars;
290

    
291
      createBitmap(res, mTotalStars);
292

    
293
      if( mNewStars!=0 )
294
         {
295
         mNodeFalling = createNodeFalling(mIncrease);
296
         mNodeFalling.enableDepthStencil(InternalOutputSurface.NO_DEPTH_NO_STENCIL);
297
         mScreen.attach(mNodeFalling);
298
         }
299

    
300
      mNodeCentral = createNodeCentral(mTotalStars);
301
      mNodeCentral.glDepthMask(false);
302
      mScreen.attach(mNodeCentral);
303

    
304
      return 0;
305
      }
306

    
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308

    
309
   private PostprocessEffectGlow constructGlow(boolean firstPhase)
310
      {
311
      Dynamic2D haloRadius = new Dynamic2D( mNewStars==0 ? 2*DUR_GLO : DUR_GLO,0.5f);
312
      Static2D point20 = new Static2D( 0, 0);
313
      Static2D point21 = new Static2D(15,50);
314
      Dynamic4D color = new Dynamic4D(DUR_GLO, 0.5f);
315
      Static4D point40 = new Static4D(1,1,1,0.0f);
316
      Static4D point41 = new Static4D(1,1,1,0.8f);
317

    
318
      if( firstPhase )
319
         {
320
         haloRadius.add(point20);
321
         haloRadius.add(point21);
322
         color.add(point40);
323
         color.add(point41);
324
         }
325
      else
326
         {
327
         haloRadius.add(point21);
328
         haloRadius.add(point20);
329
         color.add(point41);
330
         color.add(point40);
331
         }
332

    
333
      PostprocessEffectGlow glow = new PostprocessEffectGlow(haloRadius,color);
334
      glow.setQuality(EffectQuality.MEDIUM);
335
      glow.notifyWhenFinished(this);
336

    
337
      return glow;
338
      }
339

    
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341

    
342
   public void effectFinished(long id)
343
      {
344
      if( id==mMoveID )
345
         {
346
         PostprocessEffectGlow glow = constructGlow(true);
347
         mGlow1ID = glow.getID();
348
         DistortedEffects effects = mNodeCentral.getEffects();
349
         effects.apply(glow);
350
         }
351
      if( id==mGlow1ID )
352
         {
353
         renderStars(mTotalStars+(mIncrease ? mNewStars : -mNewStars));
354
         PostprocessEffectGlow glow = constructGlow(false);
355
         mGlow2ID = glow.getID();
356
         DistortedEffects effects = mNodeCentral.getEffects();
357
         effects.abortById(mGlow1ID);
358
         effects.apply(glow);
359
         }
360
      if( id==mGlow2ID )
361
         {
362
         DistortedEffects effects = mNodeCentral.getEffects();
363
         effects.abortById(mGlow2ID);
364
         createAlphaEffect(false);
365
         mAlphaID = mAlpha.getID();
366
         mAlpha.notifyWhenFinished(this);
367
         effects.apply(mAlpha);
368
         }
369
      if( id==mAlphaID )
370
         {
371
         mScreen.detach(mNodeCentral);
372
         mNodeCentral.markForDeletion();
373
         mNodeCentral=null;
374

    
375
         if( mNodeFalling!=null )
376
            {
377
            mScreen.detach(mNodeFalling);
378
            mNodeFalling.markForDeletion();
379
            mNodeFalling=null;
380
            }
381

    
382
         if( mListener!=null ) mListener.overlayFinished(id);
383
         }
384
      }
385

    
386
///////////////////////////////////////////////////////////////////////////////////////////////////
387

    
388
  @SuppressWarnings("unused")
389
  public static void enableEffects()
390
     {
391
     FragmentEffectAlpha.enable();
392
     VertexEffectMove.enable();
393
     VertexEffectScale.enable();
394
     PostprocessEffectGlow.enable();
395
     }
396
}
(5-5/5)