danoniplus 32.7.0 → 33.0.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/js/danoni_main.js CHANGED
@@ -4,12 +4,12 @@
4
4
  *
5
5
  * Source by tickle
6
6
  * Created : 2018/10/08
7
- * Revised : 2023/07/17
7
+ * Revised : 2023/07/29
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 32.7.0`;
12
- const g_revisedDate = `2023/07/17`;
11
+ const g_version = `Ver 33.0.0`;
12
+ const g_revisedDate = `2023/07/29`;
13
13
 
14
14
  // カスタム用バージョン (danoni_custom.js 等で指定可)
15
15
  let g_localVersion = ``;
@@ -47,6 +47,7 @@ const current = _ => {
47
47
  return targetScript.src;
48
48
  };
49
49
  const g_rootPath = current().match(/(^.*\/)/)[0];
50
+ const g_workPath = new URL(location.href).href.match(/(^.*\/)/)[0];
50
51
  const g_remoteFlg = g_rootPath.match(`^https://cwtickle.github.io/danoniplus/`) !== null;
51
52
  const g_randTime = Date.now();
52
53
 
@@ -767,32 +768,66 @@ const loadMultipleFiles2 = async (_fileData, _loadType) => {
767
768
  }));
768
769
  };
769
770
 
770
- /**
771
- * 入力されたパスを、ディレクトリとそれ以外に分割
772
- * 返却値:[ファイルキーワード, ルートディレクトリ]
773
- * @param {string} _path
774
- * @param {number} _pos
775
- * @param {string} _directory
776
- */
777
- const getFolderAndType = (_path, _pos, _directory = ``) => {
778
- const rootPath = (_directory === `` ? `` : g_rootPath);
779
- return (_pos > 0 ? [_path.substring(_pos + 1), `${rootPath}${_path.substring(0, _pos)}/`] : [_path, `${rootPath}${_directory}`]);
780
- };
781
-
782
771
  /**
783
772
  * 与えられたパスより、キーワードとディレクトリに分割
784
- * カレントディレクトリ指定がある場合を考慮して、処理を分けている
785
773
  * 返却値:[ファイルキーワード, ルートディレクトリ]
786
774
  * @param {string} _fileName
787
- * @param {string} _directory
775
+ * @param {string} _directory
788
776
  */
