danoniplus 31.5.0 → 31.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 : 2023/04/16
7
+ * Revised : 2023/04/26
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 31.5.0`;
12
- const g_revisedDate = `2023/04/16`;
11
+ const g_version = `Ver 31.6.0`;
12
+ const g_revisedDate = `2023/04/26`;
13
13
  const g_alphaVersion = ``;
14
14
 
15
15
  // カスタム用バージョン (danoni_custom.js 等で指定可)
@@ -4303,155 +4303,615 @@ const inputSlider = (_slider, _link) => {
4303
4303
  };
4304
4304
 
4305
4305
  /**
4306
- * 設定・オプション画面のラベル・ボタン処理の描画
4307
- * @param {Object} _sprite 基準とするスプライト(ここで指定する座標は、そのスプライトからの相対位置)
4306
+ * 譜面変更セレクターの削除
4308
4307
  */
4309
- const createOptionWindow = _sprite => {
4308
+ const resetDifWindow = _ => {
4309
+ if (document.querySelector(`#difList`) !== null) {
4310
+ deleteChildspriteAll(`difList`);
4311
+ [`difList`, `difCover`, `btnDifU`, `btnDifD`].forEach(obj => optionsprite.removeChild(document.getElementById(obj)));
4312
+ g_currentPage = `option`;
4313
+ setShortcutEvent(g_currentPage, _ => true, { displayFlg: false, dfEvtFlg: true });
4314
+ }
4315
+ };
4310
4316
 
4311
- // 各ボタン用のスプライトを作成
4312
- const optionsprite = createOptionSprite(_sprite);
4317
+ /**
4318
+ * 譜面選択処理
4319
+ * @param {number} _scrollNum
4320
+ */
4321
+ const nextDifficulty = (_scrollNum = 1) => {
4322
+ g_keyObj.prevKey = g_headerObj.keyLabels[g_stateObj.scoreId];
4323
+ g_stateObj.scoreId = nextPos(g_stateObj.scoreId, _scrollNum, g_headerObj.keyLabels.length);
4324
+ setDifficulty(true);
4325
+ resetDifWindow();
4326
+ };
4313
4327
 
4314
- // 設定毎に個別のスプライトを作成し、その中にラベル・ボタン類を配置
4315
- const spriteList = setSpriteList(g_settingPos.option);
4328
+ /**
4329
+ * 譜面リストの作成
4330
+ * @param {object} _difList
4331
+ * @param {string} _targetKey
4332
+ */
4333
+ const makeDifList = (_difList, _targetKey = ``) => {
4334
+ let k = 0;
4335
+ let pos = 0;
4336
+ g_headerObj.keyLabels.forEach((keyLabel, j) => {
4337
+ if (_targetKey === `` || keyLabel === _targetKey) {
4338
+ let text = `${getKeyName(keyLabel)} / ${g_headerObj.difLabels[j]}`;
4339
+ if (g_headerObj.makerView) {
4340
+ text += ` (${g_headerObj.creatorNames[j]})`;
4341
+ }
4342
+ _difList.appendChild(makeDifLblCssButton(`dif${k}`, text, k, _ => {
4343
+ nextDifficulty(j - g_stateObj.scoreId);
4344
+ }, { btnStyle: (j === g_stateObj.scoreId ? `Setting` : `Default`) }));
4345
+ if (j === g_stateObj.scoreId) {
4346
+ pos = k + 6;
4347
+ }
4348
+ k++;
4349
+ }
4350
+ });
4351
+ const overlength = pos * g_limitObj.setLblHeight - parseInt(_difList.style.height);
4352
+ _difList.scrollTop = (overlength > 0 ? overlength : 0);
4353
+ };
4316
4354
 
4317
- // ---------------------------------------------------
4318
- // 難易度 (Difficulty)
4319
- // 縦位置: 0
4320
- spriteList.difficulty.appendChild(createLblSetting(`Difficulty`, -5));
4355
+ /**
4356
+ * 譜面セレクター位置の変更ボタン
4357
+ * @param {number} _scrollNum
4358
+ * @returns
4359
+ */
4360
+ const makeDifBtn = (_scrollNum = 1) => {
4361
+ const dir = _scrollNum === 1 ? `D` : `U`;
4362
+ return createCss2Button(`btnDif${dir}`, g_settingBtnObj.chara[dir], _ => {
4363
+ do {
4364
+ g_stateObj.scoreId = nextPos(g_stateObj.scoreId, _scrollNum, g_headerObj.keyLabels.length);
4365
+ } while (g_stateObj.filterKeys !== `` && g_stateObj.filterKeys !== g_headerObj.keyLabels[g_stateObj.scoreId]);
4366
+ setDifficulty(true);
4367
+ deleteChildspriteAll(`difList`);
4368
+ makeDifList(difList, g_stateObj.filterKeys);
4369
+ g_keyObj.prevKey = g_keyObj.currentKey;
4370
+ }, {
4371
+ x: 430 + _scrollNum * 10, y: 40, w: 20, h: 20, siz: g_limitObj.jdgCntsSiz,
4372
+ }, g_cssObj.button_Mini);
4373
+ };
4321
4374
 
