@routevn/creator-model 1.7.2 → 1.8.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/package.json +1 -1
- package/src/model.js +638 -5
package/package.json
CHANGED
package/src/model.js
CHANGED
|
@@ -392,7 +392,7 @@ const LAYOUT_ELEMENT_BASE_TYPES = [
|
|
|
392
392
|
"container-ref-confirm-dialog-ok",
|
|
393
393
|
"container-ref-confirm-dialog-cancel",
|
|
394
394
|
];
|
|
395
|
-
export const SCHEMA_VERSION =
|
|
395
|
+
export const SCHEMA_VERSION = 8;
|
|
396
396
|
const LAYOUT_CONTAINER_ELEMENT_TYPES = [
|
|
397
397
|
"folder",
|
|
398
398
|
"container",
|
|
@@ -404,6 +404,18 @@ const LAYOUT_CONTAINER_ELEMENT_TYPES = [
|
|
|
404
404
|
"container-ref-confirm-dialog-ok",
|
|
405
405
|
"container-ref-confirm-dialog-cancel",
|
|
406
406
|
];
|
|
407
|
+
const LAYOUT_TEXT_CONTENT_ELEMENT_TYPES = [
|
|
408
|
+
"text",
|
|
409
|
+
"text-revealing",
|
|
410
|
+
"text-ref-character-name",
|
|
411
|
+
"text-revealing-ref-dialogue-content",
|
|
412
|
+
"text-ref-choice-item-content",
|
|
413
|
+
"text-ref-save-load-slot-date",
|
|
414
|
+
"text-ref-dialogue-line-character-name",
|
|
415
|
+
"text-ref-dialogue-line-content",
|
|
416
|
+
"text-ref-history-line-character-name",
|
|
417
|
+
"text-ref-history-line-content",
|
|
418
|
+
];
|
|
407
419
|
const DOMAIN_ERROR_KIND_BY_NAME = {
|
|
408
420
|
PayloadValidationError: "payload",
|
|
409
421
|
PreconditionValidationError: "precondition",
|
|
@@ -496,6 +508,15 @@ const isVariableReferenceTarget = (state, variableId) => {
|
|
|
496
508
|
return isPlainObject(variable) && variable.type !== "folder";
|
|
497
509
|
};
|
|
498
510
|
|
|
511
|
+
const isStringVariableReferenceTarget = (state, variableId) => {
|
|
512
|
+
const variable = state.variables.items[variableId];
|
|
513
|
+
return (
|
|
514
|
+
isPlainObject(variable) &&
|
|
515
|
+
variable.type === "variable" &&
|
|
516
|
+
variable.variableType === "string"
|
|
517
|
+
);
|
|
518
|
+
};
|
|
519
|
+
|
|
499
520
|
const LAYOUT_ITEM_TARGET_SET = new Set(["item.savedAt"]);
|
|
500
521
|
const LAYOUT_DIALOGUE_TARGET_SET = new Set(["dialogue.characterId"]);
|
|
501
522
|
const RUNTIME_TARGET_DOT_PATTERN = /^runtime\.([A-Za-z_$][A-Za-z0-9_$]*)$/;
|
|
@@ -3410,6 +3431,251 @@ const validateLayoutElementBlur = ({ blur, path, errorFactory }) => {
|
|
|
3410
3431
|
}
|
|
3411
3432
|
};
|
|
3412
3433
|
|
|
3434
|
+
const LAYOUT_TEXT_REVEAL_INDICATOR_ELEMENT_TYPES = [
|
|
3435
|
+
"text-revealing",
|
|
3436
|
+
"text-revealing-ref-dialogue-content",
|
|
3437
|
+
];
|
|
3438
|
+
|
|
3439
|
+
const validateLayoutTextRevealIndicatorVisual = ({
|
|
3440
|
+
visual,
|
|
3441
|
+
path,
|
|
3442
|
+
errorFactory,
|
|
3443
|
+
}) => {
|
|
3444
|
+
if (!isPlainObject(visual)) {
|
|
3445
|
+
return invalidFromErrorFactory(
|
|
3446
|
+
errorFactory,
|
|
3447
|
+
`${path} must be an object when provided`,
|
|
3448
|
+
);
|
|
3449
|
+
}
|
|
3450
|
+
|
|
3451
|
+
{
|
|
3452
|
+
const result = validateAllowedKeys({
|
|
3453
|
+
value: visual,
|
|
3454
|
+
allowedKeys: [
|
|
3455
|
+
"kind",
|
|
3456
|
+
"imageId",
|
|
3457
|
+
"resourceId",
|
|
3458
|
+
"animationName",
|
|
3459
|
+
"width",
|
|
3460
|
+
"height",
|
|
3461
|
+
"offsetX",
|
|
3462
|
+
"offsetY",
|
|
3463
|
+
],
|
|
3464
|
+
path,
|
|
3465
|
+
errorFactory,
|
|
3466
|
+
});
|
|
3467
|
+
if (result?.valid === false) {
|
|
3468
|
+
return result;
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
|
|
3472
|
+
const kind =
|
|
3473
|
+
visual.kind === "spritesheet" ||
|
|
3474
|
+
visual.resourceId !== undefined ||
|
|
3475
|
+
visual.animationName !== undefined
|
|
3476
|
+
? "spritesheet"
|
|
3477
|
+
: "image";
|
|
3478
|
+
|
|
3479
|
+
if (
|
|
3480
|
+
visual.kind !== undefined &&
|
|
3481
|
+
visual.kind !== "image" &&
|
|
3482
|
+
visual.kind !== "spritesheet"
|
|
3483
|
+
) {
|
|
3484
|
+
return invalidFromErrorFactory(
|
|
3485
|
+
errorFactory,
|
|
3486
|
+
`${path}.kind must be 'image' or 'spritesheet' when provided`,
|
|
3487
|
+
);
|
|
3488
|
+
}
|
|
3489
|
+
|
|
3490
|
+
if (kind === "image" && !isNonEmptyString(visual.imageId)) {
|
|
3491
|
+
return invalidFromErrorFactory(
|
|
3492
|
+
errorFactory,
|
|
3493
|
+
`${path}.imageId must be a non-empty string`,
|
|
3494
|
+
);
|
|
3495
|
+
}
|
|
3496
|
+
|
|
3497
|
+
if (kind === "spritesheet") {
|
|
3498
|
+
if (!isNonEmptyString(visual.resourceId)) {
|
|
3499
|
+
return invalidFromErrorFactory(
|
|
3500
|
+
errorFactory,
|
|
3501
|
+
`${path}.resourceId must be a non-empty string`,
|
|
3502
|
+
);
|
|
3503
|
+
}
|
|
3504
|
+
|
|
3505
|
+
if (!isNonEmptyString(visual.animationName)) {
|
|
3506
|
+
return invalidFromErrorFactory(
|
|
3507
|
+
errorFactory,
|
|
3508
|
+
`${path}.animationName must be a non-empty string`,
|
|
3509
|
+
);
|
|
3510
|
+
}
|
|
3511
|
+
}
|
|
3512
|
+
|
|
3513
|
+
for (const key of ["width", "height"]) {
|
|
3514
|
+
if (
|
|
3515
|
+
visual[key] !== undefined &&
|
|
3516
|
+
(!isFiniteNumber(visual[key]) || visual[key] <= 0)
|
|
3517
|
+
) {
|
|
3518
|
+
return invalidFromErrorFactory(
|
|
3519
|
+
errorFactory,
|
|
3520
|
+
`${path}.${key} must be a finite number greater than 0 when provided`,
|
|
3521
|
+
);
|
|
3522
|
+
}
|
|
3523
|
+
}
|
|
3524
|
+
|
|
3525
|
+
for (const key of ["offsetX", "offsetY"]) {
|
|
3526
|
+
if (visual[key] !== undefined && !isFiniteNumber(visual[key])) {
|
|
3527
|
+
return invalidFromErrorFactory(
|
|
3528
|
+
errorFactory,
|
|
3529
|
+
`${path}.${key} must be a finite number when provided`,
|
|
3530
|
+
);
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
};
|
|
3534
|
+
|
|
3535
|
+
const validateLayoutTextRevealIndicator = ({
|
|
3536
|
+
indicator,
|
|
3537
|
+
path,
|
|
3538
|
+
errorFactory,
|
|
3539
|
+
}) => {
|
|
3540
|
+
if (!isPlainObject(indicator)) {
|
|
3541
|
+
return invalidFromErrorFactory(
|
|
3542
|
+
errorFactory,
|
|
3543
|
+
`${path} must be an object when provided`,
|
|
3544
|
+
);
|
|
3545
|
+
}
|
|
3546
|
+
|
|
3547
|
+
{
|
|
3548
|
+
const result = validateAllowedKeys({
|
|
3549
|
+
value: indicator,
|
|
3550
|
+
allowedKeys: ["revealing", "complete", "offsetX", "offsetY"],
|
|
3551
|
+
path,
|
|
3552
|
+
errorFactory,
|
|
3553
|
+
});
|
|
3554
|
+
if (result?.valid === false) {
|
|
3555
|
+
return result;
|
|
3556
|
+
}
|
|
3557
|
+
}
|
|
3558
|
+
|
|
3559
|
+
for (const key of ["revealing", "complete"]) {
|
|
3560
|
+
if (indicator[key] !== undefined) {
|
|
3561
|
+
const result = validateLayoutTextRevealIndicatorVisual({
|
|
3562
|
+
visual: indicator[key],
|
|
3563
|
+
path: `${path}.${key}`,
|
|
3564
|
+
errorFactory,
|
|
3565
|
+
});
|
|
3566
|
+
if (result?.valid === false) {
|
|
3567
|
+
return result;
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
}
|
|
3571
|
+
|
|
3572
|
+
for (const key of ["offsetX", "offsetY"]) {
|
|
3573
|
+
if (indicator[key] !== undefined && !isFiniteNumber(indicator[key])) {
|
|
3574
|
+
return invalidFromErrorFactory(
|
|
3575
|
+
errorFactory,
|
|
3576
|
+
`${path}.${key} must be a finite number when provided`,
|
|
3577
|
+
);
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
};
|
|
3581
|
+
|
|
3582
|
+
const validateLayoutTextContent = ({ content, path, errorFactory }) => {
|
|
3583
|
+
if (!Array.isArray(content)) {
|
|
3584
|
+
return invalidFromErrorFactory(
|
|
3585
|
+
errorFactory,
|
|
3586
|
+
`${path} must be an array when provided`,
|
|
3587
|
+
);
|
|
3588
|
+
}
|
|
3589
|
+
|
|
3590
|
+
for (let index = 0; index < content.length; index += 1) {
|
|
3591
|
+
const item = content[index];
|
|
3592
|
+
const itemPath = `${path}[${index}]`;
|
|
3593
|
+
|
|
3594
|
+
if (!isPlainObject(item)) {
|
|
3595
|
+
return invalidFromErrorFactory(
|
|
3596
|
+
errorFactory,
|
|
3597
|
+
`${itemPath} must be an object`,
|
|
3598
|
+
);
|
|
3599
|
+
}
|
|
3600
|
+
|
|
3601
|
+
{
|
|
3602
|
+
const result = validateAllowedKeys({
|
|
3603
|
+
value: item,
|
|
3604
|
+
allowedKeys: ["text", "reference"],
|
|
3605
|
+
path: itemPath,
|
|
3606
|
+
errorFactory,
|
|
3607
|
+
});
|
|
3608
|
+
if (result?.valid === false) {
|
|
3609
|
+
return result;
|
|
3610
|
+
}
|
|
3611
|
+
}
|
|
3612
|
+
|
|
3613
|
+
const hasText = Object.hasOwn(item, "text");
|
|
3614
|
+
const hasReference = Object.hasOwn(item, "reference");
|
|
3615
|
+
|
|
3616
|
+
if (hasText === hasReference) {
|
|
3617
|
+
return invalidFromErrorFactory(
|
|
3618
|
+
errorFactory,
|
|
3619
|
+
`${itemPath} must include exactly one of text or reference`,
|
|
3620
|
+
);
|
|
3621
|
+
}
|
|
3622
|
+
|
|
3623
|
+
if (hasText) {
|
|
3624
|
+
if (!isString(item.text)) {
|
|
3625
|
+
return invalidFromErrorFactory(
|
|
3626
|
+
errorFactory,
|
|
3627
|
+
`${itemPath}.text must be a string`,
|
|
3628
|
+
);
|
|
3629
|
+
}
|
|
3630
|
+
continue;
|
|
3631
|
+
}
|
|
3632
|
+
|
|
3633
|
+
if (!isPlainObject(item.reference)) {
|
|
3634
|
+
return invalidFromErrorFactory(
|
|
3635
|
+
errorFactory,
|
|
3636
|
+
`${itemPath}.reference must be an object`,
|
|
3637
|
+
);
|
|
3638
|
+
}
|
|
3639
|
+
|
|
3640
|
+
{
|
|
3641
|
+
const result = validateAllowedKeys({
|
|
3642
|
+
value: item.reference,
|
|
3643
|
+
allowedKeys: ["resourceId"],
|
|
3644
|
+
path: `${itemPath}.reference`,
|
|
3645
|
+
errorFactory,
|
|
3646
|
+
});
|
|
3647
|
+
if (result?.valid === false) {
|
|
3648
|
+
return result;
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
|
|
3652
|
+
if (!isNonEmptyString(item.reference.resourceId)) {
|
|
3653
|
+
return invalidFromErrorFactory(
|
|
3654
|
+
errorFactory,
|
|
3655
|
+
`${itemPath}.reference.resourceId must be a non-empty string`,
|
|
3656
|
+
);
|
|
3657
|
+
}
|
|
3658
|
+
}
|
|
3659
|
+
};
|
|
3660
|
+
|
|
3661
|
+
const getLayoutTextContentReferenceEntries = (content) => {
|
|
3662
|
+
if (!Array.isArray(content)) {
|
|
3663
|
+
return [];
|
|
3664
|
+
}
|
|
3665
|
+
|
|
3666
|
+
const entries = [];
|
|
3667
|
+
for (let index = 0; index < content.length; index += 1) {
|
|
3668
|
+
const resourceId = content[index]?.reference?.resourceId;
|
|
3669
|
+
if (resourceId !== undefined) {
|
|
3670
|
+
entries.push({
|
|
3671
|
+
index,
|
|
3672
|
+
resourceId,
|
|
3673
|
+
});
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3676
|
+
return entries;
|
|
3677
|
+
};
|
|
3678
|
+
|
|
3413
3679
|
const validateLayoutElementData = ({
|
|
3414
3680
|
data,
|
|
3415
3681
|
path,
|
|
@@ -3438,9 +3704,11 @@ const validateLayoutElementData = ({
|
|
|
3438
3704
|
"fill",
|
|
3439
3705
|
"border",
|
|
3440
3706
|
"text",
|
|
3707
|
+
"content",
|
|
3441
3708
|
"textStyle",
|
|
3442
3709
|
"displaySpeed",
|
|
3443
3710
|
"revealEffect",
|
|
3711
|
+
"indicator",
|
|
3444
3712
|
"resourceId",
|
|
3445
3713
|
"animationName",
|
|
3446
3714
|
"imageId",
|
|
@@ -3619,6 +3887,52 @@ const validateLayoutElementData = ({
|
|
|
3619
3887
|
}
|
|
3620
3888
|
}
|
|
3621
3889
|
|
|
3890
|
+
if (data.content !== undefined) {
|
|
3891
|
+
{
|
|
3892
|
+
const result = validateLayoutTextContent({
|
|
3893
|
+
content: data.content,
|
|
3894
|
+
path: `${path}.content`,
|
|
3895
|
+
errorFactory,
|
|
3896
|
+
});
|
|
3897
|
+
if (result?.valid === false) {
|
|
3898
|
+
return result;
|
|
3899
|
+
}
|
|
3900
|
+
}
|
|
3901
|
+
|
|
3902
|
+
if (
|
|
3903
|
+
data.type !== undefined &&
|
|
3904
|
+
!LAYOUT_TEXT_CONTENT_ELEMENT_TYPES.includes(data.type)
|
|
3905
|
+
) {
|
|
3906
|
+
return invalidFromErrorFactory(
|
|
3907
|
+
errorFactory,
|
|
3908
|
+
`${path}.content can only be provided for text elements`,
|
|
3909
|
+
);
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
|
|
3913
|
+
if (data.indicator !== undefined) {
|
|
3914
|
+
{
|
|
3915
|
+
const result = validateLayoutTextRevealIndicator({
|
|
3916
|
+
indicator: data.indicator,
|
|
3917
|
+
path: `${path}.indicator`,
|
|
3918
|
+
errorFactory,
|
|
3919
|
+
});
|
|
3920
|
+
if (result?.valid === false) {
|
|
3921
|
+
return result;
|
|
3922
|
+
}
|
|
3923
|
+
}
|
|
3924
|
+
|
|
3925
|
+
if (
|
|
3926
|
+
data.type !== undefined &&
|
|
3927
|
+
!LAYOUT_TEXT_REVEAL_INDICATOR_ELEMENT_TYPES.includes(data.type)
|
|
3928
|
+
) {
|
|
3929
|
+
return invalidFromErrorFactory(
|
|
3930
|
+
errorFactory,
|
|
3931
|
+
`${path}.indicator can only be provided for text revealing elements`,
|
|
3932
|
+
);
|
|
3933
|
+
}
|
|
3934
|
+
}
|
|
3935
|
+
|
|
3622
3936
|
for (const key of [
|
|
3623
3937
|
"text",
|
|
3624
3938
|
"resourceId",
|
|
@@ -4134,9 +4448,11 @@ const validateLayoutElementItems = ({ items, path, errorFactory }) => {
|
|
|
4134
4448
|
"fill",
|
|
4135
4449
|
"border",
|
|
4136
4450
|
"text",
|
|
4451
|
+
"content",
|
|
4137
4452
|
"textStyle",
|
|
4138
4453
|
"displaySpeed",
|
|
4139
4454
|
"revealEffect",
|
|
4455
|
+
"indicator",
|
|
4140
4456
|
"resourceId",
|
|
4141
4457
|
"animationName",
|
|
4142
4458
|
"particleId",
|
|
@@ -4254,6 +4570,7 @@ const validateCharacterItems = ({ items, path, errorFactory }) => {
|
|
|
4254
4570
|
"tagIds",
|
|
4255
4571
|
"spriteGroups",
|
|
4256
4572
|
"shortcut",
|
|
4573
|
+
"nameVariableId",
|
|
4257
4574
|
"fileId",
|
|
4258
4575
|
"sprites",
|
|
4259
4576
|
],
|
|
@@ -4326,6 +4643,16 @@ const validateCharacterItems = ({ items, path, errorFactory }) => {
|
|
|
4326
4643
|
);
|
|
4327
4644
|
}
|
|
4328
4645
|
|
|
4646
|
+
if (
|
|
4647
|
+
item.nameVariableId !== undefined &&
|
|
4648
|
+
!isNonEmptyString(item.nameVariableId)
|
|
4649
|
+
) {
|
|
4650
|
+
return invalidFromErrorFactory(
|
|
4651
|
+
errorFactory,
|
|
4652
|
+
`${itemPath}.nameVariableId must be a non-empty string when provided`,
|
|
4653
|
+
);
|
|
4654
|
+
}
|
|
4655
|
+
|
|
4329
4656
|
if (item.fileId !== undefined && !isNonEmptyString(item.fileId)) {
|
|
4330
4657
|
return invalidFromErrorFactory(
|
|
4331
4658
|
errorFactory,
|
|
@@ -4781,6 +5108,13 @@ const applyCharacterUpdate = ({ currentItem, data }) => {
|
|
|
4781
5108
|
}
|
|
4782
5109
|
}
|
|
4783
5110
|
|
|
5111
|
+
if (
|
|
5112
|
+
Object.hasOwn(data, "nameVariableId") &&
|
|
5113
|
+
(data.nameVariableId === undefined || data.nameVariableId === "")
|
|
5114
|
+
) {
|
|
5115
|
+
delete nextItem.nameVariableId;
|
|
5116
|
+
}
|
|
5117
|
+
|
|
4784
5118
|
return nextItem;
|
|
4785
5119
|
};
|
|
4786
5120
|
|
|
@@ -6495,6 +6829,28 @@ const validateTransformPreviewImageReferences = ({
|
|
|
6495
6829
|
return VALID_RESULT;
|
|
6496
6830
|
};
|
|
6497
6831
|
|
|
6832
|
+
const validateStringVariableReference = ({
|
|
6833
|
+
state,
|
|
6834
|
+
variableId,
|
|
6835
|
+
path,
|
|
6836
|
+
details = {},
|
|
6837
|
+
errorFactory = createPreconditionValidationError,
|
|
6838
|
+
}) => {
|
|
6839
|
+
if (variableId === undefined || variableId === null || variableId === "") {
|
|
6840
|
+
return VALID_RESULT;
|
|
6841
|
+
}
|
|
6842
|
+
|
|
6843
|
+
if (!isStringVariableReferenceTarget(state, variableId)) {
|
|
6844
|
+
return invalidFromErrorFactory(
|
|
6845
|
+
errorFactory,
|
|
6846
|
+
`${path} must reference an existing string variable`,
|
|
6847
|
+
details,
|
|
6848
|
+
);
|
|
6849
|
+
}
|
|
6850
|
+
|
|
6851
|
+
return VALID_RESULT;
|
|
6852
|
+
};
|
|
6853
|
+
|
|
6498
6854
|
export const assertInvariants = ({ state }) => {
|
|
6499
6855
|
if (!isPlainObject(state)) {
|
|
6500
6856
|
return invalidInvariant("state must be an object");
|
|
@@ -6909,6 +7265,19 @@ export const assertInvariants = ({ state }) => {
|
|
|
6909
7265
|
}
|
|
6910
7266
|
}
|
|
6911
7267
|
|
|
7268
|
+
if (character.nameVariableId !== undefined) {
|
|
7269
|
+
const result = validateStringVariableReference({
|
|
7270
|
+
state,
|
|
7271
|
+
variableId: character.nameVariableId,
|
|
7272
|
+
path: "character.nameVariableId",
|
|
7273
|
+
details: { characterId, variableId: character.nameVariableId },
|
|
7274
|
+
errorFactory: createInvariantValidationError,
|
|
7275
|
+
});
|
|
7276
|
+
if (!result.valid) {
|
|
7277
|
+
return result;
|
|
7278
|
+
}
|
|
7279
|
+
}
|
|
7280
|
+
|
|
6912
7281
|
{
|
|
6913
7282
|
const result = validateTagIdsAgainstScope({
|
|
6914
7283
|
state,
|
|
@@ -7358,15 +7727,16 @@ export const assertInvariants = ({ state }) => {
|
|
|
7358
7727
|
elementId,
|
|
7359
7728
|
targetId,
|
|
7360
7729
|
animationName,
|
|
7730
|
+
fieldPrefix = "",
|
|
7361
7731
|
}) => {
|
|
7362
7732
|
const spritesheet = state.spritesheets?.items?.[targetId];
|
|
7363
7733
|
if (!isPlainObject(spritesheet) || spritesheet.type === "folder") {
|
|
7364
7734
|
return invalidInvariant(
|
|
7365
|
-
`${ownerLabel} element resourceId must reference an existing non-folder spritesheet`,
|
|
7735
|
+
`${ownerLabel} element ${fieldPrefix}resourceId must reference an existing non-folder spritesheet`,
|
|
7366
7736
|
{
|
|
7367
7737
|
[ownerIdField]: ownerId,
|
|
7368
7738
|
elementId,
|
|
7369
|
-
field:
|
|
7739
|
+
field: `${fieldPrefix}resourceId`,
|
|
7370
7740
|
targetId,
|
|
7371
7741
|
},
|
|
7372
7742
|
);
|
|
@@ -7377,11 +7747,11 @@ export const assertInvariants = ({ state }) => {
|
|
|
7377
7747
|
!isPlainObject(spritesheet.animations?.[animationName])
|
|
7378
7748
|
) {
|
|
7379
7749
|
return invalidInvariant(
|
|
7380
|
-
`${ownerLabel} element animationName must reference an existing spritesheet animation`,
|
|
7750
|
+
`${ownerLabel} element ${fieldPrefix}animationName must reference an existing spritesheet animation`,
|
|
7381
7751
|
{
|
|
7382
7752
|
[ownerIdField]: ownerId,
|
|
7383
7753
|
elementId,
|
|
7384
|
-
field:
|
|
7754
|
+
field: `${fieldPrefix}animationName`,
|
|
7385
7755
|
targetId: animationName,
|
|
7386
7756
|
},
|
|
7387
7757
|
);
|
|
@@ -7480,6 +7850,43 @@ export const assertInvariants = ({ state }) => {
|
|
|
7480
7850
|
}
|
|
7481
7851
|
}
|
|
7482
7852
|
|
|
7853
|
+
for (const stateName of ["revealing", "complete"]) {
|
|
7854
|
+
const visual = element.indicator?.[stateName];
|
|
7855
|
+
if (
|
|
7856
|
+
visual?.kind === "spritesheet" ||
|
|
7857
|
+
visual?.resourceId !== undefined ||
|
|
7858
|
+
visual?.animationName !== undefined
|
|
7859
|
+
) {
|
|
7860
|
+
const result = assertSpritesheetAnimationReference({
|
|
7861
|
+
ownerIdField,
|
|
7862
|
+
ownerId,
|
|
7863
|
+
ownerLabel,
|
|
7864
|
+
elementId,
|
|
7865
|
+
targetId: visual.resourceId,
|
|
7866
|
+
animationName: visual.animationName,
|
|
7867
|
+
fieldPrefix: `indicator.${stateName}.`,
|
|
7868
|
+
});
|
|
7869
|
+
if (!result.valid) {
|
|
7870
|
+
return result;
|
|
7871
|
+
}
|
|
7872
|
+
continue;
|
|
7873
|
+
}
|
|
7874
|
+
|
|
7875
|
+
if (visual?.imageId !== undefined) {
|
|
7876
|
+
const result = assertImageReference({
|
|
7877
|
+
ownerIdField,
|
|
7878
|
+
ownerId,
|
|
7879
|
+
ownerLabel,
|
|
7880
|
+
elementId,
|
|
7881
|
+
field: `indicator.${stateName}.imageId`,
|
|
7882
|
+
targetId: visual.imageId,
|
|
7883
|
+
});
|
|
7884
|
+
if (!result.valid) {
|
|
7885
|
+
return result;
|
|
7886
|
+
}
|
|
7887
|
+
}
|
|
7888
|
+
}
|
|
7889
|
+
|
|
7483
7890
|
for (const field of ["hoverSoundId", "clickSoundId"]) {
|
|
7484
7891
|
if (element[field] !== undefined) {
|
|
7485
7892
|
const result = assertSoundReference({
|
|
@@ -7577,6 +7984,23 @@ export const assertInvariants = ({ state }) => {
|
|
|
7577
7984
|
}
|
|
7578
7985
|
}
|
|
7579
7986
|
|
|
7987
|
+
for (const {
|
|
7988
|
+
index,
|
|
7989
|
+
resourceId,
|
|
7990
|
+
} of getLayoutTextContentReferenceEntries(element.content)) {
|
|
7991
|
+
if (!isVariableReferenceTarget(state, resourceId)) {
|
|
7992
|
+
return invalidInvariant(
|
|
7993
|
+
`${ownerLabel} element content.${index}.reference.resourceId must reference an existing non-folder variable`,
|
|
7994
|
+
{
|
|
7995
|
+
[ownerIdField]: ownerId,
|
|
7996
|
+
elementId,
|
|
7997
|
+
field: `content.${index}.reference.resourceId`,
|
|
7998
|
+
targetId: resourceId,
|
|
7999
|
+
},
|
|
8000
|
+
);
|
|
8001
|
+
}
|
|
8002
|
+
}
|
|
8003
|
+
|
|
7580
8004
|
if (element.variableId !== undefined) {
|
|
7581
8005
|
const result = assertVariableReference({
|
|
7582
8006
|
ownerIdField,
|
|
@@ -10639,6 +11063,7 @@ const validateCharacterCreateData = ({ data, errorFactory }) => {
|
|
|
10639
11063
|
"tagIds",
|
|
10640
11064
|
"spriteGroups",
|
|
10641
11065
|
"shortcut",
|
|
11066
|
+
"nameVariableId",
|
|
10642
11067
|
"fileId",
|
|
10643
11068
|
"sprites",
|
|
10644
11069
|
],
|
|
@@ -10694,6 +11119,16 @@ const validateCharacterCreateData = ({ data, errorFactory }) => {
|
|
|
10694
11119
|
);
|
|
10695
11120
|
}
|
|
10696
11121
|
|
|
11122
|
+
if (
|
|
11123
|
+
data.nameVariableId !== undefined &&
|
|
11124
|
+
!isNonEmptyString(data.nameVariableId)
|
|
11125
|
+
) {
|
|
11126
|
+
return invalidFromErrorFactory(
|
|
11127
|
+
errorFactory,
|
|
11128
|
+
"payload.data.nameVariableId must be a non-empty string when provided",
|
|
11129
|
+
);
|
|
11130
|
+
}
|
|
11131
|
+
|
|
10697
11132
|
if (data.fileId !== undefined && !isNonEmptyString(data.fileId)) {
|
|
10698
11133
|
return invalidFromErrorFactory(
|
|
10699
11134
|
errorFactory,
|
|
@@ -10735,6 +11170,7 @@ const validateCharacterUpdateData = ({ data, errorFactory }) => {
|
|
|
10735
11170
|
"tagIds",
|
|
10736
11171
|
"spriteGroups",
|
|
10737
11172
|
"shortcut",
|
|
11173
|
+
"nameVariableId",
|
|
10738
11174
|
"fileId",
|
|
10739
11175
|
],
|
|
10740
11176
|
path: "payload.data",
|
|
@@ -10773,6 +11209,17 @@ const validateCharacterUpdateData = ({ data, errorFactory }) => {
|
|
|
10773
11209
|
);
|
|
10774
11210
|
}
|
|
10775
11211
|
|
|
11212
|
+
if (
|
|
11213
|
+
data.nameVariableId !== undefined &&
|
|
11214
|
+
data.nameVariableId !== "" &&
|
|
11215
|
+
!isNonEmptyString(data.nameVariableId)
|
|
11216
|
+
) {
|
|
11217
|
+
return invalidFromErrorFactory(
|
|
11218
|
+
errorFactory,
|
|
11219
|
+
"payload.data.nameVariableId must be a non-empty string when provided",
|
|
11220
|
+
);
|
|
11221
|
+
}
|
|
11222
|
+
|
|
10776
11223
|
{
|
|
10777
11224
|
const result = validateOptionalUniqueIdArray({
|
|
10778
11225
|
value: data.tagIds,
|
|
@@ -11298,6 +11745,36 @@ const validateVisualElementReferenceTargets = ({
|
|
|
11298
11745
|
);
|
|
11299
11746
|
}
|
|
11300
11747
|
|
|
11748
|
+
if (
|
|
11749
|
+
data.indicator !== undefined &&
|
|
11750
|
+
!LAYOUT_TEXT_REVEAL_INDICATOR_ELEMENT_TYPES.includes(data.type)
|
|
11751
|
+
) {
|
|
11752
|
+
return invalidFromErrorFactory(
|
|
11753
|
+
errorFactory,
|
|
11754
|
+
`${ownerLabel} element indicator can only be provided for text revealing elements`,
|
|
11755
|
+
{
|
|
11756
|
+
[ownerIdField]: ownerId,
|
|
11757
|
+
elementId,
|
|
11758
|
+
field: "indicator",
|
|
11759
|
+
},
|
|
11760
|
+
);
|
|
11761
|
+
}
|
|
11762
|
+
|
|
11763
|
+
if (
|
|
11764
|
+
data.content !== undefined &&
|
|
11765
|
+
!LAYOUT_TEXT_CONTENT_ELEMENT_TYPES.includes(data.type)
|
|
11766
|
+
) {
|
|
11767
|
+
return invalidFromErrorFactory(
|
|
11768
|
+
errorFactory,
|
|
11769
|
+
`${ownerLabel} element content can only be provided for text elements`,
|
|
11770
|
+
{
|
|
11771
|
+
[ownerIdField]: ownerId,
|
|
11772
|
+
elementId,
|
|
11773
|
+
field: "content",
|
|
11774
|
+
},
|
|
11775
|
+
);
|
|
11776
|
+
}
|
|
11777
|
+
|
|
11301
11778
|
if (
|
|
11302
11779
|
data.type === "spritesheet-animation" ||
|
|
11303
11780
|
data.resourceId !== undefined ||
|
|
@@ -11398,6 +11875,66 @@ const validateVisualElementReferenceTargets = ({
|
|
|
11398
11875
|
}
|
|
11399
11876
|
}
|
|
11400
11877
|
|
|
11878
|
+
for (const stateName of ["revealing", "complete"]) {
|
|
11879
|
+
const visual = data.indicator?.[stateName];
|
|
11880
|
+
if (
|
|
11881
|
+
visual?.kind === "spritesheet" ||
|
|
11882
|
+
visual?.resourceId !== undefined ||
|
|
11883
|
+
visual?.animationName !== undefined
|
|
11884
|
+
) {
|
|
11885
|
+
const spritesheet = state.spritesheets?.items?.[visual.resourceId];
|
|
11886
|
+
if (!isPlainObject(spritesheet) || spritesheet.type === "folder") {
|
|
11887
|
+
return invalidFromErrorFactory(
|
|
11888
|
+
errorFactory,
|
|
11889
|
+
`${ownerLabel} element indicator.${stateName}.resourceId must reference an existing non-folder spritesheet`,
|
|
11890
|
+
{
|
|
11891
|
+
[ownerIdField]: ownerId,
|
|
11892
|
+
elementId,
|
|
11893
|
+
field: `indicator.${stateName}.resourceId`,
|
|
11894
|
+
targetId: visual.resourceId,
|
|
11895
|
+
},
|
|
11896
|
+
);
|
|
11897
|
+
}
|
|
11898
|
+
|
|
11899
|
+
if (
|
|
11900
|
+
!isNonEmptyString(visual.animationName) ||
|
|
11901
|
+
!isPlainObject(spritesheet.animations?.[visual.animationName])
|
|
11902
|
+
) {
|
|
11903
|
+
return invalidFromErrorFactory(
|
|
11904
|
+
errorFactory,
|
|
11905
|
+
`${ownerLabel} element indicator.${stateName}.animationName must reference an existing spritesheet animation`,
|
|
11906
|
+
{
|
|
11907
|
+
[ownerIdField]: ownerId,
|
|
11908
|
+
elementId,
|
|
11909
|
+
field: `indicator.${stateName}.animationName`,
|
|
11910
|
+
targetId: visual.animationName,
|
|
11911
|
+
},
|
|
11912
|
+
);
|
|
11913
|
+
}
|
|
11914
|
+
|
|
11915
|
+
continue;
|
|
11916
|
+
}
|
|
11917
|
+
|
|
11918
|
+
const imageId = visual?.imageId;
|
|
11919
|
+
if (imageId === undefined) {
|
|
11920
|
+
continue;
|
|
11921
|
+
}
|
|
11922
|
+
|
|
11923
|
+
const image = state.images.items[imageId];
|
|
11924
|
+
if (!isPlainObject(image) || image.type === "folder") {
|
|
11925
|
+
return invalidFromErrorFactory(
|
|
11926
|
+
errorFactory,
|
|
11927
|
+
`${ownerLabel} element indicator.${stateName}.imageId must reference an existing non-folder image`,
|
|
11928
|
+
{
|
|
11929
|
+
[ownerIdField]: ownerId,
|
|
11930
|
+
elementId,
|
|
11931
|
+
field: `indicator.${stateName}.imageId`,
|
|
11932
|
+
targetId: imageId,
|
|
11933
|
+
},
|
|
11934
|
+
);
|
|
11935
|
+
}
|
|
11936
|
+
}
|
|
11937
|
+
|
|
11401
11938
|
if (data.hoverSoundId !== undefined) {
|
|
11402
11939
|
const sound = state.sounds.items[data.hoverSoundId];
|
|
11403
11940
|
if (!isPlainObject(sound) || sound.type === "folder") {
|
|
@@ -11625,6 +12162,23 @@ const validateVisualElementReferenceTargets = ({
|
|
|
11625
12162
|
}
|
|
11626
12163
|
}
|
|
11627
12164
|
|
|
12165
|
+
for (const { index, resourceId } of getLayoutTextContentReferenceEntries(
|
|
12166
|
+
data.content,
|
|
12167
|
+
)) {
|
|
12168
|
+
if (!isVariableReferenceTarget(state, resourceId)) {
|
|
12169
|
+
return invalidFromErrorFactory(
|
|
12170
|
+
errorFactory,
|
|
12171
|
+
`${ownerLabel} element content.${index}.reference.resourceId must reference an existing non-folder variable`,
|
|
12172
|
+
{
|
|
12173
|
+
[ownerIdField]: ownerId,
|
|
12174
|
+
elementId,
|
|
12175
|
+
field: `content.${index}.reference.resourceId`,
|
|
12176
|
+
targetId: resourceId,
|
|
12177
|
+
},
|
|
12178
|
+
);
|
|
12179
|
+
}
|
|
12180
|
+
}
|
|
12181
|
+
|
|
11628
12182
|
if (data.variableId !== undefined) {
|
|
11629
12183
|
if (!isVariableReferenceTarget(state, data.variableId)) {
|
|
11630
12184
|
return invalidFromErrorFactory(
|
|
@@ -17072,6 +17626,10 @@ const COMMAND_DEFINITIONS = [
|
|
|
17072
17626
|
item.fileId = payload.data.fileId;
|
|
17073
17627
|
}
|
|
17074
17628
|
|
|
17629
|
+
if (payload.data.nameVariableId !== undefined) {
|
|
17630
|
+
item.nameVariableId = payload.data.nameVariableId;
|
|
17631
|
+
}
|
|
17632
|
+
|
|
17075
17633
|
assignOptionalTagIds({
|
|
17076
17634
|
target: item,
|
|
17077
17635
|
tagIds: payload.data.tagIds,
|
|
@@ -17112,6 +17670,21 @@ const COMMAND_DEFINITIONS = [
|
|
|
17112
17670
|
}
|
|
17113
17671
|
}
|
|
17114
17672
|
|
|
17673
|
+
{
|
|
17674
|
+
const result = validateStringVariableReference({
|
|
17675
|
+
state,
|
|
17676
|
+
variableId: payload.data.nameVariableId,
|
|
17677
|
+
path: "payload.data.nameVariableId",
|
|
17678
|
+
details: {
|
|
17679
|
+
characterId: payload.characterId,
|
|
17680
|
+
variableId: payload.data.nameVariableId,
|
|
17681
|
+
},
|
|
17682
|
+
});
|
|
17683
|
+
if (!result.valid) {
|
|
17684
|
+
return result;
|
|
17685
|
+
}
|
|
17686
|
+
}
|
|
17687
|
+
|
|
17115
17688
|
{
|
|
17116
17689
|
const result = validateTagIdsAgainstScope({
|
|
17117
17690
|
state,
|
|
@@ -17217,6 +17790,21 @@ const COMMAND_DEFINITIONS = [
|
|
|
17217
17790
|
return result;
|
|
17218
17791
|
}
|
|
17219
17792
|
|
|
17793
|
+
if (Object.hasOwn(payload.data, "nameVariableId")) {
|
|
17794
|
+
const variableResult = validateStringVariableReference({
|
|
17795
|
+
state,
|
|
17796
|
+
variableId: payload.data.nameVariableId,
|
|
17797
|
+
path: "payload.data.nameVariableId",
|
|
17798
|
+
details: {
|
|
17799
|
+
characterId: payload.characterId,
|
|
17800
|
+
variableId: payload.data.nameVariableId,
|
|
17801
|
+
},
|
|
17802
|
+
});
|
|
17803
|
+
if (!variableResult.valid) {
|
|
17804
|
+
return variableResult;
|
|
17805
|
+
}
|
|
17806
|
+
}
|
|
17807
|
+
|
|
17220
17808
|
{
|
|
17221
17809
|
const tagResult = validateTagIdsAgainstScope({
|
|
17222
17810
|
state,
|
|
@@ -17617,6 +18205,16 @@ const COMMAND_DEFINITIONS = [
|
|
|
17617
18205
|
"payload.parentId must reference a folder sprite item",
|
|
17618
18206
|
);
|
|
17619
18207
|
}
|
|
18208
|
+
|
|
18209
|
+
const parentNode = findTreeNode({
|
|
18210
|
+
nodes: collection.tree,
|
|
18211
|
+
nodeId: parentId,
|
|
18212
|
+
});
|
|
18213
|
+
if (!parentNode) {
|
|
18214
|
+
return invalidPrecondition(
|
|
18215
|
+
"payload.parentId must reference a folder sprite item in the tree",
|
|
18216
|
+
);
|
|
18217
|
+
}
|
|
17620
18218
|
}
|
|
17621
18219
|
|
|
17622
18220
|
if (payload.positionTargetId !== undefined) {
|
|
@@ -17626,6 +18224,16 @@ const COMMAND_DEFINITIONS = [
|
|
|
17626
18224
|
);
|
|
17627
18225
|
}
|
|
17628
18226
|
|
|
18227
|
+
const targetNode = findTreeNode({
|
|
18228
|
+
nodes: collection.tree,
|
|
18229
|
+
nodeId: payload.positionTargetId,
|
|
18230
|
+
});
|
|
18231
|
+
if (!targetNode) {
|
|
18232
|
+
return invalidPrecondition(
|
|
18233
|
+
"payload.positionTargetId must reference an existing sprite item in the tree",
|
|
18234
|
+
);
|
|
18235
|
+
}
|
|
18236
|
+
|
|
17629
18237
|
const targetParentId = getNodeParentId({
|
|
17630
18238
|
tree: collection.tree,
|
|
17631
18239
|
nodeId: payload.positionTargetId,
|
|
@@ -17957,6 +18565,11 @@ const COMMAND_DEFINITIONS = [
|
|
|
17957
18565
|
nodes: collection.tree,
|
|
17958
18566
|
nodeId: payload.spriteId,
|
|
17959
18567
|
});
|
|
18568
|
+
if (!currentNode) {
|
|
18569
|
+
return invalidPrecondition(
|
|
18570
|
+
"payload.spriteId must reference an existing sprite item in the tree",
|
|
18571
|
+
);
|
|
18572
|
+
}
|
|
17960
18573
|
|
|
17961
18574
|
if (payload.parentId !== undefined && payload.parentId !== null) {
|
|
17962
18575
|
const parentItem = collection.items[payload.parentId];
|
|
@@ -17966,6 +18579,16 @@ const COMMAND_DEFINITIONS = [
|
|
|
17966
18579
|
);
|
|
17967
18580
|
}
|
|
17968
18581
|
|
|
18582
|
+
const parentNode = findTreeNode({
|
|
18583
|
+
nodes: collection.tree,
|
|
18584
|
+
nodeId: payload.parentId,
|
|
18585
|
+
});
|
|
18586
|
+
if (!parentNode) {
|
|
18587
|
+
return invalidPrecondition(
|
|
18588
|
+
"payload.parentId must reference a folder sprite item in the tree",
|
|
18589
|
+
);
|
|
18590
|
+
}
|
|
18591
|
+
|
|
17969
18592
|
const descendantIds = new Set(
|
|
17970
18593
|
collectTreeDescendantIds({
|
|
17971
18594
|
node: currentNode,
|
|
@@ -17992,6 +18615,16 @@ const COMMAND_DEFINITIONS = [
|
|
|
17992
18615
|
);
|
|
17993
18616
|
}
|
|
17994
18617
|
|
|
18618
|
+
const targetNode = findTreeNode({
|
|
18619
|
+
nodes: collection.tree,
|
|
18620
|
+
nodeId: payload.positionTargetId,
|
|
18621
|
+
});
|
|
18622
|
+
if (!targetNode) {
|
|
18623
|
+
return invalidPrecondition(
|
|
18624
|
+
"payload.positionTargetId must reference an existing sprite item in the tree",
|
|
18625
|
+
);
|
|
18626
|
+
}
|
|
18627
|
+
|
|
17995
18628
|
const targetParentId = getNodeParentId({
|
|
17996
18629
|
tree: collection.tree,
|
|
17997
18630
|
nodeId: payload.positionTargetId,
|