Project

General

Profile

« Previous | Next » 

Revision 47ba5ddc

Added by Leszek Koltunski over 4 years ago

RubikCube: further fixes

View differences:

src/main/java/org/distorted/component/HorizontalNumberPicker.java
36 36
  private TextView mNumber;
37 37
  private int mMin, mMax;
38 38

  
39
  public HorizontalNumberPicker(Context context, @Nullable AttributeSet attrs)
40
    {
41
    super(context, attrs);
42

  
43
    mMin = 0;
44
    mMax = 5;
45

  
46
    inflate(context, R.layout.numberpicker, this);
47

  
48
    mNumber = findViewById(R.id.textNumber);
49

  
50
    final Button btn_less = findViewById(R.id.buttonLess);
51
    btn_less.setOnClickListener(new AddHandler(-1));
52

  
53
    final Button btn_more = findViewById(R.id.buttonMore);
54
    btn_more.setOnClickListener(new AddHandler( 1));
55
    }
56

  
57
///////////////////////////////////////////////////////////////////////////////////////////////////
58

  
59 39
  private class AddHandler implements OnClickListener
60 40
    {
61 41
    final int diff;
......
82 62
      }
83 63
    }
84 64

  
65
///////////////////////////////////////////////////////////////////////////////////////////////////
66
// PUBLIC API
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

  
69
  public HorizontalNumberPicker(Context context, @Nullable AttributeSet attrs)
70
    {
71
    super(context, attrs);
72

  
73
    mMin = 0;
74
    mMax = 5;
75

  
76
    inflate(context, R.layout.numberpicker, this);
77

  
78
    mNumber = findViewById(R.id.textNumber);
79

  
80
    final Button btn_less = findViewById(R.id.buttonLess);
81
    btn_less.setOnClickListener(new AddHandler(-1));
82

  
83
    final Button btn_more = findViewById(R.id.buttonMore);
84
    btn_more.setOnClickListener(new AddHandler( 1));
85
    }
86

  
85 87
///////////////////////////////////////////////////////////////////////////////////////////////////
86 88

  
87 89
  public int getValue()
......
111 113
      }
112 114
    }
113 115

  
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115

  
116
  public int getMin()
117
    {
118
    return mMin;
119
    }
120

  
121 116
///////////////////////////////////////////////////////////////////////////////////////////////////
122 117

  
123 118
  public void setMin(int min)
......
125 120
    mMin = min;
126 121
    }
127 122

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

  
130
  public int getMax()
131
    {
132
    return mMax;
133
    }
134

  
135 123
///////////////////////////////////////////////////////////////////////////////////////////////////
136 124

  
137 125
  public void setMax(int max)
src/main/java/org/distorted/effect/BaseEffect.java
37 37
    {
38 38
    SIZECHANGE  ( 20, 1, R.string.sizechange_effect , SizeChangeEffect.class),
39 39
    SOLVE       ( 20, 1, R.string.solve_effect      , SolveEffect.class     ),
40
    SCRAMBLE    ( 20, 1, R.string.scramble_effect   , ScrambleEffect.class  ),
40
    SCRAMBLE    ( 30, 1, R.string.scramble_effect   , ScrambleEffect.class  ),
41 41
    WIN         ( 20, 1, R.string.win_effect        , WinEffect.class       ),
42 42
    ;
43 43

  
src/main/java/org/distorted/effect/scramble/ScrambleEffect.java
85 85
    mLastVector = -1;
86 86
    }
87 87

  
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89

  
90
  public static String[] getNames()
91
    {
92
    String[] names = new String[NUM_EFFECTS];
93

  
94
    for( int i=0; i<NUM_EFFECTS; i++)
95
      {
96
      names[i] = types[i].name();
97
      }
98

  
99
    return names;
100
    }
101

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

  
104
  public static ScrambleEffect create(int ordinal) throws InstantiationException, IllegalAccessException
105
    {
106
    return types[ordinal].effect.newInstance();
107
    }
108

  
109 88
///////////////////////////////////////////////////////////////////////////////////////////////////
110 89

  
111 90
  abstract void createEffects(int duration);
112 91
  abstract void effectFinishedPlugin(final long effectID);
113 92

  
114 93
///////////////////////////////////////////////////////////////////////////////////////////////////
94
// first compute how many out of 'numScrambles' are double turns (this will matter when we compute
95
// the time a single quarter-turn takes!
115 96

  
116 97
  private void createBaseEffects(int duration, int numScrambles)
117 98
    {
118 99
    mNumScramblesLeft = numScrambles;
119 100

  
120
    // compute how many out of 'numScrambles' are double turns.
121 101
    mNumDoubleScramblesLeft=0;
122 102

  
123 103
    for(int i=0; i<numScrambles; i++)
......
197 177
    return sign==0 ? result : -result;
198 178
    }
199 179

  
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181

  
182
  private void assignEffects()
183
    {
184
    for(int i=0; i<mCubeEffectNumber; i++)
185
      {
186
      mCube.apply(mCubeEffects[i],mCubeEffectPosition[i]);
187
      mCubeEffects[i].notifyWhenFinished(this);
188
      }
189

  
190
    DistortedEffects nodeEffects = mCube.getEffects();
191

  
192
    for(int i=0; i<mNodeEffectNumber; i++)
193
      {
194
      nodeEffects.apply(mNodeEffects[i],mNodeEffectPosition[i]);
195
      mNodeEffects[i].notifyWhenFinished(this);
196
      }
197
    }
198

  
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200

  
201
  private void disassignEffects()
202
    {
203
    for(int i=0; i<mCubeEffectNumber; i++)
204
      {
205
      mCube.remove(mCubeEffects[i].getID());
206
      }
207

  
208
    DistortedEffects nodeEffects = mCube.getEffects();
209

  
210
    for(int i=0; i<mNodeEffectNumber; i++)
211
      {
212
      nodeEffects.abortById(mNodeEffects[i].getID());
213
      }
214
    }
215

  
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217
// PUBLIC API
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219

  
220
  @SuppressWarnings("unused")
221
  public static String[] getNames()
222
    {
223
    String[] names = new String[NUM_EFFECTS];
224

  
225
    for( int i=0; i<NUM_EFFECTS; i++)
226
      {
227
      names[i] = types[i].name();
228
      }
229

  
230
    return names;
231
    }
232

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

  
235
  @SuppressWarnings("unused")
236
  public static ScrambleEffect create(int ordinal) throws InstantiationException, IllegalAccessException