789
777
  const getFilePath = (_fileName, _directory = ``) => {
790
- if (_fileName.indexOf(C_MRK_CURRENT_DIRECTORY) !== -1) {
791
- const tmpType = _fileName.split(C_MRK_CURRENT_DIRECTORY)[1];
792
- return getFolderAndType(tmpType, tmpType.indexOf(`/`));
778
+ let fullPath;
779
+ if (_fileName.startsWith(C_MRK_CURRENT_DIRECTORY)) {
780
+ fullPath = `${g_workPath}${_fileName.slice(C_MRK_CURRENT_DIRECTORY.length)}`;
793
781
  } else {
794
- return getFolderAndType(_fileName, _fileName.lastIndexOf(`/`), _directory);
782
+ fullPath = `${g_rootPath}${_directory}${_fileName}`;
783
+ }
784
+ const dirPos = fullPath.lastIndexOf(`/`);
785
+ return [fullPath.slice(dirPos + 1), fullPath.slice(0, dirPos + 1)];
786
+ }
787
+
788
+ /**
789
+ * 画像ファイルの存在チェック後、プリロードする処理
790
+ * @param {string} _imgPath
791
+ * @param {string} directory
792
+ * @param {boolean} syncBackPath
793
+ * @returns
794
+ */
795
+ const preloadImgFile = (_imgPath, { directory = ``, syncBackPath = true } = {}) => {
796
+
797
+ let imgPath = _imgPath;
798
+ if (g_headerObj.autoPreload) {
799
+ if (checkImage(_imgPath)) {
800
+ if (syncBackPath) {
801
+ const [file, dir] = getFilePath(_imgPath, directory);
802
+ imgPath = `${dir}${file}`;
803
+ }
804
+ preloadFile(`image`, imgPath);
805
+ }
806
+ }
807
+ return imgPath;
808
+ };
809
+
810
+ /**
811
+ * 画像パス部分の取得
812
+ * @param {string} _str
813
+ * @returns
814
+ */
815
+ const getImageUrlPath = _str => {
816
+ const matches = _str?.match(/url\("([^"]*)"\)/);
817
+ return matches && matches.length >= 2 ? matches[1] : ``;
818
+ };
819
+
820
+ /**
821
+ * カレントディレクトリを含む文字列を置換し、変更後の文字列を作成
822
+ * @param {string} _str
823
+ */
824
+ const reviseCssText = _str => {
825
+ if (getImageUrlPath(_str) !== ``) {
826
+ const imgOriginal = getImageUrlPath(_str);
827
+ const imgPath = preloadImgFile(imgOriginal);
828
+ return replaceStr(_str, [[imgOriginal, imgPath]]);
795
829
  }
830
+ return _str;
796
831
  };
797
832
 
798
833
  /*-----------------------------------------------------------*/
@@ -890,7 +925,17 @@ const makeColorGradation = (_colorStr, { _defaultColorgrd = g_headerObj.defaultC
890
925
  const alphaVal = (_shadowFlg && _objType !== `frz`) ? `80` : (_objType === `titleArrow` ? `40` : ``);
891
926
 
892
927
  let convertColorStr = ``;
893
- const tmpColorStr = _colorStr.split(`@`);
928
+ const tmpBackgroundStr = _colorStr.split(`;`);
929
+
930
+ // 色情報以外の部分を退避
931
+ const addData = tmpBackgroundStr[1] !== undefined ? tmpBackgroundStr.slice(1).join(` `) : ``;
932
+ if ([``, `-`, `none`].includes(tmpBackgroundStr[0]) ||
933
+ tmpBackgroundStr[0].startsWith(`url(`) || tmpBackgroundStr[0].startsWith(`var(`)) {
934
+ return addData;
935
+ }
936
+
937
+ // 色情報からグラデーションを作成
938
+ const tmpColorStr = tmpBackgroundStr[0].split(`@`);
894
939
  const colorArray = tmpColorStr[0].split(`:`);
895
940
  for (let j = 0; j < colorArray.length; j++) {
896
941
  colorArray[j] = colorCdPadding(_colorCdPaddingUse, colorToHex(colorArray[j].replaceAll(`0x`, `#`)));
@@ -917,7 +962,7 @@ const makeColorGradation = (_colorStr, { _defaultColorgrd = g_headerObj.defaultC
917
962
  convertColorStr += `${colorArray.join(', ')}`;
918
963
  }
919
964
 
920
- return `${gradationType}(${convertColorStr})`;
965
+ return `${hasVal(addData) ? `${addData} ` : ''}${gradationType}(${convertColorStr})`;
921
966
  };
922
967
 
923
968
  /*-----------------------------------------------------------*/
@@ -1406,8 +1451,60 @@ const drawDefaultBackImage = _key => {
1406
1451
  } else {
1407
1452
  createEmptySprite(divRoot, `divBack`);
1408
1453
  }
1454
+
1455
+ // CSSスタイルの初期化
1456
+ Object.keys(g_cssBkProperties).forEach(prop =>
1457
+ document.documentElement.style.setProperty(prop, g_cssBkProperties[prop]));
1458
+
1459
+ Object.keys(g_headerObj).filter(val => val.startsWith(`--`) && hasVal(g_headerObj[val])).forEach(prop =>
1460
+ document.documentElement.style.setProperty(prop, getCssCustomProperty(prop, g_headerObj[prop])));
1461
+
1409
1462
  };
1410
1463
 
1464
+ /**
1465
+ * CSSカスタムプロパティの値を作成
1466
+ * @param {string} _prop
1467
+ * @param {string} _propData
1468
+ */
1469
+ const getCssCustomProperty = (_prop, _propData) =>
1470
+ document.documentElement.style.getPropertyValue(_propData) !== `` ?
1471
+ document.documentElement.style.getPropertyValue(_propData) :
1472
+ g_cssBkProperties[_propData] !== undefined ?
1473
+ g_cssBkProperties[_propData] :
1474
+ _prop.endsWith(`-x`) ? _propData : reviseCssText(makeColorGradation(_propData, { _defaultColorgrd: false }));
1475
+
1476
+ /**
1477
+ * CSSカスタムプロパティの値をオブジェクトへ退避
1478
+ */
1479
+ const getCssCustomProperties = _ => {
1480
+ try {
1481
+ const htmlStyle = document.documentElement.computedStyleMap();
1482
+ for (const [propertyName, value] of htmlStyle.entries()) {
1483
+ if (/^--/.test(propertyName)) {
1484
+ g_cssBkProperties[propertyName] = value.toString();
1485
+ }
1486
+ }
1487
+ } catch (error) {
1488
+ // FirefoxではcomputedStyleMapが使えないため、
1489
+ // CSSの全スタイルシート定義から :root がセレクタのルールを抽出し、カスタムプロパティを抽出
1490
+ const sheets = document.styleSheets;
1491
+ for (const sheet of sheets) {
1492
+ if (!g_isFile && sheet.cssRules) {
1493
+ for (const rule of sheet.cssRules) {
1494
+ if (rule.selectorText === ':root') {
1495
+ for (let i = 0; i < rule.style.length; i++) {
1496
+ const propertyName = rule.style.item(i);
1497
+ if (/^--/.test(propertyName)) {
1498
+ g_cssBkProperties[propertyName] = rule.style.getPropertyValue(propertyName);
1499
+ }
1500
+ }
1501
+ }
1502
+ }
1503
+ }
1504
+ }
1505
+ }
1506
+ }
1507
+
1411
1508
  /**
1412
1509
  * 背景・マスク用画像の描画
1413
1510
  * @param {object} _obj
@@ -1450,7 +1547,7 @@ const makeSpriteText = _obj => {
1450
1547
  * @param {object, array} _obj
1451
1548
  */
1452
1549
  const checkDuplicatedObjects = _obj => {
1453
- let addFrame = 0;
1550
+ let dataCnts = 0;
1454
1551
  if (_obj === undefined) {
1455
1552
  _obj = [];
1456
1553
  _obj[0] = [];
@@ -1458,17 +1555,17 @@ const checkDuplicatedObjects = _obj => {
1458
1555
  for (let m = 1; ; m++) {
1459
1556
  if (_obj[m] === undefined) {
1460
1557
  _obj[m] = [];
1461
- addFrame = m;
1558
+ dataCnts = m;
1462
1559
  break;
1463
1560
  }
1464
1561
  }
1465
1562
  }
1466
- return [_obj, addFrame];
1563
+ return [_obj, dataCnts];
1467
1564
  };
1468
1565
 
1469
1566
  /**
1470
1567
  * 多層スプライトデータの作成処理
1471
- * @param {array} _data
1568
+ * @param {string} _data
1472
1569
  * @param {function} _calcFrame
1473
1570
  */
1474
1571
  const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
@@ -1485,12 +1582,8 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
1485
1582
  }
1486
1583
 
1487
1584
  // 値チェックとエスケープ処理
1488
- let tmpFrame;
1489
- if (setIntVal(tmpSpriteData[0], -1) === 0) {
1490
- tmpFrame = 0;
1491
- } else {
1492
- tmpFrame = roundZero(_calcFrame(setVal(tmpSpriteData[0], 200, C_TYP_CALC)));
1493
- }
1585
+ const tmpFrame = setIntVal(tmpSpriteData[0], -1) === 0 ? 0 :
1586
+ roundZero(_calcFrame(setVal(tmpSpriteData[0], 200, C_TYP_CALC)));
1494
1587
  const tmpDepth = (tmpSpriteData[1] === C_FLG_ALL ? C_FLG_ALL : setVal(tmpSpriteData[1], 0, C_TYP_CALC));
1495
1588
  if (tmpDepth !== C_FLG_ALL && tmpDepth > maxDepth) {
1496
1589
  maxDepth = tmpDepth;
@@ -1512,23 +1605,15 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
1512
1605
  if (setVal(tmpSpriteData[11], g_presetObj.animationFillMode) !== undefined) {
1513
1606
  tmpObj.animationFillMode = setVal(tmpSpriteData[11], g_presetObj.animationFillMode);
1514
1607
  }
1515
- if (g_headerObj.autoPreload) {
1516
- if (checkImage(tmpObj.path)) {
1517
- if (g_headerObj.syncBackPath) {
1518
- const [file, dir] = getFilePath(tmpObj.path, `./`);
1519
- tmpObj.path = `${dir}${file}`;
1520
- }
1521
- preloadFile(`image`, tmpObj.path);
1522
- }
1523
- }
1608
+ tmpObj.path = preloadImgFile(tmpObj.path, { syncBackPath: g_headerObj.syncBackPath });
1524
1609
 
1525
- let addFrame = 0;
1526
- [spriteData[tmpFrame], addFrame] =
1610
+ let dataCnts = 0;
1611
+ [spriteData[tmpFrame], dataCnts] =
1527
1612
  checkDuplicatedObjects(spriteData[tmpFrame]);
1528
1613
 
1529
1614
  const emptyPatterns = [``, `[loop]`, `[jump]`];
1530
1615
  const colorObjFlg = tmpSpriteData[2]?.startsWith(`[c]`) || false;
1531
- const spriteFrameData = spriteData[tmpFrame][addFrame] = {
1616
+ const spriteFrameData = spriteData[tmpFrame][dataCnts] = {
1532
1617
  depth: tmpDepth,
1533
1618
  };
1534
1619
 
@@ -1542,7 +1627,7 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
1542
1627
  animationName: tmpObj.animationName,
1543
1628
  animationDuration: `${tmpObj.animationDuration}s`,
1544
1629
  };
1545
- spriteFrameData.colorObjId = `${tmpFrame}_${addFrame}`;
1630
+ spriteFrameData.colorObjId = `${tmpFrame}_${dataCnts}`;
1546
1631
  spriteFrameData.colorObjClass = setVal(tmpObj.class, undefined);
1547
1632
  if (tmpObj.animationFillMode !== undefined) {
1548
1633
  spriteFrameData.colorObjInfo.animationFillMode = tmpObj.animationFillMode;
@@ -1564,6 +1649,34 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
1564
1649
  return [spriteData, maxDepth];
1565
1650
  };
1566
1651
 
1652
+ /**
1653
+ * スタイル変更データの作成処理
1654
+ * @param {string} _data
1655
+ * @param {function} _calcFrame
1656
+ * @returns
1657
+ */
1658
+ const makeStyleData = (_data, _calcFrame = _frame => _frame) => {
1659
+ const spriteData = [];
1660
+ splitLF(_data).filter(data => hasVal(data)).forEach(tmpData => {
1661
+ const tmpSpriteData = tmpData.split(`,`);
1662
+
1663
+ // カスタムプロパティの名称(--始まり)で無い場合はコメントと見做してスキップ
1664
+ if (tmpSpriteData.length <= 1 || !tmpSpriteData[1].startsWith(`--`)) {
1665
+ return;
1666
+ }
1667
+ const tmpFrame = setIntVal(tmpSpriteData[0], -1) === 0 ? 0 :
1668
+ roundZero(_calcFrame(setVal(tmpSpriteData[0], 200, C_TYP_CALC)));
1669
+
1670
+ let dataCnts = 0;
1671
+ [spriteData[tmpFrame], dataCnts] = checkDuplicatedObjects(spriteData[tmpFrame]);
1672
+ spriteData[tmpFrame][dataCnts] = {
1673
+ depth: tmpSpriteData[1],
1674
+ styleData: getCssCustomProperty(tmpSpriteData[1], tmpSpriteData[2]),
1675
+ };
1676
+ });
1677
+ return [spriteData, 1];
1678
+ };
1679
+
1567
1680
  /**
1568
1681
  * 画像ファイルかどうかをチェック
1569
1682
  * @param {string} _str
@@ -1652,6 +1765,22 @@ const drawSpriteData = (_frame, _displayName, _depthName) => {
1652
1765
  const drawMainSpriteData = (_frame, _depthName) =>
1653
1766
  g_scoreObj[`${_depthName}Data`][_frame].forEach(tmpObj => drawBaseSpriteData(tmpObj, _depthName));
1654
1767
 
1768
+ /**
1769
+ * スタイル切替
1770
+ * @param {number} _frame
1771
+ * @param {string} _displayName
1772
+ */
1773
+ const drawStyleData = (_frame, _displayName) => {
1774
+ g_headerObj[`style${toCapitalize(_displayName)}Data`][_frame].forEach(tmpObj =>
1775
+ document.documentElement.style.setProperty(tmpObj.depth, tmpObj.styleData));
1776
+
1777
+ return _frame;
1778
+ };
1779
+
1780
+ const drawMainStyleData = (_frame) =>
1781
+ g_scoreObj.styleData[_frame].forEach(tmpObj =>
1782
+ document.documentElement.style.setProperty(tmpObj.depth, tmpObj.styleData));
1783
+
1655
1784
  /**
1656
1785
  * タイトル・リザルトモーションの描画
1657
1786
  * @param {string} _displayName
@@ -1660,7 +1789,7 @@ const drawTitleResultMotion = _displayName => {
1660
1789
  g_animationData.forEach(sprite => {
1661
1790
  const spriteName = `${sprite}${toCapitalize(_displayName)}`;
1662
1791
  if (g_headerObj[`${spriteName}Data`][g_scoreObj[`${spriteName}FrameNum`]] !== undefined) {
1663
- g_scoreObj[`${spriteName}FrameNum`] = drawSpriteData(g_scoreObj[`${spriteName}FrameNum`], _displayName, sprite);
1792
+ g_scoreObj[`${spriteName}FrameNum`] = g_animationFunc.draw[sprite](g_scoreObj[`${spriteName}FrameNum`], _displayName, sprite);
1664
1793
  }
1665
1794
  });
1666
1795
  };
@@ -1863,7 +1992,7 @@ const initialControl = async () => {
1863
1992
  await loadChartFile(0);
1864
1993
 
1865
1994
  // 共通設定ファイルの指定
1866
- let [settingType, settingRoot] = getFilePath(g_rootObj.settingType ?? ``, C_DIR_JS);
1995
+ let [settingType, settingRoot] = getFilePath(g_rootObj.settingType ?? ``);
1867
1996
  if (settingType !== ``) {
1868
1997
  settingType = `_${settingType}`;
1869
1998
  }
@@ -2544,6 +2673,19 @@ const headerConvert = _dosObj => {
2544
2673
  // ヘッダー群の格納先
2545
2674
  const obj = {};
2546
2675
 
2676
+ // 自動プリロードの設定
2677
+ obj.autoPreload = setBoolVal(_dosObj.autoPreload, true);
2678
+ g_headerObj.autoPreload = obj.autoPreload;
2679
+
2680
+ // デフォルトスタイルのバックアップ
2681
+ getCssCustomProperties();
2682
+
2683
+ // 初期で変更するカスタムプロパティを設定
2684
+ Object.keys(_dosObj).filter(val => val.startsWith(`--`) && hasVal(_dosObj[val])).forEach(prop => {
2685
+ g_cssBkProperties[prop] = getCssCustomProperty(prop, _dosObj[prop]);
2686
+ document.documentElement.style.setProperty(prop, g_cssBkProperties[prop]);
2687
+ });
2688
+
2547
2689
  // フォントの設定
2548
2690
  obj.customFont = _dosObj.customFont ?? ``;
2549
2691
  g_headerObj.customFont = obj.customFont;
@@ -2890,10 +3032,6 @@ const headerConvert = _dosObj => {
2890
3032
  // ハッシュタグ
2891
3033
  obj.hashTag = _dosObj.hashTag ?? ``;
2892
3034
 
2893
- // 自動プリロードの設定
2894
- obj.autoPreload = setBoolVal(_dosObj.autoPreload, true);
2895
- g_headerObj.autoPreload = obj.autoPreload;
2896
-
2897
3035
  // 読込対象の画像を指定(rel:preload)と同じ
2898
3036
  obj.preloadImages = [];
2899
3037
  if (hasVal(_dosObj.preloadImages)) {
@@ -3064,7 +3202,7 @@ const headerConvert = _dosObj => {
3064
3202
  const dataList = [_dosObj[`${sprite}title${g_localeObj.val}_data`], _dosObj[`${sprite}title_data`]];
3065
3203
  const data = dataList.find((v) => v !== undefined);
3066
3204
  if (hasVal(data)) {
3067
- [obj[`${sprite}TitleData`], obj[`${sprite}TitleMaxDepth`]] = makeSpriteData(data);
3205
+ [obj[`${sprite}TitleData`], obj[`${sprite}TitleMaxDepth`]] = g_animationFunc.make[sprite](data);
3068
3206
  }
3069
3207
  });
3070
3208
 
@@ -3837,12 +3975,12 @@ const titleInit = _ => {
3837
3975
 
3838
3976
  // タイトル用フレーム初期化
3839
3977
  g_scoreObj.titleFrameNum = 0;
3840
- g_scoreObj.backTitleFrameNum = 0;
3841
- g_scoreObj.maskTitleFrameNum = 0;
3842
3978
 
3843
- // タイトル用ループカウンター
3844
- g_scoreObj.backTitleLoopCount = 0;
3845
- g_scoreObj.maskTitleLoopCount = 0;
3979
+ // タイトルアニメーション用フレーム初期化、ループカウンター設定
3980
+ g_animationData.forEach(sprite => {
3981
+ g_scoreObj[`${sprite}TitleFrameNum`] = 0;
3982
+ g_scoreObj[`${sprite}TitleLoopCount`] = 0;
3983
+ });
3846
3984
 
3847
3985
  const keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`;
3848
3986
 
@@ -4086,15 +4224,14 @@ const titleInit = _ => {
4086
4224
  // ユーザカスタムイベント(フレーム毎)
4087
4225
  g_customJsObj.titleEnterFrame.forEach(func => func());
4088
4226
 
4089
- // 背景・マスクモーション
4227
+ // 背景・マスクモーション、スキン変更
4090
4228
  drawTitleResultMotion(g_currentPage);
4091
4229
 
4092
4230
  thisTime = performance.now();
4093
4231
  buffTime = thisTime - titleStartTime - g_scoreObj.titleFrameNum * 1000 / g_fps;
4094
4232
 
4095
4233
  g_scoreObj.titleFrameNum++;
4096
- g_scoreObj.backTitleFrameNum++;
4097
- g_scoreObj.maskTitleFrameNum++;
4234
+ g_animationData.forEach(sprite => g_scoreObj[`${sprite}TitleFrameNum`]++);
4098
4235
  g_timeoutEvtTitleId = setTimeout(flowTitleTimeline, 1000 / g_fps - buffTime);
4099
4236
  };
4100
4237
 
@@ -7421,7 +7558,11 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
7421
7558
  /**
7422
7559
  * 歌詞表示、背景・マスクデータの優先順取得
7423
7560
  */
7424
- const getPriorityHeader = _ => {
7561
+ const getPriorityHeader = (_defaultHeaders = []) => {
7562
+ if (_defaultHeaders.length > 0) {
7563
+ return makeDedupliArray(_defaultHeaders);
7564
+ }
7565
+
7425
7566
  const list = [];
7426
7567
  const anotherKeyFlg = hasVal(g_keyObj[`transKey${_keyCtrlPtn}`]);
7427
7568
  let type = ``;
@@ -7508,17 +7649,17 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
7508
7649
  wordMaxDepth = tmpWordData[k + 1];
7509
7650
  }
7510
7651
 
7511
- let addFrame = 0;
7512
- [wordData[tmpWordData[k]], addFrame] =
7652
+ let dataCnts = 0;
7653
+ [wordData[tmpWordData[k]], dataCnts] =
7513
7654
  checkDuplicatedObjects(wordData[tmpWordData[k]]);
7514
7655
 
7515
7656
  if (tmpWordData.length > 3 && tmpWordData.length < 6) {
7516
7657
  tmpWordData[3] = setIntVal(tmpWordData[3], C_WOD_FRAME);
7517
- wordData[tmpWordData[0]][addFrame].push(tmpWordData[1],
7658
+ wordData[tmpWordData[0]][dataCnts].push(tmpWordData[1],
7518
7659
  escapeHtmlForEnabledTag(tmpWordData[2]), tmpWordData[3]);
7519
7660
  break;
7520
7661
  } else {
7521
- wordData[tmpWordData[k]][addFrame].push(tmpWordData[k + 1],
7662
+ wordData[tmpWordData[k]][dataCnts].push(tmpWordData[k + 1],
7522
7663
  escapeHtmlForEnabledTag(tmpWordData[k + 2] ?? ``));
7523
7664
  }
7524
7665
  }
@@ -7528,36 +7669,19 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
7528
7669
  };
7529
7670
 
7530
7671
  /**
7531
- * 背景・マスクデータの分解
7672
+ * 背景・マスク、スキン変更データの分解
7532
7673
  * @param {string} _header
7533
- * @param {string} _scoreNo
7534
- */
7535
- const makeBackgroundData = (_header, _scoreNo) => {
7536
- const dataList = [];
7537
- const addDataList = (_type = ``) => dataList.push(...getPriorityList(_header, _type, _scoreNo));
7538
- getPriorityHeader().forEach(val => addDataList(val));
7539
-
7540
- const data = dataList.find((v) => v !== undefined);
7541
- return (data !== undefined ? makeSpriteData(data, calcFrame) : [[], -1]);
7542
- };
7543
-
7544
- /**
7545
- * リザルトモーションデータ(結果画面用背景・マスクデータ)の分解
7546
- * @param {string} _header 背景、マスク (back, mask)
7547
- * @param {string} _resultType リザルトモーションの種類 (result, failedB, failedS)
7548
7674
  * @param {string} _scoreNo 譜面番号
7549
- * @param {string} _defaultType _resultTypeが無いときの代替名
7675
+ * @param {array} resultTypes リザルトモーションの種類 (result, failedB, failedS)
7550
7676
  */
7551
- const makeBackgroundResultData = (_header, _resultType, _scoreNo, _defaultType = ``) => {
7677
+ const makeBackgroundData = (_header, _scoreNo, { resultTypes = [] } = {}) => {
7552
7678
  const dataList = [];
7679
+ const calcFrameFunc = resultTypes.length > 0 ? calcFrame : undefined;
7553
7680
  const addDataList = (_type = ``) => dataList.push(...getPriorityList(_header, _type, _scoreNo));
7554
- addDataList(_resultType);
7555
- if (_defaultType !== ``) {
7556
- addDataList(_defaultType);
7557
- }
7681
+ getPriorityHeader(resultTypes).forEach(val => addDataList(val));
7558
7682
 
7559
7683
  const data = dataList.find((v) => v !== undefined);
7560
- return (data !== undefined ? makeSpriteData(data) : [[], -1]);
7684
+ return (data !== undefined ? g_animationFunc.make[_header](data, calcFrameFunc) : [[], -1]);
7561
7685
  };
7562
7686
 
7563
7687
  // 速度変化データの分解 (2つで1セット)
@@ -7607,34 +7731,30 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
7607
7731
  [obj.wordData, obj.wordMaxDepth] = makeWordData(scoreIdHeader);
7608
7732
  }
7609
7733
 
7610
- // 背景・マスクデータの分解 (下記すべてで1セット、改行区切り)
7611
- // [フレーム数, 階層, 背景パス, class(CSSで別定義), X, Y, width, height, opacity, animationName, animationDuration]
7612
- obj.maskData = [];
7613
- obj.maskMaxDepth = -1;
7614
- obj.backData = [];
7615
- obj.backMaxDepth = -1;
7616
- if (g_stateObj.d_background === C_FLG_OFF) {
7617
- } else {
7618
- g_animationData.forEach(sprite =>
7619
- [obj[`${sprite}Data`], obj[`${sprite}MaxDepth`]] = makeBackgroundData(sprite, scoreIdHeader));
7620
- }
7734
+ // 背景・マスク・スキン変更データの分解 (下記すべてで1セット、改行区切り)
7735
+ // - 背景・マスク: [フレーム数, 階層, 背景パス, class(CSSで別定義), X, Y, width, height, opacity, animationName, animationDuration, animationFillMode]
7736
+ // - スキン変更 : [フレーム数, CSSカスタムプロパティ名, 設定内容]
7737
+ g_animationData.forEach(sprite => {
7738
+ obj[`${sprite}Data`] = [];
7739
+ obj[`${sprite}MaxDepth`] = -1;
7621
7740
 
7622
- // 結果画面用・背景/マスクデータの分解 (下記すべてで1セット、改行区切り)
7623
- // [フレーム数,階層,背景パス,class(CSSで別定義),X,Y,width,height,opacity,animationName,animationDuration]
7624
- if (g_stateObj.d_background === C_FLG_OFF && g_headerObj.resultMotionSet) {
7625
- const backgroundResults = [`backResult`, `maskResult`, `backFailed`, `maskFailed`];
7626
- backgroundResults.forEach(backName => {
7627
- g_headerObj[`${backName}Data`] = [];
7628
- g_headerObj[`${backName}MaxDepth`] = -1;
7629
- });
7630
- } else {
7631
- g_animationData.forEach(sprite => {
7741
+ if (g_stateObj.d_background === C_FLG_OFF) {
7742
+ } else {
7743
+ [obj[`${sprite}Data`], obj[`${sprite}MaxDepth`]] = makeBackgroundData(sprite, scoreIdHeader);
7744
+ }
7745
+
7746
+ if (g_stateObj.d_background === C_FLG_OFF && g_headerObj.resultMotionSet) {
7747
+ [`Result`, `Failed`].forEach(backName => {
7748
+ g_headerObj[`${backName}Data`] = [];
7749
+ g_headerObj[`${backName}MaxDepth`] = -1;
7750
+ });
7751
+ } else {
7632
7752
  [g_headerObj[`${sprite}ResultData`], g_headerObj[`${sprite}ResultMaxDepth`]] =
7633
- makeBackgroundResultData(sprite, `result`, scoreIdHeader);
7753
+ makeBackgroundData(sprite, scoreIdHeader, { resultTypes: [`result`] });
7634
7754
  [g_headerObj[`${sprite}FailedData`], g_headerObj[`${sprite}FailedMaxDepth`]] =
7635
- makeBackgroundResultData(sprite, `failed${g_stateObj.lifeMode.slice(0, 1)}`, scoreIdHeader, `result`);
7636
- });
7637
- }
7755
+ makeBackgroundData(sprite, scoreIdHeader, { resultTypes: [`failed${g_stateObj.lifeMode.slice(0, 1)}`, `result`] });
7756
+ }
7757
+ });
7638
7758
 
7639
7759
  // キー変化定義
7640
7760
  obj.keychFrames = [0];
@@ -8040,6 +8160,7 @@ const pushArrows = (_dataObj, _speedOnFrame, _motionOnFrame, _firstArrivalFrame)
8040
8160
  word: (_exceptList, _j) => listMatching(_data[startNum][_j][1], _exceptList.word),
8041
8161
  back: (_exceptList, _j) => listMatching(_data[startNum][_j].animationName, _exceptList.back),
8042
8162
  mask: (_exceptList, _j) => listMatching(_data[startNum][_j].animationName, _exceptList.mask),
8163
+ style: (_exceptList, _j) => listMatching(_data[startNum][_j].depth, _exceptList.style),
8043
8164
  };
8044
8165
 
8045
8166
  const getLength = _list =>
@@ -8603,11 +8724,11 @@ const mainInit = _ => {
8603
8724
  // カラー・モーションを適用するオブジェクトの種類
8604
8725
  const objList = (g_stateObj.dummyId === `` ? [``] : [`dummy`, ``]);
8605
8726
 
8606
- // 背景・マスクモーション(0フレーム指定)
8727
+ // 背景・マスクモーション、スキン変更(0フレーム指定)
8607
8728
  if (g_scoreObj.frameNum === 0) {
8608
8729
  g_animationData.forEach(sprite => {
8609
8730
  if (g_scoreObj[`${sprite}Data`][0] !== undefined) {
8610
- drawMainSpriteData(0, sprite);
8731
+ g_animationFunc.drawMain[sprite](0, sprite);
8611
8732
  g_scoreObj[`${sprite}Data`][0] = undefined;
8612
8733
  }
8613
8734
  });
@@ -8907,7 +9028,7 @@ const mainInit = _ => {
8907
9028
  x: jdgX[j] + 170, y: jdgY[j],
8908
9029
  w: g_limitObj.jdgCharaWidth, h: g_limitObj.jdgCharaHeight, siz: g_limitObj.jdgCharaSiz,
8909
9030
  opacity: g_stateObj.opacity / 100, display: g_workObj.judgmentDisp,
8910
- }, g_cssObj[`common_${jdgCombos[j]}`]),
9031
+ }, g_cssObj[`common_combo${jdg}`]),
8911
9032
 
8912
9033
  // Fast/Slow表示
8913
9034
  createDivCss2Label(`diff${jdg}`, ``, {
@@ -9585,10 +9706,10 @@ const mainInit = _ => {
9585
9706
  }
9586
9707
  }
9587
9708
 
9588
- // 背景・マスクモーション
9709
+ // 背景・マスクモーション、スキン変更
9589
9710
  g_animationData.forEach(sprite => {
9590
9711
  if (g_scoreObj[`${sprite}Data`][currentFrame] !== undefined) {
9591
- drawMainSpriteData(currentFrame, sprite);
9712
+ g_animationFunc.drawMain[sprite](currentFrame, sprite);
9592
9713
  }
9593
9714
  });
9594
9715
 
@@ -10138,14 +10259,14 @@ const displayDiff = (_difFrame, _fjdg = ``, _justFrames = g_headerObj.justFrames
10138
10259
  g_workObj.diffList.push(_difFrame);
10139
10260
  const difCnt = Math.abs(_difFrame);
10140
10261
  if (_difFrame > g_judgObj.arrowJ[g_judgPosObj.shobon]) {
10141
- diffJDisp = `<span class="common_kita">Excessive</span>`;
10262
+ diffJDisp = `<span class="common_excessive">Excessive</span>`;
10142
10263
  g_resultObj.excessive++;
10143
10264
  lifeDamage(true);
10144
10265
  } else if (_difFrame > _justFrames) {
10145
- diffJDisp = `<span class="common_matari">Fast ${difCnt} Frames</span>`;
10266
+ diffJDisp = `<span class="common_diffFast">Fast ${difCnt} Frames</span>`;
10146
10267
  g_resultObj.fast++;
10147
10268
  } else if (_difFrame < _justFrames * (-1)) {
10148
- diffJDisp = `<span class="common_shobon">Slow ${difCnt} Frames</span>`;
10269
+ diffJDisp = `<span class="common_diffSlow">Slow ${difCnt} Frames</span>`;
10149
10270
  g_resultObj.slow++;
10150
10271
  }
10151
10272
  document.getElementById(`diff${_fjdg}J`).innerHTML = diffJDisp;
@@ -10371,12 +10492,12 @@ const resultInit = _ => {
10371
10492
 
10372
10493
  // 結果画面用フレーム初期化
10373
10494
  g_scoreObj.resultFrameNum = 0;
10374
- g_scoreObj.backResultFrameNum = 0;
10375
- g_scoreObj.maskResultFrameNum = 0;
10376
10495
 
10377
- // 結果画面用ループカウンター
10378
- g_scoreObj.backResultLoopCount = 0;
10379
- g_scoreObj.maskResultLoopCount = 0;
10496
+ // リザルトアニメーション用フレーム初期化、ループカウンター設定
10497
+ g_animationData.forEach(sprite => {
10498
+ g_scoreObj[`${sprite}ResultFrameNum`] = 0;
10499
+ g_scoreObj[`${sprite}ResultLoopCount`] = 0;
10500
+ });
10380
10501
 
10381
10502
  const divRoot = document.querySelector(`#divRoot`);
10382
10503
 
@@ -10394,14 +10515,14 @@ const resultInit = _ => {
10394
10515
  g_animationData.forEach(sprite => {
10395
10516
  const failedData = g_rootObj[`${sprite}failedS${scoreIdHeader}_data`] ?? g_rootObj[`${sprite}failedS_data`];
10396
10517
  if (failedData !== undefined) {
10397
- [g_headerObj[`${sprite}ResultData`], g_headerObj[`${sprite}ResultMaxDepth`]] = makeSpriteData(failedData);
10518
+ [g_headerObj[`${sprite}ResultData`], g_headerObj[`${sprite}ResultMaxDepth`]] = g_animationFunc.make[sprite](failedData);
10398
10519
  }
10399
10520
  });
10400
10521
  } else if (g_gameOverFlg) {
10401
- g_headerObj.backResultData = g_headerObj.backFailedData.concat();
10402
- g_headerObj.maskResultData = g_headerObj.maskFailedData.concat();
10403
- g_headerObj.backResultMaxDepth = g_headerObj.backFailedMaxDepth;
10404
- g_headerObj.maskResultMaxDepth = g_headerObj.maskFailedMaxDepth;
10522
+ g_animationData.forEach(sprite => {
10523
+ g_headerObj[`${sprite}ResultData`] = g_headerObj[`${sprite}FailedData`].concat();
10524
+ g_headerObj[`${sprite}ResultMaxDepth`] = g_headerObj[`${sprite}FailedMaxDepth`];
10525
+ });
10405
10526
  }
10406
10527
  }
10407
10528
 
@@ -10560,20 +10681,20 @@ const resultInit = _ => {
10560
10681
  ));
10561
10682
  if (g_stateObj.autoAll === C_FLG_OFF) {
10562
10683
  multiAppend(resultWindow,
10563
- makeCssResultSymbol(`lblFast`, 350, g_cssObj.common_matari, 0, g_lblNameObj.j_fast),
10564
- makeCssResultSymbol(`lblSlow`, 350, g_cssObj.common_shobon, 2, g_lblNameObj.j_slow),
10684
+ makeCssResultSymbol(`lblFast`, 350, g_cssObj.common_diffFast, 0, g_lblNameObj.j_fast),
10685
+ makeCssResultSymbol(`lblSlow`, 350, g_cssObj.common_diffSlow, 2, g_lblNameObj.j_slow),
10565
10686
  makeCssResultSymbol(`lblFastS`, 260, g_cssObj.score, 1, g_resultObj.fast, C_ALIGN_RIGHT),
10566
10687
  makeCssResultSymbol(`lblSlowS`, 260, g_cssObj.score, 3, g_resultObj.slow, C_ALIGN_RIGHT),
10567
10688
  );
10568
10689
  if (estimatedAdj !== ``) {
10569
10690
  multiAppend(resultWindow,
10570
- makeCssResultSymbol(`lblAdj`, 350, g_cssObj.common_shakin, 4, g_lblNameObj.j_adj),
10691
+ makeCssResultSymbol(`lblAdj`, 350, g_cssObj.common_estAdj, 4, g_lblNameObj.j_adj),
10571
10692
  makeCssResultSymbol(`lblAdjS`, 260, g_cssObj.score, 5, `${getDiffFrame(estimatedAdj)}`, C_ALIGN_RIGHT),
10572
10693
  );
10573
10694
  }
10574
10695
  if (g_stateObj.excessive === C_FLG_ON) {
10575
10696
  multiAppend(resultWindow,
10576
- makeCssResultSymbol(`lblExcessive`, 350, g_cssObj.common_kita, 6, g_lblNameObj.j_excessive),
10697
+ makeCssResultSymbol(`lblExcessive`, 350, g_cssObj.common_excessive, 6, g_lblNameObj.j_excessive),
10577
10698
  makeCssResultSymbol(`lblExcessiveS`, 260, g_cssObj.score, 7, g_resultObj.excessive, C_ALIGN_RIGHT),
10578
10699
  );
10579
10700
  }
@@ -10776,7 +10897,7 @@ const resultInit = _ => {
10776
10897
  g_animationData.forEach(sprite => {
10777
10898
  if (g_scoreObj[`${sprite}ResultFrameNum`] === 0) {
10778
10899
  if (g_headerObj[`${sprite}ResultData`][0] !== undefined) {
10779
- g_scoreObj[`${sprite}ResultFrameNum`] = drawSpriteData(0, `result`, sprite);
10900
+ g_scoreObj[`${sprite}ResultFrameNum`] = g_animationFunc.draw[sprite](0, `result`, sprite);
10780
10901
  g_headerObj[`${sprite}ResultData`][0] = undefined;
10781
10902
  }
10782
10903
  }
@@ -10790,7 +10911,7 @@ const resultInit = _ => {
10790
10911
  // ユーザカスタムイベント(フレーム毎)
10791
10912
  g_customJsObj.resultEnterFrame.forEach(func => func());
10792
10913
 
10793
- // 背景・マスクモーション
10914
+ // 背景・マスクモーション、スキン変更
10794
10915
  drawTitleResultMotion(g_currentPage);
10795
10916
 
10796
10917
  // リザルト画面移行後のフェードアウト処理
@@ -10813,8 +10934,7 @@ const resultInit = _ => {
10813
10934
  buffTime = thisTime - resultStartTime - g_scoreObj.resultFrameNum * 1000 / g_fps;
10814
10935
 
10815
10936
  g_scoreObj.resultFrameNum++;
10816
- g_scoreObj.backResultFrameNum++;
10817
- g_scoreObj.maskResultFrameNum++;
10937
+ g_animationData.forEach(sprite => g_scoreObj[`${sprite}ResultFrameNum`]++);
10818
10938
  g_timeoutEvtResultId = setTimeout(flowResultTimeline, 1000 / g_fps - buffTime);
10819
10939
  };
10820
10940
  flowResultTimeline();