danoniplus 26.2.0 → 26.3.1

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 : 2022/02/20
7
+ * Revised : 2022/02/23
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 26.2.0`;
12
- const g_revisedDate = `2022/02/20`;
11
+ const g_version = `Ver 26.3.1`;
12
+ const g_revisedDate = `2022/02/23`;
13
13
  const g_alphaVersion = ``;
14
14
 
15
15
  // カスタム用バージョン (danoni_custom.js 等で指定可)
@@ -49,19 +49,16 @@ const current = _ => {
49
49
  const g_rootPath = current().match(/(^.*\/)/)[0];
50
50
  const g_remoteFlg = g_rootPath.match(`^https://cwtickle.github.io/danoniplus/`) !== null;
51
51
 
52
- window.onload = _ => {
52
+ window.onload = async () => {
53
53
  g_loadObj.main = true;
54
54
  g_currentPage = `initial`;
55
55
 
56
56
  // ロード直後に定数・初期化ファイル、旧バージョン定義関数を読込
57
57
  const randTime = new Date().getTime();
58
- loadScript(`${g_rootPath}../js/lib/danoni_localbinary.js?${randTime}`, _ => {
59
- loadScript(`${g_rootPath}../js/lib/danoni_constants.js?${randTime}`, _ => {
60
- loadScript(`${g_rootPath}../js/lib/danoni_legacy_function.js?${randTime}`, _ => {
61
- initialControl();
62
- }, false);
63
- });
64
- }, false);
58
+ await loadScript2(`${g_rootPath}../js/lib/danoni_localbinary.js?${randTime}`, false);
59
+ await loadScript2(`${g_rootPath}../js/lib/danoni_constants.js?${randTime}`);
60
+ await loadScript2(`${g_rootPath}../js/lib/danoni_legacy_function.js?${randTime}`, false);
61
+ initialControl();
65
62
  };
66
63
 
67
64
  /*-----------------------------------------------------------*/
@@ -113,6 +110,7 @@ let g_finishFlg = true;
113
110
  /** 共通オブジェクト */
114
111
  const g_loadObj = {};
115
112
  const g_rootObj = {};
113
+ const g_presetObj = {};
116
114
  let g_headerObj = {};
117
115
  let g_scoreObj = {};
118
116
  let g_attrObj = {};
@@ -524,8 +522,9 @@ function preloadFile(_as, _href, _type = ``, _crossOrigin = `anonymous`) {
524
522
  }
525
523
 
526
524
  /**
527
- * CSSファイルの読み込み(danoni_main.css以外)
525
+ * CSSファイルの読み込み (callback)
528
526
  * デフォルトは danoni_skin_default.css を読み込む
527
+ * @deprecated v27以降非推奨予定
529
528
  * @param {url} _href
530
529
  * @param {function} _func
531
530
  */
@@ -546,6 +545,31 @@ function importCssFile(_href, _func) {
546
545
  document.head.appendChild(link);
547
546
  }
548
547
 
548
+ /**
549
+ * CSSファイルの読み込み (Promise)
550
+ * デフォルトは danoni_skin_default.css を読み込む
551
+ * @param {url} _href
552
+ */
553
+ function importCssFile2(_href) {
554
+ const baseUrl = _href.split(`?`)[0];
555
+ g_loadObj[baseUrl] = false;
556
+
557
+ return new Promise(resolve => {
558
+ const link = document.createElement(`link`);
559
+ link.rel = `stylesheet`;
560
+ link.href = _href;
561
+ link.onload = _ => {
562
+ g_loadObj[baseUrl] = true;
563
+ resolve(link);
564
+ };
565
+ link.onerror = _ => {
566
+ makeWarningWindow(g_msgInfoObj.E_0041.split(`{0}`).join(baseUrl), { resetFlg: `title` });
567
+ resolve(link);
568
+ };
569
+ document.head.appendChild(link);
570
+ });
571
+ }
572
+
549
573
  /**
550
574
  * 画面共通のフォント設定
551
575
  * @param {string} _priorityFont
@@ -720,7 +744,7 @@ function createColorObject2(_id,
720
744
  style.webkitMaskImage = `url("${g_imgObj[charaStyle]}")`;
721
745
  style.webkitMaskSize = `contain`;
722
746
  Object.keys(rest).forEach(property => style[property] = rest[property]);
723
- setAttrs(div, { color: rest.background || ``, type: charaStyle, cnt: 0, });
747
+ setAttrs(div, { color: rest.background ?? ``, type: charaStyle, cnt: 0, });
724
748
 
725
749
  return div;
726
750
  }
@@ -810,7 +834,7 @@ function createCss2Button(_id, _text, _func = _ => true, { x = 0, y = g_sHeight
810
834
  if (g_initialFlg && g_btnWaitFrame[groupName].initial) {
811
835
  } else {
812
836
  style.pointerEvents = C_DIS_NONE;
813
- setTimeout(_ => style.pointerEvents = setVal(rest.pointerEvents, `auto`, C_TYP_STRING),
837
+ setTimeout(_ => style.pointerEvents = rest.pointerEvents ?? `auto`,
814
838
  g_btnWaitFrame[groupName].b_frame * 1000 / g_fps);
815
839
  }
816
840
  }
@@ -952,8 +976,9 @@ function clearWindow(_redrawFlg = false, _customDisplayName = ``) {
952
976
  }
953
977
 
954
978
  /**
955
- * 外部jsファイルの読込
979
+ * 外部jsファイルの読込 (callback)
956
980
  * 読込可否を g_loadObj[ファイル名] で管理 (true: 読込成功, false: 読込失敗)
981
+ * @deprecated v27以降非推奨予定
957
982
  * @param {string} _url
958
983
  * @param {function} _callback
959
984
  * @param {boolean} _requiredFlg (default : true / 読込必須)
@@ -980,10 +1005,42 @@ function loadScript(_url, _callback, _requiredFlg = true, _charset = `UTF-8`) {
980
1005
  document.querySelector(`head`).appendChild(script);
981
1006
  }
982
1007
 
1008
+ /**
1009
+ * 外部jsファイルの読込 (Promise)
1010
+ * 読込可否を g_loadObj[ファイル名] で管理 (true: 読込成功, false: 読込失敗)
1011
+ * @param {string} _url
1012
+ * @param {boolean} _requiredFlg (default : true / 読込必須)
1013
+ * @param {string} _charset (default : UTF-8)
1014
+ */
1015
+ function loadScript2(_url, _requiredFlg = true, _charset = `UTF-8`) {
1016
+ const baseUrl = _url.split(`?`)[0];
1017
+ g_loadObj[baseUrl] = false;
1018
+
1019
+ return new Promise((resolve, reject) => {
1020
+ const script = document.createElement(`script`);
1021
+ script.type = `text/javascript`;
1022
+ script.src = _url;
1023
+ script.charset = _charset;
1024
+ script.onload = _ => {
1025
+ g_loadObj[baseUrl] = true;
1026
+ resolve(script);
1027
+ };
1028
+ script.onerror = _err => {
1029
+ if (_requiredFlg) {
1030
+ makeWarningWindow(g_msgInfoObj.E_0041.split(`{0}`).join(_url.split(`?`)[0]));
1031
+ reject(_err);
1032
+ } else {
1033
+ resolve(script);
1034
+ }
1035
+ };
1036
+ document.querySelector(`head`).appendChild(script);
1037
+ });
1038
+ }
1039
+
983
1040
  // WebAudioAPIでAudio要素風に再生するクラス
984
1041
  class AudioPlayer {
985
1042
  constructor() {
986
- const AudioContext = window.AudioContext || window.webkitAudioContext;
1043
+ const AudioContext = window.AudioContext ?? window.webkitAudioContext;
987
1044
  this._context = new AudioContext();
988
1045
  this._gain = this._context.createGain();
989
1046
  this._gain.connect(this._context.destination);
@@ -1155,12 +1212,12 @@ function makeSpriteData(_data, _calcFrame = _frame => _frame) {
1155
1212
  }
1156
1213
 
1157
1214
  const tmpObj = {
1158
- path: escapeHtml(setVal(tmpSpriteData[2], ``, C_TYP_STRING), g_escapeStr.escapeCode), // 画像パス or テキスト
1159
- class: escapeHtml(setVal(tmpSpriteData[3], ``, C_TYP_STRING)), // CSSクラス
1215
+ path: escapeHtml(tmpSpriteData[2] ?? ``, g_escapeStr.escapeCode), // 画像パス or テキスト
1216
+ class: escapeHtml(tmpSpriteData[3] ?? ``), // CSSクラス
1160
1217
  left: setVal(tmpSpriteData[4], 0, C_TYP_CALC), // X座標
1161
1218
  top: setVal(tmpSpriteData[5], 0, C_TYP_CALC), // Y座標
1162
1219
  width: setVal(tmpSpriteData[6], 0, C_TYP_NUMBER), // spanタグの場合は font-size
1163
- height: escapeHtml(setVal(tmpSpriteData[7], ``, C_TYP_STRING)), // spanタグの場合は color(文字列可)
1220
+ height: escapeHtml(tmpSpriteData[7] ?? ``), // spanタグの場合は color(文字列可)
1164
1221
  opacity: setVal(tmpSpriteData[8], 1, C_TYP_FLOAT),
1165
1222
  animationName: escapeHtml(setVal(tmpSpriteData[9], C_DIS_NONE, C_TYP_STRING)),
1166
1223
  animationDuration: setVal(tmpSpriteData[10], 0, C_TYP_NUMBER) / g_fps,
@@ -1289,7 +1346,120 @@ function initialControl() {
1289
1346
  loadLocalStorage();
1290
1347
 
1291
1348
  // 譜面データの読み込み
1292
- loadDos(_ => loadSettingJs(), 0);
1349
+ loadDos(_ => loadBaseFiles(), 0);
1350
+ }
1351
+
1352
+ /**
1353
+ * 共通設定ファイル、スキンファイル、カスタムファイルの読込
1354
+ */
1355
+ async function loadBaseFiles() {
1356
+
1357
+ // 共通設定ファイルの指定
1358
+ let [settingType, settingRoot] = getFilePath(g_rootObj.settingType ?? ``, C_DIR_JS);
1359
+ if (settingType !== ``) {
1360
+ settingType = `_${settingType}`;
1361
+ }
1362
+
1363
+ // 共通設定ファイルの読込
1364
+ const randTime = new Date().getTime();
1365
+ await loadScript2(`${settingRoot}danoni_setting${settingType}.js?${randTime}`, false);
1366
+ loadLegacySettingFunc();
1367
+ if (document.querySelector(`#lblLoading`) !== null) {
1368
+ divRoot.removeChild(document.querySelector(`#lblLoading`));
1369
+ }
1370
+
1371
+ // クエリで譜面番号が指定されていればセット
1372
+ g_stateObj.scoreId = setVal(getQueryParamVal(`scoreId`), 0, C_TYP_NUMBER);
1373
+
1374
+ // 譜面ヘッダーの読込
1375
+ Object.assign(g_headerObj, preheaderConvert(g_rootObj));
1376
+
1377
+ // CSSファイル内のbackgroundを取得するために再描画
1378
+ if (document.querySelector(`#layer0`) === null) {
1379
+ divRoot.removeChild(document.querySelector(`#divBack`));
1380
+ createEmptySprite(divRoot, `divBack`);
1381
+ } else if (!g_headerObj.defaultSkinFlg && !g_headerObj.customBackUse) {
1382
+ createEmptySprite(divRoot, `divBack`);
1383
+ }
1384
+
1385
+ // CSSファイルの読み込み
1386
+ const skinList = g_headerObj.jsData.filter(file => file[0].indexOf(`danoni_skin`) !== -1);
1387
+ await loadMultipleFiles2(skinList, `css`);
1388
+
1389
+ // JSファイルの読み込み
1390
+ await loadMultipleFiles2(g_headerObj.jsData, `js`);
1391
+ loadLegacyCustomFunc();
1392
+
1393
+ // 譜面ヘッダー、特殊キー情報の読込
1394
+ Object.assign(g_headerObj, headerConvert(g_rootObj));
1395
+ if (g_presetObj.keysData !== undefined) {
1396
+ keysConvert(dosConvert(g_presetObj.keysData));
1397
+ g_headerObj.undefinedKeyLists = g_headerObj.undefinedKeyLists.filter(key => g_keyObj[`chara${key}_0`] === undefined);
1398
+ }
1399
+ g_headerObj.keyExtraList = keysConvert(g_rootObj, {
1400
+ keyExtraList: (g_rootObj.keyExtraList !== undefined ?
1401
+ makeDedupliArray(g_rootObj.keyExtraList.split(`,`), g_headerObj.undefinedKeyLists) : g_headerObj.undefinedKeyLists),
1402
+ });
1403
+
1404
+ // キー数情報を初期化
1405
+ g_keyObj.currentKey = g_headerObj.keyLabels[g_stateObj.scoreId];
1406
+ g_keyObj.currentPtn = 0;
1407
+
1408
+ // 画像ファイルの読み込み
1409
+ g_imgInitList.forEach(img => preloadFile(`image`, g_imgObj[img]));
1410
+
1411
+ // その他の画像ファイルの読み込み
1412
+ g_headerObj.preloadImages.filter(image => hasVal(image)).forEach(preloadImage => {
1413
+
1414
+ // Pattern A: |preloadImages=file.png|
1415
+ // Pattern B: |preloadImages=file*.png@10| -> file01.png ~ file10.png
1416
+ // Pattern C: |preloadImages=file*.png@2-9| -> file2.png ~ file9.png
1417
+ // Pattern D: |preloadImages=file*.png@003-018| -> file003.png ~ file018.png
1418
+
1419
+ const tmpPreloadImages = preloadImage.split(`@`);
1420
+ if (tmpPreloadImages.length === 1) {
1421
+ // Pattern Aの場合
1422
+ preloadFile(`image`, preloadImage);
1423
+ } else {
1424
+ const termRoopCnts = tmpPreloadImages[1].split(`-`);
1425
+ let startCnt = 1;
1426
+ let lastCnt;
1427
+ let paddingLen;
1428
+
1429
+ if (termRoopCnts.length === 1) {
1430
+ // Pattern Bの場合
1431
+ lastCnt = setVal(tmpPreloadImages[1], 1, C_TYP_NUMBER);
1432
+ paddingLen = String(setVal(tmpPreloadImages[1], 1, C_TYP_STRING)).length;
1433
+ } else {
1434
+ // Pattern C, Dの場合
1435
+ startCnt = setVal(termRoopCnts[0], 1, C_TYP_NUMBER);
1436
+ lastCnt = setVal(termRoopCnts[1], 1, C_TYP_NUMBER);
1437
+ paddingLen = String(setVal(termRoopCnts[1], 1, C_TYP_STRING)).length;
1438
+ }
1439
+ for (let k = startCnt; k <= lastCnt; k++) {
1440
+ preloadFile(`image`, tmpPreloadImages[0].replace(/\*/g, String(k).padStart(paddingLen, `0`)));
1441
+ }
1442
+ }
1443
+ });
1444
+
1445
+ // ローカルファイル起動時に各種警告文を表示
1446
+ if (g_isFile) {
1447
+ makeWarningWindow(g_msgInfoObj.W_0011);
1448
+ if (!listMatching(getMusicUrl(g_stateObj.scoreId), [`.js`, `.txt`], { suffix: `$` })) {
1449
+ if (g_userAgent.indexOf(`firefox`) !== -1) {
1450
+ makeWarningWindow(g_msgInfoObj.W_0001);
1451
+ }
1452
+ makeWarningWindow(g_msgInfoObj.W_0012);
1453
+ }
1454
+ }
1455
+
1456
+ if (g_loadObj.main) {
1457
+ // 譜面詳細情報取得のために譜面をロード
1458
+ loadDos(_ => getScoreDetailData(0), 0, true);
1459
+ } else {
1460
+ getScoreDetailData(0);
1461
+ reloadDos(0);
1462
+ }
1293
1463
  }
1294
1464
 
1295
1465
  /**
@@ -1324,7 +1494,7 @@ function loadLocalStorage() {
1324
1494
  g_localeObj.val = g_langStorage.locale;
1325
1495
  g_localeObj.num = g_localeObj.list.findIndex(val => val === g_localeObj.val);
1326
1496
  }
1327
- Object.keys(g_lang_msgInfoObj[g_localeObj.val]).forEach(property => g_msgInfoObj[property] = g_lang_msgInfoObj[g_localeObj.val][property]);
1497
+ Object.assign(g_msgInfoObj, g_lang_msgInfoObj[g_localeObj.val]);
1328
1498
 
1329
1499
  // 作品別ローカルストレージの読込
1330
1500
  const checkStorage = localStorage.getItem(g_localStorageUrl);
@@ -1357,7 +1527,7 @@ function loadLocalStorage() {
1357
1527
  * @param {number} _scoreId 譜面番号
1358
1528
  * @param {boolean} _cyclicFlg 再読込フラグ(譜面詳細情報取得用、再帰的にloadDosを呼び出す)
1359
1529
  */
1360
- function loadDos(_afterFunc, _scoreId = g_stateObj.scoreId, _cyclicFlg = false) {
1530
+ async function loadDos(_afterFunc, _scoreId = g_stateObj.scoreId, _cyclicFlg = false) {
1361
1531
 
1362
1532
  const dosInput = document.querySelector(`#dos`);
1363
1533
  const externalDosInput = document.querySelector(`#externalDos`);
@@ -1410,37 +1580,36 @@ function loadDos(_afterFunc, _scoreId = g_stateObj.scoreId, _cyclicFlg = false)
1410
1580
  `${filenameCommon}${setScoreIdHeader(_scoreId)}.${filenameExtension}`);
1411
1581
 
1412
1582
  const randTime = new Date().getTime();
1413
- loadScript(`${filename}?${randTime}`, _ => {
1414
- if (typeof externalDosInit === C_TYP_FUNCTION) {
1415
- if (document.querySelector(`#lblLoading`) !== null) {
1416
- divRoot.removeChild(document.querySelector(`#lblLoading`));
1417
- }
1418
-
1419
- // 外部データを読込(ファイルが見つからなかった場合は譜面追記をスキップ)
1420
- externalDosInit();
1421
- if (g_loadObj[filename]) {
1422
- Object.assign(g_rootObj, dosConvert(g_externalDos));
1423
- }
1583
+ await loadScript2(`${filename}?${randTime}`, false, charset);
1584
+ if (typeof externalDosInit === C_TYP_FUNCTION) {
1585
+ if (document.querySelector(`#lblLoading`) !== null) {
1586
+ divRoot.removeChild(document.querySelector(`#lblLoading`));
1587
+ }
1424
1588
 
1425
- } else {
1426
- makeWarningWindow(g_msgInfoObj.E_0022);
1589
+ // 外部データを読込(ファイルが見つからなかった場合は譜面追記をスキップ)
1590
+ externalDosInit();
1591
+ if (g_loadObj[filename]) {
1592
+ Object.assign(g_rootObj, dosConvert(g_externalDos));
1427
1593
  }
1428
- _afterFunc();
1429
- if (_cyclicFlg) {
1430
- if (g_stateObj.dosDivideFlg && _scoreId > 0) {
1431
- // 初期矢印・フリーズアロー色の再定義
1432
- if (g_stateObj.scoreLockFlg) {
1433
- Object.assign(g_rootObj, copySetColor(g_rootObj, _scoreId));
1434
- }
1435
- Object.assign(g_headerObj, resetBaseColorList(g_headerObj, g_rootObj, { scoreId: _scoreId }));
1436
1594
 
1437
- // ライフ設定のカスタム部分再取得(譜面ヘッダー加味)
1438
- Object.assign(g_gaugeOptionObj, resetCustomGauge(g_rootObj, { scoreId: _scoreId }));
1439
- Object.keys(g_gaugeOptionObj.customFulls).forEach(gaugePtn => getGaugeSetting(g_rootObj, gaugePtn, g_headerObj.difLabels.length, { scoreId: _scoreId }));
1595
+ } else {
1596
+ makeWarningWindow(g_msgInfoObj.E_0022);
1597
+ }
1598
+ _afterFunc();
1599
+ if (_cyclicFlg) {
1600
+ if (g_stateObj.dosDivideFlg && _scoreId > 0) {
1601
+ // 初期矢印・フリーズアロー色の再定義
1602
+ if (g_stateObj.scoreLockFlg) {
1603
+ Object.assign(g_rootObj, copySetColor(g_rootObj, _scoreId));
1440
1604
  }
1441
- reloadDos(_scoreId);
1605
+ Object.assign(g_headerObj, resetBaseColorList(g_headerObj, g_rootObj, { scoreId: _scoreId }));
1606
+
1607
+ // ライフ設定のカスタム部分再取得(譜面ヘッダー加味)
1608
+ Object.assign(g_gaugeOptionObj, resetCustomGauge(g_rootObj, { scoreId: _scoreId }));
1609
+ Object.keys(g_gaugeOptionObj.customFulls).forEach(gaugePtn => getGaugeSetting(g_rootObj, gaugePtn, g_headerObj.difLabels.length, { scoreId: _scoreId }));
1442
1610
  }
1443
- }, false, charset);
1611
+ reloadDos(_scoreId);
1612
+ }
1444
1613
  }
1445
1614
  }
1446
1615
 
@@ -1478,110 +1647,6 @@ function copySetColor(_baseObj, _scoreId) {
1478
1647
  return obj;
1479
1648
  }
1480
1649
 
1481
- /**
1482
- * 初回読込後に画像プリロードを設定する処理
1483
- */
1484
- function initAfterDosLoaded() {
1485
-
1486
- // クエリで譜面番号が指定されていればセット
1487
- g_stateObj.scoreId = setVal(getQueryParamVal(`scoreId`), 0, C_TYP_NUMBER);
1488
-
1489
- // 譜面ヘッダーの読込
1490
- Object.assign(g_headerObj, preheaderConvert(g_rootObj));
1491
-
1492
- // CSSファイル内のbackgroundを取得するために再描画
1493
- if (document.querySelector(`#layer0`) === null) {
1494
- divRoot.removeChild(document.querySelector(`#divBack`));
1495
- createEmptySprite(divRoot, `divBack`);
1496
- } else if (!g_headerObj.defaultSkinFlg && !g_headerObj.customBackUse) {
1497
- createEmptySprite(divRoot, `divBack`);
1498
- }
1499
-
1500
- // CSSファイルの読み込み
1501
- const skinList = g_headerObj.jsData.filter(file => file[0].indexOf(`danoni_skin`) !== -1);
1502
- loadMultipleFiles(0, skinList, `css`, _ => initAfterCssLoaded());
1503
-
1504
- /**
1505
- * スキンCSSファイルを読み込んだ後の処理
1506
- */
1507
- function initAfterCssLoaded() {
1508
-
1509
- // 譜面ヘッダー、特殊キー情報の読込
1510
- Object.assign(g_headerObj, headerConvert(g_rootObj));
1511
- if (typeof g_presetKeysData === C_TYP_STRING) {
1512
- keysConvert(dosConvert(g_presetKeysData));
1513
- g_headerObj.undefinedKeyLists = g_headerObj.undefinedKeyLists.filter(key => g_keyObj[`chara${key}_0`] === undefined);
1514
- }
1515
- g_headerObj.keyExtraList = keysConvert(g_rootObj, {
1516
- keyExtraList: (g_rootObj.keyExtraList !== undefined ?
1517
- makeDedupliArray(g_rootObj.keyExtraList.split(`,`), g_headerObj.undefinedKeyLists) : g_headerObj.undefinedKeyLists),
1518
- });
1519
-
1520
- // キー数情報を初期化
1521
- g_keyObj.currentKey = g_headerObj.keyLabels[g_stateObj.scoreId];
1522
- g_keyObj.currentPtn = 0;
1523
-
1524
- // 画像ファイルの読み込み
1525
- g_imgInitList.forEach(img => preloadFile(`image`, g_imgObj[img]));
1526
-
1527
- // その他の画像ファイルの読み込み
1528
- g_headerObj.preloadImages.filter(image => hasVal(image)).forEach(preloadImage => {
1529
-
1530
- // Pattern A: |preloadImages=file.png|
1531
- // Pattern B: |preloadImages=file*.png@10| -> file01.png ~ file10.png
1532
- // Pattern C: |preloadImages=file*.png@2-9| -> file2.png ~ file9.png
1533
- // Pattern D: |preloadImages=file*.png@003-018| -> file003.png ~ file018.png
1534
-
1535
- const tmpPreloadImages = preloadImage.split(`@`);
1536
- if (tmpPreloadImages.length === 1) {
1537
- // Pattern Aの場合
1538
- preloadFile(`image`, preloadImage);
1539
- } else {
1540
- const termRoopCnts = tmpPreloadImages[1].split(`-`);
1541
- let startCnt = 1;
1542
- let lastCnt;
1543
- let paddingLen;
1544
-
1545
- if (termRoopCnts.length === 1) {
1546
- // Pattern Bの場合
1547
- lastCnt = setVal(tmpPreloadImages[1], 1, C_TYP_NUMBER);
1548
- paddingLen = String(setVal(tmpPreloadImages[1], 1, C_TYP_STRING)).length;
1549
- } else {
1550
- // Pattern C, Dの場合
1551
- startCnt = setVal(termRoopCnts[0], 1, C_TYP_NUMBER);
1552
- lastCnt = setVal(termRoopCnts[1], 1, C_TYP_NUMBER);
1553
- paddingLen = String(setVal(termRoopCnts[1], 1, C_TYP_STRING)).length;
1554
- }
1555
- for (let k = startCnt; k <= lastCnt; k++) {
1556
- preloadFile(`image`, tmpPreloadImages[0].replace(/\*/g, String(k).padStart(paddingLen, `0`)));
1557
- }
1558
- }
1559
- });
1560
-
1561
- // ローカルファイル起動時に各種警告文を表示
1562
- if (g_isFile) {
1563
- makeWarningWindow(g_msgInfoObj.W_0011);
1564
- if (!listMatching(getMusicUrl(g_stateObj.scoreId), [`.js`, `.txt`], { suffix: `$` })) {
1565
- if (g_userAgent.indexOf(`firefox`) !== -1) {
1566
- makeWarningWindow(g_msgInfoObj.W_0001);
1567
- }
1568
- makeWarningWindow(g_msgInfoObj.W_0012);
1569
- }
1570
- }
1571
-
1572
- if (g_loadObj.main) {
1573
- // customjsの読み込み後、譜面詳細情報取得のために譜面をロード
1574
- loadMultipleFiles(0, g_headerObj.jsData, `js`, _ => {
1575
- loadLegacyCustomFunc();
1576
- loadDos(_ => getScoreDetailData(0), 0, true);
1577
- });
1578
- } else {
1579
- getScoreDetailData(0);
1580
- reloadDos(0);
1581
- }
1582
- }
1583
- }
1584
-
1585
1650
  /**
1586
1651
  * MusicUrlの基本情報を取得
1587
1652
  * @param {number} _scoreId
@@ -1589,7 +1654,7 @@ function initAfterDosLoaded() {
1589
1654
  */
1590
1655
  function getMusicUrl(_scoreId) {
1591
1656
  return g_headerObj.musicUrls !== undefined ?
1592
- g_headerObj.musicUrls[g_headerObj.musicNos[_scoreId]] ||
1657
+ g_headerObj.musicUrls[g_headerObj.musicNos[_scoreId]] ??
1593
1658
  g_headerObj.musicUrls[0] : `nosound.mp3`;
1594
1659
  }
1595
1660
 
@@ -1861,7 +1926,8 @@ function calcLevel(_scoreObj) {
1861
1926
  }
1862
1927
 
1863
1928
  /**
1864
- * jsファイルの連続読込
1929
+ * js, cssファイルの連続読込 (callback)
1930
+ * @deprecated v27以降非推奨予定
1865
1931
  * @param {number} _j
1866
1932
  * @param {array} _fileData
1867
1933
  * @param {string} _loadType
@@ -1888,6 +1954,28 @@ function loadMultipleFiles(_j, _fileData, _loadType, _afterFunc = _ => true) {
1888
1954
  }
1889
1955
  }
1890
1956
 
1957
+ /**
1958
+ * js, cssファイルの連続読込 (async function)
1959
+ * @param {array} _fileData
1960
+ * @param {string} _loadType
1961
+ */
1962
+ async function loadMultipleFiles2(_fileData, _loadType) {
1963
+ await Promise.all(_fileData.map(async filePart => {
1964
+ const filePath = `${filePart[1]}${filePart[0]}?${new Date().getTime()}`;
1965
+ if (filePart[0].endsWith(`.css`)) {
1966
+ _loadType = `css`;
1967
+ }
1968
+
1969
+ // jsファイル、cssファイルにより呼び出す関数を切替
1970
+ if (_loadType === `js`) {
1971
+ await loadScript2(filePath, false);
1972
+ } else if (_loadType === `css`) {
1973
+ const cssPath = filePath.split(`.js`).join(`.css`);
1974
+ await importCssFile2(cssPath);
1975
+ }
1976
+ }));
1977
+ }
1978
+
1891
1979
  /**
1892
1980
  * 入力されたパスを、ディレクトリとそれ以外に分割
1893
1981
  * 返却値:[ファイルキーワード, ルートディレクトリ]
@@ -1916,26 +2004,6 @@ const getFilePath = (_fileName, _directory = ``) => {
1916
2004
  }
1917
2005
  };
1918
2006
 
1919
- /**
1920
- * danoni_setting.jsの読込
1921
- */
1922
- function loadSettingJs() {
1923
-
1924
- // 共通設定ファイルの指定
1925
- let [settingType, settingRoot] = getFilePath(g_rootObj.settingType || ``, C_DIR_JS);
1926
- if (settingType !== ``) {
1927
- settingType = `_${settingType}`;
1928
- }
1929
-
1930
- const randTime = new Date().getTime();
1931
- loadScript(`${settingRoot}danoni_setting${settingType}.js?${randTime}`, _ => {
1932
- if (document.querySelector(`#lblLoading`) !== null) {
1933
- divRoot.removeChild(document.querySelector(`#lblLoading`));
1934
- }
1935
- initAfterDosLoaded();
1936
- }, false);
1937
- }
1938
-
1939
2007
  function loadMusic() {
1940
2008
 
1941
2009
  clearWindow(true);
@@ -2335,7 +2403,7 @@ const createScText = (_obj, _settingLabel, { displayName = `option`, dfLabel = `
2335
2403
  if (scKey.length > 0) {
2336
2404
  multiAppend(_obj,
2337
2405
  createDivCss2Label(`sc${_settingLabel}`,
2338
- g_scViewObj.format.split(`{0}`).join(dfLabel !== `` ? `${dfLabel}` : `${setVal(g_kCd[g_kCdN.findIndex(kCd => kCd === scKey[0])], ``, C_TYP_STRING)}`), {
2406
+ g_scViewObj.format.split(`{0}`).join(dfLabel !== `` ? `${dfLabel}` : `${g_kCd[g_kCdN.findIndex(kCd => kCd === scKey[0])] ?? ''}`), {
2339
2407
  x, y, w, siz, fontWeight: `bold`, opacity: 0.75, pointerEvents: C_DIS_NONE,
2340
2408
  })
2341
2409
  );
@@ -2351,8 +2419,8 @@ const createScTextCommon = _displayName => {
2351
2419
  .forEach(target =>
2352
2420
  createScText(document.getElementById(`btn${target}`), target, {
2353
2421
  displayName: _displayName, targetLabel: `btn${target}`,
2354
- dfLabel: setVal(g_lblNameObj[`sc_${_displayName}${target}`], ``, C_TYP_STRING),
2355
- x: g_btnPatterns[_displayName][target]
2422
+ dfLabel: g_lblNameObj[`sc_${_displayName}${target}`] ?? ``,
2423
+ x: g_btnPatterns[_displayName][target],
2356
2424
  }));
2357
2425
  }
2358
2426
 
@@ -2499,7 +2567,7 @@ function titleInit() {
2499
2567
  -webkit-text-fill-color: rgba(255,255,255,0.0);
2500
2568
  ${txtAnimations[1]}
2501
2569
  " class="${g_headerObj.titleAnimationClass[1]}">
2502
- ${setVal(g_headerObj.musicTitleForView[1], ``, C_TYP_STRING)}
2570
+ ${g_headerObj.musicTitleForView[1] ?? ``}
2503
2571
  </div>
2504
2572
  `,
2505
2573
  {
@@ -2826,30 +2894,28 @@ function preheaderConvert(_dosObj) {
2826
2894
  };
2827
2895
 
2828
2896
  // 外部スキンファイルの指定
2829
- const tmpSkinType = _dosObj.skinType || (typeof g_presetSkinType === C_TYP_STRING ? g_presetSkinType : `default`);
2897
+ const tmpSkinType = _dosObj.skinType ?? g_presetObj.skinType ?? `default`;
2830
2898
  const tmpSkinTypes = tmpSkinType.split(`,`);
2831
2899
  obj.defaultSkinFlg = tmpSkinTypes.includes(`default`);
2832
2900
  setJsFiles(tmpSkinTypes, C_DIR_SKIN, `skin`);
2833
2901
 
2834
2902
  // 外部jsファイルの指定
2835
- const tmpCustomjs = _dosObj.customjs || (typeof g_presetCustomJs === C_TYP_STRING ? g_presetCustomJs : C_JSF_CUSTOM);
2903
+ const tmpCustomjs = _dosObj.customjs ?? g_presetObj.customJs ?? C_JSF_CUSTOM;
2836
2904
  setJsFiles(tmpCustomjs.split(`,`), C_DIR_JS);
2837
2905
 
2838
2906
  // 外部cssファイルの指定
2839
- const tmpCustomcss = _dosObj.customcss || (typeof g_presetCustomCss === C_TYP_STRING ? g_presetCustomCss : ``);
2907
+ const tmpCustomcss = _dosObj.customcss ?? g_presetObj.customCss ?? ``;
2840
2908
  setJsFiles(tmpCustomcss.split(`,`), C_DIR_CSS);
2841
2909
 
2842
2910
  // デフォルト曲名表示、背景、Ready表示の利用有無
2843
2911
  g_titleLists.init.forEach(objName => {
2844
2912
  const objUpper = toCapitalize(objName);
2845
- obj[`custom${objUpper}Use`] = setVal(_dosObj[`custom${objUpper}Use`],
2846
- (typeof g_presetCustomDesignUse === C_TYP_OBJECT && (objName in g_presetCustomDesignUse) ?
2847
- setVal(g_presetCustomDesignUse[objName], false, C_TYP_BOOLEAN) : false), C_TYP_BOOLEAN);
2913
+ obj[`custom${objUpper}Use`] =
2914
+ setVal(_dosObj[`custom${objUpper}Use`] ?? g_presetObj.customDesignUse?.[objName], false, C_TYP_BOOLEAN);
2848
2915
  });
2849
2916
 
2850
2917
  // 背景・マスクモーションのパス指定方法を他の設定に合わせる設定
2851
- const tmpSyncBackPath = (typeof g_presetSyncBackPath === C_TYP_BOOLEAN ? g_presetSyncBackPath : false);
2852
- obj.syncBackPath = setVal(_dosObj.syncBackPath, tmpSyncBackPath, C_TYP_BOOLEAN);
2918
+ obj.syncBackPath = setVal(_dosObj.syncBackPath ?? g_presetObj.syncBackPath, false, C_TYP_BOOLEAN);
2853
2919
 
2854
2920
  return obj;
2855
2921
  }
@@ -2862,26 +2928,14 @@ function updateImgType(_imgType) {
2862
2928
  resetImgs(_imgType.name, _imgType.extension);
2863
2929
  reloadImgObj();
2864
2930
  Object.keys(g_imgObj).forEach(key => g_imgObj[key] = `${g_rootPath}${g_imgObj[key]}`);
2865
- if (_imgType[1] === undefined && typeof g_presetOverrideExtension === C_TYP_STRING) {
2866
- Object.keys(g_imgObj).forEach(key => g_imgObj[key] = `${g_imgObj[key].slice(0, -3)}${g_presetOverrideExtension}`);
2931
+ if (_imgType[1] === undefined && g_presetObj.overrideExtension !== undefined) {
2932
+ Object.keys(g_imgObj).forEach(key => g_imgObj[key] = `${g_imgObj[key].slice(0, -3)}${g_presetObj.overrideExtension}`);
2867
2933
  }
2868
2934
  if (!g_isFile) {
2869
2935
  g_imgInitList.forEach(img => preloadFile(`image`, g_imgObj[img]));
2870
2936
  }
2871
2937
  }
2872
2938
 
2873
- /**
2874
- * 独自で設定したラベルテキスト、オンマウステキスト、確認メッセージ定義を上書き
2875
- */
2876
- function updateLocalDesc() {
2877
- if (typeof g_local_lblNameObj === C_TYP_OBJECT && g_local_lblNameObj[g_localeObj.val] !== undefined) {
2878
- Object.keys(g_local_lblNameObj[g_localeObj.val]).forEach(property => g_lblNameObj[property] = g_local_lblNameObj[g_localeObj.val][property]);
2879
- }
2880
- if (typeof g_local_msgObj === C_TYP_OBJECT && g_local_msgObj[g_localeObj.val] !== undefined) {
2881
- Object.keys(g_local_msgObj[g_localeObj.val]).forEach(property => g_msgObj[property] = g_local_msgObj[g_localeObj.val][property]);
2882
- }
2883
- }
2884
-
2885
2939
  /**
2886
2940
  * 譜面ヘッダーの分解(その他の設定)
2887
2941
  * @param {object} _dosObj 譜面データオブジェクト
@@ -2892,7 +2946,7 @@ function headerConvert(_dosObj) {
2892
2946
  const obj = {};
2893
2947
 
2894
2948
  // フォントの設定
2895
- obj.customFont = setVal(_dosObj.customFont, ``, C_TYP_STRING);
2949
+ obj.customFont = _dosObj.customFont ?? ``;
2896
2950
  g_headerObj.customFont = obj.customFont;
2897
2951
 
2898
2952
  // 画像ルートパス、拡張子の設定 (サーバ上のみ)
@@ -2901,8 +2955,8 @@ function headerConvert(_dosObj) {
2901
2955
  let tmpImgTypes = [];
2902
2956
  if (hasVal(_dosObj.imgType)) {
2903
2957
  tmpImgTypes = _dosObj.imgType.split(`$`);
2904
- } else if (typeof g_presetImageSets === C_TYP_OBJECT) {
2905
- tmpImgTypes = g_presetImageSets.concat();
2958
+ } else if (g_presetObj.imageSets !== undefined) {
2959
+ tmpImgTypes = g_presetObj.imageSets.concat();
2906
2960
  }
2907
2961
  if (tmpImgTypes.length > 0) {
2908
2962
  tmpImgTypes.forEach((tmpImgType, j) => {
@@ -2933,9 +2987,8 @@ function headerConvert(_dosObj) {
2933
2987
  }
2934
2988
 
2935
2989
  // ラベルテキスト、オンマウステキスト、確認メッセージ定義の上書き設定
2936
- Object.keys(g_lang_lblNameObj[g_localeObj.val]).forEach(property => g_lblNameObj[property] = g_lang_lblNameObj[g_localeObj.val][property]);
2937
- Object.keys(g_lang_msgObj[g_localeObj.val]).forEach(property => g_msgObj[property] = g_lang_msgObj[g_localeObj.val][property]);
2938
- updateLocalDesc();
2990
+ Object.assign(g_lblNameObj, g_lang_lblNameObj[g_localeObj.val], g_presetObj.lblName?.[g_localeObj.val]);
2991
+ Object.assign(g_msgObj, g_lang_msgObj[g_localeObj.val], g_presetObj.msg?.[g_localeObj.val]);
2939
2992
 
2940
2993
  // 曲名
2941
2994
  obj.musicTitles = [];
@@ -2956,18 +3009,18 @@ function headerConvert(_dosObj) {
2956
3009
  if (obj.musicNos.length >= j) {
2957
3010
  obj.musicTitles[j] = escapeHtml(getMusicNameSimple(musics[0]));
2958
3011
  obj.musicTitlesForView[j] = escapeHtmlForArray(getMusicNameMultiLine(musics[0]));
2959
- obj.artistNames[j] = escapeHtml(setVal(musics[1], ``, C_TYP_STRING));
3012
+ obj.artistNames[j] = escapeHtml(musics[1] ?? ``);
2960
3013
  }
2961
3014
  }
2962
3015
  const musics = musicData[0].split(`,`);
2963
3016
  obj.musicTitle = obj.musicTitles[0];
2964
3017
  obj.musicTitleForView = obj.musicTitlesForView[0];
2965
- obj.artistName = obj.artistNames[0] || ``;
3018
+ obj.artistName = obj.artistNames[0] ?? ``;
2966
3019
  if (obj.artistName === ``) {
2967
3020
  makeWarningWindow(g_msgInfoObj.E_0011);
2968
3021
  obj.artistName = `artistName`;
2969
3022
  }
2970
- obj.artistUrl = musics[2] || ``;
3023
+ obj.artistUrl = musics[2] ?? ``;
2971
3024
  if (musics[3] !== undefined) {
2972
3025
  obj.musicTitles[0] = escapeHtml(getMusicNameSimple(musics[3]));
2973
3026
  obj.musicTitlesForView[0] = escapeHtmlForArray(getMusicNameMultiLine(musics[3]));
@@ -3003,10 +3056,10 @@ function headerConvert(_dosObj) {
3003
3056
  if (hasVal(_dosObj.tuning)) {
3004
3057
  const tunings = _dosObj.tuning.split(`,`);
3005
3058
  obj.tuning = escapeHtmlForEnabledTag(tunings[0]);
3006
- obj.creatorUrl = (tunings.length > 1 ? tunings[1] : (typeof g_presetTuningUrl === C_TYP_STRING ? g_presetTuningUrl : ``));
3059
+ obj.creatorUrl = (tunings.length > 1 ? tunings[1] : (g_presetObj.tuningUrl ?? ``));
3007
3060
  } else {
3008
- obj.tuning = (typeof g_presetTuning === C_TYP_STRING ? escapeHtmlForEnabledTag(g_presetTuning) : `name`);
3009
- obj.creatorUrl = (typeof g_presetTuningUrl === C_TYP_STRING ? g_presetTuningUrl : ``);
3061
+ obj.tuning = escapeHtmlForEnabledTag(g_presetObj.tuning ?? `name`);
3062
+ obj.creatorUrl = g_presetObj.tuningUrl ?? ``;
3010
3063
  }
3011
3064
  obj.tuningInit = obj.tuning;
3012
3065
 
@@ -3014,7 +3067,7 @@ function headerConvert(_dosObj) {
3014
3067
  if (hasVal(_dosObj.difData)) {
3015
3068
  const difs = _dosObj.difData.split(`$`);
3016
3069
  const difpos = {
3017
- key: 0, name: 1, speed: 2, border: 3, recovery: 4, damage: 5, init: 6,
3070
+ Key: 0, Name: 1, Speed: 2, Border: 3, Recovery: 4, Damage: 5, Init: 6,
3018
3071
  };
3019
3072
  obj.keyLabels = [];
3020
3073
  obj.difLabels = [];
@@ -3026,34 +3079,25 @@ function headerConvert(_dosObj) {
3026
3079
  obj.creatorNames = [];
3027
3080
  g_stateObj.scoreId = (g_stateObj.scoreId < difs.length ? g_stateObj.scoreId : 0);
3028
3081
 
3029
- const lifeData = (_name, _preData, _default) => {
3030
- const data = (_preData) ? _preData :
3031
- (typeof g_presetGauge === C_TYP_OBJECT && (_name in g_presetGauge) ?
3032
- g_presetGauge[_name] : _default);
3033
- return setVal(data, _default, C_TYP_FLOAT);
3034
- };
3035
-
3036
3082
  difs.forEach(dif => {
3037
3083
  const difDetails = dif.split(`,`);
3084
+ const lifeData = (_type, _default) =>
3085
+ setVal(difDetails[difpos[_type]] || g_presetObj.gauge?.[_type], _default, C_TYP_FLOAT);
3038
3086
 
3039
3087
  // ライフ:ノルマ、回復量、ダメージ量、初期値の設定
3040
- const border = (difDetails[difpos.border]) ? difDetails[difpos.border] :
3041
- (typeof g_presetGauge === C_TYP_OBJECT && (`Border` in g_presetGauge) ?
3042
- g_presetGauge.Border : `x`);
3043
-
3044
- obj.lifeBorders.push(border === `x` ? `x` : setVal(border, 70, C_TYP_FLOAT));
3045
- obj.lifeRecoverys.push(lifeData(`Recovery`, difDetails[difpos.recovery], 6));
3046
- obj.lifeDamages.push(lifeData(`Damage`, difDetails[difpos.damage], 40));
3047
- obj.lifeInits.push(lifeData(`Init`, difDetails[difpos.init], 25));
3088
+ obj.lifeBorders.push(lifeData(`Border`, `x`));
3089
+ obj.lifeRecoverys.push(lifeData(`Recovery`, 6));
3090
+ obj.lifeDamages.push(lifeData(`Damage`, 40));
3091
+ obj.lifeInits.push(lifeData(`Init`, 25));
3048
3092
 
3049
3093
  // キー数
3050
- const keyLabel = setVal(difDetails[difpos.key], `7`, C_TYP_STRING);
3051
- obj.keyLabels.push(g_keyObj.keyTransPattern[keyLabel] || keyLabel);
3094
+ const keyLabel = difDetails[difpos.Key] ?? `7`;
3095
+ obj.keyLabels.push(g_keyObj.keyTransPattern[keyLabel] ?? keyLabel);
3052
3096
 
3053
3097
  // 譜面名、制作者名
3054
- if (hasVal(difDetails[difpos.name])) {
3055
- const difNameInfo = difDetails[difpos.name].split(`::`);
3056
- obj.difLabels.push(escapeHtml(setVal(difNameInfo[0], `Normal`, C_TYP_STRING)));
3098
+ if (hasVal(difDetails[difpos.Name])) {
3099
+ const difNameInfo = difDetails[difpos.Name].split(`::`);
3100
+ obj.difLabels.push(escapeHtml(difNameInfo[0] ?? `Normal`));
3057
3101
  obj.creatorNames.push(difNameInfo.length > 1 ? escapeHtml(difNameInfo[1]) : obj.tuning);
3058
3102
  } else {
3059
3103
  obj.difLabels.push(`Normal`);
@@ -3061,7 +3105,7 @@ function headerConvert(_dosObj) {
3061
3105
  }
3062
3106
 
3063
3107
  // 初期速度
3064
- obj.initSpeeds.push(setVal(difDetails[difpos.speed], 3.5, C_TYP_FLOAT));
3108
+ obj.initSpeeds.push(setVal(difDetails[difpos.Speed], 3.5, C_TYP_FLOAT));
3065
3109
  });
3066
3110
  } else {
3067
3111
  makeWarningWindow(g_msgInfoObj.E_0021);
@@ -3095,7 +3139,7 @@ function headerConvert(_dosObj) {
3095
3139
  if (hasVal(_dosObj.defaultColorgrd)) {
3096
3140
  obj.defaultColorgrd = _dosObj.defaultColorgrd.split(`,`);
3097
3141
  obj.defaultColorgrd[0] = setVal(obj.defaultColorgrd[0], false, C_TYP_BOOLEAN);
3098
- obj.defaultColorgrd[1] = setVal(obj.defaultColorgrd[1], intermediateColor, C_TYP_STRING);
3142
+ obj.defaultColorgrd[1] = obj.defaultColorgrd[1] ?? intermediateColor;
3099
3143
  }
3100
3144
  g_rankObj.rankColorAllPerfect = intermediateColor;
3101
3145
 
@@ -3116,13 +3160,7 @@ function headerConvert(_dosObj) {
3116
3160
  });
3117
3161
 
3118
3162
  // フリーズアローのデフォルト色セットの利用有無 (true: 使用, false: 矢印色を優先してセット)
3119
- if (hasVal(_dosObj.defaultFrzColorUse)) {
3120
- obj.defaultFrzColorUse = setVal(_dosObj.defaultFrzColorUse, true, C_TYP_BOOLEAN);
3121
- } else if (typeof g_presetFrzColors === C_TYP_BOOLEAN) {
3122
- obj.defaultFrzColorUse = g_presetFrzColors;
3123
- } else {
3124
- obj.defaultFrzColorUse = true;
3125
- }
3163
+ obj.defaultFrzColorUse = setVal(_dosObj.defaultFrzColorUse ?? g_presetObj.frzColors, true, C_TYP_BOOLEAN);
3126
3164
 
3127
3165
  // 矢印色変化に対応してフリーズアロー色を追随する範囲の設定
3128
3166
  // (defaultFrzColorUse=false時のみ)
@@ -3133,8 +3171,8 @@ function headerConvert(_dosObj) {
3133
3171
 
3134
3172
  if (hasVal(_dosObj.frzScopeFromAC)) {
3135
3173
  tmpFrzScope.push(..._dosObj.frzScopeFromAC.split(`,`));
3136
- } else if (typeof g_presetFrzScopeFromAC === C_TYP_OBJECT) {
3137
- tmpFrzScope.push(...g_presetFrzScopeFromAC);
3174
+ } else if (g_presetObj.frzScopeFromAC !== undefined) {
3175
+ tmpFrzScope.push(...g_presetObj.frzScopeFromAC);
3138
3176
  }
3139
3177
  tmpFrzScope.filter(type => [`Normal`, `Hit`].includes(type))
3140
3178
  .forEach(data => obj.frzScopeFromArrowColors.push(data));
@@ -3158,10 +3196,10 @@ function headerConvert(_dosObj) {
3158
3196
  addGaugeFulls(g_gaugeOptionObj.survival);
3159
3197
  addGaugeFulls(g_gaugeOptionObj.border);
3160
3198
 
3161
- if (typeof g_presetGaugeList === C_TYP_OBJECT) {
3162
- Object.keys(g_presetGaugeList).forEach(key => {
3199
+ if (g_presetObj.gaugeList !== undefined) {
3200
+ Object.keys(g_presetObj.gaugeList).forEach(key => {
3163
3201
  g_gaugeOptionObj.customDefault.push(key);
3164
- g_gaugeOptionObj.varCustomDefault.push((g_presetGaugeList[key] !== `V` ? C_FLG_OFF : C_FLG_ON));
3202
+ g_gaugeOptionObj.varCustomDefault.push((g_presetObj.gaugeList[key] !== `V` ? C_FLG_OFF : C_FLG_ON));
3165
3203
  });
3166
3204
  g_gaugeOptionObj.custom = g_gaugeOptionObj.customDefault.concat();
3167
3205
  g_gaugeOptionObj.varCustom = g_gaugeOptionObj.varCustomDefault.concat();
@@ -3234,7 +3272,7 @@ function headerConvert(_dosObj) {
3234
3272
  g_diffObj.frzJdgY = (isNaN(parseFloat(_dosObj.frzJdgY)) ? 0 : parseFloat(_dosObj.frzJdgY));
3235
3273
 
3236
3274
  // musicフォルダ設定
3237
- obj.musicFolder = setVal(_dosObj.musicFolder, (g_remoteFlg ? `(..)../music` : `music`), C_TYP_STRING);
3275
+ obj.musicFolder = _dosObj.musicFolder ?? (g_remoteFlg ? `(..)../music` : `music`);
3238
3276
 
3239
3277
  // 楽曲URL
3240
3278
  if (hasVal(_dosObj.musicUrl)) {
@@ -3259,10 +3297,10 @@ function headerConvert(_dosObj) {
3259
3297
  }
3260
3298
 
3261
3299
  // 最終演出表示有無(noneで無効化)
3262
- obj.finishView = setVal(_dosObj.finishView, ``, C_TYP_STRING);
3300
+ obj.finishView = _dosObj.finishView ?? ``;
3263
3301
 
3264
3302
  // 更新日
3265
- obj.releaseDate = setVal(_dosObj.releaseDate, ``, C_TYP_STRING);
3303
+ obj.releaseDate = _dosObj.releaseDate ?? ``;
3266
3304
 
3267
3305
  // デフォルトReady/リザルト表示の遅延時間設定
3268
3306
  [`ready`, `result`].forEach(objName => {
@@ -3273,16 +3311,16 @@ function headerConvert(_dosObj) {
3273
3311
  obj.readyAnimationFrame = setVal(_dosObj.readyAnimationFrame, 150, C_TYP_NUMBER);
3274
3312
 
3275
3313
  // デフォルトReady表示のアニメーション名
3276
- obj.readyAnimationName = setVal(_dosObj.readyAnimationName, `leftToRightFade`, C_TYP_STRING);
3314
+ obj.readyAnimationName = _dosObj.readyAnimationName ?? `leftToRightFade`;
3277
3315
 
3278
3316
  // デフォルトReady表示の先頭文字色
3279
- obj.readyColor = setVal(_dosObj.readyColor, ``, C_TYP_STRING);
3317
+ obj.readyColor = _dosObj.readyColor ?? ``;
3280
3318
 
3281
3319
  // デフォルトReady表示を上書きするテキスト
3282
- obj.readyHtml = setVal(_dosObj.readyHtml, ``, C_TYP_STRING);
3320
+ obj.readyHtml = _dosObj.readyHtml ?? ``;
3283
3321
 
3284
3322
  // デフォルト曲名表示のフォントサイズ
3285
- obj.titlesize = setVal(_dosObj.titlesize, ``, C_TYP_STRING);
3323
+ obj.titlesize = _dosObj.titlesize ?? ``;
3286
3324
 
3287
3325
  // デフォルト曲名表示のフォント名
3288
3326
  // (使用例: |titlefont=Century,Meiryo UI|)
@@ -3302,7 +3340,7 @@ function headerConvert(_dosObj) {
3302
3340
  if (hasVal(_dosObj[_name])) {
3303
3341
  const tmpTitlegrd = _dosObj[_name].replace(/,/g, `:`);
3304
3342
  obj[`${_name}s`] = tmpTitlegrd.split(`$`);
3305
- obj[`${_name}`] = setVal(obj[`${_name}s`][0], ``, C_TYP_STRING);
3343
+ obj[`${_name}`] = obj[`${_name}s`][0] ?? ``;
3306
3344
  }
3307
3345
  });
3308
3346
 
@@ -3331,7 +3369,7 @@ function headerConvert(_dosObj) {
3331
3369
  }
3332
3370
  if (hasVal(_dosObj.titleanimationclass)) {
3333
3371
  _dosObj.titleanimationclass.split(`$`).forEach((animationClass, j) => {
3334
- obj.titleAnimationClass[j] = setVal(animationClass, ``, C_TYP_STRING);
3372
+ obj.titleAnimationClass[j] = animationClass ?? ``;
3335
3373
  });
3336
3374
  }
3337
3375
  if (obj.titleAnimationName.length === 1) {
@@ -3347,8 +3385,7 @@ function headerConvert(_dosObj) {
3347
3385
  obj.titlelineheight = setVal(_dosObj.titlelineheight, ``, C_TYP_NUMBER);
3348
3386
 
3349
3387
  // フリーズアローの始点で通常矢印の判定を行うか(dotさんソース方式)
3350
- obj.frzStartjdgUse = setVal(_dosObj.frzStartjdgUse,
3351
- (typeof g_presetFrzStartjdgUse === C_TYP_STRING ? setVal(g_presetFrzStartjdgUse, false, C_TYP_BOOLEAN) : false), C_TYP_BOOLEAN);
3388
+ obj.frzStartjdgUse = setVal(_dosObj.frzStartjdgUse ?? g_presetObj.frzStartjdgUse, false, C_TYP_BOOLEAN);
3352
3389
 
3353
3390
  // 譜面名に制作者名を付加するかどうかのフラグ
3354
3391
  obj.makerView = setVal(_dosObj.makerView, false, C_TYP_BOOLEAN);
@@ -3361,25 +3398,21 @@ function headerConvert(_dosObj) {
3361
3398
 
3362
3399
  // オプション利用可否設定
3363
3400
  g_canDisabledSettings.forEach(option => {
3364
- obj[`${option}Use`] = setVal(_dosObj[`${option}Use`],
3365
- (typeof g_presetSettingUse === C_TYP_OBJECT ?
3366
- setVal(g_presetSettingUse[option], true, C_TYP_BOOLEAN) : true), C_TYP_BOOLEAN);
3401
+ obj[`${option}Use`] = setVal(_dosObj[`${option}Use`] ?? g_presetObj.settingUse?.[option], true, C_TYP_BOOLEAN);
3367
3402
  });
3368
3403
 
3369
3404
  let interlockingErrorFlg = false;
3370
3405
  g_displays.forEach((option, j) => {
3371
3406
 
3372
3407
  // Display使用可否設定を分解 |displayUse=false,ON|
3373
- const displayTempUse = setVal(_dosObj[`${option}Use`],
3374
- (typeof g_presetSettingUse === C_TYP_OBJECT ?
3375
- g_presetSettingUse[option] : `true`), C_TYP_STRING);
3408
+ const displayTempUse = _dosObj[`${option}Use`] ?? g_presetObj.settingUse?.[option] ?? `true`;
3376
3409
  const displayUse = (displayTempUse !== undefined ? displayTempUse.split(`,`) : [true, C_FLG_ON]);
3377
3410
 
3378
3411
  // displayUse -> ボタンの有効/無効, displaySet -> ボタンの初期値(ON/OFF)
3379
3412
  obj[`${option}Use`] = setVal(displayUse[0], true, C_TYP_BOOLEAN);
3380
3413
  obj[`${option}Set`] = setVal(displayUse.length > 1 ? displayUse[1] :
3381
3414
  (obj[`${option}Use`] ? C_FLG_ON : C_FLG_OFF), ``, C_TYP_SWITCH);
3382
- g_stateObj[`d_${option.toLowerCase()}`] = (obj[`${option}Set`] !== `` ? obj[`${option}Set`] : C_FLG_ON);
3415
+ g_stateObj[`d_${option.toLowerCase()}`] = setVal(obj[`${option}Set`], C_FLG_ON, C_TYP_SWITCH);
3383
3416
  obj[`${option}ChainOFF`] = (_dosObj[`${option}ChainOFF`] !== undefined ? _dosObj[`${option}ChainOFF`].split(`,`) : []);
3384
3417
 
3385
3418
  // Displayのデフォルト設定で、双方向に設定されている場合は設定をブロック
@@ -3442,7 +3475,7 @@ function headerConvert(_dosObj) {
3442
3475
  obj.maskresultButton = setVal(_dosObj.maskresultButton, false, C_TYP_BOOLEAN);
3443
3476
 
3444
3477
  // color_dataの過去バージョン互換設定
3445
- obj.colorDataType = setVal(_dosObj.colorDataType, ``, C_TYP_STRING);
3478
+ obj.colorDataType = _dosObj.colorDataType ?? ``;
3446
3479
 
3447
3480
  // リザルトモーションをDisplay:BackgroundのON/OFFと連動させるかどうかの設定
3448
3481
  obj.resultMotionSet = setVal(_dosObj.resultMotionSet, true, C_TYP_BOOLEAN);
@@ -3455,8 +3488,7 @@ function headerConvert(_dosObj) {
3455
3488
 
3456
3489
  // タイトル表示用コメント
3457
3490
  const newlineTag = setVal(_dosObj.commentAutoBr, true, C_TYP_BOOLEAN) ? `<br>` : ``;
3458
- let tmpComment = setVal(_dosObj[`commentVal${g_localeObj.val}`] || _dosObj.commentVal, ``, C_TYP_STRING);
3459
- tmpComment = tmpComment.split(`\r\n`).join(`\n`);
3491
+ const tmpComment = (_dosObj[`commentVal${g_localeObj.val}`] ?? _dosObj.commentVal ?? ``).split(`\r\n`).join(`\n`);
3460
3492
  obj.commentVal = tmpComment.split(`\n`).join(newlineTag);
3461
3493
 
3462
3494
  // クレジット表示
@@ -3470,8 +3502,7 @@ function headerConvert(_dosObj) {
3470
3502
  obj.commentExternal = setVal(_dosObj.commentExternal, false, C_TYP_BOOLEAN);
3471
3503
 
3472
3504
  // Reverse時の歌詞の自動反転制御
3473
- obj.wordAutoReverse = setVal(_dosObj.wordAutoReverse,
3474
- (typeof g_presetWordAutoReverse === C_TYP_STRING ? setVal(g_presetWordAutoReverse, `auto`, C_TYP_STRING) : `auto`), C_TYP_STRING);
3505
+ obj.wordAutoReverse = _dosObj.wordAutoReverse ?? g_presetObj.wordAutoReverse ?? `auto`;
3475
3506
 
3476
3507
  // プレイサイズ(X方向)
3477
3508
  obj.playingWidth = setVal(_dosObj.playingWidth, g_sWidth, C_TYP_NUMBER);
@@ -3487,19 +3518,18 @@ function headerConvert(_dosObj) {
3487
3518
 
3488
3519
  // リザルトデータのカスタマイズ
3489
3520
  const resultFormatDefault = `【#danoni[hashTag]】[musicTitle]([keyLabel]) /[maker] /Rank:[rank]/Score:[score]/Playstyle:[playStyle]/[arrowJdg]/[frzJdg]/[maxCombo] [url]`;
3490
- obj.resultFormat = escapeHtmlForEnabledTag(setVal(_dosObj.resultFormat, (typeof g_presetResultFormat === C_TYP_STRING ?
3491
- setVal(g_presetResultFormat, resultFormatDefault, C_TYP_STRING) : resultFormatDefault), C_TYP_STRING));
3521
+ obj.resultFormat = escapeHtmlForEnabledTag(_dosObj.resultFormat ?? g_presetObj.resultFormat ?? resultFormatDefault);
3492
3522
 
3493
3523
  // フェードイン時にそれ以前のデータを蓄積しない種別(word, back, mask)を指定
3494
- obj.unStockCategories = setVal(_dosObj.unStockCategory, ``, C_TYP_STRING).split(`,`);
3495
- if (typeof g_presetUnStockCategories === C_TYP_OBJECT) {
3496
- obj.unStockCategories = makeDedupliArray(obj.unStockCategories, g_presetUnStockCategories);
3524
+ obj.unStockCategories = (_dosObj.unStockCategory ?? ``).split(`,`);
3525
+ if (g_presetObj.unStockCategories !== undefined) {
3526
+ obj.unStockCategories = makeDedupliArray(obj.unStockCategories, g_presetObj.unStockCategories);
3497
3527
  }
3498
3528
  g_fadeinStockList = g_fadeinStockList.filter(cg => obj.unStockCategories.indexOf(cg) === -1);
3499
3529
 
3500
3530
  // フェードイン時にそれ以前のデータを蓄積しないパターンを指定
3501
- if (typeof g_presetStockForceDelList === C_TYP_OBJECT) {
3502
- Object.assign(g_stockForceDelList, g_presetStockForceDelList);
3531
+ if (g_presetObj.stockForceDelList !== undefined) {
3532
+ Object.assign(g_stockForceDelList, g_presetObj.stockForceDelList);
3503
3533
  }
3504
3534
  g_fadeinStockList.forEach(type => {
3505
3535
  if (hasVal(_dosObj[`${type}StockForceDel`])) {
@@ -3776,11 +3806,11 @@ function getGaugeSetting(_dosObj, _name, _difLength, { scoreId = 0 } = {}) {
3776
3806
  }
3777
3807
  }
3778
3808
 
3779
- } else if (typeof g_presetGaugeCustom === C_TYP_OBJECT && g_presetGaugeCustom[_name]) {
3809
+ } else if (g_presetObj.gaugeCustom?.[_name] !== undefined) {
3780
3810
 
3781
3811
  const gaugeDetails = [
3782
- g_presetGaugeCustom[_name].Border, g_presetGaugeCustom[_name].Recovery,
3783
- g_presetGaugeCustom[_name].Damage, g_presetGaugeCustom[_name].Init,
3812
+ g_presetObj.gaugeCustom[_name].Border, g_presetObj.gaugeCustom[_name].Recovery,
3813
+ g_presetObj.gaugeCustom[_name].Damage, g_presetObj.gaugeCustom[_name].Init,
3784
3814
  ]
3785
3815
  if (gaugeUpdateFlg) {
3786
3816
  gaugeCreateFlg = setGaugeDetails(scoreId, gaugeDetails);
@@ -3914,7 +3944,7 @@ function keysConvert(_dosObj, { keyExtraList = _dosObj.keyExtraList.split(`,`) }
3914
3944
  let tmpMinPatterns = 1;
3915
3945
 
3916
3946
  // キーの名前 (keyNameX)
3917
- g_keyObj[`keyName${newKey}`] = setVal(_dosObj[`keyName${newKey}`], newKey, C_TYP_STRING);
3947
+ g_keyObj[`keyName${newKey}`] = _dosObj[`keyName${newKey}`] ?? newKey;
3918
3948
 
3919
3949
  // 矢印色パターン (colorX_Y)
3920
3950
  tmpMinPatterns = newKeyMultiParam(newKey, `color`, toNumber, {
@@ -5236,8 +5266,8 @@ function createLblSetting(_settingName, _adjY = 0, _settingLabel = _settingName)
5236
5266
  * @param {string} _name
5237
5267
  */
5238
5268
  function getStgDetailName(_name) {
5239
- return g_lblNameObj[`u_${_name}`] !== undefined && (typeof g_lblRenames !== C_TYP_OBJECT ||
5240
- (typeof g_lblRenames === C_TYP_OBJECT && g_lblRenames[g_currentPage])) ? g_lblNameObj[`u_${_name}`] : _name;
5269
+ return g_lblNameObj[`u_${_name}`] !== undefined &&
5270
+ (g_presetObj.lblRenames === undefined || g_presetObj.lblRenames[g_currentPage]) ? g_lblNameObj[`u_${_name}`] : _name;
5241
5271
  }
5242
5272
 
5243
5273
  /**
@@ -5291,7 +5321,7 @@ function makeDisabledLabel(_id, _heightPos, _defaultStr) {
5291
5321
  */
5292
5322
  function getKeyReverse(_localStorage, _extraKeyName = ``) {
5293
5323
  if (_localStorage[`reverse${_extraKeyName}`] !== undefined) {
5294
- g_stateObj.reverse = setVal(_localStorage[`reverse${_extraKeyName}`], C_FLG_OFF, C_TYP_STRING);
5324
+ g_stateObj.reverse = _localStorage[`reverse${_extraKeyName}`] ?? C_FLG_OFF;
5295
5325
  g_settings.reverseNum = roundZero(g_settings.reverses.findIndex(reverse => reverse === g_stateObj.reverse));
5296
5326
  } else {
5297
5327
  g_stateObj.reverse = C_FLG_OFF;
@@ -6095,7 +6125,7 @@ function keyConfigInit(_kcType = g_kcType) {
6095
6125
 
6096
6126
  // キーパターン表示
6097
6127
  const lblTransKey = hasVal(g_keyObj[`transKey${keyCtrlPtn}`]) ?
6098
- '(' + setVal(g_keyObj[`transKey${keyCtrlPtn}`], ``, C_TYP_STRING) + ')' : ``;
6128
+ `(${g_keyObj[`transKey${keyCtrlPtn}`] ?? ''})` : ``;
6099
6129
 
6100
6130
  // パターン検索
6101
6131
  const searchPattern = (_tempPtn, _sign, _transKeyUse = false, _keyCheck = `keyCtrl`) => {
@@ -6949,7 +6979,7 @@ function scoreConvert(_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
6949
6979
  break;
6950
6980
  } else {
6951
6981
  wordData[tmpWordData[k]][addFrame].push(tmpWordData[k + 1],
6952
- escapeHtmlForEnabledTag(setVal(tmpWordData[k + 2], ``, C_TYP_STRING)));
6982
+ escapeHtmlForEnabledTag(tmpWordData[k + 2] ?? ``));
6953
6983
  }
6954
6984
  }
6955
6985
  });
@@ -10035,9 +10065,9 @@ function resultInit() {
10035
10065
  .split(`[maxCombo]`).join(tweetMaxCombo)
10036
10066
  .split(`[url]`).join(`${twiturl.toString()}`.replace(/[\t\n]/g, ``));
10037
10067
 
10038
- if (typeof g_presetResultVals === C_TYP_OBJECT) {
10039
- Object.keys(g_presetResultVals).forEach(key => {
10040
- tweetResultTmp = tweetResultTmp.split(`[${key}]`).join(g_resultObj[g_presetResultVals[key]]);
10068
+ if (g_presetObj.resultVals !== undefined) {
10069
+ Object.keys(g_presetObj.resultVals).forEach(key => {
10070
+ tweetResultTmp = tweetResultTmp.split(`[${key}]`).join(g_resultObj[g_presetObj.resultVals[key]]);
10041
10071
  });
10042
10072
  }
10043
10073
  const resultText = `${unEscapeHtml(tweetResultTmp)}`;