Project

General

Profile

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

library / src / main / java / org / distorted / library / EffectQueue.java @ 8e34674e

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 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;
21

    
22
import org.distorted.library.message.EffectListener;
23
import org.distorted.library.message.EffectMessage;
24
import org.distorted.library.type.Dynamic;
25

    
26
import java.util.Vector;
27

    
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29

    
30
abstract class EffectQueue
31
  {
32
  protected byte mNumEffects;   // number of effects at the moment
33
  protected long mTotalEffects; // total number of effects ever created
34
  
35
  protected int[] mName;
36
  protected float[] mUniforms;
37
  protected Dynamic[][] mInter;
38
  protected long[] mCurrentDuration;
39
  protected byte[] mFreeIndexes;
40
  protected byte[] mIDIndex;
41
  protected long[] mID;
42
  
43
  protected long mTime=0;
44
  protected float mObjHalfX, mObjHalfY, mObjHalfZ;
45
  
46
  protected static int[] mMax = new int[EffectTypes.LENGTH];
47
  protected int mMaxIndex;
48

    
49
  protected Vector<EffectListener> mListeners =null;
50
  protected int mNumListeners=0;  // ==mListeners.length(), but we only create mListeners if the first one gets added
51
  protected long mBitmapID;
52

    
53
  private static boolean mCreated;
54

    
55
  static
56
    {
57
    release();
58
    }
59
  
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61
   
62
  EffectQueue(DistortedObject obj, int numUniforms, int index)
63
    {
64
    mNumEffects   = 0;
65
    mTotalEffects = 0;
66
    mMaxIndex     = index;
67

    
68
    if( obj!=null )
69
      {
70
      mObjHalfX = obj.getWidth() / 2.0f;
71
      mObjHalfY = obj.getHeight() / 2.0f;
72
      mObjHalfZ = obj.getDepth() / 2.0f;
73

    
74
      mBitmapID = obj.getID();
75
      }
76

    
77
    if( mMax[mMaxIndex]>0 )
78
      {
79
      mName            = new int[mMax[mMaxIndex]];
80
      mUniforms        = new float[numUniforms*mMax[mMaxIndex]];
81
      mInter           = new Dynamic[3][mMax[mMaxIndex]];
82
      mCurrentDuration = new long[mMax[mMaxIndex]];
83
      mID              = new long[mMax[mMaxIndex]];
84
      mIDIndex         = new byte[mMax[mMaxIndex]];
85
      mFreeIndexes     = new byte[mMax[mMaxIndex]];
86
     
87
      for(byte i=0; i<mMax[mMaxIndex]; i++) mFreeIndexes[i] = i;
88
      }
89
   
90
    mCreated = true;  
91
    }
92

    
93
///////////////////////////////////////////////////////////////////////////////////////////////////
94

    
95
  @SuppressWarnings("unused")
96
  int getNumEffects()
97
    {
98
    return mNumEffects;  
99
    }
100

    
101
///////////////////////////////////////////////////////////////////////////////////////////////////
102
// Only max Byte.MAX_VALUE concurrent effects per DistortedObject.
103
// If you want more, change type of the mNumEffects, mIDIndex and mFreeIndexes variables to shorts.
104

    
105
  static boolean setMax(int index, int m)
106
    {
107
    if( (!mCreated && !Distorted.isInitialized()) || m<=mMax[index] )
108
      {
109
      if( m<0              ) m = 0;
110
      else if( m>Byte.MAX_VALUE ) m = Byte.MAX_VALUE;
111

    
112
      mMax[index] = m;
113
      return true;
114
      }
115

    
116
    return false;
117
    }
118

    
119
///////////////////////////////////////////////////////////////////////////////////////////////////
120

    
121
  static int getMax(int index)
122
    {
123
    return mMax[index];
124
    }
125

    
126
///////////////////////////////////////////////////////////////////////////////////////////////////
127

    
128
  void addListener(EffectListener el)
129
    {
130
    if( mListeners==null ) mListeners = new Vector<>(2,2);
131
   
132
    mListeners.add(el);
133
    mNumListeners++;
134
    }
135
 
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

    
138
  void removeListener(EffectListener el)
139
    {
140
    if( mNumListeners>0 )  
141
      {
142
      mListeners.remove(el);
143
      mNumListeners--;
144
      }
145
    }
146

    
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148

    
149
  static void release()
150
    {
151
    EffectTypes.reset(mMax);
152
    mCreated = false;  
153
    }
154
 
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156

    
157
  synchronized int removeByID(long id)
158
    {
159
    int i = getEffectIndex(id);
160
   
161
    if( i>=0 ) 
162
      {
163
      remove(i);
164
      return 1;
165
      }
166
   
167
    return 0;
168
    }
169

    
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171

    
172
  synchronized int removeByType(EffectNames effect)
173
    {
174
    int ret = 0;
175
    int ord = effect.ordinal();  
176
     
177
    for(int i=0; i<mNumEffects; i++)
178
      {
179
      if( mName[i]==ord )
180
        {
181
        remove(i);
182
        i--;
183
        ret++;
184
        }
185
      }
186
   
187
    return ret;
188
    }
189
  
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191
  
192
  private synchronized int getEffectIndex(long id)
193
    {
194
    int index = mIDIndex[(int)(id%mMax[mMaxIndex])];
195
    return (index<mNumEffects && mID[index]==id ? index : -1);
196
    }
197

    
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199
// we do want to notify Listeners if they called 'abortAll' themselves but don't want to notify
200
// them if it is the library itself which is releasing resources.
201

    
202
  synchronized int abortAll(boolean notify)
203
    {
204
    int ret = mNumEffects;
205
    long removedID;
206
    int removedName;
207

    
208
    for(int i=0; i<ret; i++ )
209
      {
210
      mInter[0][i] = null;
211
      mInter[1][i] = null;
212
      mInter[2][i] = null;
213

    
214
      if( notify )
215
        {
216
        removedID = mID[i];
217
        removedName= mName[i];
218

    
219
        for(int j=0; j<mNumListeners; j++)
220
          EffectMessageSender.newMessage( mListeners.elementAt(j),
221
                                          EffectMessage.EFFECT_REMOVED,
222
                                          (removedID<<EffectTypes.LENGTH)+EffectNames.getType(removedName).type,
223
                                          removedName,
224
                                          mBitmapID,
225
                                          null);
226
        }
227
      }
228

    
229
    mNumEffects= 0;
230

    
231
    return ret;
232
    }
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235
// this assumes 0<=effect<mNumEffects
236
  
237
  protected void remove(int effect)
238
    {
239
    mNumEffects--;     
240
    
241
    byte removedIndex = (byte)(mID[effect]%mMax[mMaxIndex]);
242
    byte removedPosition = mIDIndex[removedIndex];
243
    mFreeIndexes[mNumEffects] = removedIndex;
244
    
245
    long removedID = mID[effect];
246
    int removedName= mName[effect];
247
    
248
    for(int j=0; j<mMax[mMaxIndex]; j++)
249
      {
250
      if( mIDIndex[j] > removedPosition ) mIDIndex[j]--; 
251
      }
252
         
253
    for(int j=effect; j<mNumEffects; j++ ) 
254
      {
255
      mName[j]            = mName[j+1];
256
      mInter[0][j]        = mInter[0][j+1];
257
      mInter[1][j]        = mInter[1][j+1];
258
      mInter[2][j]        = mInter[2][j+1];
259
      mCurrentDuration[j] = mCurrentDuration[j+1];
260
      mID[j]              = mID[j+1];
261
    
262
      moveEffect(j);
263
      }
264
   
265
    mInter[0][mNumEffects] = null;
266
    mInter[1][mNumEffects] = null;
267
    mInter[2][mNumEffects] = null;
268

    
269
    for(int i=0; i<mNumListeners; i++) 
270
      EffectMessageSender.newMessage( mListeners.elementAt(i),
271
                                      EffectMessage.EFFECT_REMOVED,
272
                                      (removedID<<EffectTypes.LENGTH)+EffectNames.getType(removedName).type,
273
                                      removedName,
274
                                      mBitmapID,
275
                                      null);
276
    }
277
  
278
///////////////////////////////////////////////////////////////////////////////////////////////////
279
  
280
  protected long addBase(EffectNames name)
281
    {    
282
    mName[mNumEffects]  = name.ordinal();
283
    mCurrentDuration[mNumEffects] = 0;
284
    
285
    int index = mFreeIndexes[mNumEffects];
286
    long id = mTotalEffects*mMax[mMaxIndex] + index;
287
    mID[mNumEffects] = id;
288
    mIDIndex[index] = mNumEffects;  
289
   
290
    mNumEffects++; 
291
    mTotalEffects++;
292
   
293
    return (id<<EffectTypes.LENGTH)+name.getType().type;
294
    }
295
    
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297
// used only for debugging
298

    
299
  @SuppressWarnings("unused")
300
  protected String printEffects(int max)
301
    {
302
    long[] indexes = new long[mMax[mMaxIndex]];
303
   
304
    for(int g=0; g<mMax[mMaxIndex]; g++)
305
      {
306
      indexes[g] = -1;  
307
      }
308
   
309
    String ret="(";
310
    int f;
311
   
312
    for(int g=0; g<max; g++) 
313
      {
314
      f = getEffectIndex(g);
315
      if( f>=0 ) indexes[f] = g;
316
      }
317
   
318
    for(int g=0; g<mMax[mMaxIndex]; g++)
319
      {
320
      ret += (g>0 ? ",":"")+(indexes[g]>=0 ? indexes[g] : " ");   
321
      }
322
   
323
    ret += ")";
324
   
325
    return ret;
326
    }
327

    
328
///////////////////////////////////////////////////////////////////////////////////////////////////
329
// Only used for debugging
330
  
331
  protected boolean printByID(long id)
332
    {
333
    int index = getEffectIndex(id);
334
   
335
    if( index>=0 ) 
336
      {
337
      boolean inter0 = mInter[0][index]==null;
338
      boolean inter1 = mInter[1][index]==null;
339
      boolean inter2 = mInter[2][index]==null;
340

    
341
      android.util.Log.e("EffectQueue", "numEffects="+mNumEffects+" effect id="+id+" index="+index+
342
                         " duration="+mCurrentDuration[index]+" inter[0] null="+inter0+" inter[1] null="+inter1+" inter[2] null="+inter2);
343
      
344
      if( !inter0 )
345
        {
346
        android.util.Log.e("EffectQueue","inter[0]: "+mInter[0][index].print());
347
        }
348
      if( !inter1 )
349
        {
350
        android.util.Log.e("EffectQueue","inter[1]: "+mInter[1][index].print());
351
        }
352
      if( !inter2 )
353
        {
354
        android.util.Log.e("EffectQueue","inter[2]: "+mInter[2][index].print());
355
        }
356

    
357
      return true;
358
      }
359
   
360
    android.util.Log.e("EffectQueue", "effect id="+id+" not found");
361

    
362
    return false;  
363
    }
364
 
365
///////////////////////////////////////////////////////////////////////////////////////////////////
366

    
367
  abstract void moveEffect(int index);
368
  }
369
///////////////////////////////////////////////////////////////////////////////////////////////////
(13-13/17)