danoniplus 49.5.0 → 49.6.1
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 +233 -65
- package/js/lib/danoni_constants.js +31 -31
- package/package.json +1 -1
package/js/danoni_main.js
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Source by tickle
|
|
6
6
|
* Created : 2018/10/08
|
|
7
|
-
* Revised : 2026/08/
|
|
7
|
+
* Revised : 2026/08/19
|
|
8
8
|
*
|
|
9
9
|
* https://github.com/cwtickle/danoniplus
|
|
10
10
|
*/
|
|
11
|
-
const g_version = `Ver 49.
|
|
12
|
-
const g_revisedDate = `2026/08/
|
|
11
|
+
const g_version = `Ver 49.6.1`;
|
|
12
|
+
const g_revisedDate = `2026/08/19`;
|
|
13
13
|
|
|
14
14
|
// カスタム用バージョン (danoni_custom.js 等で指定可)
|
|
15
15
|
let g_localVersion = ``;
|
|
@@ -135,6 +135,19 @@ let g_fps = 60;
|
|
|
135
135
|
// プレイ画面再生時の内部スケジューリング用のマージン時間(100ms)
|
|
136
136
|
let g_scheduleLead = 0.1;
|
|
137
137
|
|
|
138
|
+
// フレーム進行を音源クロック(AudioContext.currentTime)基準で補正するか
|
|
139
|
+
// - false の場合は従来通り performance.now() 基準で動作
|
|
140
|
+
let g_audioClockSync = true;
|
|
141
|
+
|
|
142
|
+
// 出力遅延(AudioContext.outputLatency)をタイミング補正に含めるか
|
|
143
|
+
// - true にすると出力デバイス(有線/Bluetooth等)によらず同じAdjustmentが使えるが、
|
|
144
|
+
// 既存のAdjustment設定値と互換性がなくなるため既定は false
|
|
145
|
+
let g_audioLatencyCompensation = false;
|
|
146
|
+
|
|
147
|
+
// 次フレームまでの待機時間の上限(ms)
|
|
148
|
+
// - 音源クロックが一時的に停止した際に待ち続けないようにするための保険
|
|
149
|
+
let g_maxFrameWait = 50;
|
|
150
|
+
|
|
138
151
|
// 譜面データの&区切りを有効にするか
|
|
139
152
|
let g_enableAmpersandSplit = true;
|
|
140
153
|
|
|
@@ -384,7 +397,7 @@ const g_convFunc = {
|
|
|
384
397
|
* @param {string} _checkStr
|
|
385
398
|
* @param {string} _default
|
|
386
399
|
* @param {string} [_type='string']
|
|
387
|
-
* @returns
|
|
400
|
+
* @returns {number|boolean|string}
|
|
388
401
|
*/
|
|
389
402
|
const setVal = (_checkStr, _default, _type = C_TYP_STRING) =>
|
|
390
403
|
hasValN(_checkStr) ? g_convFunc[_type](_checkStr, _default) : _default;
|
|
@@ -1570,7 +1583,7 @@ const getFontSize2 = (_str, _maxWidth, { font = getBasicFont(), maxSiz = 14, min
|
|
|
1570
1583
|
};
|
|
1571
1584
|
|
|
1572
1585
|
/**
|
|
1573
|
-
*
|
|
1586
|
+
* 配列中から最も長い文字列を抽出(本体では未使用)
|
|
1574
1587
|
* @param {string[]} _array
|
|
1575
1588
|
* @returns {string}
|
|
1576
1589
|
*/
|
|
@@ -1688,8 +1701,8 @@ const dragDiv = (_divName, { minX = 0, minY = 0, maxX = g_sWidth, maxY = g_sHeig
|
|
|
1688
1701
|
const nextY = div.offsetTop + evt.movementY;
|
|
1689
1702
|
const clampMaxX = (maxX === minX) ? maxX : (maxX - div.offsetWidth);
|
|
1690
1703
|
const clampMaxY = (maxY === minY) ? maxY : (maxY - div.offsetHeight);
|
|
1691
|
-
div.style.left = Math.min(Math.max(nextX, minX), clampMaxX)
|
|
1692
|
-
div.style.top = Math.min(Math.max(nextY, minY), clampMaxY)
|
|
1704
|
+
div.style.left = wUnit(Math.min(Math.max(nextX, minX), clampMaxX));
|
|
1705
|
+
div.style.top = wUnit(Math.min(Math.max(nextY, minY), clampMaxY));
|
|
1693
1706
|
div.style.position = 'absolute';
|
|
1694
1707
|
div.draggable = false;
|
|
1695
1708
|
div.setPointerCapture(evt.pointerId);
|
|
@@ -1826,7 +1839,7 @@ const createMultipleSprite = (_baseName, _num, { x = 0, priority = g_transPriori
|
|
|
1826
1839
|
for (let j = 0; j <= _num; j++) {
|
|
1827
1840
|
createEmptySprite(sprite, `${_baseName}${j}`);
|
|
1828
1841
|
}
|
|
1829
|
-
addTransform(_baseName, `root`, `translateX(${x}
|
|
1842
|
+
addTransform(_baseName, `root`, `translateX(${wUnit(x)})`, priority);
|
|
1830
1843
|
return sprite;
|
|
1831
1844
|
};
|
|
1832
1845
|
|
|
@@ -2296,13 +2309,19 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
|
|
|
2296
2309
|
maxDepth = tmpDepth;
|
|
2297
2310
|
}
|
|
2298
2311
|
|
|
2312
|
+
const colorObjFlg = tmpSpriteData[2]?.startsWith(`[c]`) || false;
|
|
2313
|
+
const transformFlg = tmpSpriteData[2]?.startsWith(`[t]`) || false;
|
|
2299
2314
|
const tmpObj = {
|
|
2300
2315
|
path: escapeHtml(tmpSpriteData[2] ?? ``, g_escapeStr.escapeCode), // 画像パス or テキスト
|
|
2301
2316
|
class: escapeHtml(tmpSpriteData[3] ?? ``), // CSSクラス
|
|
2302
|
-
left:
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2317
|
+
left: transformFlg
|
|
2318
|
+
? setVal(tmpSpriteData[4], 1000, C_TYP_NUMBER) // [t]のみtransformのPriority
|
|
2319
|
+
: setVal(tmpSpriteData[4], `0`).includes(`{`)
|
|
2320
|
+
? `${setVal(tmpSpriteData[4], 0)}`
|
|
2321
|
+
: `{${setVal(tmpSpriteData[4], 0)}}`, // X座標
|
|
2322
|
+
top: setVal(tmpSpriteData[5], `0`).includes(`{`)
|
|
2323
|
+
? `${setVal(tmpSpriteData[5], 0)}`
|
|
2324
|
+
: `{${setVal(tmpSpriteData[5], 0)}}`, // Y座標
|
|
2306
2325
|
width: `${setIntVal(tmpSpriteData[6])}`, // spanタグの場合は font-size
|
|
2307
2326
|
height: `${escapeHtml(tmpSpriteData[7] ?? ``)}`, // spanタグの場合は color(文字列可)
|
|
2308
2327
|
opacity: setVal(tmpSpriteData[8], 1, C_TYP_FLOAT),
|
|
@@ -2319,7 +2338,6 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
|
|
|
2319
2338
|
checkDuplicatedObjects(spriteData[tmpFrame]);
|
|
2320
2339
|
|
|
2321
2340
|
const emptyPatterns = [`[loop]`, `[jump]`];
|
|
2322
|
-
const colorObjFlg = tmpSpriteData[2]?.startsWith(`[c]`) || false;
|
|
2323
2341
|
const spriteFrameData = spriteData[tmpFrame][dataCnts] = {
|
|
2324
2342
|
depth: tmpDepth,
|
|
2325
2343
|
};
|
|
@@ -2327,9 +2345,15 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
|
|
|
2327
2345
|
if (colorObjFlg) {
|
|
2328
2346
|
// [c]始まりの場合、カラーオブジェクト用の作成準備を行う
|
|
2329
2347
|
const data = tmpObj.path.slice(`[c]`.length).split(`/`);
|
|
2348
|
+
let objPart = data[0];
|
|
2349
|
+
if (!isNaN(parseInt(data[0]))) {
|
|
2350
|
+
const keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`;
|
|
2351
|
+
objPart = g_keyObj[`stepRtn${keyCtrlPtn}`][data[0]];
|
|
2352
|
+
spriteFrameData.transform = parseInt(data[0]);
|
|
2353
|
+
}
|
|
2330
2354
|
spriteFrameData.colorObjInfo = {
|
|
2331
2355
|
x: tmpObj.left, y: tmpObj.top, w: tmpObj.width, h: tmpObj.height,
|
|
2332
|
-
rotate: setVal(
|
|
2356
|
+
rotate: setVal(objPart, `0`), opacity: tmpObj.opacity,
|
|
2333
2357
|
background: makeColorGradation(setVal(data[1], `#ffffff`), { _defaultColorgrd: false }),
|
|
2334
2358
|
animationName: tmpObj.animationName,
|
|
2335
2359
|
animationDuration: `${tmpObj.animationDuration}s`,
|
|
@@ -2339,6 +2363,12 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
|
|
|
2339
2363
|
if (tmpObj.animationFillMode !== undefined) {
|
|
2340
2364
|
spriteFrameData.colorObjInfo.animationFillMode = tmpObj.animationFillMode;
|
|
2341
2365
|
}
|
|
2366
|
+
} else if (transformFlg) {
|
|
2367
|
+
// [t]始まりの場合、レイヤーに対してtransformを掛ける準備を行う
|
|
2368
|
+
const transformData = tmpObj.path.slice(`[t]`.length);
|
|
2369
|
+
spriteFrameData.transform = transformData || ``;
|
|
2370
|
+
spriteFrameData.transformId = tmpObj.class;
|
|
2371
|
+
spriteFrameData.transPriority = tmpObj.left;
|
|
2342
2372
|
|
|
2343
2373
|
} else if (tmpObj.path === ``) {
|
|
2344
2374
|
spriteFrameData.command = ``;
|
|
@@ -2422,6 +2452,10 @@ const drawBaseSpriteData = (_spriteData, _name, _condition = true) => {
|
|
|
2422
2452
|
}
|
|
2423
2453
|
} else {
|
|
2424
2454
|
if (_condition) {
|
|
2455
|
+
if (_spriteData.colorObjInfo === undefined && _spriteData.transform === undefined) {
|
|
2456
|
+
baseSprite.innerHTML = convertStrToVal(_spriteData.htmlText);
|
|
2457
|
+
return;
|
|
2458
|
+
}
|
|
2425
2459
|
if (_spriteData.colorObjInfo !== undefined) {
|
|
2426
2460
|
const colorObjClass = _spriteData.colorObjClass?.split(`/`) ?? [];
|
|
2427
2461
|
const id = `${_name}${_spriteData.depth}${_spriteData.colorObjId}`;
|
|
@@ -2429,8 +2463,32 @@ const drawBaseSpriteData = (_spriteData, _name, _condition = true) => {
|
|
|
2429
2463
|
baseSprite.appendChild(
|
|
2430
2464
|
createColorObject2(id, _spriteData.colorObjInfo, ...colorObjClass)
|
|
2431
2465
|
);
|
|
2432
|
-
}
|
|
2433
|
-
|
|
2466
|
+
}
|
|
2467
|
+
if (_spriteData.transform !== undefined) {
|
|
2468
|
+
const targetId = `${_name}Sprite${_spriteData.depth}`;
|
|
2469
|
+
|
|
2470
|
+
if (!isNaN(parseInt(_spriteData.transform))) {
|
|
2471
|
+
// PlayWindow由来のtransformを継承(別transformId)
|
|
2472
|
+
const transformId = `${_name}${_spriteData.depth}PlayWindow`;
|
|
2473
|
+
const transformData = getTransform(`mainSprite`, `playWindow`);
|
|
2474
|
+
|
|
2475
|
+
if (hasVal(transformData)) {
|
|
2476
|
+
if (transformData !== getTransform(targetId, transformId)) {
|
|
2477
|
+
addTransform(targetId, transformId, transformData, g_transPriority.playWindow);
|
|
2478
|
+
}
|
|
2479
|
+
} else {
|
|
2480
|
+
delTransform(targetId, transformId);
|
|
2481
|
+
}
|
|
2482
|
+
} else {
|
|
2483
|
+
// 明示指定のtransformを適用
|
|
2484
|
+
const transformId = _spriteData.transformId || `${_name}${_spriteData.depth}`;
|
|
2485
|
+
|
|
2486
|
+
if (hasVal(_spriteData.transform)) {
|
|
2487
|
+
addTransform(targetId, transformId, _spriteData.transform, _spriteData.transPriority);
|
|
2488
|
+
} else {
|
|
2489
|
+
delTransform(targetId, transformId);
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2434
2492
|
}
|
|
2435
2493
|
}
|
|
2436
2494
|
}
|
|
@@ -2517,6 +2575,7 @@ class AudioPlayer {
|
|
|
2517
2575
|
this._gain = this._context.createGain();
|
|
2518
2576
|
this._gain.connect(this._context.destination);
|
|
2519
2577
|
this._startTime = 0;
|
|
2578
|
+
this._scheduledTime = 0;
|
|
2520
2579
|
this._fadeinPosition = 0;
|
|
2521
2580
|
this._eventListeners = {};
|
|
2522
2581
|
this.playbackRate = 1;
|
|
@@ -2541,17 +2600,25 @@ class AudioPlayer {
|
|
|
2541
2600
|
* - scheduleLead は安定した再生タイミングを確保するための内部マージン
|
|
2542
2601
|
*/
|
|
2543
2602
|
play(_adjustmentTime = 0) {
|
|
2603
|
+
// AudioContextの時計は1回だけ読み、以降はその値を使い回す
|
|
2604
|
+
// - currentTimeはレンダークォンタム単位でしか進まないため、複数回読むと
|
|
2605
|
+
// 予約時刻と論理開始時刻が最大1クォンタム分ずれる
|
|
2606
|
+
const ctxNow = this._context.currentTime;
|
|
2607
|
+
|
|
2544
2608
|
this._source = this._context.createBufferSource();
|
|
2545
2609
|
this._source.buffer = this._buffer;
|
|
2546
2610
|
this._source.playbackRate.value = this.playbackRate;
|
|
2547
2611
|
this._source.connect(this._gain);
|
|
2548
2612
|
|
|
2549
2613
|
// 実際の予約時刻(内部スケジューリング用のマージンを含む)
|
|
2550
|
-
const startAt =
|
|
2614
|
+
const startAt = ctxNow + g_scheduleLead + _adjustmentTime;
|
|
2551
2615
|
this._source.start(startAt, this._fadeinPosition);
|
|
2552
2616
|
|
|
2553
2617
|
// ゲーム側の論理的開始時刻(g_scheduleLead を含めない)
|
|
2554
|
-
this._startTime =
|
|
2618
|
+
this._startTime = ctxNow + _adjustmentTime;
|
|
2619
|
+
|
|
2620
|
+
// 実際に音が鳴り始めるAudioContext上の時刻(フレーム同期の基準)
|
|
2621
|
+
this._scheduledTime = startAt;
|
|
2555
2622
|
}
|
|
2556
2623
|
|
|
2557
2624
|
pause() {
|
|
@@ -2576,6 +2643,26 @@ class AudioPlayer {
|
|
|
2576
2643
|
return this._context.currentTime - this._startTime + this._fadeinPosition;
|
|
2577
2644
|
}
|
|
2578
2645
|
|
|
2646
|
+
/** AudioContextの現在時刻(秒) */
|
|
2647
|
+
get contextTime() {
|
|
2648
|
+
return this._context.currentTime;
|
|
2649
|
+
}
|
|
2650
|
+
|
|
2651
|
+
/** 実際に音が鳴り始めるAudioContext上の時刻(秒) */
|
|
2652
|
+
get scheduledTime() {
|
|
2653
|
+
return this._scheduledTime;
|
|
2654
|
+
}
|
|
2655
|
+
|
|
2656
|
+
/** 音が出力デバイスから実際に出るまでの遅延(秒) */
|
|
2657
|
+
get outputLatency() {
|
|
2658
|
+
return this._context.outputLatency || this._context.baseLatency || 0;
|
|
2659
|
+
}
|
|
2660
|
+
|
|
2661
|
+
/** AudioContextの状態(running / suspended / closed) */
|
|
2662
|
+
get contextState() {
|
|
2663
|
+
return this._context.state;
|
|
2664
|
+
}
|
|
2665
|
+
|
|
2579
2666
|
set currentTime(_currentTime) {
|
|
2580
2667
|
this._fadeinPosition = _currentTime;
|
|
2581
2668
|
}
|
|
@@ -2663,6 +2750,37 @@ const getSharedAudioContext = () => {
|
|
|
2663
2750
|
return g_sharedAudioContext;
|
|
2664
2751
|
};
|
|
2665
2752
|
|
|
2753
|
+
/**
|
|
2754
|
+
* AudioContextのウォームアップ
|
|
2755
|
+
* - 生成直後・resume直後のAudioContextは出力デバイスの起動待ちのため、
|
|
2756
|
+
* しばらく currentTime が進まない(環境により数十〜数百ms)
|
|
2757
|
+
* - この状態で音源をスケジュールすると、起動に要した時間がそのまま
|
|
2758
|
+
* 音源と譜面のずれになるため、無音を1回鳴らして時計が動き出すまで待つ
|
|
2759
|
+
* @returns {Promise<void>}
|
|
2760
|
+
*/
|
|
2761
|
+
const warmUpAudioContext = async () => {
|
|
2762
|
+
const ctx = getSharedAudioContext();
|
|
2763
|
+
if (ctx.state !== `running`) {
|
|
2764
|
+
await ctx.resume().catch(() => { });
|
|
2765
|
+
}
|
|
2766
|
+
if (ctx.state !== `running`) {
|
|
2767
|
+
return; // ジェスチャー未取得等でresumeできない場合は何もしない
|
|
2768
|
+
}
|
|
2769
|
+
|
|
2770
|
+
// 無音を1サンプルだけ鳴らして出力デバイスを起動させる
|
|
2771
|
+
const source = ctx.createBufferSource();
|
|
2772
|
+
source.buffer = ctx.createBuffer(1, 1, ctx.sampleRate);
|
|
2773
|
+
source.connect(ctx.destination);
|
|
2774
|
+
source.start();
|
|
2775
|
+
|
|
2776
|
+
// currentTimeが実際に進み始めるまで待機(最大500ms)
|
|
2777
|
+
const baseTime = ctx.currentTime;
|
|
2778
|
+
const limitTime = performance.now() + 500;
|
|
2779
|
+
while (ctx.currentTime === baseTime && performance.now() < limitTime) {
|
|
2780
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
2781
|
+
}
|
|
2782
|
+
};
|
|
2783
|
+
|
|
2666
2784
|
/**
|
|
2667
2785
|
* クリップボードコピー関数
|
|
2668
2786
|
* 入力値をクリップボードへコピーし、メッセージを表示
|
|
@@ -3507,8 +3625,8 @@ const createSplitCanvases = (_width, _totalHeight) => {
|
|
|
3507
3625
|
cvs.height = logicalH * g_dpr;
|
|
3508
3626
|
|
|
3509
3627
|
// ブラウザ上の表示サイズをセット
|
|
3510
|
-
cvs.style.width =
|
|
3511
|
-
cvs.style.height =
|
|
3628
|
+
cvs.style.width = wUnit(_width);
|
|
3629
|
+
cvs.style.height = wUnit(logicalH);
|
|
3512
3630
|
cvs.style.display = 'block';
|
|
3513
3631
|
|
|
3514
3632
|
const ctx = cvs.getContext('2d');
|
|
@@ -3568,8 +3686,8 @@ const createMinimapHeader = (_config, _keyCtrlPtn, _keyNum) => {
|
|
|
3568
3686
|
// 解像度と表示サイズの設定
|
|
3569
3687
|
canvas.width = logicalWidth * g_dpr;
|
|
3570
3688
|
canvas.height = headerHeight * g_dpr;
|
|
3571
|
-
canvas.style.width =
|
|
3572
|
-
canvas.style.height =
|
|
3689
|
+
canvas.style.width = wUnit(logicalWidth);
|
|
3690
|
+
canvas.style.height = wUnit(headerHeight);
|
|
3573
3691
|
canvas.style.display = 'block';
|
|
3574
3692
|
|
|
3575
3693
|
ctx.scale(g_dpr, g_dpr);
|
|
@@ -4419,8 +4537,8 @@ const headerConvert = _dosObj => {
|
|
|
4419
4537
|
obj.playingY = setIntVal(_dosObj.playingY, g_presetObj.playingY ?? 0);
|
|
4420
4538
|
|
|
4421
4539
|
// ステップゾーン位置
|
|
4422
|
-
g_posObj.stepY = (
|
|
4423
|
-
g_posObj.stepYR = (
|
|
4540
|
+
g_posObj.stepY = setVal(_dosObj.stepY, C_STEP_Y, C_TYP_FLOAT);
|
|
4541
|
+
g_posObj.stepYR = setVal(_dosObj.stepYR, C_STEP_YR, C_TYP_FLOAT);
|
|
4424
4542
|
g_posObj.stepDiffY = g_posObj.stepY - C_STEP_Y;
|
|
4425
4543
|
g_posObj.distY = obj.playingHeight - C_STEP_Y + g_posObj.stepYR;
|
|
4426
4544
|
g_posObj.reverseStepY = g_posObj.distY - g_posObj.stepY - g_posObj.stepDiffY - C_ARW_WIDTH;
|
|
@@ -4431,18 +4549,18 @@ const headerConvert = _dosObj => {
|
|
|
4431
4549
|
obj.baseSpeed = 1 + ((g_posObj.distY - (g_posObj.stepY - C_STEP_Y) * 2) / (500 - C_STEP_Y) - 1) * 0.85;
|
|
4432
4550
|
|
|
4433
4551
|
// 矢印・フリーズアロー判定位置補正
|
|
4434
|
-
g_diffObj.arrowJdgX = (
|
|
4435
|
-
g_diffObj.arrowJdgY = (
|
|
4436
|
-
g_diffObj.frzJdgX = (
|
|
4437
|
-
g_diffObj.frzJdgY = (
|
|
4552
|
+
g_diffObj.arrowJdgX = setVal(_dosObj.arrowJdgX, 0, C_TYP_FLOAT);
|
|
4553
|
+
g_diffObj.arrowJdgY = setVal(_dosObj.arrowJdgY, 0, C_TYP_FLOAT);
|
|
4554
|
+
g_diffObj.frzJdgX = setVal(_dosObj.frzJdgX, 0, C_TYP_FLOAT);
|
|
4555
|
+
g_diffObj.frzJdgY = setVal(_dosObj.frzJdgY, 0, C_TYP_FLOAT);
|
|
4438
4556
|
g_diffInitObj.arrowJdgX = g_diffObj.arrowJdgX;
|
|
4439
4557
|
g_diffInitObj.arrowJdgY = g_diffObj.arrowJdgY;
|
|
4440
4558
|
g_diffInitObj.frzJdgX = g_diffObj.frzJdgX;
|
|
4441
4559
|
g_diffInitObj.frzJdgY = g_diffObj.frzJdgY;
|
|
4442
4560
|
|
|
4443
4561
|
// ショートカット表示位置補正
|
|
4444
|
-
g_diffObj.shortcutX = (
|
|
4445
|
-
g_diffObj.shortcutY = (
|
|
4562
|
+
g_diffObj.shortcutX = setVal(_dosObj.shortcutX, 0, C_TYP_FLOAT);
|
|
4563
|
+
g_diffObj.shortcutY = setVal(_dosObj.shortcutY, 0, C_TYP_FLOAT);
|
|
4446
4564
|
g_diffInitObj.shortcutX = g_diffObj.shortcutX;
|
|
4447
4565
|
g_diffInitObj.shortcutY = g_diffObj.shortcutY;
|
|
4448
4566
|
|
|
@@ -6011,7 +6129,7 @@ const titleInit = (_initFlg = false) => {
|
|
|
6011
6129
|
}, g_lblPosObj.btnComment, g_cssObj.button_Default),
|
|
6012
6130
|
);
|
|
6013
6131
|
if (g_headerObj.musicSelectUse && getQueryParamVal(`scoreId`) === null) {
|
|
6014
|
-
lblComment.style.height =
|
|
6132
|
+
lblComment.style.height = wUnit(g_sHeight - 100);
|
|
6015
6133
|
}
|
|
6016
6134
|
setUserSelect(lblComment.style, `text`);
|
|
6017
6135
|
}
|
|
@@ -6555,7 +6673,7 @@ const changeMSelect = (_num, _initFlg = false) => {
|
|
|
6555
6673
|
g_lblPosObj.lblDifNameInfoM.w, { maxSiz: g_lblPosObj.lblDifNameInfoM.siz }));
|
|
6556
6674
|
lblDiffiInfoM.style.fontSize = lblDifNameInfoM.style.fontSize;
|
|
6557
6675
|
lblNotesInfoM.style.fontSize = lblDifNameInfoM.style.fontSize;
|
|
6558
|
-
lblCommentInfoM.style.top =
|
|
6676
|
+
lblCommentInfoM.style.top = wUnit(getStrHeight(lblDifNameInfoM.innerHTML, parseFloat(lblDifNameInfoM.style.fontSize)));
|
|
6559
6677
|
lblCommentInfoM.innerHTML = convertStrToVal(g_headerObj[`commentVal${g_settings.musicIdxNum}`]);
|
|
6560
6678
|
lblCommentM.scrollTop = 0;
|
|
6561
6679
|
|
|
@@ -8012,12 +8130,12 @@ const drawMinimap = (_scoreId, { _initFlg = false, _fadeinFlg = false } = {}) =>
|
|
|
8012
8130
|
|
|
8013
8131
|
// --- ヘッダー部分 ---
|
|
8014
8132
|
const detailMiniMapHeader = createEmptySprite(detailMiniMap, `detailMiniMapHeader`, g_windowObj.detailMiniMapHeader);
|
|
8015
|
-
$id(`detailMiniMapHeader`).top = (g_stateObj.miniMapRevFlg ? 230 + g_sHeight - 500 : 0)
|
|
8133
|
+
$id(`detailMiniMapHeader`).top = wUnit(g_stateObj.miniMapRevFlg ? 230 + g_sHeight - 500 : 0);
|
|
8016
8134
|
detailMiniMapHeader.appendChild(g_detailObj.scoreMinimapHeader[kPtn]);
|
|
8017
8135
|
|
|
8018
8136
|
// --- メイン(譜面)部分 ---
|
|
8019
8137
|
const detailMiniMapSub = createEmptySprite(detailMiniMap, `detailMiniMapSub`, g_windowObj.detailMiniMapSub);
|
|
8020
|
-
$id(`detailMiniMapSub`).top = (g_stateObj.miniMapRevFlg ? 0 : 15)
|
|
8138
|
+
$id(`detailMiniMapSub`).top = wUnit(g_stateObj.miniMapRevFlg ? 0 : 15);
|
|
8021
8139
|
|
|
8022
8140
|
Object.assign(detailMiniMapSub.style, {
|
|
8023
8141
|
overflowX: 'hidden',
|
|
@@ -9854,17 +9972,16 @@ const showToast = _msg => {
|
|
|
9854
9972
|
if (existing) existing.remove();
|
|
9855
9973
|
|
|
9856
9974
|
const toast = createDivCss2Label(`previewToast`, _msg, {
|
|
9857
|
-
x: g_btnX() + g_btnWidth() / 2, y: 50, w: g_btnWidth() / 2, h: 10,
|
|
9975
|
+
x: g_btnX() + g_btnWidth() / 2, y: 50, w: g_btnWidth() / 2, h: 10, siz: 12,
|
|
9858
9976
|
transform: `translateX(-50%)`,
|
|
9859
9977
|
background: `rgba(0,40,80,0.92)`,
|
|
9860
9978
|
color: `#aaddff`,
|
|
9861
9979
|
border: `1px solid #3366aa`,
|
|
9862
9980
|
borderRadius: `6px`,
|
|
9863
9981
|
padding: `6px 16px`,
|
|
9864
|
-
fontSize: `12px`,
|
|
9865
9982
|
fontFamily: `monospace`,
|
|
9866
9983
|
whiteSpace: `nowrap`,
|
|
9867
|
-
pointerEvents:
|
|
9984
|
+
pointerEvents: C_DIS_NONE,
|
|
9868
9985
|
transition: `opacity 0.4s`,
|
|
9869
9986
|
opacity: `1`,
|
|
9870
9987
|
});
|
|
@@ -10382,14 +10499,20 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
|
|
|
10382
10499
|
|
|
10383
10500
|
/**
|
|
10384
10501
|
* 指定関数群だけを抽出したtransform文字列を作成
|
|
10502
|
+
* @param {string} _cssString
|
|
10503
|
+
* @param {string[]} _funcNames
|
|
10504
|
+
* @returns {string}
|
|
10385
10505
|
*/
|
|
10386
|
-
const extractTransformFuncs = (
|
|
10387
|
-
const pattern = new RegExp(`\\b(${
|
|
10388
|
-
return (
|
|
10506
|
+
const extractTransformFuncs = (_cssString, _funcNames) => {
|
|
10507
|
+
const pattern = new RegExp(`\\b(${_funcNames.join(`|`)})\\([^)]*\\)`, `g`);
|
|
10508
|
+
return (_cssString.match(pattern) || []).join(` `);
|
|
10389
10509
|
};
|
|
10390
10510
|
|
|
10391
10511
|
/**
|
|
10392
10512
|
* 対象レーンのレイヤー番号を取得
|
|
10513
|
+
* @param {number} _j
|
|
10514
|
+
* @param {number} _posj
|
|
10515
|
+
* @returns {number}
|
|
10393
10516
|
*/
|
|
10394
10517
|
const getLayerIdx = (_j, _posj) => {
|
|
10395
10518
|
const baseLayer = g_keyObj[`layerGroup${keyCtrlPtn}`]?.[_j] || 0;
|
|
@@ -10399,6 +10522,8 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
|
|
|
10399
10522
|
|
|
10400
10523
|
/**
|
|
10401
10524
|
* 対象レイヤーの回転変形を取得
|
|
10525
|
+
* @param {string} _keyCtrlPtn
|
|
10526
|
+
* @returns {string[]}
|
|
10402
10527
|
*/
|
|
10403
10528
|
const getLayerRotateParts = _keyCtrlPtn => {
|
|
10404
10529
|
const raw = g_keyObj[`layerTrans${_keyCtrlPtn}`]?.[0] ?? [``, ``, ``, ``];
|
|
@@ -10414,7 +10539,7 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
|
|
|
10414
10539
|
|
|
10415
10540
|
g_keyCopyLists.simpleDef.forEach(header => updateKeyInfo(header, keyCtrlPtn));
|
|
10416
10541
|
addTransform(`keyconSprite`, `root`, `scale(${g_keyObj.scale})`, g_transPriority.scale);
|
|
10417
|
-
keyconSprite.style.height =
|
|
10542
|
+
keyconSprite.style.height = wUnit(parseFloat(keyconSprite.style.height) / ((1 + g_keyObj.scale) / 2));
|
|
10418
10543
|
const kWidth = parseInt(keyconSprite.style.width);
|
|
10419
10544
|
changeSetColor();
|
|
10420
10545
|
|
|
@@ -11228,10 +11353,10 @@ const keyConfigInit = (_kcType = g_kcType, _initFlg = false) => {
|
|
|
11228
11353
|
g_headerObj[`key${selectedKc}Def`] = setKey;
|
|
11229
11354
|
document.getElementById(`sc${selectedKc}`).textContent = getScMsg[selectedKc]();
|
|
11230
11355
|
document.getElementById(`sc${selectedKc}`).style.fontSize =
|
|
11231
|
-
|
|
11356
|
+
wUnit(getFontSize2(getScMsg[selectedKc](), g_btnWidth(5 / 12) - 40, { maxSiz: g_limitObj.mainSiz }));
|
|
11232
11357
|
if (g_isMac) {
|
|
11233
11358
|
scTitleBack.textContent = getScMsg.TitleBack();
|
|
11234
|
-
scTitleBack.style.fontSize =
|
|
11359
|
+
scTitleBack.style.fontSize = wUnit(getFontSize2(getScMsg.TitleBack(), g_btnWidth(5 / 12) - 40, { maxSiz: g_limitObj.mainSiz }));
|
|
11235
11360
|
}
|
|
11236
11361
|
changeConfigColor(document.getElementById(`sc${selectedKc}`),
|
|
11237
11362
|
g_headerObj[`key${selectedKc}`] === g_headerObj[`key${selectedKc}Def2`] ?
|
|
@@ -11321,6 +11446,7 @@ const completeTransKeyPtn = (_keyList) => {
|
|
|
11321
11446
|
});
|
|
11322
11447
|
};
|
|
11323
11448
|
|
|
11449
|
+
// KeyLockボタンを押したときの表示切替
|
|
11324
11450
|
const toggleKcDesc = () => {
|
|
11325
11451
|
if (document.getElementById(`kcDesc`) !== null) {
|
|
11326
11452
|
kcDesc.textContent = getKcDescMsg();
|
|
@@ -11331,11 +11457,13 @@ const toggleKcDesc = () => {
|
|
|
11331
11457
|
}
|
|
11332
11458
|
};
|
|
11333
11459
|
|
|
11460
|
+
// KeyLockボタンの表示文字列を取得
|
|
11334
11461
|
const getKcDescMsg = () =>
|
|
11335
11462
|
g_stateObj.keyLockFlg
|
|
11336
11463
|
? g_lblNameObj.kcNonDesc
|
|
11337
11464
|
: g_lblNameObj.kcDesc.split(`{0}`).join(g_kCd[C_KEY_RETRY]).split(`{1}:`).join(g_isMac ? `` : `Delete:`);
|
|
11338
11465
|
|
|
11466
|
+
// KeyLockボタンで使用する絵文字の取得
|
|
11339
11467
|
const getKeyLockName = () =>
|
|
11340
11468
|
`${g_lblNameObj.b_keyLock}${g_stateObj.keyLockFlg ? g_emojiObj.locked : g_emojiObj.unlocked}`;
|
|
11341
11469
|
|
|
@@ -11661,6 +11789,8 @@ const keyconfigKeyboardPreview = (() => {
|
|
|
11661
11789
|
|
|
11662
11790
|
/**
|
|
11663
11791
|
* Canvasの共通初期化処理
|
|
11792
|
+
* @param {HTMLCanvasElement} canvas
|
|
11793
|
+
* @returns {CanvasRenderingContext2D|null}
|
|
11664
11794
|
*/
|
|
11665
11795
|
const setupCanvasContext = (canvas) => {
|
|
11666
11796
|
if (!canvas) return null;
|
|
@@ -11675,6 +11805,15 @@ const keyconfigKeyboardPreview = (() => {
|
|
|
11675
11805
|
return ctx;
|
|
11676
11806
|
};
|
|
11677
11807
|
|
|
11808
|
+
/**
|
|
11809
|
+
* 円角矩形を描画する
|
|
11810
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
11811
|
+
* @param {number} x
|
|
11812
|
+
* @param {number} y
|
|
11813
|
+
* @param {number} w
|
|
11814
|
+
* @param {number} h
|
|
11815
|
+
* @param {number} r
|
|
11816
|
+
*/
|
|
11678
11817
|
const roundRect = (ctx, x, y, w, h, r) => {
|
|
11679
11818
|
ctx.beginPath();
|
|
11680
11819
|
ctx.moveTo(x + r, y);
|
|
@@ -12142,6 +12281,9 @@ const loadMusic = async () => {
|
|
|
12142
12281
|
}
|
|
12143
12282
|
|
|
12144
12283
|
if (loadSucceeded) {
|
|
12284
|
+
// 初回プレイ時に出力デバイスの起動待ちでずれるのを防ぐため、
|
|
12285
|
+
// メイン画面へ移行する前にAudioContextを起動させておく
|
|
12286
|
+
await warmUpAudioContext();
|
|
12145
12287
|
mainInit(); // 音源・譜面変換双方の完了後にまとめて呼ぶ
|
|
12146
12288
|
}
|
|
12147
12289
|
};
|
|
@@ -12617,7 +12759,7 @@ const applyShuffle = (_keyNum, _shuffleGroup, _style) => {
|
|
|
12617
12759
|
* @param {number[]} _group
|
|
12618
12760
|
* @param {number} _i
|
|
12619
12761
|
* @param {number} _divideNum
|
|
12620
|
-
* @returns
|
|
12762
|
+
* @returns {number[][]}
|
|
12621
12763
|
*/
|
|
12622
12764
|
const swapGroupNums = (_style, _group, _i, _divideNum) => {
|
|
12623
12765
|
if (_group.length % _divideNum === 0) {
|
|
@@ -12791,7 +12933,7 @@ const applySRandom = (_keyNum, _shuffleGroup, _arrowHeader, _frzHeader) => {
|
|
|
12791
12933
|
* @param {string} [_dummyNo] ダミー用譜面番号添え字
|
|
12792
12934
|
* @param {string} [_keyCtrlPtn] 選択キー及びパターン
|
|
12793
12935
|
* @param {boolean} [_scoreAnalyzeFlg=false] 譜面詳細データのために必要分で読込を中断
|
|
12794
|
-
* @returns
|
|
12936
|
+
* @returns {object} 矢印・フリーズアロー・速度/色変化データの格納オブジェクト
|
|
12795
12937
|
*/
|
|
12796
12938
|
const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
|
|
12797
12939
|
_keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`, _scoreAnalyzeFlg = false) => {
|
|
@@ -12934,7 +13076,7 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
|
|
|
12934
13076
|
* - 個別・全体色変化を一体で管理するため通常の配列で返却
|
|
12935
13077
|
* @param {string} _header
|
|
12936
13078
|
* @param {number} _scoreNo
|
|
12937
|
-
* @returns
|
|
13079
|
+
* @returns {any[][]}
|
|
12938
13080
|
*/
|
|
12939
13081
|
const setColor2Data = (_header, _scoreNo) => {
|
|
12940
13082
|
const dosColorData = getRefData(_header, `${_scoreNo}_data`);
|
|
@@ -13067,7 +13209,7 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
|
|
|
13067
13209
|
* 例) |backA2_data=back_data| -> back_dataで定義された値を使用
|
|
13068
13210
|
* @param {string} _header
|
|
13069
13211
|
* @param {string} _dataName
|
|
13070
|
-
* @returns
|
|
13212
|
+
* @returns {string|undefined}
|
|
13071
13213
|
*/
|
|
13072
13214
|
const getRefData = (_header, _dataName) => {
|
|
13073
13215
|
const data = _dosObj[`${_header}${_dataName}`];
|
|
@@ -13124,7 +13266,7 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
|
|
|
13124
13266
|
/**
|
|
13125
13267
|
* 歌詞データの分解
|
|
13126
13268
|
* @param {string} _scoreNo
|
|
13127
|
-
* @returns
|
|
13269
|
+
* @returns {string[][]}
|
|
13128
13270
|
*/
|
|
13129
13271
|
const makeWordData = _scoreNo => {
|
|
13130
13272
|
const wordDataList = [];
|
|
@@ -13225,7 +13367,7 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
|
|
|
13225
13367
|
* @param {string} _header
|
|
13226
13368
|
* @param {string} _scoreNo 譜面番号
|
|
13227
13369
|
* @param {string[]} [object.resultTypes] リザルトモーションの種類 (result, failedB, failedS)
|
|
13228
|
-
* @returns
|
|
13370
|
+
* @returns {any[][]}
|
|
13229
13371
|
*/
|
|
13230
13372
|
const makeBackgroundData = (_header, _scoreNo, { resultTypes = [] } = {}) => {
|
|
13231
13373
|
const dataList = [];
|
|
@@ -13365,6 +13507,7 @@ const calcLifeVals = _allArrows => {
|
|
|
13365
13507
|
* ライフ回復量・ダメージ量の算出
|
|
13366
13508
|
* @param {number} _val
|
|
13367
13509
|
* @param {number} _allArrows
|
|
13510
|
+
* @returns {number}
|
|
13368
13511
|
*/
|
|
13369
13512
|
const calcLifeVal = (_val, _allArrows) => _val * g_headerObj.maxLifeVal / _allArrows;
|
|
13370
13513
|
|
|
@@ -13484,6 +13627,7 @@ const setSpeedOnFrame = (_speedData, _lastFrame) => {
|
|
|
13484
13627
|
/**
|
|
13485
13628
|
* Motionオプション適用時の矢印別の速度設定
|
|
13486
13629
|
* - 矢印が表示される最大フレーム数を 101フレーム と定義。
|
|
13630
|
+
* @returns {number[]}
|
|
13487
13631
|
*/
|
|
13488
13632
|
const setMotionOnFrame = () => g_motionFunc.get(g_stateObj.motion)(fillArray(101));
|
|
13489
13633
|
|
|
@@ -13828,7 +13972,7 @@ const pushArrows = (_dataObj, _speedOnFrame, _firstArrivalFrame) => {
|
|
|
13828
13972
|
* 歌詞表示、背景・マスク表示のフェードイン時調整処理
|
|
13829
13973
|
* @param {string} _type
|
|
13830
13974
|
* @param {object} _data
|
|
13831
|
-
* @returns
|
|
13975
|
+
* @returns {object}
|
|
13832
13976
|
*/
|
|
13833
13977
|
const calcAnimationData = (_type, _data) => {
|
|
13834
13978
|
|
|
@@ -14761,15 +14905,15 @@ const mainInit = () => {
|
|
|
14761
14905
|
}
|
|
14762
14906
|
|
|
14763
14907
|
addTransform(`mainSprite`, `root`, `scale(${g_workObj.scale})`, g_transPriority.scale);
|
|
14764
|
-
addTransform(`mainSprite`, `main`, `translateX(${g_workObj.playingX}
|
|
14908
|
+
addTransform(`mainSprite`, `main`, `translateX(${wUnit(g_workObj.playingX)}) translateY(${wUnit(g_posObj.stepY - C_STEP_Y + g_headerObj.playingY)})`, g_transPriority.base);
|
|
14765
14909
|
|
|
14766
14910
|
// 曲情報・判定カウント用スプライトを作成(メインスプライトより上位)
|
|
14767
14911
|
const infoSprite = createEmptySprite(divRoot, `infoSprite`, mainCommonPos);
|
|
14768
|
-
addTransform(`infoSprite`, `main`, `translateX(${g_workObj.playingX}
|
|
14912
|
+
addTransform(`infoSprite`, `main`, `translateX(${wUnit(g_workObj.playingX)}) translateY(${wUnit(g_headerObj.playingY)})`, g_transPriority.base);
|
|
14769
14913
|
|
|
14770
14914
|
// 判定系スプライトを作成(メインスプライトより上位)
|
|
14771
14915
|
const judgeSprite = createEmptySprite(divRoot, `judgeSprite`, mainCommonPos);
|
|
14772
|
-
addTransform(`judgeSprite`, `main`, `translateX(${g_workObj.playingX}
|
|
14916
|
+
addTransform(`judgeSprite`, `main`, `translateX(${wUnit(g_workObj.playingX)}) translateY(${wUnit(g_headerObj.playingY)})`, g_transPriority.base);
|
|
14773
14917
|
const tkObj = getKeyInfo();
|
|
14774
14918
|
const [keyCtrlPtn, keyNum] = [tkObj.keyCtrlPtn, tkObj.keyNum];
|
|
14775
14919
|
|
|
@@ -14896,6 +15040,7 @@ const mainInit = () => {
|
|
|
14896
15040
|
let thisTime;
|
|
14897
15041
|
let buffTime;
|
|
14898
15042
|
let musicStartTime;
|
|
15043
|
+
let musicStartCtxTime;
|
|
14899
15044
|
let musicStartFlg = false;
|
|
14900
15045
|
|
|
14901
15046
|
g_inputKeyBuffer = {};
|
|
@@ -15634,7 +15779,7 @@ const mainInit = () => {
|
|
|
15634
15779
|
const setArrowYCondition = `${String(g_attrObj[arrowName].movLockFlg)}_${String(initManualFlg)}`;
|
|
15635
15780
|
setArrowY.get(setArrowYCondition)(arrowName, firstPosY, stepY);
|
|
15636
15781
|
if (!initManualFlg) {
|
|
15637
|
-
addTransform(arrowName, `rootX`, `translateX(${g_workObj.stepX[_j]}
|
|
15782
|
+
addTransform(arrowName, `rootX`, `translateX(${wUnit(g_workObj.stepX[_j])})`);
|
|
15638
15783
|
}
|
|
15639
15784
|
|
|
15640
15785
|
/**
|
|
@@ -15824,7 +15969,7 @@ const mainInit = () => {
|
|
|
15824
15969
|
const setArrowYCondition = `${String(g_attrObj[frzName].movLockFlg)}_${String(initManualFlg)}`;
|
|
15825
15970
|
setArrowY.get(setArrowYCondition)(frzName, firstPosY, stepY);
|
|
15826
15971
|
if (!initManualFlg) {
|
|
15827
|
-
addTransform(frzName, `rootX`, `translateX(${g_workObj.stepX[_j]}
|
|
15972
|
+
addTransform(frzName, `rootX`, `translateX(${wUnit(g_workObj.stepX[_j])})`);
|
|
15828
15973
|
}
|
|
15829
15974
|
|
|
15830
15975
|
safeExecuteCustomHooks(`g_customJsObj.makeFrzArrow`, g_customJsObj.makeFrzArrow, _attrs, frzName, _name, _arrowCnt);
|
|
@@ -16129,14 +16274,32 @@ const mainInit = () => {
|
|
|
16129
16274
|
}
|
|
16130
16275
|
|
|
16131
16276
|
// 60fpsから遅延するため、その差分を取って次回のタイミングで遅れをリカバリする
|
|
16277
|
+
// - WebAudioAPI使用時は音源クロック(AudioContext.currentTime)を基準とする
|
|
16278
|
+
// performance.now()とAudioContextの時計は独立して進むため、後者を基準にしないと
|
|
16279
|
+
// 再生開始時のオフセットずれやsuspend/resumeによるずれを吸収できない
|
|
16132
16280
|
thisTime = performance.now();
|
|
16133
16281
|
buffTime = 0;
|
|
16134
|
-
|
|
16282
|
+
let holdFrame = false;
|
|
16283
|
+
|
|
16284
|
+
if (g_audio instanceof AudioPlayer && g_audioClockSync && musicStartCtxTime !== undefined) {
|
|
16285
|
+
if (g_audio.contextState === `running`) {
|
|
16286
|
+
buffTime = (g_audio.contextTime - musicStartCtxTime) * 1000
|
|
16287
|
+
- (currentFrame - musicStartFrame) * 1000 / g_fps;
|
|
16288
|
+
} else {
|
|
16289
|
+
// AudioContext停止中は音源も止まっているため、フレーム進行も止めて復帰を待つ
|
|
16290
|
+
getSharedAudioContext(); // suspended時はresumeを試行
|
|
16291
|
+
holdFrame = true;
|
|
16292
|
+
}
|
|
16293
|
+
} else if (g_audio instanceof AudioPlayer || currentFrame >= musicStartFrame) {
|
|
16135
16294
|
buffTime = (thisTime - musicStartTime - (currentFrame - musicStartFrame) * 1000 / g_fps);
|
|
16136
16295
|
}
|
|
16137
|
-
|
|
16138
|
-
|
|
16139
|
-
|
|
16296
|
+
|
|
16297
|
+
if (!holdFrame) {
|
|
16298
|
+
g_scoreObj.frameNum++;
|
|
16299
|
+
g_scoreObj.baseFrame++;
|
|
16300
|
+
}
|
|
16301
|
+
g_timeoutEvtId = setTimeout(flowTimeline, holdFrame ? g_maxFrameWait :
|
|
16302
|
+
Math.min(Math.max(1000 / g_fps - buffTime, 0), g_maxFrameWait));
|
|
16140
16303
|
}
|
|
16141
16304
|
};
|
|
16142
16305
|
safeExecuteCustomHooks(`g_skinJsObj.main`, g_skinJsObj.main);
|
|
@@ -16149,6 +16312,11 @@ const mainInit = () => {
|
|
|
16149
16312
|
const musicStartAdjustment = (g_headerObj.blankFrame - g_stateObj.decimalAdjustment + 1) / g_fps;
|
|
16150
16313
|
musicStartTime = performance.now() + (musicStartAdjustment + g_scheduleLead) * 1000;
|
|
16151
16314
|
g_audio.play(musicStartAdjustment);
|
|
16315
|
+
|
|
16316
|
+
// 音源クロック基準の開始時刻(フレーム進行の基準)
|
|
16317
|
+
// - g_audioLatencyCompensationが有効な場合は出力遅延分だけ表示を後ろへずらす
|
|
16318
|
+
musicStartCtxTime = g_audio.scheduledTime
|
|
16319
|
+
+ (g_audioLatencyCompensation ? g_audio.outputLatency : 0);
|
|
16152
16320
|
}
|
|
16153
16321
|
|
|
16154
16322
|
g_timeoutEvtId = setTimeout(flowTimeline, 1000 / g_fps);
|
|
@@ -16340,20 +16508,20 @@ const changeAppearanceFilter = (_num = 10) => {
|
|
|
16340
16508
|
$id(`arrowSprite${topNum + j}`).clipPath = topShape;
|
|
16341
16509
|
$id(`arrowSprite${bottomNum + j}`).clipPath = bottomShape;
|
|
16342
16510
|
|
|
16343
|
-
addTransform(`filterBar${topNum + j}`, `appearance`, `translateY(${parseFloat($id(`arrowSprite${j}`).top) + topDist}
|
|
16344
|
-
addTransform(`filterBar${bottomNum + j}`, `appearance`, `translateY(${parseFloat($id(`arrowSprite${j + 1}`).top) + bottomDist}
|
|
16511
|
+
addTransform(`filterBar${topNum + j}`, `appearance`, `translateY(${wUnit(parseFloat($id(`arrowSprite${j}`).top) + topDist)})`, g_transPriority.layer);
|
|
16512
|
+
addTransform(`filterBar${bottomNum + j}`, `appearance`, `translateY(${wUnit(parseFloat($id(`arrowSprite${j + 1}`).top) + bottomDist)})`, g_transPriority.layer);
|
|
16345
16513
|
|
|
16346
16514
|
if (doubleFilterFlg) {
|
|
16347
|
-
addTransform(`filterBar${bottomNum + j}_HS`, `appearance`, `translateY(${parseFloat($id(`arrowSprite${j}`).top) + bottomDist}
|
|
16348
|
-
addTransform(`filterBar${topNum + j}_HS`, `appearance`, `translateY(${parseFloat($id(`arrowSprite${j + 1}`).top) + topDist}
|
|
16515
|
+
addTransform(`filterBar${bottomNum + j}_HS`, `appearance`, `translateY(${wUnit(parseFloat($id(`arrowSprite${j}`).top) + bottomDist)})`, g_transPriority.layer);
|
|
16516
|
+
addTransform(`filterBar${topNum + j}_HS`, `appearance`, `translateY(${wUnit(parseFloat($id(`arrowSprite${j + 1}`).top) + topDist)})`, g_transPriority.layer);
|
|
16349
16517
|
}
|
|
16350
16518
|
}
|
|
16351
16519
|
|
|
16352
16520
|
// フィルターバーのパーセント表示(フィルターバーが複数表示されるなど複雑なため、最初の階層グループの位置に追従)
|
|
16353
16521
|
if (g_appearanceRanges.includes(g_stateObj.appearance)) {
|
|
16354
16522
|
const currentBarNum = g_hidSudObj.std[g_stateObj.appearance][g_stateObj.reverse];
|
|
16355
|
-
addTransform(`filterView`, `appearance`, `translateY(${parseFloat($id(`arrowSprite${currentBarNum % 2}`).top) +
|
|
16356
|
-
(currentBarNum % 2 === 0 ? bottomDist : topDist)}
|
|
16523
|
+
addTransform(`filterView`, `appearance`, `translateY(${wUnit(parseFloat($id(`arrowSprite${currentBarNum % 2}`).top) +
|
|
16524
|
+
(currentBarNum % 2 === 0 ? bottomDist : topDist))})`, g_transPriority.layer);
|
|
16357
16525
|
filterView.textContent = `${_num}%`;
|
|
16358
16526
|
g_hidSudObj.filterPos = _num;
|
|
16359
16527
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Source by tickle
|
|
7
7
|
* Created : 2019/11/19
|
|
8
|
-
* Revised : 2026/08/
|
|
8
|
+
* Revised : 2026/08/16 (v49.6.0)
|
|
9
9
|
*
|
|
10
10
|
* https://github.com/cwtickle/danoniplus
|
|
11
11
|
*/
|
|
@@ -163,8 +163,8 @@ const C_TYP_CALC = `calc`;
|
|
|
163
163
|
let [g_sWidth, g_sHeight] = [
|
|
164
164
|
setVal($id(`canvas-frame`).width, 500, C_TYP_FLOAT), setVal($id(`canvas-frame`).height, 500, C_TYP_FLOAT)
|
|
165
165
|
];
|
|
166
|
-
$id(`canvas-frame`).width =
|
|
167
|
-
$id(`canvas-frame`).height =
|
|
166
|
+
$id(`canvas-frame`).width = wUnit(Math.max(g_sWidth, 500));
|
|
167
|
+
$id(`canvas-frame`).height = wUnit(Math.max(g_sHeight, 500));
|
|
168
168
|
$id(`canvas-frame`).margin = C_DIS_AUTO;
|
|
169
169
|
|
|
170
170
|
const g_btnWidth = (_multi = 1) => Math.min(g_sWidth, g_limitObj.btnBaseWidth) * _multi;
|
|
@@ -1615,7 +1615,7 @@ const addX = (_id, _typeId, _x = 0, { overwrite = false, priority = 1000 } = {})
|
|
|
1615
1615
|
}
|
|
1616
1616
|
if (g_posXs[_id].get(_typeId) !== _x) {
|
|
1617
1617
|
g_posXs[_id].set(_typeId, _x);
|
|
1618
|
-
addTransform(_id, `posX`, `translateX(${sumData(Array.from(g_posXs[_id].values()))}
|
|
1618
|
+
addTransform(_id, `posX`, `translateX(${wUnit(sumData(Array.from(g_posXs[_id].values())))})`, priority);
|
|
1619
1619
|
}
|
|
1620
1620
|
};
|
|
1621
1621
|
|
|
@@ -1636,7 +1636,7 @@ const addY = (_id, _typeId, _y = 0, { overwrite = false, priority = 1000 } = {})
|
|
|
1636
1636
|
}
|
|
1637
1637
|
if (g_posYs[_id].get(_typeId) !== _y) {
|
|
1638
1638
|
g_posYs[_id].set(_typeId, _y);
|
|
1639
|
-
addTransform(_id, `posY`, `translateY(${sumData(Array.from(g_posYs[_id].values()))}
|
|
1639
|
+
addTransform(_id, `posY`, `translateY(${wUnit(sumData(Array.from(g_posYs[_id].values())))})`, priority);
|
|
1640
1640
|
}
|
|
1641
1641
|
};
|
|
1642
1642
|
|
|
@@ -1653,7 +1653,7 @@ const delX = (_id, _typeId) => {
|
|
|
1653
1653
|
return;
|
|
1654
1654
|
}
|
|
1655
1655
|
const priority = g_transforms[_id]?.get(`posX`)?.priority ?? 1000;
|
|
1656
|
-
addTransform(_id, `posX`, `translateX(${sumData(Array.from(g_posXs[_id].values()))}
|
|
1656
|
+
addTransform(_id, `posX`, `translateX(${wUnit(sumData(Array.from(g_posXs[_id].values())))})`, priority);
|
|
1657
1657
|
};
|
|
1658
1658
|
|
|
1659
1659
|
/**
|
|
@@ -1669,7 +1669,7 @@ const delY = (_id, _typeId) => {
|
|
|
1669
1669
|
return;
|
|
1670
1670
|
}
|
|
1671
1671
|
const priority = g_transforms[_id]?.get(`posY`)?.priority ?? 1000;
|
|
1672
|
-
addTransform(_id, `posY`, `translateY(${sumData(Array.from(g_posYs[_id].values()))}
|
|
1672
|
+
addTransform(_id, `posY`, `translateY(${wUnit(sumData(Array.from(g_posYs[_id].values())))})`, priority);
|
|
1673
1673
|
};
|
|
1674
1674
|
|
|
1675
1675
|
/**
|
|
@@ -1866,7 +1866,7 @@ const g_stepAreaFunc = new Map([
|
|
|
1866
1866
|
['Halfway', () => {
|
|
1867
1867
|
g_arrowGroupSprite.forEach(sprite => {
|
|
1868
1868
|
for (let j = 0; j < g_stateObj.layerNum; j++) {
|
|
1869
|
-
addTransform(`${sprite}${j}`, `stepArea`, `translateY(${halfwayOffset(j)}
|
|
1869
|
+
addTransform(`${sprite}${j}`, `stepArea`, `translateY(${wUnit(halfwayOffset(j))})`, g_transPriority.stepArea);
|
|
1870
1870
|
}
|
|
1871
1871
|
});
|
|
1872
1872
|
|
|
@@ -1877,7 +1877,7 @@ const g_stepAreaFunc = new Map([
|
|
|
1877
1877
|
for (let j = 0; j < g_stateObj.layerNumDf; j++) {
|
|
1878
1878
|
addTransform(
|
|
1879
1879
|
`filterBar${j}`, `stepArea`,
|
|
1880
|
-
`translateY(calc(${g_hidSudObj[g_stateObj.appearance] === 0 ? 1 : -1} * ${halfwayOffset(j)}
|
|
1880
|
+
`translateY(calc(${g_hidSudObj[g_stateObj.appearance] === 0 ? 1 : -1} * ${wUnit(halfwayOffset(j))}))`,
|
|
1881
1881
|
g_transPriority.stepArea
|
|
1882
1882
|
);
|
|
1883
1883
|
}
|
|
@@ -1888,12 +1888,12 @@ const g_stepAreaFunc = new Map([
|
|
|
1888
1888
|
for (let j = 0; j < g_stateObj.layerNumDf; j++) {
|
|
1889
1889
|
addTransform(
|
|
1890
1890
|
`filterBar${j}_HS`, `stepArea`,
|
|
1891
|
-
`translateY(calc(${(-1) * (g_hidSudObj[g_stateObj.appearance] === 0 ? 1 : -1)} * ${halfwayOffset(j)}
|
|
1891
|
+
`translateY(calc(${(-1) * (g_hidSudObj[g_stateObj.appearance] === 0 ? 1 : -1)} * ${wUnit(halfwayOffset(j))}))`,
|
|
1892
1892
|
g_transPriority.stepArea
|
|
1893
1893
|
);
|
|
1894
1894
|
}
|
|
1895
1895
|
}
|
|
1896
|
-
addTransform(`filterView`, `stepArea`, `translateY(${halfwayOffset(Number(g_settings.reverseNum))}
|
|
1896
|
+
addTransform(`filterView`, `stepArea`, `translateY(${wUnit(halfwayOffset(Number(g_settings.reverseNum)))})`, g_transPriority.stepArea);
|
|
1897
1897
|
}
|
|
1898
1898
|
}],
|
|
1899
1899
|
['Mismatched', () => {
|
|
@@ -1903,7 +1903,7 @@ const g_stepAreaFunc = new Map([
|
|
|
1903
1903
|
if (g_workObj.orgFlatFlg) {
|
|
1904
1904
|
g_arrowGroupSprite.forEach(sprite => {
|
|
1905
1905
|
for (let j = g_stateObj.layerNumDf; j < g_stateObj.layerNum; j++) {
|
|
1906
|
-
addTransform(`${sprite}${j}`, `stepArea`, `translateY(${halfwayOffset(j)}
|
|
1906
|
+
addTransform(`${sprite}${j}`, `stepArea`, `translateY(${wUnit(halfwayOffset(j))})`, g_transPriority.stepArea);
|
|
1907
1907
|
}
|
|
1908
1908
|
});
|
|
1909
1909
|
|
|
@@ -1914,14 +1914,14 @@ const g_stepAreaFunc = new Map([
|
|
|
1914
1914
|
// Hidden+用のフィルターバー補正
|
|
1915
1915
|
addTransform(
|
|
1916
1916
|
`filterBar${j + Number(g_settings.reverseNum)}_HS`, `stepArea`,
|
|
1917
|
-
`translateY(calc((${getDirFromRev()}) * ${halfwayOffset(j)}
|
|
1917
|
+
`translateY(calc((${getDirFromRev()}) * ${wUnit(halfwayOffset(j))}))`,
|
|
1918
1918
|
g_transPriority.stepArea
|
|
1919
1919
|
);
|
|
1920
1920
|
} else {
|
|
1921
1921
|
// Sudden+用のフィルターバー補正
|
|
1922
1922
|
addTransform(
|
|
1923
1923
|
`filterBar${j - Number(g_settings.reverseNum)}`, `stepArea`,
|
|
1924
|
-
`translateY(calc((${(-1) * getDirFromRev()}) * ${halfwayOffset(j)}
|
|
1924
|
+
`translateY(calc((${(-1) * getDirFromRev()}) * ${wUnit(halfwayOffset(j))}))`,
|
|
1925
1925
|
g_transPriority.stepArea
|
|
1926
1926
|
);
|
|
1927
1927
|
}
|
|
@@ -1936,7 +1936,7 @@ const g_stepAreaFunc = new Map([
|
|
|
1936
1936
|
if (g_workObj.orgFlatFlg) {
|
|
1937
1937
|
g_arrowGroupSprite.forEach(sprite => {
|
|
1938
1938
|
for (let j = 0; j < g_stateObj.layerNumDf; j++) {
|
|
1939
|
-
addTransform(`${sprite}${j}`, `stepArea`, `translateY(${halfwayOffset(j)}
|
|
1939
|
+
addTransform(`${sprite}${j}`, `stepArea`, `translateY(${wUnit(halfwayOffset(j))})`, g_transPriority.stepArea);
|
|
1940
1940
|
}
|
|
1941
1941
|
});
|
|
1942
1942
|
|
|
@@ -1947,14 +1947,14 @@ const g_stepAreaFunc = new Map([
|
|
|
1947
1947
|
// Hidden+用のフィルターバー補正
|
|
1948
1948
|
addTransform(
|
|
1949
1949
|
`filterBar${j + Number(g_settings.reverseNum)}`, `stepArea`,
|
|
1950
|
-
`translateY(calc((${getDirFromRev()}) * ${halfwayOffset(j)}
|
|
1950
|
+
`translateY(calc((${getDirFromRev()}) * ${wUnit(halfwayOffset(j))}))`,
|
|
1951
1951
|
g_transPriority.stepArea
|
|
1952
1952
|
);
|
|
1953
1953
|
} else {
|
|
1954
1954
|
// Sudden+用のフィルターバー補正
|
|
1955
1955
|
addTransform(
|
|
1956
1956
|
`filterBar${j - Number(g_settings.reverseNum)}_HS`, `stepArea`,
|
|
1957
|
-
`translateY(calc((${(-1) * getDirFromRev()}) * ${halfwayOffset(j)}
|
|
1957
|
+
`translateY(calc((${(-1) * getDirFromRev()}) * ${wUnit(halfwayOffset(j))}))`,
|
|
1958
1958
|
g_transPriority.stepArea
|
|
1959
1959
|
);
|
|
1960
1960
|
}
|
|
@@ -1974,7 +1974,7 @@ const g_stepAreaFunc = new Map([
|
|
|
1974
1974
|
for (let j = 0; j < g_stateObj.layerNumDf; j++) {
|
|
1975
1975
|
addTransform(
|
|
1976
1976
|
`filterBar${j}_HS`, `stepArea`,
|
|
1977
|
-
`translateY(calc((${g_hidSudObj[g_stateObj.appearance] === 0 ? 1 : -1}) * ${halfwayOffset(j)}
|
|
1977
|
+
`translateY(calc((${g_hidSudObj[g_stateObj.appearance] === 0 ? 1 : -1}) * ${wUnit(halfwayOffset(j))}))`,
|
|
1978
1978
|
g_transPriority.stepArea
|
|
1979
1979
|
);
|
|
1980
1980
|
}
|
|
@@ -1983,7 +1983,7 @@ const g_stepAreaFunc = new Map([
|
|
|
1983
1983
|
for (let j = 0; j < g_stateObj.layerNumDf; j += 2) {
|
|
1984
1984
|
addTransform(
|
|
1985
1985
|
`filterBar${j + Number(g_settings.reverseNum)}_HS`, `stepArea`,
|
|
1986
|
-
`translateY(calc((${getDirFromRev()}) * ${halfwayOffset(j)}
|
|
1986
|
+
`translateY(calc((${getDirFromRev()}) * ${wUnit(halfwayOffset(j))}))`,
|
|
1987
1987
|
g_transPriority.stepArea
|
|
1988
1988
|
);
|
|
1989
1989
|
}
|
|
@@ -1998,7 +1998,7 @@ const g_stepAreaFunc = new Map([
|
|
|
1998
1998
|
['Alt-Crossing', () => {
|
|
1999
1999
|
for (let j = 0; j < g_stateObj.layerNum; j++) {
|
|
2000
2000
|
addTransform(`mainSprite${j}`, `stepArea`, `rotate(${getDirFromLayer(j) * -10}deg) ` +
|
|
2001
|
-
`translateX(${getDirFromLayer(j) * 20}
|
|
2001
|
+
`translateX(${wUnit(getDirFromLayer(j) * 20)})`, g_transPriority.stepArea);
|
|
2002
2002
|
}
|
|
2003
2003
|
}],
|
|
2004
2004
|
]);
|
|
@@ -2012,34 +2012,34 @@ const getShakingDist = () => (Math.abs((g_scoreObj.baseFrame / 2) % 100 - 50) -
|
|
|
2012
2012
|
const g_shakingFunc = new Map([
|
|
2013
2013
|
['OFF', () => true],
|
|
2014
2014
|
['Horizontal', (_multi = 1) => {
|
|
2015
|
-
addTransform(`mainSprite`, `shakingX_base`, `translateX(${getShakingDist() * _multi}
|
|
2015
|
+
addTransform(`mainSprite`, `shakingX_base`, `translateX(${wUnit(getShakingDist() * _multi)})`, g_transPriority.shakingX)
|
|
2016
2016
|
}],
|
|
2017
2017
|
['Vertical', (_multi = 1) => {
|
|
2018
|
-
addTransform(`mainSprite`, `shakingY_base`, `translateY(${getShakingDist() / 2 * _multi}
|
|
2018
|
+
addTransform(`mainSprite`, `shakingY_base`, `translateY(${wUnit(getShakingDist() / 2 * _multi)})`, g_transPriority.shakingY)
|
|
2019
2019
|
}],
|
|
2020
2020
|
['X-Horizontal', (_multi = 1) => {
|
|
2021
2021
|
for (let j = 0; j < g_stateObj.layerNum; j++) {
|
|
2022
|
-
addTransform(`mainSprite${j}`, `shakingX_layer`, `translateX(${getDirFromLayer(j) * (4 / 3) * getShakingDist() * _multi}
|
|
2022
|
+
addTransform(`mainSprite${j}`, `shakingX_layer`, `translateX(${wUnit(getDirFromLayer(j) * (4 / 3) * getShakingDist() * _multi)})`, g_transPriority.shakingX);
|
|
2023
2023
|
}
|
|
2024
2024
|
}],
|
|
2025
2025
|
['X-Vertical', (_multi = 1) => {
|
|
2026
2026
|
for (let j = 0; j < g_stateObj.layerNum; j++) {
|
|
2027
|
-
addTransform(`mainSprite${j}`, `shakingY_layer`, `translateY(${getDirFromLayer(j) * getShakingDist() * _multi}
|
|
2027
|
+
addTransform(`mainSprite${j}`, `shakingY_layer`, `translateY(${wUnit(getDirFromLayer(j) * getShakingDist() * _multi)})`, g_transPriority.shakingY);
|
|
2028
2028
|
}
|
|
2029
2029
|
}],
|
|
2030
2030
|
['Drunk', (_multi = 1) => {
|
|
2031
2031
|
const dist = getShakingDist();
|
|
2032
2032
|
if (g_workObj.drunkXFlg) {
|
|
2033
2033
|
const deltaX = dist * _multi;
|
|
2034
|
-
addTransform(`mainSprite`, `shakingX_drunk`, `translateX(${deltaX}
|
|
2035
|
-
addTransform(`infoSprite`, `shakingX_drunk`, `translateX(${deltaX}
|
|
2036
|
-
addTransform(`judgeSprite`, `shakingX_drunk`, `translateX(${deltaX}
|
|
2034
|
+
addTransform(`mainSprite`, `shakingX_drunk`, `translateX(${wUnit(deltaX)})`, g_transPriority.shakingX);
|
|
2035
|
+
addTransform(`infoSprite`, `shakingX_drunk`, `translateX(${wUnit(deltaX)})`, g_transPriority.shakingX);
|
|
2036
|
+
addTransform(`judgeSprite`, `shakingX_drunk`, `translateX(${wUnit(deltaX)})`, g_transPriority.shakingX);
|
|
2037
2037
|
}
|
|
2038
2038
|
if (g_workObj.drunkYFlg) {
|
|
2039
2039
|
const deltaY = dist / 2 * _multi;
|
|
2040
|
-
addTransform(`mainSprite`, `shakingY_drunk`, `translateY(${deltaY}
|
|
2041
|
-
addTransform(`infoSprite`, `shakingY_drunk`, `translateY(${deltaY}
|
|
2042
|
-
addTransform(`judgeSprite`, `shakingY_drunk`, `translateY(${deltaY}
|
|
2040
|
+
addTransform(`mainSprite`, `shakingY_drunk`, `translateY(${wUnit(deltaY)})`, g_transPriority.shakingY);
|
|
2041
|
+
addTransform(`infoSprite`, `shakingY_drunk`, `translateY(${wUnit(deltaY)})`, g_transPriority.shakingY);
|
|
2042
|
+
addTransform(`judgeSprite`, `shakingY_drunk`, `translateY(${wUnit(deltaY)})`, g_transPriority.shakingY);
|
|
2043
2043
|
}
|
|
2044
2044
|
// 補正がゼロになったときに軸の移動方法をランダムで決定
|
|
2045
2045
|
if (dist === 0) {
|
|
@@ -2298,7 +2298,7 @@ let g_canDisabledSettings = [`speed`, `motion`, `scroll`, `reverse`, `shuffle`,
|
|
|
2298
2298
|
|
|
2299
2299
|
const g_hidSudFunc = new Map([
|
|
2300
2300
|
['filterPos', _filterPos => `${_filterPos}${g_lblNameObj.percent}`],
|
|
2301
|
-
['range', () =>
|
|
2301
|
+
['range', () => wUnit(Math.round(g_posObj.arrowHeight - g_posObj.stepY))],
|
|
2302
2302
|
['hidden', _filterPos => `${Math.min(Math.round(g_posObj.arrowHeight * (100 - _filterPos) / 100), g_posObj.arrowHeight - g_posObj.stepY)}`],
|
|
2303
2303
|
['sudden', _filterPos => `${Math.max(Math.round(g_posObj.arrowHeight * (100 - _filterPos) / 100) - g_posObj.stepY, 0)}`],
|
|
2304
2304
|
]);
|