237
    {
238
    return types[ordinal].effect.newInstance();
239
    }
240

  
200 241
///////////////////////////////////////////////////////////////////////////////////////////////////
201 242

  
202 243
  public void effectFinished(final long effectID)
......
257 298

  
258 299
///////////////////////////////////////////////////////////////////////////////////////////////////
259 300

  
301
  @SuppressWarnings("unused")
260 302
  public long start(int duration, RubikRenderer renderer)
261 303
    {
262 304
    mCube     = renderer.getCube();
......
277 319
    return FAKE_EFFECT_ID;
278 320
    }
279 321

  
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281

  
282
  private void assignEffects()
283
    {
284
    for(int i=0; i<mCubeEffectNumber; i++)
285
      {
286
      mCube.apply(mCubeEffects[i],mCubeEffectPosition[i]);
287
      mCubeEffects[i].notifyWhenFinished(this);
288
      }
289

  
290
    DistortedEffects nodeEffects = mCube.getEffects();
291

  
292
    for(int i=0; i<mNodeEffectNumber; i++)
293
      {
294
      nodeEffects.apply(mNodeEffects[i],mNodeEffectPosition[i]);
295
      mNodeEffects[i].notifyWhenFinished(this);
296
      }
297
    }
298

  
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

  
301
  private void disassignEffects()
302
    {
303
    for(int i=0; i<mCubeEffectNumber; i++)
304
      {
305
      mCube.remove(mCubeEffects[i].getID());
306
      }
307

  
308
    DistortedEffects nodeEffects = mCube.getEffects();
309

  
310
    for(int i=0; i<mNodeEffectNumber; i++)
311
      {
312
      nodeEffects.abortById(mNodeEffects[i].getID());
313
      }
314
    }
315

  
316 322
///////////////////////////////////////////////////////////////////////////////////////////////////
317 323

  
318 324
  @SuppressWarnings("unused")
src/main/java/org/distorted/effect/scramble/ScrambleEffectRotations.java
38 38
  {
39 39
  private Random mRnd = new Random(0);
40 40

  
41
///////////////////////////////////////////////////////////////////////////////////////////////////
42

  
43
  private Static4D generateNewRandomPoint()
44
    {
45
    float x = mRnd.nextFloat();
46
    float y = mRnd.nextFloat();
47
    float z = mRnd.nextFloat();
48
    float w = mRnd.nextFloat();
49

  
50
    float len = (float)Math.sqrt(x*x + y*y + z*z + w*w);
51

  
52
    return new Static4D( x/len, y/len, z/len, w/len);
53
    }
54

  
41 55
///////////////////////////////////////////////////////////////////////////////////////////////////
42 56

  
43 57
  public void createEffects(int duration)
......
69 83
    mCubeEffects[1] = new MatrixEffectMove(d0);
70 84
    }
71 85

  
72
///////////////////////////////////////////////////////////////////////////////////////////////////
73

  
74
  private Static4D generateNewRandomPoint()
75
    {
76
    float x = mRnd.nextFloat();
77
    float y = mRnd.nextFloat();
78
    float z = mRnd.nextFloat();
79
    float w = mRnd.nextFloat();
80

  
81
    float len = (float)Math.sqrt(x*x + y*y + z*z + w*w);
82

  
83
    return new Static4D( x/len, y/len, z/len, w/len);
84
    }
85

  
86 86
///////////////////////////////////////////////////////////////////////////////////////////////////
87 87

  
88 88
  public void effectFinishedPlugin(final long effectID)
src/main/java/org/distorted/effect/sizechange/SizeChangeEffect.java
96 96
    mCube               = new RubikCube[NUM_PHASES];
97 97
    }
98 98

  
99
///////////////////////////////////////////////////////////////////////////////////////////////////
100

  
101
  public static String[] getNames()
102
    {
103
    String[] names = new String[NUM_EFFECTS];
104

  
105
    for( int i=0; i<NUM_EFFECTS; i++)
106
      {
107
      names[i] = types[i].name();
108
      }
109

  
110
    return names;
111
    }
112

  
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114

  
115
  public static SizeChangeEffect create(int ordinal) throws InstantiationException, IllegalAccessException
116
    {
117
    return types[ordinal].effect.newInstance();
118
    }
119

  
120 99
///////////////////////////////////////////////////////////////////////////////////////////////////
121 100

  
122 101
  abstract int createEffectsPhase0(int duration);
123 102
  abstract int createEffectsPhase1(int duration);
124 103

  
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126

  
127
  public void effectFinished(final long effectID)
128
    {
129
    if( mPhaseActive[0] ) effectFinishedPhase(effectID,0);
130
    if( mPhaseActive[1] ) effectFinishedPhase(effectID,1);
131
    }
132

  
133 104
///////////////////////////////////////////////////////////////////////////////////////////////////
134 105

  
135 106
  private void effectFinishedPhase(final long effectID, int phase)
......
190 161
      }
191 162
    }
192 163

  
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

  
195
  public long start(int duration, RubikRenderer renderer)
196
    {
197
    mScreen   = renderer.getScreen();
198
    mCube[0]  = renderer.getOldCube();
199
    mCube[1]  = renderer.getCube();
200
    mListener = renderer;
201
    mDuration = duration;
202

  
203
    if( mCube[0]!=null )
204
      {
205
      mPhaseActive[0] = true;
206
      mEffectFinished[0] = createEffectsPhase0(mDuration);
207
      assignEffects(0);
208
      }
209
    else
210
      {
211
      mPhaseActive[1] = true;
212
      mEffectFinished[1] = createEffectsPhase1(mDuration);
213
      assignEffects(1);
214
      mScreen.attach(mCube[1]);
215
      }
216

  
217
    return FAKE_EFFECT_ID;
218
    }
219

  
220 164
///////////////////////////////////////////////////////////////////////////////////////////////////
221 165

  
222 166
  private void assignEffects(int phase)
......
244 188
      }
245 189
    }
246 190

  
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192
// PUBLIC API
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

  
195
  public void effectFinished(final long effectID)
196
    {
197
    if( mPhaseActive[0] ) effectFinishedPhase(effectID,0);
198
    if( mPhaseActive[1] ) effectFinishedPhase(effectID,1);
199
    }
200

  
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202

  
203
  @SuppressWarnings("unused")
204
  public static String[] getNames()
205
    {
206
    String[] names = new String[NUM_EFFECTS];
207

  
208
    for( int i=0; i<NUM_EFFECTS; i++)
209
      {
210
      names[i] = types[i].name();
211
      }
212

  
213
    return names;
214
    }
