danoniplus 32.6.0 → 32.7.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/06/30
7
+ * Revised : 2023/07/17
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 32.6.0`;
12
- const g_revisedDate = `2023/06/30`;
11
+ const g_version = `Ver 32.7.0`;
12
+ const g_revisedDate = `2023/07/17`;
13
13
 
14
14
  // カスタム用バージョン (danoni_custom.js 等で指定可)
15
15
  let g_localVersion = ``;
@@ -170,7 +170,7 @@ const g_wordObj = {
170
170
  fadeInFlg0: false,
171
171
  fadeInFlg1: false,
172
172
  fadeOutFlg0: false,
173
- fadeOutFlg1: false
173
+ fadeOutFlg1: false,
174
174
  };
175
175
 
176
176
  // オーディオ設定・タイマー管理
@@ -253,6 +253,31 @@ const convertStrToVal = _str => {
253
253
  */
254
254
  const hasVal = _data => _data !== undefined && _data !== ``;
255
255
 
256
+ /**
257
+ * 変数が存在するかどうかをチェック(null無しを含む)
258
+ * @param {string} _data
259
+ */
260
+ const hasValN = _data => hasVal(_data) && _data !== null;
261
+
262
+ /**
263
+ * 文字列から他の型へ変換する処理群
264
+ */
265
+ const g_convFunc = {
266
+ float: (_checkStr, _default) => isNaN(parseFloat(_checkStr)) ? _default : parseFloat(_checkStr),
267
+ number: (_checkStr, _default) => isNaN(parseInt(_checkStr)) ? _default : parseInt(_checkStr),
268
+ boolean: (_checkStr, _default) => _checkStr.toString().toLowerCase() === `true` ? true :
269
+ (_checkStr.toString().toLowerCase() === `false` ? false : _default),
270
+ switch: (_checkStr, _default) => [C_FLG_OFF, C_FLG_ON].includes(_checkStr.toString().toUpperCase()) ? _checkStr.toString().toUpperCase() : _default,
271
+ calc: (_checkStr, _default) => {
272
+ try {
273
+ return new Function(`return ${_checkStr}`)();
274
+ } catch (err) {
275
+ return _default;
276
+ }
277
+ },
278
+ string: (_checkStr) => _checkStr,
279
+ };
280
+
256
281
  /**
257
282
  * 文字列を想定された型に変換
258
283
  * - _type は `float`(小数)、`number`(整数)、`boolean`(真偽値)、
@@ -262,62 +287,22 @@ const hasVal = _data => _data !== undefined && _data !== ``;
262
287
  * @param {string} _default
263
288
  * @param {string} _type
264
289
  */
265
- const setVal = (_checkStr, _default, _type = C_TYP_STRING) => {
266
-
267
- let convertStr = _checkStr;
268
-
269
- // 値がundefined相当の場合は無条件でデフォルト値を返却
270
- if (_checkStr === undefined || _checkStr === null || _checkStr === ``) {
271
- return _default;
272
- }
273
-
274
- if (_type === C_TYP_FLOAT) {
275
- // 数値型(小数可)の場合
276
- const toFloat = parseFloat(_checkStr);
277
- convertStr = (isNaN(toFloat) ? _default : toFloat);
278
-
279
- } else if (_type === C_TYP_NUMBER) {
280
- // 数値型(整数のみ)の場合
281
- const toInt = parseInt(_checkStr);
282
- convertStr = (isNaN(toInt) ? _default : toInt);
283
-
284
- } else if (_type === C_TYP_BOOLEAN) {
285
- // 真偽値の場合
286
- const lowerCase = _checkStr.toString().toLowerCase();
287
- convertStr = (lowerCase === `true` ? true : (lowerCase === `false` ? false : _default));
288
-
289
- } else if (_type === C_TYP_SWITCH) {
290
- // ON/OFFスイッチの場合
291
- const toSwtich = _checkStr.toString().toUpperCase();
292
- convertStr = [C_FLG_OFF, C_FLG_ON].includes(toSwtich) ? toSwtich : _default;
293
-
294
- } else if (_type === C_TYP_CALC) {
295
- try {
296
- convertStr = new Function(`return ${_checkStr}`)();
297
- } catch (err) {
298
- convertStr = _default;
299
- }
300
- }
301
-
302
- // 文字列型の場合 (最初でチェック済みのためそのまま値を返却)
303
- return convertStr;
304
- };
290
+ const setVal = (_checkStr, _default, _type = C_TYP_STRING) =>
291
+ hasValN(_checkStr) ? g_convFunc[_type](_checkStr, _default) : _default;
305
292
 
306
293
  /**
307
294
  * ブール値への変換
308
295
  * @param {string} _val
309
- * @param {boolean} _defaultVal
310
- * @returns
296
+ * @param {boolean} _defaultVal
311
297
  */
312
- const setBoolVal = (_val, _defaultVal = false) => setVal(_val, _defaultVal, C_TYP_BOOLEAN);
298
+ const setBoolVal = (_val, _defaultVal = false) => hasValN(_val) ? g_convFunc.boolean(_val, _defaultVal) : _defaultVal;
313
299
 
314
300
  /**
315
301
  * 整数値への変換
316
302
  * @param {string} _val
317
- * @param {number} _defaultVal
318
- * @returns
303
+ * @param {number} _defaultVal
319
304
  */
320
- const setIntVal = (_val, _defaultVal = 0) => setVal(_val, _defaultVal, C_TYP_NUMBER);
305
+ const setIntVal = (_val, _defaultVal = 0) => hasValN(_val) ? g_convFunc.number(_val, _defaultVal) : _defaultVal;
321
306
 
322
307
  /**
323
308
  * 先頭のみ大文字に変換(それ以降はそのまま)
@@ -339,8 +324,7 @@ const roundZero = (_num, _init = 0) => _num < 0 ? _init : _num;
339
324
  * 配列から_targetに合致する配列位置を返す
340
325
  * 存在しない場合は0を返却
341
326
  * @param {array} _list
342
- * @param {string} _target
343
- * @returns
327
+ * @param {string} _target
344
328
  */
345
329
  const getCurrentNo = (_list, _target) => roundZero(_list.indexOf(_target));
346
330
 
@@ -348,8 +332,7 @@ const getCurrentNo = (_list, _target) => roundZero(_list.indexOf(_target));
348
332
  * 配列内に存在するかどうかをチェック
349
333
  * @param {string} _val
350
334
  * @param {array} _array
351
- * @param {integer} _pos
352
- * @returns
335
+ * @param {integer} _pos
353
336
  */
354
337
  const hasValInArray = (_val, _array, _pos = 0) =>
355
338
  _array.findIndex(data => data[_pos] === _val) !== -1;
@@ -357,47 +340,41 @@ const hasValInArray = (_val, _array, _pos = 0) =>
357
340
  /**
358
341
  * 配列が既定長以上かどうかをチェック
359
342
  * @param {array} _data
360
- * @param {integer} _length
361
- * @returns
343
+ * @param {integer} _length
362
344
  */
363
345
  const hasArrayList = (_data, _length = 1) => _data !== undefined && _data.length >= _length;
364
346
 
365
347
  /**
366
348
  * 改行コード区切りの配列展開
367
- * @param {string} _str
368
- * @returns
349
+ * @param {string} _str
369
350
  */
370
- const splitLF = _str => _str.split(`\r`).join(`\n`).split(`\n`);
351
+ const splitLF = _str => _str?.split(`\r`).join(`\n`).split(`\n`);
371
352
 
372
353
  /**
373
354
  * 改行コード区切りを本来の区切り文字に変換して配列展開
374
355
  * (改行区切りで間が空行だった場合は無効化)
375
356
  * @param {string} _str
376
- * @param {string} _delim
377
- * @returns
357
+ * @param {string} _delim
378
358
  */
379
- const splitLF2 = (_str, _delim = `$`) => splitLF(_str).filter(val => val !== ``).join(_delim).split(_delim);
359
+ const splitLF2 = (_str, _delim = `$`) => splitLF(_str)?.filter(val => val !== ``).join(_delim).split(_delim);
380
360
 
381
361
  /**
382
362
  * 重複を排除した配列の生成
383
363
  * @param {array} _array1
384
- * @param {...any} _arrays
385
- * @returns
364
+ * @param {...any} _arrays
386
365
  */
387
366
  const makeDedupliArray = (_array1, ..._arrays) =>
388
367
  Array.from((new Set([..._array1, ..._arrays.flat()])).values()).filter(val => val !== undefined);
389
368
 
390
369
  /**
391
370
  * 二次元配列のコピー
392
- * @param {array2} _array2d
393
- * @returns
371
+ * @param {array2} _array2d
394
372
  */
395
373
  const copyArray2d = _array2d => structuredClone(_array2d);
396
374
 
397
375
  /**
398
376
  * 配列データを合計
399
- * @param {array} _array
400
- * @returns
377
+ * @param {array} _array
401
378
  */
402
379
  const sumData = _array => _array.reduce((p, x) => p + x);
403
380
 
@@ -405,8 +382,7 @@ const sumData = _array => _array.reduce((p, x) => p + x);
405
382
  * 最小配列長の配列を作成
406
383
  * @param {array} _array
407
384
  * @param {number} _minLength
408
- * @param {number} _defaultVal
409
- * @returns
385
+ * @param {number} _defaultVal
410
386
  */
411
387
  const makeBaseArray = (_array = [], _minLength, _defaultVal) => padArray(_array, [...Array(_minLength)].fill(_defaultVal));
412
388
 
@@ -414,7 +390,6 @@ const makeBaseArray = (_array = [], _minLength, _defaultVal) => padArray(_array,
414
390
  * ベースとする配列に対して別の配列で上書き
415
391
  * @param {array} _array
416
392
  * @param {array} _baseArray ベースとする配列
417
- * @returns
418
393
  */
419
394
  const padArray = (_array, _baseArray) => {
420
395
  _array?.forEach((val, j) => {
@@ -432,8 +407,7 @@ const padArray = (_array, _baseArray) => {
432
407
  * [1, 3, 2, 4, 6, 4, 5] -> [[4], [6], [3, 5]]
433
408
  * [9, 6, 9, 9, 8, 7, 5] -> [[0, 2, 3]]
434
409
  * @param {array} _array
435
- * @param {number} _num
436
- * @returns
410
+ * @param {number} _num
437
411
  */
438
412
  const getMaxValIdxs = (_array, _num = 1) => {
439
413
  const getMaxVal = (_a, _b) => Math.max(_a, _b);
@@ -478,9 +452,7 @@ const fuzzyListMatching = (_str, _headerList, _footerList) =>
478
452
  */
479
453
  const replaceStr = (_str, _pairs) => {
480
454
  let tmpStr = _str;
481
- _pairs.forEach(pair => {
482
- tmpStr = tmpStr.replaceAll(pair[0], pair[1]);
483
- });
455
+ _pairs.forEach(pair => tmpStr = tmpStr.replaceAll(pair[0], pair[1]));
484
456
  return tmpStr;
485
457
  };
486
458
 
@@ -513,8 +485,7 @@ const escapeHtmlForArray = _array => _array.map(str => escapeHtml(str));
513
485
  * 次のカーソルへ移動
514
486
  * @param {number} _basePos
515
487
  * @param {number} _num
516
- * @param {number} _length
517
- * @returns
488
+ * @param {number} _length
518
489
  */
519
490
  const nextPos = (_basePos, _num, _length) => (_basePos + _length + _num) % _length;
520
491
 
@@ -616,7 +587,7 @@ const createScText = (_obj, _settingLabel, { displayName = `option`, dfLabel = `
616
587
  * 各画面の汎用ショートカットキー表示
617
588
  * @param {string} _displayName
618
589
  */
