Project

General

Profile

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

library / src / main / java / org / distorted / library / effect / Effect.java @ f046b159

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
  static boolean[] mEnabled = new boolean[NUM_EFFECTS];
52

    
53
  static
54
    {
55
    for(int i=0; i<NUM_EFFECTS; i++) mEnabled[i] = false;
56
    }
57

    
58
///////////////////////////////////////////////////////////////////////////////////////////////////
59

    
60
  Effect(EffectName name)
61
    {
62
    mName      = name;
63
    mType      = name.getType();
64
    mDimension = name.getEffectDimension();
65
    mCenterDim = name.getCenterDimension();
66
    mRegionDim = name.getRegionDimension();
67

    
68
    int n = name.ordinal();
69
    float[] u = name.getUnity();
70
    int l = u.length;
71

    
72
    System.arraycopy(u, 0, mUnity, MAX_UNITY_DIM*n, l);
73

    
74
    mUnityDim[n] = l;
75

    
76
    mID = ((mNextID++)<<EffectType.LENGTH) + mType.ordinal();
77
    }
78

    
79
///////////////////////////////////////////////////////////////////////////////////////////////////
80
/**
81
 * Only for use by the library itself.
82
 *
83
 * @y.exclude
84
 */
85
  public static void onDestroy()
86
    {
87
    mNextID = 0;
88

    
89
    for(int i=0; i<NUM_EFFECTS; i++) mEnabled[i] = false;
90

    
91
    MatrixEffect.destroyStatics();
92
    VertexEffect.destroyStatics();
93
    FragmentEffect.destroyStatics();
94
    PostprocessEffect.destroyStatics();
95
    }
96

    
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98
/**
99
 * Only for use by the library itself.
100
 *
101
 * @y.exclude
102
 */
103
  public abstract boolean compute(float[] uniforms, int index, long currentDuration, long step );
104

    
105
///////////////////////////////////////////////////////////////////////////////////////////////////
106
/**
107
 * Only for use by the library itself.
108
 *
109
 * @y.exclude
110
 */
111
  public int getNumListeners()
112
    {
113
    return mNumListeners;
114
    }
115

    
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117
/**
118
 * Only for use by the library itself.
119
 *
120
 * @y.exclude
121
 */
122
  public EffectListener removeFirstListener()
123
    {
124
    if( mNumListeners>0 )
125
      {
126
      mNumListeners--;
127
      return mListeners.remove(0);
128
      }
129

    
130
    return null;
131
    }
132

    
133
///////////////////////////////////////////////////////////////////////////////////////////////////
134
// PUBLIC API
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136
/**
137
 * Do the set of Uniforms written in buffer[index], buffer[index+1], etc represent a Unity, i.e a
138
 * null Effect?
139
 */
140
  public boolean isUnity(float[] buffer, int index)
141
    {
142
    int name = mName.ordinal();
143

    
144
    switch(mUnityDim[name])
145
      {
146
      case 0: return true;
147
      case 1: return buffer[index  ]==mUnity[MAX_UNITY_DIM*name  ];
148
      case 2: return buffer[index  ]==mUnity[MAX_UNITY_DIM*name  ] &&
149
                     buffer[index+1]==mUnity[MAX_UNITY_DIM*name+1];
150
      case 3: return buffer[index  ]==mUnity[MAX_UNITY_DIM*name  ] &&
151
                     buffer[index+1]==mUnity[MAX_UNITY_DIM*name+1] &&
152
                     buffer[index+2]==mUnity[MAX_UNITY_DIM*name+2];
153
      case 4: return buffer[index  ]==mUnity[MAX_UNITY_DIM*name  ] &&
154
                     buffer[index+1]==mUnity[MAX_UNITY_DIM*name+1] &&
155
                     buffer[index+2]==mUnity[MAX_UNITY_DIM*name+2] &&
156
                     buffer[index+3]==mUnity[MAX_UNITY_DIM*name+3];
157
      }
158

    
159
    return false;
160
    }
161

    
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163
// this will enable() all Fragment Effects twice (once for smooth variant, once for non-smooth)
164
// but this shouldn't matter.
165
/**
166
 * Enable all effects of a given type.
167
 *
168
 * @param type EffectType to enable.
169
 */
170
  public static void enableEffects(EffectType type)
171
    {
172
    Method method;
173

    
174
    for(EffectName name: EffectName.values())
175
      {
176
      if( name.getType() == type )
177
        {
178
        Class<? extends Effect> cls = name.getEffectClass();
179

    
180
        try
181
          {
182
          method = cls.getMethod("enable");  // getMethod and NOT getDeclaredMethod because enable()
183
                                             // is public
184
          }
185
        catch(NoSuchMethodException ex)
186
          {
187
          android.util.Log.e("Effect", "exception getting method: "+ex.getMessage());
188
          method = null;
189
          }
190

    
191
        try
192
          {
193
          if( method!=null ) method.invoke(null);
194
          }
195
        catch(Exception ex)
196
          {
197
          android.util.Log.e("Effect", "exception invoking method: "+ex.getMessage());
198
          }
199
        }
200
      }
201
    }
202

    
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204
/**
205
 * Return the EffectType enum corresponding to this Effect.
206
 *
207
 * @see EffectType
208
 */
209
  public EffectType getType()
210
    {
211
    return mType;
212
    }
213

    
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215
/**
216
 * Return the EffectName enum corresponding to this Effect.
217
 *
218
 * @see EffectName
219
 */
220
  public EffectName getName()
221
    {
222
    return mName;
223
    }
224

    
225
///////////////////////////////////////////////////////////////////////////////////////////////////
226
/**
227
 * Return the unique ID of this Effect.
228
 */
229
  public long getID()
230
    {
231
    return mID;
232
    }
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235
/**
236
 * Return a printable name of this Effect.
237
 */
238
  public String getString()
239
    {
240
    return mName.name();
241
    }
242

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244
/**
245
 * Return the dimension of the Center supported by this effect (0- no center supported at all).
246
 */
247
  public int getCenterDimension()
248
    {
249
    return mCenterDim;
250
    }
251

    
252
///////////////////////////////////////////////////////////////////////////////////////////////////
253
/**
254
 * Return the dimension of the Region supported by this effect (0- no region supported at all).
255
 */
256
  public int getRegionDimension()
257
    {
258
    return mRegionDim;
259
    }
260

    
261
///////////////////////////////////////////////////////////////////////////////////////////////////
262
/**
263
 * Return the number of Uniforms needed to describe this effect.
264
 */
265
  public int getEffectDimension()
266
    {
267
    return mDimension;
268
    }
269

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271
/**
272
 * Adds the calling class to the list of Listeners that get notified when this Effect gets 'finished'
273
 * i.e. when the Dynamic inside this Effect reaches its final point and stops moving. This will be sent
274
 * only once, on the first time the Dynamic reaches its final point.
275
 *
276
 * If there's no Dynamic, ths message will never be sent.
277
 *
278
 * @param el A class implementing the EffectListener interface that wants to get notifications.
279
 */
280
  public void notifyWhenFinished(EffectListener el)
281
    {
282
    if( mListeners==null ) mListeners = new ArrayList<>();
283

    
284
    if( !mListeners.contains(el) )
285
      {
286
      mListeners.add(el);
287
      mNumListeners++;
288
      }
289
    }
290
  }
(1-1/31)