215

  
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217

  
218
  @SuppressWarnings("unused")
219
  public static SizeChangeEffect create(int ordinal) throws InstantiationException, IllegalAccessException
220
    {
221
    return types[ordinal].effect.newInstance();
222
    }
223

  
224
///////////////////////////////////////////////////////////////////////////////////////////////////
225

  
226
  @SuppressWarnings("unused")
227
  public long start(int duration, RubikRenderer renderer)
228
    {
229
    mScreen   = renderer.getScreen();
230
    mCube[0]  = renderer.getOldCube();
231
    mCube[1]  = renderer.getCube();
232
    mListener = renderer;
233
    mDuration = duration;
234

  
235
    if( mCube[0]!=null )
236
      {
237
      mPhaseActive[0] = true;
238
      mEffectFinished[0] = createEffectsPhase0(mDuration);
239
      assignEffects(0);
240
      }
241
    else
242
      {
243
      mPhaseActive[1] = true;
244
      mEffectFinished[1] = createEffectsPhase1(mDuration);
245
      assignEffects(1);
246
      mScreen.attach(mCube[1]);
247
      }
248

  
249
    return FAKE_EFFECT_ID;
250
    }
251

  
247 252
///////////////////////////////////////////////////////////////////////////////////////////////////
248 253

  
254
  @SuppressWarnings("unused")
249 255
  public static void enableEffects()
