squishjs 0.6.41 → 0.7.1

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 +224 -0
  13. package/src/ViewableGame.js +60 -0
  14. package/src/node-types.js +15 -0
  15. package/src/squish.js +90 -349
  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 +55 -35
  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,384 +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] = align.length;
146
-
147
- for (let i = 0; i < align.length; i++) {
148
- squishedText[6 + squishedTextColor.length + 1 + i] = align.codePointAt(i);
149
- }
150
-
151
- for (let i = 0; i < t.text.length; i++) {
152
- squishedText[6 + squishedTextColor.length + align.length + 1 + i] = t.text.codePointAt(i);
153
- }
154
-
155
- return squishedText;
156
- },
157
- unsquish: (squished) => {
158
- const textPosX = squished[0] + squished[1] / 100;
159
- const textPosY = squished[2] + squished[3] / 100;
160
- const textSize = squished[4] + squished[5] / 100;
161
- const textColor = squished.slice(6, 10);
162
- const textAlignLength = squished[10];
163
- const align = String.fromCodePoint.apply(null, squished.slice(11, 11 + textAlignLength));
164
-
165
- const text = String.fromCodePoint.apply(null, squished.slice(11 + textAlignLength));
166
-
167
- return {
168
- x: textPosX,
169
- y: textPosY,
170
- text: text,
171
- size: textSize,
172
- color: textColor,
173
- align
174
- };
175
- }
176
- },
177
- asset: {
178
- type: ASSET_SUBTYPE,
179
- squish: (a, scale) => {
180
- const assetKey = Object.keys(a)[0];
181
- const squishedAssets = new Array(8 + assetKey.length);
182
-
183
- const asset = a[assetKey];
184
-
185
- const posX = scale ? ((scale.x * asset.pos.x) + Math.round(100 * (1 - scale.x)) / 2) : asset.pos.x;
186
- const posY = scale ? ((scale.y * asset.pos.y) + Math.round(100 * (1 - scale.y)) / 2) : asset.pos.y;
187
-
188
- const sizeX = scale ? scale.x * asset.size.x : asset.size.x;
189
- const sizeY = scale ? scale.y * asset.size.y : asset.size.y;
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
+ };
190
38
 
191
- squishedAssets[0] = Math.floor(posX);
192
- squishedAssets[1] = getFractional(posX);
39
+ const typeToSquishMap = {};
193
40
 
194
- squishedAssets[2] = Math.floor(posY);
195
- squishedAssets[3] = getFractional(posY);
41
+ for (const key in squishSpec) {
42
+ typeToSquishMap[Number(squishSpec[key]['type'])] = key;
43
+ }
196
44
 
197
- squishedAssets[4] = Math.floor(sizeX);
198
- squishedAssets[5] = getFractional(sizeX);
45
+ const unsquish = (squished) => {
46
+ assert(squished[0] == 3);
199
47
 
200
- squishedAssets[6] = Math.floor(sizeY);
201
- squishedAssets[7] = getFractional(sizeY);
48
+ assert(squished.length === squished[1]);
202
49
 
203
- for (let i = 0; i < assetKey.length; i++) {
204
- squishedAssets[8 + i] = assetKey.codePointAt(i);
205
- }
206
-
207
- return squishedAssets;
208
- },
209
- unsquish: (squished) => {
210
- const assetPosX = squished[0] + squished[1] / 100;
211
- const assetPosY = squished[2] + squished[3] / 100;
50
+ let squishedIndex = 3;
212
51
 
213
- const assetSizeX = squished[4] + squished[5] / 100;
214
- const assetSizeY = squished[6] + squished[7] / 100;
52
+ let constructedInternalNode = new InternalGameNode();
215
53
 
216
- const assetKey = String.fromCodePoint.apply(null, squished.slice(8));
217
- return {
218
- [assetKey]: {
219
- pos: {
220
- x: assetPosX,
221
- y: assetPosY
222
- },
223
- size: {
224
- x: assetSizeX,
225
- y: assetSizeY
226
- }
227
- }
228
- }
229
- }
230
- },
231
- effects: {
232
- type: EFFECTS_SUBTYPE,
233
- squish: (a) => {
234
- if (a['shadow']) {
235
- const assetKey = 'shadow';
236
- let squishedLength = assetKey.length + 4; // + 4 for color
237
- if (a['shadow'].blur) {
238
- squishedLength += 2;
239
- }
240
- const squishedEffects = new Array(squishedLength);
241
- for (let i = 0; i < assetKey.length; i++) {
242
- squishedEffects[i] = assetKey.codePointAt(i);
243
- }
244
- squishedEffects[assetKey.length] = a.shadow.color[0];
245
- squishedEffects[assetKey.length + 1] = a.shadow.color[1];
246
- squishedEffects[assetKey.length + 2] = a.shadow.color[2];
247
- squishedEffects[assetKey.length + 3] = a.shadow.color[3];
54
+ while(squishedIndex < squished.length) {
248
55
 
249
- if (a.shadow.blur) {
250
- squishedEffects[assetKey.length + 4] = Math.floor(a.shadow.blur / 10)
251
- squishedEffects[assetKey.length + 5] = a.shadow.blur % 10
252
- }
56
+ const subFrameType = squished[squishedIndex];
57
+ const subFrameLength = squished[squishedIndex + 1];
58
+ const subFrame = squished.slice(squishedIndex + 2, squishedIndex + subFrameLength);
253
59
 
254
- return squishedEffects;
255
- }
256
- },
257
- unsquish: (squished) => {
258
- // 'shadow' is all (for now)
259
- const assetKey = String.fromCodePoint.apply(null, squished.slice(0, 6));
260
- const color = squished.slice(6, 10);
261
- let blur;
262
- if (squished.length > 10) {
263
- blur = squished[10] * 10 + squished[11];
264
- }
265
-
266
- const unsquished = {
267
- [assetKey]: {
268
- color
269
- }
270
- };
271
-
272
- if (blur) {
273
- unsquished[assetKey].blur = blur;
274
- }
275
-
276
- return unsquished;
277
- }
278
- },
279
- handleClick: {
280
- type: ONCLICK_SUBTYPE,
281
- squish: (a) => {
282
- return a ? [1] : [0];
283
- },
284
- unsquish: (a) => {
285
- return a[0] === 1;
286
- }
287
- },
288
- border: {
289
- type: BORDER_SUBTYPE,
290
- squish: (a) => {
291
- return [a];
292
- },
293
- unsquish: (s) => {
294
- return s[0];
295
- }
296
- },
297
- input: {
298
- type: INPUT_SUBTYPE,
299
- squish: (a) => {
300
- const squished = new Array(a.type.length);
301
- for (let i = 0; i < a.type.length; i++) {
302
- squished[i] = a.type.codePointAt(i);
303
- }
304
- return squished;
305
- },
306
- unsquish: (squished) => {
307
- return {
308
- type: String.fromCodePoint.apply(null, squished)
309
- }
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;
310
71
  }
72
+ squishedIndex += subFrameLength;
311
73
  }
312
- };
313
74
 
