Project

General

Profile

Download (16.3 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / solverui / ScreenSolver.java @ 99c2e327

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.graphics.Bitmap;
14
import android.graphics.Canvas;
15
import android.graphics.Paint;
16
import android.graphics.PorterDuff;
17
import android.graphics.drawable.Drawable;
18
import android.os.Bundle;
19
import android.view.View;
20
import android.widget.ImageButton;
21
import android.widget.LinearLayout;
22

    
23
import androidx.core.content.ContextCompat;
24

    
25
import org.distorted.dialogs.RubikDialogSolverError;
26
import org.distorted.dialogs.RubikDialogSolverImpossible;
27
import org.distorted.helpers.TransparentImageButton;
28
import org.distorted.main.MainActivity;
29
import org.distorted.main.R;
30
import org.distorted.objectlib.main.ObjectControl;
31
import org.distorted.objectlib.main.TwistyObject;
32
import org.distorted.objectlib.metadata.MetadataBALL_4;
33
import org.distorted.objectlib.metadata.MetadataCRYS_3;
34
import org.distorted.objectlib.metadata.MetadataDIAM_2;
35
import org.distorted.objectlib.metadata.MetadataDIAM_3;
36
import org.distorted.objectlib.metadata.MetadataDIAM_4;
37
import org.distorted.objectlib.metadata.MetadataDIN4_3;
38
import org.distorted.objectlib.metadata.MetadataICOS_2;
39
import org.distorted.objectlib.metadata.MetadataJING_2;
40
import org.distorted.objectlib.metadata.MetadataKILO_3;
41
import org.distorted.objectlib.metadata.MetadataKILO_5;
42
import org.distorted.objectlib.metadata.MetadataMEGA_3;
43
import org.distorted.objectlib.metadata.MetadataMEGA_5;
44
import org.distorted.objectlib.metadata.MetadataMORP_2;
45
import org.distorted.objectlib.metadata.MetadataMORP_3;
46
import org.distorted.objectlib.metadata.MetadataMORP_4;
47
import org.distorted.objectlib.metadata.MetadataPDIA_3;
48
import org.distorted.objectlib.metadata.MetadataPDUO_2;
49
import org.distorted.objectlib.metadata.MetadataPENT_2;
50
import org.distorted.objectlib.metadata.MetadataPYRA_3;
51
import org.distorted.objectlib.metadata.MetadataPYRA_4;
52
import org.distorted.objectlib.metadata.MetadataPYRA_5;
53
import org.distorted.objectlib.metadata.MetadataSTAR_3;
54
import org.distorted.objectlib.metadata.MetadataTRAJ_3;
55
import org.distorted.objectlib.metadata.MetadataTRAJ_4;
56
import org.distorted.objectlib.shape.ShapeColors;
57
import org.distorted.objectlib.shape.ShapeDiamond;
58
import org.distorted.objectlib.shape.ShapeDodecahedron;
59
import org.distorted.objectlib.shape.ShapeHexahedron;
60
import org.distorted.objectlib.shape.ShapeIcosahedron;
61
import org.distorted.objectlib.shape.ShapeOctahedron;
62
import org.distorted.objectlib.shape.ShapeTetrahedron;
63
import org.distorted.solvers.ImplementedSolversList;
64
import org.distorted.solvers.SolverMain;
65

    
66
import java.lang.ref.WeakReference;
67

    
68
///////////////////////////////////////////////////////////////////////////////////////////////////
69

    
70
public class ScreenSolver extends ScreenAbstract
71
  {
72
  private static final int RESET_DURATION = 1000;
73
  private static final int MODE_NORMAL = 0;
74
  private static final int MODE_DINO_4 = 1;
75

    
76
  private static Bitmap[] mBitmap;
77
  private ImageButton[] mColorButton;
78
  private TransparentImageButton mResetButton,mBackButton, mSolveButton;
79
  private boolean mSolving;
80
  private int mCurrentColor, mCurrentButton;
81
  private int[] mFaceColors;
82
  private int mColorMode;
83
  private int mNumColors;
84
  private float mBitmapSize;
85
  private WeakReference<SolverActivity> mWeakAct;
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

    
89
  void leaveScreen(SolverActivity act)
90
    {
91
    ObjectControl control = act.getControl();
92
    control.unsetLock();
93
    }
94

    
95
///////////////////////////////////////////////////////////////////////////////////////////////////
96

    
97
  void enterScreen(final SolverActivity act)
98
    {
99
    ObjectControl control = act.getControl();
100
    control.setLock(false);
101

    
102
    float width = act.getScreenWidthInPixels();
103
    float heigh = act.getScreenHeightInPixels();
104

    
105
    mWeakAct = new WeakReference<>(act);
106
    mSolving = false;
107

    
108
    int solverIndex= act.getSolverOrdinal();
109
    ImplementedSolversList currentSolver = ImplementedSolversList.getSolver(solverIndex);
110
    int currentObject = currentSolver.getObject();
111
    control.solveOnly();
112
    generateFaceColors(currentObject);
113

    
114
    final float BUTTON_RATIO = 0.75f;
115
    int sizeV = (int)(heigh*MainActivity.RATIO_BAR*BUTTON_RATIO);
116
    int sizeH = (int)((width/mNumColors)*BUTTON_RATIO);
117
    mBitmapSize = Math.min(sizeV,sizeH);
118

    
119
    // TOP ////////////////////////////
120
    LinearLayout layoutTop = act.findViewById(R.id.upperBar);
121
    layoutTop.removeAllViews();
122

    
123
    if( mNumColors>0 )
124
      {
125
      setupBitmaps();
126
      setupColorButtons(act,width);
127
      markButton(act);
128
      }
129

    
130
    for(ImageButton button: mColorButton) layoutTop.addView(button);
131

    
132
    // BOT ////////////////////////////
133
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1);
134

    
135
    LinearLayout layoutL = new LinearLayout(act);
136
    layoutL.setLayoutParams(params);
137
    LinearLayout layoutM = new LinearLayout(act);
138
    layoutM.setLayoutParams(params);
139
    LinearLayout layoutR = new LinearLayout(act);
140
    layoutR.setLayoutParams(params);
141

    
142
    LinearLayout layoutBot = act.findViewById(R.id.lowerBar);
143
    layoutBot.removeAllViews();
144

    
145
    setupResetButton(act);
146
    setupSolveButton(act);
147
    setupBackButton(act);
148

    
149
    layoutL.addView(mResetButton);
150
    layoutM.addView(mSolveButton);
151
    layoutR.addView(mBackButton);
152

    
153
    layoutBot.addView(layoutL);
154
    layoutBot.addView(layoutM);
155
    layoutBot.addView(layoutR);
156
    }
157

    
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159
// This doesn't quite work in many cases, but in case of the solvers that will pop up in foreseeable
160
// future it should be ok.
161

    
162
  public void generateFaceColors(int object)
163
    {
164
    mColorMode = MODE_NORMAL;
165

    
166
    if( object==MetadataPYRA_3.INDEX ||
167
        object==MetadataPYRA_4.INDEX ||
168
        object==MetadataPYRA_5.INDEX ||
169
        object==MetadataPDUO_2.INDEX ||
170
        object==MetadataJING_2.INDEX ||
171
        object==MetadataMORP_2.INDEX ||
172
        object==MetadataMORP_3.INDEX ||
173
        object==MetadataMORP_4.INDEX  )
174
      {
175
      mNumColors  = ShapeTetrahedron.NUM_FACES;
176
      mFaceColors = ShapeTetrahedron.FACE_COLORS;
177
      }
178
    else if( object==MetadataDIAM_2.INDEX ||
179
             object==MetadataDIAM_3.INDEX ||
180
             object==MetadataDIAM_4.INDEX ||
181
             object==MetadataTRAJ_3.INDEX ||
182
             object==MetadataTRAJ_4.INDEX ||
183
             object==MetadataPDIA_3.INDEX  )
184
      {
185
      mNumColors  = ShapeOctahedron.NUM_FACES;
186
      mFaceColors = ShapeOctahedron.FACE_COLORS;
187
      }
188
    else if( object==MetadataCRYS_3.INDEX ||
189
             object==MetadataSTAR_3.INDEX ||
190
             object==MetadataPENT_2.INDEX ||
191
             object==MetadataKILO_3.INDEX ||
192
             object==MetadataKILO_5.INDEX ||
193
             object==MetadataMEGA_3.INDEX ||
194
             object==MetadataMEGA_5.INDEX  )
195
      {
196
      mNumColors  = ShapeDodecahedron.NUM_FACES;
197
      mFaceColors = ShapeDodecahedron.FACE_COLORS;
198
      }
199
    else if( object==MetadataBALL_4.INDEX )
200
      {
201
      mNumColors  = ShapeDiamond.NUM_FACES;
202
      mFaceColors = ShapeDiamond.FACE_COLORS;
203
      }
204
    else if( object==MetadataICOS_2.INDEX )
205
      {
206
      mNumColors  = ShapeIcosahedron.NUM_FACES;
207
      mFaceColors = ShapeIcosahedron.FACE_COLORS;
208
      }
209
    else if( object==MetadataDIN4_3.INDEX )
210
      {
211
      mNumColors  = 4;
212
      mFaceColors = new int[] { ShapeColors.COLOR_YELLOW, ShapeColors.COLOR_RED, ShapeColors.COLOR_BLUE, ShapeColors.COLOR_WHITE};
213
      mColorMode  = MODE_DINO_4;
214
      }
215
    else
216
      {
217
      mNumColors  = ShapeHexahedron.NUM_FACES;
218
      mFaceColors = ShapeHexahedron.FACE_COLORS;
219
      }
220
    }
221

    
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223

    
224
  private void setupBitmaps()
225
    {
226
    final int SIZE = (int)mBitmapSize;
227
    final float R = SIZE*0.15f;
228
    final float M = SIZE*0.08f;
229

    
230
    mBitmap = new Bitmap[mNumColors];
231

    
232
    Paint paint = new Paint();
233
    paint.setColor(0xff008800);
234
    paint.setStyle(Paint.Style.FILL);
235

    
236
    paint.setAntiAlias(true);
237
    paint.setTextAlign(Paint.Align.CENTER);
238
    paint.setStyle(Paint.Style.FILL);
239

    
240
    for(int i=0; i<mNumColors; i++)
241
      {
242
      mBitmap[i] = Bitmap.createBitmap(SIZE, SIZE, Bitmap.Config.ARGB_8888);
243
      Canvas canvas = new Canvas(mBitmap[i]);
244

    
245
      paint.setColor(0xff000000);
246
      canvas.drawRect(0, 0, SIZE, SIZE, paint);
247

    
248
      paint.setColor(mFaceColors[i]);
249
      canvas.drawRoundRect( M, M, SIZE-M, SIZE-M, R, R, paint);
250
      }
251
    }
252

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

    
255
  private int translateColor(int color)
256
    {
257
    if( mColorMode==MODE_DINO_4 )
258
      {
259
      int realColor = mFaceColors[color];
260
      int[] hexColors = ShapeHexahedron.FACE_COLORS;
261

    
262
      for(int i=0; i<6; i++)
263
        if( hexColors[i]==realColor ) return i;
264
      }
265

    
266
    return color;
267
    }
268

    
269
///////////////////////////////////////////////////////////////////////////////////////////////////
270

    
271
  private void setupColorButtons(final SolverActivity act, final float width)
272
    {
273
    mColorButton = new ImageButton[mNumColors];
274
    int padding = (int)(width*SolverActivity.PADDING);
275
    int margin  = (int)(width*SolverActivity.SMALL_MARGIN);
276

    
277
    for(int i=0; i<mNumColors; i++)
278
      {
279
      final int ii = i;
280
      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.MATCH_PARENT, 1.0f);
281
      params.topMargin    = margin;
282
      params.bottomMargin = margin;
283
      params.leftMargin   = margin;
284
      params.rightMargin  = margin;
285

    
286
      mColorButton[i] = new ImageButton(act);
287
      mColorButton[i].setLayoutParams(params);
288
      mColorButton[i].setPadding(padding,0,padding,0);
289
      mColorButton[i].setImageBitmap(mBitmap[i]);
290

    
291
      mColorButton[i].setOnClickListener( new View.OnClickListener()
292
        {
293
        @Override
294
        public void onClick(View view)
295
          {
296
          mCurrentColor = translateColor(ii);
297
          mCurrentButton= ii;
298
          markButton(act);
299
          }
300
        });
301
      }
302
    }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

    
