Project

General

Profile

« Previous | Next » 

Revision a742d66b

Added by Leszek Koltunski 9 days ago

If an object has more than 8 colors, in the solver's SetupPosition screen display the bitmaps in two rows.

View differences:

src/main/java/org/distorted/dialogs/RubikDialogSolverView.java
21 21
import org.distorted.objectlib.solvers.verifiers.SolverAbstract;
22 22
import org.distorted.objectlib.solvers.verifiers.SolvingList;
23 23
import org.distorted.solverui.ScreenList;
24
import org.distorted.solverui.ScreenSolver;
24
import org.distorted.solverui.ScreenSetupPosition;
25 25
import org.distorted.solverui.SolverActivity;
26 26

  
27 27
///////////////////////////////////////////////////////////////////////////////////////////////////
......
59 59
        OperatingSystemInterface os = act.getInterface();
60 60
        TwistyObject object = act.getObject();
61 61
        SolverAbstract solver = list.create(os,object);
62
        ScreenSolver screen = (ScreenSolver)ScreenList.SVER.getScreenClass();
62
        ScreenSetupPosition screen = (ScreenSetupPosition)ScreenList.SVER.getScreenClass();
63 63

  
64 64
        if( solver!=null )
65 65
          {
src/main/java/org/distorted/solverui/ScreenList.java
18 18

  
19 19
public enum ScreenList
20 20
  {
21
  SVER ( null , MODE_REPLACE, new ScreenSolver()         ),
22
  SOLU ( SVER , MODE_DRAG   , new ScreenSolution()       ),
23
  PHAS ( SVER , MODE_DRAG   , new ScreenPhasedSolution() ),
21
  SVER ( null , MODE_REPLACE, new ScreenSetupPosition()        ),
22
  SOLU ( SVER , MODE_DRAG   , new ScreenSolutionSinglephased() ),
23
  PHAS ( SVER , MODE_DRAG   , new ScreenSolutionMultiphased()  ),
24 24
  ;
25 25

  
26 26
  public static final int LENGTH = values().length;
src/main/java/org/distorted/solverui/ScreenPhasedSolution.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2024 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.solverui;
11

  
12
import android.content.SharedPreferences;
13
import android.util.TypedValue;
14
import android.view.Gravity;
15
import android.view.View;
16
import android.widget.LinearLayout;
17
import android.widget.TextView;
18

  
19
import org.distorted.helpers.TransparentImageButton;
20
import org.distorted.library.effect.PostprocessEffectGlow;
21
import org.distorted.library.main.DistortedEffects;
22
import org.distorted.library.mesh.MeshBase;
23
import org.distorted.library.message.EffectListener;
24
import org.distorted.library.type.Dynamic2D;
25
import org.distorted.library.type.Dynamic4D;
26
import org.distorted.library.type.Static2D;
27
import org.distorted.library.type.Static4D;
28
import org.distorted.main.R;
29
import org.distorted.objectlib.helpers.MovesFinished;
30
import org.distorted.objectlib.main.ObjectControl;
31
import org.distorted.objectlib.main.TwistyObject;
32

  
33
import java.lang.ref.WeakReference;
34

  
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36

  
37
public class ScreenPhasedSolution extends ScreenAbstract implements MovesFinished, EffectListener
38
  {
39
  private static final int MOVES_PLACE_0 = 100;
40
  private static final int MOVES_PLACE_1 = 101;
41
  private static final int FLASH_TIME = 1200;
42
  private static final int MILLIS_PER_DEGREE = 6;
43

  
44
  private WeakReference<SolverActivity> mAct;
45
  private TransparentImageButton mPrevButton, mNextButton, mBackButton, mPrevPhase, mNextPhase;
46
  private float mButtonSize;
47

  
48
  private TextView mMovesText, mMovesPhase;
49
  private String[] mPhaseNames;
50
  private int mNumPhases;
51
  private int[][][] mMoves;
52
  private int[][] mCubitsNotInvolved;
53
  private int mNumMoves,mCurrMove,mCurrPhase;
54
  private boolean mCanMove;
55

  
56
  private Dynamic2D mHaloAndRadiusDyn;
57
  private Dynamic4D mColorDyn;
58
  private PostprocessEffectGlow mGlow;
59
  private boolean mEffectWorking;
60

  
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62

  
63
  void leaveScreen(SolverActivity act)
64
    {
65
    ObjectControl control = act.getControl();
66
    control.solveOnly();
67
    }
68

  
69
///////////////////////////////////////////////////////////////////////////////////////////////////
70

  
71
  void enterScreen(final SolverActivity act)
72
    {
73
    mAct = new WeakReference<>(act);
74

  
75
    mHaloAndRadiusDyn = new Dynamic2D(FLASH_TIME,1.0f);
76
    mHaloAndRadiusDyn.add(new Static2D( 0,0));
77
    mHaloAndRadiusDyn.add(new Static2D(10,5));
78

  
79
    mColorDyn = new Dynamic4D(FLASH_TIME,1.0f);
80

  
81
    final int[] colors  = new int[] {1,1,1}; // white
82

  
83
    Static4D P1 = new Static4D(colors[0],colors[1],colors[2], 0.0f);
84
    Static4D P2 = new Static4D(colors[0],colors[1],colors[2], 1.0f);
85
    mColorDyn.add(P1);
86
    mColorDyn.add(P2);
87

  
88
    mGlow = new PostprocessEffectGlow(mHaloAndRadiusDyn,mColorDyn);
89

  
90
    float width = act.getScreenWidthInPixels();
91
    mButtonSize = width*SolverActivity.BUTTON_TEXT_SIZE;
92

  
93
    // TOP ////////////////////////////
94
    LinearLayout layoutTop = act.findViewById(R.id.upperBar);
95
    layoutTop.removeAllViews();
96

  
97
    setupPrevPhase(act);
98
    setupNextPhase(act);
99
    setupTextPhase(act,width);
100

  
101
    layoutTop.addView(mPrevPhase);
102
    layoutTop.addView(mMovesPhase);
103
    layoutTop.addView(mNextPhase);
104

  
105
    // BOT ////////////////////////////
106
    LinearLayout layoutBot = act.findViewById(R.id.lowerBar);
107
    layoutBot.removeAllViews();
108

  
109
    LinearLayout.LayoutParams paramsL = new LinearLayout.LayoutParams((int)(width/2),LinearLayout.LayoutParams.MATCH_PARENT);
110
    LinearLayout.LayoutParams paramsM = new LinearLayout.LayoutParams((int)(width/6),LinearLayout.LayoutParams.MATCH_PARENT);
111
    LinearLayout.LayoutParams paramsR = new LinearLayout.LayoutParams((int)(width/3),LinearLayout.LayoutParams.MATCH_PARENT);
112

  
113
    LinearLayout layoutLeft = new LinearLayout(act);
114
    layoutLeft.setLayoutParams(paramsL);
115
    LinearLayout layoutMid = new LinearLayout(act);
116
    layoutMid.setLayoutParams(paramsM);
117
    LinearLayout layoutRight = new LinearLayout(act);
118
    layoutRight.setLayoutParams(paramsR);
119

  
120
    setupPrevButton(act);
121
    setupNextButton(act);
122
    setupTextView(act,width);
123

  
124
    layoutLeft.addView(mPrevButton);
125
    layoutLeft.addView(mMovesText);
126
    layoutLeft.addView(mNextButton);
127

  
128
    setupBackButton(act);
129

  
130
    layoutRight.addView(mBackButton);
131

  
132
    layoutBot.addView(layoutLeft);
133
    layoutBot.addView(layoutMid);
134
    layoutBot.addView(layoutRight);
135
    }
136

  
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

  
139
  private void setupPrevButton(final SolverActivity act)
140
    {
141
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
142
    mPrevButton = new TransparentImageButton(act,R.drawable.ui_left,params);
143

  
144
    mPrevButton.setOnClickListener( new View.OnClickListener()
145
      {
146
      @Override public void onClick(View v) { backMove(); }
147
      });
148
    }
149

  
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

  
152
  private void setupNextButton(final SolverActivity act)
153
    {
154
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
155
    mNextButton = new TransparentImageButton(act,R.drawable.ui_right,params);
156

  
157
    mNextButton.setOnClickListener( new View.OnClickListener()
158
      {
159
      @Override public void onClick(View v) { nextMove(); }
160
      });
161
    }
162

  
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164

  
165
  private void setupTextView(final SolverActivity act, final float width)
166
    {
167
    int padding = (int)(width*SolverActivity.PADDING);
168
    int margin  = (int)(width*SolverActivity.SMALL_MARGIN);
169
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,2.0f);
170
    params.topMargin    = margin;
171
    params.bottomMargin = margin;
172
    params.leftMargin   = margin;
173
    params.rightMargin  = margin;
174

  
175
    mMovesText = new TextView(act);
176
    mMovesText.setTextSize(20);
177
    mMovesText.setLayoutParams(params);
178
    mMovesText.setPadding(padding,0,padding,0);
179
    mMovesText.setGravity(Gravity.CENTER);
180
    mMovesText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mButtonSize);
181
    mMovesText.setText(act.getString(R.string.mo_placeholder,mCurrMove,mNumMoves));
182
    }
183

  
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

  
186
  private void setupPrevPhase(final SolverActivity act)
187
    {
188
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
189
    mPrevPhase = new TransparentImageButton(act,R.drawable.ui_left,params);
190

  
191
    mPrevPhase.setOnClickListener( new View.OnClickListener()
192
      {
193
      @Override public void onClick(View v) { backPhase(); }
194
      });
195
    }
196

  
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198

  
199
  private void setupNextPhase(final SolverActivity act)
200
    {
201
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
202
    mNextPhase = new TransparentImageButton(act,R.drawable.ui_right,params);
203

  
204
    mNextPhase.setOnClickListener( new View.OnClickListener()
205
      {
206
      @Override public void onClick(View v) { nextPhase(); }
207
      });
208
    }
209

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

  
212
  private void setupTextPhase(final SolverActivity act, final float width)
213
    {
214
    int padding = (int)(width*SolverActivity.PADDING);
215
    int margin  = (int)(width*SolverActivity.SMALL_MARGIN);
216
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.MATCH_PARENT,2.0f);
217
    params.topMargin    = margin;
218
    params.bottomMargin = margin;
219
    params.leftMargin   = margin;
220
    params.rightMargin  = margin;
221

  
222
    mMovesPhase = new TextView(act);
223
    mMovesPhase.setTextSize(20);
224
    mMovesPhase.setLayoutParams(params);
225
    mMovesPhase.setPadding(padding,0,padding,0);
226
    mMovesPhase.setGravity(Gravity.CENTER);
227
    mMovesPhase.setTextSize(TypedValue.COMPLEX_UNIT_PX, mButtonSize);
228
    mMovesPhase.setText(act.getString(R.string.mo_placeholder,mCurrMove,mNumMoves));
229
    }
