Project

General

Profile

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

magiccube / src / main / java / org / distorted / solverui / ScreenSolver.java @ 4c6cbfa2

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.main.TwistyObject.COLOR_BLUE;
13
import static org.distorted.objectlib.main.TwistyObject.COLOR_RED;
14
import static org.distorted.objectlib.main.TwistyObject.COLOR_WHITE;
15
import static org.distorted.objectlib.main.TwistyObject.COLOR_YELLOW;
16

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

    
28
import androidx.core.content.ContextCompat;
29

    
30
import org.distorted.dialogs.RubikDialogSolverError;
31
import org.distorted.dialogs.RubikDialogSolverImpossible;
32
import org.distorted.helpers.TransparentImageButton;
33
import org.distorted.main.MainActivity;
34
import org.distorted.main.R;
35
import org.distorted.objectlib.main.ObjectControl;
36
import org.distorted.objectlib.main.TwistyObject;
37
import org.distorted.objectlib.shape.ShapeDiamond;
38
import org.distorted.objectlib.shape.ShapeDodecahedron;
39
import org.distorted.objectlib.shape.ShapeHexahedron;
40
import org.distorted.objectlib.shape.ShapeIcosahedron;
41
import org.distorted.objectlib.shape.ShapeOctahedron;
42
import org.distorted.objectlib.shape.ShapeTetrahedron;
43
import org.distorted.objectlib.signature.ObjectConstants;
44
import org.distorted.solvers.ImplementedSolversList;
45
import org.distorted.solvers.SolverMain;
46

    
47
import java.lang.ref.WeakReference;
48

    
49
///////////////////////////////////////////////////////////////////////////////////////////////////
50

    
51
public class ScreenSolver extends ScreenAbstract
52
  {
53
  private static final int RESET_DURATION = 1000;
54
  private static final int MODE_NORMAL = 0;
55
  private static final int MODE_DINO_4 = 1;
56

    
57
  private static Bitmap[] mBitmap;
58
  private ImageButton[] mColorButton;
59
  private TransparentImageButton mResetButton,mBackButton, mSolveButton;
60
  private boolean mSolving;
61
  private int mCurrentColor, mCurrentButton;
62
  private int[] mFaceColors;
63
  private int mColorMode;
64
  private int mNumColors;
65
  private float mBitmapSize;
66
  private WeakReference<SolverActivity> mWeakAct;
67

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

    
70
  void leaveScreen(SolverActivity act)
71
    {
72
    ObjectControl control = act.getControl();
73
    control.unsetLock();
74
    }
75

    
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77

    
78
  void enterScreen(final SolverActivity act)
79
    {
80
    ObjectControl control = act.getControl();
81
    control.setLock(false);
82

    
83
    float width = act.getScreenWidthInPixels();
84
    float heigh = act.getScreenHeightInPixels();
85

    
86
    mWeakAct = new WeakReference<>(act);
87
    mSolving = false;
88

    
89
    int solverIndex= act.getSolverOrdinal();
90
    ImplementedSolversList currentSolver = ImplementedSolversList.getSolver(solverIndex);
91
    int currentObject = currentSolver.getObject();
92
    control.solveOnly();
93
    generateFaceColors(currentObject);
94

    
95
    final float BUTTON_RATIO = 0.75f;
96
    int sizeV = (int)(heigh*MainActivity.RATIO_BAR*BUTTON_RATIO);
97
    int sizeH = (int)((width/mNumColors)*BUTTON_RATIO);
98
    mBitmapSize = Math.min(sizeV,sizeH);
99

    
100
    // TOP ////////////////////////////
101
    LinearLayout layoutTop = act.findViewById(R.id.upperBar);
102
    layoutTop.removeAllViews();
103

    
104
    if( mNumColors>0 )
105
      {
106
      setupBitmaps();
107
      setupColorButtons(act,width);
108
      markButton(act);
109
      }
110

    
111
    for(ImageButton button: mColorButton) layoutTop.addView(button);
112

    
113
    // BOT ////////////////////////////
114
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1);
115

    
116
    LinearLayout layoutL = new LinearLayout(act);
117
    layoutL.setLayoutParams(params);
118
    LinearLayout layoutM = new LinearLayout(act);
119
    layoutM.setLayoutParams(params);
120
    LinearLayout layoutR = new LinearLayout(act);
121
    layoutR.setLayoutParams(params);
122

    
123
    LinearLayout layoutBot = act.findViewById(R.id.lowerBar);
124
    layoutBot.removeAllViews();
125

    
126
    setupResetButton(act);
127
    setupSolveButton(act);
128
    setupBackButton(act);
129

    
130
    layoutL.addView(mResetButton);
131
    layoutM.addView(mSolveButton);
132
    layoutR.addView(mBackButton);
133

    
134
    layoutBot.addView(layoutL);
135
    layoutBot.addView(layoutM);
136
    layoutBot.addView(layoutR);
137
    }
