danoniplus 48.4.1 → 48.4.2

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.
Files changed (2) hide show
  1. package/js/danoni_main.js +199 -193
  2. package/package.json +1 -1
package/js/danoni_main.js CHANGED
@@ -8,8 +8,8 @@
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 48.4.1`;
12
- const g_revisedDate = `2026/06/05`;
11
+ const g_version = `Ver 48.4.2`;
12
+ const g_revisedDate = `2026/06/06`;
13
13
 
14
14
  // カスタム用バージョン (danoni_custom.js 等で指定可)
15
15
  let g_localVersion = ``;
@@ -9070,14 +9070,15 @@ const resetGroupList = (_type, _keyCtrlPtn) => {
9070
9070
  let k = 1;
9071
9071
  g_keycons[`${_type}Groups`] = [0];
9072
9072
 
9073
- if (g_keyObj.currentPtn === -1) {
9074
- g_keycons[`${_type}Groups`] = addValtoArray(g_keycons[`${_type}Groups`], -1);
9075
- }
9076
- g_keycons[`${_type}GroupNum`] = Math.min(g_keyObj.currentPtn, 0);
9077
9073
  while (g_keyObj[`${_type}${_keyCtrlPtn}_${k}`] !== undefined) {
9078
9074
  g_keycons[`${_type}Groups`].push(k);
9079
9075
  k++;
9080
9076
  }
9077
+ if (g_keyObj.currentPtn === -1
9078
+ && (_type !== `stepRtn` || (_type === `stepRtn` && g_keycons[`${_type}Groups`].length > 1))) {
9079
+ g_keycons[`${_type}Groups`] = addValtoArray(g_keycons[`${_type}Groups`], -1);
9080
+ }
9081
+ g_keycons[`${_type}GroupNum`] = Math.min(g_keyObj.currentPtn, 0);
9081
9082
  };
9082
9083
 
9083
9084
  /*-----------------------------------------------------------*/
@@ -11042,27 +11043,31 @@ const keyconfigKeyboardPreview = (() => {
11042
11043
 
11043
11044
  // 色定義(既存ゲームの配色に合わせたダーク系)
11044
11045
  const C_COLOR = {
11045
- keyFill: `#1a1a2e`, // 通常キー背景
11046
- keyStroke: `#555577`, // 通常キー枠
11047
- keyText: `#ccccdd`, // 通常キー文字
11048
- keySubText: `#888899`, // サブラベル(Shift面)
11049
- mappedFill: `#003366`, // メインキー背景
11050
- mappedStroke: `#4488ff`, // メインキー枠
11051
- mappedText: `#aaddff`, // メインキー文字
11052
- altFill: `#3e3e1a`, // 代替キー背景
11053
- altStroke: `#777755`, // 代替キー枠
11054
- altText: `#eeeecc`, // 代替キー文字
11055
- shortcutFill: `#330011`, // ショートカットキー背景
11056
- shortcutStroke: `#ff4466`, // ショートカットキー枠
11057
- shortcutText: `#ffaacc`, // ショートカットキー文字
11058
- bgFill: `#0d0d1a`, // Canvas 背景
11059
- legendText: `#cccccc`, // 凡例テキスト
11046
+ normal: {
11047
+ fill: `#1a1a2e`, // 通常キー背景
11048
+ stroke: `#555577`, // 通常キー枠
11049
+ text: `#ccccdd`, // 通常キー文字
11050
+ subText: `#888899`, // サブラベル(Shift面)
11051
+ },
11052
+ mapped: {
11053
+ fill: `#003366`, // メインキー背景
11054
+ stroke: `#4488ff`, // メインキー枠
11055
+ text: `#aaddff`, // メインキー文字
11056
+ },
11057
+ alt: {
11058
+ fill: `#3e3e1a`, // 代替キー背景
11059
+ stroke: `#777755`, // 代替キー枠
11060
+ text: `#eeeecc`, // 代替キー文字
11061
+ },
11062
+ shortcut: {
11063
+ fill: `#330011`, // ショートカットキー背景
11064
+ stroke: `#ff4466`, // ショートカットキー枠
11065
+ text: `#ffaacc`, // ショートカットキー文字
11066
+ },
11067
+ bgFill: `#0d0d1a`, // Canvas 背景
11068
+ legendText: `#cccccc`, // 凡例テキスト
11060
11069
  };
11061
11070
 
11062
- // プレビューエリア
11063
- // X: canvas を divRoot 内で水平センタリング(init で動的計算)
11064
- // Y: g_sHeight に対して垂直センタリング(init で動的計算)
11065
-
11066
11071
  // 凡例エリアの高さ
11067
11072
  const LEGEND_H = 25;
11068
11073
 