230

  
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232

  
233
  private void setupBackButton(final SolverActivity act)
234
    {
235
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
236
    mBackButton = new TransparentImageButton(act,R.drawable.ui_back,params);
237

  
238
    mBackButton.setOnClickListener( new View.OnClickListener()
239
      {
240
      @Override
241
      public void onClick(View v)
242
        {
243
        ScreenList.goBack(act);
244
        }
245
      });
246
    }
247

  
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249

  
250
  public void savePreferences(SharedPreferences.Editor editor) { }
251
  public void restorePreferences(SharedPreferences preferences) { }
252

  
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

  
255
  void backPhase()
256
    {
257
    SolverActivity act = mAct.get();
258
    ObjectControl control = act.getControl();
259

  
260
    if( mCurrMove>0 )
261
      {
262
      int[][] moves = transformMoves(mMoves[mCurrPhase],0,mCurrMove, false);
263
      control.applyScrambles(moves);
264
      mCurrMove = 0;
265
      }
266
    else if( mCurrPhase>0 )
267
      {
268
      mCurrPhase--;
269
      mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
270
      mCurrMove = 0;
271
      int[][] moves = transformMoves(mMoves[mCurrPhase],0,mNumMoves, false);
272
      control.applyScrambles(moves);
273
      }
274
    else
275
      {
276
      mCurrPhase = mNumPhases-1;
277
      mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
278
      mCurrMove = mNumMoves;
279
      int[][] moves = transformMoves(mMoves, true);
280
      control.applyScrambles(moves);
281
      }
282

  
283
    setText(act);
284
    }
285

  
286
///////////////////////////////////////////////////////////////////////////////////////////////////
287

  
288
  void nextPhase()
289
    {
290
    SolverActivity act = mAct.get();
291
    ObjectControl control = act.getControl();
292

  
293
    if( mCurrPhase<mNumPhases-1 )
294
      {
295
      glowCubits(mCubitsNotInvolved[mCurrPhase]);
296
      int[][] moves = transformMoves(mMoves[mCurrPhase],mCurrMove,mNumMoves, true);
297
      control.applyScrambles(moves);
298
      mCurrPhase++;
299
      mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
300
      mCurrMove = 0;
301
      }
302
    else if( mCurrMove<mNumMoves )
303
      {
304
      glowCubits(mCubitsNotInvolved[mCurrPhase]);
305
      int[][] moves = transformMoves(mMoves[mCurrPhase],mCurrMove,mNumMoves, true);
306
      control.applyScrambles(moves);
307
      mCurrMove = mNumMoves;
308
      }
309
    else
310
      {
311
      mCurrPhase = 0;
312
      mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
313
      mCurrMove = 0;
314
      int[][] moves = transformMoves(mMoves, false);
315
      control.applyScrambles(moves);
316
      }
317

  
318
    setText(act);
319
    }
320

  
321
///////////////////////////////////////////////////////////////////////////////////////////////////
322

  
323
  private void setText(SolverActivity act)
