Project

General

Profile

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

library / src / main / java / org / distorted / library / effect / Effect.java @ 7958d843

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.effectqueue.EffectQueue;
23
import org.distorted.library.main.InternalStackFrameList;
24
import org.distorted.library.message.EffectListener;
25

    
26
import java.lang.reflect.Method;
27
import java.util.ArrayList;
28

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

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

    
45
  private ArrayList<EffectListener> mListeners =null;
46
  private int mNumListeners=0;  // ==mListeners.length(), but we only create mListeners if the first one gets added
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
  public abstract void addQueue(EffectQueue queue);
64
  public abstract void remQueue(EffectQueue queue);
65

    
66
///////////////////////////////////////////////////////////////////////////////////////////////////
67

    
68
  Effect(EffectName name)
69
    {
70
    mName      = name;
71
    mType      = name.getType();
72
    mDimension = name.getEffectDimension();
73
    mCenterDim = name.getCenterDimension();
74
    mRegionDim = name.getRegionDimension();
75

    
76
    mAndAssociation = 0xffffffff;
77
    mEquAssociation = 0;
78

    
79
    int n = name.ordinal();
80
    float[] u = name.getUnity();
81
    int l = u.length;
82

    
83
    System.arraycopy(u, 0, mUnity, MAX_UNITY_DIM*n, l);
84

    
85
    mUnityDim[n] = l;
86

    
87
    mID = (InternalStackFrameList.getNextEffectID()<<EffectType.LENGTH) + mType.ordinal();
88
    }
89

    
90
///////////////////////////////////////////////////////////////////////////////////////////////////
91
/**
92
 * Only for use by the library itself.
93
 *
94
 * @y.exclude
95
 */
96
  public static void onDestroy()
97
    {
98
    for(int i=0; i<NUM_EFFECTS; i++) mEnabled[i] = false;
99

    
100
    MatrixEffect.destroyStatics();
101
    VertexEffect.destroyStatics();
102
    FragmentEffect.destroyStatics();
103
    PostprocessEffect.destroyStatics();
104
    }
105

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

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

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

    
139
    return null;
140
    }
141

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

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

    
165
    switch(mUnityDim[name])
166
      {
167
      case 0: return true;
168
      case 1: return buffer[index  ]==mUnity[MAX_UNITY_DIM*name  ];
169
      case 2: return buffer[index  ]==mUnity[MAX_UNITY_DIM*name  ] &&
170
                     buffer[index+1]==mUnity[MAX_UNITY_DIM*name+1];
171
      case 3: 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
      case 4: return buffer[index  ]==mUnity[MAX_UNITY_DIM*name  ] &&
175
                     buffer[index+1]==mUnity[MAX_UNITY_DIM*name+1] &&
176
                     buffer[index+2]==mUnity[MAX_UNITY_DIM*name+2] &&
177
                     buffer[index+3]==mUnity[MAX_UNITY_DIM*name+3];
178
      }
179

    
180
    return false;
181
    }
182

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

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

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

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

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

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

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

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

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

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

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

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

    
305
    if( !mListeners.contains(el) )
306
      {
307
      mListeners.add(el);
308
      mNumListeners++;
309
      }
310
    }
311
  }
(1-1/32)