@routevn/creator-model 1.1.12 → 1.2.0
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/README.md +17 -0
- package/package.json +1 -1
- package/src/model.js +840 -15
package/README.md
CHANGED
|
@@ -210,6 +210,11 @@ See also:
|
|
|
210
210
|
|
|
211
211
|
- [docs/schema-compatibility.md](./docs/schema-compatibility.md)
|
|
212
212
|
|
|
213
|
+
Current animation update tween properties support either:
|
|
214
|
+
|
|
215
|
+
- `keyframes`
|
|
216
|
+
- `auto: { duration, easing }`
|
|
217
|
+
|
|
213
218
|
## Current Scope
|
|
214
219
|
|
|
215
220
|
Currently implemented command types:
|
|
@@ -232,6 +237,10 @@ Currently implemented command types:
|
|
|
232
237
|
- `image.update`
|
|
233
238
|
- `image.delete`
|
|
234
239
|
- `image.move`
|
|
240
|
+
- `spritesheet.create`
|
|
241
|
+
- `spritesheet.update`
|
|
242
|
+
- `spritesheet.delete`
|
|
243
|
+
- `spritesheet.move`
|
|
235
244
|
- `sound.create`
|
|
236
245
|
- `sound.update`
|
|
237
246
|
- `sound.delete`
|
|
@@ -280,6 +289,14 @@ Currently implemented command types:
|
|
|
280
289
|
- `layout.element.update`
|
|
281
290
|
- `layout.element.delete`
|
|
282
291
|
- `layout.element.move`
|
|
292
|
+
- `control.create`
|
|
293
|
+
- `control.update`
|
|
294
|
+
- `control.delete`
|
|
295
|
+
- `control.move`
|
|
296
|
+
- `control.element.create`
|
|
297
|
+
- `control.element.update`
|
|
298
|
+
- `control.element.delete`
|
|
299
|
+
- `control.element.move`
|
|
283
300
|
|
|
284
301
|
The rest of the future command surface should be added only when full
|
|
285
302
|
validation, preconditions, reducer behavior, and tests are added together.
|
package/package.json
CHANGED
package/src/model.js
CHANGED
|
@@ -21,6 +21,7 @@ const COLLECTION_KEYS = [
|
|
|
21
21
|
"scenes",
|
|
22
22
|
"files",
|
|
23
23
|
"images",
|
|
24
|
+
"spritesheets",
|
|
24
25
|
"sounds",
|
|
25
26
|
"videos",
|
|
26
27
|
"animations",
|
|
@@ -44,14 +45,23 @@ const normalizeStateCollections = (state) => {
|
|
|
44
45
|
return state;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
const missingCollectionKeys = ["spritesheets", "controls"].filter(
|
|
49
|
+
(key) => state[key] === undefined,
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
if (missingCollectionKeys.length === 0) {
|
|
48
53
|
return state;
|
|
49
54
|
}
|
|
50
55
|
|
|
51
|
-
|
|
56
|
+
const nextState = {
|
|
52
57
|
...state,
|
|
53
|
-
controls: createEmptyCollectionState(),
|
|
54
58
|
};
|
|
59
|
+
|
|
60
|
+
missingCollectionKeys.forEach((key) => {
|
|
61
|
+
nextState[key] = createEmptyCollectionState();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return nextState;
|
|
55
65
|
};
|
|
56
66
|
const isString = (value) => typeof value === "string";
|
|
57
67
|
const isHexColor = (value) =>
|
|
@@ -125,6 +135,7 @@ const LAYOUT_ELEMENT_BASE_TYPES = [
|
|
|
125
135
|
"container",
|
|
126
136
|
"rect",
|
|
127
137
|
"sprite",
|
|
138
|
+
"spritesheet-animation",
|
|
128
139
|
"text",
|
|
129
140
|
"text-revealing",
|
|
130
141
|
"slider",
|
|
@@ -145,7 +156,7 @@ const LAYOUT_ELEMENT_BASE_TYPES = [
|
|
|
145
156
|
"container-ref-confirm-dialog-ok",
|
|
146
157
|
"container-ref-confirm-dialog-cancel",
|
|
147
158
|
];
|
|
148
|
-
export const SCHEMA_VERSION =
|
|
159
|
+
export const SCHEMA_VERSION = 2;
|
|
149
160
|
const LAYOUT_CONTAINER_ELEMENT_TYPES = [
|
|
150
161
|
"folder",
|
|
151
162
|
"container",
|
|
@@ -853,6 +864,207 @@ const validateImageItems = ({ items, path, errorFactory }) => {
|
|
|
853
864
|
}
|
|
854
865
|
};
|
|
855
866
|
|
|
867
|
+
const validateSpritesheetAnimationMap = ({
|
|
868
|
+
animations,
|
|
869
|
+
path,
|
|
870
|
+
errorFactory,
|
|
871
|
+
}) => {
|
|
872
|
+
if (!isPlainObject(animations)) {
|
|
873
|
+
return invalidFromErrorFactory(errorFactory, `${path} must be an object`);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
for (const [animationName, animation] of Object.entries(animations)) {
|
|
877
|
+
const animationPath = `${path}.${animationName}`;
|
|
878
|
+
|
|
879
|
+
if (!isNonEmptyString(animationName)) {
|
|
880
|
+
return invalidFromErrorFactory(
|
|
881
|
+
errorFactory,
|
|
882
|
+
`${animationPath} must use a non-empty animation name`,
|
|
883
|
+
);
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
{
|
|
887
|
+
const result = validateAllowedKeys({
|
|
888
|
+
value: animation,
|
|
889
|
+
allowedKeys: ["frames", "animationSpeed", "loop"],
|
|
890
|
+
path: animationPath,
|
|
891
|
+
errorFactory,
|
|
892
|
+
});
|
|
893
|
+
if (result?.valid === false) {
|
|
894
|
+
return result;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
if (!Array.isArray(animation.frames)) {
|
|
899
|
+
return invalidFromErrorFactory(
|
|
900
|
+
errorFactory,
|
|
901
|
+
`${animationPath}.frames must be an array`,
|
|
902
|
+
);
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
for (let index = 0; index < animation.frames.length; index += 1) {
|
|
906
|
+
const frame = animation.frames[index];
|
|
907
|
+
if (!Number.isInteger(frame) || frame < 0) {
|
|
908
|
+
return invalidFromErrorFactory(
|
|
909
|
+
errorFactory,
|
|
910
|
+
`${animationPath}.frames.${index} must be an integer greater than or equal to 0`,
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
if (
|
|
916
|
+
animation.animationSpeed !== undefined &&
|
|
917
|
+
!isFiniteNumber(animation.animationSpeed)
|
|
918
|
+
) {
|
|
919
|
+
return invalidFromErrorFactory(
|
|
920
|
+
errorFactory,
|
|
921
|
+
`${animationPath}.animationSpeed must be a finite number when provided`,
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
if (animation.loop !== undefined && typeof animation.loop !== "boolean") {
|
|
926
|
+
return invalidFromErrorFactory(
|
|
927
|
+
errorFactory,
|
|
928
|
+
`${animationPath}.loop must be a boolean when provided`,
|
|
929
|
+
);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
return VALID_RESULT;
|
|
934
|
+
};
|
|
935
|
+
|
|
936
|
+
const validateSpritesheetItems = ({ items, path, errorFactory }) => {
|
|
937
|
+
for (const [itemId, item] of Object.entries(items)) {
|
|
938
|
+
const itemPath = `${path}.${itemId}`;
|
|
939
|
+
|
|
940
|
+
if (item?.type !== "folder" && item?.type !== "spritesheet") {
|
|
941
|
+
return invalidFromErrorFactory(
|
|
942
|
+
errorFactory,
|
|
943
|
+
`${itemPath}.type must be 'folder' or 'spritesheet'`,
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
{
|
|
948
|
+
const result = validateAllowedKeys({
|
|
949
|
+
value: item,
|
|
950
|
+
allowedKeys:
|
|
951
|
+
item.type === "folder"
|
|
952
|
+
? ["id", "type", "name", "description"]
|
|
953
|
+
: [
|
|
954
|
+
"id",
|
|
955
|
+
"type",
|
|
956
|
+
"name",
|
|
957
|
+
"description",
|
|
958
|
+
"thumbnailFileId",
|
|
959
|
+
"fileId",
|
|
960
|
+
"fileType",
|
|
961
|
+
"fileSize",
|
|
962
|
+
"sheetWidth",
|
|
963
|
+
"sheetHeight",
|
|
964
|
+
"frameCount",
|
|
965
|
+
"width",
|
|
966
|
+
"height",
|
|
967
|
+
"jsonData",
|
|
968
|
+
"animations",
|
|
969
|
+
],
|
|
970
|
+
path: itemPath,
|
|
971
|
+
errorFactory,
|
|
972
|
+
});
|
|
973
|
+
if (result?.valid === false) {
|
|
974
|
+
return result;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
if (!isNonEmptyString(item.id)) {
|
|
979
|
+
return invalidFromErrorFactory(
|
|
980
|
+
errorFactory,
|
|
981
|
+
`${itemPath}.id must be a non-empty string`,
|
|
982
|
+
);
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
if (item.id !== itemId) {
|
|
986
|
+
return invalidFromErrorFactory(
|
|
987
|
+
errorFactory,
|
|
988
|
+
`${itemPath}.id must match item key '${itemId}'`,
|
|
989
|
+
);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
if (!isNonEmptyString(item.name)) {
|
|
993
|
+
return invalidFromErrorFactory(
|
|
994
|
+
errorFactory,
|
|
995
|
+
`${itemPath}.name must be a non-empty string`,
|
|
996
|
+
);
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
if (item.description !== undefined && !isString(item.description)) {
|
|
1000
|
+
return invalidFromErrorFactory(
|
|
1001
|
+
errorFactory,
|
|
1002
|
+
`${itemPath}.description must be a string when provided`,
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
if (item.type === "spritesheet") {
|
|
1007
|
+
if (
|
|
1008
|
+
item.thumbnailFileId !== undefined &&
|
|
1009
|
+
!isNonEmptyString(item.thumbnailFileId)
|
|
1010
|
+
) {
|
|
1011
|
+
return invalidFromErrorFactory(
|
|
1012
|
+
errorFactory,
|
|
1013
|
+
`${itemPath}.thumbnailFileId must be a non-empty string when provided`,
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
if (!isNonEmptyString(item.fileId)) {
|
|
1018
|
+
return invalidFromErrorFactory(
|
|
1019
|
+
errorFactory,
|
|
1020
|
+
`${itemPath}.fileId must be a non-empty string`,
|
|
1021
|
+
);
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
if (item.fileType !== undefined && !isString(item.fileType)) {
|
|
1025
|
+
return invalidFromErrorFactory(
|
|
1026
|
+
errorFactory,
|
|
1027
|
+
`${itemPath}.fileType must be a string when provided`,
|
|
1028
|
+
);
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
for (const key of [
|
|
1032
|
+
"fileSize",
|
|
1033
|
+
"sheetWidth",
|
|
1034
|
+
"sheetHeight",
|
|
1035
|
+
"frameCount",
|
|
1036
|
+
"width",
|
|
1037
|
+
"height",
|
|
1038
|
+
]) {
|
|
1039
|
+
if (item[key] !== undefined && !isFiniteNumber(item[key])) {
|
|
1040
|
+
return invalidFromErrorFactory(
|
|
1041
|
+
errorFactory,
|
|
1042
|
+
`${itemPath}.${key} must be a finite number when provided`,
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
if (!isPlainObject(item.jsonData)) {
|
|
1048
|
+
return invalidFromErrorFactory(
|
|
1049
|
+
errorFactory,
|
|
1050
|
+
`${itemPath}.jsonData must be an object`,
|
|
1051
|
+
);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
{
|
|
1055
|
+
const result = validateSpritesheetAnimationMap({
|
|
1056
|
+
animations: item.animations,
|
|
1057
|
+
path: `${itemPath}.animations`,
|
|
1058
|
+
errorFactory,
|
|
1059
|
+
});
|
|
1060
|
+
if (result?.valid === false) {
|
|
1061
|
+
return result;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
};
|
|
1067
|
+
|
|
856
1068
|
const validateSoundItems = ({ items, path, errorFactory }) => {
|
|
857
1069
|
for (const [itemId, item] of Object.entries(items)) {
|
|
858
1070
|
const itemPath = `${path}.${itemId}`;
|
|
@@ -1141,16 +1353,57 @@ const validateAnimationKeyframes = ({ keyframes, path, errorFactory }) => {
|
|
|
1141
1353
|
}
|
|
1142
1354
|
};
|
|
1143
1355
|
|
|
1356
|
+
const validateAutoTweenProperty = ({ auto, path, errorFactory }) => {
|
|
1357
|
+
{
|
|
1358
|
+
const result = validateAllowedKeys({
|
|
1359
|
+
value: auto,
|
|
1360
|
+
allowedKeys: ["duration", "easing"],
|
|
1361
|
+
path,
|
|
1362
|
+
errorFactory,
|
|
1363
|
+
});
|
|
1364
|
+
if (result?.valid === false) {
|
|
1365
|
+
return result;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
if (!("duration" in auto)) {
|
|
1370
|
+
return invalidFromErrorFactory(
|
|
1371
|
+
errorFactory,
|
|
1372
|
+
`${path}.duration is required`,
|
|
1373
|
+
);
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
if (!isFiniteNumber(auto.duration) || auto.duration < 1) {
|
|
1377
|
+
return invalidFromErrorFactory(
|
|
1378
|
+
errorFactory,
|
|
1379
|
+
`${path}.duration must be a finite number >= 1`,
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
if (
|
|
1384
|
+
auto.easing !== undefined &&
|
|
1385
|
+
!ANIMATION_EASING_KEYS.includes(auto.easing)
|
|
1386
|
+
) {
|
|
1387
|
+
return invalidFromErrorFactory(
|
|
1388
|
+
errorFactory,
|
|
1389
|
+
`${path}.easing must be a supported Route Graphics easing`,
|
|
1390
|
+
);
|
|
1391
|
+
}
|
|
1392
|
+
};
|
|
1393
|
+
|
|
1144
1394
|
const validateTweenProperty = ({
|
|
1145
1395
|
config,
|
|
1146
1396
|
path,
|
|
1147
1397
|
allowEmptyKeyframes = false,
|
|
1398
|
+
allowAuto = false,
|
|
1148
1399
|
errorFactory,
|
|
1149
1400
|
}) => {
|
|
1150
1401
|
{
|
|
1151
1402
|
const result = validateAllowedKeys({
|
|
1152
1403
|
value: config,
|
|
1153
|
-
allowedKeys:
|
|
1404
|
+
allowedKeys: allowAuto
|
|
1405
|
+
? ["initialValue", "keyframes", "auto"]
|
|
1406
|
+
: ["initialValue", "keyframes"],
|
|
1154
1407
|
path,
|
|
1155
1408
|
errorFactory,
|
|
1156
1409
|
});
|
|
@@ -1159,10 +1412,20 @@ const validateTweenProperty = ({
|
|
|
1159
1412
|
}
|
|
1160
1413
|
}
|
|
1161
1414
|
|
|
1162
|
-
|
|
1415
|
+
const hasKeyframes = "keyframes" in config;
|
|
1416
|
+
const hasAuto = "auto" in config;
|
|
1417
|
+
|
|
1418
|
+
if (!hasKeyframes && !hasAuto) {
|
|
1419
|
+
return invalidFromErrorFactory(
|
|
1420
|
+
errorFactory,
|
|
1421
|
+
`${path}.keyframes or ${path}.auto is required`,
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
if (hasKeyframes && hasAuto) {
|
|
1163
1426
|
return invalidFromErrorFactory(
|
|
1164
1427
|
errorFactory,
|
|
1165
|
-
`${path}.keyframes
|
|
1428
|
+
`${path}.keyframes and ${path}.auto cannot both be defined`,
|
|
1166
1429
|
);
|
|
1167
1430
|
}
|
|
1168
1431
|
|
|
@@ -1176,6 +1439,28 @@ const validateTweenProperty = ({
|
|
|
1176
1439
|
);
|
|
1177
1440
|
}
|
|
1178
1441
|
|
|
1442
|
+
if (hasAuto) {
|
|
1443
|
+
if (config.initialValue !== undefined) {
|
|
1444
|
+
return invalidFromErrorFactory(
|
|
1445
|
+
errorFactory,
|
|
1446
|
+
`${path}.initialValue is not supported when ${path}.auto is defined`,
|
|
1447
|
+
);
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
{
|
|
1451
|
+
const result = validateAutoTweenProperty({
|
|
1452
|
+
auto: config.auto,
|
|
1453
|
+
path: `${path}.auto`,
|
|
1454
|
+
errorFactory,
|
|
1455
|
+
});
|
|
1456
|
+
if (result?.valid === false) {
|
|
1457
|
+
return result;
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
return;
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1179
1464
|
{
|
|
1180
1465
|
const result = validateAnimationKeyframes({
|
|
1181
1466
|
keyframes: config.keyframes,
|
|
@@ -1201,6 +1486,7 @@ const validateTweenDefinition = ({
|
|
|
1201
1486
|
path,
|
|
1202
1487
|
unsupportedMessage,
|
|
1203
1488
|
allowEmptyKeyframes = false,
|
|
1489
|
+
allowAuto = false,
|
|
1204
1490
|
errorFactory,
|
|
1205
1491
|
}) => {
|
|
1206
1492
|
if (!isPlainObject(tween)) {
|
|
@@ -1229,6 +1515,7 @@ const validateTweenDefinition = ({
|
|
|
1229
1515
|
config,
|
|
1230
1516
|
path: propertyPath,
|
|
1231
1517
|
allowEmptyKeyframes,
|
|
1518
|
+
allowAuto,
|
|
1232
1519
|
errorFactory,
|
|
1233
1520
|
});
|
|
1234
1521
|
if (result?.valid === false) {
|
|
@@ -1547,6 +1834,8 @@ const validateAnimationDefinition = ({ animation, path, errorFactory }) => {
|
|
|
1547
1834
|
allowedProperties: UPDATE_TWEEN_PROPERTY_KEYS,
|
|
1548
1835
|
path: `${path}.tween`,
|
|
1549
1836
|
unsupportedMessage: "is not a supported update tween property",
|
|
1837
|
+
allowEmptyKeyframes: true,
|
|
1838
|
+
allowAuto: true,
|
|
1550
1839
|
errorFactory,
|
|
1551
1840
|
});
|
|
1552
1841
|
if (result?.valid === false) {
|
|
@@ -2486,6 +2775,8 @@ const validateLayoutElementData = ({
|
|
|
2486
2775
|
"textStyle",
|
|
2487
2776
|
"displaySpeed",
|
|
2488
2777
|
"revealEffect",
|
|
2778
|
+
"resourceId",
|
|
2779
|
+
"animationName",
|
|
2489
2780
|
"imageId",
|
|
2490
2781
|
"hoverImageId",
|
|
2491
2782
|
"clickImageId",
|
|
@@ -2607,6 +2898,8 @@ const validateLayoutElementData = ({
|
|
|
2607
2898
|
|
|
2608
2899
|
for (const key of [
|
|
2609
2900
|
"text",
|
|
2901
|
+
"resourceId",
|
|
2902
|
+
"animationName",
|
|
2610
2903
|
"imageId",
|
|
2611
2904
|
"hoverImageId",
|
|
2612
2905
|
"clickImageId",
|
|
@@ -2633,6 +2926,28 @@ const validateLayoutElementData = ({
|
|
|
2633
2926
|
}
|
|
2634
2927
|
}
|
|
2635
2928
|
|
|
2929
|
+
if (data.type === "spritesheet-animation") {
|
|
2930
|
+
if (
|
|
2931
|
+
(!allowPartial || data.resourceId !== undefined) &&
|
|
2932
|
+
!isNonEmptyString(data.resourceId)
|
|
2933
|
+
) {
|
|
2934
|
+
return invalidFromErrorFactory(
|
|
2935
|
+
errorFactory,
|
|
2936
|
+
`${path}.resourceId must be a non-empty string`,
|
|
2937
|
+
);
|
|
2938
|
+
}
|
|
2939
|
+
|
|
2940
|
+
if (
|
|
2941
|
+
(!allowPartial || data.animationName !== undefined) &&
|
|
2942
|
+
!isNonEmptyString(data.animationName)
|
|
2943
|
+
) {
|
|
2944
|
+
return invalidFromErrorFactory(
|
|
2945
|
+
errorFactory,
|
|
2946
|
+
`${path}.animationName must be a non-empty string`,
|
|
2947
|
+
);
|
|
2948
|
+
}
|
|
2949
|
+
}
|
|
2950
|
+
|
|
2636
2951
|
if (data.conditionalOverrides !== undefined) {
|
|
2637
2952
|
if (!Array.isArray(data.conditionalOverrides)) {
|
|
2638
2953
|
return invalidFromErrorFactory(
|
|
@@ -2982,6 +3297,8 @@ const validateLayoutElementItems = ({ items, path, errorFactory }) => {
|
|
|
2982
3297
|
"textStyle",
|
|
2983
3298
|
"displaySpeed",
|
|
2984
3299
|
"revealEffect",
|
|
3300
|
+
"resourceId",
|
|
3301
|
+
"animationName",
|
|
2985
3302
|
"imageId",
|
|
2986
3303
|
"hoverImageId",
|
|
2987
3304
|
"clickImageId",
|
|
@@ -3888,6 +4205,17 @@ const validateCollection = ({ collection, path }) => {
|
|
|
3888
4205
|
return result;
|
|
3889
4206
|
}
|
|
3890
4207
|
}
|
|
4208
|
+
} else if (path === "state.spritesheets") {
|
|
4209
|
+
{
|
|
4210
|
+
const result = validateSpritesheetItems({
|
|
4211
|
+
items: collection.items,
|
|
4212
|
+
path: `${path}.items`,
|
|
4213
|
+
errorFactory: createStateValidationError,
|
|
4214
|
+
});
|
|
4215
|
+
if (result?.valid === false) {
|
|
4216
|
+
return result;
|
|
4217
|
+
}
|
|
4218
|
+
}
|
|
3891
4219
|
} else if (path === "state.files") {
|
|
3892
4220
|
{
|
|
3893
4221
|
const result = validateFileItems({
|
|
@@ -4061,6 +4389,18 @@ const validateCollection = ({ collection, path }) => {
|
|
|
4061
4389
|
return result;
|
|
4062
4390
|
}
|
|
4063
4391
|
}
|
|
4392
|
+
} else if (path === "state.spritesheets") {
|
|
4393
|
+
{
|
|
4394
|
+
const result = validateGenericFolderOwnership({
|
|
4395
|
+
nodes: collection.tree,
|
|
4396
|
+
items: collection.items,
|
|
4397
|
+
path: `${path}.tree`,
|
|
4398
|
+
folderLabel: "folder spritesheet item",
|
|
4399
|
+
});
|
|
4400
|
+
if (result?.valid === false) {
|
|
4401
|
+
return result;
|
|
4402
|
+
}
|
|
4403
|
+
}
|
|
4064
4404
|
} else if (path === "state.sounds") {
|
|
4065
4405
|
{
|
|
4066
4406
|
const result = validateSoundTreeFolderOwnership({
|
|
@@ -4417,13 +4757,50 @@ export const assertInvariants = ({ state }) => {
|
|
|
4417
4757
|
}
|
|
4418
4758
|
}
|
|
4419
4759
|
|
|
4420
|
-
for (const [
|
|
4421
|
-
|
|
4760
|
+
for (const [spritesheetId, spritesheet] of Object.entries(
|
|
4761
|
+
state.spritesheets.items,
|
|
4762
|
+
)) {
|
|
4763
|
+
if (spritesheet.type !== "spritesheet") {
|
|
4422
4764
|
continue;
|
|
4423
4765
|
}
|
|
4424
4766
|
|
|
4425
|
-
{
|
|
4426
|
-
|
|
4767
|
+
const result = validateFileReference({
|
|
4768
|
+
state,
|
|
4769
|
+
fileId: spritesheet.fileId,
|
|
4770
|
+
path: "spritesheet.fileId",
|
|
4771
|
+
details: { spritesheetId, fileId: spritesheet.fileId },
|
|
4772
|
+
errorFactory: createInvariantValidationError,
|
|
4773
|
+
});
|
|
4774
|
+
if (!result.valid) {
|
|
4775
|
+
return result;
|
|
4776
|
+
}
|
|
4777
|
+
|
|
4778
|
+
if (spritesheet.thumbnailFileId === undefined) {
|
|
4779
|
+
continue;
|
|
4780
|
+
}
|
|
4781
|
+
|
|
4782
|
+
const thumbnailResult = validateFileReference({
|
|
4783
|
+
state,
|
|
4784
|
+
fileId: spritesheet.thumbnailFileId,
|
|
4785
|
+
path: "spritesheet.thumbnailFileId",
|
|
4786
|
+
details: {
|
|
4787
|
+
spritesheetId,
|
|
4788
|
+
thumbnailFileId: spritesheet.thumbnailFileId,
|
|
4789
|
+
},
|
|
4790
|
+
errorFactory: createInvariantValidationError,
|
|
4791
|
+
});
|
|
4792
|
+
if (!thumbnailResult.valid) {
|
|
4793
|
+
return thumbnailResult;
|
|
4794
|
+
}
|
|
4795
|
+
}
|
|
4796
|
+
|
|
4797
|
+
for (const [soundId, sound] of Object.entries(state.sounds.items)) {
|
|
4798
|
+
if (sound.type !== "sound") {
|
|
4799
|
+
continue;
|
|
4800
|
+
}
|
|
4801
|
+
|
|
4802
|
+
{
|
|
4803
|
+
const result = validateFileReference({
|
|
4427
4804
|
state,
|
|
4428
4805
|
fileId: sound.fileId,
|
|
4429
4806
|
path: "sound.fileId",
|
|
@@ -4708,6 +5085,45 @@ export const assertInvariants = ({ state }) => {
|
|
|
4708
5085
|
return VALID_RESULT;
|
|
4709
5086
|
};
|
|
4710
5087
|
|
|
5088
|
+
const assertSpritesheetAnimationReference = ({
|
|
5089
|
+
ownerIdField,
|
|
5090
|
+
ownerId,
|
|
5091
|
+
ownerLabel,
|
|
5092
|
+
elementId,
|
|
5093
|
+
targetId,
|
|
5094
|
+
animationName,
|
|
5095
|
+
}) => {
|
|
5096
|
+
const spritesheet = state.spritesheets?.items?.[targetId];
|
|
5097
|
+
if (!isPlainObject(spritesheet) || spritesheet.type === "folder") {
|
|
5098
|
+
return invalidInvariant(
|
|
5099
|
+
`${ownerLabel} element resourceId must reference an existing non-folder spritesheet`,
|
|
5100
|
+
{
|
|
5101
|
+
[ownerIdField]: ownerId,
|
|
5102
|
+
elementId,
|
|
5103
|
+
field: "resourceId",
|
|
5104
|
+
targetId,
|
|
5105
|
+
},
|
|
5106
|
+
);
|
|
5107
|
+
}
|
|
5108
|
+
|
|
5109
|
+
if (
|
|
5110
|
+
!isNonEmptyString(animationName) ||
|
|
5111
|
+
!isPlainObject(spritesheet.animations?.[animationName])
|
|
5112
|
+
) {
|
|
5113
|
+
return invalidInvariant(
|
|
5114
|
+
`${ownerLabel} element animationName must reference an existing spritesheet animation`,
|
|
5115
|
+
{
|
|
5116
|
+
[ownerIdField]: ownerId,
|
|
5117
|
+
elementId,
|
|
5118
|
+
field: "animationName",
|
|
5119
|
+
targetId: animationName,
|
|
5120
|
+
},
|
|
5121
|
+
);
|
|
5122
|
+
}
|
|
5123
|
+
|
|
5124
|
+
return VALID_RESULT;
|
|
5125
|
+
};
|
|
5126
|
+
|
|
4711
5127
|
const assertElementReferencesForCollection = ({
|
|
4712
5128
|
items,
|
|
4713
5129
|
ownerIdField,
|
|
@@ -4720,6 +5136,24 @@ export const assertInvariants = ({ state }) => {
|
|
|
4720
5136
|
}
|
|
4721
5137
|
|
|
4722
5138
|
for (const [elementId, element] of Object.entries(owner.elements.items)) {
|
|
5139
|
+
if (
|
|
5140
|
+
element.type === "spritesheet-animation" ||
|
|
5141
|
+
element.resourceId !== undefined ||
|
|
5142
|
+
element.animationName !== undefined
|
|
5143
|
+
) {
|
|
5144
|
+
const result = assertSpritesheetAnimationReference({
|
|
5145
|
+
ownerIdField,
|
|
5146
|
+
ownerId,
|
|
5147
|
+
ownerLabel,
|
|
5148
|
+
elementId,
|
|
5149
|
+
targetId: element.resourceId,
|
|
5150
|
+
animationName: element.animationName,
|
|
5151
|
+
});
|
|
5152
|
+
if (!result.valid) {
|
|
5153
|
+
return result;
|
|
5154
|
+
}
|
|
5155
|
+
}
|
|
5156
|
+
|
|
4723
5157
|
for (const field of [
|
|
4724
5158
|
"imageId",
|
|
4725
5159
|
"hoverImageId",
|
|
@@ -5460,6 +5894,233 @@ const validateImageUpdateData = ({ data, errorFactory }) => {
|
|
|
5460
5894
|
}
|
|
5461
5895
|
};
|
|
5462
5896
|
|
|
5897
|
+
const validateSpritesheetCreateData = ({ data, errorFactory }) => {
|
|
5898
|
+
if (!isPlainObject(data)) {
|
|
5899
|
+
return invalidFromErrorFactory(
|
|
5900
|
+
errorFactory,
|
|
5901
|
+
"payload.data must be an object",
|
|
5902
|
+
);
|
|
5903
|
+
}
|
|
5904
|
+
|
|
5905
|
+
if (data.type !== "folder" && data.type !== "spritesheet") {
|
|
5906
|
+
return invalidFromErrorFactory(
|
|
5907
|
+
errorFactory,
|
|
5908
|
+
"payload.data.type must be 'folder' or 'spritesheet'",
|
|
5909
|
+
);
|
|
5910
|
+
}
|
|
5911
|
+
|
|
5912
|
+
{
|
|
5913
|
+
const result = validateAllowedKeys({
|
|
5914
|
+
value: data,
|
|
5915
|
+
allowedKeys:
|
|
5916
|
+
data.type === "folder"
|
|
5917
|
+
? ["type", "name", "description"]
|
|
5918
|
+
: [
|
|
5919
|
+
"type",
|
|
5920
|
+
"name",
|
|
5921
|
+
"description",
|
|
5922
|
+
"thumbnailFileId",
|
|
5923
|
+
"fileId",
|
|
5924
|
+
"fileType",
|
|
5925
|
+
"fileSize",
|
|
5926
|
+
"sheetWidth",
|
|
5927
|
+
"sheetHeight",
|
|
5928
|
+
"frameCount",
|
|
5929
|
+
"width",
|
|
5930
|
+
"height",
|
|
5931
|
+
"jsonData",
|
|
5932
|
+
"animations",
|
|
5933
|
+
],
|
|
5934
|
+
path: "payload.data",
|
|
5935
|
+
errorFactory,
|
|
5936
|
+
});
|
|
5937
|
+
if (result?.valid === false) {
|
|
5938
|
+
return result;
|
|
5939
|
+
}
|
|
5940
|
+
}
|
|
5941
|
+
|
|
5942
|
+
if (!isNonEmptyString(data.name)) {
|
|
5943
|
+
return invalidFromErrorFactory(
|
|
5944
|
+
errorFactory,
|
|
5945
|
+
"payload.data.name must be a non-empty string",
|
|
5946
|
+
);
|
|
5947
|
+
}
|
|
5948
|
+
|
|
5949
|
+
if (data.description !== undefined && !isString(data.description)) {
|
|
5950
|
+
return invalidFromErrorFactory(
|
|
5951
|
+
errorFactory,
|
|
5952
|
+
"payload.data.description must be a string when provided",
|
|
5953
|
+
);
|
|
5954
|
+
}
|
|
5955
|
+
|
|
5956
|
+
if (data.type === "spritesheet") {
|
|
5957
|
+
if (
|
|
5958
|
+
data.thumbnailFileId !== undefined &&
|
|
5959
|
+
!isNonEmptyString(data.thumbnailFileId)
|
|
5960
|
+
) {
|
|
5961
|
+
return invalidFromErrorFactory(
|
|
5962
|
+
errorFactory,
|
|
5963
|
+
"payload.data.thumbnailFileId must be a non-empty string when provided",
|
|
5964
|
+
);
|
|
5965
|
+
}
|
|
5966
|
+
|
|
5967
|
+
if (!isNonEmptyString(data.fileId)) {
|
|
5968
|
+
return invalidFromErrorFactory(
|
|
5969
|
+
errorFactory,
|
|
5970
|
+
"payload.data.fileId must be a non-empty string",
|
|
5971
|
+
);
|
|
5972
|
+
}
|
|
5973
|
+
|
|
5974
|
+
if (data.fileType !== undefined && !isString(data.fileType)) {
|
|
5975
|
+
return invalidFromErrorFactory(
|
|
5976
|
+
errorFactory,
|
|
5977
|
+
"payload.data.fileType must be a string when provided",
|
|
5978
|
+
);
|
|
5979
|
+
}
|
|
5980
|
+
|
|
5981
|
+
for (const key of [
|
|
5982
|
+
"fileSize",
|
|
5983
|
+
"sheetWidth",
|
|
5984
|
+
"sheetHeight",
|
|
5985
|
+
"frameCount",
|
|
5986
|
+
"width",
|
|
5987
|
+
"height",
|
|
5988
|
+
]) {
|
|
5989
|
+
if (data[key] !== undefined && !isFiniteNumber(data[key])) {
|
|
5990
|
+
return invalidFromErrorFactory(
|
|
5991
|
+
errorFactory,
|
|
5992
|
+
`payload.data.${key} must be a finite number`,
|
|
5993
|
+
);
|
|
5994
|
+
}
|
|
5995
|
+
}
|
|
5996
|
+
|
|
5997
|
+
if (!isPlainObject(data.jsonData)) {
|
|
5998
|
+
return invalidFromErrorFactory(
|
|
5999
|
+
errorFactory,
|
|
6000
|
+
"payload.data.jsonData must be an object",
|
|
6001
|
+
);
|
|
6002
|
+
}
|
|
6003
|
+
|
|
6004
|
+
{
|
|
6005
|
+
const result = validateSpritesheetAnimationMap({
|
|
6006
|
+
animations: data.animations,
|
|
6007
|
+
path: "payload.data.animations",
|
|
6008
|
+
errorFactory,
|
|
6009
|
+
});
|
|
6010
|
+
if (result?.valid === false) {
|
|
6011
|
+
return result;
|
|
6012
|
+
}
|
|
6013
|
+
}
|
|
6014
|
+
}
|
|
6015
|
+
};
|
|
6016
|
+
|
|
6017
|
+
const validateSpritesheetUpdateData = ({ data, errorFactory }) => {
|
|
6018
|
+
{
|
|
6019
|
+
const result = validateAllowedKeys({
|
|
6020
|
+
value: data,
|
|
6021
|
+
allowedKeys: [
|
|
6022
|
+
"name",
|
|
6023
|
+
"description",
|
|
6024
|
+
"thumbnailFileId",
|
|
6025
|
+
"fileId",
|
|
6026
|
+
"fileType",
|
|
6027
|
+
"fileSize",
|
|
6028
|
+
"sheetWidth",
|
|
6029
|
+
"sheetHeight",
|
|
6030
|
+
"frameCount",
|
|
6031
|
+
"width",
|
|
6032
|
+
"height",
|
|
6033
|
+
"jsonData",
|
|
6034
|
+
"animations",
|
|
6035
|
+
],
|
|
6036
|
+
path: "payload.data",
|
|
6037
|
+
errorFactory,
|
|
6038
|
+
});
|
|
6039
|
+
if (result?.valid === false) {
|
|
6040
|
+
return result;
|
|
6041
|
+
}
|
|
6042
|
+
}
|
|
6043
|
+
|
|
6044
|
+
if (Object.keys(data).length === 0) {
|
|
6045
|
+
return invalidFromErrorFactory(
|
|
6046
|
+
errorFactory,
|
|
6047
|
+
"payload.data must include at least one updatable field",
|
|
6048
|
+
);
|
|
6049
|
+
}
|
|
6050
|
+
|
|
6051
|
+
if (data.name !== undefined && !isNonEmptyString(data.name)) {
|
|
6052
|
+
return invalidFromErrorFactory(
|
|
6053
|
+
errorFactory,
|
|
6054
|
+
"payload.data.name must be a non-empty string when provided",
|
|
6055
|
+
);
|
|
6056
|
+
}
|
|
6057
|
+
|
|
6058
|
+
if (data.description !== undefined && !isString(data.description)) {
|
|
6059
|
+
return invalidFromErrorFactory(
|
|
6060
|
+
errorFactory,
|
|
6061
|
+
"payload.data.description must be a string when provided",
|
|
6062
|
+
);
|
|
6063
|
+
}
|
|
6064
|
+
|
|
6065
|
+
if (
|
|
6066
|
+
data.thumbnailFileId !== undefined &&
|
|
6067
|
+
!isNonEmptyString(data.thumbnailFileId)
|
|
6068
|
+
) {
|
|
6069
|
+
return invalidFromErrorFactory(
|
|
6070
|
+
errorFactory,
|
|
6071
|
+
"payload.data.thumbnailFileId must be a non-empty string when provided",
|
|
6072
|
+
);
|
|
6073
|
+
}
|
|
6074
|
+
|
|
6075
|
+
if (data.fileId !== undefined && !isNonEmptyString(data.fileId)) {
|
|
6076
|
+
return invalidFromErrorFactory(
|
|
6077
|
+
errorFactory,
|
|
6078
|
+
"payload.data.fileId must be a non-empty string when provided",
|
|
6079
|
+
);
|
|
6080
|
+
}
|
|
6081
|
+
|
|
6082
|
+
if (data.fileType !== undefined && !isString(data.fileType)) {
|
|
6083
|
+
return invalidFromErrorFactory(
|
|
6084
|
+
errorFactory,
|
|
6085
|
+
"payload.data.fileType must be a string when provided",
|
|
6086
|
+
);
|
|
6087
|
+
}
|
|
6088
|
+
|
|
6089
|
+
for (const key of [
|
|
6090
|
+
"fileSize",
|
|
6091
|
+
"sheetWidth",
|
|
6092
|
+
"sheetHeight",
|
|
6093
|
+
"frameCount",
|
|
6094
|
+
"width",
|
|
6095
|
+
"height",
|
|
6096
|
+
]) {
|
|
6097
|
+
if (data[key] !== undefined && !isFiniteNumber(data[key])) {
|
|
6098
|
+
return invalidFromErrorFactory(
|
|
6099
|
+
errorFactory,
|
|
6100
|
+
`payload.data.${key} must be a finite number`,
|
|
6101
|
+
);
|
|
6102
|
+
}
|
|
6103
|
+
}
|
|
6104
|
+
|
|
6105
|
+
if (data.jsonData !== undefined && !isPlainObject(data.jsonData)) {
|
|
6106
|
+
return invalidFromErrorFactory(
|
|
6107
|
+
errorFactory,
|
|
6108
|
+
"payload.data.jsonData must be an object when provided",
|
|
6109
|
+
);
|
|
6110
|
+
}
|
|
6111
|
+
|
|
6112
|
+
if (data.animations !== undefined) {
|
|
6113
|
+
const result = validateSpritesheetAnimationMap({
|
|
6114
|
+
animations: data.animations,
|
|
6115
|
+
path: "payload.data.animations",
|
|
6116
|
+
errorFactory,
|
|
6117
|
+
});
|
|
6118
|
+
if (result?.valid === false) {
|
|
6119
|
+
return result;
|
|
6120
|
+
}
|
|
6121
|
+
}
|
|
6122
|
+
};
|
|
6123
|
+
|
|
5463
6124
|
const validateSoundCreateData = ({ data, errorFactory }) => {
|
|
5464
6125
|
if (!isPlainObject(data)) {
|
|
5465
6126
|
return invalidFromErrorFactory(
|
|
@@ -7433,6 +8094,42 @@ const validateVisualElementReferenceTargets = ({
|
|
|
7433
8094
|
state,
|
|
7434
8095
|
errorFactory,
|
|
7435
8096
|
}) => {
|
|
8097
|
+
if (
|
|
8098
|
+
data.type === "spritesheet-animation" ||
|
|
8099
|
+
data.resourceId !== undefined ||
|
|
8100
|
+
data.animationName !== undefined
|
|
8101
|
+
) {
|
|
8102
|
+
const spritesheet = state.spritesheets?.items?.[data.resourceId];
|
|
8103
|
+
if (!isPlainObject(spritesheet) || spritesheet.type === "folder") {
|
|
8104
|
+
return invalidFromErrorFactory(
|
|
8105
|
+
errorFactory,
|
|
8106
|
+
`${ownerLabel} element resourceId must reference an existing non-folder spritesheet`,
|
|
8107
|
+
{
|
|
8108
|
+
[ownerIdField]: ownerId,
|
|
8109
|
+
elementId,
|
|
8110
|
+
field: "resourceId",
|
|
8111
|
+
targetId: data.resourceId,
|
|
8112
|
+
},
|
|
8113
|
+
);
|
|
8114
|
+
}
|
|
8115
|
+
|
|
8116
|
+
if (
|
|
8117
|
+
!isNonEmptyString(data.animationName) ||
|
|
8118
|
+
!isPlainObject(spritesheet.animations?.[data.animationName])
|
|
8119
|
+
) {
|
|
8120
|
+
return invalidFromErrorFactory(
|
|
8121
|
+
errorFactory,
|
|
8122
|
+
`${ownerLabel} element animationName must reference an existing spritesheet animation`,
|
|
8123
|
+
{
|
|
8124
|
+
[ownerIdField]: ownerId,
|
|
8125
|
+
elementId,
|
|
8126
|
+
field: "animationName",
|
|
8127
|
+
targetId: data.animationName,
|
|
8128
|
+
},
|
|
8129
|
+
);
|
|
8130
|
+
}
|
|
8131
|
+
}
|
|
8132
|
+
|
|
7436
8133
|
if (data.imageId !== undefined) {
|
|
7437
8134
|
const image = state.images.items[data.imageId];
|
|
7438
8135
|
if (!isPlainObject(image) || image.type === "folder") {
|
|
@@ -8246,6 +8943,30 @@ const findReferencedFileUsage = ({ state, fileId }) => {
|
|
|
8246
8943
|
}
|
|
8247
8944
|
}
|
|
8248
8945
|
|
|
8946
|
+
for (const [spritesheetId, spritesheet] of Object.entries(
|
|
8947
|
+
state.spritesheets.items,
|
|
8948
|
+
)) {
|
|
8949
|
+
if (spritesheet.type !== "spritesheet") {
|
|
8950
|
+
continue;
|
|
8951
|
+
}
|
|
8952
|
+
|
|
8953
|
+
if (spritesheet.fileId === fileId) {
|
|
8954
|
+
return {
|
|
8955
|
+
kind: "spritesheet",
|
|
8956
|
+
field: "fileId",
|
|
8957
|
+
ownerId: spritesheetId,
|
|
8958
|
+
};
|
|
8959
|
+
}
|
|
8960
|
+
|
|
8961
|
+
if (spritesheet.thumbnailFileId === fileId) {
|
|
8962
|
+
return {
|
|
8963
|
+
kind: "spritesheet",
|
|
8964
|
+
field: "thumbnailFileId",
|
|
8965
|
+
ownerId: spritesheetId,
|
|
8966
|
+
};
|
|
8967
|
+
}
|
|
8968
|
+
}
|
|
8969
|
+
|
|
8249
8970
|
for (const [soundId, sound] of Object.entries(state.sounds.items)) {
|
|
8250
8971
|
if (sound.type !== "sound") {
|
|
8251
8972
|
continue;
|
|
@@ -8439,6 +9160,108 @@ const COMMAND_DEFINITIONS = [
|
|
|
8439
9160
|
}
|
|
8440
9161
|
},
|
|
8441
9162
|
}),
|
|
9163
|
+
...createFolderedCollectionCommandDefinitions({
|
|
9164
|
+
familyName: "spritesheet",
|
|
9165
|
+
collectionKey: "spritesheets",
|
|
9166
|
+
idField: "spritesheetId",
|
|
9167
|
+
itemLabel: "spritesheet item",
|
|
9168
|
+
createDataValidator: validateSpritesheetCreateData,
|
|
9169
|
+
updateDataValidator: validateSpritesheetUpdateData,
|
|
9170
|
+
createItem: ({ payload }) => ({
|
|
9171
|
+
id: payload.spritesheetId,
|
|
9172
|
+
type: payload.data.type,
|
|
9173
|
+
name: payload.data.name,
|
|
9174
|
+
...(payload.data.description !== undefined
|
|
9175
|
+
? {
|
|
9176
|
+
description: payload.data.description,
|
|
9177
|
+
}
|
|
9178
|
+
: {}),
|
|
9179
|
+
...(payload.data.type === "spritesheet"
|
|
9180
|
+
? {
|
|
9181
|
+
fileId: payload.data.fileId,
|
|
9182
|
+
...(payload.data.thumbnailFileId !== undefined
|
|
9183
|
+
? {
|
|
9184
|
+
thumbnailFileId: payload.data.thumbnailFileId,
|
|
9185
|
+
}
|
|
9186
|
+
: {}),
|
|
9187
|
+
...(payload.data.fileType !== undefined
|
|
9188
|
+
? {
|
|
9189
|
+
fileType: payload.data.fileType,
|
|
9190
|
+
}
|
|
9191
|
+
: {}),
|
|
9192
|
+
...(payload.data.fileSize !== undefined
|
|
9193
|
+
? {
|
|
9194
|
+
fileSize: payload.data.fileSize,
|
|
9195
|
+
}
|
|
9196
|
+
: {}),
|
|
9197
|
+
...(payload.data.sheetWidth !== undefined
|
|
9198
|
+
? {
|
|
9199
|
+
sheetWidth: payload.data.sheetWidth,
|
|
9200
|
+
}
|
|
9201
|
+
: {}),
|
|
9202
|
+
...(payload.data.sheetHeight !== undefined
|
|
9203
|
+
? {
|
|
9204
|
+
sheetHeight: payload.data.sheetHeight,
|
|
9205
|
+
}
|
|
9206
|
+
: {}),
|
|
9207
|
+
...(payload.data.frameCount !== undefined
|
|
9208
|
+
? {
|
|
9209
|
+
frameCount: payload.data.frameCount,
|
|
9210
|
+
}
|
|
9211
|
+
: {}),
|
|
9212
|
+
...(payload.data.width !== undefined
|
|
9213
|
+
? {
|
|
9214
|
+
width: payload.data.width,
|
|
9215
|
+
}
|
|
9216
|
+
: {}),
|
|
9217
|
+
...(payload.data.height !== undefined
|
|
9218
|
+
? {
|
|
9219
|
+
height: payload.data.height,
|
|
9220
|
+
}
|
|
9221
|
+
: {}),
|
|
9222
|
+
jsonData: structuredClone(payload.data.jsonData),
|
|
9223
|
+
animations: structuredClone(payload.data.animations),
|
|
9224
|
+
}
|
|
9225
|
+
: {}),
|
|
9226
|
+
}),
|
|
9227
|
+
validateCreateState: ({ state, payload }) => {
|
|
9228
|
+
if (payload.data.type !== "spritesheet") {
|
|
9229
|
+
return;
|
|
9230
|
+
}
|
|
9231
|
+
|
|
9232
|
+
return validateReferencedFilesInData({
|
|
9233
|
+
state,
|
|
9234
|
+
data: payload.data,
|
|
9235
|
+
fields: ["fileId", "thumbnailFileId"],
|
|
9236
|
+
details: {
|
|
9237
|
+
spritesheetId: payload.spritesheetId,
|
|
9238
|
+
},
|
|
9239
|
+
});
|
|
9240
|
+
},
|
|
9241
|
+
validateUpdateState: ({ state, payload, currentItem }) => {
|
|
9242
|
+
if (
|
|
9243
|
+
currentItem.type === "folder" &&
|
|
9244
|
+
Object.keys(payload.data).some(
|
|
9245
|
+
(key) => key !== "name" && key !== "description",
|
|
9246
|
+
)
|
|
9247
|
+
) {
|
|
9248
|
+
return invalidPrecondition(
|
|
9249
|
+
"folder spritesheet items cannot update spritesheet fields",
|
|
9250
|
+
);
|
|
9251
|
+
}
|
|
9252
|
+
|
|
9253
|
+
if (currentItem.type === "spritesheet") {
|
|
9254
|
+
return validateReferencedFilesInData({
|
|
9255
|
+
state,
|
|
9256
|
+
data: payload.data,
|
|
9257
|
+
fields: ["fileId", "thumbnailFileId"],
|
|
9258
|
+
details: {
|
|
9259
|
+
spritesheetId: payload.spritesheetId,
|
|
9260
|
+
},
|
|
9261
|
+
});
|
|
9262
|
+
}
|
|
9263
|
+
},
|
|
9264
|
+
}),
|
|
8442
9265
|
{
|
|
8443
9266
|
type: "story.update",
|
|
8444
9267
|
validatePayload: ({ payload }) => {
|
|
@@ -14134,8 +14957,10 @@ export const validateAgainstState = ({ state, command }) => {
|
|
|
14134
14957
|
export const processCommand = ({ state, command }) => {
|
|
14135
14958
|
return captureValidation(() => {
|
|
14136
14959
|
const normalizedState = normalizeStateCollections(state);
|
|
14137
|
-
const
|
|
14138
|
-
typeof command?.type === "string" &&
|
|
14960
|
+
const shouldMaterializeNormalizedState =
|
|
14961
|
+
typeof command?.type === "string" &&
|
|
14962
|
+
(command.type.startsWith("control.") ||
|
|
14963
|
+
command.type.startsWith("spritesheet."));
|
|
14139
14964
|
|
|
14140
14965
|
if (!isPlainObject(command)) {
|
|
14141
14966
|
return invalidPrecondition("command must be an object");
|
|
@@ -14156,7 +14981,7 @@ export const processCommand = ({ state, command }) => {
|
|
|
14156
14981
|
|
|
14157
14982
|
const nextState = definition.reduce({
|
|
14158
14983
|
state: structuredClone(
|
|
14159
|
-
|
|
14984
|
+
shouldMaterializeNormalizedState ? normalizedState : state,
|
|
14160
14985
|
),
|
|
14161
14986
|
payload: command.payload,
|
|
14162
14987
|
});
|
|
@@ -14166,7 +14991,7 @@ export const processCommand = ({ state, command }) => {
|
|
|
14166
14991
|
|
|
14167
14992
|
const finalState =
|
|
14168
14993
|
nextState === undefined
|
|
14169
|
-
?
|
|
14994
|
+
? shouldMaterializeNormalizedState
|
|
14170
14995
|
? normalizedState
|
|
14171
14996
|
: state
|
|
14172
14997
|
: nextState;
|