138

    
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140
// This doesn't quite work in many cases, but in case of the solvers that will pop up in foreseeable
141
// future it should be ok.
142

    
143
  public void generateFaceColors(int object)
144
    {
145
    mColorMode = MODE_NORMAL;
146

    
147
    if( object== ObjectConstants.PYRA_3 ||
148
        object== ObjectConstants.PYRA_4 ||
149
        object== ObjectConstants.PYRA_5 ||
150
        object== ObjectConstants.PDUO_2 ||
151
        object== ObjectConstants.JING_2 ||
152
        object== ObjectConstants.MORP_2 ||
153
        object== ObjectConstants.MORP_3 ||
154
        object== ObjectConstants.MORP_4  )
155
      {
156
      mNumColors  = ShapeTetrahedron.NUM_FACES;
157
      mFaceColors = ShapeTetrahedron.FACE_COLORS;
158
      }
159
    else if( object== ObjectConstants.DIAM_2 ||
160
             object== ObjectConstants.DIAM_3 ||
161
             object== ObjectConstants.DIAM_4 ||
162
             object== ObjectConstants.TRAJ_3 ||
163
             object== ObjectConstants.TRAJ_4 ||
164
             object== ObjectConstants.PDIA_3  )
165
      {
166
      mNumColors  = ShapeOctahedron.NUM_FACES;
167
      mFaceColors = ShapeOctahedron.FACE_COLORS;
168
      }
169
    else if( object== ObjectConstants.CRYS_3 ||
170
             object== ObjectConstants.STAR_3 ||
171
             object== ObjectConstants.PENT_2 ||
172
             object== ObjectConstants.KILO_3 ||
173
             object== ObjectConstants.KILO_5 ||
174
             object== ObjectConstants.MEGA_3 ||
175
             object== ObjectConstants.MEGA_5  )
176
      {
177
      mNumColors  = ShapeDodecahedron.NUM_FACES;
178
      mFaceColors = ShapeDodecahedron.FACE_COLORS;
179
      }
180
    else if( object== ObjectConstants.BALL_4 )
181
      {
182
      mNumColors  = ShapeDiamond.NUM_FACES;
183
      mFaceColors = ShapeDiamond.FACE_COLORS;
184
      }
185
    else if( object== ObjectConstants.ICOS_2 )
186
      {
187
      mNumColors  = ShapeIcosahedron.NUM_FACES;
188
      mFaceColors = ShapeIcosahedron.FACE_COLORS;
189
      }
190
    else if( object== ObjectConstants.DIN4_3 )
191
      {
192
      mNumColors  = 4;
193
      mFaceColors = new int[] { COLOR_YELLOW, COLOR_RED, COLOR_BLUE, COLOR_WHITE };
194
      mColorMode  = MODE_DINO_4;
195
      }
196
    else
197
      {
198
      mNumColors  = ShapeHexahedron.NUM_FACES;
199
      mFaceColors = ShapeHexahedron.FACE_COLORS;
200
      }
201
    }
