Project

General

Profile

« Previous | Next » 

Revision 20dbec0e

Added by Leszek Koltunski about 5 years ago

Simplify the way applications can get notifications when an effect finishes.

Now, instead of the 'DistortedEffects.(de)registerForNotifications()' 2 APIs, we call a single 'Effect.notifyWhenFinished()'.

View differences:

src/main/java/org/distorted/library/effect/Effect.java
19 19

  
20 20
package org.distorted.library.effect;
21 21

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

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

  
24 27
///////////////////////////////////////////////////////////////////////////////////////////////////
25 28
/**
......
37 40
  private final int mRegionDim;
38 41
  private final int mCenterDim;
39 42

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

  
40 46
  private static long mNextID = 0;
41 47

  
42 48
  private final static float[] mUnity= new float[MAX_UNITY_DIM*NUM_EFFECTS];
......
99 105
 */
100 106
  public abstract boolean compute(float[] uniforms, int index, long currentDuration, long step );
101 107

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

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

  
133
    return null;
134
    }
135

  
102 136
///////////////////////////////////////////////////////////////////////////////////////////////////
103 137
// PUBLIC API
104 138
///////////////////////////////////////////////////////////////////////////////////////////////////
......
233 267
    {
234 268
    return mDimension;
235 269
    }
270

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

  
285
    if( !mListeners.contains(el) )
286
      {
287
      mListeners.add(el);
288
      mNumListeners++;
289
      }
290
    }
236 291
  }
src/main/java/org/distorted/library/effectqueue/EffectQueue.java
24 24
import org.distorted.library.effect.EffectType;
25 25
import org.distorted.library.main.DistortedLibrary;
26 26
import org.distorted.library.main.InternalMaster;
27
import org.distorted.library.message.EffectListener;
28
import org.distorted.library.message.EffectMessage;
29
import org.distorted.library.message.EffectMessageSender;
30 27

  
31 28
import java.util.ArrayList;
32 29
import java.util.HashMap;
......
53 50
  Effect[] mEffects;
54 51
  int[] mName;
55 52
  long mTime=0;
56
  ArrayList<EffectListener> mListeners =null;
57
  int mNumListeners=0;  // ==mListeners.length(), but we only create mListeners if the first one gets added
58
  long mDistortedEffectsID;
59 53

  
60 54
  private static int[] mMax = new int[EffectType.LENGTH];
61 55
  private static long mNextID;
......
90 84
  
91 85
///////////////////////////////////////////////////////////////////////////////////////////////////
92 86
   
93
  EffectQueue(long id, int numUniforms, int index)
87
  EffectQueue(int numUniforms, int index)
94 88
    {
95 89
    mCreated            = false;
96 90
    mID                 = 0;
97 91
    mNumEffects         = 0;
98 92
    mNumEffectsToBe     = 0;
99
    mDistortedEffectsID = id;
100 93
    mIndex              = index;
101 94

  
102 95
    mJobs.add(new Job(CREATE,numUniforms,false,null));  // create the stuff that depends on max number
......
105 98

  
106 99
///////////////////////////////////////////////////////////////////////////////////////////////////
107 100

  
108
  public static void allocateQueues(EffectQueue[] queues, EffectQueue[] from, int flags, long id)
101
  public static void allocateQueues(EffectQueue[] queues, EffectQueue[] from, int flags)
109 102
    {
110
    queues[0] = (flags & DistortedLibrary.CLONE_MATRIX     ) != 0 ? from[0] : new EffectQueueMatrix(id);
111
    queues[1] = (flags & DistortedLibrary.CLONE_VERTEX     ) != 0 ? from[1] : new EffectQueueVertex(id);
112
    queues[2] = (flags & DistortedLibrary.CLONE_FRAGMENT   ) != 0 ? from[2] : new EffectQueueFragment(id);
113
    queues[3] = (flags & DistortedLibrary.CLONE_POSTPROCESS) != 0 ? from[3] : new EffectQueuePostprocess(id);
103
    queues[0] = (flags & DistortedLibrary.CLONE_MATRIX     ) != 0 ? from[0] : new EffectQueueMatrix();
104
    queues[1] = (flags & DistortedLibrary.CLONE_VERTEX     ) != 0 ? from[1] : new EffectQueueVertex();
105
    queues[2] = (flags & DistortedLibrary.CLONE_FRAGMENT   ) != 0 ? from[2] : new EffectQueueFragment();
106
    queues[3] = (flags & DistortedLibrary.CLONE_POSTPROCESS) != 0 ? from[3] : new EffectQueuePostprocess();
114 107
    }
115 108

  
116 109
///////////////////////////////////////////////////////////////////////////////////////////////////
......
205 198
    return mMax[index];
206 199
    }
