pxt-common-packages 10.4.4 → 10.4.6
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/built/common-sim.d.ts +18 -0
- package/built/common-sim.js +285 -0
- package/libs/azureiot/built/debug/binary.js +461 -461
- package/libs/color/built/debug/binary.js +8 -8
- package/libs/{game/docs/reference/scene → color-coded-tilemap/docs/reference/color-coded-tilemap}/get-tile.md +3 -3
- package/libs/color-coded-tilemap/docs/reference/color-coded-tilemap/get-tiles-by-type.md +65 -0
- package/libs/{game/docs/reference/scene → color-coded-tilemap/docs/reference/color-coded-tilemap}/on-hit-tile.md +4 -4
- package/libs/color-coded-tilemap/docs/reference/color-coded-tilemap/place-on-random-tile.md +61 -0
- package/libs/{game/docs/reference/scene → color-coded-tilemap/docs/reference/color-coded-tilemap}/place.md +2 -6
- package/libs/color-coded-tilemap/docs/reference/color-coded-tilemap/set-tile-at.md +61 -0
- package/libs/{game/docs/reference/scene → color-coded-tilemap/docs/reference/color-coded-tilemap}/set-tile-map.md +3 -3
- package/libs/{game/docs/reference/scene → color-coded-tilemap/docs/reference/color-coded-tilemap}/set-tile.md +1 -1
- package/libs/{game/docs/reference/scene → color-coded-tilemap/docs/reference/color-coded-tilemap}/tile-map.md +2 -2
- package/libs/{game/docs/types → color-coded-tilemap/docs/reference/color-coded-tilemap}/tile.md +9 -5
- package/libs/color-coded-tilemap/docs/reference/color-coded-tilemap.md +32 -0
- package/libs/color-coded-tilemap/tilemap.ts +7 -7
- package/libs/color-sensor/built/debug/binary.js +8 -8
- package/libs/controller/built/debug/binary.js +7118 -7118
- package/libs/controller---none/built/debug/binary.js +7098 -7098
- package/libs/datalogger/built/debug/binary.js +63 -63
- package/libs/edge-connector/built/debug/binary.js +8 -8
- package/libs/edge-connector/docs/reference/edge-connector.md +5 -0
- package/libs/esp32/built/debug/binary.js +462 -462
- package/libs/feather/docs/reference/feather.md +11 -0
- package/libs/game/_locales/game-jsdoc-strings.json +1 -0
- package/libs/game/built/debug/binary.js +7037 -7037
- package/libs/game/docs/reference/game/set-game-over-effect.md +47 -0
- package/libs/game/docs/reference/game/set-game-over-message.md +47 -0
- package/libs/game/docs/reference/game/set-game-over-playable.md +48 -0
- package/libs/game/docs/reference/game/set-game-over-scoring-type.md +78 -0
- package/libs/game/docs/reference/game.md +8 -0
- package/libs/game/game.ts +24 -0
- package/libs/game/info.ts +18 -8
- package/libs/lcd/built/debug/binary.js +8 -8
- package/libs/light-spectrum-sensor/built/debug/binary.js +8 -8
- package/libs/lora/built/debug/binary.js +8 -8
- package/libs/matrix-keypad/built/debug/binary.js +8 -8
- package/libs/mixer/docs/reference/music/create-song.md +38 -0
- package/libs/mixer/docs/reference/music/melody-playable.md +30 -0
- package/libs/mixer/docs/reference/music/play.md +132 -0
- package/libs/mixer/docs/reference/music/song-editor.md +92 -0
- package/libs/mixer/docs/reference/music/string-playable.md +41 -0
- package/libs/mixer/docs/reference/music/tone-playable.md +30 -0
- package/libs/mixer/docs/reference/music.md +12 -7
- package/libs/mixer/docs/types/playable.md +76 -0
- package/libs/mixer/instrument.ts +28 -9
- package/libs/mixer/melody.cpp +43 -0
- package/libs/mixer/melody.ts +1 -0
- package/libs/mixer/playable.ts +4 -0
- package/libs/mixer/sequencer.ts +116 -0
- package/libs/mixer/sim/music.ts +102 -0
- package/libs/mqtt/built/debug/binary.js +176 -176
- package/libs/multiplayer/player.ts +1 -0
- package/libs/net/built/debug/binary.js +176 -176
- package/libs/net-game/built/debug/binary.js +8626 -8626
- package/libs/palette/built/debug/binary.js +7036 -7036
- package/libs/pixel/built/debug/binary.js +8 -8
- package/libs/power/built/debug/binary.js +8 -8
- package/libs/proximity/built/debug/binary.js +8 -8
- package/libs/radio/built/debug/binary.js +8 -8
- package/libs/radio-broadcast/built/debug/binary.js +8 -8
- package/libs/rotary-encoder/built/debug/binary.js +8 -8
- package/libs/screen/_locales/screen-jsdoc-strings.json +2 -0
- package/libs/screen/built/debug/binary.js +50 -50
- package/libs/screen/image.cpp +226 -0
- package/libs/screen/image.ts +44 -0
- package/libs/screen/sim/image.ts +240 -0
- package/libs/servo/built/debug/binary.js +8 -8
- package/libs/sprite-scaling/_locales/sprite-scaling-jsdoc-strings.json +18 -1
- package/libs/sprite-scaling/_locales/sprite-scaling-strings.json +1 -0
- package/libs/sprite-scaling/built/debug/binary.js +7036 -7036
- package/libs/sprite-scaling/docs/reference/sprite-scaling.md +23 -0
- package/libs/sprite-scaling/docs/reference/sprites/scaling/scale-by-pixels.md +1 -1
- package/libs/sprite-scaling/docs/reference/sprites/scaling/scale-to-pixels.md +1 -1
- package/libs/sprite-scaling/scaling.ts +24 -0
- package/libs/storyboard/built/debug/binary.js +7036 -7036
- package/package.json +2 -2
package/libs/screen/image.cpp
CHANGED
|
@@ -1159,6 +1159,232 @@ void _fillCircle(Image_ img, int cxy, int r, int c) {
|
|
|
1159
1159
|
fillCircle(img, XX(cxy), YY(cxy), r, c);
|
|
1160
1160
|
}
|
|
1161
1161
|
|
|
1162
|
+
typedef struct
|
|
1163
|
+
{
|
|
1164
|
+
int x, y;
|
|
1165
|
+
int x0, y0;
|
|
1166
|
+
int x1, y1;
|
|
1167
|
+
int W,H;
|
|
1168
|
+
int dx, dy;
|
|
1169
|
+
int yi, xi;
|
|
1170
|
+
int D;
|
|
1171
|
+
int nextFuncIndex;
|
|
1172
|
+
} LineGenState; // For keeping track of the state when generating Y values for a line, even when moving to the next X.
|
|
1173
|
+
|
|
1174
|
+
typedef struct
|
|
1175
|
+
{
|
|
1176
|
+
int min;
|
|
1177
|
+
int max;
|
|
1178
|
+
} ValueRange;
|
|
1179
|
+
|
|
1180
|
+
void nextYRange_Low(int x, LineGenState *line, ValueRange *yRange) {
|
|
1181
|
+
while (line->x == x && line->x <= line->x1 && line->x < line->W) {
|
|
1182
|
+
if (0 <= line->x) {
|
|
1183
|
+
if (line->y < yRange->min) yRange->min = line->y;
|
|
1184
|
+
if (line->y > yRange->max) yRange->max = line->y;
|
|
1185
|
+
}
|
|
1186
|
+
if (line->D > 0) {
|
|
1187
|
+
line->y += line->yi;
|
|
1188
|
+
line->D -= line->dx;
|
|
1189
|
+
}
|
|
1190
|
+
line->D += line->dy;
|
|
1191
|
+
++line->x;
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
void nextYRange_HighUp(int x, LineGenState *line, ValueRange *yRange) {
|
|
1196
|
+
while (line->x == x && line->y >= line->y1 && line->x < line->W) {
|
|
1197
|
+
if (0 <= line->x) {
|
|
1198
|
+
if (line->y < yRange->min) yRange->min = line->y;
|
|
1199
|
+
if (line->y > yRange->max) yRange->max = line->y;
|
|
1200
|
+
}
|
|
1201
|
+
if (line->D > 0) {
|
|
1202
|
+
line->x += line->xi;
|
|
1203
|
+
line->D += line->dy;
|
|
1204
|
+
}
|
|
1205
|
+
line->D += line->dx;
|
|
1206
|
+
--line->y;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
// This function is similar to the sub-function drawLineHigh for drawLine. However, it yields back after calculating all Y values of a given X. When the function is called again, it continues from the state where it yielded back previously.
|
|
1210
|
+
void nextYRange_HighDown(int x, LineGenState *line, ValueRange *yRange) {
|
|
1211
|
+
while (line->x == x && line->y <= line->y1 && line->x < line->W) {
|
|
1212
|
+
if (0 <= line->x) {
|
|
1213
|
+
if (line->y < yRange->min) yRange->min = line->y;
|
|
1214
|
+
if (line->y > yRange->max) yRange->max = line->y;
|
|
1215
|
+
}
|
|
1216
|
+
if (line->D > 0) {
|
|
1217
|
+
line->x += line->xi;
|
|
1218
|
+
line->D -= line->dy;
|
|
1219
|
+
}
|
|
1220
|
+
line->D += line->dx;
|
|
1221
|
+
++line->y;
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
LineGenState initYRangeGenerator(int16_t X0, int16_t Y0, int16_t X1, int16_t Y1) {
|
|
1226
|
+
LineGenState line;
|
|
1227
|
+
|
|
1228
|
+
line.x0 = X0, line.y0 = Y0, line.x1 = X1, line.y1 = Y1;
|
|
1229
|
+
|
|
1230
|
+
line.dx = line.x1 - line.x0;
|
|
1231
|
+
line.dy = line.y1 - line.y0;
|
|
1232
|
+
line.y = line.y0;
|
|
1233
|
+
line.x = line.x0;
|
|
1234
|
+
|
|
1235
|
+
if ((line.dy < 0 ? -line.dy : line.dy) < line.dx) {
|
|
1236
|
+
line.yi = 1;
|
|
1237
|
+
if (line.dy < 0) {
|
|
1238
|
+
line.yi = -1;
|
|
1239
|
+
line.dy = -line.dy;
|
|
1240
|
+
}
|
|
1241
|
+
line.D = 2 * line.dy - line.dx;
|
|
1242
|
+
line.dx <<= 1;
|
|
1243
|
+
line.dy <<= 1;
|
|
1244
|
+
|
|
1245
|
+
line.nextFuncIndex = 0;
|
|
1246
|
+
return line;
|
|
1247
|
+
} else {
|
|
1248
|
+
line.xi = 1;
|
|
1249
|
+
// if (dx < 0) {//should not hit
|
|
1250
|
+
// PANIC();
|
|
1251
|
+
// }
|
|
1252
|
+
if (line.dy < 0) {
|
|
1253
|
+
line.D = 2 * line.dx + line.dy;
|
|
1254
|
+
line.dx <<= 1;
|
|
1255
|
+
line.dy <<= 1;
|
|
1256
|
+
|
|
1257
|
+
line.nextFuncIndex = 1;
|
|
1258
|
+
return line;
|
|
1259
|
+
} else {
|
|
1260
|
+
line.D = 2 * line.dx - line.dy;
|
|
1261
|
+
line.dx <<= 1;
|
|
1262
|
+
line.dy <<= 1;
|
|
1263
|
+
|
|
1264
|
+
line.nextFuncIndex = 2;
|
|
1265
|
+
return line;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
void fillTriangle(Image_ img, int x0, int y0, int x1, int y1, int x2, int y2, int c) {
|
|
1271
|
+
if (x1 < x0) {
|
|
1272
|
+
swap(x0, x1);
|
|
1273
|
+
swap(y0, y1);
|
|
1274
|
+
}
|
|
1275
|
+
if (x2 < x1) {
|
|
1276
|
+
swap(x1, x2);
|
|
1277
|
+
swap(y1, y2);
|
|
1278
|
+
}
|
|
1279
|
+
if (x1 < x0) {
|
|
1280
|
+
swap(x0, x1);
|
|
1281
|
+
swap(y0, y1);
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
LineGenState lines[] = {
|
|
1285
|
+
initYRangeGenerator(x0, y0, x2, y2),
|
|
1286
|
+
initYRangeGenerator(x0, y0, x1, y1),
|
|
1287
|
+
initYRangeGenerator(x1, y1, x2, y2)
|
|
1288
|
+
};
|
|
1289
|
+
|
|
1290
|
+
lines[0].W = lines[1].W = lines[2].W = width(img);
|
|
1291
|
+
lines[0].H = lines[1].H = lines[2].H = height(img);
|
|
1292
|
+
|
|
1293
|
+
// We have 3 different sub-functions to generate Ys of edges, each particular edge maps to one of them.
|
|
1294
|
+
// Use function pointers to avoid judging which function to call at every X.
|
|
1295
|
+
typedef void (*FP_NEXT)(int x, LineGenState *line, ValueRange *yRange);
|
|
1296
|
+
FP_NEXT nextFuncList[] = { nextYRange_Low, nextYRange_HighUp, nextYRange_HighDown };
|
|
1297
|
+
FP_NEXT fpNext0 = nextFuncList[lines[0].nextFuncIndex];
|
|
1298
|
+
FP_NEXT fpNext1 = nextFuncList[lines[1].nextFuncIndex];
|
|
1299
|
+
FP_NEXT fpNext2 = nextFuncList[lines[2].nextFuncIndex];
|
|
1300
|
+
|
|
1301
|
+
ValueRange yRange={lines[0].H,-1};
|
|
1302
|
+
|
|
1303
|
+
for (int x = lines[1].x0; x <= lines[1].x1; x++) {
|
|
1304
|
+
yRange.min = lines[0].H; yRange.max = -1;
|
|
1305
|
+
fpNext0(x, &lines[0], &yRange);
|
|
1306
|
+
fpNext1(x, &lines[1], &yRange);
|
|
1307
|
+
fillRect(img, x, yRange.min, 1, yRange.max - yRange.min + 1, c);
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
fpNext2(lines[2].x0, &lines[2], &yRange);
|
|
1311
|
+
|
|
1312
|
+
for (int x = lines[2].x0 + 1; x <= lines[2].x1; x++) {
|
|
1313
|
+
yRange.min = lines[0].H; yRange.max = -1;
|
|
1314
|
+
fpNext0(x, &lines[0], &yRange);
|
|
1315
|
+
fpNext2(x, &lines[2], &yRange);
|
|
1316
|
+
fillRect(img, x, yRange.min, 1, yRange.max - yRange.min + 1, c);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
void fillPolygon4(Image_ img, int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, int c) {
|
|
1321
|
+
LineGenState lines[] = {
|
|
1322
|
+
(x0 < x1) ? initYRangeGenerator(x0, y0, x1, y1) : initYRangeGenerator(x1, y1, x0, y0),
|
|
1323
|
+
(x1 < x2) ? initYRangeGenerator(x1, y1, x2, y2) : initYRangeGenerator(x2, y2, x1, y1),
|
|
1324
|
+
(x2 < x3) ? initYRangeGenerator(x2, y2, x3, y3) : initYRangeGenerator(x3, y3, x2, y2),
|
|
1325
|
+
(x0 < x3) ? initYRangeGenerator(x0, y0, x3, y3) : initYRangeGenerator(x3, y3, x0, y0)};
|
|
1326
|
+
|
|
1327
|
+
lines[0].W = lines[1].W = lines[2].W = lines[3].W = width(img);
|
|
1328
|
+
lines[0].H = lines[1].H = lines[2].H = lines[3].H = height(img);
|
|
1329
|
+
|
|
1330
|
+
int minX = min(min(x0, x1), min(x2, x3));
|
|
1331
|
+
int maxX = min(max(max(x0, x1), max(x2, x3)), lines[0].W - 1);
|
|
1332
|
+
|
|
1333
|
+
typedef void (*FP_NEXT)(int x, LineGenState *line, ValueRange *yRange);
|
|
1334
|
+
FP_NEXT nextFuncList[] = { nextYRange_Low, nextYRange_HighUp, nextYRange_HighDown };
|
|
1335
|
+
FP_NEXT fpNext0 = nextFuncList[lines[0].nextFuncIndex];
|
|
1336
|
+
FP_NEXT fpNext1 = nextFuncList[lines[1].nextFuncIndex];
|
|
1337
|
+
FP_NEXT fpNext2 = nextFuncList[lines[2].nextFuncIndex];
|
|
1338
|
+
FP_NEXT fpNext3 = nextFuncList[lines[3].nextFuncIndex];
|
|
1339
|
+
|
|
1340
|
+
ValueRange yRange = { lines[0].H, -1 };
|
|
1341
|
+
|
|
1342
|
+
for (int x = minX; x <= maxX; x++) {
|
|
1343
|
+
yRange.min = lines[0].H; yRange.max = -1;
|
|
1344
|
+
fpNext0(x, &lines[0], &yRange);
|
|
1345
|
+
fpNext1(x, &lines[1], &yRange);
|
|
1346
|
+
fpNext2(x, &lines[2], &yRange);
|
|
1347
|
+
fpNext3(x, &lines[3], &yRange);
|
|
1348
|
+
fillRect(img, x,yRange.min, 1, yRange.max - yRange.min + 1, c);
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
//%
|
|
1353
|
+
void _fillTriangle(Image_ img, pxt::RefCollection *args) {
|
|
1354
|
+
fillTriangle(
|
|
1355
|
+
img,
|
|
1356
|
+
pxt::toInt(args->getAt(0)),
|
|
1357
|
+
pxt::toInt(args->getAt(1)),
|
|
1358
|
+
pxt::toInt(args->getAt(2)),
|
|
1359
|
+
pxt::toInt(args->getAt(3)),
|
|
1360
|
+
pxt::toInt(args->getAt(4)),
|
|
1361
|
+
pxt::toInt(args->getAt(5)),
|
|
1362
|
+
pxt::toInt(args->getAt(6))
|
|
1363
|
+
);
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
// This polygon fill is similar to fillTriangle(): Scan minY and maxY of all edges at each X, and draw a vertical line between (x,minY)~(x,maxY).
|
|
1367
|
+
// The main difference is that it sorts the endpoints of each edge, x0 < x1, to draw from left to right, but doesn't sort the edges as it's too time consuming.
|
|
1368
|
+
// Instead, just call next(), which returns immediately if the x is not in range of the edge in horizon.
|
|
1369
|
+
// NOTE: Unlike triangles, edges of a polygon can cross a vertical line at a given X multi time. This algorithm can fill correctly only if edges meet this condition: Any vertical line(x) cross edges at most 2 times.
|
|
1370
|
+
// Fortunately, no matter what perspective transform is applied, a rectangle/trapezoid will still meet this condition.
|
|
1371
|
+
// Ref: https://forum.makecode.com/t/new-3d-engine-help-filling-4-sided-polygons/18641/9
|
|
1372
|
+
//%
|
|
1373
|
+
void _fillPolygon4(Image_ img, pxt::RefCollection *args) {
|
|
1374
|
+
fillPolygon4(
|
|
1375
|
+
img,
|
|
1376
|
+
pxt::toInt(args->getAt(0)),
|
|
1377
|
+
pxt::toInt(args->getAt(1)),
|
|
1378
|
+
pxt::toInt(args->getAt(2)),
|
|
1379
|
+
pxt::toInt(args->getAt(3)),
|
|
1380
|
+
pxt::toInt(args->getAt(4)),
|
|
1381
|
+
pxt::toInt(args->getAt(5)),
|
|
1382
|
+
pxt::toInt(args->getAt(6)),
|
|
1383
|
+
pxt::toInt(args->getAt(7)),
|
|
1384
|
+
pxt::toInt(args->getAt(8))
|
|
1385
|
+
);
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1162
1388
|
} // namespace ImageMethods
|
|
1163
1389
|
|
|
1164
1390
|
namespace image {
|
package/libs/screen/image.ts
CHANGED
|
@@ -67,6 +67,18 @@ interface Image {
|
|
|
67
67
|
//% helper=imageFillCircle
|
|
68
68
|
fillCircle(cx: number, cy: number, r: number, c: color): void;
|
|
69
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Fills a triangle
|
|
72
|
+
*/
|
|
73
|
+
//% helper=imageFillTriangle
|
|
74
|
+
fillTriangle(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, col: number): void;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Fills a 4-side-polygon
|
|
78
|
+
*/
|
|
79
|
+
//% helper=imageFillPolygon4
|
|
80
|
+
fillPolygon4(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, col: number): void;
|
|
81
|
+
|
|
70
82
|
/**
|
|
71
83
|
* Returns an image rotated by -90, 0, 90, 180, 270 deg clockwise
|
|
72
84
|
*/
|
|
@@ -128,6 +140,12 @@ namespace helpers {
|
|
|
128
140
|
//% shim=ImageMethods::_blit
|
|
129
141
|
declare function _blit(img: Image, src: Image, args: number[]): boolean;
|
|
130
142
|
|
|
143
|
+
//% shim=ImageMethods::_fillTriangle
|
|
144
|
+
declare function _fillTriangle(img: Image, args: number[]): void;
|
|
145
|
+
|
|
146
|
+
//% shim=ImageMethods::_fillPolygon4
|
|
147
|
+
declare function _fillPolygon4(img: Image, args: number[]): void;
|
|
148
|
+
|
|
131
149
|
function pack(x: number, y: number) {
|
|
132
150
|
return (Math.clamp(-30000, 30000, x | 0) & 0xffff) | (Math.clamp(-30000, 30000, y | 0) << 16)
|
|
133
151
|
}
|
|
@@ -211,6 +229,32 @@ namespace helpers {
|
|
|
211
229
|
_fillCircle(img, pack(cx, cy), r, col);
|
|
212
230
|
}
|
|
213
231
|
|
|
232
|
+
export function imageFillTriangle(img: Image, x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, col: number) {
|
|
233
|
+
_blitArgs = _blitArgs || [];
|
|
234
|
+
_blitArgs[0] = x0;
|
|
235
|
+
_blitArgs[1] = y0;
|
|
236
|
+
_blitArgs[2] = x1;
|
|
237
|
+
_blitArgs[3] = y1;
|
|
238
|
+
_blitArgs[4] = x2;
|
|
239
|
+
_blitArgs[5] = y2;
|
|
240
|
+
_blitArgs[6] = col;
|
|
241
|
+
_fillTriangle(img, _blitArgs);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function imageFillPolygon4(img: Image, x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, col: number) {
|
|
245
|
+
_blitArgs = _blitArgs || [];
|
|
246
|
+
_blitArgs[0] = x0;
|
|
247
|
+
_blitArgs[1] = y0;
|
|
248
|
+
_blitArgs[2] = x1;
|
|
249
|
+
_blitArgs[3] = y1;
|
|
250
|
+
_blitArgs[4] = x2;
|
|
251
|
+
_blitArgs[5] = y2;
|
|
252
|
+
_blitArgs[6] = x3;
|
|
253
|
+
_blitArgs[7] = y3;
|
|
254
|
+
_blitArgs[8] = col;
|
|
255
|
+
_fillPolygon4(img, _blitArgs);
|
|
256
|
+
}
|
|
257
|
+
|
|
214
258
|
/**
|
|
215
259
|
* Returns an image rotated by 90, 180, 270 deg clockwise
|
|
216
260
|
*/
|
package/libs/screen/sim/image.ts
CHANGED
|
@@ -612,6 +612,246 @@ namespace pxsim.ImageMethods {
|
|
|
612
612
|
fillCircle(img, XX(cxy), YY(cxy), r, c);
|
|
613
613
|
}
|
|
614
614
|
|
|
615
|
+
interface LineGenState {
|
|
616
|
+
x: number;
|
|
617
|
+
y: number;
|
|
618
|
+
x0: number;
|
|
619
|
+
y0: number;
|
|
620
|
+
x1: number;
|
|
621
|
+
y1: number;
|
|
622
|
+
W: number;
|
|
623
|
+
H: number;
|
|
624
|
+
dx: number;
|
|
625
|
+
dy: number;
|
|
626
|
+
yi: number;
|
|
627
|
+
xi: number;
|
|
628
|
+
D: number;
|
|
629
|
+
nextFuncIndex: number;
|
|
630
|
+
}
|
|
631
|
+
interface ValueRange {
|
|
632
|
+
min: number;
|
|
633
|
+
max: number;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function nextYRange_Low(x: number, line: LineGenState, yRange: ValueRange) {
|
|
637
|
+
while (line.x === x && line.x <= line.x1 && line.x < line.W) {
|
|
638
|
+
if (0 <= line.x) {
|
|
639
|
+
if (line.y < yRange.min) yRange.min = line.y;
|
|
640
|
+
if (line.y > yRange.max) yRange.max = line.y
|
|
641
|
+
}
|
|
642
|
+
if (line.D > 0) {
|
|
643
|
+
line.y += line.yi;
|
|
644
|
+
line.D -= line.dx;
|
|
645
|
+
}
|
|
646
|
+
line.D += line.dy;
|
|
647
|
+
++line.x;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function nextYRange_HighUp(x: number, line: LineGenState, yRange: ValueRange) {
|
|
652
|
+
while (line.x == x && line.y >= line.y1 && line.x < line.W) {
|
|
653
|
+
if (0 <= line.x) {
|
|
654
|
+
if (line.y < yRange.min) yRange.min = line.y;
|
|
655
|
+
if (line.y > yRange.max) yRange.max = line.y;
|
|
656
|
+
}
|
|
657
|
+
if (line.D > 0) {
|
|
658
|
+
line.x += line.xi;
|
|
659
|
+
line.D += line.dy;
|
|
660
|
+
}
|
|
661
|
+
line.D += line.dx;
|
|
662
|
+
--line.y;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
function nextYRange_HighDown(x: number, line: LineGenState, yRange: ValueRange) {
|
|
667
|
+
while (line.x == x && line.y <= line.y1 && line.x < line.W) {
|
|
668
|
+
if (0 <= line.x) {
|
|
669
|
+
if (line.y < yRange.min) yRange.min = line.y;
|
|
670
|
+
if (line.y > yRange.max) yRange.max = line.y;
|
|
671
|
+
}
|
|
672
|
+
if (line.D > 0) {
|
|
673
|
+
line.x += line.xi;
|
|
674
|
+
line.D -= line.dy;
|
|
675
|
+
}
|
|
676
|
+
line.D += line.dx;
|
|
677
|
+
++line.y;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
function initYRangeGenerator(X0: number, Y0: number, X1: number, Y1: number): LineGenState {
|
|
682
|
+
const line: LineGenState = {
|
|
683
|
+
x: X0,
|
|
684
|
+
y: Y0,
|
|
685
|
+
x0: X0,
|
|
686
|
+
y0: Y0,
|
|
687
|
+
x1: X1,
|
|
688
|
+
y1: Y1,
|
|
689
|
+
W: 0,
|
|
690
|
+
H: 0,
|
|
691
|
+
dx: X1 - X0,
|
|
692
|
+
dy: Y1 - Y0,
|
|
693
|
+
yi: 0,
|
|
694
|
+
xi: 0,
|
|
695
|
+
D: 0,
|
|
696
|
+
nextFuncIndex: 0,
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
if ((line.dy < 0 ? -line.dy : line.dy) < line.dx) {
|
|
700
|
+
line.yi = 1;
|
|
701
|
+
if (line.dy < 0) {
|
|
702
|
+
line.yi = -1;
|
|
703
|
+
line.dy = -line.dy;
|
|
704
|
+
}
|
|
705
|
+
line.D = 2 * line.dy - line.dx;
|
|
706
|
+
line.dx = line.dx << 1;
|
|
707
|
+
line.dy = line.dy << 1;
|
|
708
|
+
|
|
709
|
+
line.nextFuncIndex = 0;
|
|
710
|
+
return line;
|
|
711
|
+
} else {
|
|
712
|
+
line.xi = 1;
|
|
713
|
+
if (line.dy < 0) {
|
|
714
|
+
line.D = 2 * line.dx + line.dy;
|
|
715
|
+
line.dx = line.dx << 1;
|
|
716
|
+
line.dy = line.dy << 1;
|
|
717
|
+
|
|
718
|
+
line.nextFuncIndex = 1;
|
|
719
|
+
return line;
|
|
720
|
+
} else {
|
|
721
|
+
line.D = 2 * line.dx - line.dy;
|
|
722
|
+
line.dx = line.dx << 1;
|
|
723
|
+
line.dy = line.dy << 1;
|
|
724
|
+
|
|
725
|
+
line.nextFuncIndex = 2;
|
|
726
|
+
return line;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
export function fillTriangle(img: RefImage, x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, c: number) {
|
|
732
|
+
if (x1 < x0) {
|
|
733
|
+
[x1, x0] = [x0, x1];
|
|
734
|
+
[y1, y0] = [y0, y1];
|
|
735
|
+
}
|
|
736
|
+
if (x2 < x1) {
|
|
737
|
+
[x2, x1] = [x1, x2];
|
|
738
|
+
[y2, y1] = [y1, y2];
|
|
739
|
+
}
|
|
740
|
+
if (x1 < x0) {
|
|
741
|
+
[x1, x0] = [x0, x1];
|
|
742
|
+
[y1, y0] = [y0, y1];
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
const lines: LineGenState[] = [
|
|
746
|
+
initYRangeGenerator(x0, y0, x2, y2),
|
|
747
|
+
initYRangeGenerator(x0, y0, x1, y1),
|
|
748
|
+
initYRangeGenerator(x1, y1, x2, y2)
|
|
749
|
+
];
|
|
750
|
+
|
|
751
|
+
lines[0].W = lines[1].W = lines[2].W = width(img);
|
|
752
|
+
lines[0].H = lines[1].H = lines[2].H = height(img);
|
|
753
|
+
|
|
754
|
+
type FP_NEXT = (x: number, line: LineGenState, yRange: ValueRange) => void;
|
|
755
|
+
const nextFuncList: FP_NEXT[] = [
|
|
756
|
+
nextYRange_Low,
|
|
757
|
+
nextYRange_HighUp,
|
|
758
|
+
nextYRange_HighDown
|
|
759
|
+
];
|
|
760
|
+
const fpNext0 = nextFuncList[lines[0].nextFuncIndex];
|
|
761
|
+
const fpNext1 = nextFuncList[lines[1].nextFuncIndex];
|
|
762
|
+
const fpNext2 = nextFuncList[lines[2].nextFuncIndex];
|
|
763
|
+
|
|
764
|
+
const yRange= {
|
|
765
|
+
min: lines[0].H,
|
|
766
|
+
max: -1
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
for (let x = lines[1].x0; x <= lines[1].x1; x++) {
|
|
770
|
+
yRange.min = lines[0].H; yRange.max = -1;
|
|
771
|
+
fpNext0(x, lines[0], yRange);
|
|
772
|
+
fpNext1(x, lines[1], yRange);
|
|
773
|
+
fillRect(img, x, yRange.min, 1, yRange.max - yRange.min + 1, c);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
fpNext2(lines[2].x0, lines[2], yRange);
|
|
777
|
+
|
|
778
|
+
for (let x = lines[2].x0 + 1; x <= lines[2].x1; x++) {
|
|
779
|
+
yRange.min = lines[0].H; yRange.max = -1;
|
|
780
|
+
fpNext0(x, lines[0], yRange);
|
|
781
|
+
fpNext2(x, lines[2], yRange);
|
|
782
|
+
fillRect(img, x, yRange.min, 1, yRange.max - yRange.min + 1, c);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
export function _fillTriangle(img: RefImage, args: RefCollection) {
|
|
787
|
+
fillTriangle(
|
|
788
|
+
img,
|
|
789
|
+
args.getAt(0) | 0,
|
|
790
|
+
args.getAt(1) | 0,
|
|
791
|
+
args.getAt(2) | 0,
|
|
792
|
+
args.getAt(3) | 0,
|
|
793
|
+
args.getAt(4) | 0,
|
|
794
|
+
args.getAt(5) | 0,
|
|
795
|
+
args.getAt(6) | 0,
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
export function fillPolygon4(img: RefImage, x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, c: number) {
|
|
800
|
+
const lines: LineGenState[]= [
|
|
801
|
+
(x0 < x1) ? initYRangeGenerator(x0, y0, x1, y1) : initYRangeGenerator(x1, y1, x0, y0),
|
|
802
|
+
(x1 < x2) ? initYRangeGenerator(x1, y1, x2, y2) : initYRangeGenerator(x2, y2, x1, y1),
|
|
803
|
+
(x2 < x3) ? initYRangeGenerator(x2, y2, x3, y3) : initYRangeGenerator(x3, y3, x2, y2),
|
|
804
|
+
(x0 < x3) ? initYRangeGenerator(x0, y0, x3, y3) : initYRangeGenerator(x3, y3, x0, y0)
|
|
805
|
+
];
|
|
806
|
+
|
|
807
|
+
lines[0].W = lines[1].W = lines[2].W = lines[3].W = width(img);
|
|
808
|
+
lines[0].H = lines[1].H = lines[2].H = lines[3].H = height(img);
|
|
809
|
+
|
|
810
|
+
let minX = Math.min(Math.min(x0, x1), Math.min(x2, x3));
|
|
811
|
+
let maxX = Math.min(Math.max(Math.max(x0, x1), Math.max(x2, x3)), lines[0].W - 1);
|
|
812
|
+
|
|
813
|
+
type FP_NEXT = (x: number, line: LineGenState, yRange: ValueRange) => void;
|
|
814
|
+
const nextFuncList: FP_NEXT[] = [
|
|
815
|
+
nextYRange_Low,
|
|
816
|
+
nextYRange_HighUp,
|
|
817
|
+
nextYRange_HighDown
|
|
818
|
+
];
|
|
819
|
+
|
|
820
|
+
const fpNext0 = nextFuncList[lines[0].nextFuncIndex];
|
|
821
|
+
const fpNext1 = nextFuncList[lines[1].nextFuncIndex];
|
|
822
|
+
const fpNext2 = nextFuncList[lines[2].nextFuncIndex];
|
|
823
|
+
const fpNext3 = nextFuncList[lines[3].nextFuncIndex];
|
|
824
|
+
|
|
825
|
+
const yRange: ValueRange = {
|
|
826
|
+
min: lines[0].H,
|
|
827
|
+
max: -1
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
for (let x = minX; x <= maxX; x++) {
|
|
831
|
+
yRange.min = lines[0].H; yRange.max = -1;
|
|
832
|
+
fpNext0(x, lines[0], yRange);
|
|
833
|
+
fpNext1(x, lines[1], yRange);
|
|
834
|
+
fpNext2(x, lines[2], yRange);
|
|
835
|
+
fpNext3(x, lines[3], yRange);
|
|
836
|
+
fillRect(img, x,yRange.min, 1, yRange.max - yRange.min + 1, c);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
export function _fillPolygon4(img: RefImage, args: RefCollection) {
|
|
841
|
+
fillPolygon4(
|
|
842
|
+
img,
|
|
843
|
+
args.getAt(0) | 0,
|
|
844
|
+
args.getAt(1) | 0,
|
|
845
|
+
args.getAt(2) | 0,
|
|
846
|
+
args.getAt(3) | 0,
|
|
847
|
+
args.getAt(4) | 0,
|
|
848
|
+
args.getAt(5) | 0,
|
|
849
|
+
args.getAt(6) | 0,
|
|
850
|
+
args.getAt(7) | 0,
|
|
851
|
+
args.getAt(8) | 0,
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
|
|
615
855
|
export function _blitRow(img: RefImage, xy: number, from: RefImage, xh: number) {
|
|
616
856
|
blitRow(img, XX(xy), YY(xy), from, XX(xh), YY(xh))
|
|
617
857
|
}
|
|
@@ -56,7 +56,7 @@ const pxsim_pxtrt = pxsim.pxtrt;
|
|
|
56
56
|
const pxsim_numops = pxsim.numops;
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
function
|
|
59
|
+
function _main___P52847(s) {
|
|
60
60
|
let r0 = s.r0, step = s.pc;
|
|
61
61
|
s.pc = -1;
|
|
62
62
|
|
|
@@ -66,19 +66,19 @@ if (yieldSteps-- < 0 && maybeYield(s, step, r0) || runtime !== pxsim.runtime) re
|
|
|
66
66
|
switch (step) {
|
|
67
67
|
case 0:
|
|
68
68
|
|
|
69
|
-
globals.
|
|
70
|
-
globals.
|
|
69
|
+
globals._intervals___53090 = (undefined);
|
|
70
|
+
globals._pollEventQueue___53103 = (undefined);
|
|
71
71
|
r0 = undefined;
|
|
72
72
|
return leave(s, r0)
|
|
73
73
|
default: oops()
|
|
74
74
|
} } }
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
_main___P52847.info = {"start":0,"length":0,"line":0,"column":0,"endLine":0,"endColumn":0,"fileName":"targetoverrides.ts","functionName":"<main>","argumentNames":[]}
|
|
76
|
+
_main___P52847.continuations = [ ]
|
|
77
77
|
|
|
78
|
-
function
|
|
78
|
+
function _main___P52847_mk(s) {
|
|
79
79
|
checkStack(s.depth);
|
|
80
80
|
return {
|
|
81
|
-
parent: s, fn:
|
|
81
|
+
parent: s, fn: _main___P52847, depth: s.depth + 1,
|
|
82
82
|
pc: 0, retval: undefined, r0: undefined, overwrittenPC: false, lambdaArgs: null,
|
|
83
83
|
} }
|
|
84
84
|
|
|
@@ -88,5 +88,5 @@ function _main___P52784_mk(s) {
|
|
|
88
88
|
|
|
89
89
|
const breakpoints = setupDebugger(1, [])
|
|
90
90
|
|
|
91
|
-
return
|
|
91
|
+
return _main___P52847
|
|
92
92
|
})
|
|
@@ -1 +1,18 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"scaling.scaleByPercent": "Scale a sprite by a percentage of its original size.",
|
|
3
|
+
"scaling.scaleByPercent|param|direction": "from the sprite anchor point, eg: ScaleDirection.Uniformly",
|
|
4
|
+
"scaling.scaleByPercent|param|sprite": "to scale to a percentage of its original size",
|
|
5
|
+
"scaling.scaleByPercent|param|value": "that is the percentage to scale the sprite by, eg: 50",
|
|
6
|
+
"scaling.scaleByPixels": "Scale a sprite by a number of pixels.",
|
|
7
|
+
"scaling.scaleByPixels|param|direction": "from the sprite anchor point, eg: ScaleDirection.Horizontally",
|
|
8
|
+
"scaling.scaleByPixels|param|sprite": "to scale to new pixel size",
|
|
9
|
+
"scaling.scaleByPixels|param|value": "that is the number of pixels to scale the sprite by, eg: 10",
|
|
10
|
+
"scaling.scaleToPercent": "Scale a sprite to a percentage of its original size.",
|
|
11
|
+
"scaling.scaleToPercent|param|direction": "from the sprite anchor point, eg: ScaleDirection.Uniformly",
|
|
12
|
+
"scaling.scaleToPercent|param|sprite": "to scale to a percentage of its original size",
|
|
13
|
+
"scaling.scaleToPercent|param|value": "that is the percentage to scale the sprite, eg: 150",
|
|
14
|
+
"scaling.scaleToPixels": "Scale a sprite to a number of pixels.",
|
|
15
|
+
"scaling.scaleToPixels|param|direction": "from the sprite anchor point, eg: ScaleDirection.Horizontally",
|
|
16
|
+
"scaling.scaleToPixels|param|sprite": "to scale to new pixel size",
|
|
17
|
+
"scaling.scaleToPixels|param|value": "that is the number of pixels to scale the sprite to, eg: 32"
|
|
18
|
+
}
|
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
"scaling.scaleByPixels|block": "change $sprite=variables_get(mySprite) scale by $value pixels $direction anchor $anchor || proportional $proportional",
|
|
4
4
|
"scaling.scaleToPercent|block": "set $sprite=variables_get(mySprite) scale to $value percent $direction anchor $anchor",
|
|
5
5
|
"scaling.scaleToPixels|block": "set $sprite=variables_get(mySprite) scale to $value pixels $direction anchor $anchor || proportional $proportional",
|
|
6
|
+
"scaling|block": "scaling",
|
|
6
7
|
"{id:category}Scaling": "Scaling"
|
|
7
8
|
}
|