306
  private void setupResetButton(final SolverActivity act)
307
    {
308
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
309
    mResetButton = new TransparentImageButton(act, R.drawable.ui_reset, params);
310

    
311
    mResetButton.setOnClickListener( new View.OnClickListener()
312
      {
313
      @Override
314
      public void onClick(View v)
315
        {
316
        ObjectControl control = act.getControl();
317
        control.resetTextureMapsEffect(RESET_DURATION);
318
        }
319
      });
320
    }
321

    
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323

    
324
  private void setupSolveButton(final SolverActivity act)
325
    {
326
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
327
    mSolveButton = new TransparentImageButton(act,R.drawable.ui_solve,params);
328

    
329
    mSolveButton.setOnClickListener( new View.OnClickListener()
330
      {
331
      @Override
332
      public void onClick(View v)
333
        {
334
        if( !mSolving )
335
          {
336
          mSolving = true;
337
          TwistyObject object = act.getObject();
338
          SolverMain solver = new SolverMain( act.getInterface(), act.getResources(), object );
339
          solver.start();
340
          }
341
        }
342
      });
343
    }
344

    
345
///////////////////////////////////////////////////////////////////////////////////////////////////
346

    
347
  private void setupBackButton(final SolverActivity act)
348
    {
349
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
350
    mBackButton = new TransparentImageButton(act,R.drawable.ui_back,params);
351

    
352
    mBackButton.setOnClickListener( new View.OnClickListener()
353
      {
354
      @Override
355
      public void onClick(View v)
356
        {
357
        ObjectControl control = act.getControl();
358
        control.resetAllTextureMaps();
359
        ScreenList.goBack(act);
360
        }
361
      });
362
    }