207 200

  
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

  
210
  public void registerForMessages(EffectListener el)
211
    {
212
    if( mListeners==null ) mListeners = new ArrayList<>();
213

  
214
    if( !mListeners.contains(el) )
215
      {
216
      mListeners.add(el);
217
      mNumListeners++;
218
      }
219
    }
220
 
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

  
223
  public void deregisterForMessages(EffectListener el)
224
    {
225
    if( mListeners.remove(el) )
226
      {
227
      mNumListeners--;
228
      }
229
    }
230

  
231 201
///////////////////////////////////////////////////////////////////////////////////////////////////
232 202

  
233 203
  public static void onDestroy()
......
244 214
    {
245 215
    mNumEffects--;
246 216

  
247
    long removedID = mEffects[effect].getID();
248

  
249 217
    for(int j=effect; j<mNumEffects; j++ )
250 218
      {
251 219
      mEffects[j]         = mEffects[j+1];
......
254 222
      }
255 223

  
256 224
    mEffects[mNumEffects] = null;
257

  
258
    for(int i=0; i<mNumListeners; i++)
259
      EffectMessageSender.newMessage( mListeners.get(i), EffectMessage.EFFECT_REMOVED, removedID, mDistortedEffectsID);
260 225
    }
261 226

  
262 227
///////////////////////////////////////////////////////////////////////////////////////////////////
......
441 406
        case DETALL: for(int j=0; j<mNumEffects; j++ )
442 407
                       {
443 408
                       changed = true;
444

  
445
                       if( job.notify )
446
                         {
447
                         for(int k=0; k<mNumListeners; k++)
448
                           EffectMessageSender.newMessage( mListeners.get(k), EffectMessage.EFFECT_REMOVED, mEffects[j].getID(), mDistortedEffectsID);
449
                         }
450

  
451 409
                       mEffects[j] = null;
452 410
                       }
453 411

  
src/main/java/org/distorted/library/effectqueue/EffectQueueFragment.java
23 23

  
24 24
import org.distorted.library.effect.EffectType;
25 25
import org.distorted.library.effect.FragmentEffect;
26
import org.distorted.library.message.EffectMessage;
27 26
import org.distorted.library.message.EffectMessageSender;
28 27

  
29 28
///////////////////////////////////////////////////////////////////////////////////////////////////
......
39 38

  
40 39
///////////////////////////////////////////////////////////////////////////////////////////////////
41 40
   
42
  EffectQueueFragment(long id)
41
  EffectQueueFragment()
43 42
    { 
44
    super(id,NUM_UNIFORMS,INDEX);
43
    super(NUM_UNIFORMS,INDEX);
45 44
    }
46 45

  
47 46
///////////////////////////////////////////////////////////////////////////////////////////////////
......
67 66

  
68 67
      if( mEffects[i].compute(mUniforms, NUM_UNIFORMS*i, mCurrentDuration[i], step) )
69 68
        {
70
        for(int j=0; j<mNumListeners; j++)
71
          EffectMessageSender.newMessage( mListeners.get(j), EffectMessage.EFFECT_FINISHED, mEffects[i].getID(), mDistortedEffectsID);
69
        EffectMessageSender.newMessage(mEffects[i]);
72 70
        }
73 71

  
74 72
      mUniforms[NUM_UNIFORMS*i+5] -= halfX;
