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.
- package/.github/workflows/node.js.yml +1 -1
- package/LICENSE.md +21 -0
- package/README.md +116 -42
- package/index.js +11 -1
- package/oldsvgexport.js +89 -0
- package/package.json +1 -1
- package/render-tester.js +120 -0
- package/src/BaseNode.js +101 -0
- package/src/Game.js +15 -3
- package/src/GameNode.js +82 -79
- package/src/InternalGameNode.js +4 -3
- package/src/Squisher.js +230 -0
- package/src/ViewableGame.js +60 -0
- package/src/node-types.js +15 -0
- package/src/squish.js +90 -432
- package/src/squishHelpers/asset.js +63 -0
- package/src/squishHelpers/border.js +16 -0
- package/src/squishHelpers/color.js +16 -0
- package/src/squishHelpers/coordinates2d.js +98 -0
- package/src/squishHelpers/effect.js +55 -0
- package/src/squishHelpers/fill.js +16 -0
- package/src/squishHelpers/handleClick.js +16 -0
- package/src/squishHelpers/id.js +16 -0
- package/src/squishHelpers/input.js +22 -0
- package/src/squishHelpers/playerIds.js +12 -0
- package/src/squishHelpers/pos.js +23 -0
- package/src/squishHelpers/size.js +23 -0
- package/src/squishHelpers/subType.js +16 -0
- package/src/squishHelpers/text.js +154 -0
- package/src/subtype-mappings.js +10 -0
- package/src/subtypes.js +7 -0
- package/src/terrain/defs.ts +16 -0
- package/src/terrain/index.ts +156 -0
- package/src/terrain/terrainFunctions.ts +142 -0
- package/src/util/geometry.js +45 -0
- package/src/util/index.ts +6 -0
- package/src/util/listenable.ts +20 -0
- package/src/util/shapes.ts +18 -0
- package/src/util/views.js +108 -0
- package/test/Layers.test.js +63 -0
- package/test/Scale.test.js +235 -0
- package/test/Squisher.test.js +49 -0
- package/test/StateUpdates.js +10 -0
- package/test/Terrain.test.js +0 -1
- package/test/main.test.js +35 -37
- package/test/utils.js +91 -0
- package/testapp.html +26 -0
- package/testapp.js +988 -0
- package/tsconfig.json +22 -0
- 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
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
const {
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
284
|
-
squishedAssets[7] = getFractional(sizeY);
|
|
39
|
+
const typeToSquishMap = {};
|
|
285
40
|
|
|
286
|
-
|
|
287
|
-
|
|
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
|
-
|
|
297
|
-
|
|
45
|
+
const unsquish = (squished) => {
|
|
46
|
+
assert(squished[0] == 3);
|
|
298
47
|
|
|
299
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
350
|
-
[assetKey]: {
|
|
351
|
-
color
|
|
352
|
-
}
|
|
353
|
-
};
|
|
54
|
+
while(squishedIndex < squished.length) {
|
|
354
55
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
56
|
+
const subFrameType = squished[squishedIndex];
|
|
57
|
+
const subFrameLength = squished[squishedIndex + 1];
|
|
58
|
+
const subFrame = squished.slice(squishedIndex + 2, squishedIndex + subFrameLength);
|
|
358
59
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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
|
|
398
|
-
|
|
399
|
-
|
|
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
|
-
|
|
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
|
-
|
|
416
|
-
|
|
417
|
-
}
|
|
87
|
+
const keysWithoutDeps = Object.keys(squishSpec).filter(key => {
|
|
88
|
+
return !squishSpec[key].dependsOn || squishSpec[key].dependsOn.length === 0;
|
|
89
|
+
});
|
|
418
90
|
|
|
419
|
-
|
|
420
|
-
assert(squished[0] == 3);
|
|
421
|
-
|
|
422
|
-
assert(squished.length === squished[1]);
|
|
91
|
+
// todo: recursively find circular deps
|
|
423
92
|
|
|
424
|
-
|
|
93
|
+
return [keysWithoutDeps, keysWithDeps].flat();
|
|
94
|
+
}
|
|
425
95
|
|
|
426
|
-
|
|
96
|
+
const squish = (entity, scale = null) => {
|
|
97
|
+
let squishedPieces = [];
|
|
427
98
|
|
|
428
|
-
|
|
99
|
+
const internalNode = entity.node;
|
|
429
100
|
|
|
430
|
-
|
|
431
|
-
const subFrameLength = squished[squishedIndex + 1];
|
|
432
|
-
const subFrame = squished.slice(squishedIndex + 2, squishedIndex + subFrameLength);
|
|
101
|
+
const sortedSpecKeys = sortSpecKeys();
|
|
433
102
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
const
|
|
440
|
-
|
|
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
|
-
|
|
450
|
-
let squishedPieces = [];
|
|
114
|
+
let nodeClassCode = CONSTRUCTOR_TO_TYPE[entity.constructor.name];
|
|
451
115
|
|
|
452
|
-
for (
|
|
453
|
-
|
|
454
|
-
|
|
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 +
|
|
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 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
|
+
};
|