202

    
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204

    
205
  private void setupBitmaps()
206
    {
207
    final int SIZE = (int)mBitmapSize;
208
    final float R = SIZE*0.15f;
209
    final float M = SIZE*0.08f;
210

    
211
    mBitmap = new Bitmap[mNumColors];
212

    
213
    Paint paint = new Paint();
214
    paint.setColor(0xff008800);
215
    paint.setStyle(Paint.Style.FILL);
216

    
217
    paint.setAntiAlias(true);
218
    paint.setTextAlign(Paint.Align.CENTER);
219
    paint.setStyle(Paint.Style.FILL);
220

    
221
    for(int i=0; i<mNumColors; i++)
222
      {
223
      mBitmap[i] = Bitmap.createBitmap(SIZE, SIZE, Bitmap.Config.ARGB_8888);
224
      Canvas canvas = new Canvas(mBitmap[i]);
225

    
226
      paint.setColor(0xff000000);
227
      canvas.drawRect(0, 0, SIZE, SIZE, paint);
228

    
229
      paint.setColor(mFaceColors[i]);
230
      canvas.drawRoundRect( M, M, SIZE-M, SIZE-M, R, R, paint);
231
      }
232
    }
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235

    
236
  private int translateColor(int color)
237
    {
238
    if( mColorMode==MODE_DINO_4 )
239
      {
240
      int realColor = mFaceColors[color];
241
      int[] hexColors = ShapeHexahedron.FACE_COLORS;
242

    
243
      for(int i=0; i<6; i++)
244
        if( hexColors[i]==realColor ) return i;
245
      }
246

    
247
    return color;
248
    }
249

    
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

    
252
  private void setupColorButtons(final SolverActivity act, final float width)
253
    {
254
    mColorButton = new ImageButton[mNumColors];
255
    int padding = (int)(width*SolverActivity.PADDING);
256
    int margin  = (int)(width*SolverActivity.SMALL_MARGIN);
257

    
258
    for(int i=0; i<mNumColors; i++)
259
      {
260
      final int ii = i;
261
      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.MATCH_PARENT, 1.0f);
262
      params.topMargin    = margin;
263
      params.bottomMargin = margin;
264
      params.leftMargin   = margin;
265
      params.rightMargin  = margin;
266

    
267
      mColorButton[i] = new ImageButton(act);
268
      mColorButton[i].setLayoutParams(params);
269
      mColorButton[i].setPadding(padding,0,padding,0);
270
      mColorButton[i].setImageBitmap(mBitmap[i]);
271

    
272
      mColorButton[i].setOnClickListener( new View.OnClickListener()
273
        {
274
        @Override
275
        public void onClick(View view)
276
          {
277
          mCurrentColor = translateColor(ii);
278
          mCurrentButton= ii;
279
          markButton(act);
280
          }
281
        });
282
      }
283
    }
284

    
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286

    
287
  private void setupResetButton(final SolverActivity act)
288
    {
289
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
290
    mResetButton = new TransparentImageButton(act, R.drawable.ui_reset, params);
291

    
292
    mResetButton.setOnClickListener( new View.OnClickListener()
293
      {
294
      @Override
295
      public void onClick(View v)
296
        {
297
        ObjectControl control = act.getControl();
298
        control.resetTextureMapsEffect(RESET_DURATION);
299
        }
300
      });
301
    }
302

    
303
///////////////////////////////////////////////////////////////////////////////////////////////////
304

    
305
  private void setupSolveButton(final SolverActivity act)
306
    {
307
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
308
    mSolveButton = new TransparentImageButton(act,R.drawable.ui_solve,params);
309

    
310
    mSolveButton.setOnClickListener( new View.OnClickListener()
311
      {
312
      @Override
313
      public void onClick(View v)
314
        {
315
        if( !mSolving )
316
          {
317
          mSolving = true;
318
          TwistyObject object = act.getObject();
319
          SolverMain solver = new SolverMain( act.getInterface(), act.getResources(), object );
320
          solver.start();
321
          }
322
        }
323
      });
324
    }