src/main/java/org/distorted/library/effectqueue/EffectQueueMatrix.java
24 24

  
25 25
import org.distorted.library.effect.EffectType;
26 26
import org.distorted.library.effect.MatrixEffect;
27
import org.distorted.library.message.EffectMessage;
28 27
import org.distorted.library.message.EffectMessageSender;
29 28

  
30 29
///////////////////////////////////////////////////////////////////////////////////////////////////
......
48 47

  
49 48
///////////////////////////////////////////////////////////////////////////////////////////////////
50 49
   
51
  EffectQueueMatrix(long id)
50
  EffectQueueMatrix()
52 51
    { 
53
    super(id,NUM_UNIFORMS,INDEX );
52
    super(NUM_UNIFORMS,INDEX );
54 53
    }
55 54

  
56 55
///////////////////////////////////////////////////////////////////////////////////////////////////
......
128 127

  
129 128
      if( mEffects[i].compute(mUniforms, NUM_UNIFORMS*i, mCurrentDuration[i], step) )
130 129
        {
131
        for(int j=0; j<mNumListeners; j++)
132
          EffectMessageSender.newMessage( mListeners.get(j), EffectMessage.EFFECT_FINISHED, mEffects[i].getID(), mDistortedEffectsID);
130
        EffectMessageSender.newMessage(mEffects[i]);
133 131
        }
134 132
      }
135 133
     
src/main/java/org/distorted/library/effectqueue/EffectQueuePostprocess.java
34 34
import org.distorted.library.main.InternalRenderState;
35 35
import org.distorted.library.main.InternalSurface;
36 36
import org.distorted.library.mesh.MeshBase;
37
import org.distorted.library.message.EffectMessage;
38 37
import org.distorted.library.message.EffectMessageSender;
39 38
import org.distorted.library.program.DistortedProgram;
40 39

  
......
60 59

  
61 60
///////////////////////////////////////////////////////////////////////////////////////////////////
62 61

  
63
  EffectQueuePostprocess(long id)
62
  EffectQueuePostprocess()
64 63
    { 
65
    super(id,NUM_UNIFORMS,INDEX );
64
    super(NUM_UNIFORMS,INDEX );
66 65
    }
67 66

  
68 67
///////////////////////////////////////////////////////////////////////////////////////////////////
......
88 87

  
89 88
      if( mEffects[i].compute(mUniforms, NUM_UNIFORMS*i, mCurrentDuration[i], step) )
90 89
        {
91
        for(int j=0; j<mNumListeners; j++)
92
          EffectMessageSender.newMessage( mListeners.get(j), EffectMessage.EFFECT_FINISHED, mEffects[i].getID(), mDistortedEffectsID);
90
        EffectMessageSender.newMessage(mEffects[i]);
93 91
        }
94 92

  
95 93
      halo = (int)mUniforms[NUM_UNIFORMS*i];
src/main/java/org/distorted/library/effectqueue/EffectQueueVertex.java
23 23

  
24 24
import org.distorted.library.effect.EffectType;
25 25
import org.distorted.library.effect.VertexEffect;
26
import org.distorted.library.message.EffectMessage;
27 26
import org.distorted.library.message.EffectMessageSender;
28 27

  
29 28
///////////////////////////////////////////////////////////////////////////////////////////////////
......
40 39

  
41 40
///////////////////////////////////////////////////////////////////////////////////////////////////
42 41
   
43
  EffectQueueVertex(long id)
42
  EffectQueueVertex()
44 43
    { 
45
    super(id,NUM_UNIFORMS,INDEX);
44
    super(NUM_UNIFORMS,INDEX);
46 45
    }
47 46

  
48 47
///////////////////////////////////////////////////////////////////////////////////////////////////
......
69 68

  
70 69
      if( mEffects[i].compute(mUniforms, NUM_UNIFORMS*i, mCurrentDuration[i], step) )
71 70
        {
72
        for(int j=0; j<mNumListeners; j++)
73
          EffectMessageSender.newMessage( mListeners.get(j), EffectMessage.EFFECT_FINISHED, mEffects[i].getID(), mDistortedEffectsID);
71
        EffectMessageSender.newMessage(mEffects[i]);
74 72
        }
75 73

  
76 74
      mUniforms[NUM_UNIFORMS*i+5] -= halfX;
src/main/java/org/distorted/library/main/DistortedEffects.java
23 23
import org.distorted.library.effect.EffectName;
24 24
import org.distorted.library.effectqueue.EffectQueue;
25 25
import org.distorted.library.effect.EffectType;
26
import org.distorted.library.message.EffectListener;
27 26

  
28 27
///////////////////////////////////////////////////////////////////////////////////////////////////
29 28
/**
......
63 62
    {
64 63
    mID = ++mNextID;
65 64
    mQueues = new EffectQueue[EffectType.LENGTH];
66
    EffectQueue.allocateQueues(mQueues,null,0,mID);
65
    EffectQueue.allocateQueues(mQueues,null,0);
67 66
    }
68 67

  
69 68
///////////////////////////////////////////////////////////////////////////////////////////////////
......
80 79
    {
81 80
    mID = ++mNextID;
82 81
    mQueues = new EffectQueue[EffectType.LENGTH];
83
    EffectQueue.allocateQueues(mQueues,dc.getQueues(),flags,mID);
82
    EffectQueue.allocateQueues(mQueues,dc.getQueues(),flags);
84 83
    }
85 84

  
86 85
///////////////////////////////////////////////////////////////////////////////////////////////////
......
94 93
      return mID;
95 94
      }
96 95

  
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98
/**
99
 * Adds the calling class to the list of Listeners that get notified each time some event happens 
100
 * to one of the Effects in our queues. Nothing will happen if 'el' is already in the list.
101
 * 
102
 * @param el A class implementing the EffectListener interface that wants to get notifications.
103
 */
104
  public void registerForMessages(EffectListener el)
105
    {
106
    for( int i=0; i<EffectType.LENGTH; i++)
107
      {
108
      mQueues[i].registerForMessages(el);
109
      }
110
    }
111

  
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113
/**
114
 * Removes the calling class from the list of Listeners that get notified if something happens to Effects in our queue.
115
 * 
116
 * @param el A class implementing the EffectListener interface that no longer wants to get notifications.
117
 */
118
  public void deregisterForMessages(EffectListener el)
119
    {
120
    for( int i=0; i<EffectType.LENGTH; i++)
121
      {
122
      mQueues[i].deregisterForMessages(el);
123
      }
124
    }
125

  
126 96
///////////////////////////////////////////////////////////////////////////////////////////////////
127 97
/**
128 98
 * Aborts all Effects.
src/main/java/org/distorted/library/message/EffectListener.java
21 21

  
22 22
///////////////////////////////////////////////////////////////////////////////////////////////////
23 23

  
24
import org.distorted.library.main.DistortedEffects;
24
import org.distorted.library.effect.Effect;
25 25

  
26 26
/**
27
 * This interface lets users of the DistortedLibrary library get notified when something happens to one of the effects.
28
 * To receive the notifications, we first have to register with a call to {@link DistortedEffects#registerForMessages(EffectListener)}.
29
 * List of all possible events that can happen is defined in {@link EffectMessage}
27
 * This interface lets users of the DistortedLibrary library get notified when a given effect finishes.
28
 * To receive the notifications, we first have to register with a call to {@link Effect#notifyWhenFinished(EffectListener)}.
30 29
 */
31 30

  
32 31
public interface EffectListener 
33 32
  {
34 33
/**
35
 * Gets called when event of type 'eventType' happens to effect 'effectID'.
34
 * Gets called when Effect 'effectID' finishes execution (i.e. the Dynamic inside it reaches its final point).
36 35
 * 
37
 * @param eventType  Type of event that happened.
38
 * @param effectID   ID of the effect the event happened to, as returned by {@link org.distorted.library.effect.Effect#getID() }
39
 * @param objectID   the ID of the DistortedEffects object, as returned by {@link org.distorted.library.main.DistortedEffects#getID()},
40
 *                   this event happened to.
41
 * @see EffectMessage
36
 * @param effectID ID of the finished effect, as returned by {@link org.distorted.library.effect.Effect#getID() }
42 37
 */
43 38
   
44
  void effectMessage(final EffectMessage eventType, final long effectID, final long objectID);
39
  void effectFinished(final long effectID);
45 40
  }