324
    {
325
    int currMove = 0;
326
    int totalMove = 0;
327

  
328
    if( mMoves!=null )
329
      {
330
      currMove = mCurrMove;
331
      for(int p=0; p<mCurrPhase; p++) currMove  += (mMoves[p]==null ? 0: mMoves[p].length);
332
      for(int p=0; p<mNumPhases; p++) totalMove += (mMoves[p]==null ? 0: mMoves[p].length);
333
      }
334

  
335
    final int cMove = currMove;
336
    final int tMove = totalMove;
337

  
338
    act.runOnUiThread(new Runnable()
339
      {
340
      @Override
341
      public void run()
342
        {
343
        mMovesPhase.setText(mPhaseNames[mCurrPhase]+" "+mCurrMove+"/"+mNumMoves);
344
        mMovesText.setText(cMove+"/"+tMove);
345
        }
346
      });
347
    }
348

  
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350

  
351
  private int[][] transformMoves(int[][] moves, int start, int end, boolean front)
352
    {
353
    int mult = front ? 1:-1;
354
    int len = end-start;
355
    int[][] ret = new int[len][];
356

  
357
    for(int m=0; m<len; m++)
358
      {
359
      int[] mv = moves[front ? start+m : end-1-m];
360
      int[] rt = new int[3];
361
      rt[0] = mv[0];
362
      rt[1] = (1<<mv[1]);
363
      rt[2] = mult*mv[2];
364
      ret[m] = rt;
365
      }
366

  
367
    return ret;
368
    }
369

  
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371

  
372
  private int[][] transformMoves(int[][][] moves, boolean front)
373
    {
374
    int len = moves.length;
375
    int totalLen = 0;
376
    for (int[][] move : moves) totalLen += (move==null ? 0 : move.length);
377

  
378
    int[][] ret = new int[totalLen][];
379
    int mult = front ? 1:-1;
380
    int index = 0;
381

  
382
    for(int m=0; m<len; m++)
383
      {
384
      int[][] mv = moves[front ? m : len-1-m];
385
      int l = (mv==null ? 0 : mv.length);
386

  
387
      for(int p=0; p<l; p++)
388
        {
389
        int[] mve = mv[front ? p : l-1-p];
390
        int[] rt = new int[3];
391
        rt[0] = mve[0];
392
        rt[1] = (1<<mve[1]);
393
        rt[2] = mult*mve[2];
394
        ret[index++] = rt;
395
        }
396
      }
397

  
398
    return ret;
399
    }
400

  
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

  
403
  private void glowCubits(int[] cubits)
404
    {
405
    if( !mEffectWorking )
406
      {
407
      mEffectWorking = true;
408
      SolverActivity act=mAct.get();
409
      ObjectControl control = act.getControl();
410
      TwistyObject object=control.getObject();
411
      DistortedEffects effects=object.getObjectEffects();
412
      effects.apply(mGlow);
413

  
414
      MeshBase mesh=object.getObjectMesh();
415
      mesh.setComponentsNotAffectedByPostprocessing(cubits);
416

  
417
      mHaloAndRadiusDyn.resetToBeginning();
418
      mColorDyn.resetToBeginning();
419
      mGlow.notifyWhenFinished(this);
420
      }
421
    }
422

  
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424

  
425
  private int[] computeCubitsNotInvolved(int[][] subphases, int numCubits)
426
    {
427
    int numCubitsInvolved = 0;
428
    boolean[] involved = new boolean[numCubits];
429

  
430
    for(int[] sub : subphases)
431
      if( sub!=null )
432
        for(int s : sub)
433
          {
434
          numCubitsInvolved++;
435
          involved[s] = true;
436
          }
437

  
438
    int[] ret = new int[numCubits-numCubitsInvolved];
439
    int index = 0;
440

  
441
    for(int c=0; c<numCubits; c++)
442
      if( !involved[c] ) ret[index++] = c;
443

  
444
    return ret;
445
    }
446

  
447
///////////////////////////////////////////////////////////////////////////////////////////////////
448

  
449
  void backMove()
450
    {
451
    if( mMoves!=null && mCanMove )
452
      {
453
      SolverActivity act=mAct.get();
454

  
455
      if( mCurrMove>0 )
456
        {
457
        mCanMove = false;
458
        int[] move = mMoves[mCurrPhase][--mCurrMove];
459
        ObjectControl control = act.getControl();
460
        control.blockTouch(MOVES_PLACE_0);
461
        control.addRotation(this, move[0], (1<<move[1]), -move[2], MILLIS_PER_DEGREE);
462
        }
463
      else if( mCurrPhase>0 )
464
        {
465
        mCurrPhase--;
466
        mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
467
        mCurrMove = mNumMoves;
468
        glowCubits(mCubitsNotInvolved[mCurrPhase]);
469
        }
470
      else
471
        {
472
        mCurrPhase = mNumPhases-1;
473
        mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
474
        mCurrMove = mNumMoves;
475
        int[][] moves = transformMoves(mMoves, true);
476
        ObjectControl control = act.getControl();
477
        control.applyScrambles(moves);
478
        glowCubits(mCubitsNotInvolved[mCurrPhase]);
479
        }
480

  
481
      setText(act);
482
      }
483
    }
484

  
485
///////////////////////////////////////////////////////////////////////////////////////////////////
486

  
487
  void nextMove()
488
    {
489
    if( mMoves!=null && mCanMove )
490
      {
491
      SolverActivity act=mAct.get();
492

  
493
      if( mCurrMove<mNumMoves )
494
        {
495
        mCanMove = false;
496
        int[] move = mMoves[mCurrPhase][mCurrMove++];
497
        ObjectControl control = act.getControl();
498
        control.blockTouch(MOVES_PLACE_1);
499
        control.addRotation(this, move[0], (1<<move[1]), move[2], MILLIS_PER_DEGREE);
500
        if( mCurrMove==mNumMoves && mCurrPhase==mNumPhases-1 ) glowCubits(mCubitsNotInvolved[mCurrPhase]);
501
        }
502
      else if( mCurrPhase<mNumPhases-1 )
503
        {
504
        mCurrPhase++;
505
        mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
506
        mCurrMove = 0;
507
        glowCubits(mCubitsNotInvolved[mCurrPhase-1]);
508
        }
509
      else
510
        {
511
        mCurrPhase = 0;
512
        mNumMoves = mMoves[mCurrPhase]==null ? 0 : mMoves[mCurrPhase].length;
513
        mCurrMove = 0;
514
        int[][] moves = transformMoves(mMoves, false);
515
        ObjectControl control = act.getControl();
516
        control.applyScrambles(moves);
517
        }
518

  
519
      setText(act);
520
      }
521
    }
522

  
523
///////////////////////////////////////////////////////////////////////////////////////////////////
524

  
525
  public void updateNames(String[] names)
526
    {
527
    mPhaseNames = names;
528
    mNumPhases = names.length;
529
    mMoves = new int[mNumPhases][][];
530
    mCubitsNotInvolved = new int[mNumPhases][];
531
    mCanMove = true;
532
    if( mAct!=null ) setSolution(null,0,null);
533
    }
