danoniplus 51.2.2 → 51.4.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 : 2026/10/07
7
+ * Revised : 2026/10/12
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 51.2.2`;
12
- const g_revisedDate = `2026/10/07`;
11
+ const g_version = `Ver 51.4.0`;
12
+ const g_revisedDate = `2026/10/12`;
13
13
 
14
14
  // カスタム用バージョン (danoni_custom.js 等で指定可)
15
15
  let g_localVersion = ``;
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2019/11/19
8
- * Revised : 2026/10/03 (v51.2.0)
8
+ * Revised : 2026/10/12 (v51.4.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -1406,7 +1406,7 @@ const g_settings = {
1406
1406
  },
1407
1407
  environments: [`adjustment`, `volume`, `colorType`, `appearance`, `opacity`, `hitPosition`,
1408
1408
  `arrowJdgX`, `arrowJdgY`, `frzJdgX`, `frzJdgY`, `shortcutX`, `shortcutY`],
1409
- keyStorages: [`reverse`, `keyCtrl`, `keyCtrlPtn`, `shuffle`, `color`, `stepRtn`],
1409
+ keyStorages: [`reverse`, `keyCtrl`, `keyCtrlPtn`, `shuffle`, `color`, `stepRtn`, `shortcut`],
1410
1410
  colorStorages: [`setColor`, `setShadowColor`, `frzColor`, `frzShadowColor`],
1411
1411
 
1412
1412
  mSelectableTerms: 3,
@@ -1551,6 +1551,12 @@ g_settings.volumeNum = g_settings.volumes.length - 1;
1551
1551
  g_settings.bgmVolumeNum = roundZero(g_settings.volumes.findIndex(v => v === g_stateObj.bgmVolume));
1552
1552
  g_settings.opacityNum = g_settings.opacitys.length - 1;
1553
1553
 
1554
+ const g_settingWindowTitleKeys = new Map([
1555
+ [optionInit, `Option`],
1556
+ [settingsDisplayInit, `Display`],
1557
+ [exSettingInit, `Settings`],
1558
+ ]);
1559
+
1554
1560
  /**
1555
1561
  * 設定画面間移動
1556
1562
  */
@@ -2353,6 +2359,9 @@ const g_keycons = {
2353
2359
  cursorNum: 0,
2354
2360
  keySwitchNum: 0,
2355
2361
  colorCursorNum: 0,
2362
+
2363
+ shortcutTypes: [`Retry`, `TitleBack`, `Pause`],
2364
+ defaultShortCuts: { Retry: C_KEY_RETRY, TitleBack: C_KEY_TITLEBACK, Pause: C_KEY_PAUSE },
2356
2365
  };
2357
2366
 
2358
2367
  let g_displays = [`stepZone`, `judgment`, `lifeGauge`, `score`, `musicInfo`, `filterLine`,
@@ -2913,7 +2922,7 @@ const g_shortcutObj = {
2913
2922
  NumpadEnter: { id: `btnPlay` },
2914
2923
  ShiftLeft_Tab: { id: `btnBack` },
2915
2924
  ShiftRight_Tab: { id: `btnBack` },
2916
- Tab: { id: `btnDisplay` },
2925
+ Tab: { id: `btnNextSetting` },
2917
2926
  KeyU: { id: `btnSettingSummary` },
2918
2927
  },
2919
2928
  difSelector: {
@@ -2948,7 +2957,7 @@ const g_shortcutObj = {
2948
2957
  NumpadEnter: { id: `lnkDifficulty` },
2949
2958
  ShiftLeft_Tab: { id: `btnBack` },
2950
2959
  ShiftRight_Tab: { id: `btnBack` },
2951
- Tab: { id: `btnDisplay` },
2960
+ Tab: { id: `btnNextSetting` },
2952
2961
  KeyU: { id: `btnSettingSummary` },
2953
2962
  },
2954
2963
  scoreDetail: {
@@ -2997,7 +3006,7 @@ const g_shortcutObj = {
2997
3006
  NumpadEnter: { id: `btnPlay` },
2998
3007
  ShiftLeft_Tab: { id: `btnBack` },
2999
3008
  ShiftRight_Tab: { id: `btnBack` },
3000
- Tab: { id: `btnDisplay` },
3009
+ Tab: { id: `btnNextSetting` },
3001
3010
  KeyU: { id: `btnSettingSummary` },
3002
3011
  },
3003
3012
  settingsDisplay: {
@@ -3094,7 +3103,7 @@ const g_shortcutObj = {
3094
3103
  NumpadEnter: { id: `btnPlay` },
3095
3104
  ShiftLeft_Tab: { id: `btnBack` },
3096
3105
  ShiftRight_Tab: { id: `btnBack` },
3097
- Tab: { id: `btnSettings` },
3106
+ Tab: { id: `btnNextSetting` },
3098
3107
  KeyU: { id: `btnSettingSummary` },
3099
3108
  },
3100
3109
  displayPreview: {
@@ -3113,7 +3122,7 @@ const g_shortcutObj = {
3113
3122
  NumpadEnter: { id: `btnPlay` },
3114
3123
  ShiftLeft_Tab: { id: `btnBack` },
3115
3124
  ShiftRight_Tab: { id: `btnBack` },
3116
- Tab: { id: `btnSettings` },
3125
+ Tab: { id: `btnNextSetting` },
3117
3126
  },
3118
3127
  exSetting: {
3119
3128
  ShiftLeft_KeyP: { id: `lnkPlayWindowL` },
@@ -3154,7 +3163,7 @@ const g_shortcutObj = {
3154
3163
  Enter: { id: `btnPlay` },
3155
3164
  ShiftLeft_Tab: { id: `btnBack` },
3156
3165
  ShiftRight_Tab: { id: `btnBack` },
3157
- Tab: { id: `btnexSetting` },
3166
+ Tab: { id: `btnNextSetting` },
3158
3167
  KeyU: { id: `btnSettingSummary` },
3159
3168
  },
3160
3169
  keyConfig: {
@@ -3217,11 +3226,11 @@ const g_btnPatterns = {
3217
3226
  title: { Start: 0, Comment: -10, MusicSelectRandom: -10 },
3218
3227
  dataMgt: { Back: 0, Environment: -35, Highscores: -35, CustomKey: -35, Others: -35 },
3219
3228
  precondition: { Back: 0 },
3220
- option: { Back: 0, KeyConfig: 0, Play: 0, Display: -5, Save: -10, Graph: -25, SettingSummary: -10 },
3229
+ option: { Back: 0, KeyConfig: 0, Play: 0, NextSetting: -5, Save: -10, Graph: -25, SettingSummary: -10 },
3221
3230
  difSelector: {},
3222
3231
  scoreDetail: {},
3223
- settingsDisplay: { Back: 0, KeyConfig: 0, Play: 0, Save: -10, Settings: -5, SettingSummary: -10 },
3224
- exSetting: { Back: 0, KeyConfig: 0, Play: 0, exSetting: -5, Save: -10, SettingSummary: -10 },
3232
+ settingsDisplay: { Back: 0, KeyConfig: 0, Play: 0, Save: -10, NextSetting: -5, SettingSummary: -10 },
3233
+ exSetting: { Back: 0, KeyConfig: 0, Play: 0, NextSetting: -5, Save: -10, SettingSummary: -10 },
3225
3234
  loadingIos: { Play: 0 },
3226
3235
  keyConfig: { Back: -3, Play: 0 },
3227
3236
  result: { Back: -5, Copy: -5, Tweet: -5, Gitter: -5, Retry: 0, GaugeTransition: -15 },
@@ -4655,6 +4664,7 @@ const g_lblNameObj = {
4655
4664
  b_cReset: `Reset`,
4656
4665
  b_precond: `Precondition`,
4657
4666
  b_keyLock: `KeyLock`,
4667
+ b_kbLane: `Group Color`,
4658
4668
 
4659
4669
  Difficulty: `Difficulty`,
4660
4670
  Speed: `Speed`,
@@ -5087,6 +5097,7 @@ const g_lang_msgObj = {
5087
5097
 
5088
5098
  graph: `譜面密度や速度変化状況、\n譜面の難易度などの情報を表示します。`,
5089
5099
  dataSave: `ハイスコア、リバース設定、\nキーコンフィグの保存の有無を設定します。`,
5100
+ toOption: `譜面、速度、ゲージなどの基本設定を設定します。`,
5090
5101
  toDisplay: `プレイ画面上のオブジェクトの\n表示・非表示(一部透明度)を設定します。`,
5091
5102
  toSettings: `その他の拡張設定を設定します。`,
5092
5103
 
@@ -5197,6 +5208,7 @@ const g_lang_msgObj = {
5197
5208
 
5198
5209
  graph: `Displays detailed information about the chart, such as chart's density status, sequences' velocity changes, and chart's difficulty.`,
