Project

General

Profile

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

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

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

    
71
///////////////////////////////////////////////////////////////////////////////////////////////////
72

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

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

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

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

    
105
      return move;
106
      }
107

    
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109

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

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

    
134
///////////////////////////////////////////////////////////////////////////////////////////////////
135

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

    
141
      alpha.removeAll();
142

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

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158

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

    
177
      mTextHeight = 0.655f;
178
      return 0.28f;
179
      }
180

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

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

    
191
      float quotient = computeQuotientAndTextHeight(total);
192

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

    
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201

    
202
   private DistortedNode createNodeFalling(boolean increase)
203
      {
204
      DistortedTexture texture = new DistortedTexture();
205
      texture.setTexture(mStarBitmap);
206

    
207
      MeshQuad[] mesh = new MeshQuad[mNewStars];
208

    
209
      for(int i=0; i<mNewStars; i++)
210
         {
211
         mesh[i] = new MeshQuad();
212
         mesh[i].setEffectAssociation(0,1,i+1);
213
         }
214

    
215
      MeshJoined wholeMesh = new MeshJoined(mesh);
216

    
217
      DistortedEffects effects = new DistortedEffects();
218
      VertexEffectScale scaleE = new VertexEffectScale(mWidth*0.15f);
219
      scaleE.setMeshAssociation(1,-1);
220
      effects.apply(scaleE);
221

    
222
      for(int i=0; i<mNewStars; i++)
223
        {
224
        Dynamic3D moveP = createRandomMove(increase);
225
        VertexEffectMove moveE= new VertexEffectMove(moveP);
226
        moveE.setMeshAssociation(0,i+1);
227
        effects.apply(moveE);
228

    
229
        if( i==0 )
230
           {
231
           mMoveID = moveE.getID();
232
           moveE.notifyWhenFinished(this);
233
           }
234
        }
235

    
236
      return new DistortedNode(texture,effects,wholeMesh);
237
      }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240

    
241
   private DistortedNode createNodeCentral(int numStars)
242
      {
243
      mTexture = new DistortedTexture();
244
      renderStars(numStars);
245

    
246
      MeshQuad mesh = new MeshQuad();
247

    
248
      DistortedEffects effects = new DistortedEffects();
249
      float scaleM  = mWidth*0.40f;
250
      Static3D moveM= new Static3D(0,0,1);
251
      MatrixEffectMove move  = new MatrixEffectMove(moveM);
252
      MatrixEffectScale scale= new MatrixEffectScale(scaleM);
253
      effects.apply(move);
254
      effects.apply(scale);
255
      createAlphaEffect(true);
256
      effects.apply(mAlpha);
257

    
258
      return new DistortedNode(mTexture,effects,mesh);
259
      }
260

    
261
///////////////////////////////////////////////////////////////////////////////////////////////////
262

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

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273

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

    
288
      createBitmap(res, mTotalStars);
289

    
290
      if( mNewStars!=0 )
291
         {
292
         mNodeFalling = createNodeFalling(mIncrease);
293
         mNodeFalling.enableDepthStencil(InternalOutputSurface.NO_DEPTH_NO_STENCIL);
294
         mScreen.attach(mNodeFalling);
295
         }
296

    
297
      mNodeCentral = createNodeCentral(mTotalStars);
298
      mNodeCentral.glDepthMask(false);
299
      mScreen.attach(mNodeCentral);
300

    
301
      return 0;
302
      }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

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

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

    
330
      PostprocessEffectGlow glow = new PostprocessEffectGlow(haloRadius,color);
331
      glow.setQuality(EffectQuality.MEDIUM);
332
      glow.notifyWhenFinished(this);
333

    
334
      return glow;
335
      }
336

    
337
///////////////////////////////////////////////////////////////////////////////////////////////////
338

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

    
372
         if( mNodeFalling!=null )
373
            {
374
            mScreen.detach(mNodeFalling);
375
            mNodeFalling.markForDeletion();
376
            mNodeFalling=null;
377
            }
378

    
379
         if( mListener!=null ) mListener.overlayFinished(id);
380
         }
381
      }
382

    
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384

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