534

  
535
///////////////////////////////////////////////////////////////////////////////////////////////////
536

  
537
  public void setSolution(int[][] moves, int phase, int[][] subphases)
538
    {
539
    SolverActivity act=mAct.get();
540

  
541
    if( subphases!=null )
542
      {
543
      ObjectControl control=act.getControl();
544
      TwistyObject object=control.getObject();
545
      int numCubits=object.getNumCubits();
546
      mCubitsNotInvolved[phase]= computeCubitsNotInvolved(subphases, numCubits);
547
      }
548

  
549
    mMoves[phase] = moves;
550
    if( phase==0 ) mNumMoves = (moves==null ? 0 : moves.length);
551
    mCurrPhase = 0;
552
    mCurrMove = 0;
553

  
554
    setText(act);
555
    }
556

  
557
///////////////////////////////////////////////////////////////////////////////////////////////////
558

  
559
  public void onActionFinished(final long effectID)
560
    {
561
    mCanMove = true;
562
    SolverActivity act=mAct.get();
563
    ObjectControl control = act.getControl();
564
    control.unblockRotation();
565
    }
566

  
567
///////////////////////////////////////////////////////////////////////////////////////////////////
568

  
569
  public void effectFinished(long id)
570
    {
571
    SolverActivity act=mAct.get();
572
    ObjectControl control = act.getControl();
573
    TwistyObject object=control.getObject();
574
    DistortedEffects effects=object.getObjectEffects();
575
    effects.abortById(id);
576
    mEffectWorking = false;
577
    }
578
  }
src/main/java/org/distorted/solverui/ScreenSetupPosition.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 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.solverui;
11

  
12
import static org.distorted.objectlib.metadata.ListObjects.*;
13
import static org.distorted.objectlib.solvers.verifiers.SolverTablebase.*;
14

  
15
import android.content.SharedPreferences;
16
import android.content.res.Resources;
17
import android.graphics.Bitmap;
18
import android.graphics.Canvas;
19
import android.graphics.Paint;
20
import android.graphics.PorterDuff;
21
import android.graphics.drawable.Drawable;
22
import android.os.Bundle;
23
import android.view.View;
24
import android.widget.ImageButton;
25
import android.widget.LinearLayout;
26

  
27
import androidx.core.content.ContextCompat;
28

  
29
import org.distorted.dialogs.RubikDialogSolverError;
30
import org.distorted.dialogs.RubikDialogSolverImpossible;
31
import org.distorted.dialogs.RubikDialogSolvers;
32
import org.distorted.helpers.TransparentImageButton;
33
import org.distorted.main.MainActivity;
34
import org.distorted.main.R;
35
import org.distorted.objectlib.helpers.OperatingSystemInterface;
36
import org.distorted.objectlib.main.ObjectControl;
37
import org.distorted.objectlib.main.TwistyObject;
38
import org.distorted.objectlib.metadata.ListObjects;
39
import org.distorted.objectlib.shape.*;
40
import org.distorted.objectlib.solvers.verifiers.ResultScreen;
41
import org.distorted.objectlib.solvers.verifiers.SolverAbstract;
42
import org.distorted.objectlib.solvers.verifiers.SolvingList;
43

  
44
import java.lang.ref.WeakReference;
45

  
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47

  
48
public class ScreenSetupPosition extends ScreenAbstract implements ResultScreen
49
  {
50
  private static final int RESET_DURATION = 1000;
51
  private static final int MODE_NORMAL = 0;
52
  private static final int MODE_DINO_4 = 1;
53

  
54
  private static final int[][] colorsHex =
55
    {
56
      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
57
      {R.string.color_white1 ,R.string.color_white2 ,R.string.color_white3 ,R.string.color_white4 ,R.string.color_white5 ,R.string.color_white6 ,R.string.color_white7  },
58
      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
59
      {R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7  },
60
      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
61
      {R.string.color_orange1,R.string.color_orange2,R.string.color_orange3,R.string.color_orange4,R.string.color_orange5,R.string.color_orange6,R.string.color_orange7 },
62
    };
63
  private static final int[][] colorsTet =
64
    {
65
      {R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7  },
66
      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
67
      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
68
      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
69
    };
70
  private static final int[][] colorsOct =
71
    {
72
      {R.string.color_violet1,R.string.color_violet2,R.string.color_violet3,R.string.color_violet4,R.string.color_violet5,R.string.color_violet6,R.string.color_violet7 },
73
      {R.string.color_grey1  ,R.string.color_grey2  ,R.string.color_grey3  ,R.string.color_grey4  ,R.string.color_grey5  ,R.string.color_grey6  ,R.string.color_grey7   },
74
      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
75
      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
76
      {R.string.color_orange1,R.string.color_orange2,R.string.color_orange3,R.string.color_orange4,R.string.color_orange5,R.string.color_orange6,R.string.color_orange7 },
77
      {R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7  },
78
      {R.string.color_white1 ,R.string.color_white2 ,R.string.color_white3 ,R.string.color_white4 ,R.string.color_white5 ,R.string.color_white6 ,R.string.color_white7  },
79
      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
80
    };
81
  private static final int[][] colorsDi4 =
82
    {
83
      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
84
      {R.string.color_white1 ,R.string.color_white2 ,R.string.color_white3 ,R.string.color_white4 ,R.string.color_white5 ,R.string.color_white6 ,R.string.color_white7  },
85
      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
86
      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
87
    };
88

  
89
  private static Bitmap[] mBitmap;
90
  private ImageButton[] mColorButton;
91
  private TransparentImageButton mResetButton,mBackButton, mSolveButton;
92
  private boolean mSolving;
93
  private int mCurrentColor, mCurrentButton;
94
  private int[] mFaceColors;
95
  private int mColorMode;
96
  private int mNumColors;
97
  private int mNumBitmapRows;
98
  private float mBitmapSize;
99
  private WeakReference<SolverActivity> mWeakAct;
100
  private int mObjectOrdinal;
101
  private String[] mPhaseNames;
102

  
103
///////////////////////////////////////////////////////////////////////////////////////////////////
104

  
105
  void leaveScreen(SolverActivity act)
106
    {
107
    ObjectControl control = act.getControl();
108
    control.unsetLock();
109
    }
110

  
111
///////////////////////////////////////////////////////////////////////////////////////////////////
112

  
113
  void enterScreen(final SolverActivity act)
114
    {
115
    ObjectControl control = act.getControl();
116
    control.setLock(false);
117

  
118
    float width = act.getScreenWidthInPixels();
119
    float heigh = act.getScreenHeightInPixels();
120

  
121
    mWeakAct = new WeakReference<>(act);
122
    mSolving = false;
123
    mPhaseNames = null;
124

  
125
    mObjectOrdinal = act.getObjectOrdinal();
126
    control.solveOnly();
127
    generateFaceColors(mObjectOrdinal);
128

  
129
    mNumBitmapRows = mNumColors>8 ? 2 : 1;
130
    mBitmapSize = computeBitmapSize(width,heigh);
131

  
132
    // TOP ////////////////////////////
133
    LinearLayout layoutTop = act.findViewById(R.id.upperBar);
134
    layoutTop.removeAllViews();
135

  
136
    if( mNumColors>0 )
137
      {
138
      setupBitmaps();
139
      setupColorButtons(act);
140
      markButton(act);
141
      addButtonsToTopLayout(act,layoutTop);
142
      }
143

  
144
    // BOT ////////////////////////////
145
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1);
146

  
147
    LinearLayout layoutL = new LinearLayout(act);
148
    layoutL.setLayoutParams(params);
149
    LinearLayout layoutM = new LinearLayout(act);
150
    layoutM.setLayoutParams(params);
151
    LinearLayout layoutR = new LinearLayout(act);
152
    layoutR.setLayoutParams(params);
153

  
154
    LinearLayout layoutBot = act.findViewById(R.id.lowerBar);
155
    layoutBot.removeAllViews();
156

  
157
    setupResetButton(act);
158
    setupSolveButton(act);
159
    setupBackButton(act);
160

  
161
    layoutL.addView(mResetButton);
162
    layoutM.addView(mSolveButton);
163
    layoutR.addView(mBackButton);
164

  
165
    layoutBot.addView(layoutL);
166
    layoutBot.addView(layoutM);
167
    layoutBot.addView(layoutR);
168
    }