5199
5210
  dataSave: `Set whether to save the high score, reverse setting, and key config.`,
5211
+ toOption: `Set basic settings such as chart, speed, and gauge.`,
5200
5212
  toDisplay: `Set the display or non-display (partial transparency) of objects on the play screen.`,
5201
5213
  toSettings: `Set other extended settings.`,
5202
5214
 
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2026/09/13
8
- * Revised : 2026/10/07 (v51.2.2)
8
+ * Revised : 2026/10/10 (v51.3.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -2580,10 +2580,22 @@ const getArrowSettings = (_retryFlg = false) => {
2580
2580
  storageObj[`keyCtrl${addKey}`] = setKeyCtrl(g_localKeyStorage, keyNum, keyCtrlPtn);
2581
2581
  if (g_keyObj.currentPtn !== -1) {
2582
2582
  storageObj[`keyCtrlPtn${addKey}`] = g_keyObj.currentPtn;
2583
+ g_keyObj.storagePtn = g_keyObj.currentPtn;
2583
2584
  g_keyCtrlBackup[keyCtrlPtn] = structuredClone(g_keyObj[`keyCtrl${keyCtrlPtn}`]);
2584
2585
  g_keyObj[`keyCtrl${keyCtrlPtn}`] = structuredClone(g_keyObj[`keyCtrl${keyCtrlPtn}d`]);
2585
2586
  }
2586
2587
 
2588
+ // ショートカットキーの保存(基盤パターンのデフォルトと異なるものだけ)
2589
+ const savedShortcut = {};
2590
+ const isDefaultShortcut = _type => g_headerObj[`key${_type}`] === getDefaultShortcut(_type);
2591
+ g_keycons.shortcutTypes.filter(type => !isDefaultShortcut(type))
2592
+ .forEach(type => savedShortcut[type] = g_headerObj[`key${type}`]);
2593
+ if (Object.keys(savedShortcut).length > 0) {
2594
+ storageObj[`shortcut${addKey}`] = savedShortcut;
2595
+ } else {
2596
+ delete storageObj[`shortcut${addKey}`];
2597
+ }
2598
+
2587
2599
  // カラーセットの保存(キー別)
2588
2600
  if (!g_keycons.colorDefTypes.includes(g_colorType)) {
2589
2601
 
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2026/09/13
8
- * Revised : 2026/09/27 (v51.1.0)
8
+ * Revised : 2026/10/12 (v51.4.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -1182,13 +1182,10 @@ const headerConvert = _dosObj => {
1182
1182
 
1183
1183
  // プレイ中のショートカットキー
1184
1184
  obj.keyRetry = setIntVal(getKeyCtrlVal(_dosObj.keyRetry), C_KEY_RETRY);
1185
- obj.keyRetryDef = obj.keyRetry;
1186
1185
  obj.keyRetryDef2 = obj.keyRetry;
1187
1186
  obj.keyTitleBack = setIntVal(getKeyCtrlVal(_dosObj.keyTitleBack), C_KEY_TITLEBACK);
1188
- obj.keyTitleBackDef = obj.keyTitleBack;
1189
1187
  obj.keyTitleBackDef2 = obj.keyTitleBack;
1190
1188
  obj.keyPause = setIntVal(getKeyCtrlVal(_dosObj.keyPause), C_KEY_PAUSE);
1191
- obj.keyPauseDef = obj.keyPause;
1192
1189
  obj.keyPauseDef2 = obj.keyPause;
1193
1190
 
1194
1191
  // フリーズアローの許容フレーム数設定
@@ -1668,6 +1665,14 @@ const headerConvert = _dosObj => {
1668
1665
  g_canDisabledSettings.forEach(option =>
1669
1666
  obj[`${option}Use`] = setBoolVal(_dosObj[`${option}Use`] ?? g_presetObj.settingUse?.[option], true));
1670
1667
 
1668
+ // 拡張機能の無効設定
1669
+ if (!setBoolVal(_dosObj.displayWindowUse, true)) {
1670
+ g_settings.settingWindows = g_settings.settingWindows.filter(option => option !== settingsDisplayInit);
1671
+ }
1672
+ if (!setBoolVal(_dosObj.exSettingWindowUse, true)) {
1673
+ g_settings.settingWindows = g_settings.settingWindows.filter(option => option !== exSettingInit);
1674
+ }
1675
+
1671
1676
  let interlockingErrorFlg = false;
1672
1677
  g_displays.forEach((option, j) => {
1673
1678
 
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2026/09/13
8
- * Revised : 2026/09/23 (v51.0.0)
8
+ * Revised : 2026/10/12 (v51.4.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -33,6 +33,7 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
33
33
  if (_initFlg) {
34
34
  g_stateObj.keyLockFlg = false;
35
35
  g_stateObj.kbPreviewFlg = false;
36
+ g_stateObj.kbLaneFlg = false;
36
37
  }
37
38
 
38
39
  multiAppend(divRoot,
@@ -400,6 +401,9 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
400
401
  viewGroup(_type);
401
402
  if (_type === `stepRtn`) {
402
403
  keyConfigInit(g_kcType);
404
+ } else if (_type === `color`) {
405
+ // カラーグループ変更時はレーン色分けプレビューへ反映
406
+ keyconfigKeyboardPreview.refresh();
403
407
  }
404
408
  };
405
409
 
@@ -480,6 +484,21 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
480
484
  viewGroup(_type);
481
485
  };
482
486
 
487
+ /**
488
+ * ショートカットキーボタンの表示更新
489
+ * @param {string} _type Retry / TitleBack / Pause
490
+ */
491
+ const updateScButton = _type => {
492
+ const siz = wUnit(getFontSize2(getScMsg[_type](), g_btnWidth(1 / 4) - 40, { maxSiz: g_limitObj.mainSiz }));
493
+ document.getElementById(`sc${_type}`).textContent = getScMsg[_type]();
494
+ document.getElementById(`sc${_type}`).style.fontSize = siz;
495
+ if (g_isMac) {
496
+ scTitleBack.textContent = getScMsg.TitleBack();
497
+ scTitleBack.style.fontSize = wUnit(getFontSize2(getScMsg.TitleBack(), g_btnWidth(1 / 4) - 40, { maxSiz: g_limitObj.mainSiz }));
498
+ }
499
+ changeConfigColor(document.getElementById(`sc${_type}`), getScButtonColor(_type));
500
+ };
501
+
483
502
  const kcSubX = parseFloat(keyconSprite.style.width) * ((1 - g_keyObj.scale) / 4);
484
503
  const kcSubY = parseFloat(keyconSprite.style.height) / ((1 + g_keyObj.scale) / 2) - parseFloat(keyconSprite.style.height);
485
504
  multiAppend(divRoot,
@@ -494,27 +513,21 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
494
513
  cursor.style.top = wUnit(g_sHeight - 160 + kcSubY);
495
514
  selectedKc = `TitleBack`;
496
515
  }
497
- }, g_lblPosObj.scTitleBack, g_cssObj.button_Default_NoColor,
498
- g_headerObj.keyTitleBack === g_headerObj.keyTitleBackDef2 ?
499
- g_cssObj.title_base : g_cssObj.keyconfig_Changekey),
516
+ }, g_lblPosObj.scTitleBack, g_cssObj.button_Default_NoColor, getScButtonColor(`TitleBack`)),
500
517
 
501
518
  // リトライのショートカットキー変更
502
519
  createCss2Button(`scRetry`, getScMsg.Retry(), () => {
503
520
  cursor.style.left = wUnit(g_btnX(1 / 2) + kcSubX);
504
521
  cursor.style.top = wUnit(g_sHeight - 160 + kcSubY);
505
522
  selectedKc = `Retry`;
506
- }, g_lblPosObj.scRetry, g_cssObj.button_Default_NoColor,
507
- g_headerObj.keyRetry === g_headerObj.keyRetryDef2 ?
508
- g_cssObj.title_base : g_cssObj.keyconfig_Changekey),
523
+ }, g_lblPosObj.scRetry, g_cssObj.button_Default_NoColor, getScButtonColor(`Retry`)),
509
524
 
510
525
  // ポーズのショートカットキー変更
511
526
  createCss2Button(`scPause`, getScMsg.Pause(), () => {
512
527
  cursor.style.left = wUnit(g_btnX(3 / 4) + kcSubX);
513
528
  cursor.style.top = wUnit(g_sHeight - 160 + kcSubY);
514
529
  selectedKc = `Pause`;
515
- }, g_lblPosObj.scPause, g_cssObj.button_Default_NoColor,
516
- g_headerObj.keyPause === g_headerObj.keyPauseDef2 ?
517
- g_cssObj.title_base : g_cssObj.keyconfig_Changekey),
530
+ }, g_lblPosObj.scPause, g_cssObj.button_Default_NoColor, getScButtonColor(`Pause`)),
518
531
 