250 256
    {
251 257
    Method method;
src/main/java/org/distorted/effect/solve/SolveEffect.java
80 80

  
81 81
  SolveEffect()
82 82
    {
83
    mPhase        =  0;
83
    mPhase= 0;
84 84

  
85 85
    mCubeEffectNumber   = new int[NUM_PHASES];
86 86
    mNodeEffectNumber   = new int[NUM_PHASES];
......
92 92

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

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

  
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99

  
100
  private void assignEffects(int phase)
101
    {
102
    mCubeEffectNumber[phase] = ( mCubeEffects[phase]!=null ) ? mCubeEffects[phase].length : 0;
103
    mNodeEffectNumber[phase] = ( mNodeEffects[phase]!=null ) ? mNodeEffects[phase].length : 0;
104

  
105
    if( mCubeEffectNumber[phase]==0 && mNodeEffectNumber[phase]==0 )
106
      {
107
      throw new RuntimeException("Cube and Node Effects ("+phase+" phase) both not created!");
108
      }
109

  
110
    for(int i=0; i<mCubeEffectNumber[phase]; i++)
111
      {
112
      mCube.apply(mCubeEffects[phase][i],mCubeEffectPosition[phase][i]);
113
      mCubeEffects[phase][i].notifyWhenFinished(this);
114
      }
115

  
116
    DistortedEffects nodeEffects = mCube.getEffects();
117

  
118
    for(int i=0; i<mNodeEffectNumber[phase]; i++)
119
      {
120
      nodeEffects.apply(mNodeEffects[phase][i],mNodeEffectPosition[phase][i]);
121
      mNodeEffects[phase][i].notifyWhenFinished(this);
122
      }
123
    }
124

  
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126

  
127
  private void effectAction(int phase)
128
    {
129
    switch(phase)
130
      {
131
      case 0: mEffectReturned = 0;
132
              mPhase          = 1;
133
              mCube.solve();
134
              createEffectsPhase1(mDuration);
135
              assignEffects(mPhase);
136
              break;
137
      case 1: mListener.effectFinished(FAKE_EFFECT_ID);
138
              break;
139
      }
140
    }
141

  
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143
// PUBLIC API
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145

  
146
  @SuppressWarnings("unused")
95 147
  public static String[] getNames()
96 148
    {
97 149
    String[] names = new String[NUM_EFFECTS];
......
106 158

  
107 159
///////////////////////////////////////////////////////////////////////////////////////////////////
108 160

  
161
  @SuppressWarnings("unused")
109 162
  public static SolveEffect create(int ordinal) throws InstantiationException, IllegalAccessException
110 163
    {
111 164
    return types[ordinal].effect.newInstance();
112 165
    }
113 166

  
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115

  
116
  abstract void createEffectsPhase0(int duration);
117
  abstract void createEffectsPhase1(int duration);
118

  
119 167
///////////////////////////////////////////////////////////////////////////////////////////////////
120 168

  
121 169
  public void effectFinished(final long effectID)
......
148 196

  
149 197
///////////////////////////////////////////////////////////////////////////////////////////////////
150 198

  
151
  private void effectAction(int phase)
152
    {
153
    switch(phase)
154
      {
155
      case 0: mEffectReturned = 0;
156
              mPhase          = 1;
157
              mCube.solve();
158
              createEffectsPhase1(mDuration);
159
              assignEffects(mPhase);
160
              break;
161
      case 1: mListener.effectFinished(FAKE_EFFECT_ID);
162
              break;
163
      }
164
    }
165

  
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

  
199
  @SuppressWarnings("unused")
168 200
  public long start(int duration, RubikRenderer renderer)
169 201
    {
170 202
    mScreen   = renderer.getScreen();
......
178 210
    return FAKE_EFFECT_ID;
179 211
    }
180 212

  
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

  
183
  private void assignEffects(int phase)
184
    {
185
    mCubeEffectNumber[phase] = ( mCubeEffects[phase]!=null ) ? mCubeEffects[phase].length : 0;
186
    mNodeEffectNumber[phase] = ( mNodeEffects[phase]!=null ) ? mNodeEffects[phase].length : 0;
187

  
188
    if( mCubeEffectNumber[phase]==0 && mNodeEffectNumber[phase]==0 )
189
      {
190
      throw new RuntimeException("Cube and Node Effects ("+phase+" phase) both not created!");
191
      }
192

  
193
    for(int i=0; i<mCubeEffectNumber[phase]; i++)
194
      {
195
      mCube.apply(mCubeEffects[phase][i],mCubeEffectPosition[phase][i]);
196
      mCubeEffects[phase][i].notifyWhenFinished(this);
197
      }
198

  
199
    DistortedEffects nodeEffects = mCube.getEffects();
200

  
201
    for(int i=0; i<mNodeEffectNumber[phase]; i++)
202
      {
203
      nodeEffects.apply(mNodeEffects[phase][i],mNodeEffectPosition[phase][i]);
204
      mNodeEffects[phase][i].notifyWhenFinished(this);
205
      }
206
    }
207

  
208 213
///////////////////////////////////////////////////////////////////////////////////////////////////
209 214

  
210 215
  @SuppressWarnings("unused")
src/main/java/org/distorted/effect/solve/SolveEffectSpin.java
25 25
import org.distorted.library.type.Dynamic1D;
26 26
import org.distorted.library.type.Static1D;
27 27
import org.distorted.library.type.Static3D;
28
import org.distorted.library.type.Static4D;
28 29

  
29 30
///////////////////////////////////////////////////////////////////////////////////////////////////
30 31

  
31 32
public class SolveEffectSpin extends SolveEffect
32 33
  {
33
  public void createEffectsPhase0(int duration)
34
  private static Static4D quatMultiply( Static4D quat1, Static4D quat2 )
34 35
    {
35
    mCubeEffectPosition[0] = new int[] {3};
36
    mCubeEffects[0]        = new Effect[mCubeEffectPosition[0].length];
36
    float qx = quat1.get1();
37
    float qy = quat1.get2();
38
    float qz = quat1.get3();
39
    float qw = quat1.get4();
37 40

  
38
    Static3D axis  = new Static3D(1,0,0);
39
    Static3D center= new Static3D(0,0,0);
41
    float rx = quat2.get1();
42
    float ry = quat2.get2();
43
    float rz = quat2.get3();
44
    float rw = quat2.get4();
40 45

  
41
    Dynamic1D d0 = new Dynamic1D(duration/2, 1.0f);
42
    d0.setMode(Dynamic.MODE_JUMP);
43
    d0.setConvexity(0.0f);          // otherwise speed of the rotation would be strangely uneven
44
    d0.add(new Static1D( 0*36));
45
    d0.add(new Static1D( 1*36));
46
    d0.add(new Static1D( 3*36));
47
    d0.add(new Static1D( 6*36));
48
    d0.add(new Static1D(10*36));
49
    mCubeEffects[0][0] = new MatrixEffectRotate(d0,axis,center);
46
    float tx = rw*qx - rz*qy + ry*qz + rx*qw;
47
    float ty = rw*qy + rz*qx + ry*qw - rx*qz;
48
    float tz = rw*qz + rz*qw - ry*qx + rx*qy;
49
    float tw = rw*qw - rz*qz - ry*qy - rx*qx;
50

  
51
    return new Static4D(tx,ty,tz,tw);
50 52
    }
51 53

  
52 54
///////////////////////////////////////////////////////////////////////////////////////////////////
55
// rotate 'vector' by quat^(-1)  ( i.e. return (quat^-1)*vector*quat )
53 56

  
54
  public void createEffectsPhase1(int duration)
57
  private static Static4D rotateVectorByInvertedQuat(Static4D vector, Static4D quat)
58
    {
59
    float qx = quat.get1();
60
    float qy = quat.get2();
61
    float qz = quat.get3();
62
    float qw = quat.get4();
63

  
64
    Static4D quatInverted= new Static4D(-qx,-qy,-qz,qw);
65
    Static4D tmp = quatMultiply(quatInverted,vector);
66

  
67
    return quatMultiply(tmp,quat);
68
    }
69

  
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71

  
72
  private void createEffects(int phase, int duration, int[] points)
55 73
    {
56
    mCubeEffectPosition[1] = new int[] {3};
57
    mCubeEffects[1]        = new Effect[mCubeEffectPosition[1].length];
74
    mCubeEffectPosition[phase] = new int[] {3};
75
    mCubeEffects[phase]        = new Effect[mCubeEffectPosition[0].length];
58 76

  
59
    Static3D axis  = new Static3D(1,0,0);
77
    Static4D quaternion = mCube.getRotationQuat();                        // always rotate around
78
    Static4D tmpAxis    = new Static4D(0,1,0,0);                          // vert axis no matter
79
    Static4D rotated    = rotateVectorByInvertedQuat(tmpAxis,quaternion); // how cube is rotated
80

  
81
    Static3D axis  = new Static3D(rotated.get1(), rotated.get2(), rotated.get3());
60 82
    Static3D center= new Static3D(0,0,0);
61 83

  
62
    Dynamic1D d1 = new Dynamic1D(duration/2, 1.0f);
63
    d1.setMode(Dynamic.MODE_JUMP);
64
    d1.setConvexity(0.0f);
65
    d1.add(new Static1D( 0*36));
66
    d1.add(new Static1D( 4*36));
67
    d1.add(new Static1D( 7*36));
68
    d1.add(new Static1D( 9*36));
69
    d1.add(new Static1D(10*36));
70
    mCubeEffects[1][0] = new MatrixEffectRotate(d1,axis,center);
84
    Dynamic1D d = new Dynamic1D(duration/2, 1.0f);
85
    d.setMode(Dynamic.MODE_JUMP);
86
    d.setConvexity(0.0f);   // otherwise speed of the rotation would be strangely uneven
87

  
88
    d.add( new Static1D(36*points[0]) );
89
    d.add( new Static1D(36*points[1]) );
90
    d.add( new Static1D(36*points[2]) );
91
    d.add( new Static1D(36*points[3]) );
92
    d.add( new Static1D(36*points[4]) );
93

  
94
    mCubeEffects[phase][0] = new MatrixEffectRotate(d,axis,center);
95
    }
96

  
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98
// PUBLIC API
99
///////////////////////////////////////////////////////////////////////////////////////////////////
100

  
101
  public void createEffectsPhase0(int duration)
102
    {
103
    createEffects(0,duration,new int[] {0,1,3,6,10});
104
    }
105

  
106
///////////////////////////////////////////////////////////////////////////////////////////////////
107

  
108
  public void createEffectsPhase1(int duration)
109
    {
110
    createEffects(1,duration,new int[] {0,4,7,9,10});
71 111
    }
72 112

  
73 113
///////////////////////////////////////////////////////////////////////////////////////////////////
src/main/java/org/distorted/effect/win/WinEffect.java
36 36
  public enum Type
37 37
    {
38 38
    NONE   (WinEffectNone.class),
39
    SPIN   (WinEffectSpin.class),
40 39
    GLOW   (WinEffectGlow.class),
41 40
    ;
42 41

  
......
77 76

  
78 77
///////////////////////////////////////////////////////////////////////////////////////////////////
79 78

  
79
  abstract void createEffects(int duration);
80

  
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82

  
83
  private void assignEffects()
84
    {
85
    mCubeEffectNumber = ( mCubeEffects!=null ) ? mCubeEffects.length : 0;
86
    mNodeEffectNumber = ( mNodeEffects!=null ) ? mNodeEffects.length : 0;
87

  
88
    if( mCubeEffectNumber==0 && mNodeEffectNumber==0 )
89
      {
90
      throw new RuntimeException("Cube and Node Effects both not created!");
91
      }
92

  
93
    for(int i=0; i<mCubeEffectNumber; i++)
94
      {
95
      mCube.apply(mCubeEffects[i],mCubeEffectPosition[i]);
96
      mCubeEffects[i].notifyWhenFinished(this);
97
      }
98

  
99
    DistortedEffects nodeEffects = mCube.getEffects();
100

  
101
    for(int i=0; i<mNodeEffectNumber; i++)
102
      {
103
      nodeEffects.apply(mNodeEffects[i],mNodeEffectPosition[i]);
104
      mNodeEffects[i].notifyWhenFinished(this);
105
      }
106
    }
107

  
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109
// PUBLIC API
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111

  
112
  @SuppressWarnings("unused")
80 113
  public static String[] getNames()
81 114
    {
82 115
    String[] names = new String[NUM_EFFECTS];
......
91 124

  
92 125
///////////////////////////////////////////////////////////////////////////////////////////////////
93 126

  
127
  @SuppressWarnings("unused")
94 128
  public static WinEffect create(int ordinal) throws InstantiationException, IllegalAccessException
95 129
    {
96 130
    return types[ordinal].effect.newInstance();
97 131
    }
98 132

  
99
///////////////////////////////////////////////////////////////////////////////////////////////////
100

  
101
  abstract void createEffects(int duration);
102

  
103 133
///////////////////////////////////////////////////////////////////////////////////////////////////
104 134

  
105 135
  public void effectFinished(final long effectID)
......
132 162

  
133 163
///////////////////////////////////////////////////////////////////////////////////////////////////
134 164

  
165
  @SuppressWarnings("unused")
135 166
  public long start(int duration, RubikRenderer renderer)
136 167
    {
137 168
    mScreen   = renderer.getScreen();
......
145 176
    return FAKE_EFFECT_ID;
146 177
    }
147 178

  
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149

  
150
  private void assignEffects()
151
    {
152
    mCubeEffectNumber = ( mCubeEffects!=null ) ? mCubeEffects.length : 0;
153
    mNodeEffectNumber = ( mNodeEffects!=null ) ? mNodeEffects.length : 0;
154

  
155
    if( mCubeEffectNumber==0 && mNodeEffectNumber==0 )
156
      {
157
      throw new RuntimeException("Cube and Node Effects both not created!");
158
      }
159

  
160
    for(int i=0; i<mCubeEffectNumber; i++)
161
      {
162
      mCube.apply(mCubeEffects[i],mCubeEffectPosition[i]);
163
      mCubeEffects[i].notifyWhenFinished(this);
164
      }
165

  
166
    DistortedEffects nodeEffects = mCube.getEffects();
167

  
168
    for(int i=0; i<mNodeEffectNumber; i++)
169
      {
170
      nodeEffects.apply(mNodeEffects[i],mNodeEffectPosition[i]);
171
      mNodeEffects[i].notifyWhenFinished(this);
172
      }
173
    }
174

  
175 179
///////////////////////////////////////////////////////////////////////////////////////////////////
176 180

  
177 181
  @SuppressWarnings("unused")
src/main/java/org/distorted/effect/win/WinEffectSpin.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 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.effect.win;
21

  
22
import org.distorted.library.effect.Effect;
23
import org.distorted.library.effect.MatrixEffectRotate;
24
import org.distorted.library.type.Dynamic;
25
import org.distorted.library.type.Dynamic1D;
26
import org.distorted.library.type.Static1D;
27
import org.distorted.library.type.Static3D;
28

  
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30

  
31
public class WinEffectSpin extends WinEffect
32
  {
33
  public void createEffects(int duration)
34
    {
35
    mCubeEffectPosition = new int[] {3};
36
    mCubeEffects        = new Effect[mCubeEffectPosition.length];
37

  
38
    Static3D axis  = new Static3D(1,0,0);
39
    Static3D center= new Static3D(0,0,0);
40

  
41
    Dynamic1D d0 = new Dynamic1D(duration/2, 1.0f);
42
    d0.setMode(Dynamic.MODE_JUMP);
43
    d0.setConvexity(0.0f);          // otherwise speed of the rotation would be strangely uneven
44
    d0.add(new Static1D( 0*36));
45
    d0.add(new Static1D( 1*36));
46
    d0.add(new Static1D( 3*36));
47
    d0.add(new Static1D( 6*36));
48
    d0.add(new Static1D(10*36));
49
    d0.add(new Static1D(14*36));
50
    d0.add(new Static1D(17*36));
51
    d0.add(new Static1D(19*36));
52
    d0.add(new Static1D(20*36));
53

  
54
    mCubeEffects[0] = new MatrixEffectRotate(d0,axis,center);
55
    }
56

  
57
///////////////////////////////////////////////////////////////////////////////////////////////////
58
// Enable all effects used in this Effect. Called by reflection from the parent class.
59

  
60
  @SuppressWarnings("unused")
61
  static void enable()
62
    {
63

  
64
    }
65
  }
src/main/java/org/distorted/magic/RubikActivity.java
42 42
    private static final int[] button_ids  = {R.id.rubikSize2, R.id.rubikSize3, R.id.rubikSize4};
43 43

  
44 44
    public static final int MIN_SCRAMBLE =  1;
45
    public static final int DEF_SCRAMBLE =  3;
45 46
    public static final int MAX_SCRAMBLE = 10;
46 47

  
47 48
    private static int mSize = DEFAULT_SIZE;
48 49
    private HorizontalNumberPicker mPicker;
49 50

  
51
///////////////////////////////////////////////////////////////////////////////////////////////////
52

  
53
    private void markButton(int size)
54
      {
55
      mSize = size;
56

  
57
      for(int b=0; b<button_ids.length; b++)
58
        {
59
        Drawable d = findViewById(button_ids[b]).getBackground();
60

  
61
        if( size == b+SMALLEST_SIZE )
62
          {
63
          d.setColorFilter(ContextCompat.getColor(this,R.color.red), PorterDuff.Mode.MULTIPLY);
64
          }
65
        else
66
          {
67
          d.clearColorFilter();
68
          }
69
        }
70
      }
71

  
72
///////////////////////////////////////////////////////////////////////////////////////////////////
73

  
74
    private void savePreferences()
75
      {
76
      SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
77
      SharedPreferences.Editor editor = preferences.edit();
78

  
79
      for (int i=0; i< BaseEffect.Type.LENGTH; i++)
80
        {
81
        BaseEffect.Type.getType(i).savePreferences(editor);
82
        }
83

  
84
      editor.putInt("scramble", mPicker.getValue() );
85

  
86
      editor.apply();
87
      }
88

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

  
91
    private void restorePreferences()
92
      {
93
      SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
94

  
95
      for (int i=0; i< BaseEffect.Type.LENGTH; i++)
96
        {
97
        BaseEffect.Type.getType(i).restorePreferences(preferences);
98
        }
99

  
100
      int scramble= preferences.getInt("scramble", DEF_SCRAMBLE);
101

  
102
      mPicker.setValue(scramble);
103
      }
104

  
105
///////////////////////////////////////////////////////////////////////////////////////////////////
106

  
107
    static int getSize()
108
      {
109
      return mSize;
110
      }
111

  
50 112
///////////////////////////////////////////////////////////////////////////////////////////////////
51 113

  
52 114
    @Override
......
96 158
      }
97 159

  
98 160
///////////////////////////////////////////////////////////////////////////////////////////////////
99

  
100
    static int getSize()
101
      {
102
      return mSize;
103
      }
104

  
161
// PUBLIC API
105 162
///////////////////////////////////////////////////////////////////////////////////////////////////
106 163

  
107 164
    public void Settings(View v)
......
157 214
        markButton(size);
158 215
        }
159 216
      }
160

  
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162

  
163
   private void markButton(int size)
164
     {
165
     mSize = size;
166

  
167
     for(int b=0; b<button_ids.length; b++)
168
       {
169
       Drawable d = findViewById(button_ids[b]).getBackground();
170

  
171
       if( size == b+SMALLEST_SIZE )
172
         {
173
         d.setColorFilter(ContextCompat.getColor(this,R.color.red), PorterDuff.Mode.MULTIPLY);
174
         }
175
       else
176
         {
177
         d.clearColorFilter();
178
         }
179
       }
180
     }
181

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

  
184
   private void savePreferences()
185
     {
186
     SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
187
     SharedPreferences.Editor editor = preferences.edit();
188

  
189
     for (int i=0; i< BaseEffect.Type.LENGTH; i++)
190
       {
191
       BaseEffect.Type.getType(i).savePreferences(editor);
192
       }
193

  
194
     editor.putInt("scramble", mPicker.getValue() );
195

  
196
     editor.apply();
197
     }
198

  
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200

  
201
   private void restorePreferences()
202
     {
203
     SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
204

  
205
     for (int i=0; i< BaseEffect.Type.LENGTH; i++)
206
       {
207
       BaseEffect.Type.getType(i).restorePreferences(preferences);
208
       }
209

  
210
     int scramble= preferences.getInt("scramble", MIN_SCRAMBLE);
211

  
212
     mPicker.setValue(scramble);
213
     }
214 217
}
src/main/java/org/distorted/magic/RubikCube.java
24 24
import android.graphics.Paint;
25 25

  
26 26
import org.distorted.library.effect.Effect;
27
import org.distorted.library.effect.EffectType;
28 27
import org.distorted.library.effect.MatrixEffectMove;
29 28
import org.distorted.library.effect.MatrixEffectQuaternion;
30 29
import org.distorted.library.effect.MatrixEffectRotate;
31 30
import org.distorted.library.effect.MatrixEffectScale;
32 31
import org.distorted.library.effect.VertexEffectSink;
33
import org.distorted.library.effectqueue.EffectQueue;
34 32
import org.distorted.library.main.DistortedEffects;
35 33
import org.distorted.library.main.DistortedNode;
36 34
import org.distorted.library.main.DistortedTexture;
......
67 65
    private MatrixEffectRotate[][][] mRotateEffect;
68 66
    private Static1D mRotationAngleStatic, mRotationAngleMiddle, mRotationAngleFinal;
69 67
    private Static3D mMove, mScale, mNodeMove, mNodeScale;
68
    private Static4D mQuatAccumulated;
70 69
    private DistortedTexture mTexture;
71 70

  
72 71
    private int mRotAxis, mRotRow;
......
93 92
      mNodeMove = new Static3D(0,0,0);
94 93
      mNodeScale= new Static3D(1,1,1);
95 94

  
95
      mQuatAccumulated = quatAcc;
96

  
96 97
      mRotAxis = VECTX;
97 98
      mTexture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
98 99

  
......
187 188

  
188 189
///////////////////////////////////////////////////////////////////////////////////////////////////
189 190

  
190
    boolean isSolved()
191
    private int computeNearestAngle(float angle)
191 192
      {
192
      Static4D q = mQuatScramble[0][0][0];
193

  
194
      float x = q.get1();
195
      float y = q.get2();
196
      float z = q.get3();
197
      float w = q.get4();
198

  
199
      for(int i = 0; i< mSize; i++)
200
        for(int j = 0; j< mSize; j++)
201
          for(int k = 0; k< mSize; k++)
202
            {
203
            if( i==0 || i==mSize-1 || j==0 || j==mSize-1 || k==0 || k==mSize-1 )
204
              {
205
              q = mQuatScramble[i][j][k];
193
      final int NEAREST = 90;
206 194

  
207
              if( q.get1()!=x || q.get2()!=y || q.get3()!=z || q.get4()!=w )
208
                {
209
                return false;
210
                }
211
              }
212
            }
195
      int tmp = (int)((angle+NEAREST/2)/NEAREST);
196
      if( angle< -(NEAREST/2) ) tmp-=1;
213 197

  
214
      return true;
198
      return NEAREST*tmp;
215 199
      }
216 200

  
217 201
///////////////////////////////////////////////////////////////////////////////////////////////////
202
// All legal rotation quats must have all four of their components equal to either
203
// 0, 1, -1, 0.5, -0.5 or +-sqrt(2)/2.
204
//
205
// Because of quatMultiplication, errors can accumulate - so to avoid this, we
206
// correct the value of the 'scramble' quat to what it should be.
207
//
208
// We also have to remember that the group of unit quaternions is a double-cover of rotations
209
// in 3D ( q represents the same rotation as -q ) - so invert if needed.
218 210

  
219
    public void apply(Effect effect, int position)
211
    private static final float SQ2 = 0.5f*((float)Math.sqrt(2));
212
    private static final float[] LEGAL = { 0.0f , 0.5f , -0.5f , 1.0f , -1.0f , SQ2 , -SQ2 };
213

  
214
    private void normalizeScrambleQuat(int i, int j, int k)
220 215
      {
221
      for(int x=0; x<mSize; x++)
222
        for(int y=0; y<mSize; y++)
223
          for(int z=0; z<mSize; z++)
224
            {
225
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
226
              {
227
              mEffects[x][y][z].apply(effect, position);
228
              }
229
            }
230
      }
216
      Static4D quat = mQuatScramble[i][j][k];
231 217

  
232
///////////////////////////////////////////////////////////////////////////////////////////////////
218
      float x = quat.get1();
219
      float y = quat.get2();
220
      float z = quat.get3();
221
      float w = quat.get4();
222
      float diff;
233 223

  
234
    public void remove(long effectID)
235
      {
236
      for(int x=0; x<mSize; x++)
237
        for(int y=0; y<mSize; y++)
238
          for(int z=0; z<mSize; z++)
224
      for(float legal: LEGAL)
225
        {
226
        diff = x-legal;
227
        if( diff*diff<0.01f ) x = legal;
228
        diff = y-legal;
229
        if( diff*diff<0.01f ) y = legal;
230
        diff = z-legal;
231
        if( diff*diff<0.01f ) z = legal;
232
        diff = w-legal;
233
        if( diff*diff<0.01f ) w = legal;
234
        }
235

  
236
      if( w<0 )
237
        {
238
        w = -w;
239
        z = -z;
240
        y = -y;
241
        x = -x;
242
        }
243
      else if( w==0 )
244
        {
245
        if( z<0 )
246
          {
247
          z = -z;
248
          y = -y;
249
          x = -x;
250
          }
251
        else if( z==0 )
252
          {
253
          if( y<0 )
239 254
            {
240
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
255
            y = -y;
256
            x = -x;
257
            }
258
          else if( y==0 )
259
            {
260
            if( x<0 )
241 261
              {
242
              mEffects[x][y][z].abortById(effectID);
262
              x = -x;
243 263
              }
244 264
            }
245
      }
246

  
247
///////////////////////////////////////////////////////////////////////////////////////////////////
265
          }
266
        }
248 267

  
249
    public void solve()
250
      {
251
      for(int x=0; x<mSize; x++)
252
        for(int y=0; y<mSize; y++)
253
          for(int z=0; z<mSize; z++)
254
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
255
              {
256
              mQuatScramble[x][y][z].set(0,0,0,1);
257
              mCurrentPosition[x][y][z].set(x,y,z);
258
              }
268
      mQuatScramble[i][j][k].set(x,y,z,w);
259 269
      }
260 270

  
261 271
///////////////////////////////////////////////////////////////////////////////////////////////////
262 272

  
263
    public String print_effects()
273
    private float getSinkStrength()
264 274
      {
265
      String str="";
266

  
267
      EffectQueue[] effects = mEffects[0][0][0].getQueues();
268
      EffectQueue matrix      = effects[0];
269
      EffectQueue vertex      = effects[1];
270
      EffectQueue fragment    = effects[2];
271
      EffectQueue postprocess = effects[3];
272

  
273
      str+="MATRIX: ";
274
      int m_len = matrix.getNumEffects();
275
      for(int i=0; i<m_len; i++)
276
        {
277
        str+=(" "+matrix.getEffect(i).getName()+"("+matrix.getEffect(i).getID()+")" );
278
        }
279
      str+='\n';
280

  
281
      str+="VERTEX: ";
282
      int v_len = vertex.getNumEffects();
283
      for(int i=0; i<v_len; i++)
275
      switch(mSize)
284 276
        {
285
        str+=(" "+vertex.getEffect(i).getName()+"("+matrix.getEffect(i).getID()+")" );
277
        case 1 : return 1.1f;
278
        case 2 : return 1.5f;
279
        case 3 : return 1.8f;
280
        case 4 : return 2.0f;
281
        default: return 3.0f - 4.0f/mSize;
286 282
        }
287
      str+='\n';
283
      }
288 284

  
289
      str+="FRAGMENT: ";
290
      int f_len = fragment.getNumEffects();
291
      for(int i=0; i<f_len; i++)
292
        {
293
        str+=(" "+fragment.getEffect(i).getName()+"("+matrix.getEffect(i).getID()+")" );
294
        }
295
      str+='\n';
285
///////////////////////////////////////////////////////////////////////////////////////////////////
296 286

  
297
      str+="POSTPROCESS: ";
298
      int p_len = postprocess.getNumEffects();
299
      for(int i=0; i<p_len; i++)
287
    private boolean belongsToRotation(int x, int y, int z, int vector, int row)
288
      {
289
      switch(vector)
300 290
        {
301
        str+=(" "+postprocess.getEffect(i).getName()+"("+matrix.getEffect(i).getID()+")" );
291
        case VECTX: return mCurrentPosition[x][y][z].get1()==row;
292
        case VECTY: return mCurrentPosition[x][y][z].get2()==row;
293
        case VECTZ: return mCurrentPosition[x][y][z].get3()==row;
302 294
        }
303
      str+='\n';
304 295

  
305
      return str;
296
      return false;
306 297
      }
298

  
307 299
///////////////////////////////////////////////////////////////////////////////////////////////////
308 300

  
309
    public int getNumEffects(EffectType type)
301
    private void modifyCurrentPosition(int x, int y, int z, Static4D quat)
310 302
      {
311
      return mEffects[0][0][0].getNumEffects(type);
303
      Static3D current = mCurrentPosition[x][y][z];
304
      float diff = 0.5f*(mSize-1);
305
      float cubitCenterX = current.get1() - diff;
306
      float cubitCenterY = current.get2() - diff;
307
      float cubitCenterZ = current.get3() - diff;
308

  
309
      Static4D cubitCenter =  new Static4D(cubitCenterX, cubitCenterY, cubitCenterZ, 0);
310
      Static4D rotatedCenter = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat);
311

  
312
      float rotatedX = rotatedCenter.get1() + diff;
313
      float rotatedY = rotatedCenter.get2() + diff;
314
      float rotatedZ = rotatedCenter.get3() + diff;
315

  
316
      int roundedX = (int)(rotatedX+0.1f);
317
      int roundedY = (int)(rotatedY+0.1f);
318
      int roundedZ = (int)(rotatedZ+0.1f);
319

  
320
      mCurrentPosition[x][y][z].set1(roundedX);
321
      mCurrentPosition[x][y][z].set2(roundedY);
322
      mCurrentPosition[x][y][z].set3(roundedZ);
312 323
      }
313 324

  
314 325
///////////////////////////////////////////////////////////////////////////////////////////////////
315 326

  
316
    public long addNewRotation(int vector, int row, int angle, long durationMillis, EffectListener listener )
327
    boolean isSolved()
317 328
      {
318
      Static3D axis = VectX;
319
      long effectID=0;
320
      boolean first = true;
321

  
322
      switch(vector)
323
        {
324
        case VECTX: axis = VectX; break;
325
        case VECTY: axis = VectY; break;
326
        case VECTZ: axis = VectZ; break;
327
        }
328

  
329
      mRotAxis = vector;
330
      mRotRow  = row;
329
      Static4D q = mQuatScramble[0][0][0];
331 330

  
332
      mRotationAngleStatic.set1(0.0f);
331
      float x = q.get1();
332
      float y = q.get2();
333
      float z = q.get3();
334
      float w = q.get4();
333 335

  
334
      for(int x=0; x<mSize; x++)
335
        for(int y=0; y<mSize; y++)
336
          for(int z=0; z<mSize; z++)
337
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
336
      for(int i = 0; i< mSize; i++)
337
        for(int j = 0; j< mSize; j++)
338
          for(int k = 0; k< mSize; k++)
339
            {
340
            if( i==0 || i==mSize-1 || j==0 || j==mSize-1 || k==0 || k==mSize-1 )
338 341
              {
339
              if( belongsToRotation(x,y,z,vector,mRotRow) )
340
                {
341
                mRotationAxis[x][y][z].set(axis);
342
                mRotationAngle[x][y][z].setDuration(durationMillis);
343
                mRotationAngle[x][y][z].resetToBeginning();
344
                mRotationAngle[x][y][z].add(new Static1D(0));
345
                mRotationAngle[x][y][z].add(new Static1D(angle));
342
              q = mQuatScramble[i][j][k];
346 343

  
347
                if( first )
348
                  {
349
                  first = false;
350
                  effectID = mRotateEffect[x][y][z].getID();
351
                  mRotateEffect[x][y][z].notifyWhenFinished(listener);
352
                  }
344
              if( q.get1()!=x || q.get2()!=y || q.get3()!=z || q.get4()!=w )
345
                {
346
                return false;
353 347
                }
354 348
              }
349
            }
355 350

  
356
      return effectID;
357
      }
358

  
359
///////////////////////////////////////////////////////////////////////////////////////////////////
360

  
361
    public int getSize()
362
      {
363
      return mSize;
351
      return true;
364 352
      }
365 353

  
366 354
///////////////////////////////////////////////////////////////////////////////////////////////////
......
415 403
              }
416 404
      }
