Project

General

Profile

Download (9.82 KB) Statistics
| Branch: | Revision:

library / src / main / java / org / distorted / library / effect / Effect.java @ 96e3b88a

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2017 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Distorted is distributed in the hope that it will be useful,                                  //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.library.effect;
21

    
22
import org.distorted.library.message.EffectListener;
23

    
24
import java.lang.reflect.Method;
25
import java.util.ArrayList;
26

    
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28
/**
29
 * Abstract Effect of any type.
30
 */
31
public abstract class Effect
32
  {
33
  private final static int MAX_UNITY_DIM = 4;
34
  private final static int NUM_EFFECTS = EffectName.LENGTH;
35

    
36
  private final long mID;
37
  private final EffectType mType;
38
  private final EffectName mName;
39
  private final int mDimension;
40
  private final int mRegionDim;
41
  private final int mCenterDim;
42

    
43
  private ArrayList<EffectListener> mListeners =null;
44
  private int mNumListeners=0;  // ==mListeners.length(), but we only create mListeners if the first one gets added
45

    
46
  private static long mNextID = 0;
47

    
48
  private final static float[] mUnity= new float[MAX_UNITY_DIM*NUM_EFFECTS];
49
  private final static int[]   mUnityDim = new int[NUM_EFFECTS];
50

    
51
  int mAndAssociation;
52
  int mEquAssociation;
53

    
54
  static boolean[] mEnabled = new boolean[NUM_EFFECTS];
55

    
56
  static
57
    {
58
    for(int i=0; i<NUM_EFFECTS; i++) mEnabled[i] = false;
59
    }
60

    
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62

    
63
  Effect(EffectName name)
64
    {
65
    mName      = name;
66
    mType      = name.getType();
67
    mDimension = name.getEffectDimension();
68
    mCenterDim = name.getCenterDimension();
69
    mRegionDim = name.getRegionDimension();
70

    
71
    mAndAssociation = 0xffffffff;
72
    mEquAssociation = 0;
73

    
74
    int n = name.ordinal();
75
    float[] u = name.getUnity();
76
    int l = u.length;
77

    
78
    System.arraycopy(u, 0, mUnity, MAX_UNITY_DIM*n, l);
79

    
80
    mUnityDim[n] = l;
81

    
82
    mID = ((mNextID++)<<EffectType.LENGTH) + mType.ordinal();
83
    }
84

    
85
///////////////////////////////////////////////////////////////////////////////////////////////////
86
/**
87
 * Only for use by the library itself.
88
 *
89
 * @y.exclude
90
 */
91
  public static void onDestroy()
92
    {
93
    mNextID = 0;
94

    
95
    for(int i=0; i<NUM_EFFECTS; i++) mEnabled[i] = false;
96

    
97
    MatrixEffect.destroyStatics();
98
    VertexEffect.destroyStatics();
99
    FragmentEffect.destroyStatics();
100
    PostprocessEffect.destroyStatics();
101
    }
102

    
103
///////////////////////////////////////////////////////////////////////////////////////////////////
104
/**
105
 * Only for use by the library itself.
106
 *
107
 * @y.exclude
108
 */
109
  public abstract boolean compute(float[] uniforms, int index, long currentDuration, long step );
110

    
111
///////////////////////////////////////////////////////////////////////////////////////////////////
112
/**
113
 * Only for use by the library itself.
114
 *
115
 * @y.exclude
116
 */
117
  public int getNumListeners()
118
    {
119
    return mNumListeners;
120
    }
121

    
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123
/**
124
 * Only for use by the library itself.
125
 *
126
 * @y.exclude
127
 */
128
  public EffectListener removeFirstListener()
129
    {
130
    if( mNumListeners>0 )
131
      {
132
      mNumListeners--;
133
      return mListeners.remove(0);
134
      }
135

    
136
    return null;
137
    }
138

    
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140
/**
141
 * Only for use by the library itself.
142
 *
143
 * @y.exclude
144
 */
145
  public void writeAssociations(int[] intUniforms, int index1, int index2)
146
    {
147
    intUniforms[index1] = mAndAssociation;
148
    intUniforms[index2] = mEquAssociation;
149
    }
150

    
151
///////////////////////////////////////////////////////////////////////////////////////////////////
152
// PUBLIC API
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154
/**
155
 * Do the set of Uniforms written in buffer[index], buffer[index+1], etc represent a Unity, i.e a
156
 * null Effect?
157
 */
158
  public boolean isUnity(float[] buffer, int index)
159
    {
160
    int name = mName.ordinal();
161

    
162
    switch(mUnityDim[name])
163
      {
164
      case 0: return true;
165
      case 1: return buffer[index  ]==mUnity[MAX_UNITY_DIM*name  ];
166
      case 2: return buffer[index  ]==mUnity[MAX_UNITY_DIM*name  ] &&
167
                     buffer[index+1]==mUnity[MAX_UNITY_DIM*name+1];
168
      case 3: return buffer[index  ]==mUnity[MAX_UNITY_DIM*name  ] &&
169
                     buffer[index+1]==mUnity[MAX_UNITY_DIM*name+1] &&
170
                     buffer[index+2]==mUnity[MAX_UNITY_DIM*name+2];
171
      case 4: return buffer[index  ]==mUnity[MAX_UNITY_DIM*name  ] &&
172
                     buffer[index+1]==mUnity[MAX_UNITY_DIM*name+1] &&
173
                     buffer[index+2]==mUnity[MAX_UNITY_DIM*name+2] &&
174
                     buffer[index+3]==mUnity[MAX_UNITY_DIM*name+3];
175
      }
176

    
177
    return false;
178
    }
179

    
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181
// this will enable() all Fragment Effects twice (once for smooth variant, once for non-smooth)
182
// but this shouldn't matter.
183
/**
184
 * Enable all effects of a given type.
185
 *
186
 * @param type EffectType to enable.
187
 */
188
  public static void enableEffects(EffectType type)
189
    {
190
    Method method;
191

    
192
    for(EffectName name: EffectName.values())
193
      {
194
      if( name.getType() == type )
195
        {
196
        Class<? extends Effect> cls = name.getEffectClass();
197

    
198
        try
199
          {
200
          method = cls.getMethod("enable");  // getMethod and NOT getDeclaredMethod because enable()
201
                                             // is public
202
          }
203
        catch(NoSuchMethodException ex)
204
          {
205
          android.util.Log.e("Effect", "exception getting method: "+ex.getMessage());
206
          method = null;
207
          }
208

    
209
        try
210
          {
211
          if( method!=null ) method.invoke(null);
212
          }
213
        catch(Exception ex)
214
          {
215
          android.util.Log.e("Effect", "exception invoking method: "+ex.getMessage());
216
          }
217
        }
218
      }
219
    }
220

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222
/**
223
 * Return the EffectType enum corresponding to this Effect.
224
 *
225
 * @see EffectType
226
 */
227
  public EffectType getType()
228
    {
229
    return mType;
230
    }
231

    
232
///////////////////////////////////////////////////////////////////////////////////////////////////
233
/**
234
 * Return the EffectName enum corresponding to this Effect.
235
 *
236
 * @see EffectName
237
 */
238
  public EffectName getName()
239
    {
240
    return mName;
241
    }
242

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244
/**
245
 * Return the unique ID of this Effect.
246
 */
247
  public long getID()
248
    {
249
    return mID;
250
    }
251

    
252
///////////////////////////////////////////////////////////////////////////////////////////////////
253
/**
254
 * Return a printable name of this Effect.
255
 */
256
  public String getString()
257
    {
258
    return mName.name();
259
    }
260

    
261
///////////////////////////////////////////////////////////////////////////////////////////////////
262
/**
263
 * Return the dimension of the Center supported by this effect (0- no center supported at all).
264
 */
265
  public int getCenterDimension()
266
    {
267
    return mCenterDim;
268
    }
269

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271
/**
272
 * Return the dimension of the Region supported by this effect (0- no region supported at all).
273
 */
274
  public int getRegionDimension()
275
    {
276
    return mRegionDim;
277
    }
278

    
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280
/**
281
 * Return the number of Uniforms needed to describe this effect.
282
 */
283
  public int getEffectDimension()
284
    {
285
    return mDimension;
286
    }
287

    
288
///////////////////////////////////////////////////////////////////////////////////////////////////
289
/**
290
 * Adds the calling class to the list of Listeners that get notified when this Effect gets 'finished'
291
 * i.e. when the Dynamic inside this Effect reaches its final point and stops moving. This will be sent
292
 * only once, on the first time the Dynamic reaches its final point.
293
 *
294
 * If there's no Dynamic, ths message will never be sent.
295
 *
296
 * @param el A class implementing the EffectListener interface that wants to get notifications.
297
 */
298
  public void notifyWhenFinished(EffectListener el)
299
    {
300
    if( mListeners==null ) mListeners = new ArrayList<>();
301

    
302
    if( !mListeners.contains(el) )
303
      {
304
      mListeners.add(el);
305
      mNumListeners++;
306
      }
307
    }
308
  }
(1-1/32)