4322
- /**
4323
- * 譜面変更セレクターの削除
4324
- */
4325
- const resetDifWindow = _ => {
4326
- if (document.querySelector(`#difList`) !== null) {
4327
- deleteChildspriteAll(`difList`);
4328
- [`difList`, `difCover`, `btnDifU`, `btnDifD`].forEach(obj => optionsprite.removeChild(document.getElementById(obj)));
4329
- g_currentPage = `option`;
4330
- setShortcutEvent(g_currentPage, _ => true, { displayFlg: false, dfEvtFlg: true });
4375
+ /**
4376
+ * 譜面変更セレクターの作成・再作成
4377
+ * @param {string} _key
4378
+ */
4379
+ const createDifWindow = (_key = ``) => {
4380
+ g_currentPage = `difSelector`;
4381
+ setShortcutEvent(g_currentPage);
4382
+ const difList = createEmptySprite(optionsprite, `difList`, g_windowObj.difList, g_cssObj.settings_DifSelector);
4383
+ const difCover = createEmptySprite(optionsprite, `difCover`, g_windowObj.difCover, g_cssObj.settings_DifSelector);
4384
+
4385
+ // リスト再作成
4386
+ makeDifList(difList, _key);
4387
+
4388
+ // ランダム選択
4389
+ difCover.appendChild(
4390
+ makeDifLblCssButton(`difRandom`, `RANDOM`, 0, _ => {
4391
+ nextDifficulty(Math.floor(Math.random() * g_headerObj.keyLabels.length));
4392
+ }, { w: g_limitObj.difCoverWidth })
4393
+ );
4394
+
4395
+ // 全リスト
4396
+ difCover.appendChild(
4397
+ makeDifLblCssButton(`keyFilter`, `ALL`, 1.5, _ => {
4398
+ resetDifWindow();
4399
+ g_stateObj.filterKeys = ``;
4400
+ createDifWindow();
4401
+ }, { w: g_limitObj.difCoverWidth, btnStyle: (g_stateObj.filterKeys === `` ? `Setting` : `Default`) })
4402
+ );
4403
+
4404
+ // キー別フィルタボタン作成
4405
+ let pos = 0;
4406
+ g_headerObj.keyLists.forEach((targetKey, m) => {
4407
+ difCover.appendChild(
4408
+ makeDifLblCssButton(`keyFilter${m}`, `${getKeyName(targetKey)} ${getStgDetailName('key')}`, m + 2.5, _ => {
4409
+ resetDifWindow();
4410
+ g_stateObj.filterKeys = targetKey;
4411
+ createDifWindow(targetKey);
4412
+ }, { w: g_limitObj.difCoverWidth, btnStyle: (g_stateObj.filterKeys === targetKey ? `Setting` : `Default`) })
4413
+ );
4414
+ if (g_stateObj.filterKeys === targetKey) {
4415
+ pos = m + 9;
4331
4416
  }
4417
+ });
4418
+ const overlength = pos * g_limitObj.setLblHeight - parseInt(difCover.style.height);
4419
+ difCover.scrollTop = (overlength > 0 ? overlength : 0);
4420
+
4421
+ multiAppend(optionsprite, makeDifBtn(-1), makeDifBtn());
4422
+ };
4423
+
4424
+ const changeDifficulty = (_num = 1) => {
4425
+ if (g_headerObj.difSelectorUse) {
4426
+ g_stateObj.filterKeys = ``;
4427
+ if (document.querySelector(`#difList`) === null) {
4428
+ g_keyObj.prevKey = g_keyObj.currentKey;
4429
+ createDifWindow();
4430
+ } else {
4431
+ resetDifWindow();
4432
+ }
4433
+ } else {
4434
+ nextDifficulty(_num);
4435
+ }
4436
+ };
4437
+
4438
+ /**
4439
+ * 譜面基礎データの取得
4440
+ * @param {number} _scoreId
4441
+ */
4442
+ const getScoreBaseData = _scoreId => {
4443
+ const arrowCnts = sumData(g_detailObj.arrowCnt[_scoreId]);
4444
+ const frzCnts = sumData(g_detailObj.frzCnt[_scoreId]);
4445
+ return {
4446
+ arrowCnts: arrowCnts,
4447
+ frzCnts: frzCnts,
4448
+ apm: Math.round((arrowCnts + frzCnts) / (g_detailObj.playingFrame[_scoreId] / g_fps / 60)),
4449
+ playingTime: transFrameToTimer(g_detailObj.playingFrame[_scoreId]),
4332
4450
  };
4451
+ };
4333
4452
 
4334
- /**
4335
- * 譜面選択処理
4336
- * @param {number} _scrollNum
4337
- */
4338
- const nextDifficulty = (_scrollNum = 1) => {
4339
- g_keyObj.prevKey = g_headerObj.keyLabels[g_stateObj.scoreId];
4340
- g_stateObj.scoreId = nextPos(g_stateObj.scoreId, _scrollNum, g_headerObj.keyLabels.length);
4341
- setDifficulty(true);
4342
- resetDifWindow();
4453
+ /**
4454
+ * 速度変化グラフの描画
4455
+ * @param {number} _scoreId
4456
+ */
4457
+ const drawSpeedGraph = _scoreId => {
4458
+ const startFrame = g_detailObj.startFrame[_scoreId];
4459
+ const playingFrame = g_detailObj.playingFrameWithBlank[_scoreId];
4460
+ const speedObj = {
4461
+ speed: { frame: [0], speed: [1], cnt: 0, strokeColor: g_graphColorObj.speed },
4462
+ boost: { frame: [0], speed: [1], cnt: 0, strokeColor: g_graphColorObj.boost }
4343
4463
  };
4344
4464
 
4345
- /**
4346
- * 譜面リストの作成
4347
- * @param {object} _difList
4348
- * @param {string} _targetKey
4349
- */
4350
- const makeDifList = (_difList, _targetKey = ``) => {
4351
- let k = 0;
4352
- let pos = 0;
4353
- g_headerObj.keyLabels.forEach((keyLabel, j) => {
4354
- if (_targetKey === `` || keyLabel === _targetKey) {
4355
- let text = `${getKeyName(keyLabel)} / ${g_headerObj.difLabels[j]}`;
4356
- if (g_headerObj.makerView) {
4357
- text += ` (${g_headerObj.creatorNames[j]})`;
4358
- }
4359
- _difList.appendChild(makeDifLblCssButton(`dif${k}`, text, k, _ => {
4360
- nextDifficulty(j - g_stateObj.scoreId);
4361
- }, { btnStyle: (j === g_stateObj.scoreId ? `Setting` : `Default`) }));
4362
- if (j === g_stateObj.scoreId) {
4363
- pos = k + 6;
4465
+ Object.keys(speedObj).forEach(speedType => {
4466
+ let frame = speedObj[speedType].frame;
4467
+ let speed = speedObj[speedType].speed;
4468
+ const speedData = g_detailObj[`${speedType}Data`][_scoreId];
4469
+
4470
+ if (speedData !== undefined) {
4471
+ for (let i = 0; i < speedData.length; i += 2) {
4472
+ if (speedData[i] >= startFrame) {
4473
+ frame.push(speedData[i] - startFrame);
4474
+ speed.push(speedData[i + 1]);
4364
4475
  }
4365
- k++;
4476
+ speedObj[speedType].cnt++;
4366
4477
  }
4478
+ frame.push(playingFrame);
4479
+ speed.push(speed[speed.length - 1]);
4480
+ }
4481
+ });
4482
+
4483
+ const canvas = document.querySelector(`#graphSpeed`);
4484
+ const context = canvas.getContext(`2d`);
4485
+ drawBaseLine(context);
4486
+
4487
+ Object.keys(speedObj).forEach((speedType, j) => {
4488
+ context.beginPath();
4489
+ let preY;
4490
+
4491
+ for (let i = 0; i < speedObj[speedType].frame.length; i++) {
4492
+ const x = speedObj[speedType].frame[i] * (g_limitObj.graphWidth - 30) / playingFrame + 30;
4493
+ const y = (speedObj[speedType].speed[i] - 1) * -90 + 105;
4494
+
4495
+ context.lineTo(x, preY);
4496
+ context.lineTo(x, y);
4497
+ preY = y;
4498
+ }
4499
+
4500
+ context.lineWidth = 1;
4501
+ context.strokeStyle = speedObj[speedType].strokeColor;
4502
+ context.stroke();
4503
+
4504
+ const lineX = (speedType === `speed`) ? 125 : 210;
4505
+ context.beginPath();
4506
+ context.moveTo(lineX, 215);
4507
+ context.lineTo(lineX + 30, 215);
4508
+ context.stroke();
4509
+ context.font = `${g_limitObj.difSelectorSiz}px ${getBasicFont()}`;
4510
+ context.fillText(speedType, lineX + 35, 218);
4511
+
4512
+ updateScoreDetailLabel(`Speed`, `${speedType}S`, speedObj[speedType].cnt, j, g_lblNameObj[`s_${speedType}`]);
4513
+ });
4514
+ };
4515
+
4516
+ /**
4517
+ * 譜面密度グラフの描画
4518
+ * @param {number} _scoreId
4519
+ */
4520
+ const drawDensityGraph = _scoreId => {
4521
+
4522
+ const canvas = document.querySelector(`#graphDensity`);
4523
+ const context = canvas.getContext(`2d`);
4524
+ drawBaseLine(context);
4525
+ for (let j = 0; j < g_limitObj.densityDivision; j++) {
4526
+ context.beginPath();
4527
+ [``, `2Push`, `3Push`].forEach(val => {
4528
+ context.fillStyle = (g_detailObj.maxDensity[_scoreId].includes(j) ? g_graphColorObj[`max${val}`] : g_graphColorObj[`default${val}`]);
4529
+ context.fillRect(16 * j * 16 / g_limitObj.densityDivision + 30, 195 - 9 * g_detailObj[`density${val}Data`][_scoreId][j] / 10,
4530
+ 15.5 * 16 / g_limitObj.densityDivision, 9 * g_detailObj[`density${val}Diff`][_scoreId][j] / 10
4531
+ );
4367
4532
  });
4368
- const overlength = pos * g_limitObj.setLblHeight - parseInt(difList.style.height);
4369
- difList.scrollTop = (overlength > 0 ? overlength : 0);
4370
- };
4533
+ context.stroke();
4534
+ }
4535
+
4536
+ const lineNames = [`Single`, `Chord`, `Triad+`];
4537
+ Object.keys(g_graphColorObj).filter(val => val.indexOf(`max`) !== -1).forEach((val, j) => {
4538
+ const lineX = 70 + j * 70;
4539
+
4540
+ context.beginPath();
4541
+ context.lineWidth = 3;
4542
+ context.fillStyle = g_rankObj.rankColorAllPerfect;
4543
+ context.strokeStyle = g_graphColorObj[val];
4544
+ context.moveTo(lineX, 215);
4545
+ context.lineTo(lineX + 20, 215);
4546
+ context.stroke();
4547
+ context.font = `${g_limitObj.difSelectorSiz}px ${getBasicFont()}`;
4548
+ context.fillText(lineNames[j], lineX + 20, 218);
4549
+ });
4371
4550
 
4372
- /**
4373
- * 譜面セレクター位置の変更ボタン
4374
- * @param {number} _scrollNum
4375
- * @returns
4376
- */
4377
- const makeDifBtn = (_scrollNum = 1) => {
4378
- const dir = _scrollNum === 1 ? `D` : `U`;
4379
- return createCss2Button(`btnDif${dir}`, g_settingBtnObj.chara[dir], _ => {
4380
- do {
4381
- g_stateObj.scoreId = nextPos(g_stateObj.scoreId, _scrollNum, g_headerObj.keyLabels.length);
4382
- } while (g_stateObj.filterKeys !== `` && g_stateObj.filterKeys !== g_headerObj.keyLabels[g_stateObj.scoreId]);
4383
- setDifficulty(true);
4384
- deleteChildspriteAll(`difList`);
4385
- makeDifList(difList, g_stateObj.filterKeys);
4386
- if (g_keyObj.prevKey !== g_keyObj.currentKey) {
4387
- g_keyObj.prevKey = g_keyObj.currentKey;
4388
- }
4389
- }, {
4390
- x: 430 + _scrollNum * 10, y: 40, w: 20, h: 20, siz: g_limitObj.jdgCntsSiz,
4391
- }, g_cssObj.button_Mini);
4392
- };
4551
+ const obj = getScoreBaseData(_scoreId);
4552
+ updateScoreDetailLabel(`Density`, `APM`, obj.apm, 0, g_lblNameObj.s_apm);
4553
+ updateScoreDetailLabel(`Density`, `Time`, obj.playingTime, 1, g_lblNameObj.s_time);
4554
+ updateScoreDetailLabel(`Density`, `Arrow`, obj.arrowCnts, 3, g_lblNameObj.s_arrow);
4555
+ updateScoreDetailLabel(`Density`, `Frz`, obj.frzCnts, 4, g_lblNameObj.s_frz);
4556
+ };
4557
+
4558
+ /**
4559
+ * 譜面明細内の補足情報の登録・更新
4560
+ * @param {string} _name 表示する譜面明細のラベル
4561
+ * @param {string} _label
4562
+ * @param {string} _value
4563
+ * @param {number} _pos 表示位置
4564
+ * @param {string} _labelname
4565
+ */
4566
+ const updateScoreDetailLabel = (_name, _label, _value, _pos = 0, _labelname = _label) => {
4567
+ const baseLabel = (_bLabel, _bLabelname, _bAlign) =>
4568
+ document.querySelector(`#detail${_name}`).appendChild(
4569
+ createDivCss2Label(`${_bLabel}`, `${_bLabelname}`, {
4570
+ x: 10, y: 105 + _pos * 20, w: 100, h: 20, siz: g_limitObj.difSelectorSiz, align: _bAlign,
4571
+ })
4572
+ );
4573
+ if (document.querySelector(`#data${_label}`) === null) {
4574
+ baseLabel(`lbl${_label}`, `${_labelname}`, C_ALIGN_LEFT);
4575
+ baseLabel(`data${_label}`, `${_value}`, C_ALIGN_RIGHT);
4576
+ } else {
4577
+ document.querySelector(`#data${_label}`).textContent = `${_value}`;
4578
+ }
4579
+ };
4393
4580
 
4581
+ /**
4582
+ * グラフの縦軸を描画
4583
+ * @param {object} _context
4584
+ * @param {number} _resolution
4585
+ */
4586
+ const drawBaseLine = (_context, _resolution = 10) => {
4587
+ _context.clearRect(0, 0, g_limitObj.graphWidth, g_limitObj.graphHeight);
4588
+
4589
+ for (let j = 0; j <= 2 * _resolution; j += 5) {
4590
+ drawLine(_context, j / _resolution, `main`, 2);
4591
+ for (let k = 1; k < 5; k++) {
4592
+ drawLine(_context, (j + k) / _resolution, `sub`, 2);
4593
+ }
4594
+ }
4595
+ };
4596
+
4597
+ /**
4598
+ * グラフ上に目盛を表示
4599
+ * @param {object} _context
4600
+ * @param {number} _y
4601
+ * @param {string} _lineType
4602
+ * @param {number} _fixed
4603
+ */
4604
+ const drawLine = (_context, _y, _lineType, _fixed = 0) => {
4605
+ const lineY = (_y - 1) * -90 + 105;
4606
+ _context.beginPath();
4607
+ _context.moveTo(30, lineY);
4608
+ _context.lineTo(g_limitObj.graphWidth, lineY);
4609
+ _context.lineWidth = 1;
4610
+
4611
+ if (_lineType === `main`) {
4612
+ const textBaseObj = document.querySelector(`#lnkDifficulty`);
4613
+ const textColor = window.getComputedStyle(textBaseObj, ``).color;
4614
+ _context.strokeStyle = textColor;
4615
+ _context.font = `12px ${getBasicFont()}`;
4616
+ _context.fillStyle = textColor;
4617
+ _context.fillText(_y.toFixed(_fixed), 0, lineY + 4);
4618
+ } else {
4619
+ _context.strokeStyle = `#646464`;
4620
+ }
4621
+ _context.stroke();
4622
+ };
4623
+
4624
+ /**
4625
+ * 譜面の難易度情報用ラベル作成
4626
+ * @param {number} _scoreId
4627
+ */
4628
+ const makeDifInfoLabels = _scoreId => {
4629
+
4630
+ // ツール難易度
4631
+ const detailToolDif = document.querySelector(`#detailToolDif`);
4394
4632
  /**
4395
- * 譜面変更セレクターの作成・再作成
4396
- * @param {string} _key
4633
+ * 譜面の難易度情報ラベルの作成
4634
+ * @param {string} _lbl
4635
+ * @param {string} _data
4636
+ * @param {object} _obj
4397
4637
  */
4398
- const createDifWindow = (_key = ``) => {
4399
- g_currentPage = `difSelector`;
4400
- setShortcutEvent(g_currentPage);
4401
- const difList = createEmptySprite(optionsprite, `difList`, g_windowObj.difList, g_cssObj.settings_DifSelector);
4402
- const difCover = createEmptySprite(optionsprite, `difCover`, g_windowObj.difCover, g_cssObj.settings_DifSelector);
4638
+ const makeDifInfoLabel = (_lbl, _data, { x = 130, y = 25, w = 125, h = 35, siz = g_limitObj.difSelectorSiz, ...rest } = {}) =>
4639
+ createDivCss2Label(_lbl, _data, { x, y, w, h, siz, align: C_ALIGN_LEFT, ...rest });
4640
+
4641
+ let printData = ``;
4642
+ for (let j = 0; j < g_detailObj.arrowCnt.length; j++) {
4643
+ const obj = getScoreBaseData(j);
4644
+ printData +=
4645
+ // 譜面番号
4646
+ `[${j + 1}]\t` +
4647
+ // ツール値
4648
+ `${g_detailObj.toolDif[j].tool}\t` +
4649
+ // 同時
4650
+ `${g_detailObj.toolDif[j].douji}\t` +
4651
+ // 縦連
4652
+ `${g_detailObj.toolDif[j].tate}\t` +
4653
+ // 総矢印数
4654
+ `${(obj.arrowCnts + obj.frzCnts)}\t` +
4655
+ // 矢印
4656
+ `${obj.arrowCnts}\t` +
4657
+ // フリーズアロー
4658
+ `${obj.frzCnts}\t` +
4659
+ // APM
4660
+ `${obj.apm}\t` +
4661
+ // 時間(分秒)
4662
+ `${obj.playingTime}\r\n`;
4663
+ }
4664
+ multiAppend(detailToolDif,
4665
+ makeDifInfoLabel(`lblTooldif`, g_lblNameObj.s_level, g_lblPosObj.lblTooldif),
4666
+ makeDifInfoLabel(`dataTooldif`, ``, g_lblPosObj.dataTooldif),
4667
+ makeDifInfoLabel(`lblDouji`, g_lblNameObj.s_douji, g_lblPosObj.lblDouji),
4668
+ makeDifInfoLabel(`lblTate`, g_lblNameObj.s_tate, g_lblPosObj.lblTate),
4669
+ makeDifInfoLabel(`dataDouji`, ``, g_lblPosObj.dataDouji),
4670
+ makeDifInfoLabel(`dataTate`, ``, g_lblPosObj.dataTate),
4671
+ makeDifInfoLabel(`lblArrowInfo`, g_lblNameObj.s_cnts, g_lblPosObj.lblArrowInfo),
4672
+ makeDifInfoLabel(`dataArrowInfo`, ``, g_lblPosObj.dataArrowInfo),
4673
+ makeDifInfoLabel(`lblArrowInfo2`, ``, g_lblPosObj.lblArrowInfo2),
4674
+ makeDifInfoLabel(`dataArrowInfo2`, ``, g_lblPosObj.dataArrowInfo2),
4675
+ makeDifLblCssButton(`lnkDifInfo`, g_lblNameObj.s_print, 8, _ => {
4676
+ copyTextToClipboard(
4677
+ `****** ${g_lblNameObj.s_printTitle} [${g_version}] ******\r\n\r\n`
4678
+ + `\t${g_lblNameObj.s_printHeader}\r\n\r\n${printData}`, g_msgInfoObj.I_0003
4679
+ );
4680
+ }, g_lblPosObj.lnkDifInfo),
4681
+ );
4682
+ createScText(lnkDifInfo, `DifInfo`, { targetLabel: `lnkDifInfo`, x: -10 });
4683
+ };
4403
4684
 
4404
- // リスト再作成
4405
- makeDifList(difList, _key);
4685
+ /**
4686
+ * 譜面の難易度情報更新
4687
+ * @param {number} _scoreId
4688
+ */
4689
+ const makeDifInfo = _scoreId => {
4406
4690
 
4407
- // ランダム選択
4408
- difCover.appendChild(
4409
- makeDifLblCssButton(`difRandom`, `RANDOM`, 0, _ => {
4410
- nextDifficulty(Math.floor(Math.random() * g_headerObj.keyLabels.length));
4411
- }, { w: g_limitObj.difCoverWidth })
4412
- );
4691
+ const arrowCnts = sumData(g_detailObj.arrowCnt[_scoreId]);
4692
+ const frzCnts = sumData(g_detailObj.frzCnt[_scoreId]);
4693
+ const push3CntStr = (g_detailObj.toolDif[_scoreId].push3.length === 0 ? `None` : `(${g_detailObj.toolDif[_scoreId].push3})`);
4413
4694
 
4414
- // 全リスト
4415
- difCover.appendChild(
4416
- makeDifLblCssButton(`keyFilter`, `ALL`, 1.5, _ => {
4417
- resetDifWindow();
4418
- g_stateObj.filterKeys = ``;
4419
- createDifWindow();
4420
- }, { w: g_limitObj.difCoverWidth, btnStyle: (g_stateObj.filterKeys === `` ? `Setting` : `Default`) })
4421
- );
4695
+ if (document.querySelector(`#lblTooldif`) === null) {
4696
+ makeDifInfoLabels(_scoreId);
4697
+ }
4698
+ dataTooldif.textContent = g_detailObj.toolDif[_scoreId].tool;
4699
+ dataDouji.textContent = g_detailObj.toolDif[_scoreId].douji;
4700
+ dataTate.textContent = g_detailObj.toolDif[_scoreId].tate;
4701
+ lblArrowInfo2.innerHTML = g_lblNameObj.s_linecnts.split(`{0}`).join(g_detailObj.toolDif[_scoreId].push3cnt);
4702
+ dataArrowInfo.innerHTML = `${arrowCnts + frzCnts} <span style="font-size:${g_limitObj.difSelectorSiz}px;">(${arrowCnts} + ${frzCnts})</span>`;
4703
+ dataArrowInfo2.innerHTML = `<br>(${g_detailObj.arrowCnt[_scoreId]})<br><br>
4704
+ (${g_detailObj.frzCnt[_scoreId]})<br><br>
4705
+ ${push3CntStr}`.split(`,`).join(`/`);
4706
+ };
4422
4707
 
4423
- // キー別フィルタボタン作成
4424
- let pos = 0;
4425
- g_headerObj.keyLists.forEach((targetKey, m) => {
4426
- difCover.appendChild(
4427
- makeDifLblCssButton(`keyFilter${m}`, `${getKeyName(targetKey)} key`, m + 2.5, _ => {
4428
- resetDifWindow();
4429
- g_stateObj.filterKeys = targetKey;
4430
- createDifWindow(targetKey);
4431
- }, { w: g_limitObj.difCoverWidth, btnStyle: (g_stateObj.filterKeys === targetKey ? `Setting` : `Default`) })
4432
- );
4433
- if (g_stateObj.filterKeys === targetKey) {
4434
- pos = m + 9;
4708
+ /**
4709
+ * 譜面初期化処理
4710
+ * - 譜面の基本設定(キー数、初期速度、リバース、ゲージ設定)をここで行う
4711
+ * - g_canLoadDifInfoFlg は譜面初期化フラグで、初期化したくない場合は対象画面にて false にしておく
4712
+ * (Display設定画面、キーコンフィグ画面では通常OFF)
4713
+ * この関数を実行後、このフラグはONに戻るようになっている
4714
+ * - [キーコン]->[初期化]->[名称設定]の順に配置する。
4715
+ * 初期化処理にてキー数関連の設定を行っているため、この順序で無いとデータが正しく格納されない
4716
+ */
4717
+ const setDifficulty = (_initFlg) => {
4718
+
4719
+ const getCurrentNo = (_list, _target) => roundZero(_list.findIndex(item => item === _target));
4720
+
4721
+ // ---------------------------------------------------
4722
+ // 1. キーコンフィグ設定 (KeyConfig)
4723
+ g_keyObj.currentKey = g_headerObj.keyLabels[g_stateObj.scoreId];
4724
+ const isNotSameKey = (g_keyObj.prevKey !== g_keyObj.currentKey);
4725
+
4726
+ if (g_headerObj.dummyScoreNos !== undefined) {
4727
+ g_stateObj.dummyId = setIntVal(g_headerObj.dummyScoreNos[g_stateObj.scoreId], ``);
4728
+ }
4729
+ // 特殊キーフラグ
4730
+ g_stateObj.extraKeyFlg = g_headerObj.keyExtraList.includes(g_keyObj.currentKey);
4731
+
4732
+ // ---------------------------------------------------
4733
+ // 2. 初期化設定
4734
+
4735
+ // 保存した設定の再読込条件(設定画面切り替え時はスキップ)
4736
+ // ローカルストレージで保存した設定を呼び出し
4737
+ if ((g_canLoadDifInfoFlg && (isNotSameKey && g_stateObj.dataSaveFlg)) || _initFlg) {
4738
+
4739
+ if (isNotSameKey && g_keyObj.prevKey !== `Dummy`) {
4740
+ // キーパターン初期化
4741
+ g_keyObj.currentPtn = 0;
4742
+ g_keycons.keySwitchNum = 0;
4743
+ }
4744
+ const hasKeyStorage = localStorage.getItem(`danonicw-${g_keyObj.currentKey}k`);
4745
+ let storageObj, addKey = ``;
4746
+
4747
+ if (!g_stateObj.extraKeyFlg) {
4748
+
4749
+ // キー別のローカルストレージの初期設定 ※特殊キーは除く
4750
+ g_localKeyStorage = hasKeyStorage ? JSON.parse(hasKeyStorage) : {
4751
+ reverse: C_FLG_OFF,
4752
+ keyCtrl: [[]],
4753
+ keyCtrlPtn: 0,
4754
+ setColor: [],
4755
+ };
4756
+ storageObj = g_localKeyStorage;
4757
+
4758
+ } else {
4759
+ storageObj = g_localStorage;
4760
+ addKey = g_keyObj.currentKey;
4761
+ }
4762
+ if (isNotSameKey) {
4763
+ getKeyReverse(storageObj, addKey);
4764
+
4765
+ // キーコンフィグ初期値設定
4766
+ if (storageObj[`keyCtrlPtn${addKey}`] === undefined) {
4767
+ storageObj[`keyCtrlPtn${addKey}`] = 0;
4435
4768
  }
4436
- });
4437
- const overlength = pos * g_limitObj.setLblHeight - parseInt(difCover.style.height);
4438
- difCover.scrollTop = (overlength > 0 ? overlength : 0);
4769
+ getKeyCtrl(storageObj, addKey);
4439
4770
 
4440
- multiAppend(optionsprite, makeDifBtn(-1), makeDifBtn());
4441
- };
4771
+ // カラーセット初期値設定
4772
+ if (storageObj[`setColor${addKey}`] === undefined) {
4773
+ storageObj[`setColor${addKey}`] = [];
4774
+ }
4775
+ if (storageObj[`setColor${addKey}`].length > 0) {
4776
+ g_keycons.colorTypes = addValtoArray(g_keycons.colorTypes, g_keycons.colorSelf);
4777
+ resetColorType({ _fromObj: storageObj, _from: addKey, _to: g_keycons.colorSelf });
4778
+ resetColorType({ _fromObj: storageObj, _from: addKey, _toObj: g_dfColorObj, _to: g_keycons.colorSelf });
4442
4779
 
4443
- const changeDifficulty = (_num = 1) => {
4444
- if (g_headerObj.difSelectorUse) {
4445
- g_stateObj.filterKeys = ``;
4446
- if (document.querySelector(`#difList`) === null) {
4447
- createDifWindow();
4448
4780
  } else {
4449
- resetDifWindow();
4781
+ if (g_localStorage.colorType === g_keycons.colorSelf) {
4782
+ g_colorType = `Default`;
4783
+ }
4784
+ g_keycons.colorTypes = g_keycons.colorTypes.filter(val => val !== g_keycons.colorSelf);
4450
4785
  }
4451
- } else {
4452
- nextDifficulty(_num);
4786
+
4787
+ const keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`;
4788
+
4789
+ // カラーグループ、シャッフルグループの設定
4790
+ g_keycons.groups.forEach(type => {
4791
+ resetGroupList(type, keyCtrlPtn);
4792
+ if (g_keyObj.currentPtn === -1) {
4793
+ const storageKeyName = storageObj[`${type}${addKey}`] || storageObj[`${type}${g_keyObj.currentKey}_-1_-1`];
4794
+ if (storageKeyName !== undefined) {
4795
+ g_keyObj[`${type}${g_keyObj.currentKey}_-1`] = structuredClone(storageKeyName);
4796
+ }
4797
+ g_keyObj[`${type}${g_keyObj.currentKey}_-1_-1`] = structuredClone(g_keyObj[`${type}${g_keyObj.currentKey}_-1`]);
4798
+ } else {
4799
+ g_keyObj[`${type}${keyCtrlPtn}`] = structuredClone(g_keyObj[`${type}${keyCtrlPtn}_0`]);
4800
+ }
4801
+ });
4802
+
4453
4803
  }
4454
- };
4804
+
4805
+ const keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`;
4806
+ if (g_headerObj.keyRetryDef === C_KEY_RETRY) {
4807
+ g_headerObj.keyRetry = setIntVal(getKeyCtrlVal(g_keyObj[`keyRetry${keyCtrlPtn}`]), g_headerObj.keyRetryDef);
4808
+ }
4809
+ if (g_headerObj.keyTitleBackDef === C_KEY_TITLEBACK) {
4810
+ g_headerObj.keyTitleBack = setIntVal(getKeyCtrlVal(g_keyObj[`keyTitleBack${keyCtrlPtn}`]), g_headerObj.keyTitleBackDef);
4811
+ }
4812
+ }
4813
+
4814
+ // スクロール設定用の配列を入れ替え
4815
+ g_settings.scrolls = structuredClone(
4816
+ typeof g_keyObj[`scrollDir${g_keyObj.currentKey}_${g_keyObj.currentPtn}`] === C_TYP_OBJECT ?
4817
+ Object.keys(g_keyObj[`scrollDir${g_keyObj.currentKey}_${g_keyObj.currentPtn}`]) : g_keyObj.scrollName_def
4818
+ );
4819
+
4820
+ // アシスト設定の配列を入れ替え
4821
+ g_settings.autoPlays = (typeof g_keyObj[`assistPos${g_keyObj.currentKey}_${g_keyObj.currentPtn}`] === C_TYP_OBJECT ?
4822
+ g_autoPlaysBase.concat(Object.keys(g_keyObj[`assistPos${g_keyObj.currentKey}_${g_keyObj.currentPtn}`])) :
4823
+ g_autoPlaysBase.concat());
4824
+
4825
+ // 速度、ゲージ、スクロール、アシスト設定のカーソル位置調整
4826
+ if (_initFlg) {
4827
+ g_stateObj.speed = g_headerObj.initSpeeds[g_stateObj.scoreId];
4828
+ g_settings.speedNum = getCurrentNo(g_settings.speeds, g_stateObj.speed);
4829
+ g_settings.gaugeNum = 0;
4830
+ }
4831
+ g_settings.scrollNum = getCurrentNo(g_settings.scrolls, g_stateObj.scroll);
4832
+ g_settings.autoPlayNum = getCurrentNo(g_settings.autoPlays, g_stateObj.autoPlay);
4833
+
4834
+ // ---------------------------------------------------
4835
+ // 3. 名称の設定
4836
+
4837
+ // 譜面名設定 (Difficulty)
4838
+ const difWidth = parseFloat(lnkDifficulty.style.width);
4839
+ const difNames = [`${getKeyName(g_keyObj.currentKey)} ${getStgDetailName('key')} / ${g_headerObj.difLabels[g_stateObj.scoreId]}`];
4840
+ lnkDifficulty.style.fontSize = `${getFontSize(difNames[0], difWidth, getBasicFont(), g_limitObj.setLblSiz)}px`;
4841
+
4842
+ if (g_headerObj.makerView) {
4843
+ difNames.push(`(${g_headerObj.creatorNames[g_stateObj.scoreId]})`);
4844
+ difNames.forEach((difName, j) => {
4845
+ const tmpSize = getFontSize(difName, difWidth, getBasicFont(), 14);
4846
+ difNames[j] = `<span style="font-size:${tmpSize}px">${difName}</span>`;
4847
+ });
4848
+ }
4849
+ lnkDifficulty.innerHTML = difNames.join(``);
4850
+
4851
+ // 速度設定 (Speed)
4852
+ setSetting(0, `speed`, ` ${g_lblNameObj.multi}`);
4853
+ if (g_headerObj.scoreDetailUse) {
4854
+ drawSpeedGraph(g_stateObj.scoreId);
4855
+ drawDensityGraph(g_stateObj.scoreId);
4856
+ makeDifInfo(g_stateObj.scoreId);
4857
+ }
4858
+
4859
+ // リバース設定 (Reverse, Scroll)
4860
+ if (g_headerObj.scrollUse) {
4861
+ g_stateObj.scroll = g_settings.scrolls[g_settings.scrollNum];
4862
+ const [visibleScr, hiddenScr] = (g_settings.scrolls.length > 1 ? [`scroll`, `reverse`] : [`reverse`, `scroll`]);
4863
+ document.getElementById(`${visibleScr}Sprite`).style.display = C_DIS_INHERIT;
4864
+ document.getElementById(`${hiddenScr}Sprite`).style.display = C_DIS_NONE;
4865
+ setSetting(0, visibleScr);
4866
+
4867
+ g_shortcutObj.option.KeyR.id = g_settings.scrolls.includes(`Reverse`) ?
4868
+ g_shortcutObj.option.KeyR.exId : g_shortcutObj.option.KeyR.dfId;
4869
+
4870
+ if (g_settings.scrolls.length > 1) {
4871
+ setReverseView(document.querySelector(`#btnReverse`));
4872
+ }
4873
+ } else {
4874
+ g_settings.scrolls = structuredClone(g_keyObj.scrollName_def);
4875
+ setSetting(0, `reverse`);
4876
+ }
4877
+
4878
+ // オート・アシスト設定 (AutoPlay)
4879
+ g_stateObj.autoPlay = g_settings.autoPlays[g_settings.autoPlayNum];
4880
+ lnkAutoPlay.textContent = getStgDetailName(g_stateObj.autoPlay);
4881
+
4882
+ // ゲージ設定 (Gauge)
4883
+ const defaultCustomGauge = g_gaugeOptionObj.custom0 || g_gaugeOptionObj.customDefault;
4884
+ if (hasVal(defaultCustomGauge)) {
4885
+ g_gaugeOptionObj.custom = (g_gaugeOptionObj[`custom${g_stateObj.scoreId}`] || defaultCustomGauge).concat();
4886
+ g_gaugeOptionObj.varCustom = (g_gaugeOptionObj[`varCustom${g_stateObj.scoreId}`] || g_gaugeOptionObj.varCustom0 || g_gaugeOptionObj.varCustomDefault).concat();
4887
+ }
4888
+ setGauge(0);
4889
+
4890
+ // ユーザカスタムイベント(初期)
4891
+ g_customJsObj.difficulty.forEach(func => func(_initFlg, g_canLoadDifInfoFlg));
4892
+
4893
+ // ---------------------------------------------------
4894
+ // 4. 譜面初期情報ロード許可フラグの設定
4895
+ g_canLoadDifInfoFlg = true;
4896
+ };
4897
+
4898
+ /**
4899
+ * 設定・オプション画面のラベル・ボタン処理の描画
4900
+ * @param {Object} _sprite 基準とするスプライト(ここで指定する座標は、そのスプライトからの相対位置)
4901
+ */
4902
+ const createOptionWindow = _sprite => {
4903
+
4904
+ // 各ボタン用のスプライトを作成
4905
+ const optionsprite = createOptionSprite(_sprite);
4906
+
4907
+ // 設定毎に個別のスプライトを作成し、その中にラベル・ボタン類を配置
4908
+ const spriteList = setSpriteList(g_settingPos.option);
4909
+
4910
+ // ---------------------------------------------------
4911
+ // 難易度 (Difficulty)
4912
+ // 縦位置: 0
4913
+ spriteList.difficulty.appendChild(createLblSetting(`Difficulty`, -5));
4914
+
4455
4915
  const lnkDifficulty = makeSettingLblCssButton(`lnkDifficulty`, ``, 0, _ => changeDifficulty(), {
4456
4916
  y: -10, h: g_limitObj.setLblHeight + 10, cxtFunc: _ => changeDifficulty(-1),
4457
4917
  });
@@ -4575,276 +5035,6 @@ const createOptionWindow = _sprite => {
4575
5035
  g_shortcutObj.option.KeyQ.id = g_settings.scoreDetailCursors[0];
4576
5036
  };
4577
5037
 
4578
- /**
4579
- * 譜面基礎データの取得
4580
- * @param {number} _scoreId
4581
- */
4582
- const getScoreBaseData = _scoreId => {
4583
- const arrowCnts = sumData(g_detailObj.arrowCnt[_scoreId]);
4584
- const frzCnts = sumData(g_detailObj.frzCnt[_scoreId]);
4585
- return {
4586
- arrowCnts: arrowCnts,
4587
- frzCnts: frzCnts,
4588
- apm: Math.round((arrowCnts + frzCnts) / (g_detailObj.playingFrame[_scoreId] / g_fps / 60)),
4589
- playingTime: transFrameToTimer(g_detailObj.playingFrame[_scoreId]),
4590
- };
4591
- };
4592
-
4593
- /**
4594
- * 速度変化グラフの描画
4595
- * @param {number} _scoreId
4596
- */
4597
- const drawSpeedGraph = _scoreId => {
4598
- const startFrame = g_detailObj.startFrame[_scoreId];
4599
- const playingFrame = g_detailObj.playingFrameWithBlank[_scoreId];
4600
- const speedObj = {
4601
- speed: { frame: [0], speed: [1], cnt: 0, strokeColor: g_graphColorObj.speed },
4602
- boost: { frame: [0], speed: [1], cnt: 0, strokeColor: g_graphColorObj.boost }
4603
- };
4604
-
4605
- Object.keys(speedObj).forEach(speedType => {
4606
- let frame = speedObj[speedType].frame;
4607
- let speed = speedObj[speedType].speed;
4608
- const speedData = g_detailObj[`${speedType}Data`][_scoreId];
4609
-
4610
- if (speedData !== undefined) {
4611
- for (let i = 0; i < speedData.length; i += 2) {
4612
- if (speedData[i] >= startFrame) {
4613
- frame.push(speedData[i] - startFrame);
4614
- speed.push(speedData[i + 1]);
4615
- }
4616
- speedObj[speedType].cnt++;
4617
- }
4618
- frame.push(playingFrame);
4619
- speed.push(speed[speed.length - 1]);
4620
- }
4621
- });
4622
-
4623
- const canvas = document.querySelector(`#graphSpeed`);
4624
- const context = canvas.getContext(`2d`);
4625
- drawBaseLine(context);
4626
-
4627
- Object.keys(speedObj).forEach((speedType, j) => {
4628
- context.beginPath();
4629
- let preY;
4630
-
4631
- for (let i = 0; i < speedObj[speedType].frame.length; i++) {
4632
- const x = speedObj[speedType].frame[i] * (g_limitObj.graphWidth - 30) / playingFrame + 30;
4633
- const y = (speedObj[speedType].speed[i] - 1) * -90 + 105;
4634
-
4635
- context.lineTo(x, preY);
4636
- context.lineTo(x, y);
4637
- preY = y;
4638
- }
4639
-
4640
- context.lineWidth = 1;
4641
- context.strokeStyle = speedObj[speedType].strokeColor;
4642
- context.stroke();
4643
-
4644
- const lineX = (speedType === `speed`) ? 125 : 210;
4645
- context.beginPath();
4646
- context.moveTo(lineX, 215);
4647
- context.lineTo(lineX + 30, 215);
4648
- context.stroke();
4649
- context.font = `${g_limitObj.difSelectorSiz}px ${getBasicFont()}`;
4650
- context.fillText(speedType, lineX + 35, 218);
4651
-
4652
- updateScoreDetailLabel(`Speed`, `${speedType}S`, speedObj[speedType].cnt, j, g_lblNameObj[`s_${speedType}`]);
4653
- });
4654
- };
4655
-
4656
- /**
4657
- * 譜面密度グラフの描画
4658
- * @param {number} _scoreId
4659
- */
4660
- const drawDensityGraph = _scoreId => {
4661
-
4662
- const canvas = document.querySelector(`#graphDensity`);
4663
- const context = canvas.getContext(`2d`);
4664
- drawBaseLine(context);
4665
- for (let j = 0; j < g_limitObj.densityDivision; j++) {
4666
- context.beginPath();
4667
- [``, `2Push`, `3Push`].forEach(val => {
4668
- context.fillStyle = (g_detailObj.maxDensity[_scoreId].includes(j) ? g_graphColorObj[`max${val}`] : g_graphColorObj[`default${val}`]);
4669
- context.fillRect(16 * j * 16 / g_limitObj.densityDivision + 30, 195 - 9 * g_detailObj[`density${val}Data`][_scoreId][j] / 10,
4670
- 15.5 * 16 / g_limitObj.densityDivision, 9 * g_detailObj[`density${val}Diff`][_scoreId][j] / 10
4671
- );
4672
- });
4673
- context.stroke();
4674
- }
4675
-
4676
- const lineNames = [`Single`, `Chord`, `Triad+`];
4677
- Object.keys(g_graphColorObj).filter(val => val.indexOf(`max`) !== -1).forEach((val, j) => {
4678
- const lineX = 70 + j * 70;
4679
-
4680
- context.beginPath();
4681
- context.lineWidth = 3;
4682
- context.fillStyle = g_rankObj.rankColorAllPerfect;
4683
- context.strokeStyle = g_graphColorObj[val];
4684
- context.moveTo(lineX, 215);
4685
- context.lineTo(lineX + 20, 215);
4686
- context.stroke();
4687
- context.font = `${g_limitObj.difSelectorSiz}px ${getBasicFont()}`;
4688
- context.fillText(lineNames[j], lineX + 20, 218);
4689
- });
4690
-
4691
- const obj = getScoreBaseData(_scoreId);
4692
- updateScoreDetailLabel(`Density`, `APM`, obj.apm, 0, g_lblNameObj.s_apm);
4693
- updateScoreDetailLabel(`Density`, `Time`, obj.playingTime, 1, g_lblNameObj.s_time);
4694
- updateScoreDetailLabel(`Density`, `Arrow`, obj.arrowCnts, 3, g_lblNameObj.s_arrow);
4695
- updateScoreDetailLabel(`Density`, `Frz`, obj.frzCnts, 4, g_lblNameObj.s_frz);
4696
- };
4697
-
4698
- /**
4699
- * 譜面明細内の補足情報の登録・更新
4700
- * @param {string} _name 表示する譜面明細のラベル
4701
- * @param {string} _label
4702
- * @param {string} _value
4703
- * @param {number} _pos 表示位置
4704
- * @param {string} _labelname
4705
- */
4706
- const updateScoreDetailLabel = (_name, _label, _value, _pos = 0, _labelname = _label) => {
4707
- const baseLabel = (_bLabel, _bLabelname, _bAlign) =>
4708
- document.querySelector(`#detail${_name}`).appendChild(
4709
- createDivCss2Label(`${_bLabel}`, `${_bLabelname}`, {
4710
- x: 10, y: 105 + _pos * 20, w: 100, h: 20, siz: g_limitObj.difSelectorSiz, align: _bAlign,
4711
- })
4712
- );
4713
- if (document.querySelector(`#data${_label}`) === null) {
4714
- baseLabel(`lbl${_label}`, `${_labelname}`, C_ALIGN_LEFT);
4715
- baseLabel(`data${_label}`, `${_value}`, C_ALIGN_RIGHT);
4716
- } else {
4717
- document.querySelector(`#data${_label}`).textContent = `${_value}`;
4718
- }
4719
- };
4720
-
4721
- /**
4722
- * グラフの縦軸を描画
4723
- * @param {object} _context
4724
- * @param {number} _resolution
4725
- */
4726
- const drawBaseLine = (_context, _resolution = 10) => {
4727
- _context.clearRect(0, 0, g_limitObj.graphWidth, g_limitObj.graphHeight);
4728
-
4729
- for (let j = 0; j <= 2 * _resolution; j += 5) {
4730
- drawLine(_context, j / _resolution, `main`, 2);
4731
- for (let k = 1; k < 5; k++) {
4732
- drawLine(_context, (j + k) / _resolution, `sub`, 2);
4733
- }
4734
- }
4735
- };
4736
-
4737
- /**
4738
- * グラフ上に目盛を表示
4739
- * @param {object} _context
4740
- * @param {number} _y
4741
- * @param {string} _lineType
4742
- * @param {number} _fixed
4743
- */
4744
- const drawLine = (_context, _y, _lineType, _fixed = 0) => {
4745
- const lineY = (_y - 1) * -90 + 105;
4746
- _context.beginPath();
4747
- _context.moveTo(30, lineY);
4748
- _context.lineTo(g_limitObj.graphWidth, lineY);
4749
- _context.lineWidth = 1;
4750
-
4751
- if (_lineType === `main`) {
4752
- const textBaseObj = document.querySelector(`#lnkDifficulty`);
4753
- const textColor = window.getComputedStyle(textBaseObj, ``).color;
4754
- _context.strokeStyle = textColor;
4755
- _context.font = `12px ${getBasicFont()}`;
4756
- _context.fillStyle = textColor;
4757
- _context.fillText(_y.toFixed(_fixed), 0, lineY + 4);
4758
- } else {
4759
- _context.strokeStyle = `#646464`;
4760
- }
4761
- _context.stroke();
4762
- };
4763
-
4764
- /**
4765
- * 譜面の難易度情報用ラベル作成
4766
- * @param {number} _scoreId
4767
- */
4768
- const makeDifInfoLabels = _scoreId => {
4769
-
4770
- // ツール難易度
4771
- const detailToolDif = document.querySelector(`#detailToolDif`);
4772
- /**
4773
- * 譜面の難易度情報ラベルの作成
4774
- * @param {string} _lbl
4775
- * @param {string} _data
4776
- * @param {object} _obj
4777
- */
4778
- const makeDifInfoLabel = (_lbl, _data, { x = 130, y = 25, w = 125, h = 35, siz = g_limitObj.difSelectorSiz, ...rest } = {}) =>
4779
- createDivCss2Label(_lbl, _data, { x, y, w, h, siz, align: C_ALIGN_LEFT, ...rest });
4780
-
4781
- let printData = ``;
4782
- for (let j = 0; j < g_detailObj.arrowCnt.length; j++) {
4783
- const obj = getScoreBaseData(j);
4784
- printData +=
4785
- // 譜面番号
4786
- `[${j + 1}]\t` +
4787
- // ツール値
4788
- `${g_detailObj.toolDif[j].tool}\t` +
4789
- // 同時
4790
- `${g_detailObj.toolDif[j].douji}\t` +
4791
- // 縦連
4792
- `${g_detailObj.toolDif[j].tate}\t` +
4793
- // 総矢印数
4794
- `${(obj.arrowCnts + obj.frzCnts)}\t` +
4795
- // 矢印
4796
- `${obj.arrowCnts}\t` +
4797
- // フリーズアロー
4798
- `${obj.frzCnts}\t` +
4799
- // APM
4800
- `${obj.apm}\t` +
4801
- // 時間(分秒)
4802
- `${obj.playingTime}\r\n`;
4803
- }
4804
- multiAppend(detailToolDif,
4805
- makeDifInfoLabel(`lblTooldif`, g_lblNameObj.s_level, g_lblPosObj.lblTooldif),
4806
- makeDifInfoLabel(`dataTooldif`, ``, g_lblPosObj.dataTooldif),
4807
- makeDifInfoLabel(`lblDouji`, g_lblNameObj.s_douji, g_lblPosObj.lblDouji),
4808
- makeDifInfoLabel(`lblTate`, g_lblNameObj.s_tate, g_lblPosObj.lblTate),
4809
- makeDifInfoLabel(`dataDouji`, ``, g_lblPosObj.dataDouji),
4810
- makeDifInfoLabel(`dataTate`, ``, g_lblPosObj.dataTate),
4811
- makeDifInfoLabel(`lblArrowInfo`, g_lblNameObj.s_cnts, g_lblPosObj.lblArrowInfo),
4812
- makeDifInfoLabel(`dataArrowInfo`, ``, g_lblPosObj.dataArrowInfo),
4813
- makeDifInfoLabel(`lblArrowInfo2`, ``, g_lblPosObj.lblArrowInfo2),
4814
- makeDifInfoLabel(`dataArrowInfo2`, ``, g_lblPosObj.dataArrowInfo2),
4815
- makeDifLblCssButton(`lnkDifInfo`, g_lblNameObj.s_print, 8, _ => {
4816
- copyTextToClipboard(
4817
- `****** ${g_lblNameObj.s_printTitle} [${g_version}] ******\r\n\r\n`
4818
- + `\t${g_lblNameObj.s_printHeader}\r\n\r\n${printData}`, g_msgInfoObj.I_0003
4819
- );
4820
- }, g_lblPosObj.lnkDifInfo),
4821
- );
4822
- createScText(lnkDifInfo, `DifInfo`, { targetLabel: `lnkDifInfo`, x: -10 });
4823
- };
4824
-
4825
- /**
4826
- * 譜面の難易度情報更新
4827
- * @param {number} _scoreId
4828
- */
4829
- const makeDifInfo = _scoreId => {
4830
-
4831
- const arrowCnts = sumData(g_detailObj.arrowCnt[_scoreId]);
4832
- const frzCnts = sumData(g_detailObj.frzCnt[_scoreId]);
4833
- const push3CntStr = (g_detailObj.toolDif[_scoreId].push3.length === 0 ? `None` : `(${g_detailObj.toolDif[_scoreId].push3})`);
4834
-
4835
- if (document.querySelector(`#lblTooldif`) === null) {
4836
- makeDifInfoLabels(_scoreId);
4837
- }
4838
- dataTooldif.textContent = g_detailObj.toolDif[_scoreId].tool;
4839
- dataDouji.textContent = g_detailObj.toolDif[_scoreId].douji;
4840
- dataTate.textContent = g_detailObj.toolDif[_scoreId].tate;
4841
- lblArrowInfo2.innerHTML = g_lblNameObj.s_linecnts.split(`{0}`).join(g_detailObj.toolDif[_scoreId].push3cnt);
4842
- dataArrowInfo.innerHTML = `${arrowCnts + frzCnts} <span style="font-size:${g_limitObj.difSelectorSiz}px;">(${arrowCnts} + ${frzCnts})</span>`;
4843
- dataArrowInfo2.innerHTML = `<br>(${g_detailObj.arrowCnt[_scoreId]})<br><br>
4844
- (${g_detailObj.frzCnt[_scoreId]})<br><br>
4845
- ${push3CntStr}`.split(`,`).join(`/`);
4846
- };
4847
-
4848
5038
  // ---------------------------------------------------
4849
5039
  // 速度モーション (Motion)
4850
5040
  // 縦位置: 3
@@ -4877,25 +5067,6 @@ const createOptionWindow = _sprite => {
4877
5067
  spriteList.scroll.style.pointerEvents = C_DIS_NONE;
4878
5068
  }
4879
5069
 
4880
- const setReverse = _btn => {
4881
- if (!g_settings.scrolls.includes(`Reverse`)) {
4882
- g_settings.reverseNum = (g_settings.reverseNum + 1) % 2;
4883
- g_stateObj.reverse = g_settings.reverses[g_settings.reverseNum];
4884
- setReverseView(_btn);
4885
- }
4886
- };
4887
-
4888
- const setReverseView = _btn => {
4889
- _btn.classList.replace(g_cssObj[`button_Rev${g_settings.reverses[(g_settings.reverseNum + 1) % 2]}`],
4890
- g_cssObj[`button_Rev${g_settings.reverses[g_settings.reverseNum]}`]);
4891
- if (!g_settings.scrolls.includes(`Reverse`)) {
4892
- _btn.textContent = `${g_lblNameObj.Reverse}:${getStgDetailName(g_stateObj.reverse)}`;
4893
- } else {
4894
- _btn.textContent = `X`;
4895
- setReverseDefault();
4896
- }
4897
- };
4898
-
4899
5070
  // ---------------------------------------------------
4900
5071
  // ミラー・ランダム (Shuffle)
4901
5072
  // 縦位置: 5.5
@@ -4914,165 +5085,6 @@ const createOptionWindow = _sprite => {
4914
5085
  // ゲージ設定詳細 縦位置: ゲージ設定+1
4915
5086
  spriteList.gauge.appendChild(createDivCss2Label(`lblGauge2`, ``, g_lblPosObj.lblGauge2));
4916
5087
 
4917
- /**
4918
- * ゲージ設定メイン
4919
- * @param {number} _scrollNum
4920
- */
4921
- const setGauge = _scrollNum => {
4922
-
4923
- // カーソルを動かさない場合は先にゲージ設定をリロード
4924
- if (_scrollNum === 0) {
4925
- gaugeChange(g_settings.gaugeNum);
4926
- }
4927
- setSetting(_scrollNum, `gauge`);
4928
-
4929
- // カーソルを動かす場合は設定変更後にゲージ設定を再設定
4930
- if (_scrollNum !== 0) {
4931
- gaugeChange(g_settings.gaugeNum);
4932
- }
4933
- lblGauge2.innerHTML = gaugeFormat(g_stateObj.lifeMode,
4934
- g_stateObj.lifeBorder, g_stateObj.lifeRcv, g_stateObj.lifeDmg, g_stateObj.lifeInit, g_stateObj.lifeVariable);
4935
- };
4936
-
4937
- /**
4938
- * ゲージ設定の切替処理
4939
- * @param {number} _gaugeNum
4940
- */
4941
- const gaugeChange = _gaugeNum => {
4942
- const tmpScoreId = g_stateObj.scoreId;
4943
-
4944
- /**
4945
- * ゲージ詳細変更
4946
- * @param {object} _baseProperty
4947
- * @param {string} _setProperty
4948
- * @param {number} _magnification
4949
- */
4950
- const setLife = (_baseProperty, _setProperty, _magnification = 1) => {
4951
- if (setVal(_baseProperty[tmpScoreId], ``, C_TYP_FLOAT) !== ``) {
4952
- g_stateObj[_setProperty] = _baseProperty[tmpScoreId] * _magnification;
4953
- }
4954
- };
4955
-
4956
- /**
4957
- * ゲージ詳細一括変更
4958
- * @param {object} _baseObj
4959
- * @param {object} _obj
4960
- */
4961
- const setLifeCategory = (_baseObj, { _magInit = 1, _magRcv = 1, _magDmg = 1 } = {}) => {
4962
- setLife(_baseObj.lifeInits, `lifeInit`, _magInit);
4963
- setLife(_baseObj.lifeRecoverys, `lifeRcv`, _magRcv);
4964
- setLife(_baseObj.lifeDamages, `lifeDmg`, _magDmg);
4965
- };
4966
-
4967
- /**
4968
- * ライフモード切替
4969
- * @param {object} _baseObj
4970
- */
4971
- const changeLifeMode = (_baseObj) => {
4972
- if (_baseObj.lifeBorders[tmpScoreId] === `x`) {
4973
- g_stateObj.lifeBorder = 0;
4974
- g_stateObj.lifeMode = C_LFE_SURVIVAL;
4975
- } else {
4976
- g_stateObj.lifeBorder = _baseObj.lifeBorders[tmpScoreId];
4977
- g_stateObj.lifeMode = C_LFE_BORDER;
4978
- }
4979
- };
4980
-
4981
- // ゲージ初期化
4982
- if (_gaugeNum === 0) {
4983
- if (hasVal(g_headerObj.lifeBorders[tmpScoreId])) {
4984
- changeLifeMode(g_headerObj);
4985
- g_gaugeType = (g_gaugeOptionObj.custom.length > 0 ? C_LFE_CUSTOM : g_stateObj.lifeMode);
4986
-
4987
- g_stateObj.lifeVariable = g_gaugeOptionObj[`var${g_gaugeType}`][_gaugeNum];
4988
- g_settings.gauges = structuredClone(g_gaugeOptionObj[g_gaugeType.toLowerCase()]);
4989
- g_stateObj.gauge = g_settings.gauges[g_settings.gaugeNum];
4990
- }
4991
- setLifeCategory(g_headerObj);
4992
-
4993
- } else {
4994
- // 設定されたゲージ設定、カーソルに合わせて設定値を更新
4995
- g_stateObj.lifeVariable = g_gaugeOptionObj[`var${g_gaugeType}`][_gaugeNum];
4996
- if (g_gaugeOptionObj.custom.length === 0 ||
4997
- g_gaugeOptionObj.defaultList.includes(g_gaugeOptionObj[`defaultGauge${tmpScoreId}`])) {
4998
- const gType = (g_gaugeType === C_LFE_CUSTOM ?
4999
- toCapitalize(g_gaugeOptionObj[`defaultGauge${tmpScoreId}`]) : g_gaugeType);
5000
- g_stateObj.lifeMode = g_gaugeOptionObj[`type${gType}`][_gaugeNum];
5001
- g_stateObj.lifeBorder = g_gaugeOptionObj[`clear${gType}`][_gaugeNum];
5002
- g_stateObj.lifeInit = g_gaugeOptionObj[`init${gType}`][_gaugeNum];
5003
- g_stateObj.lifeRcv = g_gaugeOptionObj[`rcv${gType}`][_gaugeNum];
5004
- g_stateObj.lifeDmg = g_gaugeOptionObj[`dmg${gType}`][_gaugeNum];
5005
- }
5006
- }
5007
-
5008
- // ゲージ設定(Light, Easy)の初期化
5009
- if (g_stateObj.gauge === `Light` || g_stateObj.gauge === `Easy`) {
5010
- setLifeCategory(g_headerObj, { _magRcv: 2 });
5011
- }
5012
-
5013
- // ゲージ設定別に個別設定した場合はここで設定を上書き
5014
- // 譜面ヘッダー:gaugeXXX で設定した値がここで適用される
5015
- if (hasVal(g_gaugeOptionObj[`gauge${g_stateObj.gauge}s`])) {
5016
- const tmpGaugeObj = g_gaugeOptionObj[`gauge${g_stateObj.gauge}s`];
5017
- if (hasVal(tmpGaugeObj.lifeBorders[tmpScoreId])) {
5018
- changeLifeMode(tmpGaugeObj);
5019
- }
5020
- setLifeCategory(tmpGaugeObj);
5021
- }
5022
- };
5023
-
5024
- /**
5025
- * ゲージ設定の詳細表示を整形
5026
- */
5027
- const gaugeFormat = (_mode, _border, _rcv, _dmg, _init, _lifeValFlg) => {
5028
- const initVal = g_headerObj.maxLifeVal * _init / 100;
5029
- const borderVal = (_mode === C_LFE_BORDER && _border !== 0 ?
5030
- Math.round(g_headerObj.maxLifeVal * _border / 100) : `-`);
5031
-
5032
- let lifeValCss = ``;
5033
- if (_lifeValFlg === C_FLG_ON) {
5034
- lifeValCss = ` settings_lifeVal`;
5035
- }
5036
-
5037
- // 整形用にライフ初期値を整数、回復・ダメージ量を小数第1位で丸める
5038
- const init = Math.round(initVal);
5039
- const border = (borderVal !== `-` ? borderVal : `-`);
5040
- const rcv = Math.round(_rcv * 100) / 100;
5041
- const dmg = Math.round(_dmg * 100) / 100;
5042
-
5043
- return `<div id="gaugeDivCover" class="settings_gaugeDivCover">
5044
- <div id="lblGaugeDivTable" class="settings_gaugeDivTable">
5045
- <div id="lblGaugeStart" class="settings_gaugeDivTableCol settings_gaugeStart">
5046
- ${g_lblNameObj.g_start}
5047
- </div>
5048
- <div id="lblGaugeBorder" class="settings_gaugeDivTableCol settings_gaugeEtc">
5049
- ${g_lblNameObj.g_border}
5050
- </div>
5051
- <div id="lblGaugeRecovery" class="settings_gaugeDivTableCol settings_gaugeEtc">
5052
- ${g_lblNameObj.g_recovery}
5053
- </div>
5054
- <div id="lblGaugeDamage" class="settings_gaugeDivTableCol settings_gaugeEtc">
5055
- ${g_lblNameObj.g_damage}
5056
- </div>
5057
- </div>
5058
- <div id="dataGaugeDivTable" class="settings_gaugeDivTable">
5059
- <div id="dataGaugeStart" class="settings_gaugeDivTableCol settings_gaugeVal settings_gaugeStart">
5060
- ${init}/${g_headerObj.maxLifeVal}
5061
- </div>
5062
- <div id="dataGaugeBorder" class="settings_gaugeDivTableCol settings_gaugeVal settings_gaugeEtc">
5063
- ${border}
5064
- </div>
5065
- <div id="dataGaugeRecovery" class="settings_gaugeDivTableCol settings_gaugeVal settings_gaugeEtc${lifeValCss}">
5066
- ${rcv}
5067
- </div>
5068
- <div id="dataGaugeDamage" class="settings_gaugeDivTableCol settings_gaugeVal settings_gaugeEtc${lifeValCss}">
5069
- ${dmg}
5070
- </div>
5071
- </div>
5072
- </div>
5073
- `;
5074
- };
5075
-
5076
5088
  if (g_headerObj.gaugeUse) {
5077
5089
  multiAppend(spriteList.gauge,
5078
5090
  makeSettingLblCssButton(`lnkGauge`, ``, 0, _ => setGauge(1), { cxtFunc: _ => setGauge(-1) }),
@@ -5129,196 +5141,6 @@ const createOptionWindow = _sprite => {
5129
5141
  // 縦位置: 12.5
5130
5142
  createGeneralSetting(spriteList.volume, `volume`, { unitName: g_lblNameObj.percent });
5131
5143
 
5132
- /**
5133
- * 譜面初期化処理
5134
- * - 譜面の基本設定(キー数、初期速度、リバース、ゲージ設定)をここで行う
5135
- * - g_canLoadDifInfoFlg は譜面初期化フラグで、初期化したくない場合は対象画面にて false にしておく
5136
- * (Display設定画面、キーコンフィグ画面では通常OFF)
5137
- * この関数を実行後、このフラグはONに戻るようになっている
5138
- * - [キーコン]->[初期化]->[名称設定]の順に配置する。
5139
- * 初期化処理にてキー数関連の設定を行っているため、この順序で無いとデータが正しく格納されない
5140
- */
5141
- const setDifficulty = (_initFlg) => {
5142
-
5143
- const getCurrentNo = (_list, _target) => roundZero(_list.findIndex(item => item === _target));
5144
-
5145
- // ---------------------------------------------------
5146
- // 1. キーコンフィグ設定 (KeyConfig)
5147
- g_keyObj.currentKey = g_headerObj.keyLabels[g_stateObj.scoreId];
5148
- const isNotSameKey = (g_keyObj.prevKey !== g_keyObj.currentKey);
5149
-
5150
- if (g_headerObj.dummyScoreNos !== undefined) {
5151
- g_stateObj.dummyId = setIntVal(g_headerObj.dummyScoreNos[g_stateObj.scoreId], ``);
5152
- }
5153
- // 特殊キーフラグ
5154
- g_stateObj.extraKeyFlg = g_headerObj.keyExtraList.includes(g_keyObj.currentKey);
5155
-
5156
- // ---------------------------------------------------
5157
- // 2. 初期化設定
5158
-
5159
- // 保存した設定の再読込条件(設定画面切り替え時はスキップ)
5160
- // ローカルストレージで保存した設定を呼び出し
5161
- if ((g_canLoadDifInfoFlg && (isNotSameKey && g_stateObj.dataSaveFlg)) || _initFlg) {
5162
-
5163
- if (isNotSameKey && g_keyObj.prevKey !== `Dummy`) {
5164
- // キーパターン初期化
5165
- g_keyObj.currentPtn = 0;
5166
- g_keycons.keySwitchNum = 0;
5167
- }
5168
- const hasKeyStorage = localStorage.getItem(`danonicw-${g_keyObj.currentKey}k`);
5169
- let storageObj, addKey = ``;
5170
-
5171
- if (!g_stateObj.extraKeyFlg) {
5172
-
5173
- // キー別のローカルストレージの初期設定 ※特殊キーは除く
5174
- g_localKeyStorage = hasKeyStorage ? JSON.parse(hasKeyStorage) : {
5175
- reverse: C_FLG_OFF,
5176
- keyCtrl: [[]],
5177
- keyCtrlPtn: 0,
5178
- setColor: [],
5179
- };
5180
- storageObj = g_localKeyStorage;
5181
-
5182
- } else {
5183
- storageObj = g_localStorage;
5184
- addKey = g_keyObj.currentKey;
5185
- }
5186
- if (isNotSameKey) {
5187
- getKeyReverse(storageObj, addKey);
5188
-
5189
- // キーコンフィグ初期値設定
5190
- if (storageObj[`keyCtrlPtn${addKey}`] === undefined) {
5191
- storageObj[`keyCtrlPtn${addKey}`] = 0;
5192
- }
5193
- getKeyCtrl(storageObj, addKey);
5194
-
5195
- // カラーセット初期値設定
5196
- if (storageObj[`setColor${addKey}`] === undefined) {
5197
- storageObj[`setColor${addKey}`] = [];
5198
- }
5199
- if (storageObj[`setColor${addKey}`].length > 0) {
5200
- g_keycons.colorTypes = addValtoArray(g_keycons.colorTypes, g_keycons.colorSelf);
5201
- resetColorType({ _fromObj: storageObj, _from: addKey, _to: g_keycons.colorSelf });
5202
- resetColorType({ _fromObj: storageObj, _from: addKey, _toObj: g_dfColorObj, _to: g_keycons.colorSelf });
5203
-
5204
- } else {
5205
- if (g_localStorage.colorType === g_keycons.colorSelf) {
5206
- g_colorType = `Default`;
5207
- }
5208
- g_keycons.colorTypes = g_keycons.colorTypes.filter(val => val !== g_keycons.colorSelf);
5209
- }
5210
-
5211
- const keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`;
5212
-
5213
- // カラーグループ、シャッフルグループの設定
5214
- g_keycons.groups.forEach(type => {
5215
- resetGroupList(type, keyCtrlPtn);
5216
- if (g_keyObj.currentPtn === -1) {
5217
- const storageKeyName = storageObj[`${type}${addKey}`] || storageObj[`${type}${g_keyObj.currentKey}_-1_-1`];
5218
- if (storageKeyName !== undefined) {
5219
- g_keyObj[`${type}${g_keyObj.currentKey}_-1`] = structuredClone(storageKeyName);
5220
- }
5221
- g_keyObj[`${type}${g_keyObj.currentKey}_-1_-1`] = structuredClone(g_keyObj[`${type}${g_keyObj.currentKey}_-1`]);
5222
- } else {
5223
- g_keyObj[`${type}${keyCtrlPtn}`] = structuredClone(g_keyObj[`${type}${keyCtrlPtn}_0`]);
5224
- }
5225
- });
5226
-
5227
- }
5228
-
5229
- const keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`;
5230
- if (g_headerObj.keyRetryDef === C_KEY_RETRY) {
5231
- g_headerObj.keyRetry = setIntVal(getKeyCtrlVal(g_keyObj[`keyRetry${keyCtrlPtn}`]), g_headerObj.keyRetryDef);
5232
- }
5233
- if (g_headerObj.keyTitleBackDef === C_KEY_TITLEBACK) {
5234
- g_headerObj.keyTitleBack = setIntVal(getKeyCtrlVal(g_keyObj[`keyTitleBack${keyCtrlPtn}`]), g_headerObj.keyTitleBackDef);
5235
- }
5236
- }
5237
-
5238
- // スクロール設定用の配列を入れ替え
5239
- g_settings.scrolls = structuredClone(
5240
- typeof g_keyObj[`scrollDir${g_keyObj.currentKey}_${g_keyObj.currentPtn}`] === C_TYP_OBJECT ?
5241
- Object.keys(g_keyObj[`scrollDir${g_keyObj.currentKey}_${g_keyObj.currentPtn}`]) : g_keyObj.scrollName_def
5242
- );
5243
-
5244
- // アシスト設定の配列を入れ替え
5245
- g_settings.autoPlays = (typeof g_keyObj[`assistPos${g_keyObj.currentKey}_${g_keyObj.currentPtn}`] === C_TYP_OBJECT ?
5246
- g_autoPlaysBase.concat(Object.keys(g_keyObj[`assistPos${g_keyObj.currentKey}_${g_keyObj.currentPtn}`])) :
5247
- g_autoPlaysBase.concat());
5248
-
5249
- // 速度、ゲージ、スクロール、アシスト設定のカーソル位置調整
5250
- if (_initFlg) {
5251
- g_stateObj.speed = g_headerObj.initSpeeds[g_stateObj.scoreId];
5252
- g_settings.speedNum = getCurrentNo(g_settings.speeds, g_stateObj.speed);
5253
- g_settings.gaugeNum = 0;
5254
- }
5255
- g_settings.scrollNum = getCurrentNo(g_settings.scrolls, g_stateObj.scroll);
5256
- g_settings.autoPlayNum = getCurrentNo(g_settings.autoPlays, g_stateObj.autoPlay);
5257
-
5258
- // ---------------------------------------------------
5259
- // 3. 名称の設定
5260
-
5261
- // 譜面名設定 (Difficulty)
5262
- const difWidth = parseFloat(lnkDifficulty.style.width);
5263
- const difNames = [`${getKeyName(g_keyObj.currentKey)} ${getStgDetailName('key')} / ${g_headerObj.difLabels[g_stateObj.scoreId]}`];
5264
- lnkDifficulty.style.fontSize = `${getFontSize(difNames[0], difWidth, getBasicFont(), g_limitObj.setLblSiz)}px`;
5265
-
5266
- if (g_headerObj.makerView) {
5267
- difNames.push(`(${g_headerObj.creatorNames[g_stateObj.scoreId]})`);
5268
- difNames.forEach((difName, j) => {
5269
- const tmpSize = getFontSize(difName, difWidth, getBasicFont(), 14);
5270
- difNames[j] = `<span style="font-size:${tmpSize}px">${difName}</span>`;
5271
- });
5272
- }
5273
- lnkDifficulty.innerHTML = difNames.join(``);
5274
-
5275
- // 速度設定 (Speed)
5276
- setSetting(0, `speed`, ` ${g_lblNameObj.multi}`);
5277
- if (g_headerObj.scoreDetailUse) {
5278
- drawSpeedGraph(g_stateObj.scoreId);
5279
- drawDensityGraph(g_stateObj.scoreId);
5280
- makeDifInfo(g_stateObj.scoreId);
5281
- }
5282
-
5283
- // リバース設定 (Reverse, Scroll)
5284
- if (g_headerObj.scrollUse) {
5285
- g_stateObj.scroll = g_settings.scrolls[g_settings.scrollNum];
5286
- const [visibleScr, hiddenScr] = (g_settings.scrolls.length > 1 ? [`scroll`, `reverse`] : [`reverse`, `scroll`]);
5287
- spriteList[visibleScr].style.display = C_DIS_INHERIT;
5288
- spriteList[hiddenScr].style.display = C_DIS_NONE;
5289
- setSetting(0, visibleScr);
5290
-
5291
- g_shortcutObj.option.KeyR.id = g_settings.scrolls.includes(`Reverse`) ?
5292
- g_shortcutObj.option.KeyR.exId : g_shortcutObj.option.KeyR.dfId;
5293
-
5294
- if (g_settings.scrolls.length > 1) {
5295
- setReverseView(document.querySelector(`#btnReverse`));
5296
- }
5297
- } else {
5298
- g_settings.scrolls = structuredClone(g_keyObj.scrollName_def);
5299
- setSetting(0, `reverse`);
5300
- }
5301
-
5302
- // オート・アシスト設定 (AutoPlay)
5303
- g_stateObj.autoPlay = g_settings.autoPlays[g_settings.autoPlayNum];
5304
- lnkAutoPlay.textContent = getStgDetailName(g_stateObj.autoPlay);
5305
-
5306
- // ゲージ設定 (Gauge)
5307
- const defaultCustomGauge = g_gaugeOptionObj.custom0 || g_gaugeOptionObj.customDefault;
5308
- if (hasVal(defaultCustomGauge)) {
5309
- g_gaugeOptionObj.custom = (g_gaugeOptionObj[`custom${g_stateObj.scoreId}`] || defaultCustomGauge).concat();
5310
- g_gaugeOptionObj.varCustom = (g_gaugeOptionObj[`varCustom${g_stateObj.scoreId}`] || g_gaugeOptionObj.varCustom0 || g_gaugeOptionObj.varCustomDefault).concat();
5311
- }
5312
- setGauge(0);
5313
-
5314
- // ユーザカスタムイベント(初期)
5315
- g_customJsObj.difficulty.forEach(func => func(_initFlg, g_canLoadDifInfoFlg));
5316
-
5317
- // ---------------------------------------------------
5318
- // 4. 譜面初期情報ロード許可フラグの設定
5319
- g_canLoadDifInfoFlg = true;
5320
- };
5321
-
5322
5144
  // 設定画面の一通りのオブジェクトを作成後に譜面・速度・ゲージ設定をまとめて行う
5323
5145
  setDifficulty(false);
5324
5146
  optionsprite.oncontextmenu = _ => false;
@@ -5486,6 +5308,184 @@ const setReverseDefault = _ => {
5486
5308
  g_settings.reverseNum = 0;
5487
5309
  };
5488
5310
 
5311
+ const setReverse = _btn => {
5312
+ if (!g_settings.scrolls.includes(`Reverse`)) {
5313
+ g_settings.reverseNum = (g_settings.reverseNum + 1) % 2;
5314
+ g_stateObj.reverse = g_settings.reverses[g_settings.reverseNum];
5315
+ setReverseView(_btn);
5316
+ }
5317
+ };
5318
+
5319
+ const setReverseView = _btn => {
5320
+ _btn.classList.replace(g_cssObj[`button_Rev${g_settings.reverses[(g_settings.reverseNum + 1) % 2]}`],
5321
+ g_cssObj[`button_Rev${g_settings.reverses[g_settings.reverseNum]}`]);
5322
+ if (!g_settings.scrolls.includes(`Reverse`)) {
5323
+ _btn.textContent = `${g_lblNameObj.Reverse}:${getStgDetailName(g_stateObj.reverse)}`;
5324
+ } else {
5325
+ _btn.textContent = `X`;
5326
+ setReverseDefault();
5327
+ }
5328
+ };
5329
+
5330
+ /**
5331
+ * ゲージ設定メイン
5332
+ * @param {number} _scrollNum
5333
+ */
5334
+ const setGauge = _scrollNum => {
5335
+
5336
+ // カーソルを動かさない場合は先にゲージ設定をリロード
5337
+ if (_scrollNum === 0) {
5338
+ gaugeChange(g_settings.gaugeNum);
5339
+ }
5340
+ setSetting(_scrollNum, `gauge`);
5341
+
5342
+ // カーソルを動かす場合は設定変更後にゲージ設定を再設定
5343
+ if (_scrollNum !== 0) {
5344
+ gaugeChange(g_settings.gaugeNum);
5345
+ }
5346
+ lblGauge2.innerHTML = gaugeFormat(g_stateObj.lifeMode,
5347
+ g_stateObj.lifeBorder, g_stateObj.lifeRcv, g_stateObj.lifeDmg, g_stateObj.lifeInit, g_stateObj.lifeVariable);
5348
+ };
5349
+
5350
+ /**
5351
+ * ゲージ設定の切替処理
5352
+ * @param {number} _gaugeNum
5353
+ */
5354
+ const gaugeChange = _gaugeNum => {
5355
+ const tmpScoreId = g_stateObj.scoreId;
5356
+
5357
+ /**
5358
+ * ゲージ詳細変更
5359
+ * @param {object} _baseProperty
5360
+ * @param {string} _setProperty
5361
+ * @param {number} _magnification
5362
+ */
5363
+ const setLife = (_baseProperty, _setProperty, _magnification = 1) => {
5364
+ if (setVal(_baseProperty[tmpScoreId], ``, C_TYP_FLOAT) !== ``) {
5365
+ g_stateObj[_setProperty] = _baseProperty[tmpScoreId] * _magnification;
5366
+ }
5367
+ };
5368
+
5369
+ /**
5370
+ * ゲージ詳細一括変更
5371
+ * @param {object} _baseObj
5372
+ * @param {object} _obj
5373
+ */
5374
+ const setLifeCategory = (_baseObj, { _magInit = 1, _magRcv = 1, _magDmg = 1 } = {}) => {
5375
+ setLife(_baseObj.lifeInits, `lifeInit`, _magInit);
5376
+ setLife(_baseObj.lifeRecoverys, `lifeRcv`, _magRcv);
5377
+ setLife(_baseObj.lifeDamages, `lifeDmg`, _magDmg);
5378
+ };
5379
+
5380
+ /**
5381
+ * ライフモード切替
5382
+ * @param {object} _baseObj
5383
+ */
5384
+ const changeLifeMode = (_baseObj) => {
5385
+ if (_baseObj.lifeBorders[tmpScoreId] === `x`) {
5386
+ g_stateObj.lifeBorder = 0;
5387
+ g_stateObj.lifeMode = C_LFE_SURVIVAL;
5388
+ } else {
5389
+ g_stateObj.lifeBorder = _baseObj.lifeBorders[tmpScoreId];
5390
+ g_stateObj.lifeMode = C_LFE_BORDER;
5391
+ }
5392
+ };
5393
+
5394
+ // ゲージ初期化
5395
+ if (_gaugeNum === 0) {
5396
+ if (hasVal(g_headerObj.lifeBorders[tmpScoreId])) {
5397
+ changeLifeMode(g_headerObj);
5398
+ g_gaugeType = (g_gaugeOptionObj.custom.length > 0 ? C_LFE_CUSTOM : g_stateObj.lifeMode);
5399
+
5400
+ g_stateObj.lifeVariable = g_gaugeOptionObj[`var${g_gaugeType}`][_gaugeNum];
5401
+ g_settings.gauges = structuredClone(g_gaugeOptionObj[g_gaugeType.toLowerCase()]);
5402
+ g_stateObj.gauge = g_settings.gauges[g_settings.gaugeNum];
5403
+ }
5404
+ setLifeCategory(g_headerObj);
5405
+
5406
+ } else {
5407
+ // 設定されたゲージ設定、カーソルに合わせて設定値を更新
5408
+ g_stateObj.lifeVariable = g_gaugeOptionObj[`var${g_gaugeType}`][_gaugeNum];
5409
+ if (g_gaugeOptionObj.custom.length === 0 ||
5410
+ g_gaugeOptionObj.defaultList.includes(g_gaugeOptionObj[`defaultGauge${tmpScoreId}`])) {
5411
+ const gType = (g_gaugeType === C_LFE_CUSTOM ?
5412
+ toCapitalize(g_gaugeOptionObj[`defaultGauge${tmpScoreId}`]) : g_gaugeType);
5413
+ g_stateObj.lifeMode = g_gaugeOptionObj[`type${gType}`][_gaugeNum];
5414
+ g_stateObj.lifeBorder = g_gaugeOptionObj[`clear${gType}`][_gaugeNum];
5415
+ g_stateObj.lifeInit = g_gaugeOptionObj[`init${gType}`][_gaugeNum];
5416
+ g_stateObj.lifeRcv = g_gaugeOptionObj[`rcv${gType}`][_gaugeNum];
5417
+ g_stateObj.lifeDmg = g_gaugeOptionObj[`dmg${gType}`][_gaugeNum];
5418
+ }
5419
+ }
5420
+
5421
+ // ゲージ設定(Light, Easy)の初期化
5422
+ if (g_stateObj.gauge === `Light` || g_stateObj.gauge === `Easy`) {
5423
+ setLifeCategory(g_headerObj, { _magRcv: 2 });
5424
+ }
5425
+
5426
+ // ゲージ設定別に個別設定した場合はここで設定を上書き
5427
+ // 譜面ヘッダー:gaugeXXX で設定した値がここで適用される
5428
+ if (hasVal(g_gaugeOptionObj[`gauge${g_stateObj.gauge}s`])) {
5429
+ const tmpGaugeObj = g_gaugeOptionObj[`gauge${g_stateObj.gauge}s`];
5430
+ if (hasVal(tmpGaugeObj.lifeBorders[tmpScoreId])) {
5431
+ changeLifeMode(tmpGaugeObj);
5432
+ }
5433
+ setLifeCategory(tmpGaugeObj);
5434
+ }
5435
+ };
5436
+
5437
+ /**
5438
+ * ゲージ設定の詳細表示を整形
5439
+ */
5440
+ const gaugeFormat = (_mode, _border, _rcv, _dmg, _init, _lifeValFlg) => {
5441
+ const initVal = g_headerObj.maxLifeVal * _init / 100;
5442
+ const borderVal = (_mode === C_LFE_BORDER && _border !== 0 ?
5443
+ Math.round(g_headerObj.maxLifeVal * _border / 100) : `-`);
5444
+
5445
+ let lifeValCss = ``;
5446
+ if (_lifeValFlg === C_FLG_ON) {
5447
+ lifeValCss = ` settings_lifeVal`;
5448
+ }
5449
+
5450
+ // 整形用にライフ初期値を整数、回復・ダメージ量を小数第1位で丸める
5451
+ const init = Math.round(initVal);
5452
+ const border = (borderVal !== `-` ? borderVal : `-`);
5453
+ const rcv = Math.round(_rcv * 100) / 100;
5454
+ const dmg = Math.round(_dmg * 100) / 100;
5455
+
5456
+ return `<div id="gaugeDivCover" class="settings_gaugeDivCover">
5457
+ <div id="lblGaugeDivTable" class="settings_gaugeDivTable">
5458
+ <div id="lblGaugeStart" class="settings_gaugeDivTableCol settings_gaugeStart">
5459
+ ${g_lblNameObj.g_start}
5460
+ </div>
5461
+ <div id="lblGaugeBorder" class="settings_gaugeDivTableCol settings_gaugeEtc">
5462
+ ${g_lblNameObj.g_border}
5463
+ </div>
5464
+ <div id="lblGaugeRecovery" class="settings_gaugeDivTableCol settings_gaugeEtc">
5465
+ ${g_lblNameObj.g_recovery}
5466
+ </div>
5467
+ <div id="lblGaugeDamage" class="settings_gaugeDivTableCol settings_gaugeEtc">
5468
+ ${g_lblNameObj.g_damage}
5469
+ </div>
5470
+ </div>
5471
+ <div id="dataGaugeDivTable" class="settings_gaugeDivTable">
5472
+ <div id="dataGaugeStart" class="settings_gaugeDivTableCol settings_gaugeVal settings_gaugeStart">
5473
+ ${init}/${g_headerObj.maxLifeVal}
5474
+ </div>
5475
+ <div id="dataGaugeBorder" class="settings_gaugeDivTableCol settings_gaugeVal settings_gaugeEtc">
5476
+ ${border}
5477
+ </div>
5478
+ <div id="dataGaugeRecovery" class="settings_gaugeDivTableCol settings_gaugeVal settings_gaugeEtc${lifeValCss}">
5479
+ ${rcv}
5480
+ </div>
5481
+ <div id="dataGaugeDamage" class="settings_gaugeDivTableCol settings_gaugeVal settings_gaugeEtc${lifeValCss}">
5482
+ ${dmg}
5483
+ </div>
5484
+ </div>
5485
+ </div>
5486
+ `;
5487
+ };
5488
+
5489
5489
  /**
5490
5490
  * 保存済みキーコンフィグ取得処理
5491
5491
  * @param {object} _localStorage 保存先のローカルストレージ名