417 405

  
418
///////////////////////////////////////////////////////////////////////////////////////////////////
419

  
420
    void continueRotation(float angleInDegrees)
421
      {
422
      mRotationAngleStatic.set1(angleInDegrees);
423
      }
424

  
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426

  
427
    private int computeNearestAngle(float angle)
428
      {
429
      final int NEAREST = 90;
430

  
431
      int tmp = (int)((angle+NEAREST/2)/NEAREST);
432
      if( angle< -(NEAREST/2) ) tmp-=1;
433

  
434
      return NEAREST*tmp;
435
      }
436

  
437 406
///////////////////////////////////////////////////////////////////////////////////////////////////
438 407

  
439 408
    long finishRotationNow(EffectListener listener)
......
484 453

  
485 454
///////////////////////////////////////////////////////////////////////////////////////////////////
486 455

  
487
    public void removeRotationNow()
456
    void continueRotation(float angleInDegrees)
488 457
      {
489
      float qx=0,qy=0,qz=0;
490
      boolean first = true;
491
      Static4D quat = null;
492

  
493
      switch(mRotAxis)
494
        {
495
        case VECTX: qx=1; break;
496
        case VECTY: qy=1; break;
497
        case VECTZ: qz=1; break;
498
        }
458
      mRotationAngleStatic.set1(angleInDegrees);
459
      }