519
532
  // 別キーモード警告メッセージ
520
533
  createDivCss2Label(
@@ -571,6 +584,11 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
571
584
 
572
585
  // 次の位置が見えなくなったらkeyconSpriteの位置を調整する
573
586
  adjustScrollPoint(nextLeft);
587
+
588
+ // レーン色分けプレビュー中はカーソルレーンの強調を更新
589
+ if (g_stateObj.kbLaneFlg) {
590
+ keyconfigKeyboardPreview.refresh();
591
+ }
574
592
  };
575
593
 
576
594
  /**
@@ -973,6 +991,10 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
973
991
  changeKeyConfigColor(j, k, g_keyObj.currentPtn === -1 ? g_cssObj.keyconfig_Defaultkey : g_cssObj.title_base);
974
992
  }
975
993
  }
994
+ g_keycons.shortcutTypes.forEach(type => {
995
+ g_headerObj[`key${type}`] = getDefaultShortcut(type);
996
+ updateScButton(type);
997
+ });
976
998
  changeConfigCursor(0);
977
999
  }
978
1000
  }, g_lblPosObj.btnKcReset, g_cssObj.button_Reset),
@@ -1035,17 +1057,7 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
1035
1057
  }
1036
1058
  // プレイ中ショートカットキー変更
1037
1059
  g_headerObj[`key${selectedKc}`] = setKey;
1038
- g_headerObj[`key${selectedKc}Def`] = setKey;
1039
- document.getElementById(`sc${selectedKc}`).textContent = getScMsg[selectedKc]();
1040
- document.getElementById(`sc${selectedKc}`).style.fontSize =
1041
- wUnit(getFontSize2(getScMsg[selectedKc](), g_btnWidth(1 / 4) - 40, { maxSiz: g_limitObj.mainSiz }));
1042
- if (g_isMac) {
1043
- scTitleBack.textContent = getScMsg.TitleBack();
1044
- scTitleBack.style.fontSize = wUnit(getFontSize2(getScMsg.TitleBack(), g_btnWidth(1 / 4) - 40, { maxSiz: g_limitObj.mainSiz }));
1045
- }
1046
- changeConfigColor(document.getElementById(`sc${selectedKc}`),
1047
- g_headerObj[`key${selectedKc}`] === g_headerObj[`key${selectedKc}Def2`] ?
1048
- g_cssObj.title_base : g_cssObj.keyconfig_Changekey);
1060
+ updateScButton(selectedKc);
1049
1061
  return;
1050
1062
  }
1051
1063
 
@@ -1131,6 +1143,61 @@ const completeTransKeyPtn = (_keyList) => {
1131
1143
  });
1132
1144
  };
1133
1145
 
1146
+ /**
1147
+ * 別キーモード時、移行先キーが保持するSelf保存パターンの取得可否チェック
1148
+ * @param {string} _keyCtrlPtn 例: "7_2"
1149
+ * @returns {number[][]|undefined} 適用可能な場合はSelf保存済みkeyCtrl配列、不可ならundefined
1150
+ */
1151
+ const getTransKeySelfCtrl = (_keyCtrlPtn) => {
1152
+ const transKeyName = g_keyObj[`transKey${_keyCtrlPtn}`];
1153
+ const transKeyPtn = g_keyObj[`transKeyPtn${_keyCtrlPtn}`];
1154
+ if (!hasVal(transKeyName) || transKeyPtn === undefined) {
1155
+ return undefined;
1156
+ }
1157
+ const [storageObj, addKey] = getKeyStorageObjByName(transKeyName);
1158
+ const savedCtrl = storageObj[`keyCtrl${addKey}`];
1159
+ const savedPtn = storageObj[`keyCtrlPtn${addKey}`];
1160
+
1161
+ if (savedPtn !== transKeyPtn) {
1162
+ return undefined;
1163
+ }
1164
+
1165
+ // 現在のキー配置(基準形状)とレーン数・各レーン長が完全一致することを確認
1166
+ const baseCtrl = g_keyObj[`keyCtrl${_keyCtrlPtn}`];
1167
+ const isValidShape = hasArrayList(savedCtrl, baseCtrl.length) &&
1168
+ savedCtrl.length === baseCtrl.length &&
1169
+ baseCtrl.every((lane, j) => hasArrayList(savedCtrl[j], lane.length) && savedCtrl[j].length === lane.length);
1170
+
1171
+ return isValidShape ? savedCtrl : undefined;
1172
+ };
1173
+
1174
+ /**
1175
+ * 別キーモードの移行先Selfパターンを現在のキー配置へ反映(保存はしない)
1176
+ */
1177
+ const applyTransKeySelfPattern = () => {
1178
+ const keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`;
1179
+ const savedCtrl = getTransKeySelfCtrl(keyCtrlPtn);
1180
+ if (savedCtrl === undefined) {
1181
+ return;
1182
+ }
1183
+ const baseKeyNum = g_keyObj[`${g_keyObj.defaultProp}${keyCtrlPtn}`].length;
1184
+ for (let j = 0; j < baseKeyNum; j++) {
1185
+ for (let k = 0; k < (savedCtrl[j]?.length ?? 0); k++) {
1186
+ g_keyObj[`keyCtrl${keyCtrlPtn}`][j][k] = setIntVal(savedCtrl[j][k], 0);
1187
+ }
1188
+ }
1189
+ // ショートカットも取込元の保存内容で上書き(レーンキーと重複するものは無視)
1190
+ const [storageObj, addKey] = getKeyStorageObjByName(g_keyObj[`transKey${keyCtrlPtn}`]);
1191
+ const savedShortcut = storageObj[`shortcut${addKey}`] ?? {};
1192
+ const usedKeys = g_keyObj[`keyCtrl${keyCtrlPtn}`].flat();
1193
+ g_keycons.shortcutTypes.forEach(type => {
1194
+ const savedKey = savedShortcut[type];
1195
+ g_headerObj[`key${type}`] = (savedKey !== undefined && !usedKeys.includes(savedKey))
1196
+ ? savedKey : getDefaultShortcut(type);
1197
+ });
1198
+ keyConfigInit();
1199
+ };
1200
+
1134
1201
  // KeyLockボタンを押したときの表示切替
1135
1202
  const toggleKcDesc = () => {
1136
1203
  if (document.getElementById(`kcDesc`) !== null) {
@@ -1152,6 +1219,44 @@ const getKcDescMsg = () =>
1152
1219
  const getKeyLockName = () =>
1153
1220
  `${g_lblNameObj.b_keyLock}${g_stateObj.keyLockFlg ? g_emojiObj.locked : g_emojiObj.unlocked}`;
1154
1221
 
1222
+ /** 保存・Self時に基準とするキーパターン番号 */
1223
+ const getBasePtn = () => g_keyObj.currentPtn === -1 ? g_keyObj.storagePtn : g_keyObj.currentPtn;
1224
+
1225
+ /**
1226
+ * ショートカットキーのデフォルト値(基盤パターン基準)
1227
+ * 優先順: ヘッダー指定 > パターン別定義(keyRetryX_Y等) > 定数
1228
+ * @params {string} _type Retry / TitleBack / Pause
1229
+ * @returns {number}
1230
+ */
1231
+ const getDefaultShortcut = _type => {
1232
+ const baseVal = g_keycons.defaultShortCuts[_type];
1233
+ const headerVal = g_headerObj[`key${_type}Def2`];
1234
+ if (headerVal !== baseVal) {
1235
+ return headerVal;
1236
+ }
1237
+ return setIntVal(getKeyCtrlVal(g_keyObj[`key${_type}${g_keyObj.currentKey}_${getBasePtn()}`]), headerVal);
1238
+ };
1239
+
1240
+ /**
1241
+ * ショートカットキーボタンの色クラスを取得
1242
+ * - ロード済みの保存値(Self)と同じ: Defaultkey
1243
+ * - 基準値(保存値 or パターンのデフォルト)と違う: Changekey
1244
+ * - 通常パターンでデフォルトのまま: title_base
1245
+ * @param {string} _type Retry / TitleBack / Pause
1246
+ * @returns {string}
1247
+ */
1248
+ const getScButtonColor = _type => {
1249
+ const current = g_headerObj[`key${_type}`];
1250
+ const loaded = g_keyObj.currentPtn === -1
1251
+ ? g_keyObj[`shortcut${g_keyObj.currentKey}_-1`]?.[_type] : undefined;
1252
+
1253
+ // ロード済みの保存値のまま
1254
+ if (loaded !== undefined && current === loaded) {
1255
+ return g_cssObj.keyconfig_Defaultkey;
1256
+ }
1257
+ // 本当のデフォルト(BackSpace/Delete/Pause)と違う場合は、変更の経緯を問わずChangekey
1258
+ return current !== g_keycons.defaultShortCuts[_type] ? g_cssObj.keyconfig_Changekey : g_cssObj.title_base;
1259
+ };
1155
1260
  /**
1156
1261
  * キーボードレイアウトプレビュー(Canvas版)
1157
1262
  *
@@ -1215,11 +1320,22 @@ const keyconfigKeyboardPreview = (() => {
1215
1320
  },
1216
1321
  bgFill: `#0d0d1a`, // Canvas 背景
1217
1322
  legendText: `#cccccc`, // 凡例テキスト
1323
+
1324
+ // レーン色分けモード用(凡例と文字色。レーン色自体は g_dfColorObj.setColorType2 を使用)
1325
+ // 枠線は未割当キーと同色に統一し、メイン/代替は塗りのアルファのみで区別する
1326
+ laneMain: { fill: `#cccccc`, stroke: `#555577` },
1327
+ laneAlt: { fill: `rgba(204,204,204,0.35)`, stroke: `#555577` },
1328
+ laneAltBright: { fill: `rgba(204,204,204,0.6)`, stroke: `#555577` },
1329
+ laneStroke: `#555577`,
1330
+ laneText: `#111111`,
1218
1331
  };