169

  
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171

  
172
  private float computeBitmapSize(float width, float heigh)
173
    {
174
    final float BUTTON_RATIO = 0.75f;
175
    float sizeV = (heigh/mNumBitmapRows)*MainActivity.RATIO_BAR;
176
    float sizeH = (width*mNumBitmapRows)/mNumColors;
177

  
178
    return BUTTON_RATIO*Math.min(sizeV,sizeH);
179
    }
180

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

  
183
  private void addButtonsToTopLayout(SolverActivity act, LinearLayout layout)
184
    {
185
    if( mNumBitmapRows==1 )
186
      {
187
      for(ImageButton button: mColorButton) layout.addView(button);
188
      }
189
    else if( mNumBitmapRows==2 )
190
      {
191
      LinearLayout layoutV = new LinearLayout(act);
192
      layoutV.setOrientation(LinearLayout.VERTICAL);
193
      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1);
194
      layoutV.setLayoutParams(params);
195
      LinearLayout layoutT = new LinearLayout(act);
196
      layoutT.setOrientation(LinearLayout.HORIZONTAL);
197
      LinearLayout layoutB = new LinearLayout(act);
198
      layoutB.setOrientation(LinearLayout.HORIZONTAL);
199

  
200
      int numB = mColorButton.length;
201
      for(int b=0     ; b<numB/2; b++) layoutT.addView(mColorButton[b]);
202
      for(int b=numB/2; b<numB  ; b++) layoutB.addView(mColorButton[b]);
203

  
204
      layoutV.addView(layoutT);
205
      layoutV.addView(layoutB);
206
      layout.addView(layoutV);
207
      }
208
    }
209

  
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211
// This doesn't quite work in many cases, but in case of the solvers that will pop up in foreseeable
212
// future it should be ok.
213

  
214
  public void generateFaceColors(int object)
215
    {
216
    mColorMode = MODE_NORMAL;
217

  
218
    if( object==PYRA_3.ordinal() ||
219
        object==PYRA_4.ordinal() ||
220
        object==PYRA_5.ordinal() ||
221
        object==PDUO_2.ordinal() ||
222
        object==JING_2.ordinal() ||
223
        object==MORP_2.ordinal() ||
224
        object==MORP_3.ordinal() ||
225
        object==MORP_4.ordinal()  )
226
      {
227
      mNumColors  = ShapeTetrahedron.NUM_FACES;
228
      mFaceColors = ShapeTetrahedron.FACE_COLORS;
229
      }
230
    else if( object==DIAM_2.ordinal() ||
231
             object==DIAM_3.ordinal() ||
232
             object==DIAM_4.ordinal() ||
233
             object==TRAJ_3.ordinal() ||
234
             object==TRAJ_4.ordinal() ||
235
             object==PDIA_3.ordinal()  )
236
      {
237
      mNumColors  = ShapeOctahedron.NUM_FACES;
238
      mFaceColors = ShapeOctahedron.FACE_COLORS;
239
      }
240
    else if( object==CRYS_3.ordinal() ||
241
             object==STAR_3.ordinal() ||
242
             object==PENT_2.ordinal() ||
243
             object==KILO_3.ordinal() ||
244
             object==KILO_5.ordinal() ||
245
             object==MEGA_3.ordinal() ||
246
             object==MEGA_5.ordinal()  )
247
      {
248
      mNumColors  = ShapeDodecahedron.NUM_FACES;
249
      mFaceColors = ShapeDodecahedron.FACE_COLORS;
250
      }
251
    else if( object==BALL_4.ordinal() )
252
      {
253
      mNumColors  = ShapeDiamond.NUM_FACES;
254
      mFaceColors = ShapeDiamond.FACE_COLORS;
255
      }
256
    else if( object==ICOS_2.ordinal() )
257
      {
258
      mNumColors  = ShapeIcosahedron.NUM_FACES;
259
      mFaceColors = ShapeIcosahedron.FACE_COLORS;
260
      }
261
    else if( object==DIN4_3.ordinal() )
262
      {
263
      mNumColors  = 4;
264
      mFaceColors = new int[] { ShapeColors.COLOR_YELLOW, ShapeColors.COLOR_RED, ShapeColors.COLOR_BLUE, ShapeColors.COLOR_WHITE};
265
      mColorMode  = MODE_DINO_4;
266
      }
267
    else
268
      {
269
      mNumColors  = ShapeHexahedron.NUM_FACES;
270
      mFaceColors = ShapeHexahedron.FACE_COLORS;
271
      }
272
    }
273

  
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275

  
276
  private void setupBitmaps()
277
    {
278
    final int SIZE = (int)mBitmapSize;
279
    final float R = SIZE*0.15f;
280
    final float M = SIZE*0.08f;
281

  
282
    mBitmap = new Bitmap[mNumColors];
283

  
284
    Paint paint = new Paint();
285
    paint.setColor(0xff008800);
286
    paint.setStyle(Paint.Style.FILL);
287

  
288
    paint.setAntiAlias(true);
289
    paint.setTextAlign(Paint.Align.CENTER);
290
    paint.setStyle(Paint.Style.FILL);
291

  
292
    for(int i=0; i<mNumColors; i++)
293
      {
294
      mBitmap[i] = Bitmap.createBitmap(SIZE, SIZE, Bitmap.Config.ARGB_8888);
295
      Canvas canvas = new Canvas(mBitmap[i]);
296

  
297
      paint.setColor(0xff000000);
298
      canvas.drawRect(0, 0, SIZE, SIZE, paint);
299

  
300
      paint.setColor(mFaceColors[i]);
301
      canvas.drawRoundRect( M, M, SIZE-M, SIZE-M, R, R, paint);
302
      }
303
    }
304

  
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306

  
307
  private int translateColor(int color)
308
    {
309
    if( mColorMode==MODE_DINO_4 )
310
      {
311
      int realColor = mFaceColors[color];
312
      int[] hexColors = ShapeHexahedron.FACE_COLORS;
313

  
314
      for(int i=0; i<6; i++)
315
        if( hexColors[i]==realColor ) return i;
316
      }
317

  
318
    return color;
319
    }
320

  
321
///////////////////////////////////////////////////////////////////////////////////////////////////
322

  
323
  private boolean pressSolve(SolverActivity act)
324
    {
325
    int[] solverOrdinals = SolvingList.getSolverOrdinals(mObjectOrdinal);
326

  
327
    if( solverOrdinals!=null  )
328
      {
329
      SolvingList slvList = SolvingList.getSolver(solverOrdinals[0]);
330
      OperatingSystemInterface os = act.getInterface();
331
      TwistyObject object = act.getObject();
332
      SolverAbstract solver = slvList.create(os,object);
333

  
334
      if( solver!=null )
335
        {
336
        int[] result = solver.validatePosition(object);
337

  
338
        if( result[0]>=0 ) // position is valid
339
          {
340
          if( solverOrdinals.length==1 ) // just one solver - simply launch it
341
            {
342
            solver.solve(this,result);
343
            return true;
344
            }
345
          else // more than one solver - pop up a choosing dialog
346
            {
347
            ListObjects objList = ListObjects.getObject(mObjectOrdinal);
348
            String upperName = objList.name();
349
            Bundle bundle = new Bundle();
350
            bundle.putString("argument", upperName );
351
            RubikDialogSolvers solv = new RubikDialogSolvers();
352
            solv.setArguments(bundle);
353
            solv.show( act.getSupportFragmentManager(), RubikDialogSolvers.getDialogTag() );
354
            return false;
355
            }
356
          }
357
        else
358
          {
359
          displayImpossibleDialog(result,solver.getFaceColors());
360
          return false;
361
          }
362
        }
363
      else
364
        {
365
        displayErrorDialog(act.getString(R.string.solver_generic_not_implemented));
366
        return false;
367
        }
368
      }
369
    else  // no solvers? Impossible!
370
      {
371
      displayErrorDialog("No solvers found for object "+mObjectOrdinal);
372
      return false;
373
      }
374
    }
375

  
376
///////////////////////////////////////////////////////////////////////////////////////////////////
377

  
378
  public void fail(String result) {}
379
  public void setPhaseNames(String[] names) { mPhaseNames = names; }
380

  
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

  
383
  private void setupColorButtons(final SolverActivity act)
384
    {
385
    mColorButton = new ImageButton[mNumColors];
386

  
387
    for(int i=0; i<mNumColors; i++)
388
      {
389
      final int ii = i;
390
      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.MATCH_PARENT, 1.0f);
391

  
392
      mColorButton[i] = new ImageButton(act);
393
      mColorButton[i].setLayoutParams(params);
394
      mColorButton[i].setImageBitmap(mBitmap[i]);
395

  
396
      mColorButton[i].setOnClickListener( new View.OnClickListener()
397
        {
398
        @Override
399
        public void onClick(View view)
400
          {
401
          mCurrentColor = translateColor(ii);
402
          mCurrentButton= ii;
403
          markButton(act);
404
          }
405
        });
406
      }
407
    }
408

  
409
///////////////////////////////////////////////////////////////////////////////////////////////////
410

  
411
  private void setupResetButton(final SolverActivity act)
412
    {
413
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
414
    mResetButton = new TransparentImageButton(act, R.drawable.ui_reset, params);
415

  
416
    mResetButton.setOnClickListener( new View.OnClickListener()
417
      {
418
      @Override
419
      public void onClick(View v)
420
        {
421
        ObjectControl control = act.getControl();
422
        control.resetTextureMapsEffect(RESET_DURATION);
423
        }
424
      });
425
    }
426

  
427
///////////////////////////////////////////////////////////////////////////////////////////////////
428

  
429
  private void setupSolveButton(final SolverActivity act)
430
    {
431
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
432
    mSolveButton = new TransparentImageButton(act,R.drawable.ui_solve,params);
433

  
434
    mSolveButton.setOnClickListener( new View.OnClickListener()
435
      {
436
      @Override
437
      public void onClick(View v)
438
        {
439
        if( !mSolving && pressSolve(act) ) mSolving = true;
440
        }
441
      });
442
    }
443

  
444
///////////////////////////////////////////////////////////////////////////////////////////////////
445

  
446
  private void setupBackButton(final SolverActivity act)
447
    {
448
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
449
    mBackButton = new TransparentImageButton(act,R.drawable.ui_back,params);
450

  
451
    mBackButton.setOnClickListener( new View.OnClickListener()
452
      {
453
      @Override
454
      public void onClick(View v)
455
        {
456
        ObjectControl control = act.getControl();
457
        control.resetAllTextureMaps();
458
        ScreenList.goBack(act);
459
        }
460
      });
461
    }
462

  
463
///////////////////////////////////////////////////////////////////////////////////////////////////
464

  
465
  private void markButton(SolverActivity act)
466
    {
467
    if( mCurrentButton>=mNumColors )
468
      {
469
      mCurrentButton = 0;
470
      mCurrentColor = translateColor(0);
471
      }
472

  
473
    for(int b=0; b<mNumColors; b++)
474
      {
475
      Drawable d = mColorButton[b].getBackground();
476
      int s = b==mCurrentButton ? act.getSelectedColor() : act.getNormalColor();
477
      d.setColorFilter(ContextCompat.getColor(act,s), PorterDuff.Mode.MULTIPLY);
478
      }
479
    }
480

  
481
///////////////////////////////////////////////////////////////////////////////////////////////////
482

  
483
  public void savePreferences(SharedPreferences.Editor editor)
484
    {
485
    editor.putInt("stateSolver_color" , mCurrentColor );
486
    editor.putInt("stateSolver_button", mCurrentButton);
487
    }
488

  
489
///////////////////////////////////////////////////////////////////////////////////////////////////
490

  
491
  public void restorePreferences(SharedPreferences preferences)
492
    {
493
    mCurrentColor = preferences.getInt("stateSolver_color" , 0);
494
    mCurrentButton= preferences.getInt("stateSolver_button", 0);
495
    }
496

  
497
///////////////////////////////////////////////////////////////////////////////////////////////////
498

  
499
  public int getCurrentColor()
500
    {
501
    return mCurrentColor;
502
    }
503

  
504
///////////////////////////////////////////////////////////////////////////////////////////////////
505

  
506
  public void setSolved(final String moves)
507
    {
508
    mSolving = false;
509
    final SolverActivity act = mWeakAct.get();
510

  
511
    if( act!=null )
512
      {
513
      act.runOnUiThread(new Runnable()
514
        {
515
        @Override
516
        public void run()
517
          {
518
          ScreenList.switchScreen(act, ScreenList.SOLU);
519
          ScreenSolutionSinglephased solution = (ScreenSolutionSinglephased) ScreenList.SOLU.getScreenClass();
520
          solution.setSolution(moves);
521
          if( !moves.isEmpty() ) act.doNotShowDialogAnymore();
522
          }
523
        });
524
      }
525
    }