314
- const squishSpecKeys = [
315
- 'id',
316
- 'color',
317
- 'playerIds',
318
- 'coordinates2d',
319
- 'fill',
320
- 'pos',
321
- 'size',
322
- 'text',
323
- 'asset',
324
- 'effects',
325
- 'border',
326
- 'handleClick',
327
- 'input'
328
- ];
75
+ const constructor = TYPE_TO_CONSTRUCTOR[squished[2]];
76
+ return new constructor({ node: constructedInternalNode });
77
+ }
329
78
 
330
- 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
+ });
331
86
 
332
- for (const key in squishSpec) {
333
- typeToSquishMap[Number(squishSpec[key]['type'])] = key;
334
- }
87
+ const keysWithoutDeps = Object.keys(squishSpec).filter(key => {
88
+ return !squishSpec[key].dependsOn || squishSpec[key].dependsOn.length === 0;
89
+ });
335
90
 
336
- const unsquish = (squished) => {
337
- assert(squished[0] == 3);
338
-
339
- assert(squished.length === squished[1]);
91
+ // todo: recursively find circular deps
340
92
 
341
- let squishedIndex = 2;
93
+ return [keysWithoutDeps, keysWithDeps].flat();
94
+ }
342
95
 
343
- let constructedGameNode = new InternalGameNode();
96
+ const squish = (entity, scale = null) => {
97
+ let squishedPieces = [];
344
98
 
345
- while(squishedIndex < squished.length) {
99
+ const internalNode = entity.node;
346
100
 
347
- const subFrameType = squished[squishedIndex];
348
- const subFrameLength = squished[squishedIndex + 1];
349
- const subFrame = squished.slice(squishedIndex + 2, squishedIndex + subFrameLength);
101
+ const sortedSpecKeys = sortSpecKeys();
350
102
 
351
- if (!typeToSquishMap[subFrameType]) {
352
- console.warn("Unknown sub frame type " + subFrameType);
353
- break;
354
- } else {
355
- const objField = typeToSquishMap[subFrameType];
356
- const unsquishFun = squishSpec[objField]['unsquish'];
357
- const unsquishedVal = unsquishFun(subFrame);
358
- 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]);
359
110
  }
360
- squishedIndex += subFrameLength;
361
111
  }
362
-
363
- return constructedGameNode;
364
112
  }
365
113
 
