danoniplus 52.0.0 → 52.1.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/11/01
7
+ * Revised : 2026/11/03
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 52.0.0`;
12
- const g_revisedDate = `2026/11/01`;
11
+ const g_version = `Ver 52.1.0`;
12
+ const g_revisedDate = `2026/11/03`;
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/11/01 (v52.0.0)
8
+ * Revised : 2026/11/03 (v52.1.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -3178,6 +3178,8 @@ const g_shortcutObj = {
3178
3178
  Escape: { id: `btnHelpClose` },
3179
3179
  ArrowUp: { id: `btnHelpPrev` },
3180
3180
  ArrowDown: { id: `btnHelpNext` },
3181
+ ArrowLeft: { id: `btnHelpLeft` },
3182
+ ArrowRight: { id: `btnHelpRight` },
3181
3183
  },
3182
3184
  keyConfig: {
3183
3185
  //Escape: { id: `btnBack` }, // Escapeを別用途でも使用するため、ここではコメントアウト
@@ -5176,7 +5178,7 @@ const g_lang_msgObj = {
5176
5178
  `[XZ-Axis] X-Z軸回転\n` +
5177
5179
  `[YZ-Axis] Y-Z軸回転\n` +
5178
5180
  `[Random+] X軸, Y軸, Z軸, X-Y軸, X-Z軸, Y-Z回転のいずれかが適用されます。`,
5179
- frzReturnType: `[360°/120°/60°] 指定の角度まで回転します\n[±360°/±120°] 360°/120°に加えて逆回転が掛かることがあります\n[Pendulum] 振り子のように左右に動きます`,
5181
+ frzReturnType: `回転幅を変更する設定です。\n[360°/120°/60°] 指定の角度まで回転します\n[±360°/±120°] 360°/120°に加えて逆回転が掛かることがあります\n[Pendulum] 振り子のように左右に動きます`,
5180
5182
  shaking: `ステップゾーン及び矢印を揺らす設定です。\n` +
5181
5183
  `[Horizontal] 横方向に揺らします。\n[Vertical] 縦方向に揺らします。\n` +
5182
5184
  `[X-Horizontal] レイヤーごとに左右交互の向きで横に揺らします。\n` +
@@ -5190,7 +5192,12 @@ const g_lang_msgObj = {
5190
5192
  `[Wave] 矢印とフリーズアローが左右に揺れながら移動します。\n` +
5191
5193
  `[Storm] 矢印とフリーズアローが左右に激しく揺れ、回転します。\n` +
5192
5194
  `[Blinking] 矢印が点滅します。\n[Squids] 矢印が伸び縮みします。`,
5193
- camoufrage: `ステップの見た目が配置は同じでランダムに変わります。`,
5195
+ camoufrage: `ステップの見た目が配置は同じでランダムに変わります。\n` +
5196
+ `[Color] 矢印とフリーズアローの色が他のものに擬態します。\n` +
5197
+ `[Arrow] 矢印とフリーズアローの矢印形状が他のものに擬態します。\n` +
5198
+ `[Step+Arrow] 矢印とフリーズアローの矢印形状・ステップゾーンが他のものに擬態します。\n` +
5199
+ `[Color+Arrow] 矢印とフリーズアローの色・矢印形状が他のものに擬態します。\n` +
5200
+ `[Color+Step+Arrow] 矢印とフリーズアローの色・矢印形状・ステップゾーン全てが他のものに擬態します。`,
5194
5201
  camoufrageType: `[FrzArrow] フリーズアローの帯部分を初期表示のみ非表示にし、矢印のみで表示します(ヒット/失敗時は帯を再表示)`,
5195
5202
  swapping: `ステップゾーンの位置を入れ替える設定です。\n` +
5196
5203
  `[InnerSwap] ステップゾーンの中央部分のみグループ単位で入れ替えます。\n` +
@@ -5345,7 +5352,7 @@ const g_lang_msgObj = {
5345
5352
  `[XZ-Axis] X-Z axis rotation\n` +
5346
5353
  `[YZ-Axis] Y-Z axis rotation\n` +
5347
5354
  `[Random+] Randomly rotates to one of the X/Y/Z/X-Y/X-Z/Y-Z axes.`,
5348
- frzReturnType: `[360deg/120deg/60deg] Rotates to the specified angle.\n[±360deg/±120deg] May rotate in the opposite direction in addition to 360deg/120deg.\n[Pendulum] Moves back and forth like a pendulum.`,
5355
+ frzReturnType: `Set the rotation range.\n[360deg/120deg/60deg] Rotates to the specified angle.\n[±360deg/±120deg] May rotate in the opposite direction in addition to 360deg/120deg.\n[Pendulum] Moves back and forth like a pendulum.`,
5349
5356
  shaking: `This sets shaking for the step zone and arrows.\n` +
5350
5357
  `[Horizontal] Shakes horizontally.\n[Vertical] Shakes vertically.\n` +
5351
5358
  `[X-Horizontal] Per-layer shaking with alternating left/right direction by layer.\n` +
@@ -5354,8 +5361,13 @@ const g_lang_msgObj = {
5354
5361
  `[S-Drunk] Shakes the entire screen randomly in all directions, and also shakes each layer randomly in all directions.\n` +
5355
5362
  `[H-Drunk] Adds stronger vertical movement than S-Drunk and adds rotation.`,
5356
5363
  effect: `Applies effects to the arrows and freeze arrows.\n[Dizzy/Spin] Arrows rotate.\n[Wave/Storm] Swing from left to right.\n[Blinking] Arrows blink.\n[Squids] Arrows stretch and shrink.`,
5357
- camoufrage: `The appearance of the steps changes randomly with the same placement.`,
5358
- camoufrageType: `[FrzArrow] Initially hides freeze-arrow bars and displays only the arrow portion (bars reappear on hit/failure)`,
5364
+ camoufrage: `The appearance of the steps changes randomly with the same placement.\n` +
5365
+ `[Color] The color of the arrows and freeze arrows mimics other objects.\n` +
5366
+ `[Arrow] The arrow shape of the arrows and freeze arrows mimics other objects.\n` +
5367
+ `[Step+Arrow] The arrow shape and step zone of the arrows and freeze arrows mimics other objects.\n` +
5368
+ `[Color+Arrow] The color and arrow shape of the arrows and freeze arrows mimics other objects.\n` +
5369
+ `[Color+Step+Arrow] The color, arrow shape, and step zone of the arrows and freeze arrows mimics other objects.`,
5370
+ camoufrageType: `[FrzArrow] Initially hides freeze-arrow bars and displays only the arrow portion (bars reappear on hit/failure).`,
5359
5371
  swapping: `This setting allows you to swap the positions of the step zones.\n` +
5360
5372
  `[InnerSwap] Swaps only the inner portion of step zones within each shuffle group.\n` +
5361
5373
  `[OuterSwap] Swaps the outer portion (inverse of InnerSwap) within each shuffle group.\n` +
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2026/09/13
8
- * Revised : 2026/11/01 (v52.0.0)
8
+ * Revised : 2026/11/03 (v52.1.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -2051,9 +2051,15 @@ const openHelpOverlay = (_title, _msg, _stateKey) => {
2051
2051
  if (![`option`, `exSetting`, `settingsDisplay`].includes(g_currentPage)) return;
2052
2052
 
2053
2053
  // 現在値は、g_currentPage を切り替える前に取得する(getStgDetailName が画面名を参照するため)
2054
- const currentVal = g_stateObj[_stateKey];
2055
- const currentNames = [currentVal, getStgDetailName(currentVal)];
2056
- const optNames = new Map((g_settings[`${_stateKey}s`] ?? []).map(val => [val, [val, getStgDetailName(val)]]));
2054
+ const sub = g_helpPreviewDefs[_stateKey]?.sub || (_stateKey + `Type`);
2055
+ const subList = sub !== undefined ? (g_settings[`${sub}s`] ?? []) : [];
2056
+ const currentVals = [g_stateObj[_stateKey], ...(subList.length > 0 ? [g_stateObj[sub]] : [])];
2057
+ const currentNames = currentVals.flatMap(val => [val, getStgDetailName(val)]);
2058
+ const optNames = new Map([...(g_settings[`${_stateKey}s`] ?? []), ...subList]
2059
+ .map(val => [val, [val, getStgDetailName(val)]]));
2060
+
2061
+ // Typeがある設定は、本体の説明文の後にTypeの説明文を続ける
2062
+ const helpMsg = [_msg, ...(subList.length > 0 ? [g_msgObj[sub]] : [])].filter(hasVal).join(`\n\n`);
2057
2063
  const rowElms = [];
2058
2064
  const bright = g_headerObj.baseBrightFlg;
2059
2065
 
@@ -2080,7 +2086,7 @@ const openHelpOverlay = (_title, _msg, _stateKey) => {
2080
2086
  });
2081
2087
  g_handler.addListener(body, `click`, evt => evt.stopPropagation());
2082
2088
 
2083
- parseHelpLines(_msg).forEach(line => {
2089
+ parseHelpLines(helpMsg).forEach(line => {
2084
2090
  const row = document.createElement(`div`);
2085
2091
  Object.assign(row.style, {
2086
2092
  fontFamily: getBasicFont(), fontSize: wUnit(14), lineHeight: `1.1`, textAlign: `left`,
@@ -2109,12 +2115,13 @@ const openHelpOverlay = (_title, _msg, _stateKey) => {
2109
2115
  });
2110
2116
 
2111
2117
  // 説明文の選択行 (背景) をプレビューのカーソルに追従させる
2112
- const markHelpRows = _val => {
2113
- const names = optNames.get(_val) ?? [_val];
2118
+ const markHelpRows = (_vals, _focus = 0) => {
2119
+ const names = _vals.flatMap(val => optNames.get(val) ?? [val]);
2120
+ const focusNames = optNames.get(_vals[_focus]) ?? [_vals[_focus]];
2114
2121
  rowElms.forEach(({ nameList, row }) => {
2115
2122
  const on = nameList.some(name => names.includes(name));
2116
2123
  row.style.background = on ? `rgba(80,140,255,0.25)` : ``;
2117
- if (on) {
2124
+ if (nameList.some(name => focusNames.includes(name))) {
2118
2125
  // 本文がスクロールする場合は、選択行が見える位置へ寄せる
2119
2126
  const [top, bottom] = [row.offsetTop, row.offsetTop + row.offsetHeight];
2120
2127
  if (top < body.scrollTop) {
@@ -2125,7 +2132,7 @@ const openHelpOverlay = (_title, _msg, _stateKey) => {
2125
2132
  }
2126
2133
  });
2127
2134
  };
2128
- markHelpRows(currentVal);
2135
+ markHelpRows(currentVals);
2129
2136
  g_helpSelectHook = markHelpRows;
2130
2137
 
2131
2138
  // 上下キー: プレビューの選択肢移動、または本文のスクロール
@@ -2150,6 +2157,14 @@ const openHelpOverlay = (_title, _msg, _stateKey) => {
2150
2157
  createCss2Button(`btnHelpNext`, ``, () => true, {
2151
2158
  x: 0, y: 0, w: 0, h: 0, opacity: 0, resetFunc: () => moveHelp(1),
2152
2159
  }, g_cssObj.button_Mini),
2160
+
2161
+ // 操作対象の列の切り替え (本体 / Type)
2162
+ createCss2Button(`btnHelpLeft`, ``, () => true, {
2163
+ x: 0, y: 0, w: 0, h: 0, opacity: 0, resetFunc: () => g_helpPreviewColumn(-1),
2164
+ }, g_cssObj.button_Mini),
2165
+ createCss2Button(`btnHelpRight`, ``, () => true, {
2166
+ x: 0, y: 0, w: 0, h: 0, opacity: 0, resetFunc: () => g_helpPreviewColumn(1),
2167
+ }, g_cssObj.button_Mini),
2153
2168
  );
2154
2169
  createScText(btnHelpClose, `HelpClose`, { displayName: `helpOverlay`, targetLabel: `btnHelpClose`, x: -5 });
2155
2170
  if (previewH > 0) {
@@ -2202,16 +2217,17 @@ const isLongHelp = _msg =>
2202
2217
  * - currentKey: サンプルキーではなく実際のキーに合わせてマッピングする
2203
2218
  * (StepArea, Swappingは実際のキーには非対応)
2204
2219
  * - frzUse : サンプルでフリーズアローを使用するかどうか
2220
+ * - sub : 派生する設定 (Typeなど)。選択肢の列を2列目に追加する
2205
2221
  */
2206
2222
  const g_helpPreviewDefs = {
2207
2223
  motion: {},
2208
2224
  scroll: { currentKey: true },
2209
2225
  appearance: { splitLayer: true },
2210
- playWindow: {},
2226
+ playWindow: { sub: `playWindowType` },
2211
2227
  stepArea: {},
2212
2228
  shaking: { splitLayer: true },
2213
- frzReturn: {},
2214
- effect: { currentKey: true, frzUse: true },
2229
+ frzReturn: { sub: `frzReturnType` },
2230
+ effect: { frzUse: true, splitLayer: true },
2215
2231
  swapping: { frzUse: true },
2216
2232
  };
2217
2233
 
@@ -2246,6 +2262,9 @@ let g_helpPreviewStop = () => true;
2246
2262
  /** プレビューの選択肢を前後へ動かす処理 (プレビュー表示中のみ差し替わる) */
2247
2263
  let g_helpPreviewMove = _dir => true;
2248
2264
 
2265
+ /** プレビューの操作対象の列を切り替える処理 (-1: 本体、1: Type。プレビュー表示中のみ差し替わる) */
2266
+ let g_helpPreviewColumn = _dir => true;
2267
+
2249
2268
  /**
2250
2269
  * 詳細ヘルプ内プレビューの作成
2251
2270
  * @param {HTMLDivElement} _parent オーバーレイ
@@ -2260,7 +2279,10 @@ const makeHelpPreview = (_parent, _key, _top, _height) => {
2260
2279
  return;
2261
2280
  }
2262
2281
  const playH = g_headerObj.playingHeight || g_sHeight;
2263
- const chipW = 120;
2282
+ const subList = def.sub !== undefined ? g_settings[`${def.sub}s`] : undefined;
2283
+ const subUse = subList !== undefined;
2284
+ const colW = subUse ? 90 : 120;
2285
+ const chipW = subUse ? colW * 2 + 6 : colW; // 選択肢ボタン列の全体幅 (Typeがある場合は2列)
2264
2286
  const areaW = g_sWidth - 60;
2265
2287
 
2266
2288
  // レーン定義: Scrollのみ現在選択中のキー・パターンの定義を使用 (他は4レーン固定)
@@ -2432,6 +2454,8 @@ const makeHelpPreview = (_parent, _key, _top, _height) => {
2432
2454
  let stride = Math.max(Math.round(visibleLanes.length * 0.6), 1);
2433
2455
  while (gcd(stride, visibleLanes.length) !== 1) stride++;
2434
2456
  let selected = ``;
2457
+ let subSelected = subUse ? (subList.includes(g_stateObj[def.sub]) ? g_stateObj[def.sub] : subList[0]) : ``;
2458
+ let activeCol = 0; // 上下キーの対象列 (0: 本体、1: Type)
2435
2459
  let frameCnt = 0;
2436
2460
  let noteCnt = 0;
2437
2461
  let autoCnt = 0; // 自動切替までの経過フレーム数
@@ -2443,7 +2467,7 @@ const makeHelpPreview = (_parent, _key, _top, _height) => {
2443
2467
  let filterElms = []; // Appearanceのフィルターバー・ラベル
2444
2468
  const frzLen = 90; // Effectプレビュー用フリーズアローの長さ(px)
2445
2469
  const work = { drunkXFlg: true, drunkYFlg: true, drunkAxisFlg: false, drunkRotateFlg: false };
2446
- const frz = { seq: null, axes: [], start: 0, next: 0 };
2470
+ const frz = { seq: null, seqNo: 0, axes: [], start: 0, next: 0 };
2447
2471
 
2448
2472
  /** 付与したtransformの初期化 */
2449
2473
  const resetTransforms = () => spriteIds.forEach(id => {
@@ -2598,6 +2622,18 @@ const makeHelpPreview = (_parent, _key, _top, _height) => {
2598
2622
  });
2599
2623
  };
2600
2624
 
2625
+ /** Typeの選択値を、ゲーム側の関数が参照する g_stateObj へ一時的に差し替えて実行 (g_playWindowDir など) */
2626
+ const withSub = func => {
2627
+ if (!subUse) return func();
2628
+ const org = g_stateObj[def.sub];
2629
+ g_stateObj[def.sub] = subSelected;
2630
+ try {
2631
+ return func();
2632
+ } finally {
2633
+ g_stateObj[def.sub] = org;
2634
+ }
2635
+ };
2636
+
2601
2637
  /**
2602
2638
  * 選択肢の適用
2603
2639
  * - Motion: 「配列の15がステップゾーン上」として、ステップゾーンからの距離を逆算する
@@ -2611,9 +2647,10 @@ const makeHelpPreview = (_parent, _key, _top, _height) => {
2611
2647
 
2612
2648
  assignSwapping(_key === `swapping` ? opt : null);
2613
2649
  // レーンのレイヤー配置 (StepAreaは選択肢ごと、Shakingは右半分を逆スクロール側へ)
2614
- assignLanes((_key === `stepArea` ? g_helpStepAreaLayouts[opt] : null)
2615
- ?? (g_helpPreviewDefs[_key]?.currentKey ? getScrollLayout(opt) : null)
2616
- ?? (def.splitLayer ? [0, 0, 1, 1] : [0, 0, 0, 0]));
2650
+ assignLanes((g_helpPreviewDefs[_key]?.currentKey ? getScrollLayout(opt) : null)
2651
+ ?? (_key === `stepArea` ? g_helpStepAreaLayouts[opt] : null)
2652
+ ?? (def.splitLayer ? [0, 0, 1, 1] : [0, 0, 0, 0])
2653
+ .map(val => g_stateObj.reverse === C_FLG_OFF ? val : val ^ 1));
2617
2654
  applyFlat(opt);
2618
2655
  if (_key === `stepArea`) {
2619
2656
  runStepArea(opt);
@@ -2624,7 +2661,7 @@ const makeHelpPreview = (_parent, _key, _top, _height) => {
2624
2661
 
2625
2662
  // SideScrollのみ矢印を90度回転 (ゲーム側の changeStepRtn と同じ符号)
2626
2663
  rtnOffset = (_key === `playWindow` && opt === `SideScroll` && g_stateObj.rotateEnabled)
2627
- ? 90 * (g_stateObj.playWindowType === C_FLG_REVERSE2 ? -1 : 1) : 0;
2664
+ ? 90 * (subSelected === C_FLG_REVERSE2 ? -1 : 1) : 0;
2628
2665
  if (g_stateObj.rotateEnabled) {
2629
2666
  laneInfo.forEach((lane, j) => {
2630
2667
  if (typeof getRtn(j) === `number`) {
@@ -2651,13 +2688,14 @@ const makeHelpPreview = (_parent, _key, _top, _height) => {
2651
2688
  dist[b] = dist[b - 1] + frameSpd + (trace[b] || 0);
2652
2689
  }
2653
2690
  if (_key === `playWindow`) {
2654
- addTransform(`mainSprite`, `playWindow`, g_playWindowFunc.get(opt)(), g_transPriority.playWindow);
2691
+ addTransform(`mainSprite`, `playWindow`, withSub(() => g_playWindowFunc.get(opt)()), g_transPriority.playWindow);
2655
2692
  }
2656
2693
  if (_key === `shaking`) {
2657
2694
  Object.assign(work, { drunkXFlg: true, drunkYFlg: true, drunkAxisFlg: false, drunkRotateFlg: false });
2658
2695
  }
2659
2696
  if (_key === `frzReturn`) {
2660
2697
  frz.seq = null;
2698
+ frz.seqNo = 0;
2661
2699
  frz.next = frameCnt + 30;
2662
2700
  }
2663
2701
  };
@@ -2737,8 +2775,8 @@ const makeHelpPreview = (_parent, _key, _top, _height) => {
2737
2775
  if (selected === C_FLG_OFF) return;
2738
2776
  if (frz.seq === null) {
2739
2777
  if (frameCnt < frz.next) return;
2740
- const seqs = (g_frzReturnSeqFunc.get(g_stateObj.frzReturnType) ?? g_frzReturnSeqFunc.get(`360deg`))();
2741
- frz.seq = seqs[Math.floor(Math.random() * seqs.length)];
2778
+ const seqs = (g_frzReturnSeqFunc.get(subSelected) ?? g_frzReturnSeqFunc.get(`360deg`))();
2779
+ frz.seq = seqs[frz.seqNo++ % seqs.length];
2742
2780
  frz.axes = [...g_frzReturnFunc.get(selected)()].filter(Boolean);
2743
2781
  frz.start = frameCnt;
2744
2782
  }
@@ -2813,38 +2851,83 @@ const makeHelpPreview = (_parent, _key, _top, _height) => {
2813
2851
  spriteIds.forEach(id => delete g_transforms[id]);
2814
2852
  g_helpPreviewStop = () => true;
2815
2853
  g_helpPreviewMove = _dir => true;
2854
+ g_helpPreviewColumn = _dir => true;
2816
2855
  };
2817
2856
  g_helpPreviewStop = stop;
2818
2857
 
2819
2858
  // ---------------------------------------------------
2820
- // 選択肢ボタン (g_settings の一覧から作成)
2821
- const chipH = Math.min(20, Math.floor(_height / optList.length));
2859
+ // 選択肢ボタン (本体の列と、Typeがある設定のみTypeの列)
2860
+ const chipX = baseX + viewW + 15;
2861
+ const colMain = createEmptySprite(area, `pvColMain`, { x: chipX, y: 0, w: colW, h: _height });
2862
+ const colSub = subUse ? createEmptySprite(area, `pvColSub`, { x: chipX + colW + 6, y: 0, w: colW, h: _height }) : null;
2863
+
2864
+ const makeChips = (_list, _prefix, _onSelect, _title = ``) => {
2865
+ const chipH = Math.min(20, Math.floor(_height / _list.length));
2866
+ return _list.map((opt, i) =>
2867
+ createCss2Button(`${_prefix}${i}`, getStgDetailName(opt), () => _onSelect(opt), {
2868
+ x: 0, y: i * chipH, w: colW, h: chipH - 2, siz: 12, title: _title,
2869
+ }, g_cssObj.button_Default));
2870
+ };
2871
+ const chips = makeChips(optList, `pvChip`, opt => selectMain(opt));
2872
+ const subChips = subUse ? makeChips(subList, `pvSubChip`, opt => selectSub(opt), g_msgObj[def.sub] ?? ``) : [];
2873
+ multiAppend(colMain, ...chips);
2874
+ if (subUse) {
2875
+ multiAppend(colSub, ...subChips);
2876
+ }
2877
+
2822
2878
  const markChips = () => {
2823
- chips.forEach((chip, i) => {
2879
+ const mark = (_list, _chips, _current) => _chips.forEach((chip, i) => {
2824
2880
  chip.classList.remove(g_cssObj.button_Default, g_cssObj.button_Setting);
2825
- chip.classList.add(optList[i] === selected ? g_cssObj.button_Setting : g_cssObj.button_Default);
2881
+ chip.classList.add(_list[i] === _current ? g_cssObj.button_Setting : g_cssObj.button_Default);
2826
2882
  });
2827
- g_helpSelectHook(selected);
2883
+ mark(optList, chips, selected);
2884
+ if (subUse) {
2885
+ mark(subList, subChips, subSelected);
2886
+ colSub.style.opacity = activeCol === 1 ? 1 : 0.5; // 操作対象でない列は薄く表示
2887
+ }
2888
+ colMain.style.opacity = subUse && activeCol !== 0 ? 0.5 : 1;
2889
+ g_helpSelectHook(subUse ? [selected, subSelected] : [selected], activeCol);
2828
2890
  safeExecuteCustomHooks(`g_customJsObj.helpPreview`, g_customJsObj.helpPreview, _key, selected,
2829
- { pvFrame, mainSprite, stepSprites, arrowSprites, playW, playH });
2891
+ { pvFrame, mainSprite, stepSprites, arrowSprites, playW, playH, sub: subSelected });
2830
2892
  };
2831
- const chips = optList.map((opt, i) =>
2832
- createCss2Button(`pvChip${i}`, getStgDetailName(opt), () => {
2833
- autoCnt = -g_limitObj.helpPreviewAutoFrames;
2834
- applyOption(opt);
2835
- markChips();
2836
- }, { x: baseX + viewW + 15, y: i * chipH, w: chipW, h: chipH - 2, siz: 12 }, g_cssObj.button_Default)
2837
- );
2838
- multiAppend(area, ...chips);
2839
2893
 
2894
+ // 本体の選択(選択時は自動移動時間を2倍にする)
2895
+ const selectMain = opt => {
2896
+ autoCnt = -g_limitObj.helpPreviewAutoFrames;
2897
+ activeCol = 0;
2898
+ applyOption(opt);
2899
+ markChips();
2900
+ };
2901
+
2902
+ // Typeの選択 (本体がOFF/Defaultのときは、効果が見える基準の選択肢へ切り替える)
2903
+ const selectSub = opt => {
2904
+ autoCnt = -g_limitObj.helpPreviewAutoFrames;
2905
+ activeCol = 1;
2906
+ subSelected = opt;
2907
+ const base = optList[1];
2908
+ applyOption(selected === optList[0] && optList.includes(base) ? base : selected);
2909
+ markChips();
2910
+ };
2911
+
2912
+ // 上下キー: 操作対象の列の選択肢を前後に動かす (端では反対側へ循環)
2840
2913
  const moveOption = _dir => {
2841
2914
  applyOption(optList[nextPos(optList.indexOf(selected), _dir, optList.length)]);
2842
2915
  markChips();
2843
2916
  };
2844
- // 上下キー: 選択肢を前後に動かす (端では反対側へ循環)
2845
2917
  g_helpPreviewMove = _dir => {
2846
- autoCnt = -g_limitObj.helpPreviewAutoFrames;
2847
- moveOption(_dir);
2918
+ if (subUse && activeCol === 1) {
2919
+ selectSub(subList[nextPos(subList.indexOf(subSelected), _dir, subList.length)]);
2920
+ } else {
2921
+ autoCnt = -g_limitObj.helpPreviewAutoFrames;
2922
+ moveOption(_dir);
2923
+ }
2924
+ };
2925
+
2926
+ // 左右キー: 操作対象の列を切り替える (←: 本体、→: Type)
2927
+ g_helpPreviewColumn = _dir => {
2928
+ if (!subUse) return;
2929
+ activeCol = _dir > 0 ? 1 : 0;
2930
+ markChips();
2848
2931
  };
2849
2932
 
2850
2933
  // 初期表示: 現在値 (OFF/Default の場合は最初の非OFFの選択肢)
@@ -4155,7 +4238,10 @@ const createGeneralSettingEx = (_spriteList, _name, { defaultList = [C_FLG_OFF],
4155
4238
  funcEx();
4156
4239
  createExpandedScView(_name);
4157
4240
  },
4158
- title: g_msgObj[`${_name}Type`] ?? ``,
4241
+ // 拡張ボタンの説明文表示は「拡張元」設定のヘルプが長い場合、詳細ヘルプ表示側で表示するため省略する
4242
+ title: isLongHelp(g_msgObj[`${_name}`] ?? ``) || g_helpPreviewDefs[_name] !== undefined
4243
+ ? ``
4244
+ : (g_msgObj[`${_name}Type`] ?? ``),
4159
4245
  }, g_cssObj.button_Default, g_cssObj.button_RevON);
4160
4246
 
4161
4247
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "danoniplus",
3
- "version": "52.0.0",
3
+ "version": "52.1.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",