46 41

  
47 42
///////////////////////////////////////////////////////////////////////////////////////////////////
src/main/java/org/distorted/library/message/EffectMessage.java
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.message;
21

  
22
///////////////////////////////////////////////////////////////////////////////////////////////////
23

  
24
import org.distorted.library.main.DistortedEffects;
25

  
26
/**
27
* Defines all possible events a class implementing the {@link EffectListener} interface can receive.
28
*/
29

  
30
public enum EffectMessage 
31
  {
32
/**
33
 * The effect has been removed. This can happen if someone explicitly removed the effect with a call to
34
 * {@link DistortedEffects#abortById(long)} (or one of the other 'abort' methods)
35
 */
36
  EFFECT_REMOVED,
37
  
38
/**
39
 * Interpolation of the effect has finished. 
40
 * <p>
41
 * If you set up an interpolated effect and set its Dynamic to do 3.5 interpolations of 1000 ms each
42
 * with calls to {@link org.distorted.library.type.Dynamic#setCount(float)} and {@link org.distorted.library.type.Dynamic#makeRunNowFor(long)},
43
 * then you are going to get this message exactly once after 3.5*1000 = 3500 milliseconds when the interpolation 
44
 * finishes. You will never get this message if you set the effect to go on indefinitely with a call to 
45
 * {@link org.distorted.library.type.Dynamic#setCount(float)} where float=0.0f.
46
 * <p>  
47
 * If then the end effect is equal to the effect's unity, then immediately after this message you
48
 * will also get a EFFECT_REMOVED message.
49
 */
50
  EFFECT_FINISHED
51
  }
52

  
53
///////////////////////////////////////////////////////////////////////////////////////////////////
src/main/java/org/distorted/library/message/EffectMessageSender.java
19 19

  
20 20
package org.distorted.library.message;
21 21

  
22
import org.distorted.library.effect.Effect;
23

  
22 24
import java.util.Vector;
23 25

  
24 26
///////////////////////////////////////////////////////////////////////////////////////////////////
......
32 34
  private class Message
33 35
    {
34 36
    EffectListener mListener;
35
    EffectMessage mMessage;
36 37
    long mEffectID;
37
    long mObjectID;
38 38

  
39
    Message(EffectListener l, EffectMessage m, long effID, long objID)
39
    Message(EffectListener listener, long effectID)
40 40
      {
41
      mListener = l;
42
      mMessage  = m;
43
      mEffectID = effID;
44
      mObjectID = objID;
41
      mListener = listener;
42
      mEffectID = effectID;
45 43
      }
46 44
    }
47 45
  
......
104 102
      while( mList.size()>0 )
105 103
        {
106 104
        tmp = mList.remove(0);
107
        tmp.mListener.effectMessage(tmp.mMessage, tmp.mEffectID, tmp.mObjectID);
105
        tmp.mListener.effectFinished(tmp.mEffectID);
108 106
        }
109 107

  
110 108
      synchronized(mThis)
......
124 122
  
125 123
///////////////////////////////////////////////////////////////////////////////////////////////////
126 124
        
127
  public static void newMessage(EffectListener l, EffectMessage m, long effID, long objID)
125
  public static void newMessage(Effect effect)
128 126
    {
129
    Message msg = mThis.new Message(l,m,effID,objID);
130
    mList.add(msg);
127
    int numListeners = effect.getNumListeners();
131 128

  
132
    synchronized(mThis)
129
    if( numListeners>0 )
133 130
      {
134
      mNotify = true;
135
      mThis.notify();
131
      long id = effect.getID();
132

  
133
      for(int i=0; i<numListeners; i++)
134
        {
135
        Message msg = mThis.new Message(effect.removeFirstListener(), id);
136
        mList.add(msg);
137
        }
138

  
139
      synchronized(mThis)
140
        {
141
        mNotify = true;
142
        mThis.notify();
143
        }
136 144
      }
137 145
    }
138 146
  }

Also available in: Unified diff