@routevn/creator-model 1.13.1 → 1.13.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +18 -8
  2. package/package.json +1 -1
  3. package/src/model.js +50 -118
package/README.md CHANGED
@@ -354,8 +354,17 @@ Audio effects are foldered resources stored in `audioEffects.items` and
354
354
  },
355
355
  audioEffect: {
356
356
  type: "transition",
357
- prev: { fade: { duration: 600, easing: "easeInOutSine" } },
358
- next: { fade: { duration: 900, easing: "easeInOutSine" } },
357
+ prev: {
358
+ volume: {
359
+ keyframes: [{ value: 0, duration: 600, easing: "easeInOutSine" }],
360
+ },
361
+ },
362
+ next: {
363
+ volume: {
364
+ initialValue: 0,
365
+ keyframes: [{ value: 100, duration: 900, easing: "easeInOutSine" }],
366
+ },
367
+ },
359
368
  },
360
369
  }
361
370
  ```
@@ -365,12 +374,13 @@ transition effect, or a single `target` sound slot for an update effect. Each
365
374
  slot is an object containing a `soundId`.
366
375
 
367
376
  `audioEffect.type` is either `transition` or `update`. Transition effects have
368
- at least one `prev.fade` or `next.fade`. Update effects tween one or more of
369
- `volume`, `pan`, and `playbackRate`; each property has non-empty keyframes and
370
- must finish with an absolute numeric keyframe. That final number becomes the
371
- persistent BGM property value after the effect finishes. Absolute volume values
372
- are bounded to `0..100`, pan to `-1..1`, and playback rate to `>= 0`; relative
373
- keyframes represent unbounded numeric deltas and cannot be final.
377
+ at least one property under `prev` or `next`; update effects place properties
378
+ under `tween`. Both support only `volume`, `pan`, and `playbackRate`. Each
379
+ property has non-empty keyframes and must finish with an absolute numeric
380
+ keyframe. A final `tween` or `next` value becomes the persistent BGM property
381
+ value after the effect finishes. Absolute volume values are bounded to
382
+ `0..100`, pan to `-1..1`, and playback rate to `>= 0`; relative keyframes
383
+ represent unbounded numeric deltas and cannot be final.
374
384
 
375
385
  ## Current Scope
376
386
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routevn/creator-model",
3
- "version": "1.13.1",
3
+ "version": "1.13.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/model.js CHANGED
@@ -344,7 +344,7 @@ const ANIMATION_EASING_KEYS = [
344
344
  "easeOutElastic",
345
345
  "easeInOutElastic",
346
346
  ];
347
- const AUDIO_EFFECT_TWEEN_PROPERTY_KEYS = ["volume", "pan", "playbackRate"];
347
+ const AUDIO_EFFECT_PROPERTY_KEYS = ["volume", "pan", "playbackRate"];
348
348
  const VARIABLE_SCOPE_KEYS = ["context", "device", "account"];
349
349
  const VARIABLE_TYPE_KEYS = ["string", "number", "boolean", "object"];
350
350
  const LAYOUT_TYPE_KEYS = [
@@ -2493,6 +2493,31 @@ const validateAudioEffectAbsoluteValue = ({
2493
2493
  }
2494
2494
  };
2495
2495
 
2496
+ const validateAudioEffectInitialValue = ({
2497
+ value,
2498
+ property,
2499
+ path,
2500
+ errorFactory,
2501
+ }) => {
2502
+ if (value === undefined) {
2503
+ return;
2504
+ }
2505
+
2506
+ if (!isFiniteNumber(value)) {
2507
+ return invalidFromErrorFactory(
2508
+ errorFactory,
2509
+ `${path} must be a finite number when provided`,
2510
+ );
2511
+ }
2512
+
2513
+ return validateAudioEffectAbsoluteValue({
2514
+ value,
2515
+ property,
2516
+ path,
2517
+ errorFactory,
2518
+ });
2519
+ };
2520
+
2496
2521
  const validateAudioEffectKeyframes = ({
2497
2522
  keyframes,
2498
2523
  property,
@@ -2631,30 +2656,30 @@ const validateAudioEffectKeyframes = ({
2631
2656
  }
2632
2657
  };
2633
2658
 
2634
- const validateAudioEffectTween = ({ tween, path, errorFactory }) => {
2635
- if (!isPlainObject(tween)) {
2659
+ const validateAudioEffectPropertyTracks = ({ tracks, path, errorFactory }) => {
2660
+ if (!isPlainObject(tracks)) {
2636
2661
  return invalidFromErrorFactory(errorFactory, `${path} must be an object`);
2637
2662
  }
2638
2663
 
2639
- if (Object.keys(tween).length === 0) {
2664
+ if (Object.keys(tracks).length === 0) {
2640
2665
  return invalidFromErrorFactory(
2641
2666
  errorFactory,
2642
- `${path} must contain at least one tween property`,
2667
+ `${path} must contain at least one audio property`,
2643
2668
  );
2644
2669
  }
2645
2670
 
2646
- for (const [property, config] of Object.entries(tween)) {
2647
- if (!AUDIO_EFFECT_TWEEN_PROPERTY_KEYS.includes(property)) {
2671
+ for (const [property, config] of Object.entries(tracks)) {
2672
+ if (!AUDIO_EFFECT_PROPERTY_KEYS.includes(property)) {
2648
2673
  return invalidFromErrorFactory(
2649
2674
  errorFactory,
2650
- `${path}.${property} is not a supported audio effect tween property`,
2675
+ `${path}.${property} is not a supported audio effect property`,
2651
2676
  );
2652
2677
  }
2653
2678
 
2654
2679
  {
2655
- const result = validateExactKeys({
2680
+ const result = validateAllowedKeys({
2656
2681
  value: config,
2657
- expectedKeys: ["keyframes"],
2682
+ allowedKeys: ["initialValue", "keyframes"],
2658
2683
  path: `${path}.${property}`,
2659
2684
  errorFactory,
2660
2685
  });
@@ -2663,31 +2688,18 @@ const validateAudioEffectTween = ({ tween, path, errorFactory }) => {
2663
2688
  }
2664
2689
  }
2665
2690
 
2666
- {
2667
- const result = validateAudioEffectKeyframes({
2668
- keyframes: config.keyframes,
2669
- property,
2670
- path: `${path}.${property}.keyframes`,
2691
+ if (!Object.hasOwn(config, "keyframes")) {
2692
+ return invalidFromErrorFactory(
2671
2693
  errorFactory,
2672
- });
2673
- if (result?.valid === false) {
2674
- return result;
2675
- }
2694
+ `${path}.${property}.keyframes is required`,
2695
+ );
2676
2696
  }
2677
- }
2678
- };
2679
-
2680
- const validateAudioEffectFade = ({ fade, path, side, errorFactory }) => {
2681
- if (!isPlainObject(fade)) {
2682
- return invalidFromErrorFactory(errorFactory, `${path} must be an object`);
2683
- }
2684
2697
 
2685
- if (Object.hasOwn(fade, "keyframes")) {
2686
2698
  {
2687
- const result = validateExactKeys({
2688
- value: fade,
2689
- expectedKeys: ["keyframes"],
2690
- path,
2699
+ const result = validateAudioEffectInitialValue({
2700
+ value: config.initialValue,
2701
+ property,
2702
+ path: `${path}.${property}.initialValue`,
2691
2703
  errorFactory,
2692
2704
  });
2693
2705
  if (result?.valid === false) {
@@ -2697,95 +2709,16 @@ const validateAudioEffectFade = ({ fade, path, side, errorFactory }) => {
2697
2709
 
2698
2710
  {
2699
2711
  const result = validateAudioEffectKeyframes({
2700
- keyframes: fade.keyframes,
2701
- property: "volume",
2702
- path: `${path}.keyframes`,
2712
+ keyframes: config.keyframes,
2713
+ property,
2714
+ path: `${path}.${property}.keyframes`,
2703
2715
  errorFactory,
2704
2716
  });
2705
2717
  if (result?.valid === false) {
2706
2718
  return result;
2707
2719
  }
2708
2720
  }
2709
-
2710
- for (const [index, keyframe] of fade.keyframes.entries()) {
2711
- if (keyframe.relative === true) {
2712
- return invalidFromErrorFactory(
2713
- errorFactory,
2714
- `${path}.keyframes[${index}].relative is not supported for transition fades`,
2715
- );
2716
- }
2717
- }
2718
-
2719
- return;
2720
- }
2721
-
2722
- {
2723
- const result = validateAllowedKeys({
2724
- value: fade,
2725
- allowedKeys: ["delay", "duration", "easing"],
2726
- path,
2727
- errorFactory,
2728
- });
2729
- if (result?.valid === false) {
2730
- return result;
2731
- }
2732
- }
2733
-
2734
- if (!Object.hasOwn(fade, "duration")) {
2735
- return invalidFromErrorFactory(
2736
- errorFactory,
2737
- `${path}.duration is required`,
2738
- );
2739
- }
2740
-
2741
- if (!isFiniteNumber(fade.duration) || fade.duration < 0) {
2742
- return invalidFromErrorFactory(
2743
- errorFactory,
2744
- `${path}.duration must be a finite number >= 0`,
2745
- );
2746
- }
2747
-
2748
- if (
2749
- fade.delay !== undefined &&
2750
- (!isFiniteNumber(fade.delay) || fade.delay < 0)
2751
- ) {
2752
- return invalidFromErrorFactory(
2753
- errorFactory,
2754
- `${path}.delay must be a finite number >= 0 when provided`,
2755
- );
2756
2721
  }
2757
-
2758
- return validateAudioEffectEasing({
2759
- value: fade.easing,
2760
- path: `${path}.easing`,
2761
- errorFactory,
2762
- });
2763
- };
2764
-
2765
- const validateAudioEffectTransitionSide = ({
2766
- side,
2767
- sideName,
2768
- path,
2769
- errorFactory,
2770
- }) => {
2771
- {
2772
- const result = validateExactKeys({
2773
- value: side,
2774
- expectedKeys: ["fade"],
2775
- path,
2776
- errorFactory,
2777
- });
2778
- if (result?.valid === false) {
2779
- return result;
2780
- }
2781
- }
2782
-
2783
- return validateAudioEffectFade({
2784
- fade: side.fade,
2785
- path: `${path}.fade`,
2786
- side: sideName,
2787
- errorFactory,
2788
- });
2789
2722
  };
2790
2723
 
2791
2724
  const validateAudioEffectDefinition = ({ audioEffect, path, errorFactory }) => {
@@ -2823,8 +2756,8 @@ const validateAudioEffectDefinition = ({ audioEffect, path, errorFactory }) => {
2823
2756
  );
2824
2757
  }
2825
2758
 
2826
- return validateAudioEffectTween({
2827
- tween: audioEffect.tween,
2759
+ return validateAudioEffectPropertyTracks({
2760
+ tracks: audioEffect.tween,
2828
2761
  path: `${path}.tween`,
2829
2762
  errorFactory,
2830
2763
  });
@@ -2849,9 +2782,8 @@ const validateAudioEffectDefinition = ({ audioEffect, path, errorFactory }) => {
2849
2782
  continue;
2850
2783
  }
2851
2784
 
2852
- const result = validateAudioEffectTransitionSide({
2853
- side: audioEffect[side],
2854
- sideName: side,
2785
+ const result = validateAudioEffectPropertyTracks({
2786
+ tracks: audioEffect[side],
2855
2787
  path: `${path}.${side}`,
2856
2788
  errorFactory,
2857
2789
  });