Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / effects / scramble / ScrambleEffect.java @ 826d293e

1 a5a52e8d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6 9ec1348c Leszek Koltunski
// 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 a5a52e8d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10
package org.distorted.objectlib.effects.scramble;
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 ecf3d6e3 Leszek Koltunski
import org.distorted.objectlib.main.ObjectPreRender;
20 a5a52e8d Leszek Koltunski
import org.distorted.objectlib.main.TwistyObject;
21
import org.distorted.objectlib.effects.BaseEffect;
22
import org.distorted.objectlib.helpers.MovesFinished;
23 7ba38dd4 Leszek Koltunski
import org.distorted.objectlib.main.TwistyObjectNode;
24 a5a52e8d Leszek Koltunski
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26
27
public abstract class ScrambleEffect extends BaseEffect implements EffectListener, MovesFinished
28
{
29
  public enum Type
30
    {
31
    NONE         (ScrambleEffectNone.class        ),
32
    ROTATIONS    (ScrambleEffectRotations.class   ),
33
    ;
34
35
    final Class<? extends ScrambleEffect> effect;
36
37
    Type(Class<? extends ScrambleEffect> effect)
38
      {
39
      this.effect= effect;
40
      }
41
    }
42
43
  private static final int NUM_EFFECTS = Type.values().length;
44
  private static final int FAKE_EFFECT_ID  = -3;
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 mEffectReturned;
59
  private int mNumScramblesLeft;
60 2df35810 Leszek Koltunski
  private int mDurationPerDegree;
61 a5a52e8d Leszek Koltunski
  private final Random mRnd;
62 beee90ab Leszek Koltunski
  private int[][] mBasicAngle;
63 a5a52e8d Leszek Koltunski
  private boolean mRotReady, mPluginReady;
64
65 02d80fe6 Leszek Koltunski
  ObjectPreRender mPre;
66 a5a52e8d Leszek Koltunski
  TwistyObject mObject;
67 7ba38dd4 Leszek Koltunski
  TwistyObjectNode mObjectNode;
68 a5a52e8d Leszek Koltunski
  Effect[] mNodeEffects;
69
  int[] mNodeEffectPosition;
70
  Effect[] mCubeEffects;
71
  int[] mCubeEffectPosition;
72
  int mCubeEffectNumber, mNodeEffectNumber;
73
  int mNumScrambles;
74
  int[][] mScrambles;
75
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77
78
  ScrambleEffect()
79
    {
80
    mRnd = new Random( System.currentTimeMillis() );
81
    }
82
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84
85
  abstract void createEffects(int duration, int numScrambles);
86
  abstract void effectFinishedPlugin(final long effectID);
87
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89
90
  private void createBaseEffects(int duration, int numScrambles)
91
    {
92
    mNumScramblesLeft = numScrambles;
93 beee90ab Leszek Koltunski
    int absAngle, angle, axis, row, basicDegrees, totalDegrees = 0;
94 a5a52e8d Leszek Koltunski
95
    for(int scramble=0; scramble<mNumScramblesLeft; scramble++)
96
      {
97
      mObject.randomizeNewScramble(mScrambles, mRnd, scramble, numScrambles);
98
      axis  = mScrambles[scramble][0];
99 beee90ab Leszek Koltunski
      row   = mScrambles[scramble][1];
100 a5a52e8d Leszek Koltunski
      angle = mScrambles[scramble][2];
101
      absAngle = (angle<0 ? -angle : angle);
102 beee90ab Leszek Koltunski
      basicDegrees = 360/mBasicAngle[axis][row];
103 a5a52e8d Leszek Koltunski
      totalDegrees += absAngle*basicDegrees;
104
      }
105
106
    mDurationPerDegree = duration/totalDegrees;
107
    mNumScrambles = 0;
108
109
    mRotReady    = false;
110
    mPluginReady = false;
111
112
    addNewScramble();
113
    }
114
115
///////////////////////////////////////////////////////////////////////////////////////////////////
116
117
  private void addNewScramble()
118
    {
119
    if( mNumScramblesLeft>0 )
120
      {
121
      int axis = mScrambles[mNumScrambles][0];
122
      int row  = mScrambles[mNumScrambles][1];
123
      int angle= mScrambles[mNumScrambles][2];
124
125
      mNumScramblesLeft--;
126 ecf3d6e3 Leszek Koltunski
      mPre.addRotation(this, axis, (1<<row), angle, mDurationPerDegree);
127 a5a52e8d Leszek Koltunski
      mNumScrambles++;
128
      }
129
    else
130
      {
131
      mRotReady = true;
132 ecf3d6e3 Leszek Koltunski
      if( mPluginReady ) mPre.effectFinished(FAKE_EFFECT_ID);
133 a5a52e8d Leszek Koltunski
      }
134
    }
135
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137
138
  private void assignEffects()
139
    {
140
    for(int i=0; i<mCubeEffectNumber; i++)
141
      {
142 826d293e Leszek Koltunski
      mObject.applyEffect(mCubeEffects[i],mCubeEffectPosition[i]);
143 a5a52e8d Leszek Koltunski
      mCubeEffects[i].notifyWhenFinished(this);
144
      }
145
146 7ba38dd4 Leszek Koltunski
    DistortedEffects nodeEffects = mObjectNode.getEffects();
147 a5a52e8d Leszek Koltunski
148
    for(int i=0; i<mNodeEffectNumber; i++)
149
      {
150
      nodeEffects.apply(mNodeEffects[i],mNodeEffectPosition[i]);
151
      mNodeEffects[i].notifyWhenFinished(this);
152
      }
153
    }
154
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156
157
  private void disassignEffects()
158
    {
159
    for(int i=0; i<mCubeEffectNumber; i++)
160
      {
161 826d293e Leszek Koltunski
      mObject.removeEffect(mCubeEffects[i].getID());
162 a5a52e8d Leszek Koltunski
      }
163
164 7ba38dd4 Leszek Koltunski
    DistortedEffects nodeEffects = mObjectNode.getEffects();
165 a5a52e8d Leszek Koltunski
166
    for(int i=0; i<mNodeEffectNumber; i++)
167
      {
168
      nodeEffects.abortById(mNodeEffects[i].getID());
169
      }
170
    }
171
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173
// PUBLIC API
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175
176
  @SuppressWarnings("unused")
177
  public static String[] getNames()
178
    {
179
    String[] names = new String[NUM_EFFECTS];
180
181
    for( int i=0; i<NUM_EFFECTS; i++)
182
      {
183
      names[i] = types[i].name();
184
      }
185
186
    return names;
187
    }
188
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190
191
  @SuppressWarnings("unused")
192
  public static ScrambleEffect create(int ordinal) throws InstantiationException, IllegalAccessException
193
    {
194
    return types[ordinal].effect.newInstance();
195
    }
196
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198
199
  public void onActionFinished(final long effectID)
200
    {
201
    addNewScramble();
202
    }
203
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205
206 5cc61ae4 Leszek Koltunski
  private void effectFinishedAction(final long effectID)
207 a5a52e8d Leszek Koltunski
    {
208
    mEffectReturned++;
209
    effectFinishedPlugin(effectID);
210
211
    if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
212
      {
213
      disassignEffects();
214
215
      mPluginReady = true;
216 ecf3d6e3 Leszek Koltunski
      if( mRotReady ) mPre.effectFinished(FAKE_EFFECT_ID);
217 a5a52e8d Leszek Koltunski
      }
218
    }
219
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221
222
  public void effectFinished(final long effectID)
223
    {
224
    for(int i=0; i<mCubeEffectNumber; i++)
225
      {
226
      long id = mCubeEffects[i].getID();
227
228
      if( effectID == id )
229
        {
230 5cc61ae4 Leszek Koltunski
        effectFinishedAction(effectID);
231 a5a52e8d Leszek Koltunski
        return;
232
        }
233
      }
234
235
    for(int i=0; i<mNodeEffectNumber; i++)
236
      {
237
      long id = mNodeEffects[i].getID();
238
239
      if( effectID == id )
240
        {
241 5cc61ae4 Leszek Koltunski
        effectFinishedAction(effectID);
242 a5a52e8d Leszek Koltunski
        return;
243
        }
244
      }
245
    }
246
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248
249
  @SuppressWarnings("unused")
250 7ba38dd4 Leszek Koltunski
  public long start(int duration, ObjectPreRender pre)
251 a5a52e8d Leszek Koltunski
    {
252 7ba38dd4 Leszek Koltunski
    mObject     = pre.getObject();
253
    mObjectNode = pre.getObjectNode();
254
    mPre        = pre;
255 a5a52e8d Leszek Koltunski
256
    // NOT mController.solve() !! This would be a very subtle bug. We need to do this immediately,
257
    // because here we are already inside the mController.preRender() function (doing 'scrambleObjectNow')
258
    // and doing a delayed 'solve()' here would mean we'd be sometimes first doing the first rotation,
259
    // and only after it - the solve.
260
    mObject.solve();
261
262 802fe251 Leszek Koltunski
    mBasicAngle = mObject.getBasicAngles();
263 a5a52e8d Leszek Koltunski
264 ecf3d6e3 Leszek Koltunski
    int numScrambles = pre.getNumScrambles();
265 5cc61ae4 Leszek Koltunski
    mScrambles = new int[numScrambles][3];
266 a5a52e8d Leszek Koltunski
    int dura = (int)(duration*Math.pow(numScrambles,0.66f));
267
    createBaseEffects(dura,numScrambles);
268
    createEffects    (dura,numScrambles);
269
270
    if( mCubeEffectNumber==0 && mNodeEffectNumber==0 )
271
      {
272
      throw new RuntimeException("Cube and Node Plugin Effects not created!");
273
      }
274
275
    assignEffects();
276
277
    return FAKE_EFFECT_ID;
278
    }
279
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281
282
  @SuppressWarnings("unused")
283
  public static void enableEffects()
284
    {
285
    Method method;
286
287
    for(Type type: Type.values())
288
      {
289
      try
290
        {
291
        method = type.effect.getDeclaredMethod("enable"); // enable not public, thus getDeclaredMethod
292
        }
293
      catch(NoSuchMethodException ex)
294
        {
295
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception getting method: "+ex.getMessage());
296
        method = null;
297
        }
298
299
      try
300
        {
301
        if( method!=null ) method.invoke(null);
302
        }
303
      catch(Exception ex)
304
        {
305
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception invoking method: "+ex.getMessage());
306
        }
307
      }
308
    }
309
}