danoniplus 49.4.1 → 49.5.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.
Files changed (2) hide show
  1. package/js/danoni_main.js +118 -64
  2. package/package.json +1 -1
package/js/danoni_main.js CHANGED
@@ -4,12 +4,12 @@
4
4
  *
5
5
  * Source by tickle
6
6
  * Created : 2018/10/08
7
- * Revised : 2026/08/07
7
+ * Revised : 2026/08/12
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 49.4.1`;
12
- const g_revisedDate = `2026/08/07`;
11
+ const g_version = `Ver 49.5.0`;
12
+ const g_revisedDate = `2026/08/12`;
13
13
 
14
14
  // カスタム用バージョン (danoni_custom.js 等で指定可)
15
15
  let g_localVersion = ``;
@@ -10260,56 +10260,6 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
10260
10260
  ? g_lblNameObj.kcShuffleDesc : g_lblNameObj.kcNoShuffleDesc),
10261
10261
  );
10262
10262
 
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
10263
  /**
10314
10264
  * keyconSpriteのスクロール位置調整
10315
10265
  * @param {number} _targetX
@@ -10401,7 +10351,7 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
10401
10351
  } else {
10402
10352
  changeTmpOneColor(_j);
10403
10353
  }
10404
- adjustScrollPoint(parseFloat($id(`arrow${_j}`).left));
10354
+ adjustScrollPoint(parseFloat($id(`keyGroup${_j}`).left));
10405
10355
  };
10406
10356
 
10407
10357
  /**
@@ -10427,17 +10377,101 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
10427
10377
  } else {
10428
10378
  changeTmpOneShuffle(_j);
10429
10379
  }
10430
- adjustScrollPoint(parseFloat($id(`arrow${_j}`).left));
10380
+ adjustScrollPoint(parseFloat($id(`keyGroup${_j}`).left));
10381
+ };
10382
+
10383
+ /**
10384
+ * 指定関数群だけを抽出したtransform文字列を作成
10385
+ */
10386
+ const extractTransformFuncs = (cssString, funcNames) => {
10387
+ const pattern = new RegExp(`\\b(${funcNames.join(`|`)})\\([^)]*\\)`, `g`);
10388
+ return (cssString.match(pattern) || []).join(` `);
10389
+ };
10390
+
10391
+ /**
10392
+ * 対象レーンのレイヤー番号を取得
10393
+ */
10394
+ const getLayerIdx = (_j, _posj) => {
10395
+ const baseLayer = g_keyObj[`layerGroup${keyCtrlPtn}`]?.[_j] || 0;
10396
+ const rowFlg = Number(_posj > divideCnt); // reverse/scrollDirは考慮せず固定
10397
+ return baseLayer * 2 + rowFlg;
10398
+ };
10399
+
10400
+ /**
10401
+ * 対象レイヤーの回転変形を取得
10402
+ */
10403
+ const getLayerRotateParts = _keyCtrlPtn => {
10404
+ const raw = g_keyObj[`layerTrans${_keyCtrlPtn}`]?.[0] ?? [``, ``, ``, ``];
10405
+ return raw.map(trans => trans === `` ? `` : extractTransformFuncs(trans, [`rotate`, `rotateX`, `rotateY`, `rotateZ`, `rotate3d`]));
10431
10406
  };
10432
10407
 
10408
+ // キーの一覧を表示するための準備
10409
+ const C_LAYER_Y_OFFSET = 10; // baseLayerごとの縦オフセット量
10410
+ const keyconSprite = createEmptySprite(divRoot, `keyconSprite`, g_windowObj.keyconSprite);
10411
+ const tkObj = getKeyInfo();
10412
+ const [keyCtrlPtn, keyNum, posMax, divideCnt] =
10413
+ [tkObj.keyCtrlPtn, tkObj.keyNum, tkObj.posMax, tkObj.divideCnt];
10414
+
10415
+ g_keyCopyLists.simpleDef.forEach(header => updateKeyInfo(header, keyCtrlPtn));
10416
+ addTransform(`keyconSprite`, `root`, `scale(${g_keyObj.scale})`, g_transPriority.scale);
10417
+ keyconSprite.style.height = `${parseFloat(keyconSprite.style.height) / ((1 + g_keyObj.scale) / 2)}px`;
10418
+ const kWidth = parseInt(keyconSprite.style.width);
10419
+ changeSetColor();
10420
+
10421
+ const maxLeftPos = Math.max(divideCnt, posMax - divideCnt - 2) / 2;
10422
+ const maxLeftX = Math.min(0, (kWidth - C_ARW_WIDTH) / 2 - maxLeftPos * g_keyObj.blank);
10423
+
10424
+ g_keycons.cursorNumList = [...Array(keyNum).keys()].map(i => i);
10425
+ const configKeyGroupList = g_headerObj.keyGroupOrder[g_stateObj.scoreId] ??
10426
+ g_keyObj[`keyGroupOrder${keyCtrlPtn}`] ?? tkObj.keyGroupList;
10427
+ g_keycons.colorCursorNum = 0;
10428
+
10429
+ // 色変化中の初期色を取得(矢印枠のみ)
10430
+ const arrowColorTmp = g_detailObj.miniMapParams[g_stateObj.scoreId]._scoreObj.ncolorData.Arrow;
10431
+ const arrowColors = Array.from({ length: Math.ceil(arrowColorTmp.length / 5) }, (_, i) =>
10432
+ arrowColorTmp.slice(i * 5, i * 5 + 5)
10433
+ ).filter(val => val[0] === 0);
10434
+ const initColors = [];
10435
+ arrowColors.forEach(val => {
10436
+ const laneToken = val[1];
10437
+ const laneStr = String(laneToken ?? ``);
10438
+ if (laneStr.startsWith('g')) {
10439
+ // g付きの場合は矢印グループから対象の矢印番号を検索
10440
+ const groupVal = setIntVal(laneStr.slice(1));
10441
+ for (let j = 0; j < tkObj.keyNum; j++) {
10442
+ if (g_keyObj[`color${tkObj.keyCtrlPtn}`][j] === groupVal) {
10443
+ initColors[j] = makeColorGradation(val[2]);
10444
+ }
10445
+ }
10446
+ } else {
10447
+ const laneIdx = setIntVal(laneToken, -1);
10448
+ if (laneIdx >= 0 && laneIdx < tkObj.keyNum) {
10449
+ initColors[laneIdx] = makeColorGradation(val[2]);
10450
+ }
10451
+ }
10452
+ });
10453
+ if (_initFlg) {
10454
+ g_baseColorGrs = {};
10455
+ const colorKey = Object.keys(g_keyObj).filter(val => val.startsWith(`color${g_keyObj.currentKey}`));
10456
+ colorKey.forEach(val => g_baseColorGrs[val] = g_keyObj[val]);
10457
+ }
10458
+
10459
+ const layerParts = getLayerRotateParts(keyCtrlPtn);
10460
+ g_keycons.layerIdxList = [];
10461
+
10462
+ // キーコンフィグの矢印表示
10433
10463
  const addLeft = (maxLeftX === 0 ? 0 : - maxLeftX + g_limitObj.kcColorPickerX);
10434
10464
  for (let j = 0; j < keyNum; j++) {
10435
10465
 
10436
10466
  const posj = g_keyObj[`pos${keyCtrlPtn}`][j];
10437
10467
  const stdPos = posj - ((posj > divideCnt ? posMax : 0) + divideCnt) / 2;
10468
+ const baseLayer = g_keyObj[`layerGroup${keyCtrlPtn}`]?.[j] || 0;
10469
+ const layerIdx = getLayerIdx(j, posj); // baseLayer*2 + Number(posj > divideCnt)
10470
+ const layerRotate = layerParts[layerIdx] || ``;
10471
+ g_keycons.layerIdxList[j] = layerIdx;
10438
10472
 
10439
10473
  const keyconX = g_keyObj.blank * stdPos + (kWidth - C_ARW_WIDTH) / 2 + addLeft;
10440
- const keyconY = C_KYC_HEIGHT * (Number(posj > divideCnt)) + 12;
10474
+ const keyconY = C_KYC_HEIGHT * (Number(posj > divideCnt)) + 12 + baseLayer * C_LAYER_Y_OFFSET;
10441
10475
  const colorPos = g_keyObj[`color${keyCtrlPtn}`][j];
10442
10476
  const arrowColor = getKeyConfigColor(j, colorPos);
10443
10477
 
@@ -10447,16 +10481,22 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
10447
10481
  cxtFunc: () => changeTmpColor(j, -1),
10448
10482
  }, g_cssObj.button_Default_NoColor, g_cssObj.title_base)
10449
10483
  );
10484
+
10485
+ // キーごとの親コンテナ(矢印要素を囲う)
10486
+ const keyGroup = createEmptySprite(keyconSprite, `keyGroup${j}`, { x: keyconX, y: keyconY, w: C_ARW_WIDTH, h: C_ARW_WIDTH });
10487
+ if (layerRotate !== ``) {
10488
+ keyGroup.style.transform = layerRotate; // ここだけがlayer変形の適用箇所
10489
+ }
10450
10490
  // キーコンフィグ表示用の矢印・おにぎりを表示
10451
- multiAppend(keyconSprite,
10491
+ multiAppend(keyGroup,
10452
10492
  // 矢印の塗り部分
10453
10493
  createColorObject2(`arrowShadow${j}`, {
10454
- x: keyconX, y: keyconY, background: hasVal(g_headerObj[`setShadowColor${g_colorType}`][colorPos]) ? getShadowColor(colorPos, arrowColor) : ``,
10494
+ background: hasVal(g_headerObj[`setShadowColor${g_colorType}`][colorPos]) ? getShadowColor(colorPos, arrowColor) : ``,
10455
10495
  rotate: g_keyObj[`stepRtn${keyCtrlPtn}_${g_keycons.stepRtnGroupNum}`][j], styleName: `Shadow`,
10456
10496
  }),
10457
10497
  // 矢印本体
10458
10498
  createColorObject2(`arrow${j}`, {
10459
- x: keyconX, y: keyconY, background: arrowColor, rotate: g_keyObj[`stepRtn${keyCtrlPtn}_${g_keycons.stepRtnGroupNum}`][j],
10499
+ background: arrowColor, rotate: g_keyObj[`stepRtn${keyCtrlPtn}_${g_keycons.stepRtnGroupNum}`][j],
10460
10500
  }),
10461
10501
  );
10462
10502
  if (g_headerObj.shuffleUse && g_keyObj[`shuffle${keyCtrlPtn}`] !== undefined) {
@@ -10716,10 +10756,11 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
10716
10756
  const setKeyConfigCursor = () => {
10717
10757
  const posj = g_keyObj[`pos${keyCtrlPtn}`][g_currentj];
10718
10758
  const stdPos = posj - ((posj > divideCnt ? posMax : 0) + divideCnt) / 2;
10759
+ const baseLayer = g_keyObj[`layerGroup${keyCtrlPtn}`]?.[g_currentj] || 0;
10719
10760
 
10720
10761
  const nextLeft = (kWidth - C_ARW_WIDTH) / 2 + g_keyObj.blank * stdPos + addLeft - 10;
10721
10762
  cursor.style.left = wUnit(nextLeft);
10722
- cursor.style.top = wUnit(C_KYC_HEIGHT * Number(posj > divideCnt) + 57 + C_KYC_REPHEIGHT * g_currentk);
10763
+ cursor.style.top = wUnit(C_KYC_HEIGHT * Number(posj > divideCnt) + 57 + C_KYC_REPHEIGHT * g_currentk + baseLayer * C_LAYER_Y_OFFSET);
10723
10764
  g_kcType = (g_currentk === 0 ? `Main` : `Replaced`);
10724
10765
 
10725
10766
  // 次の位置が見えなくなったらkeyconSpriteの位置を調整する
@@ -13007,7 +13048,10 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
13007
13048
  let layerTrans = tmpScrollchData[4] ?? ``;
13008
13049
  maxLayerGroup = Math.max(maxLayerGroup, layerGroup);
13009
13050
  if (g_stateObj.reverse === C_FLG_ON) {
13010
- layerTrans = invertSpecificTransforms(layerTrans);
13051
+ layerTrans = invertSpecificTransforms(layerTrans, [`translateX`]);
13052
+ }
13053
+ if (g_stateObj.swapping === `Mirror+`) {
13054
+ layerTrans = invertSpecificTransforms(layerTrans, [`translateY`]);
13011
13055
  }
13012
13056
 
13013
13057
  scrollchData.push([frame, arrowNum, frame, scrollDir, layerGroup, layerTrans]);
@@ -14168,15 +14212,20 @@ const pushScrollchs = (_header, _frameArrow, _val, _frameStep, _scrollDir, _laye
14168
14212
  /**
14169
14213
  * ホワイトリストに登録されたCSS関数内の数値符号のみを反転する関数
14170
14214
  * @param {string} cssString
14215
+ * @param {string[]} exceptList 反転対象から除外するCSS関数名のリスト
14171
14216
  * @returns {string}
14172
14217
  */
14173
- const invertSpecificTransforms = (cssString) => {
14218
+ const invertSpecificTransforms = (cssString, exceptList = []) => {
14174
14219
  // 反転対象にしたいCSS関数名を指定(ホワイトリスト)
14175
- const targetFunctions = [
14220
+ const baseTargetFunctions = [
14176
14221
  `rotate`, `rotateX`, `rotateY`, `rotateZ`, `rotate3d`,
14177
14222
  `translate`, `translateX`, `translateY`, `translateZ`, `translate3d`,
14178
14223
  `skew`, `skewX`, `skewY`
14179
14224
  ];
14225
+ const targetFunctions = baseTargetFunctions.filter(pattern => !exceptList.includes(pattern));
14226
+ if (targetFunctions.length === 0) {
14227
+ return cssString; // 反転対象がない場合は元の文字列を返す
14228
+ }
14180
14229
 
14181
14230
  // RegExパターンを作成: /(rotate|translate...)\(([^)]+)\)/g
14182
14231
  const pattern = new RegExp(`\\b(${targetFunctions.join(`|`)})\\(([^)]+)\\)`, `g`);
@@ -14268,7 +14317,12 @@ const getArrowSettings = () => {
14268
14317
  if (g_keyObj[`layerTrans${keyCtrlPtn}`]?.[0]) {
14269
14318
  g_workObj.layerTrans = structuredClone(g_keyObj[`layerTrans${keyCtrlPtn}`][0]);
14270
14319
  if (g_stateObj.reverse === C_FLG_ON) {
14271
- g_workObj.layerTrans = g_workObj.layerTrans.map(val => invertSpecificTransforms(val));
14320
+ // Reverse時はX軸反転のため、X軸の座標変換では符号を変換しない
14321
+ g_workObj.layerTrans = g_workObj.layerTrans.map(val => invertSpecificTransforms(val, [`translateX`]));
14322
+ }
14323
+ if (g_stateObj.swapping === `Mirror+`) {
14324
+ // Swapping: Mirror+ はY軸反転のため、Y軸の座標変換では符号を変換しない
14325
+ g_workObj.layerTrans = g_workObj.layerTrans.map(val => invertSpecificTransforms(val, [`translateY`]));
14272
14326
  }
14273
14327
  }
14274
14328
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "danoniplus",
3
- "version": "49.4.1",
3
+ "version": "49.5.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",