danoniplus 41.0.3 → 41.2.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 +335 -34
- package/js/lib/danoni_constants.js +32 -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 : 2025/
|
|
7
|
+
* Revised : 2025/05/09
|
|
8
8
|
*
|
|
9
9
|
* https://github.com/cwtickle/danoniplus
|
|
10
10
|
*/
|
|
11
|
-
const g_version = `Ver 41.0
|
|
12
|
-
const g_revisedDate = `2025/
|
|
11
|
+
const g_version = `Ver 41.2.0`;
|
|
12
|
+
const g_revisedDate = `2025/05/09`;
|
|
13
13
|
|
|
14
14
|
// カスタム用バージョン (danoni_custom.js 等で指定可)
|
|
15
15
|
let g_localVersion = ``;
|
|
@@ -2310,6 +2310,25 @@ class AudioPlayer {
|
|
|
2310
2310
|
}
|
|
2311
2311
|
}
|
|
2312
2312
|
|
|
2313
|
+
close() {
|
|
2314
|
+
if (this._context) {
|
|
2315
|
+
this._context.close()?.catch(() => {/* ignore double-close */ });
|
|
2316
|
+
this._buffer = null;
|
|
2317
|
+
}
|
|
2318
|
+
if (this._source) {
|
|
2319
|
+
this._source.disconnect(this._gain);
|
|
2320
|
+
this._source = null;
|
|
2321
|
+
}
|
|
2322
|
+
if (this._gain) {
|
|
2323
|
+
this._gain.disconnect();
|
|
2324
|
+
this._gain = null;
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
get elapsedTime() {
|
|
2329
|
+
return this._context.currentTime - this._startTime + this._fadeinPosition;
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2313
2332
|
set currentTime(_currentTime) {
|
|
2314
2333
|
this._fadeinPosition = _currentTime;
|
|
2315
2334
|
}
|
|
@@ -2601,7 +2620,8 @@ const initialControl = async () => {
|
|
|
2601
2620
|
g_customJsObj.preTitle.forEach(func => func());
|
|
2602
2621
|
const queryMusicId = getQueryParamVal(`musicId`);
|
|
2603
2622
|
g_settings.musicIdxNum = queryMusicId !== null ? Number(queryMusicId) :
|
|
2604
|
-
g_headerObj.musicNos[g_stateObj.scoreId]
|
|
2623
|
+
g_headerObj.musicGroups?.[g_headerObj.musicNos[g_stateObj.scoreId]] ??
|
|
2624
|
+
g_headerObj.musicNos[g_stateObj.scoreId] ?? g_headerObj.musicNos[0];
|
|
2605
2625
|
titleInit(true);
|
|
2606
2626
|
|
|
2607
2627
|
// 未使用のg_keyObjプロパティを削除
|
|
@@ -2956,6 +2976,21 @@ const copySetColor = (_baseObj, _scoreId) => {
|
|
|
2956
2976
|
const getMusicUrl = _scoreId =>
|
|
2957
2977
|
g_headerObj.musicUrls?.[g_headerObj.musicNos[_scoreId]] ?? g_headerObj.musicUrls?.[0] ?? `nosound.mp3`;
|
|
2958
2978
|
|
|
2979
|
+
/**
|
|
2980
|
+
* 音源データの実際のパスを取得
|
|
2981
|
+
* @param {string} _musicUrl
|
|
2982
|
+
* @returns {string}
|
|
2983
|
+
*/
|
|
2984
|
+
const getFullMusicUrl = (_musicUrl = ``) => {
|
|
2985
|
+
let url = `${g_rootPath}../${g_headerObj.musicFolder}/${_musicUrl}`;
|
|
2986
|
+
if (_musicUrl.indexOf(C_MRK_CURRENT_DIRECTORY) !== -1) {
|
|
2987
|
+
url = _musicUrl.split(C_MRK_CURRENT_DIRECTORY)[1];
|
|
2988
|
+
} else if (g_headerObj.musicFolder.indexOf(C_MRK_CURRENT_DIRECTORY) !== -1) {
|
|
2989
|
+
url = `${g_headerObj.musicFolder.split(C_MRK_CURRENT_DIRECTORY)[1]}/${_musicUrl}`;
|
|
2990
|
+
}
|
|
2991
|
+
return url;
|
|
2992
|
+
}
|
|
2993
|
+
|
|
2959
2994
|
/**
|
|
2960
2995
|
* 譜面ファイル読込後処理(譜面詳細情報取得用)
|
|
2961
2996
|
* @param {number} _scoreId
|
|
@@ -3583,6 +3618,19 @@ const headerConvert = _dosObj => {
|
|
|
3583
3618
|
obj.musicNos = fillArray(obj.keyLabels.length);
|
|
3584
3619
|
}
|
|
3585
3620
|
|
|
3621
|
+
// 楽曲別のグループ化設定(選曲モードのみ)
|
|
3622
|
+
if (hasVal(_dosObj.musicGroup)) {
|
|
3623
|
+
obj.musicGroups = _dosObj.musicGroup.split(`,`)
|
|
3624
|
+
.map((val, j) => setVal(val, j, C_TYP_NUMBER))
|
|
3625
|
+
.map((val, j) => val < 0 ? j + val : val);
|
|
3626
|
+
for (let k = obj.musicGroups.length; k <= Math.max(...obj.musicNos); k++) {
|
|
3627
|
+
obj.musicGroups[k] = k;
|
|
3628
|
+
}
|
|
3629
|
+
obj.musicIdxList = makeDedupliArray(obj.musicGroups);
|
|
3630
|
+
} else {
|
|
3631
|
+
obj.musicIdxList = [...Array(Math.max(...obj.musicNos) + 1).keys()];
|
|
3632
|
+
}
|
|
3633
|
+
|
|
3586
3634
|
// 譜面変更セレクターの利用有無
|
|
3587
3635
|
obj.difSelectorUse = getDifSelectorUse(_dosObj.difSelectorUse, obj.viewLists);
|
|
3588
3636
|
|
|
@@ -3741,7 +3789,22 @@ const headerConvert = _dosObj => {
|
|
|
3741
3789
|
|
|
3742
3790
|
// 楽曲URL
|
|
3743
3791
|
if (hasVal(_dosObj.musicUrl)) {
|
|
3744
|
-
|
|
3792
|
+
const musicUrls = splitLF2(_dosObj.musicUrl);
|
|
3793
|
+
obj.musicUrls = [], obj.musicStarts = [], obj.musicEnds = [];
|
|
3794
|
+
musicUrls.forEach((val, j) => {
|
|
3795
|
+
const musicUrlPair = val.split(`,`);
|
|
3796
|
+
obj.musicUrls[j] = musicUrlPair[0] || ``;
|
|
3797
|
+
if (musicUrlPair[1] !== undefined) {
|
|
3798
|
+
const musicBGMTime = musicUrlPair[1].split(`-`).map(str => str.trim());
|
|
3799
|
+
obj.musicStarts[j] = Math.floor(transTimerToFrame(musicBGMTime[0] ?? 0) / g_fps);
|
|
3800
|
+
obj.musicEnds[j] = musicBGMTime[1] !== undefined ?
|
|
3801
|
+
Math.floor((transTimerToFrame(musicBGMTime[1] ?? 0)) / g_fps) :
|
|
3802
|
+
Math.floor((transTimerToFrame(musicBGMTime[0] ?? 0) + transTimerToFrame(`0:20`)) / g_fps);
|
|
3803
|
+
} else {
|
|
3804
|
+
obj.musicStarts[j] = 0;
|
|
3805
|
+
obj.musicEnds[j] = 20;
|
|
3806
|
+
}
|
|
3807
|
+
});
|
|
3745
3808
|
} else {
|
|
3746
3809
|
makeWarningWindow(g_msgInfoObj.E_0031);
|
|
3747
3810
|
}
|
|
@@ -4874,7 +4937,7 @@ const titleInit = (_initFlg = false) => {
|
|
|
4874
4937
|
if (getQueryParamVal(`scoreId`) !== null) {
|
|
4875
4938
|
g_headerObj.viewLists = [];
|
|
4876
4939
|
g_headerObj.musicNos.forEach((val, j) => {
|
|
4877
|
-
if (val === g_settings.musicIdxNum) {
|
|
4940
|
+
if ((g_headerObj.musicGroups?.[val] ?? val) === g_settings.musicIdxNum) {
|
|
4878
4941
|
g_headerObj.viewLists.push(j);
|
|
4879
4942
|
tmpCreatorList.push(g_headerObj.creatorNames[j]);
|
|
4880
4943
|
}
|
|
@@ -4893,8 +4956,7 @@ const titleInit = (_initFlg = false) => {
|
|
|
4893
4956
|
|
|
4894
4957
|
// 選曲画面の初期化
|
|
4895
4958
|
const wheelCycle = 2;
|
|
4896
|
-
|
|
4897
|
-
const musicIdxTmpList = [...Array(musicMaxIdx + 1).keys()];
|
|
4959
|
+
g_settings.musicLoopNum = 0;
|
|
4898
4960
|
|
|
4899
4961
|
/**
|
|
4900
4962
|
* メイン以外の選曲ボタンの作成
|
|
@@ -4909,6 +4971,17 @@ const titleInit = (_initFlg = false) => {
|
|
|
4909
4971
|
align: C_ALIGN_LEFT, padding: `0 10px`,
|
|
4910
4972
|
}, g_cssObj.button_Default_NoColor, g_cssObj.title_base);
|
|
4911
4973
|
|
|
4974
|
+
/**
|
|
4975
|
+
* 選曲画面上の音量調整
|
|
4976
|
+
* @param {number} _num
|
|
4977
|
+
*/
|
|
4978
|
+
const setBGMVolume = (_num = 1) => {
|
|
4979
|
+
g_settings.bgmVolumeNum = nextPos(g_settings.bgmVolumeNum, _num, g_settings.volumes.length);
|
|
4980
|
+
g_stateObj.bgmVolume = g_settings.volumes[g_settings.bgmVolumeNum];
|
|
4981
|
+
g_audio.volume = g_stateObj.bgmVolume / 100;
|
|
4982
|
+
btnBgmVolume.textContent = `${g_stateObj.bgmVolume}${g_lblNameObj.percent}`;
|
|
4983
|
+
};
|
|
4984
|
+
|
|
4912
4985
|
for (let j = -g_settings.mSelectableTerms; j <= g_settings.mSelectableTerms; j++) {
|
|
4913
4986
|
if (j !== 0) {
|
|
4914
4987
|
divRoot.appendChild(createMSelectBtn(j));
|
|
@@ -4921,6 +4994,7 @@ const titleInit = (_initFlg = false) => {
|
|
|
4921
4994
|
createCss2Button(`btnStart`,
|
|
4922
4995
|
`>`, () => {
|
|
4923
4996
|
clearTimeout(g_timeoutEvtTitleId);
|
|
4997
|
+
pauseBGM();
|
|
4924
4998
|
g_handler.removeListener(wheelHandler);
|
|
4925
4999
|
g_keyObj.prevKey = `Dummy${g_settings.musicIdxNum}`;
|
|
4926
5000
|
}, Object.assign({
|
|
@@ -4931,17 +5005,47 @@ const titleInit = (_initFlg = false) => {
|
|
|
4931
5005
|
createCss2Button(`btnMusicSelectNext`, `↓`, () => changeMSelect(1),
|
|
4932
5006
|
g_lblPosObj.btnMusicSelectNext, g_cssObj.button_Setting),
|
|
4933
5007
|
createCss2Button(`btnMusicSelectRandom`, `Random`, () =>
|
|
4934
|
-
changeMSelect(Math.floor(Math.random() *
|
|
5008
|
+
changeMSelect(Math.floor(Math.random() * (g_headerObj.musicIdxList.length - 1)) + 1),
|
|
4935
5009
|
g_lblPosObj.btnMusicSelectRandom, g_cssObj.button_Default),
|
|
4936
5010
|
createDivCss2Label(`lblMusicCnt`, ``, g_lblPosObj.lblMusicCnt),
|
|
4937
5011
|
createDivCss2Label(`lblComment`, ``, g_lblPosObj.lblComment_music),
|
|
5012
|
+
|
|
5013
|
+
createDivCss2Label(`lblBgmVolume`, `BGM Volume`, g_lblPosObj.lblBgmVolume),
|
|
5014
|
+
createCss2Button(`btnBgmMute`, g_stateObj.bgmMuteFlg ? `🔇` : `🔊`, evt => {
|
|
5015
|
+
g_stateObj.bgmMuteFlg = !g_stateObj.bgmMuteFlg;
|
|
5016
|
+
g_stateObj.bgmMuteFlg ? pauseBGM() : playBGM(0);
|
|
5017
|
+
evt.target.innerHTML = g_stateObj.bgmMuteFlg ? `🔇` : `🔊`;
|
|
5018
|
+
}, g_lblPosObj.btnBgmMute, g_cssObj.button_Default),
|
|
5019
|
+
createCss2Button(`btnBgmVolume`, `${g_stateObj.bgmVolume}${g_lblNameObj.percent}`, () => setBGMVolume(),
|
|
5020
|
+
Object.assign({
|
|
5021
|
+
cxtFunc: () => setBGMVolume(-1),
|
|
5022
|
+
}, g_lblPosObj.btnBgmVolume), g_cssObj.button_Default),
|
|
5023
|
+
createCss2Button(`btnBgmVolumeL`, `<`, () => setBGMVolume(-1),
|
|
5024
|
+
g_lblPosObj.btnBgmVolumeL, g_cssObj.button_Setting),
|
|
5025
|
+
createCss2Button(`btnBgmVolumeR`, `>`, () => setBGMVolume(),
|
|
5026
|
+
g_lblPosObj.btnBgmVolumeR, g_cssObj.button_Setting),
|
|
4938
5027
|
);
|
|
4939
5028
|
changeMSelect(0, _initFlg);
|
|
4940
5029
|
|
|
4941
5030
|
let wheelCnt = 0;
|
|
4942
5031
|
wheelHandler = g_handler.addListener(divRoot, `wheel`, e => {
|
|
5032
|
+
|
|
5033
|
+
// コメント欄(lblComment)のスクロール可能性をチェック
|
|
5034
|
+
const isScrollable = lblComment.scrollHeight > lblComment.clientHeight;
|
|
5035
|
+
|
|
5036
|
+
// マウスがコメント欄上にあり、スクロールが可能ならイベントをスキップ
|
|
5037
|
+
if (lblComment.contains(e.target) && isScrollable) {
|
|
5038
|
+
// スクロール位置の判定
|
|
5039
|
+
const atTop = lblComment.scrollTop === 0 && e.deltaY < 0;
|
|
5040
|
+
const atBottom = (lblComment.scrollTop + lblComment.clientHeight >= lblComment.scrollHeight) && e.deltaY > 0;
|
|
5041
|
+
|
|
5042
|
+
// スクロール可能&上端または下端ではないなら処理をスキップ
|
|
5043
|
+
if (!atTop && !atBottom) {
|
|
5044
|
+
return;
|
|
5045
|
+
}
|
|
5046
|
+
}
|
|
5047
|
+
e.preventDefault();
|
|
4943
5048
|
if (g_stateObj.keyInitial && wheelCnt === 0) {
|
|
4944
|
-
e.preventDefault();
|
|
4945
5049
|
changeMSelect(e.deltaY > 0 ? 1 : -1);
|
|
4946
5050
|
}
|
|
4947
5051
|
wheelCnt = (wheelCnt + 1) % wheelCycle;
|
|
@@ -4949,6 +5053,7 @@ const titleInit = (_initFlg = false) => {
|
|
|
4949
5053
|
|
|
4950
5054
|
// 初期表示用 (2秒後に選曲画面を表示)
|
|
4951
5055
|
if (_initFlg && !g_headerObj.customTitleUse) {
|
|
5056
|
+
g_audio.muted = true;
|
|
4952
5057
|
const mSelectTitleSprite = createEmptySprite(divRoot, `mSelectTitleSprite`,
|
|
4953
5058
|
g_windowObj.mSelectTitleSprite, g_cssObj.settings_DifSelector);
|
|
4954
5059
|
multiAppend(mSelectTitleSprite,
|
|
@@ -4967,6 +5072,8 @@ const titleInit = (_initFlg = false) => {
|
|
|
4967
5072
|
if (_opacity <= 0) {
|
|
4968
5073
|
clearTimeout(fadeOpacity);
|
|
4969
5074
|
mSelectTitleSprite.style.display = C_DIS_NONE;
|
|
5075
|
+
g_audio.muted = false;
|
|
5076
|
+
g_audio.currentTime = g_headerObj.musicStarts[g_headerObj.musicIdxList[g_settings.musicIdxNum]] ?? 0;
|
|
4970
5077
|
} else {
|
|
4971
5078
|
mSelectTitleSprite.style.opacity = _opacity;
|
|
4972
5079
|
fadeOpacity = setTimeout(() => {
|
|
@@ -5251,6 +5358,173 @@ const getCreatorInfo = (_creatorList) => {
|
|
|
5251
5358
|
return [creatorName, creatorUrl, creatorIdx];
|
|
5252
5359
|
}
|
|
5253
5360
|
|
|
5361
|
+
/**
|
|
5362
|
+
* BGMの停止
|
|
5363
|
+
*/
|
|
5364
|
+
const pauseBGM = () => {
|
|
5365
|
+
if (g_audio) {
|
|
5366
|
+
g_handler.removeListener(g_stateObj.bgmTimeupdateEvtId);
|
|
5367
|
+
g_audio.pause();
|
|
5368
|
+
if (!(g_audio instanceof AudioPlayer)) {
|
|
5369
|
+
g_audio.removeAttribute('src');
|
|
5370
|
+
g_audio.load();
|
|
5371
|
+
}
|
|
5372
|
+
}
|
|
5373
|
+
[`bgmLooped`, `bgmFadeIn`, `bgmFadeOut`].forEach(id => {
|
|
5374
|
+
if (g_stateObj[id]) {
|
|
5375
|
+
clearInterval(g_stateObj[id]);
|
|
5376
|
+
g_stateObj[id] = null;
|
|
5377
|
+
}
|
|
5378
|
+
});
|
|
5379
|
+
};
|
|
5380
|
+
|
|
5381
|
+
/**
|
|
5382
|
+
* BGM再生処理
|
|
5383
|
+
* @param {number} _num
|
|
5384
|
+
* @param {number} _currentLoopNum
|
|
5385
|
+
*/
|
|
5386
|
+
const playBGM = async (_num, _currentLoopNum = g_settings.musicLoopNum) => {
|
|
5387
|
+
const FADE_STEP = 0.05 * g_stateObj.bgmVolume / 100;
|
|
5388
|
+
const FADE_INTERVAL_MS = 100;
|
|
5389
|
+
const FADE_DELAY_MS = 500;
|
|
5390
|
+
|
|
5391
|
+
const musicUrl = getMusicUrl(g_headerObj.viewLists[0]);
|
|
5392
|
+
const url = getFullMusicUrl(musicUrl);
|
|
5393
|
+
const encodeFlg = listMatching(musicUrl, [`.js`, `.txt`], { suffix: `$` });
|
|
5394
|
+
const musicStart = g_headerObj.musicStarts?.[g_headerObj.musicIdxList[g_settings.musicIdxNum]] ?? 0;
|
|
5395
|
+
const musicEnd = g_headerObj.musicEnds?.[g_headerObj.musicIdxList[g_settings.musicIdxNum]] ?? 0;
|
|
5396
|
+
|
|
5397
|
+
/**
|
|
5398
|
+
* BGMのフェードアウトとシーク
|
|
5399
|
+
*/
|
|
5400
|
+
const fadeOutAndSeek = () => {
|
|
5401
|
+
let volume = g_audio.volume;
|
|
5402
|
+
const fadeInterval = setInterval(() => {
|
|
5403
|
+
if (volume > FADE_STEP && g_currentPage === `title`) {
|
|
5404
|
+
volume -= FADE_STEP;
|
|
5405
|
+
g_audio.volume = Math.max(volume, 0);
|
|
5406
|
+
} else {
|
|
5407
|
+
clearInterval(fadeInterval);
|
|
5408
|
+
g_stateObj.bgmFadeOut = null;
|
|
5409
|
+
g_audio.pause();
|
|
5410
|
+
g_audio.currentTime = musicStart;
|
|
5411
|
+
|
|
5412
|
+
// フェードイン開始
|
|
5413
|
+
if (g_currentPage === `title`) {
|
|
5414
|
+
setTimeout(() => {
|
|
5415
|
+
fadeIn();
|
|
5416
|
+
if (encodeFlg) {
|
|
5417
|
+
// base64エンコード時はtimeupdateイベントが発火しないため、
|
|
5418
|
+
// setIntervalで時間を取得する
|
|
5419
|
+
repeatBGM();
|
|
5420
|
+
}
|
|
5421
|
+
}, FADE_DELAY_MS);
|
|
5422
|
+
} else {
|
|
5423
|
+
pauseBGM();
|
|
5424
|
+
}
|
|
5425
|
+
}
|
|
5426
|
+
}, FADE_INTERVAL_MS);
|
|
5427
|
+
g_stateObj.bgmFadeOut = fadeInterval;
|
|
5428
|
+
};
|
|
5429
|
+
|
|
5430
|
+
/**
|
|
5431
|
+
* BGMのフェードイン
|
|
5432
|
+
*/
|
|
5433
|
+
const fadeIn = () => {
|
|
5434
|
+
if (!(g_audio instanceof AudioPlayer) && !g_audio.src) {
|
|
5435
|
+
return;
|
|
5436
|
+
}
|
|
5437
|
+
let volume = 0;
|
|
5438
|
+
g_audio.play();
|
|
5439
|
+
const fadeInterval = setInterval(() => {
|
|
5440
|
+
if (volume < g_stateObj.bgmVolume / 100 && g_currentPage === `title`) {
|
|
5441
|
+
volume += FADE_STEP;
|
|
5442
|
+
g_audio.volume = Math.min(volume, 1);
|
|
5443
|
+
} else {
|
|
5444
|
+
clearInterval(fadeInterval);
|
|
5445
|
+
g_stateObj.bgmFadeIn = null;
|
|
5446
|
+
}
|
|
5447
|
+
}, FADE_INTERVAL_MS);
|
|
5448
|
+
g_stateObj.bgmFadeIn = fadeInterval;
|
|
5449
|
+
};
|
|
5450
|
+
|
|
5451
|
+
/**
|
|
5452
|
+
* BGMのループ処理
|
|
5453
|
+
*/
|
|
5454
|
+
const repeatBGM = () => {
|
|
5455
|
+
if (encodeFlg) {
|
|
5456
|
+
// base64エンコード時はtimeupdateイベントが発火しないため、setIntervalで時間を取得する
|
|
5457
|
+
const repeatCheck = setInterval((num = g_settings.musicIdxNum) => {
|
|
5458
|
+
try {
|
|
5459
|
+
if (((g_audio.elapsedTime >= musicEnd) ||
|
|
5460
|
+
num !== g_settings.musicIdxNum) && g_stateObj.bgmLooped !== null) {
|
|
5461
|
+
clearInterval(repeatCheck);
|
|
5462
|
+
g_stateObj.bgmLooped = null;
|
|
5463
|
+
fadeOutAndSeek();
|
|
5464
|
+
}
|
|
5465
|
+
} catch (e) {
|
|
5466
|
+
clearInterval(repeatCheck);
|
|
5467
|
+
g_stateObj.bgmLooped = null;
|
|
5468
|
+
}
|
|
5469
|
+
}, FADE_INTERVAL_MS);
|
|
5470
|
+
g_stateObj.bgmLooped = repeatCheck;
|
|
5471
|
+
|
|
5472
|
+
} else {
|
|
5473
|
+
g_stateObj.bgmTimeupdateEvtId = g_handler.addListener(g_audio, "timeupdate", () => {
|
|
5474
|
+
if (g_audio.currentTime >= musicEnd) {
|
|
5475
|
+
fadeOutAndSeek();
|
|
5476
|
+
}
|
|
5477
|
+
});
|
|
5478
|
+
}
|
|
5479
|
+
};
|
|
5480
|
+
|
|
5481
|
+
if (encodeFlg) {
|
|
5482
|
+
try {
|
|
5483
|
+
// base64エンコードは読込に時間が掛かるため、曲変更時のみ読込
|
|
5484
|
+
if (!hasVal(g_musicdata) || Math.abs(_num) % g_headerObj.musicIdxList.length !== 0) {
|
|
5485
|
+
await loadScript2(url);
|
|
5486
|
+
musicInit();
|
|
5487
|
+
if (_currentLoopNum !== g_settings.musicLoopNum) {
|
|
5488
|
+
return;
|
|
5489
|
+
}
|
|
5490
|
+
const tmpAudio = new AudioPlayer();
|
|
5491
|
+
const array = Uint8Array.from(atob(g_musicdata), v => v.charCodeAt(0));
|
|
5492
|
+
await tmpAudio.init(array.buffer);
|
|
5493
|
+
if (_currentLoopNum !== g_settings.musicLoopNum) {
|
|
5494
|
+
tmpAudio.close();
|
|
5495
|
+
return;
|
|
5496
|
+
}
|
|
5497
|
+
g_audio = tmpAudio;
|
|
5498
|
+
}
|
|
5499
|
+
g_audio.volume = g_stateObj.bgmVolume / 100;
|
|
5500
|
+
if (g_currentPage === `title`) {
|
|
5501
|
+
g_audio.currentTime = musicStart;
|
|
5502
|
+
g_audio.play();
|
|
5503
|
+
}
|
|
5504
|
+
} catch (e) {
|
|
5505
|
+
// 音源の読み込みに失敗した場合、エラーを表示
|
|
5506
|
+
console.warn(`BGM load error: ${e}`);
|
|
5507
|
+
}
|
|
5508
|
+
|
|
5509
|
+
} else {
|
|
5510
|
+
g_audio = new Audio();
|
|
5511
|
+
g_audio.src = url;
|
|
5512
|
+
g_audio.autoplay = false;
|
|
5513
|
+
g_audio.volume = g_stateObj.bgmVolume / 100;
|
|
5514
|
+
const loadedMeta = g_handler.addListener(g_audio, `loadedmetadata`, () => {
|
|
5515
|
+
g_handler.removeListener(loadedMeta);
|
|
5516
|
+
if (_currentLoopNum !== g_settings.musicLoopNum) {
|
|
5517
|
+
return;
|
|
5518
|
+
}
|
|
5519
|
+
g_audio.currentTime = musicStart;
|
|
5520
|
+
g_audio.play();
|
|
5521
|
+
}, { once: true });
|
|
5522
|
+
}
|
|
5523
|
+
if (musicEnd > 0) {
|
|
5524
|
+
repeatBGM();
|
|
5525
|
+
}
|
|
5526
|
+
};
|
|
5527
|
+
|
|
5254
5528
|
/**
|
|
5255
5529
|
* 選曲ボタンを押したときの処理
|
|
5256
5530
|
* @param {number} _num
|
|
@@ -5258,12 +5532,11 @@ const getCreatorInfo = (_creatorList) => {
|
|
|
5258
5532
|
*/
|
|
5259
5533
|
const changeMSelect = (_num, _initFlg = false) => {
|
|
5260
5534
|
const limitedMLength = 35;
|
|
5261
|
-
|
|
5262
|
-
const musicIdxTmpList = [...Array(musicMaxIdx + 1).keys()];
|
|
5535
|
+
pauseBGM();
|
|
5263
5536
|
|
|
5264
5537
|
// 選択方向に合わせて楽曲リスト情報を再取得
|
|
5265
5538
|
for (let j = -g_settings.mSelectableTerms; j <= g_settings.mSelectableTerms; j++) {
|
|
5266
|
-
const idx = (j + _num + g_settings.musicIdxNum +
|
|
5539
|
+
const idx = g_headerObj.musicIdxList[(j + _num + g_settings.musicIdxNum + g_headerObj.musicIdxList.length * 10) % g_headerObj.musicIdxList.length];
|
|
5267
5540
|
if (j === 0) {
|
|
5268
5541
|
} else {
|
|
5269
5542
|
document.getElementById(`btnMusicSelect${j}`).style.fontSize =
|
|
@@ -5274,33 +5547,39 @@ const changeMSelect = (_num, _initFlg = false) => {
|
|
|
5274
5547
|
}
|
|
5275
5548
|
}
|
|
5276
5549
|
// 現在選択中の楽曲IDを再設定
|
|
5277
|
-
g_settings.musicIdxNum = (g_settings.musicIdxNum + _num +
|
|
5550
|
+
g_settings.musicIdxNum = (g_settings.musicIdxNum + _num + g_headerObj.musicIdxList.length) % g_headerObj.musicIdxList.length;
|
|
5551
|
+
|
|
5552
|
+
// 楽曲の多重読込防止(この値が変化していれば読み込まない)
|
|
5553
|
+
g_settings.musicLoopNum++;
|
|
5554
|
+
const currentLoopNum = g_settings.musicLoopNum;
|
|
5278
5555
|
|
|
5279
5556
|
// 選択した楽曲に対応する譜面番号、製作者情報、曲長を取得
|
|
5280
5557
|
g_headerObj.viewLists = [];
|
|
5281
|
-
const tmpKeyList = [], tmpCreatorList = [], tmpPlayingFrameList = [];
|
|
5558
|
+
const tmpKeyList = [], tmpCreatorList = [], tmpPlayingFrameList = [], tmpBpmList = [];
|
|
5559
|
+
const targetIdx = g_headerObj.musicIdxList[(g_settings.musicIdxNum + g_headerObj.musicIdxList.length * 20) % g_headerObj.musicIdxList.length];
|
|
5282
5560
|
g_headerObj.musicNos.forEach((val, j) => {
|
|
5283
|
-
if (
|
|
5284
|
-
musicIdxTmpList.length) {
|
|
5561
|
+
if ((g_headerObj.musicGroups?.[val] ?? val) === targetIdx) {
|
|
5285
5562
|
g_headerObj.viewLists.push(j);
|
|
5286
5563
|
tmpKeyList.push(g_headerObj.keyLabels[j]);
|
|
5287
5564
|
tmpCreatorList.push(g_headerObj.creatorNames[j]);
|
|
5288
5565
|
tmpPlayingFrameList.push(g_detailObj.playingFrameWithBlank[j]);
|
|
5566
|
+
tmpBpmList.push(g_headerObj.bpms[g_headerObj.musicNos[j]]);
|
|
5289
5567
|
}
|
|
5290
5568
|
});
|
|
5291
|
-
const playingFrames = makeDedupliArray(tmpPlayingFrameList.
|
|
5569
|
+
const playingFrames = makeDedupliArray(tmpPlayingFrameList.map(val => transFrameToTimer(val))).join(`, `);
|
|
5570
|
+
const bpm = makeDedupliArray(tmpBpmList).join(`, `);
|
|
5292
5571
|
const [creatorName, creatorUrl, creatorIdx] = getCreatorInfo(tmpCreatorList);
|
|
5293
5572
|
const creatorLink = creatorIdx >= 0 ?
|
|
5294
5573
|
`<a href="${creatorUrl}" target="_blank">${creatorName}</a>` : creatorName;
|
|
5295
5574
|
|
|
5296
5575
|
// 選択した楽曲の情報表示
|
|
5297
|
-
const idx = g_settings.musicIdxNum;
|
|
5576
|
+
const idx = g_headerObj.musicIdxList[g_settings.musicIdxNum];
|
|
5298
5577
|
document.getElementById(`lblMusicSelect`).innerHTML =
|
|
5299
5578
|
`<span style="font-size:${getFontSize(g_headerObj.musicTitlesForView[idx].join(`<br>`), g_btnWidth(1 / 2), getBasicFont(), 18)}px;` +
|
|
5300
5579
|
`font-weight:bold">${g_headerObj.musicTitlesForView[idx].join(`<br>`)}</span>`;
|
|
5301
5580
|
document.getElementById(`lblMusicSelectDetail`).innerHTML =
|
|
5302
5581
|
`Maker: ${creatorLink} / Artist: <a href="${g_headerObj.artistUrls[idx]}" target="_blank">` +
|
|
5303
|
-
`${g_headerObj.artistNames[idx]}</a><br>Duration: ${playingFrames} / BPM: ${
|
|
5582
|
+
`${g_headerObj.artistNames[idx]}</a><br>Duration: ${playingFrames} / BPM: ${bpm}`;
|
|
5304
5583
|
|
|
5305
5584
|
// 選択した楽曲で使われているキー種の一覧を作成
|
|
5306
5585
|
deleteChildspriteAll(`keyTitleSprite`);
|
|
@@ -5312,14 +5591,14 @@ const changeMSelect = (_num, _initFlg = false) => {
|
|
|
5312
5591
|
|
|
5313
5592
|
|
|
5314
5593
|
// 選択した楽曲の選択位置を表示
|
|
5315
|
-
lblMusicCnt.innerHTML = `${g_settings.musicIdxNum + 1} / ${
|
|
5594
|
+
lblMusicCnt.innerHTML = `${g_settings.musicIdxNum + 1} / ${g_headerObj.musicIdxList.length}`;
|
|
5316
5595
|
|
|
5317
5596
|
// 楽曲別のローカルストレージを再取得
|
|
5318
5597
|
loadLocalStorage(g_settings.musicIdxNum);
|
|
5319
5598
|
viewKeyStorage.cache = new Map();
|
|
5320
5599
|
|
|
5321
5600
|
// 初期化もしくは楽曲変更時に速度を初期化
|
|
5322
|
-
if (_initFlg || _num !== 0) {
|
|
5601
|
+
if (_initFlg || Math.abs(_num) % g_headerObj.musicIdxList.length !== 0) {
|
|
5323
5602
|
g_stateObj.speed = g_headerObj.initSpeeds[g_headerObj.viewLists[0]];
|
|
5324
5603
|
g_settings.speedNum = getCurrentNo(g_settings.speeds, g_stateObj.speed);
|
|
5325
5604
|
}
|
|
@@ -5327,6 +5606,19 @@ const changeMSelect = (_num, _initFlg = false) => {
|
|
|
5327
5606
|
// コメント文の加工
|
|
5328
5607
|
lblComment.innerHTML = convertStrToVal(g_headerObj[`commentVal${g_settings.musicIdxNum}`]);
|
|
5329
5608
|
|
|
5609
|
+
// BGM再生処理
|
|
5610
|
+
if (!g_stateObj.bgmMuteFlg) {
|
|
5611
|
+
if (_initFlg) {
|
|
5612
|
+
playBGM(_num);
|
|
5613
|
+
} else {
|
|
5614
|
+
setTimeout(() => {
|
|
5615
|
+
if (currentLoopNum === g_settings.musicLoopNum) {
|
|
5616
|
+
playBGM(_num, currentLoopNum);
|
|
5617
|
+
}
|
|
5618
|
+
}, 500);
|
|
5619
|
+
}
|
|
5620
|
+
}
|
|
5621
|
+
|
|
5330
5622
|
// 選曲変更時のカスタム関数実行
|
|
5331
5623
|
g_customJsObj.musicSelect.forEach(func => func(g_settings.musicIdxNum));
|
|
5332
5624
|
};
|
|
@@ -5830,11 +6122,7 @@ const optionInit = () => {
|
|
|
5830
6122
|
g_stateObj.filterKeys = ``;
|
|
5831
6123
|
|
|
5832
6124
|
// 楽曲データの表示
|
|
5833
|
-
|
|
5834
|
-
`BPM: ${g_headerObj.bpms[g_settings.musicIdxNum]}`;
|
|
5835
|
-
if (!g_headerObj.musicSelectUse && g_headerObj.bpms[g_settings.musicIdxNum] === `----`) {
|
|
5836
|
-
text = ``;
|
|
5837
|
-
}
|
|
6125
|
+
const text = getMusicInfoView();
|
|
5838
6126
|
divRoot.appendChild(createDivCss2Label(`lblMusicInfo`, text,
|
|
5839
6127
|
Object.assign({ siz: getFontSize(text, g_btnWidth(3 / 4), getBasicFont(), 12) }, g_lblPosObj.lblMusicInfo)));
|
|
5840
6128
|
|
|
@@ -5858,6 +6146,20 @@ const optionInit = () => {
|
|
|
5858
6146
|
g_skinJsObj.option.forEach(func => func());
|
|
5859
6147
|
};
|
|
5860
6148
|
|
|
6149
|
+
/**
|
|
6150
|
+
* 設定画面に表示する楽曲・BPM情報の取得
|
|
6151
|
+
* @returns {string}
|
|
6152
|
+
*/
|
|
6153
|
+
const getMusicInfoView = () => {
|
|
6154
|
+
const idx = g_headerObj.musicNos[g_stateObj.scoreId];
|
|
6155
|
+
let text = `♪` + (g_headerObj.musicSelectUse ? `${g_headerObj.musicTitles[idx]} / ` : ``) +
|
|
6156
|
+
`BPM: ${g_headerObj.bpms[idx]}`;
|
|
6157
|
+
if (!g_headerObj.musicSelectUse && g_headerObj.bpms[idx] === `----`) {
|
|
6158
|
+
text = ``;
|
|
6159
|
+
}
|
|
6160
|
+
return text;
|
|
6161
|
+
};
|
|
6162
|
+
|
|
5861
6163
|
/**
|
|
5862
6164
|
* 設定画面用スプライトリストの作成
|
|
5863
6165
|
* @param {object} _settingList (設定名、縦位置、縦位置差分、幅差分、高さ差分)を設定別にリスト化
|
|
@@ -6686,6 +6988,10 @@ const setDifficulty = (_initFlg) => {
|
|
|
6686
6988
|
makeHighScore(g_stateObj.scoreId);
|
|
6687
6989
|
}
|
|
6688
6990
|
|
|
6991
|
+
// 楽曲データの表示
|
|
6992
|
+
lblMusicInfo.textContent = getMusicInfoView();
|
|
6993
|
+
lblMusicInfo.style.fontSize = wUnit(getFontSize(lblMusicInfo.textContent, g_btnWidth(3 / 4), getBasicFont(), 12));
|
|
6994
|
+
|
|
6689
6995
|
// ユーザカスタムイベント(初期)
|
|
6690
6996
|
g_customJsObj.difficulty.forEach(func => func(_initFlg, g_canLoadDifInfoFlg));
|
|
6691
6997
|
|
|
@@ -8834,13 +9140,7 @@ const loadMusic = () => {
|
|
|
8834
9140
|
g_currentPage = `loading`;
|
|
8835
9141
|
|
|
8836
9142
|
const musicUrl = getMusicUrl(g_stateObj.scoreId);
|
|
8837
|
-
|
|
8838
|
-
if (musicUrl.indexOf(C_MRK_CURRENT_DIRECTORY) !== -1) {
|
|
8839
|
-
url = musicUrl.split(C_MRK_CURRENT_DIRECTORY)[1];
|
|
8840
|
-
} else if (g_headerObj.musicFolder.indexOf(C_MRK_CURRENT_DIRECTORY) !== -1) {
|
|
8841
|
-
url = `${g_headerObj.musicFolder.split(C_MRK_CURRENT_DIRECTORY)[1]}/${musicUrl}`;
|
|
8842
|
-
}
|
|
8843
|
-
|
|
9143
|
+
const url = getFullMusicUrl(musicUrl);
|
|
8844
9144
|
g_headerObj.musicUrl = musicUrl;
|
|
8845
9145
|
g_musicEncodedFlg = listMatching(musicUrl, [`.js`, `.txt`], { suffix: `$` });
|
|
8846
9146
|
|
|
@@ -8902,6 +9202,7 @@ const setAudio = async (_url) => {
|
|
|
8902
9202
|
|
|
8903
9203
|
const loadMp3 = () => {
|
|
8904
9204
|
if (g_isFile) {
|
|
9205
|
+
g_audio = new Audio();
|
|
8905
9206
|
g_audio.src = _url;
|
|
8906
9207
|
musicAfterLoaded();
|
|
8907
9208
|
} else {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Source by tickle
|
|
7
7
|
* Created : 2019/11/19
|
|
8
|
-
* Revised : 2025/
|
|
8
|
+
* Revised : 2025/05/09 (v41.2.0)
|
|
9
9
|
*
|
|
10
10
|
* https://github.com/cwtickle/danoniplus
|
|
11
11
|
*/
|
|
@@ -288,6 +288,21 @@ const updateWindowSiz = () => {
|
|
|
288
288
|
siz: g_limitObj.difSelectorSiz, align: C_ALIGN_LEFT,
|
|
289
289
|
overflow: C_DIS_AUTO, whiteSpace: `normal`,
|
|
290
290
|
},
|
|
291
|
+
btnBgmMute: {
|
|
292
|
+
x: g_btnX() + 90, y: g_sHeight - 105, w: 40, h: 35, siz: 30,
|
|
293
|
+
},
|
|
294
|
+
lblBgmVolume: {
|
|
295
|
+
x: g_btnX(), y: g_sHeight - 85, w: g_btnWidth(1 / 4), h: 20, siz: 12, align: C_ALIGN_LEFT,
|
|
296
|
+
},
|
|
297
|
+
btnBgmVolume: {
|
|
298
|
+
x: g_btnX() + 20, y: g_sHeight - 70, w: g_btnWidth(1 / 4) - 40, h: 20, siz: 14,
|
|
299
|
+
},
|
|
300
|
+
btnBgmVolumeL: {
|
|
301
|
+
x: g_btnX(), y: g_sHeight - 70, w: 20, h: 20, siz: 12,
|
|
302
|
+
},
|
|
303
|
+
btnBgmVolumeR: {
|
|
304
|
+
x: g_btnX() + g_btnWidth(1 / 4) - 20, y: g_sHeight - 70, w: 20, h: 20, siz: 12,
|
|
305
|
+
},
|
|
291
306
|
|
|
292
307
|
/** データ管理 */
|
|
293
308
|
btnResetBack: {
|
|
@@ -999,6 +1014,13 @@ let C_WOD_FRAME = 30;
|
|
|
999
1014
|
// 譜面データ持ち回り用
|
|
1000
1015
|
const g_stateObj = {
|
|
1001
1016
|
keyInitial: false,
|
|
1017
|
+
bgmVolume: 50,
|
|
1018
|
+
bgmLooped: null,
|
|
1019
|
+
bgmFadeIn: null,
|
|
1020
|
+
bgmFadeOut: null,
|
|
1021
|
+
bgmTimeupdateEvtId: null,
|
|
1022
|
+
bgmMuteFlg: false,
|
|
1023
|
+
|
|
1002
1024
|
dosDivideFlg: false,
|
|
1003
1025
|
scoreLockFlg: false,
|
|
1004
1026
|
scoreId: 0,
|
|
@@ -1015,6 +1037,7 @@ const g_stateObj = {
|
|
|
1015
1037
|
hitPosition: 0,
|
|
1016
1038
|
fadein: 0,
|
|
1017
1039
|
volume: 100,
|
|
1040
|
+
|
|
1018
1041
|
lifeRcv: 2,
|
|
1019
1042
|
lifeDmg: 7,
|
|
1020
1043
|
lifeMode: `Border`,
|
|
@@ -1115,6 +1138,7 @@ const makeSpeedList = (_minSpd, _maxSpd) => [...Array((_maxSpd - _minSpd) * 20 +
|
|
|
1115
1138
|
const g_settings = {
|
|
1116
1139
|
|
|
1117
1140
|
musicIdxNum: 0,
|
|
1141
|
+
musicLoopNum: 0,
|
|
1118
1142
|
dataMgtNum: {
|
|
1119
1143
|
environment: 0,
|
|
1120
1144
|
highscores: 0,
|
|
@@ -1163,6 +1187,7 @@ const g_settings = {
|
|
|
1163
1187
|
|
|
1164
1188
|
volumes: [0, 0.5, 1, 2, 5, 10, 25, 50, 75, 100],
|
|
1165
1189
|
volumeNum: 0,
|
|
1190
|
+
bgmVolumeNum: 0,
|
|
1166
1191
|
|
|
1167
1192
|
appearances: [`Visible`, `Hidden`, `Hidden+`, `Sudden`, `Sudden+`, `Hid&Sud+`],
|
|
1168
1193
|
appearanceNum: 0,
|
|
@@ -1239,6 +1264,7 @@ const g_settings = {
|
|
|
1239
1264
|
};
|
|
1240
1265
|
|
|
1241
1266
|
g_settings.volumeNum = g_settings.volumes.length - 1;
|
|
1267
|
+
g_settings.bgmVolumeNum = roundZero(g_settings.volumes.findIndex(v => v === g_stateObj.bgmVolume));
|
|
1242
1268
|
g_settings.opacityNum = g_settings.opacitys.length - 1;
|
|
1243
1269
|
|
|
1244
1270
|
/**
|
|
@@ -2075,6 +2101,10 @@ const g_shortcutObj = {
|
|
|
2075
2101
|
KeyD: { id: `btnReset` },
|
|
2076
2102
|
ArrowUp: { id: `btnMusicSelectPrev` },
|
|
2077
2103
|
ArrowDown: { id: `btnMusicSelectNext` },
|
|
2104
|
+
ArrowLeft: { id: `btnBgmVolumeL` },
|
|
2105
|
+
ArrowRight: { id: `btnBgmVolumeR` },
|
|
2106
|
+
KeyM: { id: `btnBgmMute` },
|
|
2107
|
+
KeyR: { id: `btnMusicSelectRandom` },
|
|
2078
2108
|
},
|
|
2079
2109
|
dataMgt: {
|
|
2080
2110
|
KeyE: { id: `btnEnvironment` },
|
|
@@ -2433,7 +2463,7 @@ Object.keys(g_btnWaitFrame).forEach(key => {
|
|
|
2433
2463
|
// - btn + プロパティ名に合致するボタンid名に対して、
|
|
2434
2464
|
// どの位置(X方向)にショートカット名を表示するかを設定
|
|
2435
2465
|
const g_btnPatterns = {
|
|
2436
|
-
title: { Start: 0, Comment: -10 },
|
|
2466
|
+
title: { Start: 0, Comment: -10, MusicSelectRandom: -10 },
|
|
2437
2467
|
dataMgt: { Back: 0, Environment: -35, Highscores: -35, CustomKey: -35, Others: -35 },
|
|
2438
2468
|
precondition: { Back: 0 },
|
|
2439
2469
|
option: { Back: 0, KeyConfig: 0, Play: 0, Display: -5, Save: -10, Graph: -25 },
|