danoniplus 49.4.2 → 49.6.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/08/12
7
+ * Revised : 2026/08/16
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 49.4.2`;
12
- const g_revisedDate = `2026/08/12`;
11
+ const g_version = `Ver 49.6.0`;
12
+ const g_revisedDate = `2026/08/16`;
13
13
 
14
14
  // カスタム用バージョン (danoni_custom.js 等で指定可)
15
15
  let g_localVersion = ``;
@@ -384,7 +384,7 @@ const g_convFunc = {
384
384
  * @param {string} _checkStr
385
385
  * @param {string} _default
386
386
  * @param {string} [_type='string']
387
- * @returns
387
+ * @returns {number|boolean|string}
388
388
  */
389
389
  const setVal = (_checkStr, _default, _type = C_TYP_STRING) =>
390
390
  hasValN(_checkStr) ? g_convFunc[_type](_checkStr, _default) : _default;
@@ -1570,7 +1570,7 @@ const getFontSize2 = (_str, _maxWidth, { font = getBasicFont(), maxSiz = 14, min
1570
1570
  };
1571
1571
 
1572
1572
  /**
1573
- * 配列中から最も長い文字列を抽出
1573
+ * 配列中から最も長い文字列を抽出(本体では未使用)
1574
1574
  * @param {string[]} _array
1575
1575
  * @returns {string}
1576
1576
  */
@@ -1688,8 +1688,8 @@ const dragDiv = (_divName, { minX = 0, minY = 0, maxX = g_sWidth, maxY = g_sHeig
1688
1688
  const nextY = div.offsetTop + evt.movementY;
1689
1689
  const clampMaxX = (maxX === minX) ? maxX : (maxX - div.offsetWidth);
1690
1690
  const clampMaxY = (maxY === minY) ? maxY : (maxY - div.offsetHeight);
1691
- div.style.left = Math.min(Math.max(nextX, minX), clampMaxX) + 'px';
1692
- div.style.top = Math.min(Math.max(nextY, minY), clampMaxY) + 'px';
1691
+ div.style.left = wUnit(Math.min(Math.max(nextX, minX), clampMaxX));
1692
+ div.style.top = wUnit(Math.min(Math.max(nextY, minY), clampMaxY));
1693
1693
  div.style.position = 'absolute';
1694
1694
  div.draggable = false;
1695
1695
  div.setPointerCapture(evt.pointerId);
@@ -1826,7 +1826,7 @@ const createMultipleSprite = (_baseName, _num, { x = 0, priority = g_transPriori
1826
1826
  for (let j = 0; j <= _num; j++) {
1827
1827
  createEmptySprite(sprite, `${_baseName}${j}`);
1828
1828
  }
1829
- addTransform(_baseName, `root`, `translateX(${x}px)`, priority);
1829
+ addTransform(_baseName, `root`, `translateX(${wUnit(x)})`, priority);
1830
1830
  return sprite;
1831
1831
  };
1832
1832
 
@@ -2296,13 +2296,19 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
2296
2296
  maxDepth = tmpDepth;
2297
2297
  }
2298
2298
 
2299
+ const colorObjFlg = tmpSpriteData[2]?.startsWith(`[c]`) || false;
2300
+ const transformFlg = tmpSpriteData[2]?.startsWith(`[t]`) || false;
2299
2301
  const tmpObj = {
2300
2302
  path: escapeHtml(tmpSpriteData[2] ?? ``, g_escapeStr.escapeCode), // 画像パス or テキスト
2301
2303
  class: escapeHtml(tmpSpriteData[3] ?? ``), // CSSクラス
2302
- left: setVal(tmpSpriteData[4], `0`).includes(`{`) ?
2303
- `${setVal(tmpSpriteData[4], 0)}` : `{${setVal(tmpSpriteData[4], 0)}}`, // X座標
2304
- top: setVal(tmpSpriteData[5], `0`).includes(`{`) ?
2305
- `${setVal(tmpSpriteData[5], 0)}` : `{${setVal(tmpSpriteData[5], 0)}}`, // Y座標
2304
+ left: transformFlg
2305
+ ? setVal(tmpSpriteData[4], 1000, C_TYP_NUMBER) // [t]のみtransformのPriority
2306
+ : setVal(tmpSpriteData[4], `0`).includes(`{`)
2307
+ ? `${setVal(tmpSpriteData[4], 0)}`
2308
+ : `{${setVal(tmpSpriteData[4], 0)}}`, // X座標
2309
+ top: setVal(tmpSpriteData[5], `0`).includes(`{`)
2310
+ ? `${setVal(tmpSpriteData[5], 0)}`
2311
+ : `{${setVal(tmpSpriteData[5], 0)}}`, // Y座標
2306
2312
  width: `${setIntVal(tmpSpriteData[6])}`, // spanタグの場合は font-size
2307
2313
  height: `${escapeHtml(tmpSpriteData[7] ?? ``)}`, // spanタグの場合は color(文字列可)
2308
2314
  opacity: setVal(tmpSpriteData[8], 1, C_TYP_FLOAT),
@@ -2319,7 +2325,6 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
2319
2325
  checkDuplicatedObjects(spriteData[tmpFrame]);
2320
2326
 
2321
2327
  const emptyPatterns = [`[loop]`, `[jump]`];
2322
- const colorObjFlg = tmpSpriteData[2]?.startsWith(`[c]`) || false;
2323
2328
  const spriteFrameData = spriteData[tmpFrame][dataCnts] = {
2324
2329
  depth: tmpDepth,
2325
2330
  };
@@ -2327,9 +2332,15 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
2327
2332
  if (colorObjFlg) {
2328
2333
  // [c]始まりの場合、カラーオブジェクト用の作成準備を行う
2329
2334
  const data = tmpObj.path.slice(`[c]`.length).split(`/`);
2335
+ let objPart = data[0];
2336
+ if (!isNaN(parseInt(data[0]))) {
2337
+ const keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`;
2338
+ objPart = g_keyObj[`stepRtn${keyCtrlPtn}`][data[0]];
2339
+ spriteFrameData.transform = parseInt(data[0]);
2340
+ }
2330
2341
  spriteFrameData.colorObjInfo = {
2331
2342
  x: tmpObj.left, y: tmpObj.top, w: tmpObj.width, h: tmpObj.height,
2332
- rotate: setVal(data[0], `0`), opacity: tmpObj.opacity,
2343
+ rotate: setVal(objPart, `0`), opacity: tmpObj.opacity,
2333
2344
  background: makeColorGradation(setVal(data[1], `#ffffff`), { _defaultColorgrd: false }),
2334
2345
  animationName: tmpObj.animationName,
2335
2346
  animationDuration: `${tmpObj.animationDuration}s`,
@@ -2339,6 +2350,12 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
2339
2350
  if (tmpObj.animationFillMode !== undefined) {
2340
2351
  spriteFrameData.colorObjInfo.animationFillMode = tmpObj.animationFillMode;
2341
2352
  }
2353
+ } else if (transformFlg) {
2354
+ // [t]始まりの場合、レイヤーに対してtransformを掛ける準備を行う
2355
+ const transformData = tmpObj.path.slice(`[t]`.length);
2356
+ spriteFrameData.transform = transformData || ``;
2357
+ spriteFrameData.transformId = tmpObj.class;
2358
+ spriteFrameData.transPriority = tmpObj.left;
2342
2359
 
2343
2360
  } else if (tmpObj.path === ``) {
2344
2361
  spriteFrameData.command = ``;
@@ -2422,6 +2439,10 @@ const drawBaseSpriteData = (_spriteData, _name, _condition = true) => {
2422
2439
  }
2423
2440
  } else {
2424
2441
  if (_condition) {
2442
+ if (_spriteData.colorObjInfo === undefined && _spriteData.transform === undefined) {
2443
+ baseSprite.innerHTML = convertStrToVal(_spriteData.htmlText);
2444
+ return;
2445
+ }
2425
2446
  if (_spriteData.colorObjInfo !== undefined) {
2426
2447
  const colorObjClass = _spriteData.colorObjClass?.split(`/`) ?? [];
2427
2448
  const id = `${_name}${_spriteData.depth}${_spriteData.colorObjId}`;
@@ -2429,8 +2450,32 @@ const drawBaseSpriteData = (_spriteData, _name, _condition = true) => {
2429
2450
  baseSprite.appendChild(
2430
2451
  createColorObject2(id, _spriteData.colorObjInfo, ...colorObjClass)
2431
2452
  );
2432
- } else {
2433
- baseSprite.innerHTML = convertStrToVal(_spriteData.htmlText);
2453
+ }
2454
+ if (_spriteData.transform !== undefined) {
2455
+ const targetId = `${_name}Sprite${_spriteData.depth}`;
2456
+
2457
+ if (!isNaN(parseInt(_spriteData.transform))) {
2458
+ // PlayWindow由来のtransformを継承(別transformId)
2459
+ const transformId = `${_name}${_spriteData.depth}PlayWindow`;
2460
+ const transformData = getTransform(`mainSprite`, `playWindow`);
2461
+
2462
+ if (hasVal(transformData)) {
2463
+ if (transformData !== getTransform(targetId, transformId)) {
2464
+ addTransform(targetId, transformId, transformData, g_transPriority.playWindow);
2465
+ }
2466
+ } else {
2467
+ delTransform(targetId, transformId);
2468
+ }
2469
+ } else {
2470
+ // 明示指定のtransformを適用
2471
+ const transformId = _spriteData.transformId || `${_name}${_spriteData.depth}`;
2472
+
2473
+ if (hasVal(_spriteData.transform)) {
2474
+ addTransform(targetId, transformId, _spriteData.transform, _spriteData.transPriority);
2475
+ } else {
2476
+ delTransform(targetId, transformId);
2477
+ }
2478
+ }
2434
2479
  }
2435
2480
  }
2436
2481
  }
@@ -3507,8 +3552,8 @@ const createSplitCanvases = (_width, _totalHeight) => {
3507
3552
  cvs.height = logicalH * g_dpr;
3508
3553
 
3509
3554
  // ブラウザ上の表示サイズをセット
3510
- cvs.style.width = `${_width}px`;
3511
- cvs.style.height = `${logicalH}px`;
3555
+ cvs.style.width = wUnit(_width);
3556
+ cvs.style.height = wUnit(logicalH);
3512
3557
  cvs.style.display = 'block';
3513
3558
 
3514
3559
  const ctx = cvs.getContext('2d');
@@ -3568,8 +3613,8 @@ const createMinimapHeader = (_config, _keyCtrlPtn, _keyNum) => {
3568
3613
  // 解像度と表示サイズの設定
3569
3614
  canvas.width = logicalWidth * g_dpr;
3570
3615
  canvas.height = headerHeight * g_dpr;
3571
- canvas.style.width = `${logicalWidth}px`;
3572
- canvas.style.height = `${headerHeight}px`;
3616
+ canvas.style.width = wUnit(logicalWidth);
3617
+ canvas.style.height = wUnit(headerHeight);
3573
3618
  canvas.style.display = 'block';
3574
3619
 
3575
3620
  ctx.scale(g_dpr, g_dpr);
@@ -4419,8 +4464,8 @@ const headerConvert = _dosObj => {
4419
4464
  obj.playingY = setIntVal(_dosObj.playingY, g_presetObj.playingY ?? 0);
4420
4465
 
4421
4466
  // ステップゾーン位置
4422
- g_posObj.stepY = (isNaN(parseFloat(_dosObj.stepY)) ? C_STEP_Y : parseFloat(_dosObj.stepY));
4423
- g_posObj.stepYR = (isNaN(parseFloat(_dosObj.stepYR)) ? C_STEP_YR : parseFloat(_dosObj.stepYR));
4467
+ g_posObj.stepY = setVal(_dosObj.stepY, C_STEP_Y, C_TYP_FLOAT);
4468
+ g_posObj.stepYR = setVal(_dosObj.stepYR, C_STEP_YR, C_TYP_FLOAT);
4424
4469
  g_posObj.stepDiffY = g_posObj.stepY - C_STEP_Y;
4425
4470
  g_posObj.distY = obj.playingHeight - C_STEP_Y + g_posObj.stepYR;
4426
4471
  g_posObj.reverseStepY = g_posObj.distY - g_posObj.stepY - g_posObj.stepDiffY - C_ARW_WIDTH;
@@ -4431,18 +4476,18 @@ const headerConvert = _dosObj => {
4431
4476
  obj.baseSpeed = 1 + ((g_posObj.distY - (g_posObj.stepY - C_STEP_Y) * 2) / (500 - C_STEP_Y) - 1) * 0.85;
4432
4477
 
4433
4478
  // 矢印・フリーズアロー判定位置補正
4434
- g_diffObj.arrowJdgX = (isNaN(parseFloat(_dosObj.arrowJdgX)) ? 0 : parseFloat(_dosObj.arrowJdgX));
4435
- g_diffObj.arrowJdgY = (isNaN(parseFloat(_dosObj.arrowJdgY)) ? 0 : parseFloat(_dosObj.arrowJdgY));
4436
- g_diffObj.frzJdgX = (isNaN(parseFloat(_dosObj.frzJdgX)) ? 0 : parseFloat(_dosObj.frzJdgX));
4437
- g_diffObj.frzJdgY = (isNaN(parseFloat(_dosObj.frzJdgY)) ? 0 : parseFloat(_dosObj.frzJdgY));
4479
+ g_diffObj.arrowJdgX = setVal(_dosObj.arrowJdgX, 0, C_TYP_FLOAT);
4480
+ g_diffObj.arrowJdgY = setVal(_dosObj.arrowJdgY, 0, C_TYP_FLOAT);
4481
+ g_diffObj.frzJdgX = setVal(_dosObj.frzJdgX, 0, C_TYP_FLOAT);
4482
+ g_diffObj.frzJdgY = setVal(_dosObj.frzJdgY, 0, C_TYP_FLOAT);
4438
4483
  g_diffInitObj.arrowJdgX = g_diffObj.arrowJdgX;
4439
4484
  g_diffInitObj.arrowJdgY = g_diffObj.arrowJdgY;
4440
4485
  g_diffInitObj.frzJdgX = g_diffObj.frzJdgX;
4441
4486
  g_diffInitObj.frzJdgY = g_diffObj.frzJdgY;
4442
4487
 
4443
4488
  // ショートカット表示位置補正
4444
- g_diffObj.shortcutX = (isNaN(parseFloat(_dosObj.shortcutX)) ? 0 : parseFloat(_dosObj.shortcutX));
4445
- g_diffObj.shortcutY = (isNaN(parseFloat(_dosObj.shortcutY)) ? 0 : parseFloat(_dosObj.shortcutY));
4489
+ g_diffObj.shortcutX = setVal(_dosObj.shortcutX, 0, C_TYP_FLOAT);
4490
+ g_diffObj.shortcutY = setVal(_dosObj.shortcutY, 0, C_TYP_FLOAT);
4446
4491
  g_diffInitObj.shortcutX = g_diffObj.shortcutX;
4447
4492
  g_diffInitObj.shortcutY = g_diffObj.shortcutY;
4448
4493
 
@@ -6011,7 +6056,7 @@ const titleInit = (_initFlg = false) => {
6011
6056
  }, g_lblPosObj.btnComment, g_cssObj.button_Default),
6012
6057
  );
6013
6058
  if (g_headerObj.musicSelectUse && getQueryParamVal(`scoreId`) === null) {
6014
- lblComment.style.height = `${g_sHeight - 100}px`;
6059
+ lblComment.style.height = wUnit(g_sHeight - 100);
6015
6060
  }
6016
6061
  setUserSelect(lblComment.style, `text`);
6017
6062
  }
@@ -6555,7 +6600,7 @@ const changeMSelect = (_num, _initFlg = false) => {
6555
6600
  g_lblPosObj.lblDifNameInfoM.w, { maxSiz: g_lblPosObj.lblDifNameInfoM.siz }));
6556
6601
  lblDiffiInfoM.style.fontSize = lblDifNameInfoM.style.fontSize;
6557
6602
  lblNotesInfoM.style.fontSize = lblDifNameInfoM.style.fontSize;
6558
- lblCommentInfoM.style.top = `${getStrHeight(lblDifNameInfoM.innerHTML, parseFloat(lblDifNameInfoM.style.fontSize))}px`;
6603
+ lblCommentInfoM.style.top = wUnit(getStrHeight(lblDifNameInfoM.innerHTML, parseFloat(lblDifNameInfoM.style.fontSize)));
6559
6604
  lblCommentInfoM.innerHTML = convertStrToVal(g_headerObj[`commentVal${g_settings.musicIdxNum}`]);
6560
6605
  lblCommentM.scrollTop = 0;
6561
6606
 
@@ -8012,12 +8057,12 @@ const drawMinimap = (_scoreId, { _initFlg = false, _fadeinFlg = false } = {}) =>
8012
8057
 
8013
8058
  // --- ヘッダー部分 ---
8014
8059
  const detailMiniMapHeader = createEmptySprite(detailMiniMap, `detailMiniMapHeader`, g_windowObj.detailMiniMapHeader);
8015
- $id(`detailMiniMapHeader`).top = (g_stateObj.miniMapRevFlg ? 230 + g_sHeight - 500 : 0) + `px`;
8060
+ $id(`detailMiniMapHeader`).top = wUnit(g_stateObj.miniMapRevFlg ? 230 + g_sHeight - 500 : 0);
8016
8061
  detailMiniMapHeader.appendChild(g_detailObj.scoreMinimapHeader[kPtn]);
8017
8062
 
8018
8063
  // --- メイン(譜面)部分 ---
8019
8064
  const detailMiniMapSub = createEmptySprite(detailMiniMap, `detailMiniMapSub`, g_windowObj.detailMiniMapSub);
8020
- $id(`detailMiniMapSub`).top = (g_stateObj.miniMapRevFlg ? 0 : 15) + `px`;
8065
+ $id(`detailMiniMapSub`).top = wUnit(g_stateObj.miniMapRevFlg ? 0 : 15);
8021
8066
 
8022
8067
  Object.assign(detailMiniMapSub.style, {
8023
8068
  overflowX: 'hidden',
@@ -9854,17 +9899,16 @@ const showToast = _msg => {
9854
9899
  if (existing) existing.remove();
9855
9900
 
9856
9901
  const toast = createDivCss2Label(`previewToast`, _msg, {
9857
- x: g_btnX() + g_btnWidth() / 2, y: 50, w: g_btnWidth() / 2, h: 10,
9902
+ x: g_btnX() + g_btnWidth() / 2, y: 50, w: g_btnWidth() / 2, h: 10, siz: 12,
9858
9903
  transform: `translateX(-50%)`,
9859
9904
  background: `rgba(0,40,80,0.92)`,
9860
9905
  color: `#aaddff`,
9861
9906
  border: `1px solid #3366aa`,
9862
9907
  borderRadius: `6px`,
9863
9908
  padding: `6px 16px`,
9864
- fontSize: `12px`,
9865
9909
  fontFamily: `monospace`,
9866
9910
  whiteSpace: `nowrap`,
9867
- pointerEvents: `none`,
9911
+ pointerEvents: C_DIS_NONE,
9868
9912
  transition: `opacity 0.4s`,
9869
9913
  opacity: `1`,
9870
9914
  });
@@ -10260,56 +10304,6 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
10260
10304
  ? g_lblNameObj.kcShuffleDesc : g_lblNameObj.kcNoShuffleDesc),
10261
10305
  );
10262
10306
 
10263
- // キーの一覧を表示
10264
- const keyconSprite = createEmptySprite(divRoot, `keyconSprite`, g_windowObj.keyconSprite);
10265
- const tkObj = getKeyInfo();
10266
- const [keyCtrlPtn, keyNum, posMax, divideCnt] =
10267
- [tkObj.keyCtrlPtn, tkObj.keyNum, tkObj.posMax, tkObj.divideCnt];
10268
-
10269
- g_keyCopyLists.simpleDef.forEach(header => updateKeyInfo(header, keyCtrlPtn));
10270
- addTransform(`keyconSprite`, `root`, `scale(${g_keyObj.scale})`, g_transPriority.scale);
10271
- keyconSprite.style.height = `${parseFloat(keyconSprite.style.height) / ((1 + g_keyObj.scale) / 2)}px`;
10272
- const kWidth = parseInt(keyconSprite.style.width);
10273
- changeSetColor();
10274
-
10275
- const maxLeftPos = Math.max(divideCnt, posMax - divideCnt - 2) / 2;
10276
- const maxLeftX = Math.min(0, (kWidth - C_ARW_WIDTH) / 2 - maxLeftPos * g_keyObj.blank);
10277
-
10278
- g_keycons.cursorNumList = [...Array(keyNum).keys()].map(i => i);
10279
- const configKeyGroupList = g_headerObj.keyGroupOrder[g_stateObj.scoreId] ??
10280
- g_keyObj[`keyGroupOrder${keyCtrlPtn}`] ?? tkObj.keyGroupList;
10281
- g_keycons.colorCursorNum = 0;
10282
-
10283
- // 色変化中の初期色を取得(矢印枠のみ)
10284
- const arrowColorTmp = g_detailObj.miniMapParams[g_stateObj.scoreId]._scoreObj.ncolorData.Arrow;
10285
- const arrowColors = Array.from({ length: Math.ceil(arrowColorTmp.length / 5) }, (_, i) =>
10286
- arrowColorTmp.slice(i * 5, i * 5 + 5)
10287
- ).filter(val => val[0] === 0);
10288
- const initColors = [];
10289
- arrowColors.forEach(val => {
10290
- const laneToken = val[1];
10291
- const laneStr = String(laneToken ?? ``);
10292
- if (laneStr.startsWith('g')) {
10293
- // g付きの場合は矢印グループから対象の矢印番号を検索
10294
- const groupVal = setIntVal(laneStr.slice(1));
10295
- for (let j = 0; j < tkObj.keyNum; j++) {
10296
- if (g_keyObj[`color${tkObj.keyCtrlPtn}`][j] === groupVal) {
10297
- initColors[j] = makeColorGradation(val[2]);
10298
- }
10299
- }
10300
- } else {
10301
- const laneIdx = setIntVal(laneToken, -1);
10302
- if (laneIdx >= 0 && laneIdx < tkObj.keyNum) {
10303
- initColors[laneIdx] = makeColorGradation(val[2]);
10304
- }
10305
- }
10306
- });
10307
- if (_initFlg) {
10308
- g_baseColorGrs = {};
10309
- const colorKey = Object.keys(g_keyObj).filter(val => val.startsWith(`color${g_keyObj.currentKey}`));
10310
- colorKey.forEach(val => g_baseColorGrs[val] = g_keyObj[val]);
10311
- }
10312
-
10313
10307
  /**
10314
10308
  * keyconSpriteのスクロール位置調整
10315
10309
  * @param {number} _targetX
@@ -10401,7 +10395,7 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
10401
10395
  } else {
10402
10396
  changeTmpOneColor(_j);
10403
10397
  }
10404
- adjustScrollPoint(parseFloat($id(`arrow${_j}`).left));
10398
+ adjustScrollPoint(parseFloat($id(`keyGroup${_j}`).left));
10405
10399
  };
10406
10400
 
10407
10401
  /**
@@ -10427,17 +10421,109 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
10427
10421
  } else {
10428
10422
  changeTmpOneShuffle(_j);
10429
10423
  }
10430
- adjustScrollPoint(parseFloat($id(`arrow${_j}`).left));
10424
+ adjustScrollPoint(parseFloat($id(`keyGroup${_j}`).left));
10431
10425
  };
10432
10426
 
10427
+ /**
10428
+ * 指定関数群だけを抽出したtransform文字列を作成
10429
+ * @param {string} _cssString
10430
+ * @param {string[]} _funcNames
10431
+ * @returns {string}
10432
+ */
10433
+ const extractTransformFuncs = (_cssString, _funcNames) => {
10434
+ const pattern = new RegExp(`\\b(${_funcNames.join(`|`)})\\([^)]*\\)`, `g`);
10435
+ return (_cssString.match(pattern) || []).join(` `);
10436
+ };
10437
+
10438
+ /**
10439
+ * 対象レーンのレイヤー番号を取得
10440
+ * @param {number} _j
10441
+ * @param {number} _posj
10442
+ * @returns {number}
10443
+ */
10444
+ const getLayerIdx = (_j, _posj) => {
10445
+ const baseLayer = g_keyObj[`layerGroup${keyCtrlPtn}`]?.[_j] || 0;
10446
+ const rowFlg = Number(_posj > divideCnt); // reverse/scrollDirは考慮せず固定
10447
+ return baseLayer * 2 + rowFlg;
10448
+ };
10449
+
10450
+ /**
10451
+ * 対象レイヤーの回転変形を取得
10452
+ * @param {string} _keyCtrlPtn
10453
+ * @returns {string[]}
10454
+ */
10455
+ const getLayerRotateParts = _keyCtrlPtn => {
10456
+ const raw = g_keyObj[`layerTrans${_keyCtrlPtn}`]?.[0] ?? [``, ``, ``, ``];
10457
+ return raw.map(trans => trans === `` ? `` : extractTransformFuncs(trans, [`rotate`, `rotateX`, `rotateY`, `rotateZ`, `rotate3d`]));
10458
+ };
10459
+
10460
+ // キーの一覧を表示するための準備
10461
+ const C_LAYER_Y_OFFSET = 10; // baseLayerごとの縦オフセット量
10462
+ const keyconSprite = createEmptySprite(divRoot, `keyconSprite`, g_windowObj.keyconSprite);
10463
+ const tkObj = getKeyInfo();
10464
+ const [keyCtrlPtn, keyNum, posMax, divideCnt] =
10465
+ [tkObj.keyCtrlPtn, tkObj.keyNum, tkObj.posMax, tkObj.divideCnt];
10466
+
10467
+ g_keyCopyLists.simpleDef.forEach(header => updateKeyInfo(header, keyCtrlPtn));
10468
+ addTransform(`keyconSprite`, `root`, `scale(${g_keyObj.scale})`, g_transPriority.scale);
10469
+ keyconSprite.style.height = wUnit(parseFloat(keyconSprite.style.height) / ((1 + g_keyObj.scale) / 2));
10470
+ const kWidth = parseInt(keyconSprite.style.width);
10471
+ changeSetColor();
10472
+
10473
+ const maxLeftPos = Math.max(divideCnt, posMax - divideCnt - 2) / 2;
10474
+ const maxLeftX = Math.min(0, (kWidth - C_ARW_WIDTH) / 2 - maxLeftPos * g_keyObj.blank);
10475
+
10476
+ g_keycons.cursorNumList = [...Array(keyNum).keys()].map(i => i);
10477
+ const configKeyGroupList = g_headerObj.keyGroupOrder[g_stateObj.scoreId] ??
10478
+ g_keyObj[`keyGroupOrder${keyCtrlPtn}`] ?? tkObj.keyGroupList;
10479
+ g_keycons.colorCursorNum = 0;
10480
+
10481
+ // 色変化中の初期色を取得(矢印枠のみ)
10482
+ const arrowColorTmp = g_detailObj.miniMapParams[g_stateObj.scoreId]._scoreObj.ncolorData.Arrow;
10483
+ const arrowColors = Array.from({ length: Math.ceil(arrowColorTmp.length / 5) }, (_, i) =>
10484
+ arrowColorTmp.slice(i * 5, i * 5 + 5)
10485
+ ).filter(val => val[0] === 0);
10486
+ const initColors = [];
10487
+ arrowColors.forEach(val => {
10488
+ const laneToken = val[1];
10489
+ const laneStr = String(laneToken ?? ``);
10490
+ if (laneStr.startsWith('g')) {
10491
+ // g付きの場合は矢印グループから対象の矢印番号を検索
10492
+ const groupVal = setIntVal(laneStr.slice(1));
10493
+ for (let j = 0; j < tkObj.keyNum; j++) {
10494
+ if (g_keyObj[`color${tkObj.keyCtrlPtn}`][j] === groupVal) {
10495
+ initColors[j] = makeColorGradation(val[2]);
10496
+ }
10497
+ }
10498
+ } else {
10499
+ const laneIdx = setIntVal(laneToken, -1);
10500
+ if (laneIdx >= 0 && laneIdx < tkObj.keyNum) {
10501
+ initColors[laneIdx] = makeColorGradation(val[2]);
10502
+ }
10503
+ }
10504
+ });
10505
+ if (_initFlg) {
10506
+ g_baseColorGrs = {};
10507
+ const colorKey = Object.keys(g_keyObj).filter(val => val.startsWith(`color${g_keyObj.currentKey}`));
10508
+ colorKey.forEach(val => g_baseColorGrs[val] = g_keyObj[val]);
10509
+ }
10510
+
10511
+ const layerParts = getLayerRotateParts(keyCtrlPtn);
10512
+ g_keycons.layerIdxList = [];
10513
+
10514
+ // キーコンフィグの矢印表示
10433
10515
  const addLeft = (maxLeftX === 0 ? 0 : - maxLeftX + g_limitObj.kcColorPickerX);
10434
10516
  for (let j = 0; j < keyNum; j++) {
10435
10517
 
10436
10518
  const posj = g_keyObj[`pos${keyCtrlPtn}`][j];
10437
10519
  const stdPos = posj - ((posj > divideCnt ? posMax : 0) + divideCnt) / 2;
10520
+ const baseLayer = g_keyObj[`layerGroup${keyCtrlPtn}`]?.[j] || 0;
10521
+ const layerIdx = getLayerIdx(j, posj); // baseLayer*2 + Number(posj > divideCnt)
10522
+ const layerRotate = layerParts[layerIdx] || ``;
10523
+ g_keycons.layerIdxList[j] = layerIdx;
10438
10524
 
10439
10525
  const keyconX = g_keyObj.blank * stdPos + (kWidth - C_ARW_WIDTH) / 2 + addLeft;
10440
- const keyconY = C_KYC_HEIGHT * (Number(posj > divideCnt)) + 12;
10526
+ const keyconY = C_KYC_HEIGHT * (Number(posj > divideCnt)) + 12 + baseLayer * C_LAYER_Y_OFFSET;
10441
10527
  const colorPos = g_keyObj[`color${keyCtrlPtn}`][j];
10442
10528
  const arrowColor = getKeyConfigColor(j, colorPos);
10443
10529
 
@@ -10447,16 +10533,22 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
10447
10533
  cxtFunc: () => changeTmpColor(j, -1),
10448
10534
  }, g_cssObj.button_Default_NoColor, g_cssObj.title_base)
10449
10535
  );
10536
+
10537
+ // キーごとの親コンテナ(矢印要素を囲う)
10538
+ const keyGroup = createEmptySprite(keyconSprite, `keyGroup${j}`, { x: keyconX, y: keyconY, w: C_ARW_WIDTH, h: C_ARW_WIDTH });
10539
+ if (layerRotate !== ``) {
10540
+ keyGroup.style.transform = layerRotate; // ここだけがlayer変形の適用箇所
10541
+ }
10450
10542
  // キーコンフィグ表示用の矢印・おにぎりを表示
10451
- multiAppend(keyconSprite,
10543
+ multiAppend(keyGroup,
10452
10544
  // 矢印の塗り部分
10453
10545
  createColorObject2(`arrowShadow${j}`, {
10454
- x: keyconX, y: keyconY, background: hasVal(g_headerObj[`setShadowColor${g_colorType}`][colorPos]) ? getShadowColor(colorPos, arrowColor) : ``,
10546
+ background: hasVal(g_headerObj[`setShadowColor${g_colorType}`][colorPos]) ? getShadowColor(colorPos, arrowColor) : ``,
10455
10547
  rotate: g_keyObj[`stepRtn${keyCtrlPtn}_${g_keycons.stepRtnGroupNum}`][j], styleName: `Shadow`,
10456
10548
  }),
10457
10549
  // 矢印本体
10458
10550
  createColorObject2(`arrow${j}`, {
10459
- x: keyconX, y: keyconY, background: arrowColor, rotate: g_keyObj[`stepRtn${keyCtrlPtn}_${g_keycons.stepRtnGroupNum}`][j],
10551
+ background: arrowColor, rotate: g_keyObj[`stepRtn${keyCtrlPtn}_${g_keycons.stepRtnGroupNum}`][j],
10460
10552
  }),
10461
10553
  );
10462
10554
  if (g_headerObj.shuffleUse && g_keyObj[`shuffle${keyCtrlPtn}`] !== undefined) {
@@ -10716,10 +10808,11 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
10716
10808
  const setKeyConfigCursor = () => {
10717
10809
  const posj = g_keyObj[`pos${keyCtrlPtn}`][g_currentj];
10718
10810
  const stdPos = posj - ((posj > divideCnt ? posMax : 0) + divideCnt) / 2;
10811
+ const baseLayer = g_keyObj[`layerGroup${keyCtrlPtn}`]?.[g_currentj] || 0;
10719
10812
 
10720
10813
  const nextLeft = (kWidth - C_ARW_WIDTH) / 2 + g_keyObj.blank * stdPos + addLeft - 10;
10721
10814
  cursor.style.left = wUnit(nextLeft);
10722
- cursor.style.top = wUnit(C_KYC_HEIGHT * Number(posj > divideCnt) + 57 + C_KYC_REPHEIGHT * g_currentk);
10815
+ cursor.style.top = wUnit(C_KYC_HEIGHT * Number(posj > divideCnt) + 57 + C_KYC_REPHEIGHT * g_currentk + baseLayer * C_LAYER_Y_OFFSET);
10723
10816
  g_kcType = (g_currentk === 0 ? `Main` : `Replaced`);
10724
10817
 
10725
10818
  // 次の位置が見えなくなったらkeyconSpriteの位置を調整する
@@ -11187,10 +11280,10 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
11187
11280
  g_headerObj[`key${selectedKc}Def`] = setKey;
11188
11281
  document.getElementById(`sc${selectedKc}`).textContent = getScMsg[selectedKc]();
11189
11282
  document.getElementById(`sc${selectedKc}`).style.fontSize =
11190
- `${getFontSize2(getScMsg[selectedKc](), g_btnWidth(5 / 12) - 40, { maxSiz: g_limitObj.mainSiz })}px`;
11283
+ wUnit(getFontSize2(getScMsg[selectedKc](), g_btnWidth(5 / 12) - 40, { maxSiz: g_limitObj.mainSiz }));
11191
11284
  if (g_isMac) {
11192
11285
  scTitleBack.textContent = getScMsg.TitleBack();
11193
- scTitleBack.style.fontSize = `${getFontSize2(getScMsg.TitleBack(), g_btnWidth(5 / 12) - 40, { maxSiz: g_limitObj.mainSiz })}px`;
11286
+ scTitleBack.style.fontSize = wUnit(getFontSize2(getScMsg.TitleBack(), g_btnWidth(5 / 12) - 40, { maxSiz: g_limitObj.mainSiz }));
11194
11287
  }
11195
11288
  changeConfigColor(document.getElementById(`sc${selectedKc}`),
11196
11289
  g_headerObj[`key${selectedKc}`] === g_headerObj[`key${selectedKc}Def2`] ?
@@ -11280,6 +11373,7 @@ const completeTransKeyPtn = (_keyList) => {
11280
11373
  });
11281
11374
  };
11282
11375
 
11376
+ // KeyLockボタンを押したときの表示切替
11283
11377
  const toggleKcDesc = () => {
11284
11378
  if (document.getElementById(`kcDesc`) !== null) {
11285
11379
  kcDesc.textContent = getKcDescMsg();
@@ -11290,11 +11384,13 @@ const toggleKcDesc = () => {
11290
11384
  }
11291
11385
  };
11292
11386
 
11387
+ // KeyLockボタンの表示文字列を取得
11293
11388
  const getKcDescMsg = () =>
11294
11389
  g_stateObj.keyLockFlg
11295
11390
  ? g_lblNameObj.kcNonDesc
11296
11391
  : g_lblNameObj.kcDesc.split(`{0}`).join(g_kCd[C_KEY_RETRY]).split(`{1}:`).join(g_isMac ? `` : `Delete:`);
11297
11392
 
11393
+ // KeyLockボタンで使用する絵文字の取得
11298
11394
  const getKeyLockName = () =>
11299
11395
  `${g_lblNameObj.b_keyLock}${g_stateObj.keyLockFlg ? g_emojiObj.locked : g_emojiObj.unlocked}`;
11300
11396
 
@@ -11620,6 +11716,8 @@ const keyconfigKeyboardPreview = (() => {
11620
11716
 
11621
11717
  /**
11622
11718
  * Canvasの共通初期化処理
11719
+ * @param {HTMLCanvasElement} canvas
11720
+ * @returns {CanvasRenderingContext2D|null}
11623
11721
  */
11624
11722
  const setupCanvasContext = (canvas) => {
11625
11723
  if (!canvas) return null;
@@ -11634,6 +11732,15 @@ const keyconfigKeyboardPreview = (() => {
11634
11732
  return ctx;
11635
11733
  };
11636
11734
 
11735
+ /**
11736
+ * 円角矩形を描画する
11737
+ * @param {CanvasRenderingContext2D} ctx
11738
+ * @param {number} x
11739
+ * @param {number} y
11740
+ * @param {number} w
11741
+ * @param {number} h
11742
+ * @param {number} r
11743
+ */
11637
11744
  const roundRect = (ctx, x, y, w, h, r) => {
11638
11745
  ctx.beginPath();
11639
11746
  ctx.moveTo(x + r, y);
@@ -12576,7 +12683,7 @@ const applyShuffle = (_keyNum, _shuffleGroup, _style) => {
12576
12683
  * @param {number[]} _group
12577
12684
  * @param {number} _i
12578
12685
  * @param {number} _divideNum
12579
- * @returns
12686
+ * @returns {number[][]}
12580
12687
  */
12581
12688
  const swapGroupNums = (_style, _group, _i, _divideNum) => {
12582
12689
  if (_group.length % _divideNum === 0) {
@@ -12750,7 +12857,7 @@ const applySRandom = (_keyNum, _shuffleGroup, _arrowHeader, _frzHeader) => {
12750
12857
  * @param {string} [_dummyNo] ダミー用譜面番号添え字
12751
12858
  * @param {string} [_keyCtrlPtn] 選択キー及びパターン
12752
12859
  * @param {boolean} [_scoreAnalyzeFlg=false] 譜面詳細データのために必要分で読込を中断
12753
- * @returns
12860
+ * @returns {object} 矢印・フリーズアロー・速度/色変化データの格納オブジェクト
12754
12861
  */
12755
12862
  const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
12756
12863
  _keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`, _scoreAnalyzeFlg = false) => {
@@ -12893,7 +13000,7 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
12893
13000
  * - 個別・全体色変化を一体で管理するため通常の配列で返却
12894
13001
  * @param {string} _header
12895
13002
  * @param {number} _scoreNo
12896
- * @returns
13003
+ * @returns {any[][]}
12897
13004
  */
12898
13005
  const setColor2Data = (_header, _scoreNo) => {
12899
13006
  const dosColorData = getRefData(_header, `${_scoreNo}_data`);
@@ -13026,7 +13133,7 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
13026
13133
  * 例) |backA2_data=back_data| -> back_dataで定義された値を使用
13027
13134
  * @param {string} _header
13028
13135
  * @param {string} _dataName
13029
- * @returns
13136
+ * @returns {string|undefined}
13030
13137
  */
13031
13138
  const getRefData = (_header, _dataName) => {
13032
13139
  const data = _dosObj[`${_header}${_dataName}`];
@@ -13083,7 +13190,7 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
13083
13190
  /**
13084
13191
  * 歌詞データの分解
13085
13192
  * @param {string} _scoreNo
13086
- * @returns
13193
+ * @returns {string[][]}
13087
13194
  */
13088
13195
  const makeWordData = _scoreNo => {
13089
13196
  const wordDataList = [];
@@ -13184,7 +13291,7 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
13184
13291
  * @param {string} _header
13185
13292
  * @param {string} _scoreNo 譜面番号
13186
13293
  * @param {string[]} [object.resultTypes] リザルトモーションの種類 (result, failedB, failedS)
13187
- * @returns
13294
+ * @returns {any[][]}
13188
13295
  */
13189
13296
  const makeBackgroundData = (_header, _scoreNo, { resultTypes = [] } = {}) => {
13190
13297
  const dataList = [];
@@ -13324,6 +13431,7 @@ const calcLifeVals = _allArrows => {
13324
13431
  * ライフ回復量・ダメージ量の算出
13325
13432
  * @param {number} _val
13326
13433
  * @param {number} _allArrows
13434
+ * @returns {number}
13327
13435
  */
13328
13436
  const calcLifeVal = (_val, _allArrows) => _val * g_headerObj.maxLifeVal / _allArrows;
13329
13437
 
@@ -13443,6 +13551,7 @@ const setSpeedOnFrame = (_speedData, _lastFrame) => {
13443
13551
  /**
13444
13552
  * Motionオプション適用時の矢印別の速度設定
13445
13553
  * - 矢印が表示される最大フレーム数を 101フレーム と定義。
13554
+ * @returns {number[]}
13446
13555
  */
13447
13556
  const setMotionOnFrame = () => g_motionFunc.get(g_stateObj.motion)(fillArray(101));
13448
13557
 
@@ -13787,7 +13896,7 @@ const pushArrows = (_dataObj, _speedOnFrame, _firstArrivalFrame) => {
13787
13896
  * 歌詞表示、背景・マスク表示のフェードイン時調整処理
13788
13897
  * @param {string} _type
13789
13898
  * @param {object} _data
13790
- * @returns
13899
+ * @returns {object}
13791
13900
  */
13792
13901
  const calcAnimationData = (_type, _data) => {
13793
13902
 
@@ -14720,15 +14829,15 @@ const mainInit = () => {
14720
14829
  }
14721
14830
 
14722
14831
  addTransform(`mainSprite`, `root`, `scale(${g_workObj.scale})`, g_transPriority.scale);
14723
- addTransform(`mainSprite`, `main`, `translateX(${g_workObj.playingX}px) translateY(${g_posObj.stepY - C_STEP_Y + g_headerObj.playingY}px)`, g_transPriority.base);
14832
+ addTransform(`mainSprite`, `main`, `translateX(${wUnit(g_workObj.playingX)}) translateY(${wUnit(g_posObj.stepY - C_STEP_Y + g_headerObj.playingY)})`, g_transPriority.base);
14724
14833
 
14725
14834
  // 曲情報・判定カウント用スプライトを作成(メインスプライトより上位)
14726
14835
  const infoSprite = createEmptySprite(divRoot, `infoSprite`, mainCommonPos);
14727
- addTransform(`infoSprite`, `main`, `translateX(${g_workObj.playingX}px) translateY(${g_headerObj.playingY}px)`, g_transPriority.base);
14836
+ addTransform(`infoSprite`, `main`, `translateX(${wUnit(g_workObj.playingX)}) translateY(${wUnit(g_headerObj.playingY)})`, g_transPriority.base);
14728
14837
 
14729
14838
  // 判定系スプライトを作成(メインスプライトより上位)
14730
14839
  const judgeSprite = createEmptySprite(divRoot, `judgeSprite`, mainCommonPos);
14731
- addTransform(`judgeSprite`, `main`, `translateX(${g_workObj.playingX}px) translateY(${g_headerObj.playingY}px)`, g_transPriority.base);
14840
+ addTransform(`judgeSprite`, `main`, `translateX(${wUnit(g_workObj.playingX)}) translateY(${wUnit(g_headerObj.playingY)})`, g_transPriority.base);
14732
14841
  const tkObj = getKeyInfo();
14733
14842
  const [keyCtrlPtn, keyNum] = [tkObj.keyCtrlPtn, tkObj.keyNum];
14734
14843
 
@@ -15593,7 +15702,7 @@ const mainInit = () => {
15593
15702
  const setArrowYCondition = `${String(g_attrObj[arrowName].movLockFlg)}_${String(initManualFlg)}`;
15594
15703
  setArrowY.get(setArrowYCondition)(arrowName, firstPosY, stepY);
15595
15704
  if (!initManualFlg) {
15596
- addTransform(arrowName, `rootX`, `translateX(${g_workObj.stepX[_j]}px)`);
15705
+ addTransform(arrowName, `rootX`, `translateX(${wUnit(g_workObj.stepX[_j])})`);
15597
15706
  }
15598
15707
 
15599
15708
  /**
@@ -15783,7 +15892,7 @@ const mainInit = () => {
15783
15892
  const setArrowYCondition = `${String(g_attrObj[frzName].movLockFlg)}_${String(initManualFlg)}`;
15784
15893
  setArrowY.get(setArrowYCondition)(frzName, firstPosY, stepY);
15785
15894
  if (!initManualFlg) {
15786
- addTransform(frzName, `rootX`, `translateX(${g_workObj.stepX[_j]}px)`);
15895
+ addTransform(frzName, `rootX`, `translateX(${wUnit(g_workObj.stepX[_j])})`);
15787
15896
  }
15788
15897
 
15789
15898
  safeExecuteCustomHooks(`g_customJsObj.makeFrzArrow`, g_customJsObj.makeFrzArrow, _attrs, frzName, _name, _arrowCnt);
@@ -16299,20 +16408,20 @@ const changeAppearanceFilter = (_num = 10) => {
16299
16408
  $id(`arrowSprite${topNum + j}`).clipPath = topShape;
16300
16409
  $id(`arrowSprite${bottomNum + j}`).clipPath = bottomShape;
16301
16410
 
16302
- addTransform(`filterBar${topNum + j}`, `appearance`, `translateY(${parseFloat($id(`arrowSprite${j}`).top) + topDist}px)`, g_transPriority.layer);
16303
- addTransform(`filterBar${bottomNum + j}`, `appearance`, `translateY(${parseFloat($id(`arrowSprite${j + 1}`).top) + bottomDist}px)`, g_transPriority.layer);
16411
+ addTransform(`filterBar${topNum + j}`, `appearance`, `translateY(${wUnit(parseFloat($id(`arrowSprite${j}`).top) + topDist)})`, g_transPriority.layer);
16412
+ addTransform(`filterBar${bottomNum + j}`, `appearance`, `translateY(${wUnit(parseFloat($id(`arrowSprite${j + 1}`).top) + bottomDist)})`, g_transPriority.layer);
16304
16413
 
16305
16414
  if (doubleFilterFlg) {
16306
- addTransform(`filterBar${bottomNum + j}_HS`, `appearance`, `translateY(${parseFloat($id(`arrowSprite${j}`).top) + bottomDist}px)`, g_transPriority.layer);
16307
- addTransform(`filterBar${topNum + j}_HS`, `appearance`, `translateY(${parseFloat($id(`arrowSprite${j + 1}`).top) + topDist}px)`, g_transPriority.layer);
16415
+ addTransform(`filterBar${bottomNum + j}_HS`, `appearance`, `translateY(${wUnit(parseFloat($id(`arrowSprite${j}`).top) + bottomDist)})`, g_transPriority.layer);
16416
+ addTransform(`filterBar${topNum + j}_HS`, `appearance`, `translateY(${wUnit(parseFloat($id(`arrowSprite${j + 1}`).top) + topDist)})`, g_transPriority.layer);
16308
16417
  }
16309
16418
  }
16310
16419
 
16311
16420
  // フィルターバーのパーセント表示(フィルターバーが複数表示されるなど複雑なため、最初の階層グループの位置に追従)
16312
16421
  if (g_appearanceRanges.includes(g_stateObj.appearance)) {
16313
16422
  const currentBarNum = g_hidSudObj.std[g_stateObj.appearance][g_stateObj.reverse];
16314
- addTransform(`filterView`, `appearance`, `translateY(${parseFloat($id(`arrowSprite${currentBarNum % 2}`).top) +
16315
- (currentBarNum % 2 === 0 ? bottomDist : topDist)}px)`, g_transPriority.layer);
16423
+ addTransform(`filterView`, `appearance`, `translateY(${wUnit(parseFloat($id(`arrowSprite${currentBarNum % 2}`).top) +
16424
+ (currentBarNum % 2 === 0 ? bottomDist : topDist))})`, g_transPriority.layer);
16316
16425
  filterView.textContent = `${_num}%`;
16317
16426
  g_hidSudObj.filterPos = _num;
16318
16427
  }
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2019/11/19
8
- * Revised : 2026/08/06 (v49.4.0)
8
+ * Revised : 2026/08/16 (v49.6.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -163,8 +163,8 @@ const C_TYP_CALC = `calc`;
163
163
  let [g_sWidth, g_sHeight] = [
164
164
  setVal($id(`canvas-frame`).width, 500, C_TYP_FLOAT), setVal($id(`canvas-frame`).height, 500, C_TYP_FLOAT)
165
165
  ];
166
- $id(`canvas-frame`).width = `${Math.max(g_sWidth, 500)}px`;
167
- $id(`canvas-frame`).height = `${Math.max(g_sHeight, 500)}px`;
166
+ $id(`canvas-frame`).width = wUnit(Math.max(g_sWidth, 500));
167
+ $id(`canvas-frame`).height = wUnit(Math.max(g_sHeight, 500));
168
168
  $id(`canvas-frame`).margin = C_DIS_AUTO;
169
169
 
170
170
  const g_btnWidth = (_multi = 1) => Math.min(g_sWidth, g_limitObj.btnBaseWidth) * _multi;
@@ -1615,7 +1615,7 @@ const addX = (_id, _typeId, _x = 0, { overwrite = false, priority = 1000 } = {})
1615
1615
  }
1616
1616
  if (g_posXs[_id].get(_typeId) !== _x) {
1617
1617
  g_posXs[_id].set(_typeId, _x);
1618
- addTransform(_id, `posX`, `translateX(${sumData(Array.from(g_posXs[_id].values()))}px)`, priority);
1618
+ addTransform(_id, `posX`, `translateX(${wUnit(sumData(Array.from(g_posXs[_id].values())))})`, priority);
1619
1619
  }
1620
1620
  };
1621
1621
 
@@ -1636,7 +1636,7 @@ const addY = (_id, _typeId, _y = 0, { overwrite = false, priority = 1000 } = {})
1636
1636
  }
1637
1637
  if (g_posYs[_id].get(_typeId) !== _y) {
1638
1638
  g_posYs[_id].set(_typeId, _y);
1639
- addTransform(_id, `posY`, `translateY(${sumData(Array.from(g_posYs[_id].values()))}px)`, priority);
1639
+ addTransform(_id, `posY`, `translateY(${wUnit(sumData(Array.from(g_posYs[_id].values())))})`, priority);
1640
1640
  }
1641
1641
  };
1642
1642
 
@@ -1653,7 +1653,7 @@ const delX = (_id, _typeId) => {
1653
1653
  return;
1654
1654
  }
1655
1655
  const priority = g_transforms[_id]?.get(`posX`)?.priority ?? 1000;
1656
- addTransform(_id, `posX`, `translateX(${sumData(Array.from(g_posXs[_id].values()))}px)`, priority);
1656
+ addTransform(_id, `posX`, `translateX(${wUnit(sumData(Array.from(g_posXs[_id].values())))})`, priority);
1657
1657
  };
1658
1658
 
1659
1659
  /**
@@ -1669,7 +1669,7 @@ const delY = (_id, _typeId) => {
1669
1669
  return;
1670
1670
  }
1671
1671
  const priority = g_transforms[_id]?.get(`posY`)?.priority ?? 1000;
1672
- addTransform(_id, `posY`, `translateY(${sumData(Array.from(g_posYs[_id].values()))}px)`, priority);
1672
+ addTransform(_id, `posY`, `translateY(${wUnit(sumData(Array.from(g_posYs[_id].values())))})`, priority);
1673
1673
  };
1674
1674
 
1675
1675
  /**
@@ -1866,7 +1866,7 @@ const g_stepAreaFunc = new Map([
1866
1866
  ['Halfway', () => {
1867
1867
  g_arrowGroupSprite.forEach(sprite => {
1868
1868
  for (let j = 0; j < g_stateObj.layerNum; j++) {
1869
- addTransform(`${sprite}${j}`, `stepArea`, `translateY(${halfwayOffset(j)}px)`, g_transPriority.stepArea);
1869
+ addTransform(`${sprite}${j}`, `stepArea`, `translateY(${wUnit(halfwayOffset(j))})`, g_transPriority.stepArea);
1870
1870
  }
1871
1871
  });
1872
1872
 
@@ -1877,7 +1877,7 @@ const g_stepAreaFunc = new Map([
1877
1877
  for (let j = 0; j < g_stateObj.layerNumDf; j++) {
1878
1878
  addTransform(
1879
1879
  `filterBar${j}`, `stepArea`,
1880
- `translateY(calc(${g_hidSudObj[g_stateObj.appearance] === 0 ? 1 : -1} * ${halfwayOffset(j)}px))`,
1880
+ `translateY(calc(${g_hidSudObj[g_stateObj.appearance] === 0 ? 1 : -1} * ${wUnit(halfwayOffset(j))}))`,
1881
1881
  g_transPriority.stepArea
1882
1882
  );
1883
1883
  }
@@ -1888,12 +1888,12 @@ const g_stepAreaFunc = new Map([
1888
1888
  for (let j = 0; j < g_stateObj.layerNumDf; j++) {
1889
1889
  addTransform(
1890
1890
  `filterBar${j}_HS`, `stepArea`,
1891
- `translateY(calc(${(-1) * (g_hidSudObj[g_stateObj.appearance] === 0 ? 1 : -1)} * ${halfwayOffset(j)}px))`,
1891
+ `translateY(calc(${(-1) * (g_hidSudObj[g_stateObj.appearance] === 0 ? 1 : -1)} * ${wUnit(halfwayOffset(j))}))`,
1892
1892
  g_transPriority.stepArea
1893
1893
  );
1894
1894
  }
1895
1895
  }
1896
- addTransform(`filterView`, `stepArea`, `translateY(${halfwayOffset(Number(g_settings.reverseNum))}px)`, g_transPriority.stepArea);
1896
+ addTransform(`filterView`, `stepArea`, `translateY(${wUnit(halfwayOffset(Number(g_settings.reverseNum)))})`, g_transPriority.stepArea);
1897
1897
  }
1898
1898
  }],
1899
1899
  ['Mismatched', () => {
@@ -1903,7 +1903,7 @@ const g_stepAreaFunc = new Map([
1903
1903
  if (g_workObj.orgFlatFlg) {
1904
1904
  g_arrowGroupSprite.forEach(sprite => {
1905
1905
  for (let j = g_stateObj.layerNumDf; j < g_stateObj.layerNum; j++) {
1906
- addTransform(`${sprite}${j}`, `stepArea`, `translateY(${halfwayOffset(j)}px)`, g_transPriority.stepArea);
1906
+ addTransform(`${sprite}${j}`, `stepArea`, `translateY(${wUnit(halfwayOffset(j))})`, g_transPriority.stepArea);
1907
1907
  }
1908
1908
  });
1909
1909
 
@@ -1914,14 +1914,14 @@ const g_stepAreaFunc = new Map([
1914
1914
  // Hidden+用のフィルターバー補正
1915
1915
  addTransform(
1916
1916
  `filterBar${j + Number(g_settings.reverseNum)}_HS`, `stepArea`,
1917
- `translateY(calc((${getDirFromRev()}) * ${halfwayOffset(j)}px))`,
1917
+ `translateY(calc((${getDirFromRev()}) * ${wUnit(halfwayOffset(j))}))`,
1918
1918
  g_transPriority.stepArea
1919
1919
  );
1920
1920
  } else {
1921
1921
  // Sudden+用のフィルターバー補正
1922
1922
  addTransform(
1923
1923
  `filterBar${j - Number(g_settings.reverseNum)}`, `stepArea`,
1924
- `translateY(calc((${(-1) * getDirFromRev()}) * ${halfwayOffset(j)}px))`,
1924
+ `translateY(calc((${(-1) * getDirFromRev()}) * ${wUnit(halfwayOffset(j))}))`,
1925
1925
  g_transPriority.stepArea
1926
1926
  );
1927
1927
  }
@@ -1936,7 +1936,7 @@ const g_stepAreaFunc = new Map([
1936
1936
  if (g_workObj.orgFlatFlg) {
1937
1937
  g_arrowGroupSprite.forEach(sprite => {
1938
1938
  for (let j = 0; j < g_stateObj.layerNumDf; j++) {
1939
- addTransform(`${sprite}${j}`, `stepArea`, `translateY(${halfwayOffset(j)}px)`, g_transPriority.stepArea);
1939
+ addTransform(`${sprite}${j}`, `stepArea`, `translateY(${wUnit(halfwayOffset(j))})`, g_transPriority.stepArea);
1940
1940
  }
1941
1941
  });
1942
1942
 
@@ -1947,14 +1947,14 @@ const g_stepAreaFunc = new Map([
1947
1947
  // Hidden+用のフィルターバー補正
1948
1948
  addTransform(
1949
1949
  `filterBar${j + Number(g_settings.reverseNum)}`, `stepArea`,
1950
- `translateY(calc((${getDirFromRev()}) * ${halfwayOffset(j)}px))`,
1950
+ `translateY(calc((${getDirFromRev()}) * ${wUnit(halfwayOffset(j))}))`,
1951
1951
  g_transPriority.stepArea
1952
1952
  );
1953
1953
  } else {
1954
1954
  // Sudden+用のフィルターバー補正
1955
1955
  addTransform(
1956
1956
  `filterBar${j - Number(g_settings.reverseNum)}_HS`, `stepArea`,
1957
- `translateY(calc((${(-1) * getDirFromRev()}) * ${halfwayOffset(j)}px))`,
1957
+ `translateY(calc((${(-1) * getDirFromRev()}) * ${wUnit(halfwayOffset(j))}))`,
1958
1958
  g_transPriority.stepArea
1959
1959
  );
1960
1960
  }
@@ -1974,7 +1974,7 @@ const g_stepAreaFunc = new Map([
1974
1974
  for (let j = 0; j < g_stateObj.layerNumDf; j++) {
1975
1975
  addTransform(
1976
1976
  `filterBar${j}_HS`, `stepArea`,
1977
- `translateY(calc((${g_hidSudObj[g_stateObj.appearance] === 0 ? 1 : -1}) * ${halfwayOffset(j)}px))`,
1977
+ `translateY(calc((${g_hidSudObj[g_stateObj.appearance] === 0 ? 1 : -1}) * ${wUnit(halfwayOffset(j))}))`,
1978
1978
  g_transPriority.stepArea
1979
1979
  );
1980
1980
  }
@@ -1983,7 +1983,7 @@ const g_stepAreaFunc = new Map([
1983
1983
  for (let j = 0; j < g_stateObj.layerNumDf; j += 2) {
1984
1984
  addTransform(
1985
1985
  `filterBar${j + Number(g_settings.reverseNum)}_HS`, `stepArea`,
1986
- `translateY(calc((${getDirFromRev()}) * ${halfwayOffset(j)}px))`,
1986
+ `translateY(calc((${getDirFromRev()}) * ${wUnit(halfwayOffset(j))}))`,
1987
1987
  g_transPriority.stepArea
1988
1988
  );
1989
1989
  }
@@ -1998,7 +1998,7 @@ const g_stepAreaFunc = new Map([
1998
1998
  ['Alt-Crossing', () => {
1999
1999
  for (let j = 0; j < g_stateObj.layerNum; j++) {
2000
2000
  addTransform(`mainSprite${j}`, `stepArea`, `rotate(${getDirFromLayer(j) * -10}deg) ` +
2001
- `translateX(${getDirFromLayer(j) * 20}px)`, g_transPriority.stepArea);
2001
+ `translateX(${wUnit(getDirFromLayer(j) * 20)})`, g_transPriority.stepArea);
2002
2002
  }
2003
2003
  }],
2004
2004
  ]);
@@ -2012,34 +2012,34 @@ const getShakingDist = () => (Math.abs((g_scoreObj.baseFrame / 2) % 100 - 50) -
2012
2012
  const g_shakingFunc = new Map([
2013
2013
  ['OFF', () => true],
2014
2014
  ['Horizontal', (_multi = 1) => {
2015
- addTransform(`mainSprite`, `shakingX_base`, `translateX(${getShakingDist() * _multi}px)`, g_transPriority.shakingX)
2015
+ addTransform(`mainSprite`, `shakingX_base`, `translateX(${wUnit(getShakingDist() * _multi)})`, g_transPriority.shakingX)
2016
2016
  }],
2017
2017
  ['Vertical', (_multi = 1) => {
2018
- addTransform(`mainSprite`, `shakingY_base`, `translateY(${getShakingDist() / 2 * _multi}px)`, g_transPriority.shakingY)
2018
+ addTransform(`mainSprite`, `shakingY_base`, `translateY(${wUnit(getShakingDist() / 2 * _multi)})`, g_transPriority.shakingY)
2019
2019
  }],
2020
2020
  ['X-Horizontal', (_multi = 1) => {
2021
2021
  for (let j = 0; j < g_stateObj.layerNum; j++) {
2022
- addTransform(`mainSprite${j}`, `shakingX_layer`, `translateX(${getDirFromLayer(j) * (4 / 3) * getShakingDist() * _multi}px)`, g_transPriority.shakingX);
2022
+ addTransform(`mainSprite${j}`, `shakingX_layer`, `translateX(${wUnit(getDirFromLayer(j) * (4 / 3) * getShakingDist() * _multi)})`, g_transPriority.shakingX);
2023
2023
  }
2024
2024
  }],
2025
2025
  ['X-Vertical', (_multi = 1) => {
2026
2026
  for (let j = 0; j < g_stateObj.layerNum; j++) {
2027
- addTransform(`mainSprite${j}`, `shakingY_layer`, `translateY(${getDirFromLayer(j) * getShakingDist() * _multi}px)`, g_transPriority.shakingY);
2027
+ addTransform(`mainSprite${j}`, `shakingY_layer`, `translateY(${wUnit(getDirFromLayer(j) * getShakingDist() * _multi)})`, g_transPriority.shakingY);
2028
2028
  }
2029
2029
  }],
2030
2030
  ['Drunk', (_multi = 1) => {
2031
2031
  const dist = getShakingDist();
2032
2032
  if (g_workObj.drunkXFlg) {
2033
2033
  const deltaX = dist * _multi;
2034
- addTransform(`mainSprite`, `shakingX_drunk`, `translateX(${deltaX}px)`, g_transPriority.shakingX);
2035
- addTransform(`infoSprite`, `shakingX_drunk`, `translateX(${deltaX}px)`, g_transPriority.shakingX);
2036
- addTransform(`judgeSprite`, `shakingX_drunk`, `translateX(${deltaX}px)`, g_transPriority.shakingX);
2034
+ addTransform(`mainSprite`, `shakingX_drunk`, `translateX(${wUnit(deltaX)})`, g_transPriority.shakingX);
2035
+ addTransform(`infoSprite`, `shakingX_drunk`, `translateX(${wUnit(deltaX)})`, g_transPriority.shakingX);
2036
+ addTransform(`judgeSprite`, `shakingX_drunk`, `translateX(${wUnit(deltaX)})`, g_transPriority.shakingX);
2037
2037
  }
2038
2038
  if (g_workObj.drunkYFlg) {
2039
2039
  const deltaY = dist / 2 * _multi;
2040
- addTransform(`mainSprite`, `shakingY_drunk`, `translateY(${deltaY}px)`, g_transPriority.shakingY);
2041
- addTransform(`infoSprite`, `shakingY_drunk`, `translateY(${deltaY}px)`, g_transPriority.shakingY);
2042
- addTransform(`judgeSprite`, `shakingY_drunk`, `translateY(${deltaY}px)`, g_transPriority.shakingY);
2040
+ addTransform(`mainSprite`, `shakingY_drunk`, `translateY(${wUnit(deltaY)})`, g_transPriority.shakingY);
2041
+ addTransform(`infoSprite`, `shakingY_drunk`, `translateY(${wUnit(deltaY)})`, g_transPriority.shakingY);
2042
+ addTransform(`judgeSprite`, `shakingY_drunk`, `translateY(${wUnit(deltaY)})`, g_transPriority.shakingY);
2043
2043
  }
2044
2044
  // 補正がゼロになったときに軸の移動方法をランダムで決定
2045
2045
  if (dist === 0) {
@@ -2298,7 +2298,7 @@ let g_canDisabledSettings = [`speed`, `motion`, `scroll`, `reverse`, `shuffle`,
2298
2298
 
2299
2299
  const g_hidSudFunc = new Map([
2300
2300
  ['filterPos', _filterPos => `${_filterPos}${g_lblNameObj.percent}`],
2301
- ['range', () => `${Math.round(g_posObj.arrowHeight - g_posObj.stepY)}px`],
2301
+ ['range', () => wUnit(Math.round(g_posObj.arrowHeight - g_posObj.stepY))],
2302
2302
  ['hidden', _filterPos => `${Math.min(Math.round(g_posObj.arrowHeight * (100 - _filterPos) / 100), g_posObj.arrowHeight - g_posObj.stepY)}`],
2303
2303
  ['sudden', _filterPos => `${Math.max(Math.round(g_posObj.arrowHeight * (100 - _filterPos) / 100) - g_posObj.stepY, 0)}`],
2304
2304
  ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "danoniplus",
3
- "version": "49.4.2",
3
+ "version": "49.6.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",