325

    
326
///////////////////////////////////////////////////////////////////////////////////////////////////
327

    
328
  private void setupBackButton(final SolverActivity act)
329
    {
330
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
331
    mBackButton = new TransparentImageButton(act,R.drawable.ui_back,params);
332

    
333
    mBackButton.setOnClickListener( new View.OnClickListener()
334
      {
335
      @Override
336
      public void onClick(View v)
337
        {
338
        ObjectControl control = act.getControl();
339
        control.resetAllTextureMaps();
340
        ScreenList.goBack(act);
341
        }
342
      });
343
    }
344

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

    
347
  private void markButton(SolverActivity act)
348
    {
349
    if( mCurrentButton>=mNumColors )
350
      {
351
      mCurrentButton = 0;
352
      mCurrentColor = translateColor(0);
353
      }
354

    
355
    for(int b=0; b<mNumColors; b++)
356
      {
357
      Drawable d = mColorButton[b].getBackground();
358

    
359
      if( b==mCurrentButton )
360
        {
361
        d.setColorFilter(ContextCompat.getColor(act,R.color.red), PorterDuff.Mode.MULTIPLY);
362
        }
363
      else
364
        {
365
        d.clearColorFilter();
366
        }
367
      }
368
    }
369

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

    
372
  public void savePreferences(SharedPreferences.Editor editor)
373
    {
374
    editor.putInt("stateSolver_color" , mCurrentColor );
375
    editor.putInt("stateSolver_button", mCurrentButton);
376
    }
377

    
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379

    
380
  public void restorePreferences(SharedPreferences preferences)
381
    {
382
    mCurrentColor = preferences.getInt("stateSolver_color" , 0);
383
    mCurrentButton= preferences.getInt("stateSolver_button", 0);
384
    }
385

    
386
///////////////////////////////////////////////////////////////////////////////////////////////////
387

    
388
  public int getCurrentColor()
389
    {
390
    return mCurrentColor;
391
    }
392

    
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394

    
395
  public void setSolved(final String moves)
396
    {
397
    mSolving = false;
398
    final SolverActivity act = mWeakAct.get();
399

    
400
    if( act!=null )
401
      {
402
      act.runOnUiThread(new Runnable()
403
        {
404
        @Override
405
        public void run()
406
          {
407
          ScreenList.switchScreen(act, ScreenList.SOLU);
408
          ScreenSolution solution = (ScreenSolution) ScreenList.SOLU.getScreenClass();
409
          solution.setupMoves(act, moves);
410
          }
411
        });
412
      }
413
    }
414

    
415
///////////////////////////////////////////////////////////////////////////////////////////////////
416

    
417
  public void setSolved(final int[][] moves)
418
    {
419
    mSolving = false;
420
    final SolverActivity act = mWeakAct.get();
421

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

    
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438

    
439
  public void displayErrorDialog(String message)
440
    {
441
    mSolving = false;
442
    SolverActivity act = mWeakAct.get();
443

    
444
    if( act!=null )
445
      {
446
      RubikDialogSolverError dialog = new RubikDialogSolverError();
447
      Bundle bundle = new Bundle();
448
      bundle.putString("argument", message );
449
      dialog.setArguments(bundle);
450
      dialog.show( act.getSupportFragmentManager(), null);
451
      }
452
    }
453

    
454
///////////////////////////////////////////////////////////////////////////////////////////////////
455

    
456
  public void displayImpossibleDialog(String message)
457
    {
458
    mSolving = false;
459
    SolverActivity act = mWeakAct.get();
460

    
461
    if( act!=null )
462
      {
463
      RubikDialogSolverImpossible dialog = new RubikDialogSolverImpossible();
464
      Bundle bundle = new Bundle();
465
      bundle.putString("argument", message );
466
      dialog.setArguments(bundle);
467
      dialog.show( act.getSupportFragmentManager(), null);
468
      }
469
    }
470
  }
(4-4/8)