Project

General

Profile

« Previous | Next » 

Revision 01932078

Added by Leszek Koltunski 10 months ago

Carve out the fourth layer: stickers.

View differences:

src/main/java/org/distorted/objectlib/main/ObjectPreRender.java
133 133

  
134 134
      if( mNewObject!=null )
135 135
        {
136
        mNewObject.setLibInterface(mInterface);
137 136
        mController.setTouchControl(mNewObject);
138 137
        mNewObject.setObjectRatioNow(mScale, mController.getScalingSize() );
139 138

  
src/main/java/org/distorted/objectlib/main/TwistyObject.java
12 12
import java.io.InputStream;
13 13
import java.util.Random;
14 14

  
15
import android.graphics.Bitmap;
16
import android.graphics.Canvas;
17
import android.graphics.Paint;
18

  
19 15
import org.distorted.library.effect.Effect;
20 16
import org.distorted.library.effect.MatrixEffectMove;
21 17
import org.distorted.library.effect.MatrixEffectQuaternion;
22 18
import org.distorted.library.effect.MatrixEffectScale;
23
import org.distorted.library.main.DistortedLibrary;
24 19
import org.distorted.library.main.DistortedNode;
25
import org.distorted.library.main.DistortedTexture;
26 20
import org.distorted.library.message.EffectListener;
27 21
import org.distorted.library.type.Static3D;
28 22
import org.distorted.library.type.Static4D;
29 23

  
30
import org.distorted.objectlib.helpers.FactoryCubit;
31
import org.distorted.objectlib.helpers.FactorySticker;
32
import org.distorted.objectlib.helpers.ObjectLibInterface;
33
import org.distorted.objectlib.helpers.ObjectSticker;
34
import org.distorted.objectlib.helpers.ObjectStickerOverride;
35 24
import org.distorted.objectlib.helpers.OperatingSystemInterface;
36 25
import org.distorted.objectlib.json.JsonReader;
37 26
import org.distorted.objectlib.metadata.Metadata;
......
46 35

  
47 36
///////////////////////////////////////////////////////////////////////////////////////////////////
48 37

  
49
public abstract class TwistyObject extends TwistyObjectSolved
38
public abstract class TwistyObject extends TwistyObjectWithStickers
50 39
{
51
  public static final int COLOR_STROKE   = 0xff000000;
52
  public static final int COLOR_INTERNAL = 0xff000000;
53

  
54
  private static final int DEFAULT_TEXTURE_HEIGHT = 256;
55
  private static final int DEFAULT_TEXTURE_ROWS   = 8;
56

  
57 40
  private static final float MAX_SIZE_CHANGE = 1.35f;
58 41
  private static final float MIN_SIZE_CHANGE = 0.75f;
59 42

  
60
  protected float[][][][] mStickerCoords;
61

  
62
  private int[][] mStickerVariants;
63
  private float[] mStickerScales;
64
  private int mNumTextures, mNumOverrides;
65
  private int mNumStickerTypes;
66 43
  private Static4D mQuat;
67 44
  private float mSize;
68 45
  private Static3D mObjectScale;
69
  private DistortedTexture mTexture;
70 46
  private float mInitScreenRatio;
71 47
  private float mObjectScreenRatio;
72
  private int mNumTexRows, mNumTexCols, mTexHeight;
73 48
  private ObjectScrambler mScrambler;
74 49
  private TouchControl mTouchControl;
75 50
  private DistortedNode mNode;
76
  private ObjectLibInterface mInterface;
77
  private Bitmap mBitmap;
78
  private ObjectSticker[] mStickers;
79 51
  private Metadata mMetadata;
80
  private ObjectStickerOverride[] mStickerOverrides;
81 52
  private boolean mError;
82 53
  private String mErrorString;
83 54
  private TwistyLayerRotations mRotation;
84
  private float mTextureBorderMultiplier, mTextureCornerMultiplier;
85 55

  
86 56
///////////////////////////////////////////////////////////////////////////////////////////////////
87 57

  
......
140 110
  public abstract String[][] getTutorials();
141 111
  public abstract float[] getDist3D();
142 112

  
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114

  
115
  protected void setReader(JsonReader reader) { }
116
  public String getInventor()                 { return mMetadata.getAuthor(); }
117
  public int getYearOfInvention()             { return mMetadata.getYearOfInvention(); }
118
  public float getComplexity()                { return mMetadata.getDifficulty(); }
119
  public String getObjectName()               { return mMetadata.getObjectName(); }
120
  public ObjectSignature getSignature()       { return mMetadata.getSignature(); }
121
  public int getCategory()                    { return mMetadata!=null ? mMetadata.getCategory() : 0; }
122

  
143 123
///////////////////////////////////////////////////////////////////////////////////////////////////
144 124

  
145 125
  private void initialize(int iconMode, Static4D quat, Static3D move, float scale, InitAssets asset, boolean fromJSON)
146 126
    {
147
    super.initialize(iconMode, asset,fromJSON);
127
    super.initialize(iconMode,asset,fromJSON);
148 128

  
149 129
    mQuat = quat;
150 130
    mInitScreenRatio = getScreenRatio();
151 131

  
152
    mTextureBorderMultiplier = 1.0f;
153
    mTextureCornerMultiplier = 1.0f;
154

  
155 132
    int scramblingType = getScrambleType();
156 133
    int[][] edges = getScrambleEdges();
157 134
    int[][] algorithms = getScrambleAlgorithms();
......
169 146
    MatrixEffectQuaternion quatEffect = new MatrixEffectQuaternion(mQuat, CENTER);
170 147
    MatrixEffectMove moveEffect = new MatrixEffectMove(move);
171 148

  
172
    InputStream meshStream = asset!=null ? asset.getMeshStream(): null;
173
    boolean fromDMESH = (meshStream!=null);
174
    setUpTextures(fromDMESH,fromJSON);
175

  
176 149
    mEffects.apply(quatEffect);
177 150
    mEffects.apply(scaleEffect);
178 151
    mEffects.apply(moveEffect);
179 152

  
180
    mNode = new DistortedNode(mTexture,mEffects,mMesh);
153
    mNode = new DistortedNode(mNodeTexture,mEffects,mMesh);
181 154
    }
182 155

  
183 156
///////////////////////////////////////////////////////////////////////////////////////////////////
184
// LATER
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186
// in degrees so that everything can be treated modulo 360
187 157

  
188 158
  public int getGhostAngle()
189 159
    {
......
198 168
    return ImplementedTablebasesList.createPacked(os,shortName);
199 169
    }
200 170

  
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202

  
203
  private void figureOutBitmapDimensions(int numTextures)
204
    {
205
    int maxSize = DistortedLibrary.getMaxTextureSize();
206

  
207
    mTexHeight  = DEFAULT_TEXTURE_HEIGHT;
208

  
209
    while(true)
210
      {
211
      mNumTexCols = DEFAULT_TEXTURE_ROWS;
212
      mNumTexRows = numTextures/mNumTexCols + 1;
213

  
214
      if( mNumTexRows*mTexHeight <= maxSize &&
215
          mNumTexCols*mTexHeight <= maxSize  ) break;
216

  
217
      mTexHeight/=2;
218
      }
219
    }
220

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

  
223
  private void setUpTextures(boolean fromDMESH, boolean fromJSON)
224
    {
225
    mTexture = new DistortedTexture();
226

  
227
    if( fromJSON )
228
      {
229
      mNumStickerTypes = getNumStickerTypes();
230
      }
231
    else
232
      {
233
      FactoryCubit factory = FactoryCubit.getInstance();
234
      mStickerCoords   = factory.getStickerCoords();
235
      mStickerVariants = factory.getStickerVariants();
236
      mStickerScales   = factory.getStickerScales();
237
      adjustStickerCoords();
238
      mNumStickerTypes = (mStickerCoords==null ? 0 : mStickerCoords.length);
239
      }
240

  
241
    mStickerOverrides = getStickerOverrides();
242
    mNumOverrides = mStickerOverrides==null ? 0 : mStickerOverrides.length;
243

  
244
    mNumTextures= mNumFaceColors*mNumStickerTypes + mNumOverrides;
245
    figureOutBitmapDimensions(mNumTextures);
246
    if( mNumTexCols*mNumTexRows < mNumTextures+1 ) mNumTexRows++;
247

  
248
    if( !fromDMESH || shouldResetTextureMaps() ) resetAllTextureMaps();
249
    else overrideCubitFaceColor();
250

  
251
    setTexture();
252
    }
253

  
254 171
///////////////////////////////////////////////////////////////////////////////////////////////////
255 172

  
256 173
  public Metadata getMetadata()
......
258 175
    return mMetadata;
259 176
    }
260 177

  
261
///////////////////////////////////////////////////////////////////////////////////////////////////
262

  
263
  public int getVariantStickerShape(int variant, int face)
264
    {
265
    if( variant <mStickerVariants.length )
266
      {
267
      int[] var = mStickerVariants[variant];
268
      return face>=var.length ? -1 : var[face];
269
      }
270
    return -1;
271
    }
272

  
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274

  
275
  public boolean shouldResetTextureMaps()
276
    {
277
    return false;
278
    }
279

  
280 178
///////////////////////////////////////////////////////////////////////////////////////////////////
281 179

  
282 180
  public int[][] getScrambleAlgorithms()
......
291 189
    return ObjectScrambler.SCRAMBLING_ALGORITHMS;
292 190
    }
293 191

  
294
///////////////////////////////////////////////////////////////////////////////////////////////////
295

  
296
  void setLibInterface(ObjectLibInterface inter)
297
    {
298
    mInterface = inter;
299
    }
300

  
301 192
///////////////////////////////////////////////////////////////////////////////////////////////////
302 193

  
303 194
  synchronized float removeRotation()
......
347 238
    return mRotation.beginRotation(axis,row);
348 239
    }
349 240

  
350
///////////////////////////////////////////////////////////////////////////////////////////////////
351

  
352
  void setTextureMap(int cubit, int face, int color)
353
    {
354
    int variant  = getCubitVariant(cubit);
355
    int shape    = getVariantStickerShape(variant,face);
356
    int texIndex = color<0 || shape<0 ? mNumTextures-mNumOverrides : shape*mNumFaceColors + color;
357
    int row      = (mNumTexRows-1) - texIndex/mNumTexCols;
358
    int col      = texIndex%mNumTexCols;
359

  
360
    final float ratioW = 1.0f/mNumTexCols;
361
    final float ratioH = 1.0f/mNumTexRows;
362
    final Static4D[] maps = new Static4D[1];
363
    maps[0] = new Static4D(col*ratioW, row*ratioH, ratioW, ratioH);
364
    mMesh.setTextureMap(maps, mMaxNumCubitFaces*cubit+face);
365
    }
366

  
367
///////////////////////////////////////////////////////////////////////////////////////////////////
368
// figure out the puzzle face to which (cubit,face) belongs, repaint all (cubit,face) pairs to
369
// the new color.
370

  
371
  void repaintPuzzleFace(int cubit, int face, int newColor)
372
    {
373
    int oldColorIndex = getDefaultCubitFaceColor(cubit,face);
374

  
375
    if( oldColorIndex<0 || oldColorIndex>=mNumFaceColors )
376
      {
377
      System.out.println("TwistyObject.repaintPuzzleFace: index="+oldColorIndex);
378
      return;
379
      }
380

  
381
    int oldColor = mColorTable[oldColorIndex];
382

  
383
    if( oldColor!=newColor )
384
      {
385
      oldColor = mOriginalColorTable[oldColorIndex];
386
      changeColorInTexture(oldColor,newColor);
387
      mColorTable[oldColorIndex] = newColor;
388
      setTexture();
389

  
390
      int numOrig = numberOfDifferentColors(mOriginalColorTable);
391
      int numNow  = numberOfDifferentColors(mColorTable);
392
      mCurrentColorSchemeSubmittable = (numOrig==numNow);
393
      }
394
    }
395

  
396
///////////////////////////////////////////////////////////////////////////////////////////////////
397
// this doesn't have to return the real, displayed color - but the default one (from Shape classes).
398
// The real displayed color can be different because of the sticker color overrides.
399

  
400
  int getDefaultCubitFaceColor(int cubit, int face)
401
    {
402
    int puzzleFace = getPuzzleFace(cubit,face);
403
    if( puzzleFace>=0 ) puzzleFace %= mNumFaceColors;
404
    return puzzleFace;
405
    }
406

  
407
///////////////////////////////////////////////////////////////////////////////////////////////////
408

  
409
  void resetAllTextureMaps()
410
    {
411
    final float ratioW = 1.0f/mNumTexCols;
412
    final float ratioH = 1.0f/mNumTexRows;
413
    int cubColor, stiShape, texIndex, variant, row, col;
414

  
415
    for(int cubit=0; cubit<mNumCubits; cubit++)
416
      {
417
      final Static4D[] maps = new Static4D[mMaxNumCubitFaces];
418
      variant = getCubitVariant(cubit);
419

  
420
      for( int face=0; face<mMaxNumCubitFaces; face++)
421
        {
422
        cubColor = getDefaultCubitFaceColor(cubit,face);
423
        stiShape = getVariantStickerShape(variant,face);
424
        texIndex = cubColor<0 || stiShape<0 ? mNumTextures-mNumOverrides : stiShape*mNumFaceColors + cubColor;
425
        row      = (mNumTexRows-1) - texIndex/mNumTexCols;
426
        col      = texIndex%mNumTexCols;
427

  
428
        maps[face] = new Static4D( col*ratioW, row*ratioH, ratioW, ratioH);
429
        }
430

  
431
      mMesh.setTextureMap(maps, mMaxNumCubitFaces*cubit);
432
      }
433

  
434
    overrideCubitFaceColor();
435
    }
436

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

  
439
  private void overrideCubitFaceColor()
440
    {
441
    final float ratioW = 1.0f/mNumTexCols;
442
    final float ratioH = 1.0f/mNumTexRows;
443

  
444
    for(int i=0; i<mNumOverrides; i++)
445
      {
446
      int[] cubitFaces = mStickerOverrides[i].getCubitFaces();
447
      int length = cubitFaces.length/2;
448
      int color = mNumTextures-mNumOverrides+1+i;
449
      int row   = (mNumTexRows-1) - color/mNumTexCols;
450
      int col   = color%mNumTexCols;
451

  
452
      for(int j=0; j<length; j++)
453
        {
454
        final Static4D[] maps = new Static4D[1];
455
        maps[0] = new Static4D(col*ratioW, row*ratioH, ratioW, ratioH);
456
        int cubit = cubitFaces[2*j];
457
        int face  = cubitFaces[2*j+1];
458
        mMesh.setTextureMap(maps, mMaxNumCubitFaces*cubit+face);
459
        }
460
      }
461
    }
462

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

  
465
  void releaseResources()
466
    {
467
    super.releaseResources();
468

  
469
    mTexture.markForDeletion();
470

  
471
    if( mBitmap!=null )
472
      {
473
      mBitmap.recycle();
474
      mBitmap = null;
475
      }
476
    }
477

  
478
///////////////////////////////////////////////////////////////////////////////////////////////////
479

  
480
  private int numberOfDifferentColors(int[] table)
481
    {
482
    int ret=0;
483
    int len = table.length;
484

  
485
    for(int i=0; i<len; i++)
486
      {
487
      boolean increase = true;
488

  
489
      for(int j=0; j<i; j++)
490
        if( table[j]==table[i] )
491
          {
492
          increase = false;
493
          break;
494
          }
495

  
496
      if( increase ) ret++;
497
      }
498

  
499
    return ret;
500
    }
501

  
502
///////////////////////////////////////////////////////////////////////////////////////////////////
503

  
504
  private void restoreSti(String key, OperatingSystemInterface os)
505
    {
506
    mTextureBorderMultiplier = os.getFloat(key+"_border", 1.0f);
507
    mTextureCornerMultiplier = os.getFloat(key+"_corner", 1.0f);
508
    String colors = os.getString(key+"_colors", null);
509
    boolean different = false;
510

  
511
    if( colors!=null ) different = restoreColors(colors,mColorTable);
512

  
513
    if( different || mTextureBorderMultiplier!=1.0f || mTextureCornerMultiplier!=1.0f )
514
      {
515
      createTexture(mTextureBorderMultiplier,mTextureCornerMultiplier);
516
      setTexture();
517
      int numOrig = numberOfDifferentColors(mOriginalColorTable);
518
      int numNow  = numberOfDifferentColors(mColorTable);
519
      mCurrentColorSchemeSubmittable = (numOrig==numNow);
520
      }
521
    }
522

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

  
525
  synchronized void restorePreferences(OperatingSystemInterface os)
526
    {
527
    String key = getShortName();
528
    super.restorePreferences(key,os);
529
    restoreSti(key,os);
530
    }
531

  
532
///////////////////////////////////////////////////////////////////////////////////////////////////
533

  
534
  synchronized void restoreStickers(OperatingSystemInterface os)
535
    {
536
    String key = getShortName();
537
    restoreSti(key,os);
538
    }
539

  
540
///////////////////////////////////////////////////////////////////////////////////////////////////
541

  
542
  void savePreferences(OperatingSystemInterface os)
543
    {
544
    String key = getShortName();
545
    super.savePreferences(key,os);
546

  
547
    os.putFloat(key+"_border", mTextureBorderMultiplier);
548
    os.putFloat(key+"_corner", mTextureCornerMultiplier);
549
    os.putString(key+"_colors", createColors(mColorTable) );
550
    }
551

  
552
///////////////////////////////////////////////////////////////////////////////////////////////////
553

  
554
  public void removePreferences(OperatingSystemInterface os)
555
    {
556
    String key = getShortName();
557
    super.removePreferences(key,os);
558

  
559
    os.remove(key+"_border");
560
    os.remove(key+"_corner");
561
    os.remove(key+"_colors");
562
    }
563

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

  
566
  private String createColors(int[] table)
567
    {
568
    StringBuilder sb = new StringBuilder();
569
    int len = table!=null ? table.length : 0;
570

  
571
    for(int i=0; i<len; i++)
572
      {
573
      sb.append(table[i]);
574
      sb.append(',');
575
      }
576

  
577
    return sb.toString();
578
    }
579

  
580
///////////////////////////////////////////////////////////////////////////////////////////////////
581

  
582
  private boolean restoreColors(String colors, int[] table)
583
    {
584
    String[] parts = colors.split(",");
585
    int len = parts.length;
586
    boolean ret = false;
587

  
588
    try
589
      {
590
      for(int s=0; s<len; s++)
591
        {
592
        table[s] = Integer.parseInt(parts[s]);
593
        if( table[s]!=mOriginalColorTable[s] ) ret = true;
594
        }
595
      }
596
    catch(NumberFormatException nfe)
597
      {
598
      for(int s=0; s<len; s++) table[s] = mOriginalColorTable[s];
599
      return false;
600
      }
601

  
602
    return ret;
603
    }
604

  
605
///////////////////////////////////////////////////////////////////////////////////////////////////
606

  
607
  private float computeRadiusCorrection(float[][] sticker, int curr, int len)
608
    {
609
    final float A = 0.8f;  // 0<A<1
610

  
611
    int prev = curr>0 ? curr-1 : len-1;
612
    int next = curr<len-1 ? curr+1 : 0;
613

  
614
    float v1x = sticker[prev][0]-sticker[curr][0];
615
    float v1y = sticker[prev][1]-sticker[curr][1];
616
    float v2x = sticker[next][0]-sticker[curr][0];
617
    float v2y = sticker[next][1]-sticker[curr][1];
618

  
619
    float len1= v1x*v1x+v1y*v1y;
620
    float len2= v2x*v2x+v2y*v2y;
621

  
622
    float cos = (v1x*v2x+v1y*v2y) / ( (float)Math.sqrt(len1*len2) );
623

  
624
    return 1-A*cos;
625
    }
