danoniplus 40.6.0 → 40.7.0-a2

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 : 2025/03/16
7
+ * Revised : 2025/03/22
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 40.6.0`;
12
- const g_revisedDate = `2025/03/16`;
11
+ const g_version = `Ver 40.7.0`;
12
+ const g_revisedDate = `2025/03/22`;
13
13
 
14
14
  // カスタム用バージョン (danoni_custom.js 等で指定可)
15
15
  let g_localVersion = ``;
@@ -78,6 +78,7 @@ const g_isDebug = g_isLocal ||
78
78
  const isLocalMusicFile = _scoreId => g_isFile && !listMatching(getMusicUrl(_scoreId), [`.js`, `.txt`], { suffix: `$` });
79
79
 
80
80
  window.onload = async () => {
81
+ await new Promise(resolve => setTimeout(resolve, 500));
81
82
  g_loadObj.main = true;
82
83
  g_currentPage = `initial`;
83
84
  const links = document.querySelectorAll(`link`);
@@ -2605,6 +2606,19 @@ const initialControl = async () => {
2605
2606
  const customKeyList = g_headerObj.keyLists.filter(val =>
2606
2607
  g_keyObj.defaultKeyList.findIndex(key => key === val) < 0);
2607
2608
 
2609
+ if (customKeyList.length === 0) {
2610
+ g_settings.preconditions = g_settings.preconditions.filter(val => !val.includes(`g_editorTmp`));
2611
+ }
2612
+
2613
+ const addNewOrderGroup = (_orgList, _sortRule) => {
2614
+ // インデックスを保持した配列を作成、ルールに従ってソート
2615
+ const indexedList = _orgList.map((value, idx) => ({ value, idx }));
2616
+ const sortedList = [...indexedList].sort(_sortRule);
2617
+ // ソート後の配列のインデックスに基づいて、元のインデックスを取得
2618
+ const newIdxs = sortedList.map(({ idx }) => indexedList.findIndex(({ idx: originalIdx }) => originalIdx === idx));
2619
+ return !newIdxs.every((val, j) => val === j) ? newIdxs : undefined;
2620
+ };
2621
+
2608
2622
  customKeyList.forEach(key => {
2609
2623
  const keyBase = `${key}_0`;
2610
2624
  const keyCtrlPtn = `${g_keyObj.defaultProp}${keyBase}`;
@@ -2613,14 +2627,21 @@ const initialControl = async () => {
2613
2627
  const orgKeyNum = g_keyObj[keyCtrlPtn].length;
2614
2628
  const baseX = Math.floor(Math.random() * (100 - keyGroupList.length));
2615
2629
 
2630
+ const divPos = g_keyObj[`div${keyBase}`];
2631
+ const divMaxPos = g_keyObj[`divMax${keyBase}`] ?? Math.max(...g_keyObj[`pos${keyBase}`]) + 1;
2632
+ const stdPos = Math.max(divPos, divMaxPos - divPos);
2633
+ const [deltaXAbove, deltaXBelow] = [(divPos - stdPos) / 2, (divMaxPos - divPos - stdPos) / 2];
2634
+
2616
2635
  keyGroupList.forEach((keyGroupNo, j) => {
2617
2636
  const keyN = keyGroupNo === `0` ? key : `${key}_${j + 1}`;
2618
2637
  const filterCond = (j) => keyGroup[j].findIndex(val => val === keyGroupNo) >= 0;
2619
2638
  const keyCtrlList = g_keyObj[keyCtrlPtn].filter((val, j) => filterCond(j));
2620
2639
  const charaList = g_keyObj[`chara${keyBase}`].filter((val, j) => filterCond(j));
2621
2640
  const colorList = g_keyObj[`color${keyBase}_0`].filter((val, j) => filterCond(j));
2641
+ const stepRtnList = g_keyObj[`stepRtn${keyBase}_0`].filter((val, j) => filterCond(j));
2622
2642
  const keyNum = g_keyObj[keyCtrlPtn].filter((val, j) => filterCond(j)).length;
2623
2643
 
2644
+ // ---- Dancing☆Onigiri (CW Edition対応)のフォーマット
2624
2645
  g_editorTmp[keyN] = {};
2625
2646
  g_editorTmp[keyN].id = orgKeyNum * 100 + baseX + j;
2626
2647
  g_editorTmp[keyN].num = keyNum;
@@ -2636,6 +2657,77 @@ const initialControl = async () => {
2636
2657
  return `${frzName}_data`;
2637
2658
  });
2638
2659
  g_editorTmp[keyN].colorGroup = colorList.map(val => val % 3);
2660
+
2661
+ // orderGroupsのカスタマイズ
2662
+ if (divMaxPos > divPos) {
2663
+
2664
+ // posXの実際の相対位置を計算
2665
+ const orgPosList = g_keyObj[`pos${keyBase}`].filter((val, j) => filterCond(j));
2666
+ const posList = orgPosList.map(val => val < divPos ? val - deltaXAbove : val - divPos - deltaXBelow);
2667
+
2668
+ g_editorTmp[keyN].orderGroups = [];
2669
+
2670
+ // パターン1: 上下グループ分けして各グループ内で位置順にソート(上下反転)
2671
+ const upDownIdxs = addNewOrderGroup(orgPosList, (a, b) => {
2672
+ const aAbove = a.value < divPos;
2673
+ const bAbove = b.value < divPos;
2674
+ if (aAbove !== bAbove) return Number(aAbove) - Number(bAbove);
2675
+ return a.value - b.value;
2676
+ });
2677
+ if (upDownIdxs !== undefined) {
2678
+ g_editorTmp[keyN].orderGroups.push(upDownIdxs);
2679
+ }
2680
+
2681
+ // パターン2: 単純にステップゾーンのX座標が小さい順にソート
2682
+ const sortedIdxs = addNewOrderGroup(posList, (a, b) => a.value - b.value);
2683
+ if (sortedIdxs !== undefined) {
2684
+ g_editorTmp[keyN].orderGroups.push(sortedIdxs);
2685
+ }
2686
+ if (g_editorTmp[keyN].orderGroups.length === 0) {
2687
+ delete g_editorTmp[keyN].orderGroups;
2688
+ }
2689
+ }
2690
+
2691
+ // ---- ダンおに譜面作成エディタ ver3フォーマット
2692
+
2693
+ // 既存のシャッフルグループからミラー配列を自動生成
2694
+ let k = 0, n = 0, convTxt = ``;
2695
+ let prevMirrorList = [];
2696
+ while (g_keyObj[`shuffle${keyBase}_${k}`] !== undefined) {
2697
+
2698
+ const orgTmpList = []
2699
+ const mirrorTmpList = [];
2700
+ const mirrorList = [];
2701
+ g_keyObj[`shuffle${keyBase}_${k}`].filter((val, m) => filterCond(m))
2702
+ .forEach((_val, _i) => orgTmpList[_val]?.push(_i) || (orgTmpList[_val] = [_i]));
2703
+ orgTmpList.forEach((list, idx) => mirrorTmpList[idx] = list.toReversed());
2704
+ orgTmpList?.forEach((list, a) => list?.forEach((val, b) => mirrorList[orgTmpList[a][b]] = mirrorTmpList[a][b]));
2705
+ if (!mirrorList.every((val, p) => val === prevMirrorList[p])) {
2706
+ convTxt += `\$conv${n + 1}=Mirror${n + 1},${mirrorList.join(',')}<br>`;
2707
+ prevMirrorList = mirrorList.concat();
2708
+ n++;
2709
+ }
2710
+ k++;
2711
+ }
2712
+
2713
+ // 矢印・フリーズアローのヘッダー情報を定義
2714
+ let noteTxt = ``, freezeTxt = ``;
2715
+ g_editorTmp[keyN].noteNames.forEach((val, j) =>
2716
+ noteTxt += `|${val.slice(0, -(`_data`.length))}[i]_data=[a${String(j).padStart(2, `0`)}]|[E]<br>`);
2717
+
2718
+ g_editorTmp[keyN].freezeNames.forEach((val, j) =>
2719
+ freezeTxt += `|${val.slice(0, -(`_data`.length))}[i]_data=[f${String(j).padStart(2, `0`)}]|[E]<br>`);
2720
+
2721
+ g_editorTmp2 += g_editorTmp2Template
2722
+ .replace(`[__KEY__]`, keyN)
2723
+ .replace(`[__MAP__]`, colorList.map(val => val < 3 ? (val + 1) % 3 : val % 7).join(','))
2724
+ .replace(`[__POS__]`, fillArray(keyNum).map((val, j) =>
2725
+ isNaN(parseFloat(stepRtnList[j])) ? 28 : 24).join(`,`))
2726
+ .replace(`[__TXT__]`, g_editorTmp[keyN].chars.map(val => val.replace(`, `, ``)).join(`,`))
2727
+ .replace(`[__CONV__]`, convTxt)
2728
+ .replace(`[__NOTE__]`, noteTxt)
2729
+ .replace(`[__FREEZE__]`, freezeTxt)
2730
+ .replaceAll(`\n`, ``);
2639
2731
  });
2640
2732
  });
2641
2733
  };
@@ -5275,9 +5367,14 @@ const preconditionInit = () => {
5275
5367
 
5276
5368
  createDivCss2Label(`lblPrecondView`, viewKeyStorage(`g_rootObj`), g_lblPosObj.lblPrecondView),
5277
5369
  createCss2Button(`btnPrecondView`, g_lblNameObj.b_copyStorage, () =>
5278
- copyTextToClipboard(
5279
- viewKeyStorage(g_settings.preconditions[g_settings.preconditionNum * numOfPrecs + g_settings.preconditionNumSub], ``, false),
5280
- g_msgInfoObj.I_0007),
5370
+ copyTextToClipboard((() => {
5371
+ const key = g_settings.preconditions[g_settings.preconditionNum * numOfPrecs + g_settings.preconditionNumSub];
5372
+ if (key === `g_editorTmp2`) {
5373
+ return g_editorTmp2.replaceAll(`<br>`, `\r\n`).replaceAll(`&nbsp;`, ` `);
5374
+ } else {
5375
+ return viewKeyStorage(key, ``, false);
5376
+ }
5377
+ })(), g_msgInfoObj.I_0007),
5281
5378
  g_lblPosObj.btnPrecondView, g_cssObj.button_Default, g_cssObj.button_ON),
5282
5379
  );
5283
5380
  setUserSelect($id(`lblPrecondView`), `text`);
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2019/11/19
8
- * Revised : 2025/03/12 (v40.5.2)
8
+ * Revised : 2025/03/22 (v40.7.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -1179,7 +1179,7 @@ const g_settings = {
1179
1179
  settingWindowNum: 0,
1180
1180
 
1181
1181
  preconditions: [`g_rootObj`, `g_headerObj`, `g_keyObj`, `g_scoreObj`, `g_workObj`,
1182
- `g_detailObj`, `g_stateObj`, `g_attrObj`, `g_editorTmp`],
1182
+ `g_detailObj`, `g_stateObj`, `g_attrObj`, `g_editorTmp`, `g_editorTmp2`],
1183
1183
  preconditionNum: 0,
1184
1184
  preconditionNumSub: 0,
1185
1185
  };
@@ -3187,7 +3187,42 @@ g_keycons.groups.forEach(type => {
3187
3187
  tmpName.forEach(property => g_keyObj[`${property.slice(0, -2)}`] = g_keyObj[property].concat());
3188
3188
  });
3189
3189
 
3190
+ // 外部エディター用テンプレート
3191
+ // g_editorTmp: Dancing☆Onigiriエディター (CW Edition対応)
3192
+ // g_editorTmp2: ダンおに譜面作成エディタ ver3.x
3190
3193
  const g_editorTmp = {};
3194
+ let g_editorTmp2 = ``;
3195
+
3196
+ const g_editorTmp2Template = `
3197
+ <br>
3198
+ \$key=[__KEY__]<br>
3199
+ \$map=[__MAP__]<br>
3200
+ \$pos=[__POS__]<br>
3201
+ \$txt=[__TXT__]<br>
3202
+ [__CONV__]
3203
+ <br>
3204
+ \$dosformat=<br>function externalDosInit() {[E]<br>
3205
+ [E]<br>
3206
+ &nbsp;&nbsp;g_externalDos = \`[E]<br>
3207
+ [E]<br>
3208
+ [header][E]<br>
3209
+ [E]<br>
3210
+ [notestart]<br>
3211
+ [__NOTE__]
3212
+ <br>
3213
+ [__FREEZE__]
3214
+ <br>
3215
+ |speed[i]_data=[speed]|[E]<br>
3216
+ |boost[i]_data=[boost]|[E]<br>
3217
+ [datatext][E]<br>
3218
+ |edit[i]_info=[edit]|[E][E]<br>
3219
+ [noteend]<br>
3220
+ <br>
3221
+ [footer]<br>
3222
+ &nbsp;&nbsp;\`;[E]<br>
3223
+ }<br>
3224
+ <br>
3225
+ `;
3191
3226
 
3192
3227
  // 特殊キーのコピー種 (simple: 代入、multiple: 配列ごと代入)
3193
3228
  // 後でプロパティ削除に影響するため、先頭文字が全く同じ場合は長い方を先に定義する (例: divMax, div)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "danoniplus",
3
- "version": "40.6.0",
3
+ "version": "40.7.0-a2",
4
4
  "description": "Dancing☆Onigiri (CW Edition) - Web-based Rhythm Game",
5
5
  "main": "./js/danoni_main.js",
6
6
  "scripts": {