Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / effects / scramble / ScrambleEffect.java @ 7ba38dd4

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube 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
// Magic Cube 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 Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objectlib.effects.scramble;
21

    
22
import java.lang.reflect.Method;
23
import java.util.Random;
24

    
25
import org.distorted.library.effect.Effect;
26
import org.distorted.library.main.DistortedEffects;
27
import org.distorted.library.main.DistortedFramebuffer;
28
import org.distorted.library.message.EffectListener;
29

    
30
import org.distorted.objectlib.main.ObjectPreRender;
31
import org.distorted.objectlib.main.ObjectType;
32
import org.distorted.objectlib.main.TwistyObject;
33
import org.distorted.objectlib.effects.BaseEffect;
34
import org.distorted.objectlib.helpers.MovesFinished;
35
import org.distorted.objectlib.main.TwistyObjectNode;
36

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

    
39
public abstract class ScrambleEffect extends BaseEffect implements EffectListener, MovesFinished
40
{
41
  public enum Type
42
    {
43
    NONE         (ScrambleEffectNone.class        ),
44
    ROTATIONS    (ScrambleEffectRotations.class   ),
45
    ;
46

    
47
    final Class<? extends ScrambleEffect> effect;
48

    
49
    Type(Class<? extends ScrambleEffect> effect)
50
      {
51
      this.effect= effect;
52
      }
53
    }
54

    
55
  private static final int NUM_EFFECTS = Type.values().length;
56
  private static final int FAKE_EFFECT_ID  = -3;
57
  private static final Type[] types;
58

    
59
  static
60
    {
61
    int i=0;
62
    types = new Type[NUM_EFFECTS];
63

    
64
    for(Type type: Type.values())
65
      {
66
      types[i++] = type;
67
      }
68
    }
69

    
70

    
71
  private int mEffectReturned;
72
  private int mNumScramblesLeft;
73
  private int mDurationPerDegree;
74
  private final Random mRnd;
75
  private int[] mBasicAngle;
76
  private boolean mRotReady, mPluginReady;
77

    
78
  ObjectPreRender mPre;
79
  TwistyObject mObject;
80
  TwistyObjectNode mObjectNode;
81
  Effect[] mNodeEffects;
82
  int[] mNodeEffectPosition;
83
  Effect[] mCubeEffects;
84
  int[] mCubeEffectPosition;
85
  int mCubeEffectNumber, mNodeEffectNumber;
86
  int mNumScrambles;
87
  int[][] mScrambles;
88

    
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90

    
91
  ScrambleEffect()
92
    {
93
    mRnd = new Random( System.currentTimeMillis() );
94
    mScrambles = new int[ObjectType.MAX_SCRAMBLE][3];
95
    }
96

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

    
99
  abstract void createEffects(int duration, int numScrambles);
100
  abstract void effectFinishedPlugin(final long effectID);
101

    
102
///////////////////////////////////////////////////////////////////////////////////////////////////
103

    
104
  private void createBaseEffects(int duration, int numScrambles)
105
    {
106
    mNumScramblesLeft = numScrambles;
107
    int absAngle, angle, axis, basicDegrees, totalDegrees = 0;
108

    
109
    for(int scramble=0; scramble<mNumScramblesLeft; scramble++)
110
      {
111
      mObject.randomizeNewScramble(mScrambles, mRnd, scramble, numScrambles);
112
      axis  = mScrambles[scramble][0];
113
      angle = mScrambles[scramble][2];
114
      absAngle = (angle<0 ? -angle : angle);
115
      basicDegrees = 360/mBasicAngle[axis];
116
      totalDegrees += absAngle*basicDegrees;
117
      }
118

    
119
    mDurationPerDegree = duration/totalDegrees;
120
    mNumScrambles = 0;
121

    
122
    mRotReady    = false;
123
    mPluginReady = false;
124

    
125
    addNewScramble();
126
    }
127

    
128
///////////////////////////////////////////////////////////////////////////////////////////////////
129

    
130
  private void addNewScramble()
131
    {
132
    if( mNumScramblesLeft>0 )
133
      {
134
      int axis = mScrambles[mNumScrambles][0];
135
      int row  = mScrambles[mNumScrambles][1];
136
      int angle= mScrambles[mNumScrambles][2];
137

    
138
      mNumScramblesLeft--;
139
      mPre.addRotation(this, axis, (1<<row), angle, mDurationPerDegree);
140
      mNumScrambles++;
141
      }
142
    else
143
      {
144
      mRotReady = true;
145
      if( mPluginReady ) mPre.effectFinished(FAKE_EFFECT_ID);
146
      }
147
    }
148

    
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150

    
151
  private void assignEffects()
152
    {
153
    for(int i=0; i<mCubeEffectNumber; i++)
154
      {
155
      mObject.apply(mCubeEffects[i],mCubeEffectPosition[i]);
156
      mCubeEffects[i].notifyWhenFinished(this);
157
      }
158

    
159
    DistortedEffects nodeEffects = mObjectNode.getEffects();
160

    
161
    for(int i=0; i<mNodeEffectNumber; i++)
162
      {
163
      nodeEffects.apply(mNodeEffects[i],mNodeEffectPosition[i]);
164
      mNodeEffects[i].notifyWhenFinished(this);
165
      }
166
    }
167

    
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169

    
170
  private void disassignEffects()
171
    {
172
    for(int i=0; i<mCubeEffectNumber; i++)
173
      {
174
      mObject.remove(mCubeEffects[i].getID());
175
      }
176

    
177
    DistortedEffects nodeEffects = mObjectNode.getEffects();
178

    
179
    for(int i=0; i<mNodeEffectNumber; i++)
180
      {
181
      nodeEffects.abortById(mNodeEffects[i].getID());
182
      }
183
    }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186
// PUBLIC API
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

    
189
  @SuppressWarnings("unused")
190
  public static String[] getNames()
191
    {
192
    String[] names = new String[NUM_EFFECTS];
193

    
194
    for( int i=0; i<NUM_EFFECTS; i++)
195
      {
196
      names[i] = types[i].name();
197
      }
198

    
199
    return names;
200
    }
201

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203

    
204
  @SuppressWarnings("unused")
205
  public static ScrambleEffect create(int ordinal) throws InstantiationException, IllegalAccessException
206
    {
207
    return types[ordinal].effect.newInstance();
208
    }
209

    
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211

    
212
  public void onActionFinished(final long effectID)
213
    {
214
    addNewScramble();
215
    }
216

    
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218

    
219
  private void effectFinishedAction(final long effectID, final long id)
220
    {
221
    mEffectReturned++;
222
    effectFinishedPlugin(effectID);
223

    
224
    if( mEffectReturned == mCubeEffectNumber+mNodeEffectNumber )
225
      {
226
      disassignEffects();
227

    
228
      mPluginReady = true;
229
      if( mRotReady ) mPre.effectFinished(FAKE_EFFECT_ID);
230
      }
231
    }
232

    
233
///////////////////////////////////////////////////////////////////////////////////////////////////
234

    
235
  public void effectFinished(final long effectID)
236
    {
237
    for(int i=0; i<mCubeEffectNumber; i++)
238
      {
239
      long id = mCubeEffects[i].getID();
240

    
241
      if( effectID == id )
242
        {
243
        effectFinishedAction(effectID,id);
244
        return;
245
        }
246
      }
247

    
248
    for(int i=0; i<mNodeEffectNumber; i++)
249
      {
250
      long id = mNodeEffects[i].getID();
251

    
252
      if( effectID == id )
253
        {
254
        effectFinishedAction(effectID,id);
255
        return;
256
        }
257
      }
258
    }
259

    
260
///////////////////////////////////////////////////////////////////////////////////////////////////
261

    
262
  @SuppressWarnings("unused")
263
  public long start(int duration, ObjectPreRender pre)
264
    {
265
    mObject     = pre.getObject();
266
    mObjectNode = pre.getObjectNode();
267
    mPre        = pre;
268

    
269
    // NOT mController.solve() !! This would be a very subtle bug. We need to do this immediately,
270
    // because here we are already inside the mController.preRender() function (doing 'scrambleObjectNow')
271
    // and doing a delayed 'solve()' here would mean we'd be sometimes first doing the first rotation,
272
    // and only after it - the solve.
273
    mObject.solve();
274

    
275
    mBasicAngle = mObject.getBasicAngle();
276

    
277
    int numScrambles = pre.getNumScrambles();
278
    int dura = (int)(duration*Math.pow(numScrambles,0.66f));
279
    createBaseEffects(dura,numScrambles);
280
    createEffects    (dura,numScrambles);
281

    
282
    if( mCubeEffectNumber==0 && mNodeEffectNumber==0 )
283
      {
284
      throw new RuntimeException("Cube and Node Plugin Effects not created!");
285
      }
286

    
287
    assignEffects();
288

    
289
    return FAKE_EFFECT_ID;
290
    }
291

    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293

    
294
  @SuppressWarnings("unused")
295
  public static void enableEffects()
296
    {
297
    Method method;
298

    
299
    for(Type type: Type.values())
300
      {
301
      try
302
        {
303
        method = type.effect.getDeclaredMethod("enable"); // enable not public, thus getDeclaredMethod
304
        }
305
      catch(NoSuchMethodException ex)
306
        {
307
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception getting method: "+ex.getMessage());
308
        method = null;
309
        }
310

    
311
      try
312
        {
313
        if( method!=null ) method.invoke(null);
314
        }
315
      catch(Exception ex)
316
        {
317
        android.util.Log.e("ScrambleEffect", type.effect.getSimpleName()+": exception invoking method: "+ex.getMessage());
318
        }
319
      }
320
    }
321
}
(1-1/3)