squishjs 0.6.42 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/.github/workflows/node.js.yml +1 -1
  2. package/LICENSE.md +21 -0
  3. package/README.md +116 -42
  4. package/index.js +11 -1
  5. package/oldsvgexport.js +89 -0
  6. package/package.json +1 -1
  7. package/render-tester.js +120 -0
  8. package/src/BaseNode.js +101 -0
  9. package/src/Game.js +15 -3
  10. package/src/GameNode.js +82 -79
  11. package/src/InternalGameNode.js +4 -3
  12. package/src/Squisher.js +230 -0
  13. package/src/ViewableGame.js +60 -0
  14. package/src/node-types.js +15 -0
  15. package/src/squish.js +90 -432
  16. package/src/squishHelpers/asset.js +63 -0
  17. package/src/squishHelpers/border.js +16 -0
  18. package/src/squishHelpers/color.js +16 -0
  19. package/src/squishHelpers/coordinates2d.js +98 -0
  20. package/src/squishHelpers/effect.js +55 -0
  21. package/src/squishHelpers/fill.js +16 -0
  22. package/src/squishHelpers/handleClick.js +16 -0
  23. package/src/squishHelpers/id.js +16 -0
  24. package/src/squishHelpers/input.js +22 -0
  25. package/src/squishHelpers/playerIds.js +12 -0
  26. package/src/squishHelpers/pos.js +23 -0
  27. package/src/squishHelpers/size.js +23 -0
  28. package/src/squishHelpers/subType.js +16 -0
  29. package/src/squishHelpers/text.js +154 -0
  30. package/src/subtype-mappings.js +10 -0
  31. package/src/subtypes.js +7 -0
  32. package/src/terrain/defs.ts +16 -0
  33. package/src/terrain/index.ts +156 -0
  34. package/src/terrain/terrainFunctions.ts +142 -0
  35. package/src/util/geometry.js +45 -0
  36. package/src/util/index.ts +6 -0
  37. package/src/util/listenable.ts +20 -0
  38. package/src/util/shapes.ts +18 -0
  39. package/src/util/views.js +108 -0
  40. package/test/Layers.test.js +63 -0
  41. package/test/Scale.test.js +235 -0
  42. package/test/Squisher.test.js +49 -0
  43. package/test/StateUpdates.js +10 -0
  44. package/test/Terrain.test.js +0 -1
  45. package/test/main.test.js +35 -37
  46. package/test/utils.js +91 -0
  47. package/testapp.html +26 -0
  48. package/testapp.js +988 -0
  49. package/tsconfig.json +22 -0
  50. package/license.txt +0 -674
package/src/squish.js CHANGED
@@ -1,467 +1,125 @@
1
- const InternalGameNode = require("./InternalGameNode");
2
- const Colors = require('./Colors');
3
-
4
1
  const assert = require('assert');
5
2
 
6
- const ASSET_TYPE = 1;
7
-
8
- const COLOR_SUBTYPE = 42;
9
- const ID_SUBTYPE = 43;
10
- const PLAYER_ID_SUBTYPE = 44;
11
- const POS_SUBTYPE = 45;
12
- const SIZE_SUBTYPE = 46;
13
- const TEXT_SUBTYPE = 47;
14
- const ASSET_SUBTYPE = 48;
15
- const EFFECTS_SUBTYPE = 49;
16
- const ONCLICK_SUBTYPE = 50;
17
- const INPUT_SUBTYPE = 51;
18
- const COORDINATES_2D_SUBTYPE = 52;
19
- const FILL_SUBTYPE = 53;
20
- const BORDER_SUBTYPE = 54;
21
-
22
- const { getFractional, hypLength } = require('./util/');
3
+ const InternalGameNode = require("./InternalGameNode");
4
+ const { CONSTRUCTOR_TO_TYPE, TYPE_TO_CONSTRUCTOR } = require('./node-types');
5
+ const SUBTYPE_MAPPINGS = require('./subtype-mappings');
6
+
7
+ const { squishId } = require('./squishHelpers/id');
8
+ const { squishColor } = require('./squishHelpers/color');
9
+ const { squishPlayerIds } = require('./squishHelpers/playerIds');
10
+ const { squishPos } = require('./squishHelpers/pos');
11
+ const { squishFill } = require('./squishHelpers/fill');
12
+ const { squishSize } = require('./squishHelpers/size');
13
+ const { squishHandleClick } = require('./squishHelpers/handleClick');
14
+ const { squishBorder } = require('./squishHelpers/border');
15
+ const { squishSubType } = require('./squishHelpers/subType');
16
+ const { squishInput } = require('./squishHelpers/input');
17
+ const { squishCoordinates2d } = require('./squishHelpers/coordinates2d');
18
+ const { squishEffect } = require('./squishHelpers/effect');
19
+ const { squishText } = require('./squishHelpers/text');
20
+ const { squishAsset } = require('./squishHelpers/asset');
23
21
 