@@ -11073,15 +11078,12 @@ const keyconfigKeyboardPreview = (() => {
11073
11078
  // offsetX : 行左端の水平オフセット(単位: BASE_KEY_W)。未指定時は0
11074
11079
  // keys : キー定義の配列
11075
11080
  //
11076
- // 各キー: { kc, w?, h?, label? }
11077
- // kc : keyCode(数値)。-1 はスペーサー(描画・キャッシュなし)。
11078
- // w : 幅倍率(BASE_KEY_W 基準。省略時 1)
11079
- // h : 高さ倍率(BASE_KEY_H 基準。省略時 1)
11080
- // label : 省略時は g_kCd[kc] を参照。g_kCd が空文字のキーや
11081
- // 左右を区別したいキーに指定する。
11082
- //
11083
- // 右Shift/Ctrl/Alt は danoniplus 独自コード 256〜258 を使用。
11084
- // Appli キーは 93 を使用(g_kCd[93] = `Appli`)。
11081
+ // 各キー: { code, w?, h?, label? }
11082
+ // code : KeyboardEvent.code(文字列)。空文字 "" はスペーサー(描画・キャッシュなし)。
11083
+ // w : 幅倍率(BASE_KEY_W 基準。省略時 1)
11084
+ // h : 高さ倍率(BASE_KEY_H 基準。省略時 1)
11085
+ // label : 省略時は g_kCd[keyCode] を参照。g_kCd が空文字のキーや
11086
+ // 左右を区別したいキーに指定する。
11085
11087
  // -------------------------------------------------------------------------
11086
11088
  /**
11087
11089
  * g_localeObj.val に応じた MAIN_ROWS を生成して返す。
@@ -11095,106 +11097,106 @@ const keyconfigKeyboardPreview = (() => {
11095
11097
  // Row0: Fn キー行(JIS/US 共通)
11096
11098
  {
11097
11099
  keys: [
11098
- { kc: 27 }, // Esc
11099
- { kc: -1, w: 0.5 }, // スペーサー
11100
- { kc: 112 }, { kc: 113 }, { kc: 114 }, { kc: 115 },
11101
- { kc: -1, w: 0.25 }, // スペーサー
11102
- { kc: 116 }, { kc: 117 }, { kc: 118 }, { kc: 119 },
11103
- { kc: -1, w: 0.25 }, // スペーサー
11104
- { kc: 120 }, { kc: 121 }, { kc: 122 }, { kc: 123 },
11100
+ { code: `Escape` },
11101
+ { code: ``, w: 0.5 }, // スペーサー
11102
+ { code: `F1` }, { code: `F2` }, { code: `F3` }, { code: `F4` },
11103
+ { code: ``, w: 0.25 }, // スペーサー
11104
+ { code: `F5` }, { code: `F6` }, { code: `F7` }, { code: `F8` },
11105
+ { code: ``, w: 0.25 }, // スペーサー
11106
+ { code: `F9` }, { code: `F10` }, { code: `F11` }, { code: `F12` },
11105
11107
  ],
11106
11108
  },
11107
11109
  // Row1: 数字行
11108
- // JIS: ..., 220(intlYen), BS
11109
- // US : ..., BS
11110
+ // JIS: ..., Minus, Equal, IntlYen, BS
11111
+ // US : ..., Minus, Equal, BS
11110
11112
  {
11111
11113
  keys: [
11112
- { kc: 229 },
11113
- { kc: 49 }, { kc: 50 }, { kc: 51 }, { kc: 52 }, { kc: 53 }, { kc: 54 },
11114
- { kc: 55 }, { kc: 56 }, { kc: 57 }, { kc: 48 }, { kc: 189 }, { kc: 222 },
11114
+ { code: `Backquote` },
11115
+ { code: `Digit1` }, { code: `Digit2` }, { code: `Digit3` }, { code: `Digit4` }, { code: `Digit5` }, { code: `Digit6` },
11116
+ { code: `Digit7` }, { code: `Digit8` }, { code: `Digit9` }, { code: `Digit0` }, { code: `Minus` }, { code: `Equal` },
11115
11117
  ...(isJa
11116
- ? [{ kc: 220, w: 0.75 }, { kc: 8, label: `Back\nSpace` }] // JIS: intlYen + BS
11117
- : [{ kc: 8, w: 1.7 }] // US : BS のみ(広い)
11118
+ ? [{ code: `IntlYen`, w: 0.75 }, { code: `Backspace`, label: `Back\nSpace` }] // JIS: IntlYen + BS
11119
+ : [{ code: `Backspace`, w: 1.7 }] // US : BS のみ(広い)
11118
11120
  ),
11119
11121
  ],
11120
11122
  },
11121
11123
  // Row2: QWERTY
11122
- // JIS: ..., [, Enter(13)
11123
- // US : ..., [, ]
11124
+ // JIS: ..., BracketLeft, BracketRight, Enter(縦長)
11125
+ // US : ..., BracketLeft, BracketRight, Backslash
11124
11126
  {
11125
11127
  keys: [
11126
- { kc: 9, w: 1.5 },
11127
- { kc: 81 }, { kc: 87 }, { kc: 69 }, { kc: 82 }, { kc: 84 }, { kc: 89 },
11128
- { kc: 85 }, { kc: 73 }, { kc: 79 }, { kc: 80 }, { kc: 192 },
11128
+ { code: `Tab`, w: 1.5 },
11129
+ { code: `KeyQ` }, { code: `KeyW` }, { code: `KeyE` }, { code: `KeyR` }, { code: `KeyT` }, { code: `KeyY` },
11130
+ { code: `KeyU` }, { code: `KeyI` }, { code: `KeyO` }, { code: `KeyP` }, { code: `BracketLeft` },
11129
11131
  ...(isJa
11130
- ? [{ kc: 219 }, { kc: 13, w: 1.25, h: 2 }] // JIS: [, Enter縦長
11131
- : [{ kc: 219 }, { kc: 221, w: 1.2 }] // US : [, ]
11132
+ ? [{ code: `BracketRight` }, { code: `Enter`, w: 1.25, h: 2 }] // JIS: BracketRight + Enter縦長
11133
+ : [{ code: `BracketRight` }, { code: `Backslash`, w: 1.2 }] // US : BracketRight + Backslash
11132
11134
  ),
11133
11135
  ],
11134
11136
  },
11135
11137
  // Row3: ASDF
11136
- // JIS: ..., L, ;, ', ¥(221)
11137
- // US : ..., L, ;, ', Enter(13)
11138
+ // JIS: ..., KeyL, Semicolon, Quote, Backslash
11139
+ // US : ..., KeyL, Semicolon, Quote, Enter(横長)
11138
11140
  {
11139
11141
  keys: [
11140
- { kc: 20, w: 1.75, label: `Caps\nLock` },
11141
- { kc: 65 }, { kc: 83 }, { kc: 68 }, { kc: 70 }, { kc: 71 }, { kc: 72 },
11142
- { kc: 74 }, { kc: 75 }, { kc: 76 }, { kc: 187 }, { kc: 186 },
11142
+ { code: `CapsLock`, w: 1.75, label: `Caps\nLock` },
11143
+ { code: `KeyA` }, { code: `KeyS` }, { code: `KeyD` }, { code: `KeyF` }, { code: `KeyG` }, { code: `KeyH` },
11144
+ { code: `KeyJ` }, { code: `KeyK` }, { code: `KeyL` }, { code: `Semicolon` }, { code: `Quote` },
11143
11145
  ...(isJa
11144
- ? [{ kc: 221 }] // JIS: ¥
11145
- : [{ kc: 13, w: 1.9 }] // US : Enter横長
11146
+ ? [{ code: `Backslash` }] // JIS: Backslash(¥)
11147
+ : [{ code: `Enter`, w: 1.9 }] // US : Enter横長
11146
11148
  ),
11147
11149
  ],
11148
11150
  },
11149
11151
  // Row4: ZXCV
11150
11152
  // L)Shift の幅で行頭位置を揃える
11151
- // JIS: L)Shift, ..., intlRo(226), R)Shift
11152
- // US : L)Shift, ..., R)Shift
11153
+ // JIS: L)Shift, ..., IntlRo, R)Shift
11154
+ // US : L)Shift, ..., R)Shift
11153
11155
  {
11154
11156
  keys: [
11155
- { kc: 16, w: 2.25 },
11156
- { kc: 90 }, { kc: 88 }, { kc: 67 }, { kc: 86 }, { kc: 66 }, { kc: 78 },
11157
- { kc: 77 }, { kc: 188 }, { kc: 190 }, { kc: 191 },
11157
+ { code: `ShiftLeft`, w: 2.25 },
11158
+ { code: `KeyZ` }, { code: `KeyX` }, { code: `KeyC` }, { code: `KeyV` }, { code: `KeyB` }, { code: `KeyN` },
11159
+ { code: `KeyM` }, { code: `Comma` }, { code: `Period` }, { code: `Slash` },
11158
11160
  ...(isJa
11159
- ? [{ kc: 226 }, { kc: 256, w: 1.5 }] // JIS: intlRo + R)Shift
11160
- : [{ kc: 256, w: 2.4 }] // US : R)Shift のみ(広い)
11161
+ ? [{ code: `IntlRo` }, { code: `ShiftRight`, w: 1.5 }] // JIS: IntlRo + R)Shift
11162
+ : [{ code: `ShiftRight`, w: 2.4 }] // US : R)Shift のみ(広い)
11161
11163
  ),
11162
11164
  ],
11163
11165
  },
11164
11166
  // Row5: スペースバー行
11165
- // JIS: ..., NoConv(29), Space, Conv(28), カタカナひらがな(242), ...
11167
+ // JIS: ..., NonConvert, Space, Convert, KanaMode, ...
11166
11168
  // US : ..., Space, ...
11167
11169
  {
11168
11170
  keys: [
11169
- { kc: 17, w: 1.25 }, { kc: 91 }, { kc: 18 },
11171
+ { code: `ControlLeft`, w: 1.25 }, { code: `MetaLeft` }, { code: `AltLeft` },
11170
11172
  ...(isJa
11171
- // JIS: NoConv + Space + Conv + カタカナひらがな
11172
- ? [{ kc: 29 }, { kc: 32, w: 5.25 }, { kc: 28 }, { kc: 242 }]
11173
+ // JIS: NonConvert + Space + Convert + KanaMode
11174
+ ? [{ code: `NonConvert` }, { code: `Space`, w: 5.25 }, { code: `Convert` }, { code: `KanaMode` }]
11173
11175
  // US : Space のみ(広い)
11174
- : [{ kc: 32, w: 8.25 }]
11176
+ : [{ code: `Space`, w: 8.25 }]
11175
11177
  ),
11176
- { kc: 258 }, { kc: 93 },
11178
+ { code: `AltRight` }, { code: `ContextMenu` },
11177
11179
  ...(isJa
11178
- ? [{ kc: 257, w: 1.2 }]
11179
- : [{ kc: 257, w: 1.05 }]
11180
+ ? [{ code: `ControlRight`, w: 1.2 }]
11181
+ : [{ code: `ControlRight`, w: 1.05 }]
11180
11182
  ),
11181
11183
  ],
11182
11184
  },
11183
11185
  ];
11184
11186
  };
11187
+
11185
11188
  // 編集キークラスター(PrintSc/ScrollLk/Pause/Insert/Delete/Home/End/PgUp/PgDn + 矢印キー)
11186
11189
  // MAIN_ROWS と行インデックスを揃えて配置する。空行はスキップされる。
11187
11190
  const NAV_ROWS = [
11188
- { keys: [{ kc: 44, label: `Print\nScreen` }, { kc: 145, label: `Scroll\nLock` }, { kc: 19 }] },
11189
- { keys: [{ kc: 45 }, { kc: 36 }, { kc: 33, label: `Page\nUp` }] }, // Insert Home PgUp
11190
- { keys: [{ kc: 46 }, { kc: 35 }, { kc: 34, label: `Page\nDown` }] }, // Delete End PgDn
11191
- { keys: [] }, // ASDF行:空
11192
- { keys: [{ kc: -1 }, { kc: 38 }, { kc: -1 }] }, // ↑
11193
- { keys: [{ kc: 37 }, { kc: 40 }, { kc: 39 }] }, // ← ↓ →
11191
+ { keys: [{ code: `PrintScreen`, label: `Print\nScreen` }, { code: `ScrollLock`, label: `Scroll\nLock` }, { code: `Pause` }] },
11192
+ { keys: [{ code: `Insert` }, { code: `Home` }, { code: `PageUp`, label: `Page\nUp` }] }, // Insert Home PgUp
11193
+ { keys: [{ code: `Delete` }, { code: `End` }, { code: `PageDown`, label: `Page\nDown` }] }, // Delete End PgDn
11194
+ { keys: [] }, // ASDF行:空
11195
+ { keys: [{ code: `` }, { code: `ArrowUp` }, { code: `` }] }, // ↑
11196
+ { keys: [{ code: `ArrowLeft` }, { code: `ArrowDown` }, { code: `ArrowRight` }] }, // ← ↓ →
11194
11197
  ];
11195
11198
 
11196
11199
  // テンキー(MAIN_ROWS と行インデックスを揃えて配置。1行目は空行で Fn行に揃える)
11197
- // kc は g_kCd 定義に従う: 96〜111=テンキー各種, 144=NumLk
11198
11200
  // 標準テンキーレイアウト(2行目から):
11199
11201
  // [NumLk] [T/] [T*] [T-]
11200
11202
  // [T7][T8][T9] [T+]
@@ -11203,11 +11205,11 @@ const keyconfigKeyboardPreview = (() => {
11203
11205
  // [ T0 ][T.] [TEnter] ← T0 は横2u、TEnter は縦2u
11204
11206
  const NUM_ROWS = [
11205
11207
  { keys: [] },
11206
- { keys: [{ kc: 144, label: `Num\nLock` }, { kc: 111 }, { kc: 106 }, { kc: 109 }] }, // NumLk T/ T* T-
11207
- { keys: [{ kc: 103 }, { kc: 104 }, { kc: 105 }, { kc: 107, h: 2 }] }, // T7 T8 T9 T+(縦2u)
11208
- { keys: [{ kc: 100 }, { kc: 101 }, { kc: 102 }] }, // T4 T5 T6
11209
- { keys: [{ kc: 97 }, { kc: 98 }, { kc: 99 }, { kc: 108, h: 2 }] }, // T1 T2 T3 TEnter(縦2u)
11210
- { keys: [{ kc: 96, w: 2 }, { kc: 110 }] }, // T0(横2u) T.
11208
+ { keys: [{ code: `NumLock`, label: `Num\nLock` }, { code: `NumpadDivide` }, { code: `NumpadMultiply` }, { code: `NumpadSubtract` }] }, // NumLk T/ T* T-
11209
+ { keys: [{ code: `Numpad7` }, { code: `Numpad8` }, { code: `Numpad9` }, { code: `NumpadAdd`, h: 2 }] }, // T7 T8 T9 T+(縦2u)
11210
+ { keys: [{ code: `Numpad4` }, { code: `Numpad5` }, { code: `Numpad6` }] }, // T4 T5 T6
11211
+ { keys: [{ code: `Numpad1` }, { code: `Numpad2` }, { code: `Numpad3` }, { code: `NumpadEnter`, h: 2 }] }, // T1 T2 T3 TEnter(縦2u)
11212
+ { keys: [{ code: `Numpad0`, w: 2 }, { code: `NumpadDecimal` }] }, // T0(横2u) T.
11211
11213
  ];
11212
11214
 
11213
11215
  // -------------------------------------------------------------------------
@@ -11215,12 +11217,12 @@ const keyconfigKeyboardPreview = (() => {
11215
11217
  // -------------------------------------------------------------------------
11216
11218
  const _state = {
11217
11219
  visible: false,
11218
- mappedSet: new Set(), // メインキー(各矢印の index 0)
11219
- altSet: new Set(), // 代替キー(各矢印の index 1 以降)
11220
- shortcutSet: new Set(), // プレイ中ショートカット(keyRetry / keyTitleBack / PgDn / PgUp)
11220
+ mappedSet: new Set(), // メインキー(code文字列)
11221
+ altSet: new Set(), // 代替キー(code文字列)
11222
+ shortcutSet: new Set(), // ショートカットキー(code文字列)
11221
11223
  canvasBase: null,
11222
11224
  canvasMap: null,
11223
- keyRects: [], // { kc, x, y, w, h, label } — drawMap で照合するキャッシュ
11225
+ keyDataList: [], // { code, x, y, w, h, label } — drawMap で照合するキャッシュ
11224
11226
  scale: 1, // BASE_KEY_W/H に掛けるスケール係数
11225
11227
  cvsW: 500, // 実際の Canvas 幅(スケール計算後)
11226
11228
  cvsH: 240, // 実際の Canvas 高さ(スケール計算後)
@@ -11282,22 +11284,24 @@ const keyconfigKeyboardPreview = (() => {
11282
11284
  // -------------------------------------------------------------------------
11283
11285
 
11284
11286
  /**
11285
- * keyCode に対応する [primaryLabel, subLabel] を返す。
11286
- * kc が -1(スペーサー)の場合は [``, ``] を返す。
11287
- * g_kCd の値は `"primary"` または `"primary sub"` 形式の文字列。
11287
+ * code に対応する [primaryLabel, subLabel] を返す。
11288
11288
  *
11289
- * @param {number} kc
11289
+ * @param {string} code
11290
11290
  * @param {string|undefined} forcedLabel - ROWS の label 指定がある場合に優先
11291
11291
  * @returns {string[]} [primary, sub]
11292
11292
  */
11293
- const getKeyLabels = (kc, forcedLabel) => {
11294
- if (kc < 0) return [``, ``];
11293
+ const getKeyLabels = (code, forcedLabel) => {
11294
+ if (!code) return [``, ``];
11295
11295
  if (forcedLabel !== undefined) return [forcedLabel, ``];
11296
11296
 
11297
- const raw = g_kCd[kc];
11298
- if (raw && raw !== g_kCd[0] && raw !== g_kCd[1]) {
11299
- const parts = raw.split(` `);
11300
- return [parts[0] || ``, parts[1] || ``];
11297
+ // code 文字列から従来の keyCode を逆引きして g_kCd から取得
11298
+ const kc = g_kCdN.indexOf(code);
11299
+ if (kc >= 0) {
11300
+ const raw = g_kCd[kc];
11301
+ if (raw && raw !== g_kCd[0] && raw !== g_kCd[1]) {
11302
+ const parts = raw.split(` `);
11303
+ return [parts[0] || ``, parts[1] || ``];
11304
+ }
11301
11305
  }
11302
11306
  return [`?`, ``];
11303
11307
  };
@@ -11312,6 +11316,22 @@ const keyconfigKeyboardPreview = (() => {
11312
11316
  const kg = () => Math.max(1, Math.round(BASE_KEY_GAP * _state.scale));
11313
11317
  const kr = () => Math.max(2, Math.round(4 * _state.scale));
11314
11318
 
11319
+ /**
11320
+ * Canvasの共通初期化処理
11321
+ */
11322
+ const setupCanvasContext = (canvas) => {
11323
+ if (!canvas) return null;
11324
+ canvas.style.top = wUnit(40);
11325
+ canvas.width = _state.cvsW * g_dpr;
11326
+ canvas.height = _state.cvsH * g_dpr;
11327
+ canvas.style.width = wUnit(_state.cvsW);
11328
+ canvas.style.height = wUnit(_state.cvsH);
11329
+
11330
+ const ctx = canvas.getContext(`2d`);
11331
+ ctx.scale(g_dpr, g_dpr);
11332
+ return ctx;
11333
+ };
11334
+
11315
11335
  const roundRect = (ctx, x, y, w, h, r) => {
11316
11336
  ctx.beginPath();
11317
11337
  ctx.moveTo(x + r, y);
@@ -11326,23 +11346,47 @@ const keyconfigKeyboardPreview = (() => {
11326
11346
  ctx.closePath();
11327
11347
  };
11328
11348
 
11329
- const drawKeyLabel = (ctx, x, y, keyW, keyH, primary, sub, textColor, subColor) => {
11349
+ /**
11350
+ * 単一キーを描画する(枠の描画と内部テキストの書き込みを一括化)
11351
+ * @param {CanvasRenderingContext2D} ctx
11352
+ * @param {Object} keyData - 位置・サイズ・キーコードを含むキー情報
11353
+ * @param {Object} style - fill, stroke, text 等の色セット
11354
+ * @param {number} lw - 枠線の太さ(lineWidth)
11355
+ */
11356
+ const drawOneKey = (ctx, { keyData, style, lw = 1 }) => {
11357
+ const { x, y, w: keyW, h: keyH, code, label } = keyData;
11358
+
11359
+ // 1. キーの枠線・背景を描画
11360
+ roundRect(ctx, x + 0.5, y + 0.5, keyW - 1, keyH - 1, kr());
11361
+ ctx.fillStyle = style.fill;
11362
+ ctx.strokeStyle = style.stroke;
11363
+ ctx.lineWidth = lw;
11364
+ ctx.fill();
11365
+ ctx.stroke();
11366
+
11367
+ // 2. キー内部のテキスト(メイン・サブ)を描画
11368
+ const [primary, sub] = getKeyLabels(code, label);
11369
+
11330
11370
  const fs = (_textLen) => _textLen >= 5 * keyW / BASE_KEY_W
11331
11371
  ? Math.max(6, Math.floor(9 * _state.scale))
11332
11372
  : Math.max(7, Math.floor(11 * _state.scale));
11333
11373
 
11374
+ // サブラベル(Shift面などの表記)がある場合
11334
11375
  if (sub) {
11335
- ctx.fillStyle = subColor;
11376
+ ctx.fillStyle = style.subText || style.text;
11336
11377
  ctx.font = `bold ${Math.max(6, Math.floor(9 * _state.scale))}px monospace`;
11337
11378
  ctx.textAlign = `right`;
11338
11379
  ctx.textBaseline = `top`;
11339
11380
  ctx.fillText(sub, x + keyW - 2, y + 2);
11340
11381
  }
11382
+
11383
+ // メインラベルの描画(改行表記に対応)
11341
11384
  const [primary1, primary2] = primary.split(`\n`);
11342
- ctx.fillStyle = textColor;
11385
+ ctx.fillStyle = style.text;
11343
11386
  ctx.textAlign = `center`;
11344
11387
  ctx.textBaseline = `middle`;
11345
11388
  const subDiff = sub ? 2 : 0;
11389
+
11346
11390
  if (primary2) {
11347
11391
  const siz = fs(Math.max(primary1.length, primary2.length));
11348
11392
  ctx.font = `bold ${siz}px monospace`;
@@ -11354,23 +11398,13 @@ const keyconfigKeyboardPreview = (() => {
11354
11398
  }
11355
11399
  };
11356
11400
 
11357
- const drawOneKey = (ctx, x, y, keyW, keyH, fill, stroke, lw, primary, sub, textColor, subColor) => {
11358
- roundRect(ctx, x + 0.5, y + 0.5, keyW - 1, keyH - 1, kr());
11359
- ctx.fillStyle = fill;
11360
- ctx.strokeStyle = stroke;
11361
- ctx.lineWidth = lw;
11362
- ctx.fill();
11363
- ctx.stroke();
11364
- drawKeyLabel(ctx, x, y, keyW, keyH, primary, sub, textColor, subColor);
11365
- };
11366
-
11367
11401
  // -------------------------------------------------------------------------
11368
11402
  // レイアウト計算・描画
11369
11403
  // -------------------------------------------------------------------------
11370
11404
 
11371
11405
  /**
11372
11406
  * rows 配列から各キーの矩形座標を計算し、
11373
- * canvas に描画しながら keyRects へキャッシュする。
11407
+ * canvas に描画しながら keyDataList へキャッシュする。
11374
11408
  *
11375
11409
  * @param {CanvasRenderingContext2D} ctx
11376
11410
  * @param {Array} rows - MAIN_ROWS または NAV_ROWS({offsetX, keys} 形式)
@@ -11392,21 +11426,17 @@ const keyconfigKeyboardPreview = (() => {
11392
11426
  const keyW = kw(keyDef.w || 1);
11393
11427
  const keyH = kh(keyDef.h || 1);
11394
11428
 
11395
- if (keyDef.kc >= 0) {
11396
- _state.keyRects.push({
11397
- kc: keyDef.kc,
11429
+ if (keyDef.code !== ``) {
11430
+ const keyData = {
11431
+ code: keyDef.code,
11398
11432
  x: curX,
11399
11433
  y: rowY,
11400
11434
  w: keyW,
11401
11435
  h: keyH,
11402
11436
  label: keyDef.label,
11403
- });
11404
- const [primary, sub] = getKeyLabels(keyDef.kc, keyDef.label);
11405
- drawOneKey(
11406
- ctx, curX, rowY, keyW, keyH,
11407
- C_COLOR.keyFill, C_COLOR.keyStroke, 1,
11408
- primary, sub, C_COLOR.keyText, C_COLOR.keySubText
11409
- );
11437
+ };
11438
+ _state.keyDataList.push(keyData);
11439
+ drawOneKey(ctx, { keyData, style: C_COLOR.normal, lw: 1 });
11410
11440
  }
11411
11441
 
11412
11442
  curX += keyW + gap;
@@ -11415,26 +11445,18 @@ const keyconfigKeyboardPreview = (() => {
11415
11445
  };
11416
11446
 
11417
11447
  /**
11418
- * キーボード背景レイヤーを描画し keyRects をキャッシュする。
11448
+ * キーボード背景レイヤーを描画し keyDataList をキャッシュする。
11419
11449
  * init 時に呼ぶ。
11420
11450
  */
11421
11451
  const drawBase = () => {
11422
- const canvas = _state.canvasBase;
11423
- if (!canvas) return;
11452
+ const ctx = setupCanvasContext(_state.canvasBase);
11453
+ if (!ctx) return;
11424
11454
 
11425
- canvas.style.top = wUnit(40);
11426
- canvas.width = _state.cvsW * g_dpr;
11427
- canvas.height = _state.cvsH * g_dpr;
11428
- canvas.style.width = wUnit(_state.cvsW);
11429
- canvas.style.height = wUnit(_state.cvsH);
11430
-
11431
- const ctx = canvas.getContext(`2d`);
11432
- ctx.scale(g_dpr, g_dpr);
11433
11455
  ctx.clearRect(0, 0, _state.cvsW, _state.cvsH);
11434
11456
  ctx.fillStyle = C_COLOR.bgFill;
11435
11457
  ctx.fillRect(0, 0, _state.cvsW, _state.cvsH);
11436
11458
 
11437
- _state.keyRects = [];
11459
+ _state.keyDataList = [];
11438
11460
 
11439
11461
  const mainRows = buildMainRows();
11440
11462
  const gap = kg();
@@ -11456,25 +11478,26 @@ const keyconfigKeyboardPreview = (() => {
11456
11478
 
11457
11479
  // 凡例
11458
11480
  const ly = _state.cvsH - 10;
11459
- const fnt = `${Math.max(9, Math.floor(12 * _state.scale))}px ${getBasicFont()}`;
11460
- ctx.font = fnt;
11481
+ ctx.font = `${Math.max(9, Math.floor(12 * _state.scale))}px ${getBasicFont()}`;
11461
11482
  ctx.textAlign = `left`;
11462
11483
  ctx.textBaseline = `middle`;
11463
11484
 
11464
- const drawLegend = (x, fill, stroke, label) => {
11465
- roundRect(ctx, x, ly - 5, 10, 10, 2);
11466
- ctx.fillStyle = fill; ctx.fill();
11467
- ctx.strokeStyle = stroke; ctx.lineWidth = 1; ctx.stroke();
11468
- ctx.fillStyle = C_COLOR.legendText;
11469
- ctx.fillText(label, x + 14, ly);
11485
+ const legends = [
11486
+ { style: C_COLOR.normal, label: g_lblNameObj.unallocated },
11487
+ { style: C_COLOR.mapped, label: g_lblNameObj.allocated },
11488
+ { style: C_COLOR.alt, label: g_lblNameObj.altAllocated },
11489
+ { style: C_COLOR.shortcut, label: g_lblNameObj.shortcutKey }
11490
+ ];
11470
11491
 
11471
- return 14 + ctx.measureText(label).width + 14;
11472
- };
11473
11492
  let lx = 8;
11474
- lx += drawLegend(lx, C_COLOR.keyFill, C_COLOR.keyStroke, g_lblNameObj.unallocated);
11475
- lx += drawLegend(lx, C_COLOR.mappedFill, C_COLOR.mappedStroke, g_lblNameObj.allocated);
11476
- lx += drawLegend(lx, C_COLOR.altFill, C_COLOR.altStroke, g_lblNameObj.altAllocated);
11477
- lx += drawLegend(lx, C_COLOR.shortcutFill, C_COLOR.shortcutStroke, g_lblNameObj.shortcutKey);
11493
+ legends.forEach(item => {
11494
+ roundRect(ctx, lx, ly - 5, 10, 10, 2);
11495
+ ctx.fillStyle = item.style.fill; ctx.fill();
11496
+ ctx.strokeStyle = item.style.stroke; ctx.lineWidth = 1; ctx.stroke();
11497
+ ctx.fillStyle = C_COLOR.legendText;
11498
+ ctx.fillText(item.label, lx + 14, ly);
11499
+ lx += ctx.measureText(item.label).width + 28;
11500
+ });
11478
11501
  };
11479
11502
 
11480
11503
  /**
@@ -11483,47 +11506,25 @@ const keyconfigKeyboardPreview = (() => {
11483
11506
  * 同一キーにメインと代替が重なる場合はメインを優先する。
11484
11507
  */
11485
11508
  const drawMap = () => {
11486
- const canvas = _state.canvasMap;
11487
- if (!canvas) return;
11488
-
11489
- canvas.style.top = wUnit(40);
11490
- canvas.width = _state.cvsW * g_dpr;
11491
- canvas.height = _state.cvsH * g_dpr;
11492
- canvas.style.width = wUnit(_state.cvsW);
11493
- canvas.style.height = wUnit(_state.cvsH);
11509
+ const ctx = setupCanvasContext(_state.canvasMap);
11510
+ if (!ctx) return;
11494
11511
 
11495
- const ctx = canvas.getContext(`2d`);
11496
- ctx.scale(g_dpr, g_dpr);
11497
11512
  ctx.clearRect(0, 0, _state.cvsW, _state.cvsH);
11498
11513
 
11499
- // 優先度: ショートカット > メイン > 代替(後から描くほど優先)
11500
- const drawKey = (fill, stroke, text) => rect => {
11501
- const [primary, sub] = getKeyLabels(rect.kc, rect.label);
11502
- roundRect(ctx, rect.x + 0.5, rect.y + 0.5, rect.w - 1, rect.h - 1, kr());
11503
- ctx.fillStyle = fill;
11504
- ctx.strokeStyle = stroke;
11505
- ctx.lineWidth = 1.5;
11506
- ctx.fill();
11507
- ctx.stroke();
11508
- drawKeyLabel(ctx, rect.x, rect.y, rect.w, rect.h, primary, sub, text, text);
11514
+ // キー状態に応じた色取得ロジック(優先度: ショートカット > メイン > 代替)
11515
+ const getKeyStyle = (code) => {
11516
+ if (_state.shortcutSet.has(code)) return C_COLOR.shortcut;
11517
+ if (_state.mappedSet.has(code)) return C_COLOR.mapped;
11518
+ if (_state.altSet.has(code)) return C_COLOR.alt;
11519
+ return null;
11509
11520
  };
11510
11521
 
11511
- // 1. 代替キー(メイン・ショートカットと重複しない場合のみ)
11512
- _state.keyRects
11513
- .filter(rect => _state.altSet.has(rect.kc)
11514
- && !_state.mappedSet.has(rect.kc)
11515
- && !_state.shortcutSet.has(rect.kc))
11516
- .forEach(drawKey(C_COLOR.altFill, C_COLOR.altStroke, C_COLOR.altText));
11517
-
11518
- // 2. メインキー(ショートカットと重複しない場合のみ)
11519
- _state.keyRects
11520
- .filter(rect => _state.mappedSet.has(rect.kc) && !_state.shortcutSet.has(rect.kc))
11521
- .forEach(drawKey(C_COLOR.mappedFill, C_COLOR.mappedStroke, C_COLOR.mappedText));
11522
-
11523
- // 3. ショートカット(常に最前面)
11524
- _state.keyRects
11525
- .filter(rect => _state.shortcutSet.has(rect.kc))
11526
- .forEach(drawKey(C_COLOR.shortcutFill, C_COLOR.shortcutStroke, C_COLOR.shortcutText));
11522
+ _state.keyDataList.forEach(keyData => {
11523
+ const style = getKeyStyle(keyData.code);
11524
+ if (style) {
11525
+ drawOneKey(ctx, { keyData, style, lw: 1.5 });
11526
+ }
11527
+ });
11527
11528
  };
11528
11529
 
11529
11530
  // -------------------------------------------------------------------------
@@ -11596,12 +11597,17 @@ const keyconfigKeyboardPreview = (() => {
11596
11597
  const ctrl = g_keyObj[`keyCtrl${tkObj.keyCtrlPtn}`]
11597
11598
  .filter((val, idx) => tkObj.keyGroupMaps[idx].includes(configKeyGroupList[g_keycons.keySwitchNum]));
11598
11599
 
11599
- _state.mappedSet = new Set(ctrl.map(arr => arr[0]).filter(v => v > 0));
11600
- _state.altSet = new Set(ctrl.flatMap(arr => arr.slice(1)).filter(v => v > 0));
11600
+ // 数値から code 文字列へ安全に変換するヘルパー
11601
+ const toCodeStr = (num) => g_kCdN[num] || ``;
11602
+
11603
+ _state.mappedSet = new Set(ctrl.map(arr => toCodeStr(arr[0])).filter(v => v !== ``));
11604
+ _state.altSet = new Set(ctrl.flatMap(arr => arr.slice(1)).map(toCodeStr).filter(v => v !== ``));
11605
+
11601
11606
  // プレイ中ショートカット: keyRetry / keyTitleBack は g_headerObj から取得、PgDn(34) / PgUp(33) は固定
11602
11607
  _state.shortcutSet = new Set(
11603
- [g_headerObj.keyRetry, g_headerObj.keyTitleBack, 34, 33].filter(v => v > 0)
11608
+ [g_headerObj.keyRetry, g_headerObj.keyTitleBack, 34, 33].map(toCodeStr).filter(v => v !== ``)
11604
11609
  );
11610
+
11605
11611
  if (_state.visible) drawMap();
11606
11612
  };
11607
11613
 
@@ -11614,7 +11620,7 @@ const keyconfigKeyboardPreview = (() => {
11614
11620
  _state.mappedSet = new Set();
11615
11621
  _state.altSet = new Set();
11616
11622
  _state.shortcutSet = new Set();
11617
- _state.keyRects = [];
11623
+ _state.keyDataList = [];
11618
11624
  _state.canvasBase = null;
11619
11625
  _state.canvasMap = null;
11620
11626
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "danoniplus",
3
- "version": "48.4.1",
3
+ "version": "48.4.2",
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",