363

    
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365

    
366
  private void markButton(SolverActivity act)
367
    {
368
    if( mCurrentButton>=mNumColors )
369
      {
370
      mCurrentButton = 0;
371
      mCurrentColor = translateColor(0);
372
      }
373

    
374
    for(int b=0; b<mNumColors; b++)
375
      {
376
      Drawable d = mColorButton[b].getBackground();
377

    
378
      if( b==mCurrentButton )
379
        {
380
        d.setColorFilter(ContextCompat.getColor(act,R.color.red), PorterDuff.Mode.MULTIPLY);
381
        }
382
      else
383
        {
384
        d.clearColorFilter();
385
        }
386
      }
387
    }
388

    
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390

    
391
  public void savePreferences(SharedPreferences.Editor editor)
392
    {
393
    editor.putInt("stateSolver_color" , mCurrentColor );
394
    editor.putInt("stateSolver_button", mCurrentButton);
395
    }
396

    
397
///////////////////////////////////////////////////////////////////////////////////////////////////
398

    
399
  public void restorePreferences(SharedPreferences preferences)
400
    {
401
    mCurrentColor = preferences.getInt("stateSolver_color" , 0);
402
    mCurrentButton= preferences.getInt("stateSolver_button", 0);
403
    }
404

    
405
///////////////////////////////////////////////////////////////////////////////////////////////////
406

    
407
  public int getCurrentColor()