619
- const createScTextCommon = _displayName => {
590
+ const createScTextCommon = _displayName =>
620
591
  Object.keys(g_btnPatterns[_displayName]).filter(target => document.getElementById(`btn${target}`) !== null)
621
592
  .forEach(target =>
622
593
  createScText(document.getElementById(`btn${target}`), target, {
@@ -624,7 +595,6 @@ const createScTextCommon = _displayName => {
624
595
  dfLabel: g_lblNameObj[`sc_${_displayName}${target}`] ?? ``,
625
596
  x: g_btnPatterns[_displayName][target],
626
597
  }));
627
- };
628
598
 
629
599
  /**
630
600
  * ショートカットキー有効化
@@ -667,8 +637,7 @@ const openLink = _url => {
667
637
 
668
638
  /**
669
639
  * URLのフルパスを取得
670
- * @param {string} _url
671
- * @returns
640
+ * @param {string} _url
672
641
  */
673
642
  const getFullPath = _url => {
674
643
  const link = document.createElement(`a`);
@@ -832,8 +801,7 @@ const getFilePath = (_fileName, _directory = ``) => {
832
801
 
833
802
  /**
834
803
  * 対象のカラーコードが明暗どちらかを判定 (true: 明色, false: 暗色)
835
- * @param {string} _colorStr
836
- * @returns
804
+ * @param {string} _colorStr
837
805
  */
838
806
  const checkLightOrDark = _colorStr => {
839
807
  const r = parseInt(_colorStr.substring(1, 3), 16);
@@ -860,15 +828,13 @@ const byteToHex = _num => (`${_num.toString(16).padStart(2, '0')}`);
860
828
 
861
829
  /**
862
830
  * カラーコードかどうかを判定 (簡易版)
863
- * @param {string} _str
864
- * @returns
831
+ * @param {string} _str
865
832
  */
866
833
  const isColorCd = _str => _str.substring(0, 1) === `#`;
867
834
 
868
835
  /**
869
836
  * CSSの位置表記系かどうかをチェック
870
- * @param {string} _str
871
- * @returns
837
+ * @param {string} _str
872
838
  */
873
839
  const hasAnglePointInfo = _str => fuzzyListMatching(_str, g_checkStr.cssHeader, g_checkStr.cssFooter);
874
840
 
@@ -999,7 +965,6 @@ const getFontSize = (_str, _maxWidth, _font = getBasicFont(), _maxFontsize = 64,
999
965
  * @param {string} _id
1000
966
  * @param {string} _str
1001
967
  * @param {string} _altId
1002
- * @returns
1003
968
  */
1004
969
  const createDescDiv = (_id, _str, _altId = _id) =>
1005
970
  createDivCss2Label(_id, _str, Object.assign(g_lblPosObj[_altId], {
@@ -1090,8 +1055,7 @@ const createImg = (_id, _imgPath, _x, _y, _width, _height) => {
1090
1055
  * @param {string} _parentObj
1091
1056
  * @param {string} _id
1092
1057
  * @param {function} _func
1093
- * @param {object} _obj
1094
- * @returns
1058
+ * @param {object} _obj
1095
1059
  */
1096
1060
  const createColorPicker = (_parentObj, _id, _func, { x = 0, y = 0 } = {}) => {
1097
1061
  const picker = document.createElement(`input`);
@@ -1146,8 +1110,7 @@ const createColorObject2 = (_id,
1146
1110
  * @param {object} _parentObj 親スプライト
1147
1111
  * @param {string} _newObjId 作成する子スプライト名
1148
1112
  * @param {object} _obj (x, y, w, h, ...rest)
1149
- * @param {...any} _classes
1150
- * @returns
1113
+ * @param {...any} _classes
1151
1114
  */
1152
1115
  const createEmptySprite = (_parentObj, _newObjId, { x = 0, y = 0, w = g_sWidth, h = g_sHeight, title = ``, ...rest } = {}, ..._classes) => {
1153
1116
  if (document.getElementById(_newObjId) !== null) {
@@ -1517,83 +1480,84 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
1517
1480
  const tmpSpriteData = tmpData.split(`,`);
1518
1481
 
1519
1482
  // 深度が"-"の場合はスキップ
1520
- if (tmpSpriteData.length > 1 && tmpSpriteData[1] !== `-`) {
1483
+ if (tmpSpriteData.length <= 1 || tmpSpriteData[1] === `-`) {
1484
+ return;
1485
+ }
1521
1486
 
1522
- // 値チェックとエスケープ処理
1523
- let tmpFrame;
1524
- if (setIntVal(tmpSpriteData[0], -1) === 0) {
1525
- tmpFrame = 0;
1526
- } else {
1527
- tmpFrame = roundZero(_calcFrame(setVal(tmpSpriteData[0], 200, C_TYP_CALC)));
1528
- }
1529
- const tmpDepth = (tmpSpriteData[1] === C_FLG_ALL ? C_FLG_ALL : setVal(tmpSpriteData[1], 0, C_TYP_CALC));
1530
- if (tmpDepth !== C_FLG_ALL && tmpDepth > maxDepth) {
1531
- maxDepth = tmpDepth;
1532
- }
1533
-
1534
- const tmpObj = {
1535
- path: escapeHtml(tmpSpriteData[2] ?? ``, g_escapeStr.escapeCode), // 画像パス or テキスト
1536
- class: escapeHtml(tmpSpriteData[3] ?? ``), // CSSクラス
1537
- left: setVal(tmpSpriteData[4], `0`).includes(`{`) ?
1538
- `${setVal(tmpSpriteData[4], 0)}` : `{${setVal(tmpSpriteData[4], 0)}}`, // X座標
1539
- top: setVal(tmpSpriteData[5], `0`).includes(`{`) ?
1540
- `${setVal(tmpSpriteData[5], 0)}` : `{${setVal(tmpSpriteData[5], 0)}}`, // Y座標
1541
- width: `${setIntVal(tmpSpriteData[6])}`, // spanタグの場合は font-size
1542
- height: `${escapeHtml(tmpSpriteData[7] ?? ``)}`, // spanタグの場合は color(文字列可)
1543
- opacity: setVal(tmpSpriteData[8], 1, C_TYP_FLOAT),
1544
- animationName: escapeHtml(setVal(tmpSpriteData[9], C_DIS_NONE)),
1545
- animationDuration: setIntVal(tmpSpriteData[10]) / g_fps,
1546
- };
1547
- if (setVal(tmpSpriteData[11], g_presetObj.animationFillMode) !== undefined) {
1548
- tmpObj.animationFillMode = setVal(tmpSpriteData[11], g_presetObj.animationFillMode);
1549
- }
1550
- if (g_headerObj.autoPreload) {
1551
- if (checkImage(tmpObj.path)) {
1552
- if (g_headerObj.syncBackPath) {
1553
- const [file, dir] = getFilePath(tmpObj.path, `./`);
1554
- tmpObj.path = `${dir}${file}`;
1555
- }
1556
- preloadFile(`image`, tmpObj.path);
1487
+ // 値チェックとエスケープ処理
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
+ }
1494
+ const tmpDepth = (tmpSpriteData[1] === C_FLG_ALL ? C_FLG_ALL : setVal(tmpSpriteData[1], 0, C_TYP_CALC));
1495
+ if (tmpDepth !== C_FLG_ALL && tmpDepth > maxDepth) {
1496
+ maxDepth = tmpDepth;
1497
+ }
1498
+
1499
+ const tmpObj = {
1500
+ path: escapeHtml(tmpSpriteData[2] ?? ``, g_escapeStr.escapeCode), // 画像パス or テキスト
1501
+ class: escapeHtml(tmpSpriteData[3] ?? ``), // CSSクラス
1502
+ left: setVal(tmpSpriteData[4], `0`).includes(`{`) ?
1503
+ `${setVal(tmpSpriteData[4], 0)}` : `{${setVal(tmpSpriteData[4], 0)}}`, // X座標
1504
+ top: setVal(tmpSpriteData[5], `0`).includes(`{`) ?
1505
+ `${setVal(tmpSpriteData[5], 0)}` : `{${setVal(tmpSpriteData[5], 0)}}`, // Y座標
1506
+ width: `${setIntVal(tmpSpriteData[6])}`, // spanタグの場合は font-size
1507
+ height: `${escapeHtml(tmpSpriteData[7] ?? ``)}`, // spanタグの場合は color(文字列可)
1508
+ opacity: setVal(tmpSpriteData[8], 1, C_TYP_FLOAT),
1509
+ animationName: escapeHtml(setVal(tmpSpriteData[9], C_DIS_NONE)),
1510
+ animationDuration: setIntVal(tmpSpriteData[10]) / g_fps,
1511
+ };
1512
+ if (setVal(tmpSpriteData[11], g_presetObj.animationFillMode) !== undefined) {
1513
+ tmpObj.animationFillMode = setVal(tmpSpriteData[11], g_presetObj.animationFillMode);
1514
+ }
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}`;
1557
1520
  }
1521
+ preloadFile(`image`, tmpObj.path);
1558
1522
  }
1523
+ }
1559
1524
 
1560
- let addFrame = 0;
1561
- [spriteData[tmpFrame], addFrame] =
1562
- checkDuplicatedObjects(spriteData[tmpFrame]);
1563
-
1564
- const emptyPatterns = [``, `[loop]`, `[jump]`];
1565
- const colorObjFlg = tmpSpriteData[2]?.startsWith(`[c]`) || false;
1566
- spriteData[tmpFrame][addFrame] = {
1567
- depth: tmpDepth,
1568
- };
1525
+ let addFrame = 0;
1526
+ [spriteData[tmpFrame], addFrame] =
1527
+ checkDuplicatedObjects(spriteData[tmpFrame]);
1569
1528
 
1570
- if (colorObjFlg) {
1571
- // [c]始まりの場合、カラーオブジェクト用の作成準備を行う
1572
- const data = tmpObj.path.slice(`[c]`.length).split(`/`);
1573
- spriteData[tmpFrame][addFrame].colorObjInfo = {
1574
- x: tmpObj.left, y: tmpObj.top, w: tmpObj.width, h: tmpObj.height,
1575
- rotate: setVal(data[0], `0`), opacity: tmpObj.opacity,
1576
- background: makeColorGradation(setVal(data[1], `#ffffff`), { _defaultColorgrd: false }),
1577
- animationName: tmpObj.animationName,
1578
- animationDuration: `${tmpObj.animationDuration}s`,
1579
- };
1580
- spriteData[tmpFrame][addFrame].colorObjId = `${tmpFrame}_${addFrame}`;
1581
- spriteData[tmpFrame][addFrame].colorObjClass = setVal(tmpObj.class, undefined);
1582
- if (tmpObj.animationFillMode !== undefined) {
1583
- spriteData[tmpFrame][addFrame].colorObjInfo.animationFillMode = tmpObj.animationFillMode;
1584
- }
1529
+ const emptyPatterns = [``, `[loop]`, `[jump]`];
1530
+ const colorObjFlg = tmpSpriteData[2]?.startsWith(`[c]`) || false;
1531
+ const spriteFrameData = spriteData[tmpFrame][addFrame] = {
1532
+ depth: tmpDepth,
1533
+ };
1585
1534
 
1586
- } else if (emptyPatterns.includes(tmpObj.path)) {
1587
- // ループ、フレームジャンプ、空の場合の処理
1588
- spriteData[tmpFrame][addFrame].command = tmpObj.path;
1589
- spriteData[tmpFrame][addFrame].jumpFrame = tmpObj.class;
1590
- spriteData[tmpFrame][addFrame].maxLoop = tmpObj.left;
1591
- spriteData[tmpFrame][addFrame].htmlText = ``;
1592
- } else {
1593
- // それ以外の画像、テキストの場合
1594
- spriteData[tmpFrame][addFrame].animationName = tmpObj.animationName;
1595
- spriteData[tmpFrame][addFrame].htmlText = (checkImage(tmpObj.path) ? makeSpriteImage(tmpObj) : makeSpriteText(tmpObj));
1596
- }
1535
+ if (colorObjFlg) {
1536
+ // [c]始まりの場合、カラーオブジェクト用の作成準備を行う
1537
+ const data = tmpObj.path.slice(`[c]`.length).split(`/`);
1538
+ spriteFrameData.colorObjInfo = {
1539
+ x: tmpObj.left, y: tmpObj.top, w: tmpObj.width, h: tmpObj.height,
1540
+ rotate: setVal(data[0], `0`), opacity: tmpObj.opacity,
1541
+ background: makeColorGradation(setVal(data[1], `#ffffff`), { _defaultColorgrd: false }),
1542
+ animationName: tmpObj.animationName,
1543
+ animationDuration: `${tmpObj.animationDuration}s`,
1544
+ };
1545
+ spriteFrameData.colorObjId = `${tmpFrame}_${addFrame}`;
1546
+ spriteFrameData.colorObjClass = setVal(tmpObj.class, undefined);
1547
+ if (tmpObj.animationFillMode !== undefined) {
1548
+ spriteFrameData.colorObjInfo.animationFillMode = tmpObj.animationFillMode;
1549
+ }
1550
+
1551
+ } else if (emptyPatterns.includes(tmpObj.path)) {
1552
+ // ループ、フレームジャンプ、空の場合の処理
1553
+ spriteFrameData.command = tmpObj.path;
1554
+ spriteFrameData.jumpFrame = tmpObj.class;
1555
+ spriteFrameData.maxLoop = tmpObj.left;
1556
+ spriteFrameData.htmlText = ``;
1557
+ } else {
1558
+ // それ以外の画像、テキストの場合
1559
+ spriteFrameData.animationName = tmpObj.animationName;
1560
+ spriteFrameData.htmlText = (checkImage(tmpObj.path) ? makeSpriteImage(tmpObj) : makeSpriteText(tmpObj));
1597
1561
  }
1598
1562
  });
1599
1563
 
@@ -1723,10 +1687,7 @@ class AudioPlayer {
1723
1687
  this._duration = _buffer.duration;
1724
1688
  this._buffer = _buffer;
1725
1689
  });
1726
-
1727
- if (this._eventListeners[`canplaythrough`] !== undefined) {
1728
- this._eventListeners[`canplaythrough`].forEach(_listener => _listener());
1729
- }
1690
+ this._eventListeners[`canplaythrough`]?.forEach(_listener => _listener());
1730
1691
  }
1731
1692
 
1732
1693
  play(_adjustmentTime = 0) {
@@ -2208,8 +2169,7 @@ const resetColorAndGauge = _scoreId => {
2208
2169
  /**
2209
2170
  * 譜面番号固定かつ譜面ファイル分割時に初期色情報を他譜面へコピー
2210
2171
  * @param {object} _baseObj
2211
- * @param {number} _scoreId
2212
- * @returns
2172
+ * @param {number} _scoreId
2213
2173
  */
2214
2174
  const copySetColor = (_baseObj, _scoreId) => {
2215
2175
  const obj = {};
@@ -2226,8 +2186,7 @@ const copySetColor = (_baseObj, _scoreId) => {
2226
2186
 
2227
2187
  /**
2228
2188
  * MusicUrlの基本情報を取得
2229
- * @param {number} _scoreId
2230
- * @returns
2189
+ * @param {number} _scoreId
2231
2190
  */
2232
2191
  const getMusicUrl = _scoreId => {
2233
2192
  return g_headerObj.musicUrls !== undefined ?
@@ -2269,7 +2228,7 @@ const storeBaseData = (_scoreId, _scoreObj, _keyCtrlPtn) => {
2269
2228
  noteCnt.frz[j] = 0;
2270
2229
 
2271
2230
  const tmpFrzData = _scoreObj.frzData[j].filter((data, k) => k % 2 === 0);
2272
- [_scoreObj.arrowData[j], tmpFrzData].forEach((typeData, m) => {
2231
+ [_scoreObj.arrowData[j], tmpFrzData].forEach((typeData, m) =>
2273
2232
  typeData.forEach(note => {
2274
2233
  if (isNaN(parseFloat(note))) {
2275
2234
  return;
@@ -2280,8 +2239,7 @@ const storeBaseData = (_scoreId, _scoreObj, _keyCtrlPtn) => {
2280
2239
  noteCnt[types[m]][j]++;
2281
2240
  allData++;
2282
2241
  }
2283
- });
2284
- });
2242
+ }));
2285
2243
  fullData = fullData.concat(..._scoreObj.arrowData[j], ...tmpFrzData);
2286
2244
  }
2287
2245
 
@@ -2504,10 +2462,29 @@ const calcLevel = _scoreObj => {
2504
2462
  };
2505
2463
  };
2506
2464
 
2465
+ /**
2466
+ * ロケールを含んだヘッダーの優先度設定
2467
+ * @param {object} _obj
2468
+ * @param {...any} _params
2469
+ */
2470
+ const getHeader = (_obj, ..._params) => {
2471
+ let headerLocale, headerDf;
2472
+ Object.keys(_params).forEach(j => {
2473
+ headerLocale ??= _obj[`${_params[j]}${g_localeObj.val}`];
2474
+ headerDf ??= _obj[_params[j]];
2475
+ });
2476
+ return headerLocale ?? headerDf;
2477
+ };
2478
+
2479
+ /**
2480
+ * ヘッダー名の互換設定
2481
+ * @param {string} _param
2482
+ */
2483
+ const getHname = _param => [_param, _param.toLowerCase()];
2484
+
2507
2485
  /**
2508
2486
  * 譜面ヘッダーの分解(スキン、jsファイルなどの設定)
2509
- * @param {object} _dosObj
2510
- * @returns
2487
+ * @param {object} _dosObj
2511
2488
  */
2512
2489
  const preheaderConvert = _dosObj => {
2513
2490
 
@@ -2523,14 +2500,13 @@ const preheaderConvert = _dosObj => {
2523
2500
  obj.jsData = [];
2524
2501
  obj.stepRtnUse = true;
2525
2502
 
2526
- const setJsFiles = (_files, _defaultDir, _type = `custom`) => {
2503
+ const setJsFiles = (_files, _defaultDir, _type = `custom`) =>
2527
2504
  _files.forEach(file => {
2528
2505
  if (hasVal(file)) {
2529
2506
  const [jsFile, jsDir] = getFilePath(file, _defaultDir);
2530
2507
  obj.jsData.push([_type === `skin` ? `danoni_skin_${jsFile}.js` : jsFile, jsDir]);
2531
2508
  }
2532
2509
  });
2533
- };
2534
2510
 
2535
2511
  // 外部スキンファイルの指定
2536
2512
  const tmpSkinType = _dosObj.skinType ?? g_presetObj.skinType ?? `default`;
@@ -2539,11 +2515,11 @@ const preheaderConvert = _dosObj => {
2539
2515
  setJsFiles(tmpSkinTypes, C_DIR_SKIN, `skin`);
2540
2516
 
2541
2517
  // 外部jsファイルの指定
2542
- const tmpCustomjs = _dosObj.customjs ?? g_presetObj.customJs ?? C_JSF_CUSTOM;
2518
+ const tmpCustomjs = getHeader(_dosObj, ...getHname(`customJs`)) ?? g_presetObj.customJs ?? C_JSF_CUSTOM;
2543
2519
  setJsFiles(tmpCustomjs.replaceAll(`*`, g_presetObj.customJs).split(`,`), C_DIR_JS);
2544
2520
 
2545
2521
  // 外部cssファイルの指定
2546
- const tmpCustomcss = _dosObj.customcss ?? g_presetObj.customCss ?? ``;
2522
+ const tmpCustomcss = getHeader(_dosObj, ...getHname(`customCss`)) ?? g_presetObj.customCss ?? ``;
2547
2523
  setJsFiles(tmpCustomcss.replaceAll(`*`, g_presetObj.customCss).split(`,`), C_DIR_CSS);
2548
2524
 
2549
2525
  // デフォルト曲名表示、背景、Ready表示の利用有無
@@ -2568,14 +2544,6 @@ const headerConvert = _dosObj => {
2568
2544
  // ヘッダー群の格納先
2569
2545
  const obj = {};
2570
2546
 
2571
- /**
2572
- * ロケールを含んだヘッダーの取得
2573
- * @param {object} _obj
2574
- * @param {string} _param
2575
- * @returns
2576
- */
2577
- const getHeader = (_obj, _param) => _obj[`${_param}${g_localeObj.val}`] ?? _obj[_param];
2578
-
2579
2547
  // フォントの設定
2580
2548
  obj.customFont = _dosObj.customFont ?? ``;
2581
2549
  g_headerObj.customFont = obj.customFont;
@@ -2682,7 +2650,7 @@ const headerConvert = _dosObj => {
2682
2650
  obj.minSpeed = C_MIN_SPEED;
2683
2651
  obj.maxSpeed = C_MAX_SPEED;
2684
2652
  }
2685
- g_settings.speeds = [...Array((obj.maxSpeed - obj.minSpeed) * 20 + 1).keys()].map(i => obj.minSpeed + i / 20);
2653
+ g_settings.speeds = makeSpeedList(obj.minSpeed, obj.maxSpeed);
2686
2654
 
2687
2655
  // プレイ中のショートカットキー
2688
2656
  obj.keyRetry = setIntVal(getKeyCtrlVal(_dosObj.keyRetry), C_KEY_RETRY);
@@ -2964,29 +2932,30 @@ const headerConvert = _dosObj => {
2964
2932
  obj.readyHtml = _dosObj.readyHtml ?? ``;
2965
2933
 
2966
2934
  // デフォルト曲名表示のフォントサイズ
2967
- obj.titlesize = getHeader(_dosObj, `titlesize`) ?? ``;
2935
+ obj.titlesize = getHeader(_dosObj, ...getHname(`titleSize`)) ?? ``;
2968
2936
 
2969
2937
  // デフォルト曲名表示のフォント名
2970
2938
  // (使用例: |titlefont=Century,Meiryo UI|)
2971
2939
  obj.titlefonts = g_titleLists.defaultFonts.concat();
2972
- getHeader(_dosObj, `titlefont`)?.split(`$`).forEach((font, j) => obj.titlefonts[j] = `'${(font.replaceAll(`,`, `', '`))}'`);
2940
+ getHeader(_dosObj, ...getHname(`titleFont`))?.split(`$`).forEach((font, j) => obj.titlefonts[j] = `'${(font.replaceAll(`,`, `', '`))}'`);
2973
2941
  if (obj.titlefonts[1] === undefined) {
2974
2942
  obj.titlefonts[1] = obj.titlefonts[0];
2975
2943
  }
2976
2944
 
2977
2945
  // デフォルト曲名表示, 背景矢印のグラデーション指定css
2978
- g_titleLists.grdList.forEach(_name => {
2979
- obj[`${_name}s`] = [];
2980
- if (hasVal(_dosObj[_name])) {
2981
- const tmpTitlegrd = _dosObj[_name].replaceAll(`,`, `:`);
2982
- obj[`${_name}s`] = tmpTitlegrd.split(`$`);
2983
- obj[`${_name}`] = obj[`${_name}s`][0] ?? ``;
2946
+ [`titlegrd`, `titleArrowgrd`].forEach(_name => {
2947
+ const objName = `${_name.toLowerCase()}`;
2948
+ obj[`${objName}s`] = [];
2949
+ const tmpTitlegrd = getHeader(_dosObj, ...getHname(_name))?.replaceAll(`,`, `:`);
2950
+ if (hasVal(tmpTitlegrd)) {
2951
+ obj[`${objName}s`] = tmpTitlegrd.split(`$`);
2952
+ obj[`${objName}`] = obj[`${objName}s`][0] ?? ``;
2984
2953
  }
2985
2954
  });
2986
2955
 
2987
2956
  // デフォルト曲名表示の表示位置調整
2988
2957
  obj.titlepos = [[0, 0], [0, 0]];
2989
- getHeader(_dosObj, `titlepos`)?.split(`$`).forEach((pos, j) => obj.titlepos[j] = pos.split(`,`).map(x => parseFloat(x)));
2958
+ getHeader(_dosObj, ...getHname(`titlePos`))?.split(`$`).forEach((pos, j) => obj.titlepos[j] = pos.split(`,`).map(x => parseFloat(x)));
2990
2959
 
2991
2960
  // タイトル文字のアニメーション設定
2992
2961
  obj.titleAnimationName = [`leftToRight`];
@@ -2995,28 +2964,26 @@ const headerConvert = _dosObj => {
2995
2964
  obj.titleAnimationTimingFunction = [`ease`];
2996
2965
  obj.titleAnimationClass = [``];
2997
2966
 
2998
- _dosObj.titleanimation?.split(`$`).forEach((pos, j) => {
2967
+ getHeader(_dosObj, ...getHname(`titleAnimation`))?.split(`$`).forEach((pos, j) => {
2999
2968
  const titleAnimation = pos.split(`,`);
3000
2969
  obj.titleAnimationName[j] = setVal(titleAnimation[0], obj.titleAnimationName[0]);
3001
2970
  obj.titleAnimationDuration[j] = setVal(titleAnimation[1] / g_fps, obj.titleAnimationDuration[0], C_TYP_FLOAT);
3002
2971
  obj.titleAnimationDelay[j] = setVal(titleAnimation[2] / g_fps, obj.titleAnimationDelay[0], C_TYP_FLOAT);
3003
2972
  obj.titleAnimationTimingFunction[j] = setVal(titleAnimation[3], obj.titleAnimationName[3]);
3004
2973
  });
3005
- _dosObj.titleanimationclass?.split(`$`).forEach((animationClass, j) => {
3006
- obj.titleAnimationClass[j] = animationClass ?? ``;
3007
- });
2974
+ getHeader(_dosObj, ...getHname(`titleAnimationClass`))?.split(`$`).forEach((animationClass, j) =>
2975
+ obj.titleAnimationClass[j] = animationClass ?? ``);
3008
2976
 
3009
2977
  if (obj.titleAnimationName.length === 1) {
3010
- g_titleLists.animation.forEach(pattern => {
3011
- obj[`titleAnimation${pattern}`][1] = obj[`titleAnimation${pattern}`][0];
3012
- });
2978
+ g_titleLists.animation.forEach(pattern =>
2979
+ obj[`titleAnimation${pattern}`][1] = obj[`titleAnimation${pattern}`][0]);
3013
2980
  }
3014
2981
  if (obj.titleAnimationClass.length === 1) {
3015
2982
  obj.titleAnimationClass[1] = obj.titleAnimationClass[0];
3016
2983
  }
3017
2984
 
3018
2985
  // デフォルト曲名表示の複数行時の縦間隔
3019
- obj.titlelineheight = setIntVal(getHeader(_dosObj, `titlelineheight`), ``);
2986
+ obj.titlelineheight = setIntVal(getHeader(_dosObj, ...getHname(`titleLineHeight`)), ``);
3020
2987
 
3021
2988
  // フリーズアローの始点で通常矢印の判定を行うか(dotさんソース方式)
3022
2989
  obj.frzStartjdgUse = setBoolVal(_dosObj.frzStartjdgUse ?? g_presetObj.frzStartjdgUse);
@@ -3036,9 +3003,8 @@ const headerConvert = _dosObj => {
3036
3003
  }
3037
3004
 
3038
3005
  // オプション利用可否設定
3039
- g_canDisabledSettings.forEach(option => {
3040
- obj[`${option}Use`] = setBoolVal(_dosObj[`${option}Use`] ?? g_presetObj.settingUse?.[option], true);
3041
- });
3006
+ g_canDisabledSettings.forEach(option =>
3007
+ obj[`${option}Use`] = setBoolVal(_dosObj[`${option}Use`] ?? g_presetObj.settingUse?.[option], true));
3042
3008
 
3043
3009
  let interlockingErrorFlg = false;
3044
3010
  g_displays.forEach((option, j) => {
@@ -3071,12 +3037,11 @@ const headerConvert = _dosObj => {
3071
3037
  });
3072
3038
 
3073
3039
  if (!interlockingErrorFlg) {
3074
- g_displays.forEach(option => {
3040
+ g_displays.forEach(option =>
3075
3041
  obj[`${option}ChainOFF`].forEach(defaultOption => {
3076
3042
  g_stateObj[`d_${defaultOption.toLowerCase()}`] = C_FLG_OFF;
3077
3043
  interlockingButton(obj, defaultOption, C_FLG_OFF, C_FLG_ON);
3078
- });
3079
- });
3044
+ }));
3080
3045
  }
3081
3046
 
3082
3047
  // ローカルストレージに保存済みのColorType設定からDisplayのColor設定を反映
@@ -3094,7 +3059,6 @@ const headerConvert = _dosObj => {
3094
3059
  // [フレーム数,階層,背景パス,class(CSSで別定義),X,Y,width,height,opacity,animationName,animationDuration]
3095
3060
  g_animationData.forEach(sprite => {
3096
3061
  obj[`${sprite}TitleData`] = [];
3097
- obj[`${sprite}TitleData`].length = 0;
3098
3062
  obj[`${sprite}TitleMaxDepth`] = -1;
3099
3063
 
3100
3064
  const dataList = [_dosObj[`${sprite}title${g_localeObj.val}_data`], _dosObj[`${sprite}title_data`]];
@@ -3117,7 +3081,7 @@ const headerConvert = _dosObj => {
3117
3081
  obj.resultMotionSet = setBoolVal(_dosObj.resultMotionSet, true);
3118
3082
 
3119
3083
  // 譜面明細の使用可否
3120
- const tmpDetails = _dosObj.scoreDetailUse?.split(`,`).filter(val => hasVal(val) && val !== `false`)
3084
+ const tmpDetails = getHeader(_dosObj, `scoreDetailUse`, `chartDetailUse`)?.split(`,`).filter(val => hasVal(val) && val !== `false`)
3121
3085
  .map(val => replaceStr(val, g_settings.scoreDetailTrans));
3122
3086
  g_settings.scoreDetails = g_settings.scoreDetailDefs.filter(val => tmpDetails?.includes(val) || tmpDetails === undefined);
3123
3087
 
@@ -3187,7 +3151,6 @@ const headerConvert = _dosObj => {
3187
3151
  * 譜面リスト作成有無の状態を取得
3188
3152
  * @param {boolean} _headerFlg
3189
3153
  * @param {array} _viewLists
3190
- * @returns
3191
3154
  */
3192
3155
  const getDifSelectorUse = (_headerFlg, _viewLists = g_headerObj.viewLists) => setBoolVal(_headerFlg, _viewLists.length > 5);
3193
3156
 
@@ -3206,7 +3169,6 @@ const resetColorType = ({ _from = ``, _to = ``, _fromObj = g_headerObj, _toObj =
3206
3169
  * 配列にデータを先頭に追加
3207
3170
  * @param {array} _arr
3208
3171
  * @param {string} _target
3209
- * @returns
3210
3172
  */
3211
3173
  const addValtoArray = (_arr, _target) => {
3212
3174
  if (!_arr.includes(_target)) {
@@ -3530,8 +3492,7 @@ const getGaugeSetting = (_dosObj, _name, _difLength, { scoreId = 0 } = {}) => {
3530
3492
 
3531
3493
  /**
3532
3494
  * キー名の取得
3533
- * @param {string} _key
3534
- * @returns
3495
+ * @param {string} _key
3535
3496
  */
3536
3497
  const getKeyName = _key => hasVal(g_keyObj[`keyName${_key}`]) ? g_keyObj[`keyName${_key}`] : _key;
3537
3498
 
@@ -3539,8 +3500,7 @@ const getKeyName = _key => hasVal(g_keyObj[`keyName${_key}`]) ? g_keyObj[`keyNam
3539
3500
  * KeyBoardEvent.code の値をCW Edition用のキーコードに変換
3540
3501
  * 簡略指定ができるように、以下の記述を許容
3541
3502
  * 例) KeyD -> D, ArrowDown -> Down, AltLeft -> Alt
3542
- * @param {string} _kCdN
3543
- * @returns
3503
+ * @param {string} _kCdN
3544
3504
  */
3545
3505
  const getKeyCtrlVal = _kCdN => {
3546
3506
  const convVal = Object.keys(g_kCdN).findIndex(val =>
@@ -3575,8 +3535,7 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList?.split(`,`)
3575
3535
  * キーパターン(相対パターン)をキーパターン(実際のパターン番号)に変換
3576
3536
  * 例) 12_(0) -> 12_4
3577
3537
  * それ以外の文字列が来た場合は、そのままの値を戻す
3578
- * @param {string} _str
3579
- * @returns
3538
+ * @param {string} _str
3580
3539
  */
3581
3540
  const getKeyPtnName = _str => {
3582
3541
  const regex = /\((\d+)\)/;
@@ -3635,14 +3594,13 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList?.split(`,`)
3635
3594
  const dfPtn = setIntVal(g_keyObj.dfPtnNum);
3636
3595
 
3637
3596
  if (hasVal(_dosObj[keyheader])) {
3638
- const tmpArray = splitLF2(_dosObj[keyheader]);
3639
- for (let k = 0; k < tmpArray.length; k++) {
3640
- if (existParam(tmpArray[k], `${keyheader}_${k + dfPtn}`)) {
3641
- continue;
3597
+ splitLF2(_dosObj[keyheader])?.forEach((tmpParam, k) => {
3598
+ if (existParam(tmpParam, `${keyheader}_${k + dfPtn}`)) {
3599
+ return;
3642
3600
  }
3643
3601
 
3644
3602
  let ptnCnt = 0;
3645
- tmpArray[k].split(`/`).forEach(list => {
3603
+ tmpParam.split(`/`).forEach(list => {
3646
3604
 
3647
3605
  const keyPtn = getKeyPtnName(list);
3648
3606
  if (list === ``) {
@@ -3671,7 +3629,7 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList?.split(`,`)
3671
3629
  }
3672
3630
  });
3673
3631
  g_keyObj[`${keyheader}_${k + dfPtn}`] = structuredClone(g_keyObj[`${keyheader}_${k + dfPtn}_0`]);
3674
- }
3632
+ });
3675
3633
 
3676
3634
  } else if (g_keyObj[`${keyheader}_${dfPtn}_0`] === undefined) {
3677
3635
  // 特に指定が無い場合はkeyCtrlX_Yの配列長で決定
@@ -3717,39 +3675,36 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList?.split(`,`)
3717
3675
  const keyheader = _name + _key;
3718
3676
  const dfPtn = setIntVal(g_keyObj.dfPtnNum);
3719
3677
 
3720
- if (_dosObj[keyheader] !== undefined) {
3721
- const tmpParams = splitLF2(_dosObj[keyheader]);
3722
- for (let k = 0; k < tmpParams.length; k++) {
3723
- const pairName = `${_pairName}${_key}_${k + dfPtn}`;
3724
- if (!hasVal(tmpParams[k])) {
3725
- continue;
3726
- }
3727
- g_keyObj[pairName] = {}
3678
+ splitLF2(_dosObj[keyheader])?.forEach((tmpParam, k) => {
3679
+ const pairName = `${_pairName}${_key}_${k + dfPtn}`;
3680
+ if (!hasVal(tmpParam)) {
3681
+ return;
3682
+ }
3683
+ g_keyObj[pairName] = {}
3728
3684
 
3729
- // デフォルト項目がある場合は先に定義
3730
- if (_defaultName !== ``) {
3731
- g_keyObj[pairName][_defaultName] = [...Array(g_keyObj[`${g_keyObj.defaultProp}${_key}_${k + dfPtn}`].length)].fill(_defaultVal);
3732
- }
3733
- tmpParams[k].split(`/`).forEach(pairs => {
3734
- const keyPtn = getKeyPtnName(pairs);
3735
- if (pairs === ``) {
3736
- } else if (g_keyObj[`${_pairName}${keyPtn}`] !== undefined) {
3737
- // 他のキーパターン指定時、該当があればプロパティを全コピー
3738
- Object.assign(g_keyObj[pairName], g_keyObj[`${_pairName}${keyPtn}`]);
3739
- } else {
3740
- // 通常の指定方法(例:|scroll8i=Cross::1,1,1,-,-,-,1,1/Split::1,1,1,1,-,-,-,-|)から取り込み
3741
- // 部分的にキーパターン指定があった場合は既存パターンを展開 (例: |scroll9j=Cross::1,7_0,1|)
3742
- const tmpParamPair = pairs.split(`::`);
3743
- g_keyObj[pairName][tmpParamPair[0]] =
3744
- makeBaseArray(tmpParamPair[1].split(`,`).map(n =>
3745
- g_keyObj[`${_pairName}${getKeyPtnName(n)}`] !== undefined ?
3746
- structuredClone(g_keyObj[`${_pairName}${getKeyPtnName(n)}`][tmpParamPair[0]]) :
3747
- [n === `-` ? -1 : parseInt(n, 10)]
3748
- ).flat(), g_keyObj[`${g_keyObj.defaultProp}${_key}_${k + dfPtn}`].length, _defaultVal);
3749
- }
3750
- });
3685
+ // デフォルト項目がある場合は先に定義
3686
+ if (_defaultName !== ``) {
3687
+ g_keyObj[pairName][_defaultName] = [...Array(g_keyObj[`${g_keyObj.defaultProp}${_key}_${k + dfPtn}`].length)].fill(_defaultVal);
3751
3688
  }
3752
- }
3689
+ tmpParam.split(`/`).forEach(pairs => {
3690
+ const keyPtn = getKeyPtnName(pairs);
3691
+ if (pairs === ``) {
3692
+ } else if (g_keyObj[`${_pairName}${keyPtn}`] !== undefined) {
3693
+ // 他のキーパターン指定時、該当があればプロパティを全コピー
3694
+ Object.assign(g_keyObj[pairName], g_keyObj[`${_pairName}${keyPtn}`]);
3695
+ } else {
3696
+ // 通常の指定方法(例:|scroll8i=Cross::1,1,1,-,-,-,1,1/Split::1,1,1,1,-,-,-,-|)から取り込み
3697
+ // 部分的にキーパターン指定があった場合は既存パターンを展開 (例: |scroll9j=Cross::1,7_0,1|)
3698
+ const tmpParamPair = pairs.split(`::`);
3699
+ g_keyObj[pairName][tmpParamPair[0]] =
3700
+ makeBaseArray(tmpParamPair[1]?.split(`,`).map(n =>
3701
+ g_keyObj[`${_pairName}${getKeyPtnName(n)}`] !== undefined ?
3702
+ structuredClone(g_keyObj[`${_pairName}${getKeyPtnName(n)}`][tmpParamPair[0]]) :
3703
+ [n === `-` ? -1 : parseInt(n, 10)]
3704
+ ).flat(), g_keyObj[`${g_keyObj.defaultProp}${_key}_${k + dfPtn}`].length, _defaultVal);
3705
+ }
3706
+ });
3707
+ });
3753
3708
  };
3754
3709
 
3755
3710
  // 対象キー毎に処理
@@ -3790,26 +3745,24 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList?.split(`,`)
3790
3745
  newKeyMultiParam(newKey, `pos`, toFloat);
3791
3746
 
3792
3747
  // 各キーの区切り位置 (divX_Y)
3793
- if (_dosObj[`div${newKey}`] !== undefined) {
3794
- const tmpDivs = _dosObj[`div${newKey}`].split(`$`);
3795
- for (let k = 0; k < tmpDivs.length; k++) {
3796
- const tmpDivPtn = tmpDivs[k].split(`,`);
3797
- const ptnName = `${newKey}_${k + dfPtnNum}`;
3798
-
3799
- if (g_keyObj[`div${tmpDivPtn[0]}`] !== undefined) {
3800
- // 既定キーパターンが指定された場合、存在すればその値を適用
3801
- g_keyObj[`div${ptnName}`] = g_keyObj[`div${tmpDivPtn[0]}`];
3802
- g_keyObj[`divMax${ptnName}`] = setVal(g_keyObj[`divMax${tmpDivPtn[0]}`], undefined, C_TYP_FLOAT);
3803
- } else if (!hasVal(tmpDivPtn[0]) && setIntVal(g_keyObj[`div${ptnName}`], -1) !== -1) {
3804
- // カスタムキー側のdivXが未定義だが、すでに初期設定で定義済みの場合はスキップ
3805
- continue;
3806
- } else {
3807
- // それ以外の場合は指定された値を適用(未指定時はその後で指定)
3808
- g_keyObj[`div${ptnName}`] = setVal(tmpDivPtn[0], undefined, C_TYP_NUMBER);
3809
- g_keyObj[`divMax${ptnName}`] = setVal(tmpDivPtn[1], undefined, C_TYP_FLOAT);
3810
- }
3748
+ _dosObj[`div${newKey}`]?.split(`$`).forEach((tmpDiv, k) => {
3749
+ const tmpDivPtn = tmpDiv.split(`,`);
3750
+ const ptnName = `${newKey}_${k + dfPtnNum}`;
3751
+
3752
+ if (g_keyObj[`div${tmpDivPtn[0]}`] !== undefined) {
3753
+ // 既定キーパターンが指定された場合、存在すればその値を適用
3754
+ g_keyObj[`div${ptnName}`] = g_keyObj[`div${tmpDivPtn[0]}`];
3755
+ g_keyObj[`divMax${ptnName}`] = setVal(g_keyObj[`divMax${tmpDivPtn[0]}`], undefined, C_TYP_FLOAT);
3756
+ } else if (!hasVal(tmpDivPtn[0]) && setIntVal(g_keyObj[`div${ptnName}`], -1) !== -1) {
3757
+ // カスタムキー側のdivXが未定義だが、すでに初期設定で定義済みの場合はスキップ
3758
+ return;
3759
+ } else {
3760
+ // それ以外の場合は指定された値を適用(未指定時はその後で指定)
3761
+ g_keyObj[`div${ptnName}`] = setVal(tmpDivPtn[0], undefined, C_TYP_NUMBER);
3762
+ g_keyObj[`divMax${ptnName}`] = setVal(tmpDivPtn[1], undefined, C_TYP_FLOAT);
3811
3763
  }
3812
- }
3764
+ });
3765
+
3813
3766
  // charaX_Y, posX_Y, keyGroupX_Y, divX_Y, divMaxX_Yが未指定の場合はkeyCtrlX_Yを元に適用
3814
3767
  for (let k = 0; k < g_keyObj.minPatterns; k++) {
3815
3768
  setKeyDfVal(`${newKey}_${k + dfPtnNum}`);
@@ -3959,7 +3912,7 @@ const titleInit = _ => {
3959
3912
  // 変数 titlelineheight の定義 (使用例: |titlelineheight=50|)
3960
3913
  const titlelineheight = (g_headerObj.titlelineheight !== `` ? g_headerObj.titlelineheight - (titlefontsize2 + 10) : 0);
3961
3914
 
3962
- let txtAnimations = [``, ``];
3915
+ const txtAnimations = [``, ``];
3963
3916
  if (!g_headerObj.customTitleAnimationUse) {
3964
3917
  for (let j = 0; j < txtAnimations.length; j++) {
3965
3918
  txtAnimations[j] = `animation-name:${g_headerObj.titleAnimationName[j]};
@@ -4028,7 +3981,6 @@ const titleInit = _ => {
4028
3981
  * @param {string} _id
4029
3982
  * @param {string} _text
4030
3983
  * @param {string} _url
4031
- * @returns
4032
3984
  */
4033
3985
  const createCreditBtn = (_id, _text, _url) =>
4034
3986
  createCss2Button(_id, _text, _ => true,
@@ -4143,10 +4095,10 @@ const titleInit = _ => {
4143
4095
  g_scoreObj.titleFrameNum++;
4144
4096
  g_scoreObj.backTitleFrameNum++;
4145
4097
  g_scoreObj.maskTitleFrameNum++;
4146
- g_timeoutEvtTitleId = setTimeout(_ => flowTitleTimeline(), 1000 / g_fps - buffTime);
4098
+ g_timeoutEvtTitleId = setTimeout(flowTitleTimeline, 1000 / g_fps - buffTime);
4147
4099
  };
4148
4100
 
4149
- g_timeoutEvtTitleId = setTimeout(_ => flowTitleTimeline(), 1000 / g_fps);
4101
+ g_timeoutEvtTitleId = setTimeout(flowTitleTimeline, 1000 / g_fps);
4150
4102
 
4151
4103
  // キー操作イベント(デフォルト)
4152
4104
  setShortcutEvent(g_currentPage, _ => true, { dfEvtFlg: true });
@@ -4341,7 +4293,6 @@ const setSpriteList = _settingList => {
4341
4293
  /**
4342
4294
  * 設定ウィンドウの作成
4343
4295
  * @param {string} _sprite
4344
- * @returns
4345
4296
  */
4346
4297
  const createOptionSprite = _sprite => createEmptySprite(_sprite, `optionsprite`, g_windowObj.optionSprite);
4347
4298
 
@@ -4349,7 +4300,6 @@ const createOptionSprite = _sprite => createEmptySprite(_sprite, `optionsprite`,
4349
4300
  * スライダー共通処理
4350
4301
  * @param {object} _slider
4351
4302
  * @param {object} _link
4352
- * @returns
4353
4303
  */
4354
4304
  const inputSlider = (_slider, _link) => {
4355
4305
  const value = parseInt(_slider.value);
@@ -4373,7 +4323,6 @@ const resetDifWindow = _ => {
4373
4323
  * 次の譜面番号を取得
4374
4324
  * @param {number} _scoreId
4375
4325
  * @param {number} _scrollNum
4376
- * @returns
4377
4326
  */
4378
4327
  const getNextDifficulty = (_scoreId, _scrollNum) => {
4379
4328
  const currentPosIdx = g_headerObj.viewLists.findIndex(val => val === _scoreId);
@@ -4422,7 +4371,6 @@ const makeDifList = (_difList, _targetKey = ``) => {
4422
4371
  /**
4423
4372
  * 譜面セレクター位置の変更ボタン
4424
4373
  * @param {number} _scrollNum
4425
- * @returns
4426
4374
  */
4427
4375
  const makeDifBtn = (_scrollNum = 1) => {
4428
4376
  const dir = _scrollNum === 1 ? `D` : `U`;
@@ -4529,8 +4477,8 @@ const drawSpeedGraph = _scoreId => {
4529
4477
  };
4530
4478
 
4531
4479
  Object.keys(speedObj).forEach(speedType => {
4532
- let frame = speedObj[speedType].frame;
4533
- let speed = speedObj[speedType].speed;
4480
+ const frame = speedObj[speedType].frame;
4481
+ const speed = speedObj[speedType].speed;
4534
4482
  const speedData = g_detailObj[`${speedType}Data`][_scoreId];
4535
4483
 
4536
4484
  if (speedData !== undefined) {
@@ -4552,6 +4500,7 @@ const drawSpeedGraph = _scoreId => {
4552
4500
 
4553
4501
  const avgX = [0, 0];
4554
4502
  const avgSubX = [1, 1];
4503
+ const lineX = [125, 210];
4555
4504
  Object.keys(speedObj).forEach((speedType, j) => {
4556
4505
  context.beginPath();
4557
4506
  let preY;
@@ -4580,13 +4529,12 @@ const drawSpeedGraph = _scoreId => {
4580
4529
  context.strokeStyle = speedObj[speedType].strokeColor;
4581
4530
  context.stroke();
4582
4531
 
4583
- const lineX = (speedType === `speed`) ? 125 : 210;
4584
4532
  context.beginPath();
4585
- context.moveTo(lineX, 215);
4586
- context.lineTo(lineX + 25, 215);
4533
+ context.moveTo(lineX[j], 215);
4534
+ context.lineTo(lineX[j] + 25, 215);
4587
4535
  context.stroke();
4588
4536
  context.font = `${g_limitObj.difSelectorSiz}px ${getBasicFont()}`;
4589
- context.fillText(g_lblNameObj[`s_${speedType}`], lineX + 30, 218);
4537
+ context.fillText(g_lblNameObj[`s_${speedType}`], lineX[j] + 30, 218);
4590
4538
 
4591
4539
  updateScoreDetailLabel(`Speed`, `${speedType}S`, speedObj[speedType].cnt, j, g_lblNameObj[`s_${speedType}`]);
4592
4540
  updateScoreDetailLabel(`Speed`, `avgD${speedType}`, avgSubX[j] === 1 ? `----` : `${(avgSubX[j]).toFixed(2)}x`, j + 4, g_lblNameObj[`s_avgD${speedType}`]);
@@ -5426,27 +5374,21 @@ const setReverseView = _btn => {
5426
5374
  */
5427
5375
  const setGauge = (_scrollNum, _gaugeInitFlg = false) => {
5428
5376
 
5429
- /**
5430
- * ゲージ詳細変更
5431
- * @param {object} _baseProperty
5432
- * @param {string} _setProperty
5433
- * @param {number} _magnification
5434
- */
5435
- const setLife = (_baseProperty, _setProperty, _magnification = 1) => {
5436
- if (setVal(_baseProperty[g_stateObj.scoreId], ``, C_TYP_FLOAT) !== ``) {
5437
- g_stateObj[_setProperty] = _baseProperty[g_stateObj.scoreId] * _magnification;
5438
- }
5439
- };
5440
-
5441
5377
  /**
5442
5378
  * ゲージ詳細一括変更
5443
5379
  * @param {object} _baseObj
5444
5380
  * @param {object} _obj
5445
5381
  */
5446
5382
  const setLifeCategory = (_baseObj, { _magInit = 1, _magRcv = 1, _magDmg = 1 } = {}) => {
5447
- setLife(_baseObj.lifeInits, `lifeInit`, _magInit);
5448
- setLife(_baseObj.lifeRecoverys, `lifeRcv`, _magRcv);
5449
- setLife(_baseObj.lifeDamages, `lifeDmg`, _magDmg);
5383
+ if (hasVal(_baseObj.lifeInits[g_stateObj.scoreId])) {
5384
+ g_stateObj.lifeInit = _baseObj.lifeInits[g_stateObj.scoreId] * _magInit;
5385
+ }
5386
+ if (hasVal(_baseObj.lifeRecoverys[g_stateObj.scoreId])) {
5387
+ g_stateObj.lifeRcv = _baseObj.lifeRecoverys[g_stateObj.scoreId] * _magRcv;
5388
+ }
5389
+ if (hasVal(_baseObj.lifeDamages[g_stateObj.scoreId])) {
5390
+ g_stateObj.lifeDmg = _baseObj.lifeDamages[g_stateObj.scoreId] * _magDmg;
5391
+ }
5450
5392
  };
5451
5393
 
5452
5394
  /**
@@ -5526,7 +5468,6 @@ const setGauge = (_scrollNum, _gaugeInitFlg = false) => {
5526
5468
  * @param {number} _dmg
5527
5469
  * @param {number} _init
5528
5470
  * @param {string} _lifeValFlg
5529
- * @returns
5530
5471
  */
5531
5472
  const gaugeFormat = (_mode, _border, _rcv, _dmg, _init, _lifeValFlg) => {
5532
5473
  const initVal = g_headerObj.maxLifeVal * _init / 100;
@@ -5603,7 +5544,6 @@ const gaugeFormat = (_mode, _border, _rcv, _dmg, _init, _lifeValFlg) => {
5603
5544
  * @param {number} _dmg
5604
5545
  * @param {number} _init
5605
5546
  * @param {number} _allCnt
5606
- * @returns
5607
5547
  */
5608
5548
  const getAccuracy = (_border, _rcv, _dmg, _init, _allCnt) => {
5609
5549
  const justPoint = _rcv + _dmg > 0 ? Math.max(_border - _init + _dmg * _allCnt, 0) / (_rcv + _dmg) : 0;
@@ -5661,9 +5601,7 @@ const getKeyCtrl = (_localStorage, _extraKeyName = ``) => {
5661
5601
  g_keyObj[`${header}${copyPtn}`] = structuredClone(g_keyObj[`${header}${basePtn}`]);
5662
5602
  }
5663
5603
  });
5664
- g_keyCopyLists.simple.forEach(header => {
5665
- g_keyObj[`${header}${copyPtn}`] = g_keyObj[`${header}${basePtn}`];
5666
- });
5604
+ g_keyCopyLists.simple.forEach(header => g_keyObj[`${header}${copyPtn}`] = g_keyObj[`${header}${basePtn}`]);
5667
5605
 
5668
5606
  g_keycons.groups.forEach(type => {
5669
5607
  let maxPtn = 0;
@@ -5885,11 +5823,10 @@ const createSettingsDisplayWindow = _sprite => {
5885
5823
  appearanceSlider.addEventListener(`input`, _ =>
5886
5824
  g_hidSudObj.filterPos = inputSlider(appearanceSlider, lblAppearancePos), false);
5887
5825
 
5888
- const dispAppearanceSlider = _ => {
5826
+ const dispAppearanceSlider = _ =>
5889
5827
  [`lblAppearancePos`, `lblAppearanceBar`, `lnkLockBtn`, `lnkfilterLine`].forEach(obj =>
5890
5828
  $id(obj).visibility = g_appearanceRanges.includes(g_stateObj.appearance) ? `Visible` : `Hidden`
5891
5829
  );
5892
- };
5893
5830
  dispAppearanceSlider();
5894
5831
 
5895
5832
  // ---------------------------------------------------
@@ -6041,7 +5978,6 @@ const keyConfigInit = (_kcType = g_kcType) => {
6041
5978
  * @param {number} _len
6042
5979
  * @param {number} _j
6043
5980
  * @param {number} _scrollNum
6044
- * @returns
6045
5981
  */
6046
5982
  const changeTmpData = (_type, _len, _j, _scrollNum) => {
6047
5983
  const tmpNo = nextPos(g_keyObj[`${_type}${keyCtrlPtn}_${g_keycons[`${_type}GroupNum`]}`][_j], _scrollNum, _len);
@@ -6234,7 +6170,6 @@ const keyConfigInit = (_kcType = g_kcType) => {
6234
6170
  * @param {string} _directionFlg
6235
6171
  * @param {function} _func
6236
6172
  * @param {*} object (x, y, w, h, siz)
6237
- * @returns
6238
6173
  */
6239
6174
  const makeMiniKCButton = (_id, _directionFlg, _func, { x = g_sWidth * 5 / 6 - 30, y = 15, w = 15, h = 20, siz = g_limitObj.mainSiz } = {}) => {
6240
6175
  return createCss2Button(`${_id}${_directionFlg}`, g_settingBtnObj.chara[_directionFlg], _func,
@@ -6512,7 +6447,6 @@ const keyConfigInit = (_kcType = g_kcType) => {
6512
6447
  * @param {number} _tempPtn
6513
6448
  * @param {number} _sign
6514
6449
  * @param {boolean} _transKeyUse
6515
- * @returns
6516
6450
  */
6517
6451
  const searchPattern = (_tempPtn, _sign, _transKeyUse = false, _skipFlg = false) => {
6518
6452
  let nextPtn = _tempPtn + _sign;
@@ -6703,14 +6637,12 @@ const keyConfigInit = (_kcType = g_kcType) => {
6703
6637
  * 影矢印色の取得
6704
6638
  * @param {number} _colorPos
6705
6639
  * @param {string} _arrowColor
6706
- * @returns
6707
6640
  */
6708
6641
  const getShadowColor = (_colorPos, _arrowColor) => g_headerObj.setShadowColor[_colorPos] === `Default` ?
6709
6642
  _arrowColor : g_headerObj.setShadowColor[_colorPos];
6710
6643
 
6711
6644
  /**
6712
6645
  * キー数基礎情報の取得
6713
- * @returns
6714
6646
  */
6715
6647
  const getKeyInfo = _ => {
6716
6648
  const keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`;
@@ -7007,9 +6939,7 @@ const loadingScoreInit = async () => {
7007
6939
  // キーパターン(デフォルト)に対応する矢印番号を格納
7008
6940
  convertReplaceNums();
7009
6941
 
7010
- const setData = (_data, _minLength = 1) => {
7011
- return (hasArrayList(_data, _minLength) ? _data.concat() : []);
7012
- };
6942
+ const setData = (_data, _minLength = 1) => hasArrayList(_data, _minLength) ? _data.concat() : [];
7013
6943
 
7014
6944
  // フレーム・曲開始位置調整
7015
6945
  let preblankFrame = 0;
@@ -7033,9 +6963,8 @@ const loadingScoreInit = async () => {
7033
6963
  });
7034
6964
  }
7035
6965
 
7036
- Object.keys(g_dataMinObj).forEach(dataType => {
7037
- g_scoreObj[`${dataType}Data`] = setData(tmpObj[`${dataType}Data`], g_dataMinObj[dataType]);
7038
- });
6966
+ Object.keys(g_dataMinObj).forEach(dataType =>
6967
+ g_scoreObj[`${dataType}Data`] = setData(tmpObj[`${dataType}Data`], g_dataMinObj[dataType]));
7039
6968
 
7040
6969
  lastFrame += preblankFrame;
7041
6970
  firstArrowFrame += preblankFrame;
@@ -7309,22 +7238,8 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
7309
7238
  * 矢印データの格納
7310
7239
  * @param {string} _data
7311
7240
  */
7312
- const storeArrowData = _data => {
7313
- let arrowData = [];
7314
-
7315
- if (hasVal(_data)) {
7316
- const tmpData = splitLF(_data).join(``);
7317
- if (tmpData !== undefined) {
7318
- arrowData = tmpData.split(`,`);
7319
- if (isNaN(parseFloat(arrowData[0]))) {
7320
- return [];
7321
- } else {
7322
- arrowData = arrowData.map(data => calcFrame(data)).sort((_a, _b) => _a - _b);
7323
- }
7324
- }
7325
- }
7326
- return arrowData;
7327
- };
7241
+ const storeArrowData = _data => hasVal(_data) ?
7242
+ splitLF(_data)?.join(``).split(`,`).filter(data => !isNaN(parseFloat(data))).map(data => calcFrame(data)).sort((_a, _b) => _a - _b) : [];
7328
7243
 
7329
7244
  for (let j = 0; j < keyNum; j++) {
7330
7245
 
@@ -7385,7 +7300,6 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
7385
7300
  /**
7386
7301
  * 個別・全体色変化データをマージして整列し、単純配列として返却
7387
7302
  * @param {string} _header
7388
- * @returns
7389
7303
  */
7390
7304
  const mergeColorData = (_header = ``) => {
7391
7305
  if (obj[`color${_header}Data`] === undefined) return [];
@@ -7485,7 +7399,6 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
7485
7399
  * 例) |backA2_data=back_data| -> back_dataで定義された値を使用
7486
7400
  * @param {string} _header
7487
7401
  * @param {string} _dataName
7488
- * @returns
7489
7402
  */
7490
7403
  const getRefData = (_header, _dataName) => {
7491
7404
  const data = _dosObj[`${_header}${_dataName}`];
@@ -7497,7 +7410,6 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
7497
7410
  * @param {string} _header
7498
7411
  * @param {string} _type
7499
7412
  * @param {number} _scoreNo
7500
- * @returns
7501
7413
  */
7502
7414
  const getPriorityList = (_header, _type, _scoreNo) => [
7503
7415
  getRefData(_header, `${_type}${g_localeObj.val}${_scoreNo}_data`),
@@ -7508,7 +7420,6 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
7508
7420
 
7509
7421
  /**
7510
7422
  * 歌詞表示、背景・マスクデータの優先順取得
7511
- * @returns
7512
7423
  */
7513
7424
  const getPriorityHeader = _ => {
7514
7425
  const list = [];
@@ -7704,9 +7615,8 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
7704
7615
  obj.backMaxDepth = -1;
7705
7616
  if (g_stateObj.d_background === C_FLG_OFF) {
7706
7617
  } else {
7707
- g_animationData.forEach(sprite => {
7708
- [obj[`${sprite}Data`], obj[`${sprite}MaxDepth`]] = makeBackgroundData(sprite, scoreIdHeader);
7709
- });
7618
+ g_animationData.forEach(sprite =>
7619
+ [obj[`${sprite}Data`], obj[`${sprite}MaxDepth`]] = makeBackgroundData(sprite, scoreIdHeader));
7710
7620
  }
7711
7621
 
7712
7622
  // 結果画面用・背景/マスクデータの分解 (下記すべてで1セット、改行区切り)
@@ -7867,7 +7777,6 @@ const setMotionOnFrame = _ => g_motionFunc[g_stateObj.motion]([...Array(g_sHeigh
7867
7777
  * @param {array} _frms
7868
7778
  * @param {number} _spd
7869
7779
  * @param {number} _pnFlg 正負(1 もしくは -1)
7870
- * @returns
7871
7780
  */
7872
7781
  const getBoostTrace = (_frms, _spd, _pnFlg = 1) => {
7873
7782
  for (let j = C_MOTION_STD_POS + 1; j < C_MOTION_STD_POS + 70; j++) {
@@ -7880,7 +7789,6 @@ const getBoostTrace = (_frms, _spd, _pnFlg = 1) => {
7880
7789
  * Brake用の適用関数
7881
7790
  * - 初期は+2x、ステップゾーンに近づくにつれて加速量を下げる (20 → 34)
7882
7791
  * @param {array} _frms
7883
- * @returns
7884
7792
  */
7885
7793
  const getBrakeTrace = _frms => {
7886
7794
  for (let j = C_MOTION_STD_POS + 5; j < C_MOTION_STD_POS + 19; j++) {
@@ -8076,7 +7984,6 @@ const pushArrows = (_dataObj, _speedOnFrame, _motionOnFrame, _firstArrivalFrame)
8076
7984
  * @param {string} _header
8077
7985
  * @param {function} _setFunc
8078
7986
  * @param {object} obj _colorFlg: 個別色変化フラグ, _calcFrameFlg: 逆算を無条件で行うかどうかの可否
8079
- * @returns
8080
7987
  */
8081
7988
  const calcDataTiming = (_type, _header, _setFunc = _ => true,
8082
7989
  { _term = 4, _colorFlg = false, _calcFrameFlg = false } = {}) => {
@@ -8117,7 +8024,6 @@ const pushArrows = (_dataObj, _speedOnFrame, _motionOnFrame, _firstArrivalFrame)
8117
8024
  * 歌詞表示、背景・マスク表示のフェードイン時調整処理
8118
8025
  * @param {string} _type
8119
8026
  * @param {object} _data
8120
- * @returns
8121
8027
  */
8122
8028
  const calcAnimationData = (_type, _data) => {
8123
8029
 
@@ -8130,11 +8036,10 @@ const pushArrows = (_dataObj, _speedOnFrame, _motionOnFrame, _firstArrivalFrame)
8130
8036
  (cgArrays.includes(_type) ? _data[startNum][_j][0] === _data[startNum][_k][0] :
8131
8037
  _data[startNum][_j].depth === _data[startNum][_k].depth);
8132
8038
 
8133
- const fuzzyCheck = (_str, _list) => listMatching(_str, _list);
8134
8039
  const isExceptData = {
8135
- word: (_exceptList, _j) => fuzzyCheck(_data[startNum][_j][1], _exceptList.word),
8136
- back: (_exceptList, _j) => fuzzyCheck(_data[startNum][_j].animationName, _exceptList.back),
8137
- mask: (_exceptList, _j) => fuzzyCheck(_data[startNum][_j].animationName, _exceptList.mask),
8040
+ word: (_exceptList, _j) => listMatching(_data[startNum][_j][1], _exceptList.word),
8041
+ back: (_exceptList, _j) => listMatching(_data[startNum][_j].animationName, _exceptList.back),
8042
+ mask: (_exceptList, _j) => listMatching(_data[startNum][_j].animationName, _exceptList.mask),
8138
8043
  };
8139
8044
 
8140
8045
  const getLength = _list =>
@@ -8193,7 +8098,6 @@ const pushArrows = (_dataObj, _speedOnFrame, _motionOnFrame, _firstArrivalFrame)
8193
8098
 
8194
8099
  // 実際に処理させる途中変速配列を作成
8195
8100
  g_workObj.speedData = [];
8196
- g_workObj.speedData.length = 0;
8197
8101
  g_workObj.speedData.push(g_scoreObj.frameNum);
8198
8102
  g_workObj.speedData.push(_speedOnFrame[g_scoreObj.frameNum]);
8199
8103
 
@@ -9020,10 +8924,9 @@ const mainInit = _ => {
9020
8924
  Ii: [`ii`, 0], Shakin: [`shakin`, 1], Matari: [`matari`, 2], Shobon: [`shobon`, 3], Uwan: [`uwan`, 4],
9021
8925
  MCombo: [`combo`, 5], Kita: [`kita`, 7], Iknai: [`iknai`, 8], FCombo: [`combo`, 9],
9022
8926
  };
9023
- Object.keys(jdgMainScoreObj).forEach(jdgScore => {
8927
+ Object.keys(jdgMainScoreObj).forEach(jdgScore =>
9024
8928
  infoSprite.appendChild(makeCounterSymbol(`lbl${jdgScore}`, g_headerObj.playingWidth - 110,
9025
- g_cssObj[`common_${jdgMainScoreObj[jdgScore][0]}`], jdgMainScoreObj[jdgScore][1] + 1, 0, g_workObj.scoreDisp));
9026
- });
8929
+ g_cssObj[`common_${jdgMainScoreObj[jdgScore][0]}`], jdgMainScoreObj[jdgScore][1] + 1, 0, g_workObj.scoreDisp)));
9027
8930
 
9028
8931
  // パーフェクト演出
9029
8932
  judgeSprite.appendChild(createDivCss2Label(`finishView`, ``, g_lblPosObj.finishView, g_cssObj.common_kita));
@@ -9240,12 +9143,12 @@ const mainInit = _ => {
9240
9143
  * @param _deleteObj 削除オブジェクト
9241
9144
  */
9242
9145
  const judgeObjDelete = {};
9243
- g_typeLists.arrow.forEach(type => {
9146
+ g_typeLists.arrow.forEach(type =>
9244
9147
  judgeObjDelete[type] = (_j, _deleteName) => {
9245
9148
  g_workObj[`judg${toCapitalize(type)}Cnt`][_j]++;
9246
9149
  arrowSprite[g_attrObj[_deleteName].dividePos].removeChild(document.getElementById(_deleteName));
9247
- }
9248
- });
9150
+ delete g_attrObj[_deleteName];
9151
+ });
9249
9152
 
9250
9153
  /**
9251
9154
  * 自動判定
@@ -9747,28 +9650,20 @@ const mainInit = _ => {
9747
9650
  changeStepY(currentFrame);
9748
9651
 
9749
9652
  // ダミー矢印生成(背面に表示するため先に処理)
9750
- if (g_workObj.mkDummyArrow[currentFrame] !== undefined) {
9751
- g_workObj.mkDummyArrow[currentFrame].forEach(data =>
9752
- makeArrow(data, ++dummyArrowCnts[data], `dummyArrow`, g_workObj.dummyArrowColors[data]));
9753
- }
9653
+ g_workObj.mkDummyArrow[currentFrame]?.forEach(data =>
9654
+ makeArrow(data, ++dummyArrowCnts[data], `dummyArrow`, g_workObj.dummyArrowColors[data]));
9754
9655
 
9755
9656
  // 矢印生成
9756
- if (g_workObj.mkArrow[currentFrame] !== undefined) {
9757
- g_workObj.mkArrow[currentFrame].forEach(data =>
9758
- makeArrow(data, ++arrowCnts[data], `arrow`, g_workObj.arrowColors[data]));
9759
- }
9657
+ g_workObj.mkArrow[currentFrame]?.forEach(data =>
9658
+ makeArrow(data, ++arrowCnts[data], `arrow`, g_workObj.arrowColors[data]));
9760
9659
 
9761
9660
  // ダミーフリーズアロー生成
9762
- if (g_workObj.mkDummyFrzArrow[currentFrame] !== undefined) {
9763
- g_workObj.mkDummyFrzArrow[currentFrame].forEach(data =>
9764
- makeFrzArrow(data, ++dummyFrzCnts[data], `dummyFrz`, g_workObj.dummyFrzNormalColors[data], g_workObj.dummyFrzNormalBarColors[data]));
9765
- }
9661
+ g_workObj.mkDummyFrzArrow[currentFrame]?.forEach(data =>
9662
+ makeFrzArrow(data, ++dummyFrzCnts[data], `dummyFrz`, g_workObj.dummyFrzNormalColors[data], g_workObj.dummyFrzNormalBarColors[data]));
9766
9663
 
9767
9664
  // フリーズアロー生成
9768
- if (g_workObj.mkFrzArrow[currentFrame] !== undefined) {
9769
- g_workObj.mkFrzArrow[currentFrame].forEach(data =>
9770
- makeFrzArrow(data, ++frzCnts[data], `frz`, g_workObj.frzNormalColors[data], g_workObj.frzNormalBarColors[data]));
9771
- }
9665
+ g_workObj.mkFrzArrow[currentFrame]?.forEach(data =>
9666
+ makeFrzArrow(data, ++frzCnts[data], `frz`, g_workObj.frzNormalColors[data], g_workObj.frzNormalBarColors[data]));
9772
9667
 
9773
9668
  // 矢印・フリーズアロー移動&消去
9774
9669
  for (let j = 0; j < keyNum; j++) {
@@ -9805,56 +9700,54 @@ const mainInit = _ => {
9805
9700
  }
9806
9701
 
9807
9702
  // 歌詞表示
9808
- if (g_scoreObj.wordData[currentFrame] !== undefined) {
9809
- g_scoreObj.wordData[currentFrame].forEach(tmpObj => {
9810
- g_wordObj.wordDir = tmpObj[0];
9811
- g_wordObj.wordDat = tmpObj[1];
9812
- g_wordSprite = document.querySelector(`#lblword${g_wordObj.wordDir}`);
9703
+ g_scoreObj.wordData[currentFrame]?.forEach(tmpObj => {
9704
+ g_wordObj.wordDir = tmpObj[0];
9705
+ g_wordObj.wordDat = tmpObj[1];
9706
+ g_wordSprite = document.querySelector(`#lblword${g_wordObj.wordDir}`);
9813
9707
 
9814
- const wordDepth = Number(g_wordObj.wordDir);
9815
- if (g_wordObj.wordDat.substring(0, 5) === `[fade`) {
9708
+ const wordDepth = Number(g_wordObj.wordDir);
9709
+ if (g_wordObj.wordDat.substring(0, 5) === `[fade`) {
9816
9710
 
9817
- // フェードイン・アウト開始
9818
- const fkey = fadeFlgs[Object.keys(fadeFlgs).find(flg => g_wordObj.wordDat === `[${flg}]`)];
9819
- g_wordObj[`fade${fkey[0]}Flg${wordDepth}`] = true;
9820
- g_wordObj[`fade${fkey[1]}Flg${wordDepth}`] = false;
9821
- g_wordSprite.style.animationName =
9822
- `fade${fkey[0]}${(++g_workObj[`fade${fkey[0]}No`][wordDepth] % 2)}`;
9711
+ // フェードイン・アウト開始
9712
+ const fkey = fadeFlgs[Object.keys(fadeFlgs).find(flg => g_wordObj.wordDat === `[${flg}]`)];
9713
+ g_wordObj[`fade${fkey[0]}Flg${wordDepth}`] = true;
9714
+ g_wordObj[`fade${fkey[1]}Flg${wordDepth}`] = false;
9715
+ g_wordSprite.style.animationName =
9716
+ `fade${fkey[0]}${(++g_workObj[`fade${fkey[0]}No`][wordDepth] % 2)}`;
9823
9717
 
9824
- g_workObj.lastFadeFrame[wordDepth] = currentFrame;
9825
- g_workObj.wordFadeFrame[wordDepth] = (tmpObj.length > 2 ?
9826
- setIntVal(tmpObj[2], C_WOD_FRAME) : C_WOD_FRAME);
9718
+ g_workObj.lastFadeFrame[wordDepth] = currentFrame;
9719
+ g_workObj.wordFadeFrame[wordDepth] = (tmpObj.length > 2 ?
9720
+ setIntVal(tmpObj[2], C_WOD_FRAME) : C_WOD_FRAME);
9827
9721
 
9828
- g_wordSprite.style.animationDuration = `${g_workObj.wordFadeFrame[wordDepth] / g_fps}s`;
9829
- g_wordSprite.style.animationTimingFunction = `linear`;
9830
- g_wordSprite.style.animationFillMode = `forwards`;
9722
+ g_wordSprite.style.animationDuration = `${g_workObj.wordFadeFrame[wordDepth] / g_fps}s`;
9723
+ g_wordSprite.style.animationTimingFunction = `linear`;
9724
+ g_wordSprite.style.animationFillMode = `forwards`;
9831
9725
 
9832
- } else if ([`[center]`, `[left]`, `[right]`].includes(g_wordObj.wordDat)) {
9726
+ } else if ([`[center]`, `[left]`, `[right]`].includes(g_wordObj.wordDat)) {
9833
9727
 
9834
- // 歌詞位置変更
9835
- g_wordSprite.style.textAlign = g_wordObj.wordDat.slice(1, -1);
9728
+ // 歌詞位置変更
9729
+ g_wordSprite.style.textAlign = g_wordObj.wordDat.slice(1, -1);
9836
9730
 
9837
- } else if (/\[fontSize=\d+\]/.test(g_wordObj.wordDat)) {
9731
+ } else if (/\[fontSize=\d+\]/.test(g_wordObj.wordDat)) {
9838
9732
 
9839
- // フォントサイズ変更
9840
- const fontSize = setIntVal(g_wordObj.wordDat.match(/\d+/)[0], g_limitObj.mainSiz);
9841
- g_wordSprite.style.fontSize = `${fontSize}px`;
9733
+ // フォントサイズ変更
9734
+ const fontSize = setIntVal(g_wordObj.wordDat.match(/\d+/)[0], g_limitObj.mainSiz);
9735
+ g_wordSprite.style.fontSize = `${fontSize}px`;
9842
9736
 
9843
- } else {
9737
+ } else {
9844
9738
 
9845
- // フェードイン・アウト処理後、表示する歌詞を表示
9846
- const fadingFlg = currentFrame - g_workObj.lastFadeFrame[wordDepth] >= g_workObj.wordFadeFrame[wordDepth];
9847
- [`Out`, `In`].forEach(pattern => {
9848
- if (g_wordObj[`fade${pattern}Flg${g_wordObj.wordDir}`] && fadingFlg) {
9849
- g_wordSprite.style.animationName = `none`;
9850
- g_wordObj[`fade${pattern}Flg${g_wordObj.wordDir}`] = false;
9851
- }
9852
- });
9853
- g_workObj[`word${g_wordObj.wordDir}Data`] = g_wordObj.wordDat;
9854
- g_wordSprite.innerHTML = g_wordObj.wordDat;
9855
- }
9856
- });
9857
- }
9739
+ // フェードイン・アウト処理後、表示する歌詞を表示
9740
+ const fadingFlg = currentFrame - g_workObj.lastFadeFrame[wordDepth] >= g_workObj.wordFadeFrame[wordDepth];
9741
+ [`Out`, `In`].forEach(pattern => {
9742
+ if (g_wordObj[`fade${pattern}Flg${g_wordObj.wordDir}`] && fadingFlg) {
9743
+ g_wordSprite.style.animationName = `none`;
9744
+ g_wordObj[`fade${pattern}Flg${g_wordObj.wordDir}`] = false;
9745
+ }
9746
+ });
9747
+ g_workObj[`word${g_wordObj.wordDir}Data`] = g_wordObj.wordDat;
9748
+ g_wordSprite.innerHTML = g_wordObj.wordDat;
9749
+ }
9750
+ });
9858
9751
 
9859
9752
  // 判定キャラクタ消去
9860
9753
  jdgGroups.forEach(jdg => {
@@ -9905,7 +9798,7 @@ const mainInit = _ => {
9905
9798
  }
9906
9799
  g_scoreObj.frameNum++;
9907
9800
  g_scoreObj.baseFrame++;
9908
- g_timeoutEvtId = setTimeout(_ => flowTimeline(), 1000 / g_fps - buffTime);
9801
+ g_timeoutEvtId = setTimeout(flowTimeline, 1000 / g_fps - buffTime);
9909
9802
  }
9910
9803
  };
9911
9804
  g_skinJsObj.main.forEach(func => func());
@@ -9920,7 +9813,7 @@ const mainInit = _ => {
9920
9813
  g_audio.play(musicStartAdjustment);
9921
9814
  }
9922
9815
 
9923
- g_timeoutEvtId = setTimeout(_ => flowTimeline(), 1000 / g_fps);
9816
+ g_timeoutEvtId = setTimeout(flowTimeline, 1000 / g_fps);
9924
9817
  };
9925
9818
 
9926
9819
  /**
@@ -10026,50 +9919,33 @@ const changeColors = (_mkColor, _mkColorCd, _header, _name) => {
10026
9919
  * @param {number} _frameNum
10027
9920
  */
10028
9921
  const changeCssMotions = (_header, _name, _frameNum) => {
10029
-
10030
9922
  const camelHeader = _header === `` ? _name : `${_header}${toCapitalize(_name)}`;
10031
- const frameData = g_workObj[`mk${toCapitalize(camelHeader)}CssMotion`][_frameNum];
10032
-
10033
- if (frameData !== undefined) {
10034
- for (let j = 0; j < frameData.length; j++) {
10035
- const targetj = frameData[j];
10036
- g_workObj[`${camelHeader}CssMotions`][targetj] =
10037
- g_workObj[`mk${toCapitalize(camelHeader)}CssMotionName`][_frameNum][2 * j + g_workObj.dividePos[targetj]];
10038
- }
10039
- }
9923
+ g_workObj[`mk${toCapitalize(camelHeader)}CssMotion`][_frameNum]?.forEach((targetj, j) =>
9924
+ g_workObj[`${camelHeader}CssMotions`][targetj] =
9925
+ g_workObj[`mk${toCapitalize(camelHeader)}CssMotionName`][_frameNum][2 * j + g_workObj.dividePos[targetj]]);
10040
9926
  };
10041
9927
 
10042
9928
  /**
10043
9929
  * スクロール方向の変更(矢印・フリーズアロー)
10044
9930
  * @param {number} _frameNum
10045
9931
  */
10046
- const changeScrollArrowDirs = (_frameNum) => {
10047
- const frameData = g_workObj.mkScrollchArrow[_frameNum];
10048
- if (frameData !== undefined) {
10049
- for (let j = 0; j < frameData.length; j++) {
10050
- const targetj = frameData[j];
10051
- g_workObj.scrollDir[targetj] = g_workObj.scrollDirDefault[targetj] * g_workObj.mkScrollchArrowDir[_frameNum][j];
10052
- g_workObj.dividePos[targetj] = (g_workObj.scrollDir[targetj] === 1 ? 0 : 1);
10053
- }
10054
- }
10055
- };
9932
+ const changeScrollArrowDirs = (_frameNum) =>
9933
+ g_workObj.mkScrollchArrow[_frameNum]?.forEach((targetj, j) => {
9934
+ g_workObj.scrollDir[targetj] = g_workObj.scrollDirDefault[targetj] * g_workObj.mkScrollchArrowDir[_frameNum][j];
9935
+ g_workObj.dividePos[targetj] = (g_workObj.scrollDir[targetj] === 1 ? 0 : 1);
9936
+ });
10056
9937
 
10057
9938
  /**
10058
9939
  * ステップゾーンの位置反転
10059
9940
  * @param {number} _frameNum
10060
9941
  */
10061
- const changeStepY = (_frameNum) => {
10062
- const frameData = g_workObj.mkScrollchStep[_frameNum];
10063
- if (frameData !== undefined) {
10064
- for (let j = 0; j < frameData.length; j++) {
10065
- const targetj = frameData[j];
10066
- const dividePos = (g_workObj.scrollDirDefault[targetj] * g_workObj.mkScrollchStepDir[_frameNum][j] === 1 ? 0 : 1);
10067
- const baseY = C_STEP_Y + g_posObj.reverseStepY * dividePos;
10068
- $id(`stepRoot${targetj}`).top = `${baseY}px`;
10069
- $id(`frzHit${targetj}`).top = `${baseY}px`;
10070
- }
10071
- }
10072
- };
9942
+ const changeStepY = (_frameNum) =>
9943
+ g_workObj.mkScrollchStep[_frameNum]?.forEach((targetj, j) => {
9944
+ const dividePos = (g_workObj.scrollDirDefault[targetj] * g_workObj.mkScrollchStepDir[_frameNum][j] === 1 ? 0 : 1);
9945
+ const baseY = C_STEP_Y + g_posObj.reverseStepY * dividePos;
9946
+ $id(`stepRoot${targetj}`).top = `${baseY}px`;
9947
+ $id(`frzHit${targetj}`).top = `${baseY}px`;
9948
+ });
10073
9949
 
10074
9950
  /**
10075
9951
  * フリーズアローヒット時の描画変更
@@ -10590,9 +10466,8 @@ const resultInit = _ => {
10590
10466
 
10591
10467
  const mTitleForView = [g_headerObj.musicTitleForView[0], g_headerObj.musicTitleForView[1] || ``];
10592
10468
  if (g_headerObj.musicTitlesForView[g_headerObj.musicNos[g_stateObj.scoreId]] !== undefined) {
10593
- mTitleForView.forEach((mTitle, j) => {
10594
- mTitleForView[j] = g_headerObj.musicTitlesForView[g_headerObj.musicNos[g_stateObj.scoreId]][j];
10595
- });
10469
+ mTitleForView.forEach((mTitle, j) =>
10470
+ mTitleForView[j] = g_headerObj.musicTitlesForView[g_headerObj.musicNos[g_stateObj.scoreId]][j]);
10596
10471
  }
10597
10472
 
10598
10473
  const keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`;
@@ -10678,12 +10553,11 @@ const resultInit = _ => {
10678
10553
  };
10679
10554
 
10680
10555
  // キャラクタ、スコア描画
10681
- Object.keys(jdgScoreObj).forEach(score => {
10556
+ Object.keys(jdgScoreObj).forEach(score =>
10682
10557
  multiAppend(resultWindow,
10683
10558
  makeCssResultSymbol(`lbl${jdgScoreObj[score].id}`, 0, g_cssObj[`common_${jdgScoreObj[score].color}`], jdgScoreObj[score].pos, jdgScoreObj[score].label),
10684
10559
  makeCssResultSymbol(`lbl${jdgScoreObj[score].id}S`, 50, g_cssObj.common_score, jdgScoreObj[score].pos, g_resultObj[score], C_ALIGN_RIGHT),
10685
- );
10686
- });
10560
+ ));
10687
10561
  if (g_stateObj.autoAll === C_FLG_OFF) {
10688
10562
  multiAppend(resultWindow,
10689
10563
  makeCssResultSymbol(`lblFast`, 350, g_cssObj.common_matari, 0, g_lblNameObj.j_fast),
@@ -10852,9 +10726,8 @@ const resultInit = _ => {
10852
10726
  [`[url]`, g_isLocal ? `` : `${twiturl.toString()}`.replace(/[\t\n]/g, ``)]
10853
10727
  ]);
10854
10728
  if (g_presetObj.resultVals !== undefined) {
10855
- Object.keys(g_presetObj.resultVals).forEach(key => {
10856
- tweetResultTmp = tweetResultTmp.split(`[${key}]`).join(g_resultObj[g_presetObj.resultVals[key]]);
10857
- });
10729
+ Object.keys(g_presetObj.resultVals).forEach(key =>
10730
+ tweetResultTmp = tweetResultTmp.split(`[${key}]`).join(g_resultObj[g_presetObj.resultVals[key]]));
10858
10731
  }
10859
10732
  const resultText = `${unEscapeHtml(tweetResultTmp)}`;
10860
10733
  const tweetResult = `https://twitter.com/intent/tweet?text=${encodeURIComponent(resultText)}`;
@@ -10876,9 +10749,8 @@ const resultInit = _ => {
10876
10749
  resetCommonBtn(`btnBack`, g_lblNameObj.b_back, g_lblPosObj.btnRsBack, titleInit, g_cssObj.button_Back),
10877
10750
 
10878
10751
  // リザルトデータをクリップボードへコピー
10879
- createCss2Button(`btnCopy`, g_lblNameObj.b_copy, _ => {
10880
- copyTextToClipboard(resultText, g_msgInfoObj.I_0001);
10881
- }, g_lblPosObj.btnRsCopy, g_cssObj.button_Setting),
10752
+ createCss2Button(`btnCopy`, g_lblNameObj.b_copy, _ => copyTextToClipboard(resultText, g_msgInfoObj.I_0001),
10753
+ g_lblPosObj.btnRsCopy, g_cssObj.button_Setting),
10882
10754
 
10883
10755
  // リザルトデータをTwitterへ転送
10884
10756
  createCss2Button(`btnTweet`, g_lblNameObj.b_tweet, _ => true, Object.assign(g_lblPosObj.btnRsTweet, {
@@ -10943,7 +10815,7 @@ const resultInit = _ => {
10943
10815
  g_scoreObj.resultFrameNum++;
10944
10816
  g_scoreObj.backResultFrameNum++;
10945
10817
  g_scoreObj.maskResultFrameNum++;
10946
- g_timeoutEvtResultId = setTimeout(_ => flowResultTimeline(), 1000 / g_fps - buffTime);
10818
+ g_timeoutEvtResultId = setTimeout(flowResultTimeline, 1000 / g_fps - buffTime);
10947
10819
  };
10948
10820
  flowResultTimeline();
10949
10821