526

  
527
///////////////////////////////////////////////////////////////////////////////////////////////////
528

  
529
  public void setSolved(final int[][] moves, final int phaseNumber, final int[][] subphases)
530
    {
531
    mSolving = false;
532
    final SolverActivity act = mWeakAct.get();
533

  
534
    if( act!=null )
535
      {
536
      act.runOnUiThread(new Runnable()
537
        {
538
        @Override
539
        public void run()
540
          {
541
          if( mPhaseNames!=null )
542
            {
543
            ScreenSolutionMultiphased screen = (ScreenSolutionMultiphased) ScreenList.PHAS.getScreenClass();
544
            if( phaseNumber==0 )
545
              {
546
              ScreenList.switchScreen(act, ScreenList.PHAS);
547
              screen.updateNames(mPhaseNames);
548
              }
549
            screen.setSolution(moves, phaseNumber,subphases);
550
            }
551
          else
552
            {
553
            ScreenList.switchScreen(act, ScreenList.SOLU);
554
            ScreenSolutionSinglephased screen = (ScreenSolutionSinglephased) ScreenList.SOLU.getScreenClass();
555
            screen.setSolution(moves);
556
            }
557

  
558
          if( moves!=null && moves.length>0 ) act.doNotShowDialogAnymore();
559
          }
560
        });
561
      }
562
    }
563

  
564
///////////////////////////////////////////////////////////////////////////////////////////////////
565

  
566
  public void displayErrorDialog(String message)
567
    {
568
    mSolving = false;
569
    SolverActivity act = mWeakAct.get();
570

  
571
    if( act!=null )
572
      {
573
      RubikDialogSolverError dialog = new RubikDialogSolverError();
574
      Bundle bundle = new Bundle();
575
      bundle.putString("argument", message );
576
      dialog.setArguments(bundle);
577
      dialog.show( act.getSupportFragmentManager(), null);
578
      }
579
    }
580

  
581
///////////////////////////////////////////////////////////////////////////////////////////////////
582

  
583
  public void displayImpossibleDialog(String message)
584
    {
585
    mSolving = false;
586
    SolverActivity act = mWeakAct.get();
587

  
588
    if( act!=null )
589
      {
590
      RubikDialogSolverImpossible dialog = new RubikDialogSolverImpossible();
591
      Bundle bundle = new Bundle();
592
      bundle.putString("argument", message );
593
      dialog.setArguments(bundle);
594
      dialog.show( act.getSupportFragmentManager(), null);
595
      }
596
    }
597

  
598
///////////////////////////////////////////////////////////////////////////////////////////////////
599

  
600
  public void displayImpossibleDialog(int[] errorCode, int[] faceColors)
601
    {
602
    mSolving = false;
603
    SolverActivity act = mWeakAct.get();
604

  
605
    if( act!=null )
606
      {
607
      String message = error(act.getResources(),errorCode,faceColors);
608
      displayImpossibleDialog(message);
609
      }
610
    }
611

  
612
///////////////////////////////////////////////////////////////////////////////////////////////////
613

  
614
  int getHexColor(int color,int variant) { return colorsHex[color][variant]; }
615
  int getTetColor(int color,int variant) { return colorsTet[color][variant]; }
616
  int getOctColor(int color,int variant) { return colorsOct[color][variant]; }
617
  int getDi4Color(int color,int variant) { return colorsDi4[color][variant]; }
618

  
619
///////////////////////////////////////////////////////////////////////////////////////////////////
620

  
621
  String hexCornerMissingError(Resources res, int face0, int face1, int face2)
622
    {
623
    int j0 = getHexColor(face0,3);
624
    int j1 = getHexColor(face1,3);
625
    int j2 = getHexColor(face2,4);
626

  
627
    String c0 = res.getString(j0);
628
    String c1 = res.getString(j1);
629
    String c2 = res.getString(j2);
630

  
631
    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
632
    }
633

  
634
///////////////////////////////////////////////////////////////////////////////////////////////////
635

  
636
  String hexCenterMissingError(Resources res, int face)
637
    {
638
    int color = getHexColor(face,2);
639
    String clr= res.getString(color);
640
    return res.getString(R.string.solver_generic_missing_center,clr);
641
    }
642

  
643
///////////////////////////////////////////////////////////////////////////////////////////////////
644

  
645
  String hexEdgeMissingError(Resources res, int face0, int face1)
646
    {
647
    int j0 = getHexColor(face0,3);
648
    int j1 = getHexColor(face1,6);
649

  
650
    String c0 = res.getString(j0);
651
    String c1 = res.getString(j1);
652

  
653
    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
654
    }
655

  
656
///////////////////////////////////////////////////////////////////////////////////////////////////
657

  
658
  String hexEdgeTwistedError(Resources res, int color0, int color1)
659
    {
660
    int j0 = getHexColor(color0,3);
661
    int j1 = getHexColor(color1,6);
662

  
663
    String c0 = res.getString(j0);
664
    String c1 = res.getString(j1);
665

  
666
    return res.getString(R.string.solver_generic_twisted_edge,c0,c1);
667
    }
668

  
669
///////////////////////////////////////////////////////////////////////////////////////////////////
670

  
671
  String hexCornerTwistedError(Resources res, int color0, int color1, int color2)
672
    {
673
    int j0 = getHexColor(color0,3);
674
    int j1 = getHexColor(color1,3);
675
    int j2 = getHexColor(color2,5);
676

  
677
    String c0 = res.getString(j0);
678
    String c1 = res.getString(j1);
679
    String c2 = res.getString(j2);
680

  
681
    return res.getString(R.string.solver_generic_twisted_corner,c0,c1,c2);
682
    }
683

  
684
///////////////////////////////////////////////////////////////////////////////////////////////////
685

  
686
  String hexEdgeMonoError(Resources res, int color)
687
    {
688
    int j0 = getHexColor(color,3);
689
    int j1 = getHexColor(color,6);
690
    String c0 = res.getString(j0);
691
    String c1 = res.getString(j1);
692

  
693
    return res.getString(R.string.solver_generic_edge_mono,c0,c1);
694
    }
695

  
696
///////////////////////////////////////////////////////////////////////////////////////////////////
697

  
698
  String hexEdgeTwiceError(Resources res, int color0, int color1)
699
    {
700
    int j0 = getHexColor(color0,3);
701
    int j1 = getHexColor(color1,6);
702
    String c0 = res.getString(j0);
703
    String c1 = res.getString(j1);
704

  
705
    return res.getString(R.string.solver_generic_edge_twice,c0,c1);
706
    }
707

  
708
///////////////////////////////////////////////////////////////////////////////////////////////////
709

  
710
  String octCenterMissingError(Resources res, int face)