499 460

  
500
      for(int x=0; x<mSize; x++)
501
        for(int y=0; y<mSize; y++)
502
          for(int z=0; z<mSize; z++)
503
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
504
              {
505
              if( belongsToRotation(x,y,z,mRotAxis,mRotRow) )
506
                {
507
                if( first )
508
                  {
509
                  first = false;
510
                  int pointNum = mRotationAngle[x][y][z].getNumPoints();
511

  
512
                  if( pointNum>=1 )
513
                    {
514
                    float startingAngle = mRotationAngle[x][y][z].getPoint(pointNum-1).get1();
515
                    int nearestAngleInDegrees = computeNearestAngle(startingAngle);
516
                    double nearestAngleInRadians = nearestAngleInDegrees*Math.PI/180;
517
                    float sinA =-(float)Math.sin(nearestAngleInRadians*0.5);
518
                    float cosA = (float)Math.cos(nearestAngleInRadians*0.5);
519
                    quat = new Static4D(qx*sinA, qy*sinA, qz*sinA, cosA);
520
                    }
521
                  else
522
                    {
523
                    android.util.Log.e("cube", "ERROR removing rotation!");
524
                    return;
525
                    }
526
                  }
527

  
528
                mRotationAngle[x][y][z].removeAll();
529
                mQuatScramble[x][y][z].set(RubikSurfaceView.quatMultiply(quat,mQuatScramble[x][y][z]));
530
                normalizeScrambleQuat(x,y,z);
531
                modifyCurrentPosition(x,y,z,quat);
532
                }
533
              }
534

  
535
      mRotationAngleStatic.set1(0);
536
      }
537

  
538
///////////////////////////////////////////////////////////////////////////////////////////////////
539
// All legal rotation quats must have all four of their components equal to either
540
// 0, 1, -1, 0.5, -0.5 or +-sqrt(2)/2.
541
//
542
// Because of quatMultiplication, errors can accumulate - so to avoid this, we
543
// correct the value of the 'scramble' quat to what it should be.
544
//
545
// We also have to remember that the group of unit quaternions is a double-cover of rotations
546
// in 3D ( q represents the same rotation as -q ) - so invert if needed.
547

  
548
    private static final float SQ2 = 0.5f*((float)Math.sqrt(2));
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff