Project

General

Profile

Download (20.9 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / json / JsonWriter.java @ 4c87f159

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
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.json;
11

    
12
import java.io.BufferedWriter;
13
import java.io.FileOutputStream;
14
import java.io.IOException;
15
import java.io.OutputStreamWriter;
16
import java.nio.charset.StandardCharsets;
17

    
18
import org.distorted.objectlib.helpers.ObjectFaceShape;
19
import org.distorted.objectlib.helpers.ObjectSignature;
20
import org.distorted.objectlib.helpers.ObjectStickerOverride;
21
import org.json.JSONArray;
22
import org.json.JSONException;
23
import org.json.JSONObject;
24

    
25
import org.distorted.library.type.Static3D;
26
import org.distorted.library.type.Static4D;
27

    
28
import org.distorted.objectlib.helpers.ObjectShape;
29
import org.distorted.objectlib.helpers.ObjectSticker;
30
import org.distorted.objectlib.scrambling.ScrambleState;
31
import org.distorted.objectlib.main.TwistyObject;
32

    
33
///////////////////////////////////////////////////////////////////////////////////////////////////
34

    
35
public class JsonWriter
36
{
37
  public static final int VERSION_OBJECT_MAJOR = 4;
38
  public static final int VERSION_OBJECT_MINOR = 0;
39
  public static final int VERSION_EXTRAS_MAJOR = 1;
40
  public static final int VERSION_EXTRAS_MINOR = 0;
41

    
42
  private static JsonWriter mThis;
43
  private static int mNumCubitFaces;
44

    
45
///////////////////////////////////////////////////////////////////////////////////////////////////
46

    
47
  private JsonWriter()
48
    {
49

    
50
    }
51

    
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53

    
54
  private JSONArray generateCubits(TwistyObject object) throws JSONException
55
    {
56
    JSONArray array = new JSONArray();
57

    
58
    int[] numLayers     = object.getNumLayers();
59
    float[][] positions = object.getCubitPositions(numLayers);
60
    int numCubits       = positions.length;
61

    
62
    for(int c=0; c<numCubits; c++)
63
      {
64
      JSONObject cubit = new JSONObject();
65
      Static4D rotQuat = object.getCubitQuats(c,numLayers);
66
      int variant      = object.getCubitVariant(c,numLayers);
67
      int type         = object.getCubitType(c);
68
      float[] offset   = object.getCubitOffset(c);
69

    
70
      JSONArray pos = new JSONArray();
71
      int numPos = positions[c].length;
72
      for(int j=0; j<numPos; j++) pos.put(positions[c][j]);
73
      cubit.put("centers", pos);
74
      cubit.put("qx", rotQuat.get0() );
75
      cubit.put("qy", rotQuat.get1() );
76
      cubit.put("qz", rotQuat.get2() );
77
      cubit.put("qw", rotQuat.get3() );
78
      cubit.put("variant", variant );
79
      cubit.put("type", type);
80

    
81
      if( offset!=null )
82
        {
83
        cubit.put("offsetX", offset[0]);
84
        cubit.put("offsetY", offset[1]);
85
        cubit.put("offsetZ", offset[2]);
86
        }
87

    
88
      JSONArray colors = new JSONArray();
89

    
90
      for(int f=0; f<mNumCubitFaces; f++)
91
        {
92
        int cubColor = object.getCubitFaceMap(c,f);
93
        colors.put(cubColor);
94
        }
95
      cubit.put("colors",colors);
96

    
97
      array.put(cubit);
98
      }
99

    
100
    return array;
101
    }
102

    
103
///////////////////////////////////////////////////////////////////////////////////////////////////
104

    
105
  private JSONArray generateCorners(float[][] corners) throws JSONException
106
    {
107
    JSONArray array = new JSONArray();
108

    
109
    for(float[] c : corners)
110
      {
111
      JSONObject corner = new JSONObject();
112
      corner.put("strength", c[0]);
113
      corner.put("radius"  , c[1]);
114
      array.put(corner);
115
      }
116

    
117
    return array;
118
    }
119

    
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121

    
122
  private JSONArray generateCenters(float[][] centers) throws JSONException
123
    {
124
    JSONArray array = new JSONArray();
125

    
126
    for(float[] c : centers)
127
      {
128
      JSONObject center = new JSONObject();
129
      center.put("x", c[0]);
130
      center.put("y", c[1]);
131
      center.put("z", c[2]);
132
      array.put(center);
133
      }
134

    
135
    return array;
136
    }
137

    
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139

    
140
  private JSONArray generateBands(float[][] bands) throws JSONException
141
    {
142
    JSONArray array = new JSONArray();
143

    
144
    for (float[] b : bands)
145
      {
146
      JSONObject band = new JSONObject();
147
      band.put("height"          , b[0]);
148
      band.put("angle"           , b[1]);
149
      band.put("distanceToCenter", b[2]);
150
      band.put("distanceToFlat"  , b[3]);
151
      band.put("numOfBands"      , b[4]);
152
      band.put("extraI"          , b[5]);
153
      band.put("extraJ"          , b[6]);
154
      array.put(band);
155
      }
156

    
157
    return array;
158
    }
159

    
160
///////////////////////////////////////////////////////////////////////////////////////////////////
161

    
162
  private JSONArray generateFaces(TwistyObject object, int[][] vertIndices, int[] bandIndices, int[] faceOuter, int cubit, int[] numLayers) throws JSONException
163
    {
164
    JSONArray array = new JSONArray();
165
    int numFaces = vertIndices.length;
166
    int variant = object.getCubitVariant(cubit,numLayers);
167

    
168
    for(int i=0; i<numFaces; i++)
169
      {
170
      JSONObject face = new JSONObject();
171
      face.put("bandIndex", bandIndices[i]);
172

    
173
      int sticker = object.getVariantFaceColor(variant,i);
174
      face.put("sticker", sticker);
175
      face.put("isOuter", faceOuter[i]);
176

    
177
      JSONArray vertArr = new JSONArray();
178
      int numV = vertIndices[i].length;
179
      for(int j=0; j<numV; j++) vertArr.put(vertIndices[i][j]);
180
      face.put("vertexIndices",vertArr);
181

    
182
      array.put(face);
183
      }
184

    
185
    return array;
186
    }
187

    
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

    
190
  private JSONArray generateVertices(float[][] vertices, int[] cornerIndices, int[] centerIndices) throws JSONException
191
    {
192
    JSONArray array = new JSONArray();
193
    int numVertices = vertices.length;
194

    
195
    for(int j=0; j<numVertices; j++)
196
      {
197
      JSONObject vert = new JSONObject();
198
      vert.put("x", vertices[j][0]);
199
      vert.put("y", vertices[j][1]);
200
      vert.put("z", vertices[j][2]);
201
      vert.put("cornerIndex", cornerIndices[j]);
202
      vert.put("centerIndex", centerIndices[j]);
203
      array.put(vert);
204
      }
205

    
206
    return array;
207
    }
208

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

    
211
  private JSONObject generateConvexity(float[] convexity) throws JSONException
212
    {
213
    JSONObject object = new JSONObject();
214
    object.put("x", convexity[0]);
215
    object.put("y", convexity[1]);
216
    object.put("z", convexity[2]);
217
    return object;
218
    }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221

    
222
  private int findCubitWithVariant(TwistyObject object, int variant, int numCubits, int[] numLayers)
223
    {
224
    for(int i=0; i<numCubits; i++)
225
      {
226
      if( object.getCubitVariant(i,numLayers)==variant ) return i;
227
      }
228

    
229
    return -1;
230
    }
231

    
232
///////////////////////////////////////////////////////////////////////////////////////////////////
233

    
234
  private JSONArray generateShapes(TwistyObject object) throws JSONException
235
    {
236
    JSONArray shapes = new JSONArray();
237

    
238
    int[] numLayers = object.getNumLayers();
239
    int numVariants = object.getNumCubitVariants(numLayers);
240
    float[][] positions = object.getCubitPositions(numLayers);
241
    int[][] faceOuter   = object.getVariantFaceIsOuter();
242
    int numCubits = positions.length;
243
    mNumCubitFaces = 0;
244

    
245
    for(int i=0; i<numVariants; i++)
246
      {
247
      JSONObject shapeObj = new JSONObject();
248

    
249
      ObjectShape shape = object.getObjectShape(i);
250
      ObjectFaceShape face = object.getObjectFaceShape(i);
251

    
252
      float[] convexity  = face.getConvexityCenter();
253
      float[][] vertices = shape.getVertices();
254
      int[][] vertIndices= shape.getVertIndices();
255
      float[][] bands    = face.getBands();
256
      int[] bandIndices  = face.getBandIndices();
257
      float[][] corners  = face.getCorners();
258
      int[] cornerIndices= face.getCornerIndices();
259
      float[][] centers  = face.getCenters();
260
      int[] centerIndices= face.getCenterIndices();
261

    
262
      int num = vertIndices.length;
263
      if( num>mNumCubitFaces ) mNumCubitFaces=num;
264

    
265
      int cubit = findCubitWithVariant(object,i,numCubits,numLayers);
266

    
267
      if( convexity!=null )
268
        {
269
        JSONObject convObj = generateConvexity(convexity);
270
        shapeObj.put("convexity", convObj);
271
        }
272

    
273
      JSONArray verticesArr = generateVertices(vertices,cornerIndices,centerIndices);
274
      shapeObj.put("vertices", verticesArr);
275
      JSONArray facesArr = generateFaces(object,vertIndices,bandIndices,faceOuter[i],cubit,numLayers);
276
      shapeObj.put("faces", facesArr);
277
      JSONArray bandsArr = generateBands(bands);
278
      shapeObj.put("bands", bandsArr);
279

    
280
      if( corners!=null )
281
        {
282
        JSONArray cornerArr = generateCorners(corners);
283
        shapeObj.put("cornerPush", cornerArr);
284
        }
285

    
286
      if( centers!=null )
287
        {
288
        JSONArray centerArr = generateCenters(centers);
289
        shapeObj.put("centerPush", centerArr);
290
        }
291

    
292
      shapes.put(shapeObj);
293
      }
294

    
295
    return shapes;
296
    }
297

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

    
300
  private JSONArray generateStickers(TwistyObject object) throws JSONException
301
    {
302
    JSONArray stickers = new JSONArray();
303

    
304
    int numStickers = object.getNumStickerTypes();
305

    
306
    for(int i=0; i<numStickers; i++)
307
      {
308
      JSONObject stickerObj = new JSONObject();
309
      JSONArray  vertexArray= new JSONArray();
310

    
311
      ObjectSticker sticker = object.retSticker(i);
312

    
313
      float[] coords     = sticker.getCoords();
314
      float[] curvatures = sticker.getCurvature();
315
      float[] radii      = sticker.getRadii();
316
      float   stroke     = sticker.getStroke();
317

    
318
      stickerObj.put("stroke", stroke);
319
      int numVertices = radii.length;
320

    
321
      for(int j=0; j<numVertices; j++)
322
        {
323
        JSONObject vertex = new JSONObject();
324
        vertex.put("x", coords[2*j  ]);
325
        vertex.put("y", coords[2*j+1]);
326
        vertex.put("angle", curvatures==null ? 0 : curvatures[j]);
327
        vertex.put("radius",radii[j]);
328
        vertexArray.put(vertex);
329
        }
330
      stickerObj.put("vertices", vertexArray);
331
      stickers.put(stickerObj);
332
      }
333

    
334
    return stickers;
335
    }
336

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

    
339
  private JSONArray generateOverrides(TwistyObject object) throws JSONException
340
    {
341
    ObjectStickerOverride[] overrides = object.getStickerOverrides();
342

    
343
    if( overrides!=null )
344
      {
345
      JSONArray overrideArray = new JSONArray();
346

    
347
      for (ObjectStickerOverride objectStickerOverride : overrides)
348
        {
349
        JSONObject override = new JSONObject();
350
        int[] cubfac = objectStickerOverride.getCubitFaces();
351
        int color    = objectStickerOverride.getColor();
352
        JSONArray cubfacArray = new JSONArray();
353
        for (int cf : cubfac) cubfacArray.put(cf);
354

    
355
        override.put("cubitfaces", cubfacArray);
356
        override.put("color", color);
357

    
358
        overrideArray.put(override);
359
        }
360

    
361
      return overrideArray;
362
      }
363

    
364
    return null;
365
    }
366

    
367
///////////////////////////////////////////////////////////////////////////////////////////////////
368

    
369
  private JSONObject generateMesh(TwistyObject object) throws JSONException
370
    {
371
    JSONObject mesh = new JSONObject();
372

    
373
    JSONArray shapes   = generateShapes(object);  // do this before cubits so we calculate numCubitFaces
374
    JSONArray cubits   = generateCubits(object);
375
    JSONArray stickers = generateStickers(object);
376

    
377
    mesh.put("shapes"  , shapes);
378
    mesh.put("cubits"  , cubits);
379
    mesh.put("stickers", stickers);
380

    
381
    JSONArray overrides = generateOverrides(object);
382
    if( overrides!=null ) mesh.put("overrides", overrides);
383

    
384
    return mesh;
385
    }
386

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

    
389
  private JSONObject generateMetadata(TwistyObject object, int numScramble) throws JSONException
390
    {
391
    JSONObject metadata = new JSONObject();
392

    
393
    metadata.put("longname"   , object.getObjectName() );
394
    metadata.put("inventor"   , object.getInventor());
395
    metadata.put("year"       , object.getYearOfInvention());
396
    metadata.put("complexity" , object.getComplexity());
397
    metadata.put("size"       , object.getSize() );
398
    metadata.put("scrambles"  , numScramble );
399
    metadata.put("shortname"  , object.getShortName() );
400
    metadata.put("resetmaps"  , object.shouldResetTextureMaps() );
401
    metadata.put("num_faces"  , object.getNumFaces() );
402

    
403
    ObjectSignature signature = object.getSignature();
404

    
405
    metadata.put("signature1" , signature.getLong1() );
406
    metadata.put("signature2" , signature.getLong2() );
407
    metadata.put("signature3" , signature.getLong3() );
408

    
409
    return metadata;
410
    }
411

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

    
414
  private JSONArray generateQuats(TwistyObject object) throws JSONException
415
    {
416
    JSONArray quatsArray = new JSONArray();
417
    Static4D[] quats = object.getQuats();
418

    
419
    for(Static4D quat : quats)
420
      {
421
      JSONObject q = new JSONObject();
422
      q.put("x",quat.get0());
423
      q.put("y",quat.get1());
424
      q.put("z",quat.get2());
425
      q.put("w",quat.get3());
426
      quatsArray.put(q);
427
      }
428

    
429
    return quatsArray;
430
    }
431

    
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433

    
434
  private JSONArray generateAxis(TwistyObject object) throws JSONException
435
    {
436
    JSONArray axis = new JSONArray();
437

    
438
    Static3D[] rotAxis = object.getRotationAxis();
439
    int numAxis = rotAxis.length;
440
    int[][] basicAngle = object.getBasicAngles();
441
    int[] numLayers = object.getNumLayers();
442
    float[][] cuts = object.getCuts(numLayers);
443
    boolean[][] rotatable = object.getLayerRotatable(numLayers);
444

    
445
    for( int i=0; i<numAxis; i++ )
446
      {
447
      JSONObject axObject = new JSONObject();
448
      Static3D ax = rotAxis[i];
449

    
450
      axObject.put("x", ax.get0() );
451
      axObject.put("y", ax.get1() );
452
      axObject.put("z", ax.get2() );
453

    
454
      JSONArray angleArray = new JSONArray();
455
      for(float angle : basicAngle[i]) angleArray.put(angle);
456
      axObject.put("basicAngles", angleArray);
457
      JSONArray cutsArray = new JSONArray();
458
      if( cuts[i]!=null ) for(float cut : cuts[i]) cutsArray.put(cut);
459
      axObject.put("cuts", cutsArray);
460
      JSONArray rotaArray = new JSONArray();
461
      for(boolean rot : rotatable[i]) rotaArray.put(rot);
462
      axObject.put("rotatable", rotaArray );
463

    
464
      axis.put(axObject);
465
      }
466

    
467
    return axis;
468
    }
469

    
470
///////////////////////////////////////////////////////////////////////////////////////////////////
471

    
472
  private JSONObject generateScrambling(TwistyObject object) throws JSONException
473
    {
474
    JSONObject scrambling = new JSONObject();
475

    
476
    ScrambleState[] states = object.getScrambleStates();
477
    int scrambleType = object.getScrambleType();
478
    scrambling.put("scrambleType",scrambleType );
479

    
480
    if( states!=null )
481
      {
482
      JSONArray scrambleStates = new JSONArray();
483

    
484
      for(ScrambleState state : states)
485
        {
486
        JSONArray axisArray = new JSONArray();
487
        int numAxis = state.getNumAxis();
488

    
489
        for(int ax=0; ax<numAxis; ax++)
490
          {
491
          JSONArray axArray = new JSONArray();
492
          int[] axData = state.getAx(ax);
493

    
494
          if( axData!=null )
495
            for(int data : axData) axArray.put(data);
496

    
497
          axisArray.put(axArray);
498
          }
499

    
500
        scrambleStates.put(axisArray);
501
        }
502

    
503
      scrambling.put("scrambleStates", scrambleStates);
504
      }
505

    
506
    return scrambling;
507
    }
508

    
509
///////////////////////////////////////////////////////////////////////////////////////////////////
510

    
511
  private JSONObject generateTouchControl(TwistyObject object) throws JSONException
512
    {
513
    JSONObject touchControl = new JSONObject();
514

    
515
    touchControl.put("movementType" , object.getTouchControlType() );
516
    touchControl.put("movementSplit", object.getTouchControlSplit() );
517

    
518
    int[][][] enabled = object.getEnabled();
519

    
520
    if( enabled!=null )
521
      {
522
      JSONArray enabledArray = new JSONArray();
523

    
524
      for(int[][] faceEnabled : enabled)
525
        {
526
        JSONArray faceArray = new JSONArray();
527

    
528
        for(int[] sectionEnabled : faceEnabled)
529
          {
530
          JSONArray sectionArray = new JSONArray();
531
          for(int ax : sectionEnabled) sectionArray.put(ax);
532
          faceArray.put(sectionArray);
533
          }
534
        enabledArray.put(faceArray);
535
        }
536

    
537
      touchControl.put("enabledAxis", enabledArray);
538
      }
539

    
540
    int[] numLayers = object.getNumLayers();
541
    float[] dist3D = object.getDist3D(numLayers);
542

    
543
    if( dist3D!=null )
544
      {
545
      JSONArray distArray = new JSONArray();
546
      for( float dist: dist3D ) distArray.put(dist);
547
      touchControl.put("dist3D", distArray);
548
      }
549

    
550
    return touchControl;
551
    }
552

    
553
///////////////////////////////////////////////////////////////////////////////////////////////////
554

    
555
  private JSONArray generateColors(TwistyObject object)
556
    {
557
    JSONArray jsonColors = new JSONArray();
558
    int numFaceColors = object.getNumFaceColors();
559
    for(int i=0; i<numFaceColors; i++) jsonColors.put(object.getColor(i));
560

    
561
    jsonColors.put(object.getInternalColor());
562

    
563
    return jsonColors;
564
    }
565

    
566
///////////////////////////////////////////////////////////////////////////////////////////////////
567

    
568
  private JSONObject generateSolved(TwistyObject object) throws JSONException
569
    {
570
    JSONObject solved = new JSONObject();
571
    int[][] solvedGroups = object.getSolvedQuats();
572

    
573
    solved.put("functionIndex", object.getSolvedFunctionIndex() );
574

    
575
    if( solvedGroups!=null )
576
      {
577
      JSONArray groupArray = new JSONArray();
578

    
579
      for( int[] group : solvedGroups )
580
        {
581
        JSONArray groupElements = new JSONArray();
582
        for( int element : group ) groupElements.put(element);
583
        groupArray.put(groupElements);
584
        }
585

    
586
      solved.put("groups", groupArray );
587
      }
588

    
589
    return solved;
590
    }
591

    
592
///////////////////////////////////////////////////////////////////////////////////////////////////
593

    
594
  public String createObjectString(TwistyObject object,int numScramble) throws JSONException
595
    {
596
    JSONObject json = new JSONObject();
597

    
598
    JSONObject metadata    = generateMetadata(object,numScramble);
599
    JSONObject mesh        = generateMesh(object);
600
    JSONArray  axis        = generateAxis(object);
601
    JSONArray  quats       = generateQuats(object);
602
    JSONObject scrambling  = generateScrambling(object);
603
    JSONObject touchControl= generateTouchControl(object);
604
    JSONArray  colors      = generateColors(object);
605
    JSONObject solved      = generateSolved(object);
606

    
607
    json.put("major"       , VERSION_OBJECT_MAJOR);
608
    json.put("minor"       , VERSION_OBJECT_MINOR);
609
    json.put("metadata"    , metadata);
610
    json.put("mesh"        , mesh);
611
    json.put("axis"        , axis);
612
    json.put("quats"       , quats);
613
    json.put("scrambling"  , scrambling);
614
    json.put("touchcontrol", touchControl);
615
    json.put("colors"      , colors);
616
    json.put("solved"      , solved);
617

    
618
    return json.toString();
619
    }
620

    
621
///////////////////////////////////////////////////////////////////////////////////////////////////
622

    
623
  public String createExtrasString(TwistyObject object) throws JSONException
624
    {
625
    String[][] tuts = object.getTutorials();
626

    
627
    if( tuts!=null )
628
      {
629
      JSONObject json = new JSONObject();
630
      JSONArray  tutorials = new JSONArray();
631

    
632
      for(String[] tut : tuts)
633
        {
634
        String language = tut[0];
635
        String link     = tut[1];
636
        String title    = tut[2];
637
        String author   = tut[3];
638

    
639
        JSONObject oneTut = new JSONObject();
640

    
641
        oneTut.put("language", language);
642
        oneTut.put("link"    , link    );
643
        oneTut.put("title"   , title   );
644
        oneTut.put("author"  , author  );
645

    
646
        tutorials.put(oneTut);
647
        }
648

    
649
      json.put("major"     , VERSION_EXTRAS_MAJOR);
650
      json.put("minor"     , VERSION_EXTRAS_MINOR);
651
      json.put("object"    , object.getShortName() );
652
      json.put("tutorials" , tutorials);
653

    
654
      return json.toString();
655
      }
656

    
657
    return null;
658
    }
659

    
660
///////////////////////////////////////////////////////////////////////////////////////////////////
661

    
662
  public void write(String filename, String contents) throws IOException
663
    {
664
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filename), StandardCharsets.UTF_8);
665
    BufferedWriter bw = new BufferedWriter(osw);
666
    bw.write(contents);
667
    bw.flush();
668
    }
669

    
670
///////////////////////////////////////////////////////////////////////////////////////////////////
671

    
672
  public static JsonWriter getInstance()
673
    {
674
    if( mThis==null ) mThis = new JsonWriter();
675
    return mThis;
676
    }
677
}
(2-2/2)