Project

General

Profile

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

magiccube / src / main / java / org / distorted / screens / RubikScreenSolver.java @ 8145d8b8

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 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.screens;
11

    
12
import static org.distorted.objectlib.main.TwistyObject.*;
13

    
14
import java.lang.ref.WeakReference;
15

    
16
import android.content.SharedPreferences;
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 androidx.core.content.ContextCompat;
24
import android.view.View;
25
import android.widget.ImageButton;
26
import android.widget.LinearLayout;
27

    
28
import org.distorted.objectlib.main.ObjectControl;
29
import org.distorted.objectlib.main.ObjectSignatures;
30
import org.distorted.objectlib.main.TwistyObject;
31

    
32
import org.distorted.dialogs.RubikDialogSolverError;
33
import org.distorted.helpers.TransparentImageButton;
34
import org.distorted.main.R;
35
import org.distorted.main.RubikActivity;
36
import org.distorted.objectlib.shape.ShapeDiamond;
37
import org.distorted.objectlib.shape.ShapeDodecahedron;
38
import org.distorted.objectlib.shape.ShapeHexahedron;
39
import org.distorted.objectlib.shape.ShapeIcosahedron;
40
import org.distorted.objectlib.shape.ShapeOctahedron;
41
import org.distorted.objectlib.shape.ShapeTetrahedron;
42
import org.distorted.objects.RubikObjectList;
43
import org.distorted.solvers.ImplementedSolversList;
44
import org.distorted.solvers.SolverMain;
45

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

    
48
public class RubikScreenSolver extends RubikScreenAbstract
49
  {
50
  private static final int RESET_DURATION = 1000;
51

    
52
  private static Bitmap[] mBitmap;
53
  private ImageButton[] mColorButton;
54
  private TransparentImageButton mResetButton,mBackButton, mSolveButton;
55
  private boolean mSolving;
56
  private int mCurrentColor;
57
  private int[] mFaceColors;
58
  private int mNumColors;
59
  private float mBitmapSize;
60
  private WeakReference<RubikActivity> mWeakAct;
61

    
62
///////////////////////////////////////////////////////////////////////////////////////////////////
63

    
64
  void leaveScreen(RubikActivity act)
65
    {
66
    ObjectControl control = act.getControl();
67
    control.unsetLock();
68
    }
69

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

    
72
  void enterScreen(final RubikActivity act)
73
    {
74
    ObjectControl control = act.getControl();
75
    control.setLock(false);
76

    
77
    float width = act.getScreenWidthInPixels();
78
    float heigh = act.getScreenHeightInPixels();
79

    
80
    mWeakAct = new WeakReference<>(act);
81
    mSolving = false;
82

    
83
    int solverIndex= act.getSolverIndex();
84
    ImplementedSolversList currentSolver = ImplementedSolversList.getSolver(solverIndex);
85
    int currentObject = currentSolver.getObject();
86
    act.changeIfDifferent(currentObject,control);
87
    control.solveOnly();
88
    RubikObjectList.setCurrObject(currentObject);
89

    
90
    generateFaceColors(currentObject);
91

    
92
    final float BUTTON_RATIO = 0.75f;
93
    int sizeV = (int)(heigh*RubikActivity.RATIO_BAR*BUTTON_RATIO);
94
    int sizeH = (int)((width/mNumColors)*BUTTON_RATIO);
95
    mBitmapSize = Math.min(sizeV,sizeH);
96

    
97
    // TOP ////////////////////////////
98
    LinearLayout layoutTop = act.findViewById(R.id.upperBar);
99
    layoutTop.removeAllViews();
100

    
101
    if( mNumColors>0 )
102
      {
103
      setupBitmaps();
104
      setupColorButtons(act,width);
105
      markButton(act);
106
      }
107

    
108
    for(ImageButton button: mColorButton) layoutTop.addView(button);
109

    
110
    // BOT ////////////////////////////
111
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1);
112

    
113
    LinearLayout layoutL = new LinearLayout(act);
114
    layoutL.setLayoutParams(params);
115
    LinearLayout layoutM = new LinearLayout(act);
116
    layoutM.setLayoutParams(params);
117
    LinearLayout layoutR = new LinearLayout(act);
118
    layoutR.setLayoutParams(params);
119

    
120
    LinearLayout layoutBot = act.findViewById(R.id.lowerBar);
121
    layoutBot.removeAllViews();
122

    
123
    setupResetButton(act);
124
    setupSolveButton(act);
125
    setupBackButton(act);
126

    
127
    layoutL.addView(mResetButton);
128
    layoutM.addView(mSolveButton);
129
    layoutR.addView(mBackButton);
130

    
131
    layoutBot.addView(layoutL);
132
    layoutBot.addView(layoutM);
133
    layoutBot.addView(layoutR);
134
    }
135

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

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

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

    
199
  private void setupBitmaps()
200
    {
201
    final int SIZE = (int)mBitmapSize;
202
    final float R = SIZE*0.15f;
203
    final float M = SIZE*0.08f;
204

    
205
    mBitmap = new Bitmap[mNumColors];
206

    
207
    Paint paint = new Paint();
208
    paint.setColor(0xff008800);
209
    paint.setStyle(Paint.Style.FILL);
210

    
211
    paint.setAntiAlias(true);
212
    paint.setTextAlign(Paint.Align.CENTER);
213
    paint.setStyle(Paint.Style.FILL);
214

    
215
    for(int i=0; i<mNumColors; i++)
216
      {
217
      mBitmap[i] = Bitmap.createBitmap(SIZE, SIZE, Bitmap.Config.ARGB_8888);
218
      Canvas canvas = new Canvas(mBitmap[i]);
219

    
220
      paint.setColor(0xff000000);
221
      canvas.drawRect(0, 0, SIZE, SIZE, paint);
222

    
223
      paint.setColor(mFaceColors[i]);
224
      canvas.drawRoundRect( M, M, SIZE-M, SIZE-M, R, R, paint);
225
      }
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  private void setupColorButtons(final RubikActivity act, final float width)
231
    {
232
    mColorButton = new ImageButton[mNumColors];
233
    int padding = (int)(width*RubikActivity.PADDING);
234
    int margin  = (int)(width*RubikActivity.SMALL_MARGIN);
235

    
236
    for(int i=0; i<mNumColors; i++)
237
      {
238
      final int ii = i;
239
      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.MATCH_PARENT, 1.0f);
240
      params.topMargin    = margin;
241
      params.bottomMargin = margin;
242
      params.leftMargin   = margin;
243
      params.rightMargin  = margin;
244

    
245
      mColorButton[i] = new ImageButton(act);
246
      mColorButton[i].setLayoutParams(params);
247
      mColorButton[i].setPadding(padding,0,padding,0);
248
      mColorButton[i].setImageBitmap(mBitmap[i]);
249

    
250
      mColorButton[i].setOnClickListener( new View.OnClickListener()
251
        {
252
        @Override
253
        public void onClick(View view)
254
          {
255
          mCurrentColor = ii;
256
          markButton(act);
257
          }
258
        });
259
      }
260
    }
261

    
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263

    
264
  private void setupResetButton(final RubikActivity act)
265
    {
266
    int icon = RubikActivity.getDrawable(R.drawable.ui_small_reset,R.drawable.ui_medium_reset, R.drawable.ui_big_reset, R.drawable.ui_huge_reset);
267
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
268
    mResetButton = new TransparentImageButton(act, icon, TransparentImageButton.GRAVITY_MIDDLE, params);
269

    
270
    mResetButton.setOnClickListener( new View.OnClickListener()
271
      {
272
      @Override
273
      public void onClick(View v)
274
        {
275
        ObjectControl control = act.getControl();
276
        control.resetTextureMapsEffect(RESET_DURATION);
277
        }
278
      });
279
    }
280

    
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282

    
283
  private void setupSolveButton(final RubikActivity act)
284
    {
285
    final int icon = RubikActivity.getDrawable(R.drawable.ui_small_solve,R.drawable.ui_medium_solve, R.drawable.ui_big_solve, R.drawable.ui_huge_solve);
286
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
287
    mSolveButton = new TransparentImageButton(act,icon,TransparentImageButton.GRAVITY_MIDDLE,params);
288

    
289
    mSolveButton.setOnClickListener( new View.OnClickListener()
290
      {
291
      @Override
292
      public void onClick(View v)
293
        {
294
        if( !mSolving )
295
          {
296
          mSolving = true;
297
          TwistyObject object = act.getObject();
298
          SolverMain solver = new SolverMain( act.getResources(), object );
299
          solver.start();
300
          }
301
        }
302
      });
303
    }
304

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

    
307
  private void setupBackButton(final RubikActivity act)
308
    {
309
    final int icon = RubikActivity.getDrawable(R.drawable.ui_small_back,R.drawable.ui_medium_back, R.drawable.ui_big_back, R.drawable.ui_huge_back);
310
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
311
    mBackButton = new TransparentImageButton(act, icon, TransparentImageButton.GRAVITY_MIDDLE, params);
312

    
313
    mBackButton.setOnClickListener( new View.OnClickListener()
314
      {
315
      @Override
316
      public void onClick(View v)
317
        {
318
        ObjectControl control = act.getControl();
319
        control.resetAllTextureMaps();
320
        ScreenList.goBack(act);
321
        }
322
      });
323
    }
324

    
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326

    
327
  private void markButton(RubikActivity act)
328
    {
329
    for(int b=0; b<mNumColors; b++)
330
      {
331
      Drawable d = mColorButton[b].getBackground();
332

    
333
      if( b==mCurrentColor )
334
        {
335
        d.setColorFilter(ContextCompat.getColor(act,R.color.red), PorterDuff.Mode.MULTIPLY);
336
        }
337
      else
338
        {
339
        d.clearColorFilter();
340
        }
341
      }
342
    }
343

    
344
///////////////////////////////////////////////////////////////////////////////////////////////////
345

    
346
  public void savePreferences(SharedPreferences.Editor editor)
347
    {
348
    editor.putInt("stateSolver_color", mCurrentColor);
349
    }
350

    
351
///////////////////////////////////////////////////////////////////////////////////////////////////
352

    
353
  public void restorePreferences(SharedPreferences preferences)
354
    {
355
    mCurrentColor = preferences.getInt("stateSolver_color", 0);
356
    }
357

    
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359

    
360
  public int getCurrentColor()
361
    {
362
    return mCurrentColor;
363
    }
364

    
365
///////////////////////////////////////////////////////////////////////////////////////////////////
366

    
367
  public void setSolved(final String moves)
368
    {
369
    mSolving = false;
370
    final RubikActivity act = mWeakAct.get();
371

    
372
    if( act!=null )
373
      {
374
      act.runOnUiThread(new Runnable()
375
        {
376
        @Override
377
        public void run()
378
          {
379
          ScreenList.switchScreen(act, ScreenList.SOLU);
380
          RubikScreenSolution solution = (RubikScreenSolution) ScreenList.SOLU.getScreenClass();
381
          solution.setupMoves(act, moves);
382
          }
383
        });
384
      }
385
    }
386

    
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388

    
389
  public void setSolved(final int[][] moves)
390
    {
391
    mSolving = false;
392
    final RubikActivity act = mWeakAct.get();
393

    
394
    if( act!=null )
395
      {
396
      act.runOnUiThread(new Runnable()
397
        {
398
        @Override
399
        public void run()
400
          {
401
          ScreenList.switchScreen(act, ScreenList.SOLU);
402
          RubikScreenSolution solution = (RubikScreenSolution) ScreenList.SOLU.getScreenClass();
403
          solution.setupMoves(act, moves);
404
          }
405
        });
406
      }
407
    }
408

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

    
411
  public void displayErrorDialog(String message)
412
    {
413
    mSolving = false;
414
    RubikActivity act = mWeakAct.get();
415

    
416
    if( act!=null )
417
      {
418
      RubikDialogSolverError dialog = new RubikDialogSolverError();
419
      Bundle bundle = new Bundle();
420
      bundle.putString("argument", message );
421
      dialog.setArguments(bundle);
422
      dialog.show( act.getSupportFragmentManager(), null);
423
      }
424
    }
425
  }
(8-8/10)