24
22
  const squishSpec = {
25
- id: {
26
- type: ID_SUBTYPE,
27
- squish: (i) => {
28
- return [i];
29
- },
30
- unsquish: (arr) => {
31
- return arr[0];
32
- }
33
- },
34
- color: {
35
- type: COLOR_SUBTYPE,
36
- squish: (c) => {
37
- return [c[0], c[1], c[2], c[3]];
38
- },
39
- unsquish: (squished) => {
40
- return [squished[0], squished[1], squished[2], squished[3]];
41
- }
42
- },
43
- playerIds: {
44
- type: PLAYER_ID_SUBTYPE,
45
- squish: (i) => i,
46
- unsquish: (squished) => squished
47
- },
48
- pos: {
49
- type: POS_SUBTYPE,
50
- squish: (p) => {
51
- return [Math.floor(p.x), Math.round(100 * (p.x - Math.floor(p.x))), Math.floor(p.y), Math.round(100 * (p.y - Math.floor(p.y)))]
52
- },
53
- unsquish: (squished) => {
54
- return {
55
- x: squished[0] + squished[1] / 100,
56
- y: squished[2] + squished[3] / 100
57
- }
58
- }
59
- },
60
- coordinates2d: {
61
- type: COORDINATES_2D_SUBTYPE,
62
- squish: (p, scale) => {
63
- const originalCoords = p.flat();
64
- const squished = new Array(originalCoords.length * 2);
65
-
66
- for (const i in originalCoords) {
67
- if (scale) {
68
- const isX = i % 2 == 0;
69
- const scaleValue = isX ? scale.x : scale.y;
70
- const scaled = scaleValue * originalCoords[i];
71
-
72
- const removedSpace = Math.round(100 * (1 - scaleValue));
73
-
74
- const shifted = scaled + (removedSpace / 2);
75
-
76
- squished[2 * i] = shifted;
77
- squished[(2 * i) + 1] = getFractional(shifted);
78
-
79
- } else {
80
- squished[2 * i] = Math.floor(originalCoords[i]);
81
- squished[(2 * i) + 1] = Math.round(100 * (originalCoords[i] - Math.floor(originalCoords[i])));
82
- }
83
- }
84
-
85
- return squished;
86
- },
87
- unsquish: (squished) => {
88
- const unsquished = new Array(squished.length / 2);
89
- for (let i = 0; i < squished.length; i += 2) {
90
- const value = squished[i] + (squished[i + 1] / 100);
91
- unsquished[i / 2] = value;
92
- }
93
- return unsquished;
94
- }
95
- },
96
- fill: {
97
- type: FILL_SUBTYPE,
98
- squish: (c) => {
99
- return [c[0], c[1], c[2], c[3]];
100
- },
101
- unsquish: (squished) => {
102
- return [squished[0], squished[1], squished[2], squished[3]];
103
- }
104
- },
105
- size: {
106
- type: SIZE_SUBTYPE,
107
- squish: (s) => {
108
- return [Math.floor(s.x), Math.round(100 * (s.x - Math.floor(s.x))), Math.floor(s.y), Math.round(100 * (s.y - Math.floor(s.y)))]
109
- },
110
- unsquish: (squished) => {
111
- return {
112
- x: squished[0] + squished[1] / 100,
113
- y: squished[2] + squished[3] / 100
114
- }
115
- }
116
- },
117
- text: {
118
- type: TEXT_SUBTYPE,
119
- squish: (t, scale) => {
120
- const textX = scale ? (t.x * scale.x) + Math.round(100 * (1 - scale.x)) / 2 : t.x;
121
- const textY = scale ? (t.y * scale.y) + Math.round(100 * (1 - scale.y)) / 2 : t.y;
122
-
123
- const align = t.align || 'left';
124
- const squishedText = new Array(t.text.length + 10 + align.length);
125
-
126
- squishedText[0] = Math.floor(textX);
127
- squishedText[1] = Math.round(100 * (textX - Math.floor(textX)));
128
-
129
- squishedText[2] = Math.floor(textY);
130
- squishedText[3] = Math.round(100 * (textY - Math.floor(textY)));
131
-
132
- const textSize = t.size || 1;
133
- const scaledTextSize = scale ? textSize * hypLength(scale.x, scale.y) : textSize;
134
-
135
- squishedText[4] = Math.floor(scaledTextSize);
136
- squishedText[5] = Math.round(100 * (scaledTextSize - Math.floor(scaledTextSize)));
137
-
138
- const textColor = t.color || Colors.BLACK;
139
- const squishedTextColor = squishSpec.color.squish(textColor);
140
-
141
- for (let i = 0; i < squishedTextColor.length; i++) {
142
- squishedText[6 + i] = squishedTextColor[i];
143
- }
144
-
145
- squishedText[6 + squishedTextColor.length] = 3 * [...align].length;
146
-
147
- let j = 0;
148
- for (let i = 0; i < [...align].length; i++) {
149
- const codePointToInsert = [...align][i].codePointAt(0);//.codePointAt(i);
150
- const codePointString = codePointToInsert.toString();
151
- let ting;
152
- if (codePointString.length == 1) {
153
- ting = [`00`, `00`, `0${codePointString}`];
154
- } else if (codePointString.length == 2) {
155
- ting = [`00`, `00`, `${codePointString}`];
156
- } else if (codePointString.length == 3) {
157
- ting = [`00`, `0${codePointString.charAt(0)}`, `${codePointString.charAt(1)}${codePointString.charAt(2)}`];
158
- } else if (codePointString.length == 4) {
159
- ting = [`00`, `${codePointString.charAt(0)}${codePointString.charAt(1)}`, `${codePointString.charAt(2)}${codePointString.charAt(3)}`];
160
- } else if (codePointString.length == 5) {
161
- ting = [`0${codePointString.charAt(0)}`, `${codePointString.charAt(1)}${codePointString.charAt(2)}`, `${codePointString.charAt(3)}${codePointString.charAt(4)}`];
162
- } else {
163
- ting = [`${codePointString.charAt(0)}${codePointString.charAt(1)}`, `${codePointString.charAt(2)}${codePointString.charAt(3)}`, `${codePointString.charAt(4)}${codePointString.charAt(5)}`];
164
- }
165
- squishedText[6 + squishedTextColor.length + 1 + j] = Number(ting[0]);
166
- squishedText[6 + squishedTextColor.length + 1 + j + 1] = Number(ting[1]);
167
- squishedText[6 + squishedTextColor.length + 1 + j + 2] = Number(ting[2]);
168
- j += 3;
169
- }
170
-
171
- let k = 0;
172
- for (let i = 0; i < [...t.text].length; i++) {
173
- const codePointToInsert = [...t.text][i].codePointAt(0);
174
- const codePointString = codePointToInsert.toString();
175
- let ting;
176
- if (codePointString.length == 1) {
177
- ting = [`00`, `00`, `0${codePointString}`];
178
- } else if (codePointString.length == 2) {
179
- ting = [`00`, `00`, `${codePointString}`];
180
- } else if (codePointString.length == 3) {
181
- ting = [`00`, `0${codePointString.charAt(0)}`, `${codePointString.charAt(1)}${codePointString.charAt(2)}`];
182
- } else if (codePointString.length == 4) {
183
- ting = [`00`, `${codePointString.charAt(0)}${codePointString.charAt(1)}`, `${codePointString.charAt(2)}${codePointString.charAt(3)}`];
184
- } else if (codePointString.length == 5) {
185
- ting = [`0${codePointString.charAt(0)}`, `${codePointString.charAt(1)}${codePointString.charAt(2)}`, `${codePointString.charAt(3)}${codePointString.charAt(4)}`];
186
- } else {
187
- ting = [`${codePointString.charAt(0)}${codePointString.charAt(1)}`, `${codePointString.charAt(2)}${codePointString.charAt(3)}`, `${codePointString.charAt(4)}${codePointString.charAt(5)}`];
188
- }
189
- squishedText[6 + squishedTextColor.length + 1 + j + k] = Number(ting[0]);
190
- squishedText[6 + squishedTextColor.length + 1 + j + k + 1] = Number(ting[1]);
191
- squishedText[6 + squishedTextColor.length + 1 + j + k + 2] = Number(ting[2]);
192
-
193
- k += 3;
194
- }
195
-
196
- return squishedText;
197
- },
198
- unsquish: (squished) => {
199
- const textPosX = squished[0] + squished[1] / 100;
200
- const textPosY = squished[2] + squished[3] / 100;
201
- const textSize = squished[4] + squished[5] / 100;
202
- const textColor = squished.slice(6, 10);
203
- const textAlignLength = squished[10];
204
- const textAlignVal = squished.slice(11, 11 + textAlignLength);
205
- const textVal = squished.slice(11 + textAlignLength);
206
-
207
- let alignCodePoints = [];
208
- for (let i = 0; i < textAlignVal.length; i+=3) {
209
- let firstChunk = textAlignVal[i].toString();
210
- if (firstChunk.length == 1) {
211
- firstChunk = `0${firstChunk}`;
212
- }
213
-
214
- let secondChunk = textAlignVal[i + 1].toString();
215
- if (secondChunk.length == 1) {
216
- secondChunk = `0${secondChunk}`;
217
- }
218
-
219
- let thirdChunk = textAlignVal[i + 2].toString();
220
- if (thirdChunk.length == 1) {
221
- thirdChunk = `0${thirdChunk}`;
222
- }
223
-
224
- const codePoint = firstChunk + secondChunk + thirdChunk;
225
- alignCodePoints.push(codePoint);
226
- }
227
-
228
- const textCodePoints = [];
229
- for (let i = 0; i < textVal.length; i+=3) {
230
- let firstChunk = textVal[i].toString();
231
- if (firstChunk.length == 1) {
232
- firstChunk = `0${firstChunk}`;
233
- }
234
- let secondChunk = textVal[i + 1].toString();
235
- if (secondChunk.length == 1) {
236
- secondChunk = `0${secondChunk}`;
237
- }
238
- let thirdChunk = textVal[i + 2].toString();
239
- if (thirdChunk.length == 1) {
240
- thirdChunk = `0${thirdChunk}`;
241
- }
242
-
243
- const codePoint = firstChunk + secondChunk + thirdChunk;
244
- textCodePoints.push(codePoint);
245
- }
246
-
247
- const align = String.fromCodePoint.apply(null, alignCodePoints);
248
- const text = String.fromCodePoint.apply(null, textCodePoints);//squished.slice(11 + textAlignLength));
249
-
250
- return {
251
- x: textPosX,
252
- y: textPosY,
253
- text: text,
254
- size: textSize,
255
- color: textColor,
256
- align
257
- };
258
- }
259
- },
260
- asset: {
261
- type: ASSET_SUBTYPE,
262
- squish: (a, scale) => {
263
- const assetKey = Object.keys(a)[0];
264
- const squishedAssets = new Array(8 + assetKey.length);
265
-
266
- const asset = a[assetKey];
267
-
268
- const posX = scale ? ((scale.x * asset.pos.x) + Math.round(100 * (1 - scale.x)) / 2) : asset.pos.x;
269
- const posY = scale ? ((scale.y * asset.pos.y) + Math.round(100 * (1 - scale.y)) / 2) : asset.pos.y;
270
-
271
- const sizeX = scale ? scale.x * asset.size.x : asset.size.x;
272
- const sizeY = scale ? scale.y * asset.size.y : asset.size.y;
273
-
274
- squishedAssets[0] = Math.floor(posX);
275
- squishedAssets[1] = getFractional(posX);
276
-
277
- squishedAssets[2] = Math.floor(posY);
278
- squishedAssets[3] = getFractional(posY);
279
-
280
- squishedAssets[4] = Math.floor(sizeX);
281
- squishedAssets[5] = getFractional(sizeX);
23
+ id: squishId,
24
+ color: squishColor,
25
+ playerIds: squishPlayerIds,
26
+ pos: squishPos,
27
+ coordinates2d: squishCoordinates2d,
28
+ fill: squishFill,
29
+ size: squishSize,
30
+ text: squishText,
31
+ asset: squishAsset,
32
+ effects: squishEffect,
33
+ handleClick:squishHandleClick,
34
+ border: squishBorder,
35
+ subType: squishSubType,
36
+ input: squishInput
37
+ };
282
38
 
283
- squishedAssets[6] = Math.floor(sizeY);
284
- squishedAssets[7] = getFractional(sizeY);
39
+ const typeToSquishMap = {};
285
40
 
286
- for (let i = 0; i < assetKey.length; i++) {
287
- squishedAssets[8 + i] = assetKey.codePointAt(i);
288
- }
289
-
290
- return squishedAssets;
291
- },
292
- unsquish: (squished) => {
293
- const assetPosX = squished[0] + squished[1] / 100;
294
- const assetPosY = squished[2] + squished[3] / 100;
41
+ for (const key in squishSpec) {
42
+ typeToSquishMap[Number(squishSpec[key]['type'])] = key;
43
+ }
295
44
 
296
- const assetSizeX = squished[4] + squished[5] / 100;
297
- const assetSizeY = squished[6] + squished[7] / 100;
45
+ const unsquish = (squished) => {
46
+ assert(squished[0] == 3);
298
47
 
299
- const assetKey = String.fromCodePoint.apply(null, squished.slice(8));
300
- return {
301
- [assetKey]: {
302
- pos: {
303
- x: assetPosX,
304
- y: assetPosY
305
- },
306
- size: {
307
- x: assetSizeX,
308
- y: assetSizeY
309
- }
310
- }
311
- }
312
- }
313
- },
314
- effects: {
315
- type: EFFECTS_SUBTYPE,
316
- squish: (a) => {
317
- if (a['shadow']) {
318
- const assetKey = 'shadow';
319
- let squishedLength = assetKey.length + 4; // + 4 for color
320
- if (a['shadow'].blur) {
321
- squishedLength += 2;
322
- }
323
- const squishedEffects = new Array(squishedLength);
324
- for (let i = 0; i < assetKey.length; i++) {
325
- squishedEffects[i] = assetKey.codePointAt(i);
326
- }
327
- squishedEffects[assetKey.length] = a.shadow.color[0];
328
- squishedEffects[assetKey.length + 1] = a.shadow.color[1];
329
- squishedEffects[assetKey.length + 2] = a.shadow.color[2];
330
- squishedEffects[assetKey.length + 3] = a.shadow.color[3];
48
+ assert(squished.length === squished[1]);
331
49
 
332
- if (a.shadow.blur) {
333
- squishedEffects[assetKey.length + 4] = Math.floor(a.shadow.blur / 10)
334
- squishedEffects[assetKey.length + 5] = a.shadow.blur % 10
335
- }
50
+ let squishedIndex = 3;
336
51
 
337
- return squishedEffects;
338
- }
339
- },
340
- unsquish: (squished) => {
341
- // 'shadow' is all (for now)
342
- const assetKey = String.fromCodePoint.apply(null, squished.slice(0, 6));
343
- const color = squished.slice(6, 10);
344
- let blur;
345
- if (squished.length > 10) {
346
- blur = squished[10] * 10 + squished[11];
347
- }
52
+ let constructedInternalNode = new InternalGameNode();
348
53
 
349
- const unsquished = {
350
- [assetKey]: {
351
- color
352
- }
353
- };
54
+ while(squishedIndex < squished.length) {
354
55
 
355
- if (blur) {
356
- unsquished[assetKey].blur = blur;
357
- }
56
+ const subFrameType = squished[squishedIndex];
57
+ const subFrameLength = squished[squishedIndex + 1];
58
+ const subFrame = squished.slice(squishedIndex + 2, squishedIndex + subFrameLength);
358
59
 
359
- return unsquished;
360
- }
361
- },
362
- handleClick: {
363
- type: ONCLICK_SUBTYPE,
364
- squish: (a) => {
365
- return a ? [1] : [0];
366
- },
367
- unsquish: (a) => {
368
- return a[0] === 1;
369
- }
370
- },
371
- border: {
372
- type: BORDER_SUBTYPE,
373
- squish: (a) => {
374
- return [a];
375
- },
376
- unsquish: (s) => {
377
- return s[0];
378
- }
379
- },
380
- input: {
381
- type: INPUT_SUBTYPE,
382
- squish: (a) => {
383
- const squished = new Array(a.type.length);
384
- for (let i = 0; i < a.type.length; i++) {
385
- squished[i] = a.type.codePointAt(i);
386
- }
387
- return squished;
388
- },
389
- unsquish: (squished) => {
390
- return {
391
- type: String.fromCodePoint.apply(null, squished)
392
- }
60
+ if (!typeToSquishMap[subFrameType]) {
61
+ console.warn("Unknown sub frame type " + subFrameType);
62
+ break;
63
+ } else {
64
+ const objField = typeToSquishMap[subFrameType];
65
+ const unsquishFun = squishSpec[objField]['unsquish'];
66
+ // anything that was declared as a dependency of this property will be available when
67
+ // calling this property's unsquish function
68
+ const dependencyReference = Object.assign({}, constructedInternalNode);
69
+ const unsquishedVal = unsquishFun(subFrame, dependencyReference);
70
+ constructedInternalNode[objField] = unsquishedVal;
393
71
  }
72
+ squishedIndex += subFrameLength;
394
73
  }
395
- };
396
74
 
397
- const squishSpecKeys = [
398
- 'id',
399
- 'color',
400
- 'playerIds',
401
- 'coordinates2d',
402
- 'fill',
403
- 'pos',
404
- 'size',
405
- 'text',
406
- 'asset',
407
- 'effects',
408
- 'border',
409
- 'handleClick',
410
- 'input'
411
- ];
75
+ const constructor = TYPE_TO_CONSTRUCTOR[squished[2]];
76
+ return new constructor({ node: constructedInternalNode });
77
+ }
412
78
 
413
- const typeToSquishMap = {};
79
+ // When squishing, we need to make sure that properties that other properties depend on are inserted first.
80
+ // This is because when unsquishing, we need to guarantee that the dependee is available to the function responsible
81
+ // for creating the dependant
82
+ const sortSpecKeys = () => {
83
+ const keysWithDeps = Object.keys(squishSpec).filter(key => {
84
+ return squishSpec[key].dependsOn && squishSpec[key].dependsOn.length > 0;
85
+ });
414
86
 
415
- for (const key in squishSpec) {
416
- typeToSquishMap[Number(squishSpec[key]['type'])] = key;
417
- }
87
+ const keysWithoutDeps = Object.keys(squishSpec).filter(key => {
88
+ return !squishSpec[key].dependsOn || squishSpec[key].dependsOn.length === 0;
89
+ });
418
90
 
419
- const unsquish = (squished) => {
420
- assert(squished[0] == 3);
421
-
422
- assert(squished.length === squished[1]);
91
+ // todo: recursively find circular deps
423
92
 
424
- let squishedIndex = 2;
93
+ return [keysWithoutDeps, keysWithDeps].flat();
94
+ }
425
95
 
426
- let constructedGameNode = new InternalGameNode();
96
+ const squish = (entity, scale = null) => {
97
+ let squishedPieces = [];
427
98
 
428
- while(squishedIndex < squished.length) {
99
+ const internalNode = entity.node;
429
100
 
430
- const subFrameType = squished[squishedIndex];
431
- const subFrameLength = squished[squishedIndex + 1];
432
- const subFrame = squished.slice(squishedIndex + 2, squishedIndex + subFrameLength);
101
+ const sortedSpecKeys = sortSpecKeys();
433
102
 
434
- if (!typeToSquishMap[subFrameType]) {
435
- console.warn("Unknown sub frame type " + subFrameType);
436
- break;
437
- } else {
438
- const objField = typeToSquishMap[subFrameType];
439
- const unsquishFun = squishSpec[objField]['unsquish'];
440
- const unsquishedVal = unsquishFun(subFrame);
441
- constructedGameNode[objField] = unsquishedVal;
103
+ for (const keyIndex in sortedSpecKeys) {
104
+ const key = sortedSpecKeys[keyIndex];
105
+ if (key in internalNode) {
106
+ const attr = internalNode[key];
107
+ if (attr !== undefined && attr !== null) {
108
+ const squished = squishSpec[key].squish(attr, scale, internalNode);
109
+ squishedPieces.push([squishSpec[key]['type'], squished.length + 2, ...squished]);
442
110
  }
443
- squishedIndex += subFrameLength;
444
111
  }
445
-
446
- return constructedGameNode;
447
112
  }
448
113
 
449
- const squish = (entity, scale = null) => {
450
- let squishedPieces = [];
114
+ let nodeClassCode = CONSTRUCTOR_TO_TYPE[entity.constructor.name];
451
115
 
452
- for (const keyIndex in squishSpecKeys) {
453
- const key = squishSpecKeys[keyIndex];
454
- if (key in entity) {
455
- const attr = entity[key];
456
- if (attr !== undefined && attr !== null) {
457
- const squished = squishSpec[key].squish(attr, scale);
458
- squishedPieces.push([squishSpec[key]['type'], squished.length + 2, ...squished]);
459
- }
460
- }
116
+ // implemented for json support (infer from subtype instead of custom json property)
117
+ if (!nodeClassCode) {
118
+ nodeClassCode = CONSTRUCTOR_TO_TYPE[SUBTYPE_MAPPINGS[internalNode.subType]];
461
119
  }
462
120
 
463
121
  const squished = squishedPieces.flat();
464
- return [3, squished.length + 2, ...squished];
122
+ return [3, squished.length + 3, nodeClassCode, ...squished];
465
123
 
466
124
  }
467
125
 
@@ -0,0 +1,63 @@
1
+ const { getFractional } = require('../util')
2
+
3
+ const ASSET_SUBTYPE = 48;
4
+
5
+ const squishAsset = {
6
+ type: ASSET_SUBTYPE,
7
+ squish: (a, scale) => {
8
+ const assetKey = Object.keys(a)[0];
9
+ const squishedAssets = new Array(8 + assetKey.length);
10
+
11
+ const asset = a[assetKey];
12
+
13
+ const posX = scale ? ((scale.x * asset.pos.x) + Math.round(100 * (1 - scale.x)) / 2) : asset.pos.x;
14
+ const posY = scale ? ((scale.y * asset.pos.y) + Math.round(100 * (1 - scale.y)) / 2) : asset.pos.y;
15
+
16
+ const sizeX = scale ? scale.x * asset.size.x : asset.size.x;
17
+ const sizeY = scale ? scale.y * asset.size.y : asset.size.y;
18
+
19
+ squishedAssets[0] = Math.floor(posX);
20
+ squishedAssets[1] = getFractional(posX);
21
+
22
+ squishedAssets[2] = Math.floor(posY);
23
+ squishedAssets[3] = getFractional(posY);
24
+
25
+ squishedAssets[4] = Math.floor(sizeX);
26
+ squishedAssets[5] = getFractional(sizeX);
27
+
28
+ squishedAssets[6] = Math.floor(sizeY);
29
+ squishedAssets[7] = getFractional(sizeY);
30
+
31
+ for (let i = 0; i < assetKey.length; i++) {
32
+ squishedAssets[8 + i] = assetKey.codePointAt(i);
33
+ }
34
+
35
+ return squishedAssets;
36
+ },
37
+ unsquish: (squished) => {
38
+ const assetPosX = squished[0] + squished[1] / 100;
39
+ const assetPosY = squished[2] + squished[3] / 100;
40
+
41
+ const assetSizeX = squished[4] + squished[5] / 100;
42
+ const assetSizeY = squished[6] + squished[7] / 100;
43
+
44
+ const assetKey = String.fromCodePoint.apply(null, squished.slice(8));
45
+ return {
46
+ [assetKey]: {
47
+ pos: {
48
+ x: assetPosX,
49
+ y: assetPosY
50
+ },
51
+ size: {
52
+ x: assetSizeX,
53
+ y: assetSizeY
54
+ }
55
+ }
56
+ }
57
+ }
58
+ }
59
+
60
+ module.exports = {
61
+ ASSET_SUBTYPE,
62
+ squishAsset
63
+ };
@@ -0,0 +1,16 @@
1
+ const BORDER_SUBTYPE = 54;
2
+
3
+ const squishBorder = {
4
+ type: BORDER_SUBTYPE,
5
+ squish: (a) => {
6
+ return [a];
7
+ },
8
+ unsquish: (s) => {
9
+ return s[0];
10
+ }
11
+ }
12
+
13
+ module.exports = {
14
+ BORDER_SUBTYPE,
15
+ squishBorder
16
+ };
@@ -0,0 +1,16 @@
1
+ const COLOR_SUBTYPE = 42;
2
+
3
+ const squishColor = {
4
+ type: COLOR_SUBTYPE,
5
+ squish: (c) => {
6
+ return [c[0], c[1], c[2], c[3]];
7
+ },
8
+ unsquish: (squished) => {
9
+ return [squished[0], squished[1], squished[2], squished[3]];
10
+ }
11
+ }
12
+
13
+ module.exports = {
14
+ COLOR_SUBTYPE,
15
+ squishColor
16
+ };