Project

General

Profile

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

magiccube / src / main / java / org / distorted / screens / RubikScreenSolver.java @ 379b3273

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 java.lang.ref.WeakReference;
13

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

    
26
import org.distorted.objectlib.main.ObjectControl;
27
import org.distorted.objectlib.main.ObjectSignatures;
28
import org.distorted.objectlib.main.TwistyObject;
29

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

    
44
///////////////////////////////////////////////////////////////////////////////////////////////////
45

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

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

    
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61

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

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

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

    
75
    float width = act.getScreenWidthInPixels();
76
    float heigh = act.getScreenHeightInPixels();
77

    
78
    mWeakAct = new WeakReference<>(act);
79
    mSolving = false;
80

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

    
88
    generateFaceColors(currentObject);
89

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

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

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

    
106
    for(ImageButton button: mColorButton) layoutTop.addView(button);
107

    
108
    // BOT ////////////////////////////
109
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1);
110

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

    
118
    LinearLayout layoutBot = act.findViewById(R.id.lowerBar);
119
    layoutBot.removeAllViews();
120

    
121
    setupResetButton(act);
122
    setupSolveButton(act);
123
    setupBackButton(act);
124

    
125
    layoutL.addView(mResetButton);
126
    layoutM.addView(mSolveButton);
127
    layoutR.addView(mBackButton);
128

    
129
    layoutBot.addView(layoutL);
130
    layoutBot.addView(layoutM);
131
    layoutBot.addView(layoutR);
132
    }
133

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

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

    
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191

    
192
  private void setupBitmaps()
193
    {
194
    final int SIZE = (int)mBitmapSize;
195
    final float R = SIZE*0.15f;
196
    final float M = SIZE*0.08f;
197

    
198
    mBitmap = new Bitmap[mNumColors];
199

    
200
    Paint paint = new Paint();
201
    paint.setColor(0xff008800);
202
    paint.setStyle(Paint.Style.FILL);
203

    
204
    paint.setAntiAlias(true);
205
    paint.setTextAlign(Paint.Align.CENTER);
206
    paint.setStyle(Paint.Style.FILL);
207

    
208
    for(int i=0; i<mNumColors; i++)
209
      {
210
      mBitmap[i] = Bitmap.createBitmap(SIZE, SIZE, Bitmap.Config.ARGB_8888);
211
      Canvas canvas = new Canvas(mBitmap[i]);
212

    
213
      paint.setColor(0xff000000);
214
      canvas.drawRect(0, 0, SIZE, SIZE, paint);
215

    
216
      paint.setColor(mFaceColors[i]);
217
      canvas.drawRoundRect( M, M, SIZE-M, SIZE-M, R, R, paint);
218
      }
219
    }
220

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

    
223
  private void setupColorButtons(final RubikActivity act, final float width)
224
    {
225
    mColorButton = new ImageButton[mNumColors];
226
    int padding = (int)(width*RubikActivity.PADDING);
227
    int margin  = (int)(width*RubikActivity.SMALL_MARGIN);
228

    
229
    for(int i=0; i<mNumColors; i++)
230
      {
231
      final int ii = i;
232
      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.MATCH_PARENT, 1.0f);
233
      params.topMargin    = margin;
234
      params.bottomMargin = margin;
235
      params.leftMargin   = margin;
236
      params.rightMargin  = margin;
237

    
238
      mColorButton[i] = new ImageButton(act);
239
      mColorButton[i].setLayoutParams(params);
240
      mColorButton[i].setPadding(padding,0,padding,0);
241
      mColorButton[i].setImageBitmap(mBitmap[i]);
242

    
243
      mColorButton[i].setOnClickListener( new View.OnClickListener()
244
        {
245
        @Override
246
        public void onClick(View view)
247
          {
248
          mCurrentColor = ii;
249
          markButton(act);
250
          }
251
        });
252
      }
253
    }
254

    
255
///////////////////////////////////////////////////////////////////////////////////////////////////
256

    
257
  private void setupResetButton(final RubikActivity act)
258
    {
259
    int icon = RubikActivity.getDrawable(R.drawable.ui_small_reset,R.drawable.ui_medium_reset, R.drawable.ui_big_reset, R.drawable.ui_huge_reset);
260
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
261
    mResetButton = new TransparentImageButton(act, icon, TransparentImageButton.GRAVITY_MIDDLE, params);
262

    
263
    mResetButton.setOnClickListener( new View.OnClickListener()
264
      {
265
      @Override
266
      public void onClick(View v)
267
        {
268
        ObjectControl control = act.getControl();
269
        control.resetTextureMapsEffect(RESET_DURATION);
270
        }
271
      });
272
    }