711
    {
712
    int index = getOctColor(face,2);
713
    String color = res.getString(index);
714
    return res.getString(R.string.solver_generic_missing_center,color);
715
    }
716

  
717
///////////////////////////////////////////////////////////////////////////////////////////////////
718

  
719
  String octCornerMissingError(Resources res, int f1, int f2)
720
    {
721
    int i1 = getOctColor(f1,3);
722
    int i2 = getOctColor(f2,4);
723
    String c1 = res.getString(i1);
724
    String c2 = res.getString(i2);
725
    return res.getString(R.string.solver_generic_missing_corner2,c1,c2);
726
    }
727

  
728
///////////////////////////////////////////////////////////////////////////////////////////////////
729

  
730
  String tetCornerMissingError(Resources res, int color0, int color1, int color2)
731
    {
732
    int j0 = getTetColor(color0,3);
733
    int j1 = getTetColor(color1,3);
734
    int j2 = getTetColor(color2,4);
735

  
736
    String c0 = res.getString(j0);
737
    String c1 = res.getString(j1);
738
    String c2 = res.getString(j2);
739

  
740
    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
741
    }
742

  
743
///////////////////////////////////////////////////////////////////////////////////////////////////
744

  
745
  String tetEdgeMissingError(Resources res, int face0, int face1)
746
    {
747
    int j0 = getTetColor(face0,3);
748
    int j1 = getTetColor(face1,6);
749

  
750
    String c0 = res.getString(j0);
751
    String c1 = res.getString(j1);
752

  
753
    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
754
    }
755

  
756
///////////////////////////////////////////////////////////////////////////////////////////////////
757

  
758
  String tetCenterMissingError(Resources res, int face)
759
    {
760
    int j = getTetColor(face,2);
761
    String c = res.getString(j);
762
    return res.getString(R.string.solver_generic_missing_center,c);
763
    }
764

  
765
///////////////////////////////////////////////////////////////////////////////////////////////////
766

  
767
  String tetVertexMissingError(Resources res, int color0, int color1, int color2)
768
    {
769
    int j0 = getTetColor(color0,3);
770
    int j1 = getTetColor(color1,3);
771
    int j2 = getTetColor(color2,4);
772

  
773
    String c0 = res.getString(j0);
774
    String c1 = res.getString(j1);
775
    String c2 = res.getString(j2);
776

  
777
    return res.getString(R.string.solver_generic_missing_vertex,c0,c1,c2);
778
    }
779

  
780
///////////////////////////////////////////////////////////////////////////////////////////////////
781

  
782
  String di4EdgeThreeError(Resources res, int color)
783
    {
784
    int j0 = getDi4Color(color,7);
785
    String c0 = res.getString(j0);
786
    return res.getString(R.string.solver_generic_edge_three,c0);
787
    }
788

  
789
///////////////////////////////////////////////////////////////////////////////////////////////////
790

  
791
  public String error(Resources res, int[] err, int[] faceColors)
792
    {
793
    switch(err[0])
794
      {
795
      case ERROR_HEX_CORNER_MISSING    : return hexCornerMissingError(res,err[1],err[2],err[3]);
796
      case ERROR_HEX_CENTER_MISSING    : return hexCenterMissingError(res,err[1]);
797
      case ERROR_HEX_EDGE_MISSING      : return hexEdgeMissingError(res,err[1],err[2]);
798
      case ERROR_HEX_EDGE_TWISTED      : return hexEdgeTwistedError(res,err[1],err[2]);
799
      case ERROR_HEX_EDGE_MONOCHROMATIC: return hexEdgeMonoError(res,err[1]);
800
      case ERROR_HEX_EDGE_TWICE        : return hexEdgeTwiceError(res,err[1],err[2]);
801
      case ERROR_HEX_CORNER_TWISTED    : return hexCornerTwistedError(res,err[1],err[2],err[3]);
802

  
803
      case ERROR_TET_CORNER_MISSING    : return tetCornerMissingError(res,err[1],err[2],err[3]);
804
      case ERROR_TET_VERTEX_MISSING    : return tetVertexMissingError(res,err[1],err[2],err[3]);
805
      case ERROR_TET_EDGE_MISSING      : return tetEdgeMissingError(res,faceColors[err[1]],faceColors[err[2]]);
806
      case ERROR_TET_CENTER_MISSING    : return tetCenterMissingError(res,err[1]);
807

  
808
      case ERROR_OCT_CENTER_MISSING    : return octCenterMissingError(res,err[1]);
809
      case ERROR_OCT_CORNER_MISSING    : return octCornerMissingError(res,err[1],err[2]);
810

  
811
      case ERROR_DI4_EDGE_THREE        : return di4EdgeThreeError(res,err[1]);
812

  
813
      case ERROR_CORNERS_CANNOT        : return res.getString(R.string.solver_generic_corners_cannot);
814
      case ERROR_EDGE_CANNOT           : return res.getString(R.string.solver_generic_edges_cannot);
815
      case ERROR_CORNER_TWISTED        : return res.getString(R.string.solver_generic_corner_twist);
816
      case ERROR_CORNER_TWIST_90       : return res.getString(R.string.solver_generic_corner_twist) + " (90)";
817
      case ERROR_CORNER_TWIST_180      : return res.getString(R.string.solver_generic_corner_twist) + " (180)";
818
      case ERROR_EDGE_TWISTED          : return res.getString(R.string.solver_generic_edge_twist);
819
      case ERROR_TWO_CENTERS           : return res.getString(R.string.solver_generic_two_centers);
820
      case ERROR_TWO_CORNERS           : return res.getString(R.string.solver_generic_two_corners);
821
      case ERROR_TWO_EDGES             : return res.getString(R.string.solver_generic_two_edges);
822
      case ERROR_FREE_CORNERS_NOT_EVEN : return res.getString(R.string.solver_generic_free_corners_odd);
823
      case ERROR_FREE_CORNERS_ROTATED  : return res.getString(R.string.solver_generic_free_corners_rotated);
824
      case ERROR_VERTICES_CANNOT       : return res.getString(R.string.solver_generic_vertices_cannot);
825
      case ERROR_C_V_DONT_MATCH        : return res.getString(R.string.solver_generic_c_v_dont_match);
826
      case ERROR_TWO_CORNERS_TWO_EDGES : return res.getString(R.string.solver_two_corners_two_edges);
827
      }
828

  
829
    return null;
830
    }
831
  }
src/main/java/org/distorted/solverui/ScreenSolution.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 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.solverui;
11

  
12
import android.content.SharedPreferences;
13
import android.util.TypedValue;
14
import android.view.Gravity;
15
import android.view.LayoutInflater;
16
import android.view.View;
17
import android.widget.LinearLayout;
18
import android.widget.TextView;
19

  
20
import org.distorted.helpers.TransparentImageButton;
21
import org.distorted.main.R;
22
import org.distorted.objectlib.helpers.MovesFinished;
23
import org.distorted.objectlib.main.ObjectControl;
24
import org.distorted.objectlib.patterns.RubikPattern;
25

  
26
import java.lang.ref.WeakReference;
27

  
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff