Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / effects / fastscramble / FastScrambleEffect.java @ 00057bb1

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2022 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.effects.fastscramble;
11

    
12
import java.lang.reflect.Method;
13
import java.util.Random;
14

    
15
import org.distorted.library.effect.Effect;
16
import org.distorted.library.main.DistortedEffects;
17
import org.distorted.library.message.EffectListener;
18

    
19
import org.distorted.objectlib.main.ObjectPreRender;
20
import org.distorted.objectlib.main.TwistyObject;
21

    
22
import org.distorted.objectlib.effects.BaseEffect;
23
import org.distorted.objectlib.main.TwistyObjectNode;
24

    
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

    
27
public abstract class FastScrambleEffect extends BaseEffect implements EffectListener
28
{
29
  public enum Type
30
    {
31
    SPIN   (FastScrambleEffectSpin.class),
32
    ;
33

    
34
    final Class<? extends FastScrambleEffect> effect;
35

    
36
    Type(Class<? extends FastScrambleEffect> effect)
37
      {
38
      this.effect = effect;
39
      }
40
    }
41

    
42
  private static final int NUM_EFFECTS = Type.values().length;
43
  private static final int NUM_PHASES  = 2;
44
  private static final int FAKE_EFFECT_ID = -5;
45
  private static final Type[] types;
46

    
47
  static
48
    {
49
    int i=0;
50
    types = new Type[NUM_EFFECTS];
51

    
52
    for(Type type: Type.values())
53
      {
54
      types[i++] = type;
55
      }
56
    }
57

    
58
  private int mDuration;
59
  private int mEffectReturned;
60
  private final int[] mCubeEffectNumber, mNodeEffectNumber;
61
  private int mPhase;
62
  private final Random mRnd;
63
  private final Object mLock;
64
  int mNumScrambles;
65
  int[][] mScrambles;
66

    
67
  ObjectPreRender mPre;
68
  TwistyObject mObject;
69
  TwistyObjectNode mObjectNode;
70
  Effect[][] mCubeEffects;
71
  int[][] mCubeEffectPosition;
72
  Effect[][] mNodeEffects;
73
  int[][] mNodeEffectPosition;
74

    
75
///////////////////////////////////////////////////////////////////////////////////////////////////
76

    
77
  FastScrambleEffect()
78
    {
79
    mLock = new Object();
80
    mRnd = new Random( System.currentTimeMillis() );
81

    
82
    mPhase= 0;
83

    
84
    mCubeEffectNumber   = new int[NUM_PHASES];
85
    mNodeEffectNumber   = new int[NUM_PHASES];
86
    mCubeEffectPosition = new int[NUM_PHASES][];
87
    mNodeEffectPosition = new int[NUM_PHASES][];
88
    mCubeEffects        = new Effect[NUM_PHASES][];
89
    mNodeEffects        = new Effect[NUM_PHASES][];
90
    }
91

    
92
///////////////////////////////////////////////////////////////////////////////////////////////////
93

    
94
  abstract void createEffectsPhase0(int duration);
95
  abstract void createEffectsPhase1(int duration);
96

    
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98

    
99
  private void createScrambles()
100
    {
101
    mScrambles = new int[mNumScrambles][3];
102

    
103
    if( mObject!=null )
104
      {
105
      synchronized(mLock)
106
        {
107
        for(int scramble=0; scramble<mNumScrambles; scramble++)
108
          {
109
          mObject.randomizeNewScramble(mScrambles, mRnd, scramble, mNumScrambles);
110
          }
111
        }
112
      }
113
    }
114

    
115
///////////////////////////////////////////////////////////////////////////////////////////////////
116

    
117
  private void assignEffects(int phase)
118
    {
119
    mCubeEffectNumber[phase] = ( mCubeEffects[phase]!=null ) ? mCubeEffects[phase].length : 0;
120
    mNodeEffectNumber[phase] = ( mNodeEffects[phase]!=null ) ? mNodeEffects[phase].length : 0;
121

    
122
    if( mCubeEffectNumber[phase]==0 && mNodeEffectNumber[phase]==0 )
123
      {
124
      throw new RuntimeException("Cube and Node Effects ("+phase+" phase) both not created!");
125
      }
126

    
127
    for(int i=0; i<mCubeEffectNumber[phase]; i++)
128
      {
129
      mObject.applyEffect(mCubeEffects[phase][i],mCubeEffectPosition[phase][i]);
130
      mCubeEffects[phase][i].notifyWhenFinished(this);
131
      }
132

    
133
    DistortedEffects nodeEffects = mObjectNode.getEffects();
134

    
135
    for(int i=0; i<mNodeEffectNumber[phase]; i++)
136
      {
137
      nodeEffects.apply(mNodeEffects[phase][i],mNodeEffectPosition[phase][i]);
138
      mNodeEffects[phase][i].notifyWhenFinished(this);
139
      }
140
    }
141

    
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143

    
144
  private void effectAction(int phase)
145
    {
146
    switch(phase)
147
      {
148
      case 0: mEffectReturned = 0;
149
              mPhase          = 1;
150

    
151
              // do not start initializing the Object until we have finished creating moves!
152
              synchronized(mLock)
153
                {
154
                mPre.applyScrambles(mScrambles);
155
                }
156

    
157
              createEffectsPhase1(mDuration);
158
              assignEffects(mPhase);
159
              break;
160
      case 1: mPre.effectFinished(FAKE_EFFECT_ID);
161
              break;
162
      }
163
    }
164

    
165
///////////////////////////////////////////////////////////////////////////////////////////////////
166
// PUBLIC API
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  @SuppressWarnings("unused")
170
  public static String[] getNames()
171
    {
172
    String[] names = new String[NUM_EFFECTS];
173

    
174
    for( int i=0; i<NUM_EFFECTS; i++)
175
      {
176
      names[i] = types[i].name();
177
      }
178

    
179
    return names;
180
    }
181

    
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183

    
184
  @SuppressWarnings("unused")
185
  public static FastScrambleEffect create(int ordinal) throws InstantiationException, IllegalAccessException
186
    {
187
    return types[ordinal].effect.newInstance();
188
    }
189

    
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191

    
192
  public void effectFinished(final long effectID)
193
    {
194
    int total = mCubeEffectNumber[mPhase]+mNodeEffectNumber[mPhase];
195

    
196
    for(int i=0; i<mCubeEffectNumber[mPhase]; i++)
197
      {
198
      long id = mCubeEffects[mPhase][i].getID();
199

    
200
      if( effectID == id )
201
        {
202
        if( ++mEffectReturned == total ) effectAction(mPhase);
203
        mObject.removeEffect(id);
204
        return;
205
        }
206
      }
207
    for(int i=0; i<mNodeEffectNumber[mPhase]; i++)
208
      {
209
      long id = mNodeEffects[mPhase][i].getID();
210

    
211
      if( effectID == id )
212
        {
213
        if( ++mEffectReturned == total ) effectAction(mPhase);
214
        mObjectNode.getEffects().abortById(id);
215
        return;
216
        }
217
      }
218
    }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221

    
222
  @SuppressWarnings("unused")
223
  public long start(int duration, ObjectPreRender pre)
224
    {
225
    mObject       = pre.getObject();
226
    mObjectNode   = pre.getObjectNode();
227
    mPre          = pre;
228
    mDuration     = duration;
229
    mNumScrambles = pre.getNumScrambles();
230

    
231
    Thread thread = new Thread()
232
      {
233
      public void run()
234
        {
235
        createScrambles();
236
        }
237
      };
238

    
239
    thread.start();
240

    
241
    createEffectsPhase0(mDuration);
242
    assignEffects(mPhase);
243

    
244
    return FAKE_EFFECT_ID;
245
    }
246

    
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248

    
249
  @SuppressWarnings("unused")
250
  public static void enableEffects()
251
    {
252
    Method method;
253

    
254
    for(Type type: Type.values())
255
      {
256
      try
257
        {
258
        method = type.effect.getDeclaredMethod("enable"); // enable not public, thus getDeclaredMethod
259
        }
260
      catch(NoSuchMethodException ex)
261
        {
262
        android.util.Log.e("FastScrambleEffect", type.effect.getSimpleName()+": exception getting method: "+ex.getMessage());
263
        method = null;
264
        }
265

    
266
      try
267
        {
268
        if( method!=null ) method.invoke(null);
269
        }
270
      catch(Exception ex)
271
        {
272
        android.util.Log.e("FastScrambleEffect", type.effect.getSimpleName()+": exception invoking method: "+ex.getMessage());
273
        }
274
      }
275
    }
276
}
(1-1/2)