273

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

    
276
  private void setupSolveButton(final RubikActivity act)
277
    {
278
    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);
279
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
280
    mSolveButton = new TransparentImageButton(act,icon,TransparentImageButton.GRAVITY_MIDDLE,params);
281

    
282
    mSolveButton.setOnClickListener( new View.OnClickListener()
283
      {
284
      @Override
285
      public void onClick(View v)
286
        {
287
        if( !mSolving )
288
          {
289
          mSolving = true;
290
          TwistyObject object = act.getObject();
291
          SolverMain solver = new SolverMain( act.getResources(), object );
292
          solver.start();
293
          }
294
        }
295
      });
296
    }
297

    
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299

    
300
  private void setupBackButton(final RubikActivity act)
301
    {
302
    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);
303
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT,1.0f);
304
    mBackButton = new TransparentImageButton(act, icon, TransparentImageButton.GRAVITY_MIDDLE, params);
305

    
306
    mBackButton.setOnClickListener( new View.OnClickListener()
307
      {
308
      @Override
309
      public void onClick(View v)
310
        {
311
        ObjectControl control = act.getControl();
312
        control.resetAllTextureMaps();
313
        ScreenList.goBack(act);
314
        }
315
      });
316
    }
317

    
318
///////////////////////////////////////////////////////////////////////////////////////////////////
319

    
320
  private void markButton(RubikActivity act)
321
    {
322
    for(int b=0; b<mNumColors; b++)
323
      {
324
      Drawable d = mColorButton[b].getBackground();
325

    
326
      if( b==mCurrentColor )
327
        {
328
        d.setColorFilter(ContextCompat.getColor(act,R.color.red), PorterDuff.Mode.MULTIPLY);
329
        }
330
      else
331
        {
332
        d.clearColorFilter();
333
        }
334
      }
335
    }
336

    
337
///////////////////////////////////////////////////////////////////////////////////////////////////
338

    
339
  public void savePreferences(SharedPreferences.Editor editor)
340
    {
341
    editor.putInt("stateSolver_color", mCurrentColor);
342
    }
343

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

    
346
  public void restorePreferences(SharedPreferences preferences)
347
    {
348
    mCurrentColor = preferences.getInt("stateSolver_color", 0);
349
    }
350

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

    
353
  public int getCurrentColor()
354
    {
355
    return mCurrentColor;
356
    }
357

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

    
360
  public void setSolved(final String moves)
361
    {
362
    mSolving = false;
363
    final RubikActivity act = mWeakAct.get();
364

    
365
    if( act!=null )
366
      {
367
      act.runOnUiThread(new Runnable()
368
        {
369
        @Override
370
        public void run()
371
          {
372
          ScreenList.switchScreen(act, ScreenList.SOLU);
373
          RubikScreenSolution solution = (RubikScreenSolution) ScreenList.SOLU.getScreenClass();
374
          solution.setupMoves(act, moves);
375
          }
376
        });
377
      }
378
    }
379

    
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381

    
382
  public void setSolved(final int[][] moves)
383
    {
384
    mSolving = false;
385
    final RubikActivity act = mWeakAct.get();
386

    
387
    if( act!=null )
388
      {
389
      act.runOnUiThread(new Runnable()
390
        {
391
        @Override
392
        public void run()
393
          {
394
          ScreenList.switchScreen(act, ScreenList.SOLU);
395
          RubikScreenSolution solution = (RubikScreenSolution) ScreenList.SOLU.getScreenClass();
396
          solution.setupMoves(act, moves);
397
          }
398
        });
399
      }
400
    }
401

    
402
///////////////////////////////////////////////////////////////////////////////////////////////////
403

    
404
  public void displayErrorDialog(String message)
405
    {
406
    mSolving = false;
407
    RubikActivity act = mWeakAct.get();
408

    
409
    if( act!=null )
410
      {
411
      RubikDialogSolverError dialog = new RubikDialogSolverError();
412
      Bundle bundle = new Bundle();
413
      bundle.putString("argument", message );
414
      dialog.setArguments(bundle);
415
      dialog.show( act.getSupportFragmentManager(), null);
416
      }
417
    }
418
  }
(8-8/10)