danoniplus 44.2.0 → 44.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Dancing☆Onigiri (CW Edition)
2
2
 
3
3
  [![CodeQL](https://github.com/cwtickle/danoniplus/workflows/CodeQL/badge.svg)](https://github.com/cwtickle/danoniplus/actions?query=workflow%3ACodeQL)
4
+ ![CodeRabbit Pull Request Reviews](https://img.shields.io/coderabbit/prs/github/cwtickle/danoniplus?utm_source=oss&utm_medium=github&utm_campaign=cwtickle%2Fdanoniplus&labelColor=171717&color=FF570A&link=https%3A%2F%2Fcoderabbit.ai&label=CodeRabbit+Reviews)
4
5
  [![Discord](https://img.shields.io/discord/698460971231870977?style=flat&logo=discord&logoColor=%23ffffff&label=Discord&labelColor=%236666ff&color=%23000066)](https://discord.gg/YVWUdUGyMy)
5
6
  [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/cwtickle/danoniplus?sort=semver)](https://github.com/cwtickle/danoniplus/security/policy)
6
7
  [![GitHub All Releases](https://img.shields.io/github/downloads/cwtickle/danoniplus/total?color=%23ff3399&label=downloads%20%28recently%29)](https://github.com/cwtickle/danoniplus/releases)
@@ -120,9 +121,13 @@ If you would like to cooperate with the development, please see below. Even if y
120
121
  - [Dancing☆Onigiri エディター(CW Edition 対応)](https://github.com/superkuppabros/danoni-editor) @superkuppabros
121
122
  - [ダンおに曲データjs化ツール](https://github.com/suzme/danoni-base64) @suzme
122
123
  - [ダンおに矢印色ツール](https://github.com/suzme/danoni-colorpicker) @suzme
124
+ - [ダンおにゲージ計算機 (Gauge Calculator)](http://www.omission0.com/other/gauge_calculator/) @goe0
125
+ - [ダンおに波形解析ツール](https://github.com/suzme/danoni-waveform) @suzme
126
+
127
+ #### Conversion Tool from Legacy Flash Environments / 旧Flashからの変換ツール
128
+
123
129
  - [Dancing☆Onigiri Chart Reverser](https://github.com/cwtickle/danoniplus-reverser) @cwtickle
124
130
  - [Dancing☆Onigiri Chart Converter](https://github.com/cwtickle/danoniplus-converter) @cwtickle
125
- - [ダンおにゲージ計算機 (Gauge Calculator)](http://www.omission0.com/other/gauge_calculator/) @goe0
126
131
 
127
132
  ### Kirizma / キリズマ
128
133
 
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/02/18
7
+ * Revised : 2026/02/21
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 44.2.0`;
12
- const g_revisedDate = `2026/02/18`;
11
+ const g_version = `Ver 44.4.0`;
12
+ const g_revisedDate = `2026/02/21`;
13
13
 
14
14
  // カスタム用バージョン (danoni_custom.js 等で指定可)
15
15
  let g_localVersion = ``;
@@ -65,10 +65,26 @@ const g_referenceDomains = [
65
65
  ];
66
66
  Object.freeze(g_referenceDomains);
67
67
 
68
+ // ドメイン管理リスト
69
+ const g_domainList = [
70
+ { label: `jsdelivr`, hosts: [`cdn.jsdelivr.net`] },
71
+ { label: `unpkg`, hosts: [`unpkg.com`, `www.unpkg.com`] },
72
+ ];
73
+ Object.freeze(g_domainList);
74
+
68
75
  const g_rootPath = current().match(/(^.*\/)/)[0];
69
76
  let g_workPath;
70
77
  const hasRemoteDomain = _path => g_referenceDomains.some(domain => _path.match(`^https://${domain}/`) !== null);
78
+ const detectDomain = _url => {
79
+ try {
80
+ const host = new URL(_url).hostname; // 例: "cdn.jsdelivr.net"
81
+ return g_domainList.find(({ hosts }) => hosts.some(h => host === h || host.endsWith(`.${h}`)))?.label ?? null;
82
+ } catch {
83
+ return null;
84
+ }
85
+ }
71
86
  const g_remoteFlg = hasRemoteDomain(g_rootPath);
87
+ const g_remoteDomain = detectDomain(g_rootPath);
72
88
 
73
89
  const g_randTime = Date.now();
74
90
  const g_versionForUrl = g_version.slice(4); // URL用に先頭の"Ver "を削除
@@ -1895,6 +1911,8 @@ const clearWindow = (_redrawFlg = false, _customDisplayName = ``) => {
1895
1911
 
1896
1912
  // ボタン、オブジェクトをクリア (divRoot配下のもの)
1897
1913
  deleteChildspriteAll(`divRoot`);
1914
+ divRoot.style.perspective = ``;
1915
+ divRoot.style.perspectiveOrigin = ``;
1898
1916
 
1899
1917
  // 拡張範囲を取得
1900
1918
  const diffX = (_customDisplayName === `Main` && g_workObj.nonDefaultSc ?
@@ -5331,7 +5349,8 @@ const titleInit = (_initFlg = false) => {
5331
5349
  customVersion += ` / ${g_localVersion2}`;
5332
5350
  }
5333
5351
  const releaseDate = (g_headerObj.releaseDate !== `` ? ` @${g_headerObj.releaseDate}` : ``);
5334
- const versionName = `© 2018-${g_revisedDate.slice(0, 4)} ティックル, CW ${g_version}${customVersion}${releaseDate}`;
5352
+ const remoteDomainInfo = g_remoteDomain !== null ? ` (${g_remoteDomain})` : ``;
5353
+ const versionName = `© 2018-${g_revisedDate.slice(0, 4)} ティックル, CW ${g_version}${remoteDomainInfo}${customVersion}${releaseDate}`;
5335
5354
  const getLinkSiz = _name => getFontSize2(_name, g_sWidth / 2 - 20, { maxSiz: g_limitObj.lnkSiz, minSiz: 12 });
5336
5355
 
5337
5356
  /**
@@ -8111,8 +8130,8 @@ const gaugeFormat = (_mode, _border, _rcv, _dmg, _init, _lifeValFlg) => {
8111
8130
  const [rateText, allowableCntsText] = getAccuracy(borderVal, realRcv, realDmg, initVal, allCnt);
8112
8131
  g_workObj.requiredAccuracy = rateText;
8113
8132
 
8114
- // 許容ミス数のみ、オンマウスで表示するためpointer-eventsを有効にする
8115
- return `<div id="gaugeDivCover" class="settings_gaugeDivCover">
8133
+ // このテーブルのみpointer-eventsを有効にする(オンマウス許可)
8134
+ return `<div id="gaugeDivCover" class="settings_gaugeDivCover" style="pointer-events: auto;">
8116
8135
  <div id="lblGaugeDivTable" class="settings_gaugeDivTable">
8117
8136
  <div id="lblGaugeStart" class="settings_gaugeDivTableCol settings_gaugeStart">
8118
8137
  ${g_lblNameObj.g_start}
@@ -8143,9 +8162,8 @@ const gaugeFormat = (_mode, _border, _rcv, _dmg, _init, _lifeValFlg) => {
8143
8162
  <div id="dataGaugeDamage" class="settings_gaugeDivTableCol settings_gaugeVal settings_gaugeEtc">
8144
8163
  ${dmgText}
8145
8164
  </div>
8146
- <div id="dataGaugeRate" class="settings_gaugeDivTableCol settings_gaugeVal settings_gaugeEtc"
8147
- title="${allowableCntsText}" style="pointer-events: auto;">
8148
- ${rateText}
8165
+ <div id="dataGaugeRate" class="settings_gaugeDivTableCol settings_gaugeVal settings_gaugeEtc" style="line-height: 12px;">
8166
+ ${rateText}<br><span style="font-size: 10px;">${allowableCntsText}</span>
8149
8167
  </div>
8150
8168
  </div>
8151
8169
  </div>
@@ -8169,7 +8187,7 @@ const getAccuracy = (_border, _rcv, _dmg, _init, _allCnt) => {
8169
8187
 
8170
8188
  // 許容ミス数の計算
8171
8189
  const allowableCnts = Math.min(_allCnt - minRecovery, _allCnt);
8172
- let allowableCntsText = _allCnt > 0 ? (allowableCnts >= 0 ? `${allowableCnts}miss↓` : `Impossible (${allowableCnts}miss)`) : ``;
8190
+ let allowableCntsText = _allCnt > 0 && allowableCnts !== 0 ? (allowableCnts > 0 ? `${allowableCnts}miss↓` : `(${allowableCnts}miss)`) : ``;
8173
8191
 
8174
8192
  if ((_rcv === 0 && _dmg === 0) || _rcv < 0 || _dmg < 0) {
8175
8193
  rateText = `----`;
@@ -11958,6 +11976,12 @@ const mainInit = () => {
11958
11976
 
11959
11977
  // ステップゾーン、矢印のメインスプライトを作成
11960
11978
  const mainSprite = createEmptySprite(divRoot, `mainSprite`, mainCommonPos);
11979
+ if (g_stateObj.frzReturn !== C_FLG_OFF) {
11980
+ divRoot.style.perspective = `1400px`;
11981
+ divRoot.style.perspectiveOrigin = `center 60%`;
11982
+ mainSprite.style.transformOrigin = `center 55%`;
11983
+ }
11984
+
11961
11985
  addTransform(`mainSprite`, `root`, `scale(${g_workObj.scale})`);
11962
11986
  addXY(`mainSprite`, `root`, g_workObj.playingX, g_posObj.stepY - C_STEP_Y + g_headerObj.playingY);
11963
11987
 
@@ -12080,8 +12104,8 @@ const mainInit = () => {
12080
12104
  g_effectFunc.get(g_stateObj.effect)();
12081
12105
 
12082
12106
  // Appearanceのオプション適用時は一部描画を隠す
12083
- changeAppearanceFilter(g_appearanceRanges.includes(g_stateObj.appearance) ?
12084
- g_hidSudObj.filterPos : g_hidSudObj.filterPosDefault[g_stateObj.appearance], true);
12107
+ changeAppearanceBar(g_appearanceRanges.includes(g_stateObj.appearance)
12108
+ ? g_hidSudObj.filterPos : g_hidSudObj.filterPosDefault[g_stateObj.appearance], 0);
12085
12109
 
12086
12110
  // Shaking初期化
12087
12111
  if (g_stateObj.shaking !== C_FLG_OFF) {
@@ -12409,10 +12433,15 @@ const mainInit = () => {
12409
12433
  } else if (g_appearanceRanges.includes(g_stateObj.appearance) && g_stateObj.filterLock === C_FLG_OFF) {
12410
12434
  const MAX_FILTER_POS = 100;
12411
12435
  const MIN_FILTER_POS = 0;
12436
+
12412
12437
  if (setCode === g_hidSudObj.pgDown[g_stateObj.appearance][g_stateObj.reverse]) {
12413
- changeAppearanceFilter(Math.min(g_hidSudObj.filterPos + 1, MAX_FILTER_POS));
12438
+ keyIsShift()
12439
+ ? changeAppearanceBar(g_hidSudObj.filterPos, 2)
12440
+ : changeAppearanceFilter(Math.min(g_hidSudObj.filterPos + 1, MAX_FILTER_POS));
12414
12441
  } else if (setCode === g_hidSudObj.pgUp[g_stateObj.appearance][g_stateObj.reverse]) {
12415
- changeAppearanceFilter(Math.max(g_hidSudObj.filterPos - 1, MIN_FILTER_POS));
12442
+ keyIsShift()
12443
+ ? changeAppearanceBar(g_hidSudObj.filterPos, -2)
12444
+ : changeAppearanceFilter(Math.max(g_hidSudObj.filterPos - 1, MIN_FILTER_POS));
12416
12445
  }
12417
12446
  }
12418
12447
  return blockCode(setCode);
@@ -13367,12 +13396,61 @@ const makeStepZone = (_j, _keyCtrlPtn) => {
13367
13396
  }
13368
13397
  };
13369
13398
 
13399
+ /**
13400
+ * フィルターバーの対象表示変更
13401
+ * @param {number} _num
13402
+ * @param {number} _dirPlus
13403
+ */
13404
+ const changeAppearanceBar = (_num = 10, _dirPlus = 2) => {
13405
+ if (_dirPlus !== 0) {
13406
+ const step = Math.trunc(_dirPlus / 2) * 2;
13407
+ g_workObj.aprFilterCnt = nextPos(g_workObj.aprFilterCnt, step, g_stateObj.layerNum);
13408
+ }
13409
+ changeAppearanceFilter(_num);
13410
+
13411
+ // フィルターバーを使用するオプションのみ以下を適用
13412
+ if (g_appearanceRanges.includes(g_stateObj.appearance) && g_stateObj.d_filterline === C_FLG_ON) {
13413
+
13414
+ // 階層が多い場合はShift+pgUp/pgDownで表示する階層グループを切り替え
13415
+ const topNum = g_hidSudObj[g_stateObj.appearance];
13416
+ const bottomNum = (g_hidSudObj[g_stateObj.appearance] + 1) % 2;
13417
+
13418
+ for (let j = 0; j < g_stateObj.layerNum; j += 2) {
13419
+ [`${topNum + j}`, `${bottomNum + j}`].forEach(type => {
13420
+ const displayState = (j === g_workObj.aprFilterCnt ? C_DIS_INHERIT : C_DIS_NONE);
13421
+ $id(`filterBar${type}`).display = displayState;
13422
+
13423
+ if (![`Default`, `Halfway`].includes(g_stateObj.stepArea)) {
13424
+ $id(`filterBar${type}_HS`).display = displayState;
13425
+ }
13426
+ });
13427
+ }
13428
+
13429
+ // スクロールが1種類でHidden+/Sudden+の場合、対面のフィルターバーは不要なため非表示にする
13430
+ const baseLayer = g_workObj.aprFilterCnt;
13431
+ const dividePosPart = g_workObj.dividePos.filter(v => Math.floor(v / 2) === g_workObj.aprFilterCnt / 2);
13432
+ const currentBarNum = g_hidSudObj.std[g_stateObj.appearance][
13433
+ dividePosPart.length > 0
13434
+ ? dividePosPart[0] % 2 === 0 ? C_FLG_OFF : C_FLG_ON
13435
+ : g_stateObj.reverse
13436
+ ];
13437
+
13438
+ if (g_stateObj.appearance !== `Hid&Sud+`
13439
+ && dividePosPart.length > 0
13440
+ && dividePosPart.every(v => v % 2 === dividePosPart[0] % 2)) {
13441
+ $id(`filterBar${(currentBarNum + 1) % 2 + baseLayer}`).display = C_DIS_NONE;
13442
+ if (![`Default`, `Halfway`].includes(g_stateObj.stepArea)) {
13443
+ $id(`filterBar${(currentBarNum + 1) % 2 + baseLayer}_HS`).display = C_DIS_NONE;
13444
+ }
13445
+ }
13446
+ }
13447
+ }
13448
+
13370
13449
  /**
13371
13450
  * アルファマスクの再描画 (Appearance: Hidden+, Sudden+ 用)
13372
13451
  * @param {number} _num
13373
- * @param {boolean} _shiftFlg シフトキーを押したかどうかのフラグ
13374
13452
  */
13375
- const changeAppearanceFilter = (_num = 10, _shiftFlg = keyIsShift()) => {
13453
+ const changeAppearanceFilter = (_num = 10) => {
13376
13454
  const MAX_FILTER_POS = 100;
13377
13455
  const topNum = g_hidSudObj[g_stateObj.appearance];
13378
13456
  const bottomNum = (g_hidSudObj[g_stateObj.appearance] + 1) % 2;
@@ -13401,35 +13479,18 @@ const changeAppearanceFilter = (_num = 10, _shiftFlg = keyIsShift()) => {
13401
13479
  $id(`filterBar${bottomNum + j}_HS`).top = wUnit(parseFloat($id(`arrowSprite${j}`).top) + bottomDist);
13402
13480
  $id(`filterBar${topNum + j}_HS`).top = wUnit(parseFloat($id(`arrowSprite${j + 1}`).top) + topDist);
13403
13481
  }
13404
-
13405
- // 階層が多い場合はShift+pgUp/pgDownで表示する階層グループを切り替え
13406
- if (_shiftFlg && g_stateObj.d_filterline === C_FLG_ON) {
13407
- [`${topNum + j}`, `${bottomNum + j}`].forEach(type => {
13408
- const displayState = (j === g_workObj.aprFilterCnt ? C_DIS_INHERIT : C_DIS_NONE);
13409
- $id(`filterBar${type}`).display = displayState;
13410
-
13411
- if (![`Default`, `Halfway`].includes(g_stateObj.stepArea)) {
13412
- $id(`filterBar${type}_HS`).display = displayState;
13413
- }
13414
- });
13415
- }
13416
- }
13417
-
13418
- if (_shiftFlg) {
13419
- g_workObj.aprFilterCnt = nextPos(g_workObj.aprFilterCnt, 2, g_stateObj.layerNum);
13420
13482
  }
13421
13483
 
13484
+ // フィルターバーのパーセント表示(フィルターバーが複数表示されるなど複雑なため、最初の階層グループの位置に追従)
13422
13485
  if (g_appearanceRanges.includes(g_stateObj.appearance)) {
13423
- $id(`filterView`).top =
13424
- $id(`filterBar${(g_hidSudObj.std[g_stateObj.appearance][g_stateObj.reverse]) % 2}`).top;
13486
+ const currentBarNum = g_hidSudObj.std[g_stateObj.appearance][g_stateObj.reverse];
13487
+ $id(`filterView`).top = $id(`filterBar${currentBarNum % 2}`).top;
13425
13488
  filterView.textContent = `${_num}%`;
13426
-
13427
- // スクロールが1種類でHidden+/Sudden+の場合、対面のフィルターバーは不要なため非表示にする
13428
- if (g_stateObj.appearance !== `Hid&Sud+` && g_workObj.dividePos.every(v => v === g_workObj.dividePos[0])) {
13429
- $id(`filterBar${(g_hidSudObj.std[g_stateObj.appearance][g_stateObj.reverse] + 1) % 2}`).display = C_DIS_NONE;
13430
- }
13431
13489
  g_hidSudObj.filterPos = _num;
13432
13490
  }
13491
+
13492
+ // ユーザカスタムイベント(アルファマスクの再描画)
13493
+ g_customJsObj.appearanceFilter.forEach(func => func(topNum, bottomNum));
13433
13494
  };
13434
13495
 
13435
13496
  /**
@@ -13487,7 +13548,32 @@ const changeReturn = (_rad, _axis) => {
13487
13548
  if (_axis[1] !== undefined) {
13488
13549
  _transform += ` rotate${_axis[1]}(${_rad}deg)`;
13489
13550
  }
13490
- if (document.getElementById(`mainSprite`) !== null) {
13551
+ const sprite = document.getElementById(`mainSprite`);
13552
+ if (sprite !== null) {
13553
+ sprite.style.transformStyle = `preserve-3d`;
13554
+ const rad360 = _rad % 360;
13555
+
13556
+ let isBack = false;
13557
+
13558
+ // 単軸回転
13559
+ if (_axis.length === 1) {
13560
+ const axis = _axis[0];
13561
+ if (axis === 'Y' || axis === 'X') {
13562
+ isBack = rad360 > 90 && rad360 < 270;
13563
+ }
13564
+ // Z軸は平面回転なので「裏側」は存在しない
13565
+ }
13566
+
13567
+ // 2軸回転(XZ / XY / YZ)
13568
+ if (_axis.length === 2) {
13569
+ // 2軸回転は「どちらかの軸が裏側なら裏側」とみなす
13570
+ const [a1, a2] = _axis;
13571
+ const back1 = (a1 === 'Y' || a1 === 'X') && (rad360 > 90 && rad360 < 270);
13572
+ const back2 = (a2 === 'Y' || a2 === 'X') && (rad360 > 90 && rad360 < 270);
13573
+ isBack = back1 || back2;
13574
+ }
13575
+ sprite.style.opacity = isBack ? 0.7 : 1;
13576
+
13491
13577
  addTransform(`mainSprite`, `frzReturn`, _transform);
13492
13578
 
13493
13579
  if (_rad < 360 && g_workObj.frzReturnFlg) {
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2019/11/19
8
- * Revised : 2026/02/18 (v44.2.0)
8
+ * Revised : 2026/02/21 (v44.4.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -4577,6 +4577,8 @@ const g_customJsObj = {
4577
4577
  dummyArrow: [],
4578
4578
  dummyFrz: [],
4579
4579
 
4580
+ appearanceFilter: [],
4581
+
4580
4582
  judg_ii: [],
4581
4583
  judg_shakin: [],
4582
4584
  judg_matari: [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "danoniplus",
3
- "version": "44.2.0",
3
+ "version": "44.4.0",
4
4
  "description": "Dancing☆Onigiri (CW Edition) - Web-based Rhythm Game",
5
5
  "main": "./js/danoni_main.js",
6
6
  "scripts": {