366
- const squish = (entity, scale = null) => {
367
- let squishedPieces = [];
114
+ let nodeClassCode = CONSTRUCTOR_TO_TYPE[entity.constructor.name];
368
115
 
369
- for (const keyIndex in squishSpecKeys) {
370
- const key = squishSpecKeys[keyIndex];
371
- if (key in entity) {
372
- const attr = entity[key];
373
- if (attr !== undefined && attr !== null) {
374
- const squished = squishSpec[key].squish(attr, scale);
375
- squishedPieces.push([squishSpec[key]['type'], squished.length + 2, ...squished]);
376
- }
377
- }
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]];
378
119
  }
379
120
 
380
121
  const squished = squishedPieces.flat();
381
- return [3, squished.length + 2, ...squished];
122
+ return [3, squished.length + 3, nodeClassCode, ...squished];
382
123
 
383
124
  }
384
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
+ };
@@ -0,0 +1,98 @@
1
+ const { getFractional } = require('../util');
2
+ const subtypes = require('../subtypes');
3
+
4
+ const COORDINATES_2D_SUBTYPE = 52;
5
+
6
+ const squishHelper = (scale, coord) => {
7
+ const scaledCenter = scale * coord;
8
+ const removedSpaceCenter = Math.round(100 * (1 - scale));
9
+ return scaledCenter + (removedSpaceCenter / 2);
10
+ }
11
+
12
+ const squishCoordinates2d = {
13
+ type: COORDINATES_2D_SUBTYPE,
14
+ squish: (p, scale, node) => {
15
+ const originalCoords = p.flat();
16
+ const squished = new Array(originalCoords.length * 2);
17
+
18
+ if (node.subType == subtypes.SHAPE_2D_CIRCLE) {
19
+ if (scale) {
20
+ const shiftedCenterX = squishHelper(scale.x, originalCoords[0])
21
+ squished[0] = shiftedCenterX;
22
+ squished[1] = getFractional(shiftedCenterX);
23
+
24
+ const shiftedCenterY = squishHelper(scale.y, originalCoords[1])
25
+ squished[2] = shiftedCenterY;
26
+ squished[3] = getFractional(shiftedCenterY);
27
+
28
+ let diagonal;
29
+ if (scale.x === scale.y) {
30
+ diagonal = scale.x * originalCoords[2];
31
+ } else {
32
+ // probably broken
33
+ diagonal = Math.sqrt( Math.pow(100 * scale.x, 2) + Math.pow(100 * scale.y, 2)) * (originalCoords[2] / 100);
34
+ }
35
+
36
+ squished[4] = Math.floor(diagonal);
37
+ squished[5] = getFractional(diagonal);
38
+ } else {
39
+ const centerX = originalCoords[0];
40
+ squished[0] = Math.floor(centerX);
41
+ squished[1] = getFractional(centerX);
42
+
43
+ const centerY = originalCoords[1];
44
+ squished[2] = Math.floor(centerY);
45
+ squished[3] = getFractional(centerY);
46
+
47
+ const radius = originalCoords[2];
48
+ squished[4] = Math.round(radius);
49
+ squished[5] = getFractional(radius);
50
+ }
51
+ } else {
52
+ for (const i in originalCoords) {
53
+ if (scale) {
54
+ const isX = i % 2 == 0;
55
+ const scaleValue = isX ? scale.x : scale.y;
56
+ const scaled = scaleValue * originalCoords[i];
57
+
58
+ const removedSpace = Math.round(100 * (1 - scaleValue));
59
+
60
+ const shifted = scaled + (removedSpace / 2);
61
+
62
+ squished[2 * i] = shifted;
63
+ squished[(2 * i) + 1] = getFractional(shifted);
64
+
65
+ } else {
66
+ squished[2 * i] = Math.floor(originalCoords[i]);
67
+ squished[(2 * i) + 1] = Math.round(100 * (originalCoords[i] - Math.floor(originalCoords[i])));
68
+ }
69
+ }
70
+ }
71
+
72
+ return squished;
73
+ },
74
+ dependsOn: ['subType'],
75
+ unsquish: (squished, { subType }) => {
76
+ const unsquished = new Array(squished.length / 2);
77
+ for (let i = 0; i < squished.length; i += 2) {
78
+ const value = squished[i] + (squished[i + 1] / 100);
79
+ unsquished[i / 2] = value;
80
+ }
81
+
82
+ if (subType === subtypes.SHAPE_2D_POLYGON || subType === subtypes.SHAPE_2D_LINE) {
83
+ const coordPairs = new Array(unsquished.length / 2);
84
+ for (let i = 0; i < unsquished.length; i += 2) {
85
+ coordPairs[i / 2] = [unsquished[i], unsquished[i + 1]];
86
+ }
87
+
88
+ return coordPairs;
89
+ }
90
+
91
+ return unsquished;
92
+ }
93
+ }
94
+
95
+ module.exports = {
96
+ COORDINATES_2D_SUBTYPE,
97
+ squishCoordinates2d
98
+ };