danoniplus 40.1.0 → 40.3.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 +103 -41
- package/js/lib/danoni_constants.js +28 -2
- package/package.json +1 -1
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 : 2025/03/
|
|
7
|
+
* Revised : 2025/03/08
|
|
8
8
|
*
|
|
9
9
|
* https://github.com/cwtickle/danoniplus
|
|
10
10
|
*/
|
|
11
|
-
const g_version = `Ver 40.
|
|
12
|
-
const g_revisedDate = `2025/03/
|
|
11
|
+
const g_version = `Ver 40.3.0`;
|
|
12
|
+
const g_revisedDate = `2025/03/08`;
|
|
13
13
|
|
|
14
14
|
// カスタム用バージョン (danoni_custom.js 等で指定可)
|
|
15
15
|
let g_localVersion = ``;
|
|
@@ -475,19 +475,20 @@ const getIndent = (_level) => ' '.repeat(_level * 4);
|
|
|
475
475
|
* ストレージ情報の取得
|
|
476
476
|
* @param {string} _name g_storageFuncの実行キー名
|
|
477
477
|
* @param {string} _key g_storageFuncの実行キーの引数
|
|
478
|
+
* @param {boolean} [_colorFmt=true]
|
|
478
479
|
* @returns {string}
|
|
479
480
|
*/
|
|
480
|
-
const viewKeyStorage = (_name, _key =
|
|
481
|
+
const viewKeyStorage = (_name, _key = ``, _colorFmt = true) => {
|
|
481
482
|
|
|
482
483
|
// キャッシュ設定
|
|
483
484
|
if (!viewKeyStorage.cache) {
|
|
484
485
|
viewKeyStorage.cache = new Map();
|
|
485
486
|
}
|
|
486
|
-
const cacheKey = _key + _name;
|
|
487
|
+
const cacheKey = _key + _name + String(_colorFmt);
|
|
487
488
|
if (viewKeyStorage.cache.has(cacheKey)) {
|
|
488
489
|
return viewKeyStorage.cache.get(cacheKey);
|
|
489
490
|
}
|
|
490
|
-
const result = formatObject(g_storageFunc.get(_name)?.(_key) || setVal(_name, ``, C_TYP_CALC));
|
|
491
|
+
const result = formatObject(g_storageFunc.get(_name)?.(_key) || setVal(_name, ``, C_TYP_CALC), 0, { colorFmt: _colorFmt });
|
|
491
492
|
viewKeyStorage.cache.set(cacheKey, result);
|
|
492
493
|
return result;
|
|
493
494
|
}
|
|
@@ -496,44 +497,53 @@ const viewKeyStorage = (_name, _key = ``) => {
|
|
|
496
497
|
* オブジェクトのネスト表示処理
|
|
497
498
|
* @param {Object} _obj
|
|
498
499
|
* @param {Number} _indent
|
|
499
|
-
* @param {
|
|
500
|
-
* @param {
|
|
501
|
-
* @param {string} [key='']
|
|
500
|
+
* @param {boolean} [colorFmt=true] フォーマット加工フラグ
|
|
501
|
+
* @param {string} [rootKey=''] オブジェクトの最上位プロパティ名
|
|
502
502
|
* @param {Object} [_parent=null]
|
|
503
503
|
* @returns {string}
|
|
504
504
|
*/
|
|
505
|
-
const formatObject = (_obj, _indent = 0, {
|
|
505
|
+
const formatObject = (_obj, _indent = 0, { colorFmt = true, rootKey = `` } = {}) => {
|
|
506
506
|
if (_obj === null || typeof _obj !== 'object') {
|
|
507
507
|
return JSON.stringify(_obj);
|
|
508
508
|
}
|
|
509
|
-
if (seen.has(_obj)) {
|
|
510
|
-
return '[Circular]';
|
|
511
|
-
}
|
|
512
|
-
seen.add(_obj);
|
|
513
509
|
const baseIndent = getIndent(_indent);
|
|
514
510
|
const nestedIndent = getIndent(_indent + 1);
|
|
515
511
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
512
|
+
/**
|
|
513
|
+
* データの装飾処理
|
|
514
|
+
* @param {string|boolean|number|Object} _value
|
|
515
|
+
* @param {string} _rootKey
|
|
516
|
+
* @returns {string}
|
|
517
|
+
*/
|
|
518
|
+
const formatValue = (_value, _rootKey) => {
|
|
519
519
|
if (colorFmt) {
|
|
520
|
-
if (typeof _value ===
|
|
521
|
-
|
|
520
|
+
if (typeof _value === C_TYP_STRING) {
|
|
521
|
+
|
|
522
|
+
// カラーコードの色付け処理
|
|
523
|
+
_value = escapeHtml(_value).replaceAll(`\n`, `<br>`);
|
|
524
|
+
const colorCodePattern = /(#|0x)(?:[A-Fa-f0-9]{6}(?:[A-Fa-f0-9]{2})?|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{3})/g;
|
|
522
525
|
if (colorCodePattern.test(_value)) {
|
|
523
526
|
return _value.replace(colorCodePattern, (match) =>
|
|
524
527
|
`<span style="color:${match.replace(`0x`, `#`)}">◆</span>${match.replace(`0x`, `#`)}`);
|
|
525
528
|
}
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
529
|
+
} else if (typeof _value === C_TYP_BOOLEAN) {
|
|
530
|
+
|
|
531
|
+
// boolean値の色付け処理
|
|
532
|
+
return (_value ? `<span style="color:#66ff66">✔ true</span>` :
|
|
533
|
+
`<span style="color:#ff9999">❌ false</span>`);
|
|
534
|
+
|
|
535
|
+
} else if (typeof _value === C_TYP_NUMBER) {
|
|
536
|
+
|
|
537
|
+
if (_rootKey.startsWith(`scrollDir`)) {
|
|
538
|
+
// scrollDirXのスクロール方向表示処理
|
|
539
|
+
return _value === 1 ? `1|<span style="color:#ff9999">↑</span>` : `-1|<span style="color:#66ff66">↓</span>`;
|
|
540
|
+
|
|
541
|
+
} else if (_rootKey.startsWith(`keyCtrl`) && !_rootKey.startsWith(`keyCtrlPtn`)) {
|
|
542
|
+
// keyCtrlXの対応キー表示処理
|
|
543
|
+
return (g_kCd[_value] && _value !== 0) ? `${_value}|<span style="color:#ffff66">${g_kCd[_value]}</span>` : `----`;
|
|
532
544
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
if (typeof _value === 'object' && _value !== null) {
|
|
536
|
-
return formatObject(_value, _indent + 1, { seen, colorFmt, key }, _parent);
|
|
545
|
+
} else if (typeof _value === C_TYP_OBJECT && _value !== null) {
|
|
546
|
+
return formatObject(_value, _indent + 1, { colorFmt, rootKey: _rootKey });
|
|
537
547
|
}
|
|
538
548
|
}
|
|
539
549
|
return JSON.stringify(_value);
|
|
@@ -547,7 +557,7 @@ const formatObject = (_obj, _indent = 0, { seen = new WeakSet(), colorFmt = true
|
|
|
547
557
|
if (colorFmt && _obj.length > 100) {
|
|
548
558
|
const filteredArray = _obj.reduce((result, value, index) => {
|
|
549
559
|
if (hasVal(value)) {
|
|
550
|
-
result.push(`${index}: ${formatValue(value,
|
|
560
|
+
result.push(`${index}: ${formatValue(value, rootKey)}`);
|
|
551
561
|
}
|
|
552
562
|
return result;
|
|
553
563
|
}, []);
|
|
@@ -558,11 +568,11 @@ const formatObject = (_obj, _indent = 0, { seen = new WeakSet(), colorFmt = true
|
|
|
558
568
|
.map(value => {
|
|
559
569
|
const isNestedObject = typeof value === 'object' && value !== null;
|
|
560
570
|
return isArrayOfArrays
|
|
561
|
-
? `${nestedIndent}${formatValue(value,
|
|
571
|
+
? `${nestedIndent}${formatValue(value, rootKey)}`
|
|
562
572
|
: isNestedObject
|
|
563
|
-
? formatObject(value, _indent + 1, {
|
|
564
|
-
: formatValue(value,
|
|
565
|
-
}).join(isArrayOfArrays ? `,<br>` : `, `);
|
|
573
|
+
? formatObject(value, _indent + 1, { colorFmt, rootKey })
|
|
574
|
+
: formatValue(value, rootKey)
|
|
575
|
+
}).filter(val => !hasVal(val) || val !== `----`).join(isArrayOfArrays ? `,<br>` : `, `);
|
|
566
576
|
|
|
567
577
|
return `[${isArrayOfArrays ? `<br>` : ``}${formattedArray}${isArrayOfArrays ? `<br>${baseIndent}` : ''}]`;
|
|
568
578
|
}
|
|
@@ -571,12 +581,12 @@ const formatObject = (_obj, _indent = 0, { seen = new WeakSet(), colorFmt = true
|
|
|
571
581
|
const formattedEntries = Object.entries(_obj)
|
|
572
582
|
.map(([key, value]) => {
|
|
573
583
|
const isNestedObject = typeof value === 'object' && value !== null;
|
|
574
|
-
const
|
|
584
|
+
const baseKey = rootKey === `` ? key : rootKey;
|
|
575
585
|
const formattedValue = isNestedObject
|
|
576
|
-
? formatObject(value, _indent + 1, {
|
|
577
|
-
: formatValue(value,
|
|
586
|
+
? formatObject(value, _indent + 1, { colorFmt, rootKey: baseKey }, _obj)
|
|
587
|
+
: formatValue(value, baseKey);
|
|
578
588
|
return `<br>${nestedIndent}"${key}": ${formattedValue}`;
|
|
579
|
-
}).join(`,`);
|
|
589
|
+
}).filter(val => !hasVal(val) || val !== `----`).join(`,`);
|
|
580
590
|
|
|
581
591
|
let result = `{${formattedEntries}<br>${baseIndent}}`;
|
|
582
592
|
if (!colorFmt) {
|
|
@@ -2529,6 +2539,44 @@ const initialControl = async () => {
|
|
|
2529
2539
|
delete g_keyObj[key];
|
|
2530
2540
|
}
|
|
2531
2541
|
});
|
|
2542
|
+
|
|
2543
|
+
// エディター用のフォーマッター作成
|
|
2544
|
+
const customKeyList = g_headerObj.keyLists.filter(val =>
|
|
2545
|
+
g_keyObj.defaultKeyList.findIndex(key => key === val) < 0);
|
|
2546
|
+
|
|
2547
|
+
customKeyList.forEach(key => {
|
|
2548
|
+
const keyBase = `${key}_0`;
|
|
2549
|
+
const keyCtrlPtn = `${g_keyObj.defaultProp}${keyBase}`;
|
|
2550
|
+
const keyGroup = g_keyObj[`keyGroup${keyBase}`];
|
|
2551
|
+
const keyGroupList = makeDedupliArray(keyGroup.flat());
|
|
2552
|
+
const orgKeyNum = g_keyObj[keyCtrlPtn].length;
|
|
2553
|
+
const baseX = Math.floor(Math.random() * (100 - keyGroupList.length));
|
|
2554
|
+
|
|
2555
|
+
keyGroupList.forEach((keyGroupNo, j) => {
|
|
2556
|
+
const keyN = keyGroupNo === `0` ? key : `${key}_${j + 1}`;
|
|
2557
|
+
const filterCond = (j) => keyGroup[j].findIndex(val => val === keyGroupNo) >= 0;
|
|
2558
|
+
const keyCtrlList = g_keyObj[keyCtrlPtn].filter((val, j) => filterCond(j));
|
|
2559
|
+
const charaList = g_keyObj[`chara${keyBase}`].filter((val, j) => filterCond(j));
|
|
2560
|
+
const colorList = g_keyObj[`color${keyBase}_0`].filter((val, j) => filterCond(j));
|
|
2561
|
+
const keyNum = g_keyObj[keyCtrlPtn].filter((val, j) => filterCond(j)).length;
|
|
2562
|
+
|
|
2563
|
+
g_editorTmp[keyN] = {};
|
|
2564
|
+
g_editorTmp[keyN].id = orgKeyNum * 100 + baseX + j;
|
|
2565
|
+
g_editorTmp[keyN].num = keyNum;
|
|
2566
|
+
g_editorTmp[keyN].chars = keyCtrlList.map(val => g_kCd[val[0]]);
|
|
2567
|
+
g_editorTmp[keyN].keys = keyCtrlList.map(val => g_kCdN[val[0]]).map(val => replaceStr(val, g_escapeStr.editorKey));
|
|
2568
|
+
g_editorTmp[keyN].alternativeKeys = keyCtrlList.map(val => val[1] === 0 ? `` : g_kCdN[val[1]]).map(val => replaceStr(val, g_escapeStr.editorKey));
|
|
2569
|
+
g_editorTmp[keyN].noteNames = charaList.map(val => `${val}_data`);
|
|
2570
|
+
g_editorTmp[keyN].freezeNames = charaList.map(val => {
|
|
2571
|
+
let frzName = replaceStr(val, g_escapeStr.frzName);
|
|
2572
|
+
if (frzName.indexOf(`frz`) === -1 && frzName.indexOf(`foni`) === -1) {
|
|
2573
|
+
frzName = frzName.replaceAll(frzName, `frz${toCapitalize(frzName)}`);
|
|
2574
|
+
}
|
|
2575
|
+
return `${frzName}_data`;
|
|
2576
|
+
});
|
|
2577
|
+
g_editorTmp[keyN].colorGroup = colorList.map(val => val % 3);
|
|
2578
|
+
});
|
|
2579
|
+
});
|
|
2532
2580
|
};
|
|
2533
2581
|
|
|
2534
2582
|
/**
|
|
@@ -5000,10 +5048,12 @@ const dataMgtInit = () => {
|
|
|
5000
5048
|
g_stateObj[`dm_${key}`] = C_FLG_OFF;
|
|
5001
5049
|
g_settings.dataMgtNum[key] = 0;
|
|
5002
5050
|
|
|
5051
|
+
const keyWidth = Math.min(Math.max(50, getStrWidth(getKeyName(key), g_limitObj.setLblSiz, getBasicFont())), 80);
|
|
5003
5052
|
keyListSprite.appendChild(createMgtButton(key, j - 2, 0, {
|
|
5004
|
-
w:
|
|
5053
|
+
w: keyWidth,
|
|
5054
|
+
siz: getFontSize(getKeyName(key), keyWidth, getBasicFont(), g_limitObj.setLblSiz, 10),
|
|
5005
5055
|
}));
|
|
5006
|
-
document.getElementById(`btn${key}`).innerHTML = getKeyName(key);
|
|
5056
|
+
document.getElementById(`btn${toCapitalize(key)}`).innerHTML = getKeyName(key);
|
|
5007
5057
|
|
|
5008
5058
|
keyListSprite.appendChild(createCss2Button(`btnView${key}`, ``, evt => {
|
|
5009
5059
|
keyList.forEach(keyx => {
|
|
@@ -5030,7 +5080,7 @@ const dataMgtInit = () => {
|
|
|
5030
5080
|
multiAppend(divRoot,
|
|
5031
5081
|
createCss2Button(`btnBack`, g_lblNameObj.b_back, () => true,
|
|
5032
5082
|
Object.assign(g_lblPosObj.btnResetBack, {
|
|
5033
|
-
resetFunc: () =>
|
|
5083
|
+
resetFunc: () => [`title`, `precondition`].includes(prevPage) ? titleInit() : g_moveSettingWindow(false),
|
|
5034
5084
|
}), g_cssObj.button_Back),
|
|
5035
5085
|
|
|
5036
5086
|
createCss2Button(`btnPrecond`, g_lblNameObj.b_precond, () => true,
|
|
@@ -5137,6 +5187,11 @@ const preconditionInit = () => {
|
|
|
5137
5187
|
.replace(/[\t\n]/g, ``), 0, 15, g_cssObj.flex_centering),
|
|
5138
5188
|
|
|
5139
5189
|
createDivCss2Label(`lblPrecondView`, viewKeyStorage(`g_rootObj`), g_lblPosObj.lblPrecondView),
|
|
5190
|
+
createCss2Button(`btnPrecondView`, g_lblNameObj.b_copyStorage, () =>
|
|
5191
|
+
copyTextToClipboard(
|
|
5192
|
+
viewKeyStorage(g_settings.preconditions[g_settings.preconditionNum * numOfPrecs + g_settings.preconditionNumSub], ``, false),
|
|
5193
|
+
g_msgInfoObj.I_0007),
|
|
5194
|
+
g_lblPosObj.btnPrecondView, g_cssObj.button_Default, g_cssObj.button_ON),
|
|
5140
5195
|
);
|
|
5141
5196
|
setUserSelect($id(`lblPrecondView`), `text`);
|
|
5142
5197
|
|
|
@@ -5166,6 +5221,7 @@ const preconditionInit = () => {
|
|
|
5166
5221
|
}
|
|
5167
5222
|
lblPrecondView.innerHTML = viewKeyStorage(g_settings.preconditions[g_settings.preconditionNum * numOfPrecs + j]);
|
|
5168
5223
|
lblPrecondView.scrollTop = 0;
|
|
5224
|
+
g_settings.preconditionNumSub = j;
|
|
5169
5225
|
evt.target.classList.replace(g_cssObj.button_Default, g_cssObj.button_Reset);
|
|
5170
5226
|
}, {
|
|
5171
5227
|
x: g_btnX() + g_btnWidth((j % (numOfPrecs / 2)) / (numOfPrecs / 2 + 1)),
|
|
@@ -5185,6 +5241,12 @@ const preconditionInit = () => {
|
|
|
5185
5241
|
g_customJsObj.precondition.forEach(func => func());
|
|
5186
5242
|
|
|
5187
5243
|
multiAppend(divRoot,
|
|
5244
|
+
|
|
5245
|
+
// データ管理画面へ移動
|
|
5246
|
+
createCss2Button(`btnReset`, g_lblNameObj.dataReset, () => {
|
|
5247
|
+
dataMgtInit();
|
|
5248
|
+
}, g_lblPosObj.btnReset, g_cssObj.button_Reset),
|
|
5249
|
+
|
|
5188
5250
|
createCss2Button(`btnBack`, g_lblNameObj.b_back, () => true,
|
|
5189
5251
|
Object.assign(g_lblPosObj.btnPrecond, {
|
|
5190
5252
|
resetFunc: () => {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Source by tickle
|
|
7
7
|
* Created : 2019/11/19
|
|
8
|
-
* Revised : 2025/03/
|
|
8
|
+
* Revised : 2025/03/08 (v40.3.0)
|
|
9
9
|
*
|
|
10
10
|
* https://github.com/cwtickle/danoniplus
|
|
11
11
|
*/
|
|
@@ -283,6 +283,9 @@ const updateWindowSiz = () => {
|
|
|
283
283
|
btnKeyStorage: {
|
|
284
284
|
x: g_btnX(1) - 140, y: 100 + g_sHeight / 4 + 10, w: 70, h: 20, siz: 16,
|
|
285
285
|
},
|
|
286
|
+
btnPrecondView: {
|
|
287
|
+
x: g_btnX(1) - 90, y: 110, w: 70, h: 20, siz: 16,
|
|
288
|
+
},
|
|
286
289
|
|
|
287
290
|
/** 設定画面 */
|
|
288
291
|
btnBack: {
|
|
@@ -785,6 +788,18 @@ const g_escapeStr = {
|
|
|
785
788
|
[`all[]`, `sumData(g_detailObj.arrowCnt[{0}]) + sumData(g_detailObj.frzCnt[{0}])`],
|
|
786
789
|
[`maxlife[]`, `g_headerObj.maxLifeVal`],
|
|
787
790
|
],
|
|
791
|
+
editorKey: [
|
|
792
|
+
[`ArrowLeft`, `KeyU`],
|
|
793
|
+
[`ArrowDown`, `KeyI`],
|
|
794
|
+
[`ArrowUp`, `Digit8`],
|
|
795
|
+
[`ArrowRight`, `KeyO`],
|
|
796
|
+
[`Space`, `KeyG`],
|
|
797
|
+
[`KeyB`, `KeyH`],
|
|
798
|
+
[`Enter`, `BackSlash`],
|
|
799
|
+
[`ShiftLeft`, `KeyZ`],
|
|
800
|
+
[`ShiftRight`, `Slash`],
|
|
801
|
+
[`Tab`, `KeyQ`],
|
|
802
|
+
]
|
|
788
803
|
};
|
|
789
804
|
|
|
790
805
|
/** 設定・オプション画面用共通 */
|
|
@@ -1156,8 +1171,9 @@ const g_settings = {
|
|
|
1156
1171
|
settingWindowNum: 0,
|
|
1157
1172
|
|
|
1158
1173
|
preconditions: [`g_rootObj`, `g_headerObj`, `g_keyObj`, `g_scoreObj`, `g_workObj`,
|
|
1159
|
-
`g_detailObj`, `g_stateObj`, `g_attrObj`],
|
|
1174
|
+
`g_detailObj`, `g_stateObj`, `g_attrObj`, `g_editorTmp`],
|
|
1160
1175
|
preconditionNum: 0,
|
|
1176
|
+
preconditionNumSub: 0,
|
|
1161
1177
|
};
|
|
1162
1178
|
|
|
1163
1179
|
g_settings.volumeNum = g_settings.volumes.length - 1;
|
|
@@ -2487,6 +2503,7 @@ const g_keyObj = {
|
|
|
2487
2503
|
dfPtnNum: 0,
|
|
2488
2504
|
|
|
2489
2505
|
minKeyCtrlNum: 2,
|
|
2506
|
+
defaultKeyList: [],
|
|
2490
2507
|
|
|
2491
2508
|
// キー別ヘッダー
|
|
2492
2509
|
// - 譜面データ中に出てくる矢印(ノーツ)の種類と順番(ステップゾーン表示順)を管理する
|
|
@@ -3023,6 +3040,11 @@ const g_keyObj = {
|
|
|
3023
3040
|
// g_keyObj.defaultProp の上書きを禁止
|
|
3024
3041
|
Object.defineProperty(g_keyObj, `defaultProp`, { writable: false });
|
|
3025
3042
|
|
|
3043
|
+
// 既定のキー定義リストを動的に作成
|
|
3044
|
+
Object.keys(g_keyObj)
|
|
3045
|
+
.filter(key => key.startsWith(g_keyObj.defaultProp) && key.endsWith(`_0`))
|
|
3046
|
+
.forEach(key => g_keyObj.defaultKeyList.push(key.split(`_`)[0].slice(g_keyObj.defaultProp.length)));
|
|
3047
|
+
|
|
3026
3048
|
// キーパターンのコピーリスト
|
|
3027
3049
|
// ・コピー先:コピー元の順に指定する
|
|
3028
3050
|
// ・上から順に処理する
|
|
@@ -3157,6 +3179,8 @@ g_keycons.groups.forEach(type => {
|
|
|
3157
3179
|
tmpName.forEach(property => g_keyObj[`${property.slice(0, -2)}`] = g_keyObj[property].concat());
|
|
3158
3180
|
});
|
|
3159
3181
|
|
|
3182
|
+
const g_editorTmp = {};
|
|
3183
|
+
|
|
3160
3184
|
// 特殊キーのコピー種 (simple: 代入、multiple: 配列ごと代入)
|
|
3161
3185
|
// 後でプロパティ削除に影響するため、先頭文字が全く同じ場合は長い方を先に定義する (例: divMax, div)
|
|
3162
3186
|
const g_keyCopyLists = {
|
|
@@ -3447,6 +3471,7 @@ const g_lang_msgInfoObj = {
|
|
|
3447
3471
|
I_0004: `musicUrlが設定されていないため、無音モードで再生します`,
|
|
3448
3472
|
I_0005: `正規のミラー譜面で無いため、ハイスコアは保存されません`,
|
|
3449
3473
|
I_0006: `ローカルストレージ情報をクリップボードにコピーしました!`,
|
|
3474
|
+
I_0007: `オブジェクト情報をクリップボードにコピーしました!`,
|
|
3450
3475
|
},
|
|
3451
3476
|
En: {
|
|
3452
3477
|
W_0001: `Your browser is not guaranteed to work.<br>
|
|
@@ -3501,6 +3526,7 @@ const g_lang_msgInfoObj = {
|
|
|
3501
3526
|
I_0004: `Play in silence mode because "musicUrl" is not set`,
|
|
3502
3527
|
I_0005: `Highscore is not saved because not a regular mirrored chart.`,
|
|
3503
3528
|
I_0006: `Local storage information copied to clipboard!`,
|
|
3529
|
+
I_0007: `Object information copied to clipboard!`,
|
|
3504
3530
|
},
|
|
3505
3531
|
};
|
|
3506
3532
|
|