626

  
627
///////////////////////////////////////////////////////////////////////////////////////////////////
628
// might be overridden in subclasses which want per-edge radii
629

  
630
  protected float[][][] getStickerRadii()
631
    {
632
    float radius = getStickerRadius();
633
    int numStickers = mStickerCoords.length;
634
    float[][][] ret = new float[numStickers][][];
635

  
636
    for(int s=0; s<numStickers; s++)
637
      {
638
      int numLoops = mStickerCoords[s].length;
639
      ret[s] = new float[numLoops][];
640

  
641
      for(int l=0; l<numLoops; l++)
642
        {
643
        int numVertices = mStickerCoords[s][l].length;
644
        ret[s][l] = new float[numVertices];
645
        for(int v=0; v<numVertices; v++) ret[s][l][v] = radius;
646
        }
647
      }
648

  
649
    return ret;
650
    }
651

  
652
///////////////////////////////////////////////////////////////////////////////////////////////////
653
// might be overridden in subclasses which want per-edge strokes
654

  
655
  protected float[][][] getStickerStrokes()
656
    {
657
    float stroke = getStickerStroke();
658
    int numStickers = mStickerCoords.length;
659
    float[][][] ret = new float[numStickers][][];
660

  
661
    for(int s=0; s<numStickers; s++)
662
      {
663
      int numLoops = mStickerCoords[s].length;
664
      ret[s] = new float[numLoops][];
665

  
666
      for(int l=0; l<numLoops; l++)
667
        {
668
        int numVertices = mStickerCoords[s][l].length;
669
        ret[s][l] = new float[numVertices];
670
        for(int v=0; v<numVertices; v++) ret[s][l][v] = stroke;
671
        }
672
      }
673

  
674
    return ret;
675
    }
676

  
677
///////////////////////////////////////////////////////////////////////////////////////////////////
678

  
679
  public ObjectSticker retSticker(int sticker)
680
    {
681
    if( mStickers==null )
682
      {
683
      float[][][] radii   = getStickerRadii();
684
      float[][][] strokes = getStickerStrokes();
685
      float[][][] angles  = getStickerAngles();
686
      int numStickers = mStickerCoords.length;
687
      mStickers = new ObjectSticker[numStickers];
688

  
689
      for(int s=0; s<numStickers; s++)
690
        {
691
        float scale = mStickerScales.length>s ? mStickerScales[s] : 1.0f;
692
        int numLoops = mStickerCoords[s].length;
693
        float[][] rad = new float[numLoops][];
694
        float[][] str = new float[numLoops][];
695

  
696
        for(int l=0; l<numLoops; l++)
697
          {
698
          int numVerts = mStickerCoords[s][l].length;
699
          rad[l] = new float[numVerts];
700
          str[l] = new float[numVerts];
701
          float[] st = strokes[s][l];
702
          float[] ra = radii[s][l];
703

  
704
          for(int v=0; v<numVerts; v++)
705
            {
706
            rad[l][v] = ra[v] * computeRadiusCorrection(mStickerCoords[s][l],v,numVerts) / scale;
707
            str[l][v] = st[v] / scale;
708
            }
709
          }
710

  
711
        mStickers[s] = new ObjectSticker(mStickerCoords[s], (angles==null ? null : angles[s]) ,rad, str);
712
        }
713
      }
714

  
715
    return mStickers[sticker];
716
    }
717

  
718
///////////////////////////////////////////////////////////////////////////////////////////////////
719
// some objects (currently Kilominx,Ivy,Rex) might want to change the stickers.
720

  
721
  public void adjustStickerCoords()
722
    {
723

  
724
    }
725

  
726
///////////////////////////////////////////////////////////////////////////////////////////////////
727

  
728
  public int getInternalColor()
729
    {
730
    return COLOR_INTERNAL;
731
    }
732

  
733
///////////////////////////////////////////////////////////////////////////////////////////////////
734
// the getFaceColors + final INTERNAL_COLOR in a grid (so that we do not exceed the maximum texture size)
735

  
736
  void createTexture(float border, float corner)
737
    {
738
    Paint paint = new Paint();
739
    Canvas canvas = new Canvas(mBitmap);
740

  
741
    paint.setAntiAlias(true);
742
    paint.setTextAlign(Paint.Align.CENTER);
743
    paint.setStyle(Paint.Style.FILL);
744
    paint.setColor(getInternalColor());
745
    canvas.drawRect(0, 0, mNumTexCols*mTexHeight, mNumTexRows*mTexHeight, paint);
746

  
747
    mTextureBorderMultiplier = border;
748
    mTextureCornerMultiplier = corner;
749

  
750
    int texture = 0;
751
    FactorySticker factory = FactorySticker.getInstance();
752

  
753
    for(int row=0; row<mNumTexRows; row++)
754
      for(int col=0; col<mNumTexCols; col++)
755
        {
756
        if( texture<mNumTextures-mNumOverrides )
757
          {
758
          ObjectSticker sticker = retSticker(texture/mNumFaceColors);
759
          int color = mColorTable[texture%mNumFaceColors];
760
          factory.drawRoundedPolygons( canvas, paint, col*mTexHeight, (mNumTexRows-row)*mTexHeight, color,
761
                                       mTexHeight, sticker,mTextureBorderMultiplier,mTextureCornerMultiplier);
762
          }
763
        else if( texture>mNumTextures-mNumOverrides && texture<=mNumTextures )
764
          {
765
          int color = mStickerOverrides[mNumTextures-texture].getColor();
766
          factory.drawSolidColor(canvas, paint, col*mTexHeight, (mNumTexRows-row)*mTexHeight, color, mTexHeight);
767
          }
768

  
769
        texture++;
770
        }
771
    }
772

  
773
///////////////////////////////////////////////////////////////////////////////////////////////////
774

  
775
  private void changeColorInTexture(int oldColor, int newColor)
776
    {
777
    Paint paint = new Paint();
778
    Canvas canvas = new Canvas(mBitmap);
779
    paint.setAntiAlias(true);
780
    int texture = 0;
781
    FactorySticker factory = FactorySticker.getInstance();
782

  
783
    for(int row=0; row<mNumTexRows; row++)
784
      for(int col=0; col<mNumTexCols; col++)
785
        {
786
        if( texture<mNumTextures-mNumOverrides )
787
          {
788
          int color = mOriginalColorTable[texture%mNumFaceColors];
789

  
790
          if( color==oldColor )
791
            {
792
            ObjectSticker sticker = retSticker(texture/mNumFaceColors);
793
            factory.drawRoundedPolygons( canvas, paint, col*mTexHeight, (mNumTexRows-row)*mTexHeight,
794
                                         newColor, mTexHeight, sticker,mTextureBorderMultiplier,mTextureCornerMultiplier);
795
            }
796
          }
797

  
798
        texture++;
799
        }
800
    }
801

  
802
///////////////////////////////////////////////////////////////////////////////////////////////////
803

  
804
  void setTexture()
805
    {
806
    if( mBitmap==null )
807
      {
808
      mBitmap = Bitmap.createBitmap( mNumTexCols*mTexHeight, mNumTexRows*mTexHeight, Bitmap.Config.ARGB_4444);
809
      createTexture(mTextureBorderMultiplier,mTextureCornerMultiplier);
810
      }
811

  
812
    if( !mTexture.setTextureAlreadyInverted(mBitmap) )
813
      {
814
      int max = DistortedLibrary.getMaxTextureSize();
815
      mInterface.reportProblem("failed to set texture of size "+mBitmap.getWidth()+"x"+mBitmap.getHeight()+" max is "+max, true);
816
      }
817
    }
818

  
819 241
///////////////////////////////////////////////////////////////////////////////////////////////////
820 242

  
821 243
  void setObjectRatioNow(float sc, int nodeSize)
......
898 320
    mEffects.abortById(effectID);
899 321
    }
900 322

  
901
///////////////////////////////////////////////////////////////////////////////////////////////////
902

  
903
  public ObjectStickerOverride[] getStickerOverrides()
904
    {
905
    return null;
906
    }
907

  
908 323
///////////////////////////////////////////////////////////////////////////////////////////////////
909 324

  
910 325
  public boolean getError()
......
921 336

  
922 337
///////////////////////////////////////////////////////////////////////////////////////////////////
923 338
// PUBLIC API
924
///////////////////////////////////////////////////////////////////////////////////////////////////
925

  
926
  public int getCubitFaceStickerIndex(int cubit, int face)
927
    {
928
    Static4D texMap = mMesh.getTextureMap(mMaxNumCubitFaces*cubit + face);
929

  
930
    int x = (int)(texMap.get0()/texMap.get2());
931
    int y = (int)(texMap.get1()/texMap.get3());
932

  
933
    return (mNumTexRows-1-y)*mNumTexCols + x;
934
    }
935

  
936
///////////////////////////////////////////////////////////////////////////////////////////////////
937

  
938
  public Bitmap getStickerBitmap()
939
    {
940
    return mBitmap;
941
    }
942

  
943 339
///////////////////////////////////////////////////////////////////////////////////////////////////
944 340

  
945 341
  public DistortedNode getNode()
......
947 343
    return mNode;
948 344
    }
949 345

  
950
///////////////////////////////////////////////////////////////////////////////////////////////////
951

  
952
  public int getNumStickerTypes()
953
    {
954
    return mNumStickerTypes;
955
    }
956

  
957 346
///////////////////////////////////////////////////////////////////////////////////////////////////
958 347

  
959 348
  public String reportState()
......
1019 408

  
1020 409
    return factor;
1021 410
    }
1022

  
1023
///////////////////////////////////////////////////////////////////////////////////////////////////
1024

  
1025
  protected void setReader(JsonReader reader) { }
1026
  public String getInventor()                 { return mMetadata.getAuthor(); }
1027
  public int getYearOfInvention()             { return mMetadata.getYearOfInvention(); }
1028
  public float getComplexity()                { return mMetadata.getDifficulty(); }
1029
  public String getObjectName()               { return mMetadata.getObjectName(); }
1030
  public ObjectSignature getSignature()       { return mMetadata.getSignature(); }
1031
  public int getCategory()                    { return mMetadata!=null ? mMetadata.getCategory() : 0; }
1032
  public boolean isSubmittable()              { return mCurrentColorSchemeSubmittable; }