1219
1332
 
1220
1333
  // 凡例エリアの高さ
1221
1334
  const LEGEND_H = 25;
1222
1335
 
1336
+ // レーン色分けモードで、同一キーに割り当てられた色を分割描画する上限数
1337
+ const C_LANE_SPLIT_MAX = 3;
1338
+
1223
1339
  // -------------------------------------------------------------------------
1224
1340
  // キーレイアウト定義
1225
1341
  //
@@ -1379,6 +1495,7 @@ const keyconfigKeyboardPreview = (() => {
1379
1495
  mappedSet: new Set(), // メインキー(code文字列)
1380
1496
  altSet: new Set(), // 代替キー(code文字列)
1381
1497
  shortcutSet: new Set(), // ショートカットキー(code文字列)
1498
+ laneMap: new Map(), // code文字列 → { entries: [{ colorPos, alt }], cursor: boolean }
1382
1499
  canvasBase: null,
1383
1500
  canvasMap: null,
1384
1501
  keyDataList: [], // { code, x, y, w, h, label } — drawMap で照合するキャッシュ
@@ -1524,13 +1641,16 @@ const keyconfigKeyboardPreview = (() => {
1524
1641
  * @param {Object} keyData - 位置・サイズ・キーコードを含むキー情報
1525
1642
  * @param {Object} style - fill, stroke, text 等の色セット
1526
1643
  * @param {number} lw - 枠線の太さ(lineWidth)
1644
+ * @param {boolean} shapeFlg - 枠線・背景を描画するかどうか(false の場合はテキストのみ描画)
1527
1645
  */
1528
- const drawOneKey = (ctx, { keyData, style, lw = 1 }) => {
1646
+ const drawOneKey = (ctx, { keyData, style, lw = 1, shapeFlg = true }) => {
1529
1647
  const { x, y, w: keyW, h: keyH, code, label } = keyData;
1530
1648
 
1531
1649
  // 1. キーの枠線・背景を描画
1532
- roundRect(ctx, x + 0.5, y + 0.5, keyW - 1, keyH - 1, kr());
1533
- fillStrokeShape(ctx, { fill: style.fill, stroke: style.stroke, lineWidth: lw });
1650
+ if (shapeFlg) {
1651
+ roundRect(ctx, x + 0.5, y + 0.5, keyW - 1, keyH - 1, kr());
1652
+ fillStrokeShape(ctx, { fill: style.fill, stroke: style.stroke, lineWidth: lw });
1653
+ }
1534
1654
 
1535
1655
  // 2. キー内部のテキスト(メイン・サブ)を描画
1536
1656
  const [primary, sub] = getKeyLabels(code, label);
@@ -1648,9 +1768,13 @@ const keyconfigKeyboardPreview = (() => {
1648
1768
 
1649
1769
  const legends = [
1650
1770
  { style: C_COLOR.normal, label: g_lblNameObj.unallocated },
1651
- { style: C_COLOR.mapped, label: g_lblNameObj.allocated },
1652
- { style: C_COLOR.alt, label: g_lblNameObj.altAllocated },
1653
- { style: C_COLOR.shortcut, label: g_lblNameObj.shortcutKey }
1771
+ { style: g_stateObj.kbLaneFlg ? C_COLOR.laneMain : C_COLOR.mapped, label: g_lblNameObj.allocated },
1772
+ {
1773
+ style: g_stateObj.kbLaneFlg
1774
+ ? (g_headerObj.baseBrightFlg ? C_COLOR.laneAltBright : C_COLOR.laneAlt) : C_COLOR.alt,
1775
+ label: g_lblNameObj.altAllocated,
1776
+ },
1777
+ { style: C_COLOR.shortcut, label: g_lblNameObj.shortcutKey },
1654
1778
  ];
1655
1779
 
1656
1780
  let lx = 8;
@@ -1665,6 +1789,111 @@ const keyconfigKeyboardPreview = (() => {
1665
1789
  });
1666
1790
  };
1667
1791
 
1792
+ /**
1793
+ * 明度が低い色を、未割当キーと区別できる下限まで持ち上げる
1794
+ * @param {string} _hex #rrggbb 形式の色
1795
+ * @param {number} _minLum 下限値(RGBの最大成分で判定)
1796
+ * @returns {string}
1797
+ */
1798
+ const liftDarkColor = (_hex, _minLum = 0x66) => {
1799
+ const n = parseInt(_hex.slice(1, 7), 16);
1800
+ const [r, g, b] = [(n >> 16) & 255, (n >> 8) & 255, n & 255];
1801
+ const lum = Math.max(r, g, b);
1802
+ if (lum >= _minLum) {
1803
+ return _hex;
1804
+ }
1805
+ const d = _minLum - lum;
1806
+ return `#${[r, g, b].map(v => (v + d).toString(16).padStart(2, `0`)).join(``)}`;
1807
+ };
1808
+
1809
+ /**
1810
+ * #rrggbb 形式の色にアルファ値を付与する
1811
+ * @param {string} _hex
1812
+ * @param {number} _alpha
1813
+ * @returns {string}
1814
+ */
1815
+ const hexToRgba = (_hex, _alpha) => {
1816
+ const n = parseInt(_hex.slice(1, 7), 16);
1817
+ return `rgba(${(n >> 16) & 255}, ${(n >> 8) & 255}, ${n & 255}, ${_alpha})`;
1818
+ };
1819
+
1820
+ /**
1821
+ * レーン色分けモードのスタイル取得(色は譜面ミニマップと同じ setColorType2 固定)
1822
+ * @param {number} _colorPos カラーグループ番号
1823
+ * @param {boolean} _altFlg 代替キーか
1824
+ */
1825
+ const getLaneStyle = (_colorPos, _altFlg) => {
1826
+ const brightFlg = g_headerObj.baseBrightFlg;
1827
+ const baseColor = g_dfColorObj.setColorType2[_colorPos] ?? `#ffffff`;
1828
+
1829
+ // 明背景のみ、黒に近い色を未割当キーと区別できる明るさまで持ち上げる
1830
+ const color = brightFlg ? liftDarkColor(baseColor) : baseColor;
1831
+ // 明背景では暗色セットが使われるため、文字は白にする
1832
+ const mainText = brightFlg ? `#ffffff` : C_COLOR.laneText;
1833
+ if (!_altFlg) {
1834
+ return { fill: color, text: mainText };
1835
+ }
1836
+ return brightFlg
1837
+ ? { fill: hexToRgba(color, 0.6), text: `#ffffff` }
1838
+ : { fill: hexToRgba(color, 0.35), text: color };
1839
+ };
1840
+
1841
+ /**
1842
+ * レーン色分けモードでの単一キー描画
1843
+ * - 複数色の場合は縦方向に等分割して塗り分ける
1844
+ * @param {CanvasRenderingContext2D} ctx
1845
+ * @param {Object} keyData
1846
+ * @param {{colorPos: number, alt: boolean}[]} entries
1847
+ * @param {boolean} cursorFlg カーソル中のレーンか
1848
+ */
1849
+ const drawLaneKey = (ctx, keyData, entries, cursorFlg) => {
1850
+ const { x, y, w: keyW, h: keyH } = keyData;
1851
+ const styles = entries.map(val => getLaneStyle(val.colorPos, val.alt));
1852
+ const segW = keyW / styles.length;
1853
+
1854
+ styles.forEach((style, i) => {
1855
+ ctx.save();
1856
+ ctx.beginPath();
1857
+ ctx.rect(x + segW * i, y, segW, keyH);
1858
+ ctx.clip();
1859
+ roundRect(ctx, x + 0.5, y + 0.5, keyW - 1, keyH - 1, kr());
1860
+ fillStrokeShape(ctx, { fill: style.fill });
1861
+ ctx.restore();
1862
+ });
1863
+
1864
+ // 枠線はキー全体に対して1回だけ、全キー共通の色で描画
1865
+ roundRect(ctx, x + 0.5, y + 0.5, keyW - 1, keyH - 1, kr());
1866
+ fillStrokeShape(ctx, { stroke: C_COLOR.laneStroke, lineWidth: 1.5 });
1867
+
1868
+ // 文字は全体に1回だけ描画(メインが含まれる場合はメインの文字色)
1869
+ const mainIdx = entries.findIndex(val => !val.alt);
1870
+ const textColor = styles[mainIdx >= 0 ? mainIdx : 0].text;
1871
+ drawOneKey(ctx, { keyData, style: { text: textColor }, shapeFlg: false });
1872
+
1873
+ // カーソル中のレーンは白枠で強調
1874
+ if (cursorFlg) {
1875
+ roundRect(ctx, x + 0.5, y + 0.5, keyW - 1, keyH - 1, kr());
1876
+ fillStrokeShape(ctx, { stroke: `#ffffff`, lineWidth: 2.5 });
1877
+ }
1878
+ };
1879
+
1880
+ /**
1881
+ * レーン色分けモードのマッピング描画(ショートカットキーは専用色で最優先)
1882
+ * @param {CanvasRenderingContext2D} ctx
1883
+ */
1884
+ const drawLaneMap = ctx => {
1885
+ _state.keyDataList.forEach(keyData => {
1886
+ if (_state.shortcutSet.has(keyData.code)) {
1887
+ drawOneKey(ctx, { keyData, style: C_COLOR.shortcut, lw: 1.5 });
1888
+ return;
1889
+ }
1890
+ const info = _state.laneMap.get(keyData.code);
1891
+ if (info !== undefined) {
1892
+ drawLaneKey(ctx, keyData, info.entries, info.cursor);
1893
+ }
1894
+ });
1895
+ };
1896
+
1668
1897
  /**
1669
1898
  * マッピング強調レイヤーを再描画する。
1670
1899
  * メインキー(mappedSet)を青系、代替キー(altSet)を黄系で色分けする。
@@ -1675,6 +1904,11 @@ const keyconfigKeyboardPreview = (() => {
1675
1904
 
1676
1905
  ctx.clearRect(0, 0, _state.cvsW, _state.cvsH);
1677
1906
 
1907
+ if (g_stateObj.kbLaneFlg) {
1908
+ drawLaneMap(ctx);
1909
+ return;
1910
+ }
1911
+
1678
1912
  // キー状態に応じた色取得ロジック(優先度: ショートカット > メイン > 代替)
1679
1913
  const getKeyStyle = (code) => {
1680
1914
  if (_state.shortcutSet.has(code)) return C_COLOR.shortcut;
@@ -1719,6 +1953,16 @@ const keyconfigKeyboardPreview = (() => {
1719
1953
  pointerEvents: C_DIS_AUTO, background: `#00000080`, display: C_DIS_NONE, overflow: `hidden`,
1720
1954
  });
1721
1955
 
1956
+ // レーン色分け表示の切替ボタン(プレビューエリア内の上部余白に配置)
1957
+ const getLaneBtnName = () => `${g_lblNameObj.b_kbLane ?? `Lane Color`}: ${boolToSwitch(!!g_stateObj.kbLaneFlg)}`;
1958
+ const btnLane = createCss2Button(`btnKbLane`, getLaneBtnName(), () => {
1959
+ g_stateObj.kbLaneFlg = !g_stateObj.kbLaneFlg;
1960
+ btnLane.textContent = getLaneBtnName();
1961
+ drawBase(); // 凡例の切替
1962
+ refresh();
1963
+ }, { x: _state.cvsW - 130, y: 10, w: 120, h: 22, siz: 12 }, g_cssObj.button_Mini);
1964
+ areaDiv.appendChild(btnLane);
1965
+
1722
1966
  /**
1723
1967
  * プレビュー用canvasを生成しareaDivに追加、_stateに登録する
1724
1968
  * @param {string} _id
@@ -1777,6 +2021,33 @@ const keyconfigKeyboardPreview = (() => {
1777
2021
  [g_headerObj.keyRetry, g_headerObj.keyTitleBack, g_headerObj.keyPause, 34, 33].map(toCodeStr).filter(v => v !== ``)
1778
2022
  );
1779
2023
 
2024
+ // レーン色分け用: キーコード → 割り当て先レーンのカラーグループ情報
2025
+ const colorList = g_keyObj[`color${tkObj.keyCtrlPtn}`];
2026
+ _state.laneMap = new Map();
2027
+ g_keyObj[`keyCtrl${tkObj.keyCtrlPtn}`].forEach((arr, j) => {
2028
+ if (!tkObj.keyGroupMaps[j].includes(configKeyGroupList[g_keycons.keySwitchNum])) {
2029
+ return;
2030
+ }
2031
+ arr.forEach((num, k) => {
2032
+ const code = toCodeStr(num);
2033
+ if (code === ``) {
2034
+ return;
2035
+ }
2036
+ const info = _state.laneMap.get(code) ?? { entries: [], cursor: false };
2037
+ const [colorPos, alt] = [colorList[j], k > 0];
2038
+ if (!info.entries.some(val => val.colorPos === colorPos && val.alt === alt)) {
2039
+ info.entries.push({ colorPos, alt });
2040
+ }
2041
+ info.cursor ||= (j === g_currentj);
2042
+ _state.laneMap.set(code, info);
2043
+ });
2044
+ });
2045
+ // メイン優先で並べ、分割数は上限まで
2046
+ _state.laneMap.forEach(info => {
2047
+ info.entries.sort((a, b) => Number(a.alt) - Number(b.alt));
2048
+ info.entries = info.entries.slice(0, C_LANE_SPLIT_MAX);
2049
+ });
2050
+
1780
2051
  if (_state.visible) drawMap();
1781
2052
  };
1782
2053
 
@@ -1789,6 +2060,7 @@ const keyconfigKeyboardPreview = (() => {
1789
2060
  _state.mappedSet = new Set();
1790
2061
  _state.altSet = new Set();
1791
2062
  _state.shortcutSet = new Set();
2063
+ _state.laneMap = new Map();
1792
2064
  _state.keyDataList = [];
1793
2065
  _state.canvasBase = null;
1794
2066
  _state.canvasMap = null;
@@ -1826,19 +2098,18 @@ const getShadowColor = (_colorPos, _arrowColor) => g_headerObj.setShadowColor[_c
1826
2098
 
1827
2099
  /**
1828
2100
  * デフォルトの曲中ショートカットをキー数・キーパターンにより切り替え
1829
- * - キーコンフィグ画面で個別に変えていた場合は変更しない
2101
+ * - Self(-1)のときは保存済みの値を優先(レーンキーと重複する場合は無視)
2102
+ * - それ以外はパターンのデフォルトへ戻す
1830
2103
  */
1831
2104
  const setPlayingShortcut = () => {
1832
2105
  const keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`;
1833
- if (g_headerObj.keyRetryDef === C_KEY_RETRY) {
1834
- g_headerObj.keyRetry = setIntVal(getKeyCtrlVal(g_keyObj[`keyRetry${keyCtrlPtn}`]), g_headerObj.keyRetryDef);
1835
- }
1836
- if (g_headerObj.keyTitleBackDef === C_KEY_TITLEBACK) {
1837
- g_headerObj.keyTitleBack = setIntVal(getKeyCtrlVal(g_keyObj[`keyTitleBack${keyCtrlPtn}`]), g_headerObj.keyTitleBackDef);
1838
- }
1839
- if (g_headerObj.keyPauseDef === C_KEY_PAUSE) {
1840
- g_headerObj.keyPause = setIntVal(getKeyCtrlVal(g_keyObj[`keyPause${keyCtrlPtn}`]), g_headerObj.keyPauseDef);
1841
- }
2106
+ const saved = g_keyObj.currentPtn === -1 ? g_keyObj[`shortcut${g_keyObj.currentKey}_-1`] : undefined;
2107
+ const usedKeys = (g_keyObj[`keyCtrl${keyCtrlPtn}`] ?? []).flat();
2108
+ g_keycons.shortcutTypes.forEach(type => {
2109
+ const savedKey = saved?.[type];
2110
+ g_headerObj[`key${type}`] = (savedKey !== undefined && !usedKeys.includes(savedKey))
2111
+ ? savedKey : getDefaultShortcut(type);
2112
+ });
1842
2113
  };
1843
2114
 
1844
2115
  /**
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2026/09/13
8
- * Revised : 2026/09/29 (v51.1.1)
8
+ * Revised : 2026/10/12 (v51.4.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -14,7 +14,7 @@
14
14
  /* Scene : SETTINGS [lime] */
15
15
  /*-----------------------------------------------------------*/
16
16
 
17
- const commonSettingBtn = _labelName => {
17
+ const commonSettingBtn = () => {
18
18
 
19
19
  const switchSave = evt => {
20
20
  const from = boolToSwitch(g_stateObj.dataSaveFlg);
@@ -24,6 +24,8 @@ const commonSettingBtn = _labelName => {
24
24
  const to = boolToSwitch(g_stateObj.dataSaveFlg);
25
25
  evt.target.classList.replace(g_cssObj[`button_${from}`], g_cssObj[`button_${to}`]);
26
26
  };
27
+ const nextPageNum = nextPos(g_settings.settingWindowNum, 1, g_settings.settingWindows.length);
28
+ const labelName = g_settingWindowTitleKeys.get(g_settings.settingWindows[nextPageNum]);
27
29
 
28
30
  multiAppend(divRoot,
29
31
 
@@ -42,18 +44,19 @@ const commonSettingBtn = _labelName => {
42
44
  // プレイ開始
43
45
  makePlayButton(() => loadMusic()),
44
46
 
45
- // Display設定へ移動
46
- createCss2Button(`btn${_labelName}`, `>`, () => true, {
47
+ // 次の設定へ移動
48
+ createCss2Button(`btnNextSetting`, `>`, () => true, {
47
49
  ...g_lblPosObj.btnSwitchSetting,
48
- title: g_msgObj[`to${_labelName}`], resetFunc: () => g_moveSettingWindow(),
50
+ title: g_msgObj[`to${labelName}`], resetFunc: () => g_moveSettingWindow(),
49
51
  cxtFunc: () => g_moveSettingWindow(true, -1),
52
+ display: g_settings.settingWindows.length > 1 ? C_DIS_INHERIT : C_DIS_NONE,
50
53
  }, g_cssObj.button_Mini),
51
54
 
52
55
  // データセーブフラグの切替
53
56
  createCss2Button(`btnSave`, g_lblNameObj.dataSave, evt => switchSave(evt), {
54
57
  ...g_lblPosObj.btnSave,
55
58
  cxtFunc: evt => switchSave(evt),
56
- visibility: g_langStorage.safeMode === C_FLG_OFF ? C_DIS_INHERIT : `hidden`,
59
+ display: g_langStorage.safeMode === C_FLG_OFF ? C_DIS_INHERIT : C_DIS_NONE,
57
60
  }, g_cssObj.button_Default, (g_stateObj.dataSaveFlg ? g_cssObj.button_ON : g_cssObj.button_OFF)),
58
61
 
59
62
  // データ管理画面へ移動
@@ -170,7 +173,7 @@ const optionInit = () => {
170
173
  safeExecuteCustomHooks(`g_customJsObj.option`, g_customJsObj.option);
171
174
 
172
175
  // ボタン描画
173
- commonSettingBtn(`Display`);
176
+ commonSettingBtn();
174
177
 
175
178
  // キー操作イベント(デフォルト)
176
179
  setShortcutEvent(g_currentPage, () => true, { dfEvtFlg: true });
@@ -1274,52 +1277,6 @@ const getKeyStorageObjByName = (_keyName) => {
1274
1277
  }), ``];
1275
1278
  };
1276
1279
 
1277
- /**
1278
- * 別キーモード時、移行先キーが保持するSelf保存パターンの取得可否チェック
1279
- * @param {string} _keyCtrlPtn 例: "7_2"
1280
- * @returns {number[][]|undefined} 適用可能な場合はSelf保存済みkeyCtrl配列、不可ならundefined
1281
- */
1282
- const getTransKeySelfCtrl = (_keyCtrlPtn) => {
1283
- const transKeyName = g_keyObj[`transKey${_keyCtrlPtn}`];
1284
- const transKeyPtn = g_keyObj[`transKeyPtn${_keyCtrlPtn}`];
1285
- if (!hasVal(transKeyName) || transKeyPtn === undefined) {
1286
- return undefined;
1287
- }
1288
- const [storageObj, addKey] = getKeyStorageObjByName(transKeyName);
1289
- const savedCtrl = storageObj[`keyCtrl${addKey}`];
1290
- const savedPtn = storageObj[`keyCtrlPtn${addKey}`];
1291
-
1292
- if (savedPtn !== transKeyPtn) {
1293
- return undefined;
1294
- }
1295
-
1296
- // 現在のキー配置(基準形状)とレーン数・各レーン長が完全一致することを確認
1297
- const baseCtrl = g_keyObj[`keyCtrl${_keyCtrlPtn}`];
1298
- const isValidShape = hasArrayList(savedCtrl, baseCtrl.length) &&
1299
- savedCtrl.length === baseCtrl.length &&
1300
- baseCtrl.every((lane, j) => hasArrayList(savedCtrl[j], lane.length) && savedCtrl[j].length === lane.length);
1301
-
1302
- return isValidShape ? savedCtrl : undefined;
1303
- };
1304
-
1305
- /**
1306
- * 別キーモードの移行先Selfパターンを現在のキー配置へ反映(保存はしない)
1307
- */
1308
- const applyTransKeySelfPattern = () => {
1309
- const keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`;
1310
- const savedCtrl = getTransKeySelfCtrl(keyCtrlPtn);
1311
- if (savedCtrl === undefined) {
1312
- return;
1313
- }
1314
- const baseKeyNum = g_keyObj[`${g_keyObj.defaultProp}${keyCtrlPtn}`].length;
1315
- for (let j = 0; j < baseKeyNum; j++) {
1316
- for (let k = 0; k < (savedCtrl[j]?.length ?? 0); k++) {
1317
- g_keyObj[`keyCtrl${keyCtrlPtn}`][j][k] = setIntVal(savedCtrl[j][k], 0);
1318
- }
1319
- }
1320
- keyConfigInit();
1321
- };
1322
-
1323
1280
  /**
1324
1281
  * 譜面初期化処理
1325
1282
  * - 譜面の基本設定(キー数、初期速度、リバース、ゲージ設定)をここで行う
@@ -1371,6 +1328,7 @@ const setDifficulty = (_chartChangeFlg) => {
1371
1328
  storageObj[`keyCtrlPtn${addKey}`] = 0;
1372
1329
  }
1373
1330
  getKeyCtrl(storageObj, addKey);
1331
+ g_keyObj[`shortcut${g_keyObj.currentKey}_-1`] = structuredClone(storageObj[`shortcut${addKey}`] ?? {});
1374
1332
 
1375
1333
  // カラーセット初期値設定
1376
1334
  if (storageObj[`setColor${addKey}`] === undefined) {
@@ -1401,10 +1359,9 @@ const setDifficulty = (_chartChangeFlg) => {
1401
1359
  g_keyObj[`${type}${keyCtrlPtn}`] = structuredClone(g_keyObj[`${type}${keyCtrlPtn}_0`]);
1402
1360
  }
1403
1361
  });
1404
-
1362
+ // 曲中ショートカットキーの切り替え
1363
+ setPlayingShortcut();
1405
1364
  }
1406
- // 曲中ショートカットキーの切り替え
1407
- setPlayingShortcut();
1408
1365
  }
1409
1366
 
1410
1367
  // スクロール設定用の配列を入れ替え
@@ -2449,7 +2406,7 @@ const settingsDisplayInit = () => {
2449
2406
  safeExecuteCustomHooks(`g_customJsObj.settingsDisplay`, g_customJsObj.settingsDisplay);
2450
2407
 
2451
2408
  // ボタン描画
2452
- commonSettingBtn(`Settings`);
2409
+ commonSettingBtn();
2453
2410
 
2454
2411
  // キー操作イベント(デフォルト)
2455
2412
  setShortcutEvent(g_currentPage);
@@ -3288,7 +3245,7 @@ const exSettingInit = () => {
3288
3245
  safeExecuteCustomHooks(`g_customJsObj.exSetting`, g_customJsObj.exSetting);
3289
3246
 
3290
3247
  // 設定系のボタン群をまとめて作成(Data Save, Display切替, Back, KeyConfig, Playボタン)
3291
- commonSettingBtn(g_currentPage);
3248
+ commonSettingBtn();
3292
3249
 
3293
3250
  // キー操作イベント(デフォルト)
3294
3251
  setShortcutEvent(g_currentPage, () => true, { dfEvtFlg: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "danoniplus",
3
- "version": "51.2.2",
3
+ "version": "51.4.0",
4
4
  "description": "Dancing☆Onigiri (CW Edition) - Web-based Rhythm Game",
5
5
  "main": "./js/danoni_main.js",
6
6
  "jsdelivr": "./js/danoni_main.js",