408
    {
409
    return mCurrentColor;
410
    }
411

    
412
///////////////////////////////////////////////////////////////////////////////////////////////////
413

    
414
  public void setSolved(final String moves)
415
    {
416
    mSolving = false;
417
    final SolverActivity act = mWeakAct.get();
418

    
419
    if( act!=null )
420
      {
421
      act.runOnUiThread(new Runnable()
422
        {
423
        @Override
424
        public void run()
425
          {
426
          ScreenList.switchScreen(act, ScreenList.SOLU);
427
          ScreenSolution solution = (ScreenSolution) ScreenList.SOLU.getScreenClass();
428
          solution.setupMoves(act, moves);
429
          }
430
        });
431
      }
432
    }
433

    
434
///////////////////////////////////////////////////////////////////////////////////////////////////
435

    
436
  public void setSolved(final int[][] moves)
437
    {
438
    mSolving = false;
439
    final SolverActivity act = mWeakAct.get();
440

    
441
    if( act!=null )
442
      {
443
      act.runOnUiThread(new Runnable()
444
        {
445
        @Override
446
        public void run()
447
          {
448
          ScreenList.switchScreen(act, ScreenList.SOLU);
449
          ScreenSolution solution = (ScreenSolution) ScreenList.SOLU.getScreenClass();
450
          solution.setupMoves(act, moves);
451
          }
452
        });
453
      }
454
    }
455

    
456
///////////////////////////////////////////////////////////////////////////////////////////////////
457

    
458
  public void displayErrorDialog(String message)
459
    {
460
    mSolving = false;
461
    SolverActivity act = mWeakAct.get();
462

    
463
    if( act!=null )
464
      {
465
      RubikDialogSolverError dialog = new RubikDialogSolverError();
466
      Bundle bundle = new Bundle();
467
      bundle.putString("argument", message );
468
      dialog.setArguments(bundle);
469
      dialog.show( act.getSupportFragmentManager(), null);
470
      }
471
    }
472

    
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474

    
475
  public void displayImpossibleDialog(String message)
476
    {
477
    mSolving = false;
478
    SolverActivity act = mWeakAct.get();
479

    
480
    if( act!=null )
481
      {
482
      RubikDialogSolverImpossible dialog = new RubikDialogSolverImpossible();
483
      Bundle bundle = new Bundle();
484
      bundle.putString("argument", message );
485
      dialog.setArguments(bundle);
486
      dialog.show( act.getSupportFragmentManager(), null);
487
      }
488
    }
489
  }
(4-4/8)