1033 411
}
src/main/java/org/distorted/objectlib/main/TwistyObjectWithStickers.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.objectlib.main;
11

  
12
import android.graphics.Bitmap;
13
import android.graphics.Canvas;
14
import android.graphics.Paint;
15

  
16
import org.distorted.library.main.DistortedLibrary;
17
import org.distorted.library.main.DistortedTexture;
18
import org.distorted.library.type.Static4D;
19
import org.distorted.objectlib.helpers.FactoryCubit;
20
import org.distorted.objectlib.helpers.FactorySticker;
21
import org.distorted.objectlib.helpers.ObjectSticker;
22
import org.distorted.objectlib.helpers.ObjectStickerOverride;
23
import org.distorted.objectlib.helpers.OperatingSystemInterface;
24

  
25
import java.io.InputStream;
26

  
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28
// The fourth layer of the PUzzle implementation: stickers.
29

  
30
public abstract class TwistyObjectWithStickers extends TwistyObjectSolved
31
{
32
  public static final int COLOR_STROKE   = 0xff000000;
33
  public static final int COLOR_INTERNAL = 0xff000000;
34

  
35
  private static final int DEFAULT_TEXTURE_HEIGHT = 256;
36
  private static final int DEFAULT_TEXTURE_ROWS   = 8;
37

  
38
  protected float[][][][] mStickerCoords;
39
  protected DistortedTexture mNodeTexture;
40

  
41
  private int[][] mStickerVariants;
42
  private float[] mStickerScales;
43
  private int mNumTextures, mNumOverrides;
44
  private int mNumStickerTypes;
45
  private int mNumTexRows, mNumTexCols, mTexHeight;
46
  private Bitmap mBitmap;
47
  private ObjectSticker[] mStickers;
48
  private ObjectStickerOverride[] mStickerOverrides;
49
  private float mTextureBorderMultiplier, mTextureCornerMultiplier;
50

  
51
///////////////////////////////////////////////////////////////////////////////////////////////////
52

  
53
  public abstract float getStickerRadius();
54
  public abstract float getStickerStroke();
55
  public abstract float[][][] getStickerAngles();
56
  public abstract String getShortName();
57
  public abstract int getFOV();
58

  
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

  
61
  public void adjustStickerCoords()                    { } // some objects (currently Kilominx,Ivy,Rex) want to change the stickers.
62
  public int getInternalColor()                        { return COLOR_INTERNAL; }
63
  public ObjectStickerOverride[] getStickerOverrides() { return null; }
64
  public Bitmap getStickerBitmap()                     { return mBitmap; }
65
  public int getNumStickerTypes()                      { return mNumStickerTypes; }
66
  public boolean isSubmittable()                       { return mCurrentColorSchemeSubmittable; }
67

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

  
70
  void initialize(int iconMode, InitAssets asset, boolean fromJSON)
71
    {
72
    super.initialize(iconMode,asset,fromJSON);
73

  
74
    mTextureBorderMultiplier = 1.0f;
75
    mTextureCornerMultiplier = 1.0f;
76

  
77
    mNodeTexture= new DistortedTexture();
78

  
79
    InputStream meshStream = asset!=null ? asset.getMeshStream(): null;
80
    boolean fromDMESH = (meshStream!=null);
81
    setUpTextures(fromDMESH,fromJSON);
82
    }
83

  
84
///////////////////////////////////////////////////////////////////////////////////////////////////
85
// in degrees so that everything can be treated modulo 360
86

  
87
  private void figureOutBitmapDimensions(int numTextures)
88
    {
89
    int maxSize = DistortedLibrary.getMaxTextureSize();
90

  
91
    mTexHeight  = DEFAULT_TEXTURE_HEIGHT;
92

  
93
    while(true)
94
      {
95
      mNumTexCols = DEFAULT_TEXTURE_ROWS;
96
      mNumTexRows = numTextures/mNumTexCols + 1;
97

  
98
      if( mNumTexRows*mTexHeight <= maxSize &&
99
          mNumTexCols*mTexHeight <= maxSize  ) break;
100

  
101
      mTexHeight/=2;
102
      }
103
    }
104

  
105
///////////////////////////////////////////////////////////////////////////////////////////////////
106

  
107
  private void setUpTextures(boolean fromDMESH, boolean fromJSON)
108
    {
109
    if( fromJSON )
110
      {
111
      mNumStickerTypes = getNumStickerTypes();
112
      }
113
    else
114
      {
115
      FactoryCubit factory = FactoryCubit.getInstance();
116
      mStickerCoords   = factory.getStickerCoords();
117
      mStickerVariants = factory.getStickerVariants();
118
      mStickerScales   = factory.getStickerScales();
119
      adjustStickerCoords();
120
      mNumStickerTypes = (mStickerCoords==null ? 0 : mStickerCoords.length);
121
      }
122

  
123
    mStickerOverrides = getStickerOverrides();
124
    mNumOverrides = mStickerOverrides==null ? 0 : mStickerOverrides.length;
125

  
126
    mNumTextures= mNumFaceColors*mNumStickerTypes + mNumOverrides;
127
    figureOutBitmapDimensions(mNumTextures);
128
    if( mNumTexCols*mNumTexRows < mNumTextures+1 ) mNumTexRows++;
129

  
130
    if( !fromDMESH || shouldResetTextureMaps() ) resetAllTextureMaps();
131
    else overrideCubitFaceColor();
132

  
133
    setTexture();
134
    }
135

  
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

  
138
  public int getVariantStickerShape(int variant, int face)
139
    {
140
    if( variant <mStickerVariants.length )
141
      {
142
      int[] var = mStickerVariants[variant];
143
      return face>=var.length ? -1 : var[face];
144
      }
145
    return -1;
146
    }
147

  
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149

  
150
  public boolean shouldResetTextureMaps()
151
    {
152
    return false;
153
    }
154

  
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156

  
157
  void setTextureMap(int cubit, int face, int color)
158
    {
159
    int variant  = getCubitVariant(cubit);
160
    int shape    = getVariantStickerShape(variant,face);
161
    int texIndex = color<0 || shape<0 ? mNumTextures-mNumOverrides : shape*mNumFaceColors + color;
162
    int row      = (mNumTexRows-1) - texIndex/mNumTexCols;
163
    int col      = texIndex%mNumTexCols;
164

  
165
    final float ratioW = 1.0f/mNumTexCols;
166
    final float ratioH = 1.0f/mNumTexRows;
167
    final Static4D[] maps = new Static4D[1];
168
    maps[0] = new Static4D(col*ratioW, row*ratioH, ratioW, ratioH);
169
    mMesh.setTextureMap(maps, mMaxNumCubitFaces*cubit+face);
170
    }
171

  
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173
// figure out the puzzle face to which (cubit,face) belongs, repaint all (cubit,face) pairs to
174
// the new color.
175

  
176
  void repaintPuzzleFace(int cubit, int face, int newColor)
177
    {
178
    int oldColorIndex = getDefaultCubitFaceColor(cubit,face);
179

  
180
    if( oldColorIndex<0 || oldColorIndex>=mNumFaceColors )
181
      {
182
      System.out.println("TwistyObject.repaintPuzzleFace: index="+oldColorIndex);
183
      return;
184
      }
185

  
186
    int oldColor = mColorTable[oldColorIndex];
187

  
188
    if( oldColor!=newColor )
189
      {
190
      oldColor = mOriginalColorTable[oldColorIndex];
191
      changeColorInTexture(oldColor,newColor);
192
      mColorTable[oldColorIndex] = newColor;
193
      setTexture();
194

  
195
      int numOrig = numberOfDifferentColors(mOriginalColorTable);
196
      int numNow  = numberOfDifferentColors(mColorTable);
197
      mCurrentColorSchemeSubmittable = (numOrig==numNow);
198
      }
199
    }
200

  
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202
// this doesn't have to return the real, displayed color - but the default one (from Shape classes).
203
// The real displayed color can be different because of the sticker color overrides.
204

  
205
  int getDefaultCubitFaceColor(int cubit, int face)
206
    {
207
    int puzzleFace = getPuzzleFace(cubit,face);
208
    if( puzzleFace>=0 ) puzzleFace %= mNumFaceColors;
209
    return puzzleFace;
210
    }
211

  
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213

  
214
  void resetAllTextureMaps()
215
    {
216
    final float ratioW = 1.0f/mNumTexCols;
217
    final float ratioH = 1.0f/mNumTexRows;
218
    int cubColor, stiShape, texIndex, variant, row, col;
219

  
220
    for(int cubit=0; cubit<mNumCubits; cubit++)
221
      {
222
      final Static4D[] maps = new Static4D[mMaxNumCubitFaces];
223
      variant = getCubitVariant(cubit);
224

  
225
      for( int face=0; face<mMaxNumCubitFaces; face++)
226
        {
227
        cubColor = getDefaultCubitFaceColor(cubit,face);
228
        stiShape = getVariantStickerShape(variant,face);
229
        texIndex = cubColor<0 || stiShape<0 ? mNumTextures-mNumOverrides : stiShape*mNumFaceColors + cubColor;
230
        row      = (mNumTexRows-1) - texIndex/mNumTexCols;
231
        col      = texIndex%mNumTexCols;
232

  
233
        maps[face] = new Static4D( col*ratioW, row*ratioH, ratioW, ratioH);
234
        }
235

  
236
      mMesh.setTextureMap(maps, mMaxNumCubitFaces*cubit);
237
      }
238

  
239
    overrideCubitFaceColor();
240
    }
241

  
242
///////////////////////////////////////////////////////////////////////////////////////////////////
243

  
244
  private void overrideCubitFaceColor()
245
    {
246
    final float ratioW = 1.0f/mNumTexCols;
247
    final float ratioH = 1.0f/mNumTexRows;
248

  
249
    for(int i=0; i<mNumOverrides; i++)
250
      {
251
      int[] cubitFaces = mStickerOverrides[i].getCubitFaces();
252
      int length = cubitFaces.length/2;
253
      int color = mNumTextures-mNumOverrides+1+i;
254
      int row   = (mNumTexRows-1) - color/mNumTexCols;
255
      int col   = color%mNumTexCols;
256

  
257
      for(int j=0; j<length; j++)
258
        {
259
        final Static4D[] maps = new Static4D[1];
260
        maps[0] = new Static4D(col*ratioW, row*ratioH, ratioW, ratioH);
261
        int cubit = cubitFaces[2*j];
262
        int face  = cubitFaces[2*j+1];
263
        mMesh.setTextureMap(maps, mMaxNumCubitFaces*cubit+face);
264
        }
265
      }
266
    }
267

  
268
///////////////////////////////////////////////////////////////////////////////////////////////////
269

  
270
  private int numberOfDifferentColors(int[] table)
271
    {
272
    int ret=0;
273
    int len = table.length;
274

  
275
    for(int i=0; i<len; i++)
276
      {
277
      boolean increase = true;
278

  
279
      for(int j=0; j<i; j++)
280
        if( table[j]==table[i] )
281
          {
282
          increase = false;
283
          break;
284
          }
285

  
286
      if( increase ) ret++;
287
      }
288

  
289
    return ret;
290
    }
291

  
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293

  
294
  private void restoreSti(String key, OperatingSystemInterface os)
295
    {
296
    mTextureBorderMultiplier = os.getFloat(key+"_border", 1.0f);
297
    mTextureCornerMultiplier = os.getFloat(key+"_corner", 1.0f);
298
    String colors = os.getString(key+"_colors", null);
299
    boolean different = false;
300

  
301
    if( colors!=null ) different = restoreColors(colors,mColorTable);
302

  
303
    if( different || mTextureBorderMultiplier!=1.0f || mTextureCornerMultiplier!=1.0f )
304
      {
305
      createTexture(mTextureBorderMultiplier,mTextureCornerMultiplier);
306
      setTexture();
307
      int numOrig = numberOfDifferentColors(mOriginalColorTable);
308
      int numNow  = numberOfDifferentColors(mColorTable);
309
      mCurrentColorSchemeSubmittable = (numOrig==numNow);
310
      }
311
    }
312

  
313
///////////////////////////////////////////////////////////////////////////////////////////////////
314

  
315
  synchronized void restorePreferences(OperatingSystemInterface os)
316
    {
317
    String key = getShortName();
318
    super.restorePreferences(key,os);
319
    restoreSti(key,os);
320
    }
321

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

  
324
  synchronized void restoreStickers(OperatingSystemInterface os)
325
    {
326
    String key = getShortName();
327
    restoreSti(key,os);
328
    }
329

  
330
///////////////////////////////////////////////////////////////////////////////////////////////////
331

  
332
  void savePreferences(OperatingSystemInterface os)
333
    {
334
    String key = getShortName();
335
    super.savePreferences(key,os);
336

  
337
    os.putFloat(key+"_border", mTextureBorderMultiplier);
338
    os.putFloat(key+"_corner", mTextureCornerMultiplier);
339
    os.putString(key+"_colors", createColors(mColorTable) );
340
    }
341

  
342
///////////////////////////////////////////////////////////////////////////////////////////////////
343

  
344
  public void removePreferences(OperatingSystemInterface os)
345
    {
346
    String key = getShortName();
347
    super.removePreferences(key,os);
348

  
349
    os.remove(key+"_border");
350
    os.remove(key+"_corner");
351
    os.remove(key+"_colors");
352
    }
353

  
354
///////////////////////////////////////////////////////////////////////////////////////////////////
355

  
356
  private String createColors(int[] table)
357
    {
358
    StringBuilder sb = new StringBuilder();
359
    int len = table!=null ? table.length : 0;
360

  
361
    for(int i=0; i<len; i++)
362
      {
363
      sb.append(table[i]);
364
      sb.append(',');
365
      }
366

  
367
    return sb.toString();
368
    }
369

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

  
372
  private boolean restoreColors(String colors, int[] table)
373
    {
374
    String[] parts = colors.split(",");
375
    int len = parts.length;
376
    boolean ret = false;
377

  
378
    try
379
      {
380
      for(int s=0; s<len; s++)
381
        {
382
        table[s] = Integer.parseInt(parts[s]);
383
        if( table[s]!=mOriginalColorTable[s] ) ret = true;
384
        }
385
      }
386
    catch(NumberFormatException nfe)
387
      {
388
      for(int s=0; s<len; s++) table[s] = mOriginalColorTable[s];
389
      return false;
390
      }
391

  
392
    return ret;
393
    }
394

  
395
///////////////////////////////////////////////////////////////////////////////////////////////////
396

  
397
  private float computeRadiusCorrection(float[][] sticker, int curr, int len)
398
    {
399
    final float A = 0.8f;  // 0<A<1
400

  
401
    int prev = curr>0 ? curr-1 : len-1;
402
    int next = curr<len-1 ? curr+1 : 0;
403

  
404
    float v1x = sticker[prev][0]-sticker[curr][0];
405
    float v1y = sticker[prev][1]-sticker[curr][1];
406
    float v2x = sticker[next][0]-sticker[curr][0];
407
    float v2y = sticker[next][1]-sticker[curr][1];
408

  
409
    float len1= v1x*v1x+v1y*v1y;
410
    float len2= v2x*v2x+v2y*v2y;
411

  
412
    float cos = (v1x*v2x+v1y*v2y) / ( (float)Math.sqrt(len1*len2) );
413

  
414
    return 1-A*cos;
415
    }
416

  
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418
// might be overridden in subclasses which want per-edge radii
419

  
420
  protected float[][][] getStickerRadii()
421
    {
422
    float radius = getStickerRadius();
423
    int numStickers = mStickerCoords.length;
424
    float[][][] ret = new float[numStickers][][];
425

  
426
    for(int s=0; s<numStickers; s++)
427
      {
428
      int numLoops = mStickerCoords[s].length;
429
      ret[s] = new float[numLoops][];
430

  
431
      for(int l=0; l<numLoops; l++)
432
        {
433
        int numVertices = mStickerCoords[s][l].length;
434
        ret[s][l] = new float[numVertices];
435
        for(int v=0; v<numVertices; v++) ret[s][l][v] = radius;
436
        }
437
      }
438

  
439
    return ret;
440
    }
441

  
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443
// might be overridden in subclasses which want per-edge strokes
444

  
445
  protected float[][][] getStickerStrokes()
446
    {
447
    float stroke = getStickerStroke();
448
    int numStickers = mStickerCoords.length;
449
    float[][][] ret = new float[numStickers][][];
450

  
451
    for(int s=0; s<numStickers; s++)
452
      {
453
      int numLoops = mStickerCoords[s].length;
454
      ret[s] = new float[numLoops][];
455

  
456
      for(int l=0; l<numLoops; l++)
457
        {
458
        int numVertices = mStickerCoords[s][l].length;
459
        ret[s][l] = new float[numVertices];
460
        for(int v=0; v<numVertices; v++) ret[s][l][v] = stroke;
461
        }
462
      }
463

  
464
    return ret;
465
    }
466

  
467
///////////////////////////////////////////////////////////////////////////////////////////////////
468

  
469
  public ObjectSticker retSticker(int sticker)
470
    {
471
    if( mStickers==null )
472
      {
473
      float[][][] radii   = getStickerRadii();
474
      float[][][] strokes = getStickerStrokes();
475
      float[][][] angles  = getStickerAngles();
476
      int numStickers = mStickerCoords.length;
477
      mStickers = new ObjectSticker[numStickers];
478

  
479
      for(int s=0; s<numStickers; s++)
480
        {
481
        float scale = mStickerScales.length>s ? mStickerScales[s] : 1.0f;
482
        int numLoops = mStickerCoords[s].length;
483
        float[][] rad = new float[numLoops][];
484
        float[][] str = new float[numLoops][];
485

  
486
        for(int l=0; l<numLoops; l++)
487
          {
488
          int numVerts = mStickerCoords[s][l].length;
489
          rad[l] = new float[numVerts];
490
          str[l] = new float[numVerts];
491
          float[] st = strokes[s][l];
492
          float[] ra = radii[s][l];
493

  
494
          for(int v=0; v<numVerts; v++)
495
            {
496
            rad[l][v] = ra[v] * computeRadiusCorrection(mStickerCoords[s][l],v,numVerts) / scale;
497
            str[l][v] = st[v] / scale;
498
            }
499
          }
500

  
501
        mStickers[s] = new ObjectSticker(mStickerCoords[s], (angles==null ? null : angles[s]) ,rad, str);
502
        }
503
      }
504

  
505
    return mStickers[sticker];
506
    }
507

  
508
///////////////////////////////////////////////////////////////////////////////////////////////////
509
// the getFaceColors + final INTERNAL_COLOR in a grid (so that we do not exceed the maximum texture size)
510

  
511
  void createTexture(float border, float corner)
512
    {
513
    Paint paint = new Paint();
514
    Canvas canvas = new Canvas(mBitmap);
515

  
516
    paint.setAntiAlias(true);
517
    paint.setTextAlign(Paint.Align.CENTER);
518
    paint.setStyle(Paint.Style.FILL);
519
    paint.setColor(getInternalColor());
520
    canvas.drawRect(0, 0, mNumTexCols*mTexHeight, mNumTexRows*mTexHeight, paint);
521

  
522
    mTextureBorderMultiplier = border;
523
    mTextureCornerMultiplier = corner;
524

  
525
    int texture = 0;
526
    FactorySticker factory = FactorySticker.getInstance();
527

  
528
    for(int row=0; row<mNumTexRows; row++)
529
      for(int col=0; col<mNumTexCols; col++)
530
        {
531
        if( texture<mNumTextures-mNumOverrides )
532
          {
533
          ObjectSticker sticker = retSticker(texture/mNumFaceColors);
534
          int color = mColorTable[texture%mNumFaceColors];
535
          factory.drawRoundedPolygons( canvas, paint, col*mTexHeight, (mNumTexRows-row)*mTexHeight, color,
536
                                       mTexHeight, sticker,mTextureBorderMultiplier,mTextureCornerMultiplier);
537
          }
538
        else if( texture>mNumTextures-mNumOverrides && texture<=mNumTextures )
539
          {
540
          int color = mStickerOverrides[mNumTextures-texture].getColor();
541
          factory.drawSolidColor(canvas, paint, col*mTexHeight, (mNumTexRows-row)*mTexHeight, color, mTexHeight);
542
          }
543

  
544
        texture++;
545
        }
546
    }
547

  
548
///////////////////////////////////////////////////////////////////////////////////////////////////
549

  
550
  private void changeColorInTexture(int oldColor, int newColor)
551
    {
552
    Paint paint = new Paint();
553
    Canvas canvas = new Canvas(mBitmap);
554
    paint.setAntiAlias(true);
555
    int texture = 0;
556
    FactorySticker factory = FactorySticker.getInstance();
557

  
558
    for(int row=0; row<mNumTexRows; row++)
559
      for(int col=0; col<mNumTexCols; col++)
560
        {
561
        if( texture<mNumTextures-mNumOverrides )
562
          {
563
          int color = mOriginalColorTable[texture%mNumFaceColors];
564

  
565
          if( color==oldColor )
566
            {
567
            ObjectSticker sticker = retSticker(texture/mNumFaceColors);
568
            factory.drawRoundedPolygons( canvas, paint, col*mTexHeight, (mNumTexRows-row)*mTexHeight,
569
                                         newColor, mTexHeight, sticker,mTextureBorderMultiplier,mTextureCornerMultiplier);
570
            }
571
          }
572

  
573
        texture++;
574
        }
575
    }
576

  
577
///////////////////////////////////////////////////////////////////////////////////////////////////
578

  
579
  void setTexture()
580
    {
581
    if( mBitmap==null )
582
      {
583
      mBitmap = Bitmap.createBitmap( mNumTexCols*mTexHeight, mNumTexRows*mTexHeight, Bitmap.Config.ARGB_4444);
584
      createTexture(mTextureBorderMultiplier,mTextureCornerMultiplier);
585
      }
586

  
587
    if( !mNodeTexture.setTextureAlreadyInverted(mBitmap) )
588
      {
589
      int max = DistortedLibrary.getMaxTextureSize();
590
      System.out.println("failed to set texture of size "+mBitmap.getWidth()+"x"+mBitmap.getHeight()+" max is "+max);
591
      }
592
    }
593

  
594
///////////////////////////////////////////////////////////////////////////////////////////////////
595

  
596
  public int getCubitFaceStickerIndex(int cubit, int face)
597
    {
598
    Static4D texMap = mMesh.getTextureMap(mMaxNumCubitFaces*cubit + face);
599

  
600
    int x = (int)(texMap.get0()/texMap.get2());
601
    int y = (int)(texMap.get1()/texMap.get3());
602

  
603
    return (mNumTexRows-1-y)*mNumTexCols + x;
604
    }
605
}

Also available in: Unified diff