nonebot-plugin-osubot 6.23.1__py3-none-any.whl → 6.24.1__py3-none-any.whl
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.
Potentially problematic release.
This version of nonebot-plugin-osubot might be problematic. Click here for more details.
- nonebot_plugin_osubot/api.py +7 -5
- nonebot_plugin_osubot/draw/bmap.py +19 -21
- nonebot_plugin_osubot/draw/bp.py +1 -1
- nonebot_plugin_osubot/draw/echarts.py +8 -2
- nonebot_plugin_osubot/draw/info.py +2 -0
- nonebot_plugin_osubot/draw/map.py +5 -2
- nonebot_plugin_osubot/draw/osu_preview.py +64 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/css/style.css +258 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/README.md +109 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js +3 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js.map +1 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js +3 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js.map +1 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/index.html +437 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/beatmap.js +211 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/hitobject.js +29 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/point.js +55 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/scroll.js +45 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/timingpoint.js +35 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/LegacyRandom.js +81 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/PalpableCatchHitObject.js +53 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/bananashower.js +33 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/catch.js +211 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/fruit.js +21 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/juicestream.js +176 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/hitnote.js +21 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/holdnote.js +37 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/mania.js +164 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/preview.js +61 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/bezier2.js +33 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/catmullcurve.js +34 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/centripetalcatmullrom.js +30 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/circumstancedcircle.js +47 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curve.js +25 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curvetype.js +17 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/equaldistancemulticurve.js +70 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/linearbezier.js +40 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/hitcircle.js +85 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/slider.js +120 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/spinner.js +56 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/standard.js +170 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/donkat.js +40 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/drumroll.js +34 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/shaker.js +58 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/taiko.js +120 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/util.js +61 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/pic.html +115 -0
- nonebot_plugin_osubot/draw/score.py +4 -4
- nonebot_plugin_osubot/file.py +1 -12
- nonebot_plugin_osubot/mania/__init__.py +9 -10
- nonebot_plugin_osubot/matcher/bp_analyze.py +9 -9
- nonebot_plugin_osubot/matcher/guess.py +3 -3
- nonebot_plugin_osubot/matcher/map_convert.py +12 -7
- nonebot_plugin_osubot/matcher/preview.py +10 -3
- nonebot_plugin_osubot/matcher/recommend.py +7 -12
- nonebot_plugin_osubot/osufile/mods/AP.png +0 -0
- nonebot_plugin_osubot/osufile/mods/CL.png +0 -0
- nonebot_plugin_osubot/osufile/mods/DT.png +0 -0
- nonebot_plugin_osubot/osufile/mods/EZ.png +0 -0
- nonebot_plugin_osubot/osufile/mods/FI.png +0 -0
- nonebot_plugin_osubot/osufile/mods/FL.png +0 -0
- nonebot_plugin_osubot/osufile/mods/HD.png +0 -0
- nonebot_plugin_osubot/osufile/mods/HR.png +0 -0
- nonebot_plugin_osubot/osufile/mods/HT.png +0 -0
- nonebot_plugin_osubot/osufile/mods/MR.png +0 -0
- nonebot_plugin_osubot/osufile/mods/NC.png +0 -0
- nonebot_plugin_osubot/osufile/mods/NF.png +0 -0
- nonebot_plugin_osubot/osufile/mods/PF.png +0 -0
- nonebot_plugin_osubot/osufile/mods/RX.png +0 -0
- nonebot_plugin_osubot/osufile/mods/SD.png +0 -0
- nonebot_plugin_osubot/osufile/mods/SO.png +0 -0
- nonebot_plugin_osubot/osufile/mods/TD.png +0 -0
- nonebot_plugin_osubot/osufile/mods/V2.png +0 -0
- nonebot_plugin_osubot/pp.py +7 -0
- nonebot_plugin_osubot/schema/__init__.py +0 -2
- nonebot_plugin_osubot/schema/beatmapsets.py +42 -0
- nonebot_plugin_osubot/schema/score.py +1 -0
- {nonebot_plugin_osubot-6.23.1.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/METADATA +2 -2
- {nonebot_plugin_osubot-6.23.1.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/RECORD +80 -39
- nonebot_plugin_osubot/schema/sayo_beatmap.py +0 -59
- {nonebot_plugin_osubot-6.23.1.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
function JuiceStream(data, beatmap)
|
|
2
|
+
{
|
|
3
|
+
Slider.call(this, data, beatmap);
|
|
4
|
+
|
|
5
|
+
var points = data[5].split('|');
|
|
6
|
+
var sliderType = points[0];
|
|
7
|
+
points[0] = this.position;
|
|
8
|
+
for (var i = 1; i < points.length; i++)
|
|
9
|
+
{
|
|
10
|
+
points[i] = new Point(points[i].split(':'));
|
|
11
|
+
}
|
|
12
|
+
this.repeat = data[6] | 0;
|
|
13
|
+
this.pixelLength = +data[7];
|
|
14
|
+
|
|
15
|
+
this.timingPoint = this.beatmap.timingPointAt(this.time);
|
|
16
|
+
this.beatLength = this.timingPoint.beatLength;
|
|
17
|
+
this.timingPointStart = this.timingPoint.time;
|
|
18
|
+
|
|
19
|
+
this.sliderTime = this.beatLength * ( this.pixelLength / this.beatmap.SliderMultiplier ) / 100;
|
|
20
|
+
this.velocityFactor = 100 * this.beatmap.SliderMultiplier / this.beatLength;
|
|
21
|
+
this.tickDistanceFactor = 100 * this.beatmap.SliderMultiplier / this.beatmap.SliderTickRate;
|
|
22
|
+
this.velocity = this.velocityFactor * this.timingPoint.sliderVelocity;
|
|
23
|
+
this.tickDistance = this.tickDistanceFactor * this.timingPoint.sliderVelocity;
|
|
24
|
+
|
|
25
|
+
this.endTime = this.time + this.sliderTime * this.repeat;
|
|
26
|
+
this.duration = this.endTime - this.time;
|
|
27
|
+
|
|
28
|
+
this.spanCount = parseInt(this.repeat);
|
|
29
|
+
|
|
30
|
+
this.curve = Curve.parse(sliderType, points, this.pixelLength);
|
|
31
|
+
|
|
32
|
+
this.endPosition = this.curve.pointAt(1);
|
|
33
|
+
|
|
34
|
+
this.max_length = 100000;
|
|
35
|
+
let length = Math.min(this.max_length, this.pixelLength);
|
|
36
|
+
this.tickDistance = Math.clamp(this.tickDistance, 0, length);
|
|
37
|
+
this.minDistanceFromEnd = this.velocity * 10;
|
|
38
|
+
|
|
39
|
+
this.events = [];
|
|
40
|
+
this.events.push({type: "head", time: this.time, pathProgress: 0});
|
|
41
|
+
if (this.tickDistance != 0) {
|
|
42
|
+
for (let span = 0; span < this.spanCount; span++) {
|
|
43
|
+
let spanStartTime = this.time + span * this.sliderTime;
|
|
44
|
+
let reversed = span % 2 == 1;
|
|
45
|
+
let ticks = this.generateTicks(span, spanStartTime, this.sliderTime, reversed, length, this.tickDistance, this.minDistanceFromEnd);
|
|
46
|
+
if (reversed) ticks = ticks.reverse();
|
|
47
|
+
this.events.push(...ticks);
|
|
48
|
+
if (span < this.spanCount - 1)
|
|
49
|
+
{
|
|
50
|
+
this.events.push({
|
|
51
|
+
type: "repeat",
|
|
52
|
+
time: spanStartTime + this.sliderTime,
|
|
53
|
+
pathProgress: (span + 1) % 2
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let legacyLastTickOffset = 36;
|
|
60
|
+
let finalSpanIndex = this.spanCount - 1;
|
|
61
|
+
let finalSpanStartTime = this.time + finalSpanIndex * this.sliderTime;
|
|
62
|
+
let finalSpanEndTime = Math.max(this.time + this.duration / 2, (finalSpanStartTime + this.sliderTime) - legacyLastTickOffset);
|
|
63
|
+
let finalProgress = (finalSpanEndTime - finalSpanStartTime) / this.sliderTime;
|
|
64
|
+
|
|
65
|
+
if (this.spanCount % 2 == 0) finalProgress = 1 - finalProgress;
|
|
66
|
+
|
|
67
|
+
this.events.push({
|
|
68
|
+
type: "legacyLastTick",
|
|
69
|
+
time: finalSpanEndTime,
|
|
70
|
+
pathProgress: finalProgress
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
this.events.push({
|
|
74
|
+
type: "tail",
|
|
75
|
+
time: this.endTime,
|
|
76
|
+
pathProgress: this.spanCount % 2
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
this.nested = [];
|
|
80
|
+
}
|
|
81
|
+
JuiceStream.prototype = Object.create(Slider.prototype);
|
|
82
|
+
JuiceStream.prototype.constructor = JuiceStream;
|
|
83
|
+
JuiceStream.ID = 2;
|
|
84
|
+
Catch.prototype.hitObjectTypes[JuiceStream.ID] = JuiceStream;
|
|
85
|
+
JuiceStream.prototype.generateTicks = function(spanIndex, spanStartTime, spanDuration, reversed, length, tickDistance, minDistanceFromEnd) {
|
|
86
|
+
let ticks = [];
|
|
87
|
+
for (let d = tickDistance; d <= length; d += tickDistance) {
|
|
88
|
+
if (d >= length - minDistanceFromEnd)
|
|
89
|
+
break;
|
|
90
|
+
|
|
91
|
+
let pathProgress = d / length;
|
|
92
|
+
let timeProgress = reversed ? 1 - pathProgress : pathProgress;
|
|
93
|
+
|
|
94
|
+
ticks.push({type: "tick", time: spanStartTime + timeProgress * spanDuration, pathProgress});
|
|
95
|
+
}
|
|
96
|
+
return ticks;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
JuiceStream.prototype.buildNested = function() {
|
|
100
|
+
this.nested = [];
|
|
101
|
+
|
|
102
|
+
let lastEvent = null;
|
|
103
|
+
for(let i = 0; i < this.events.length; i++) {
|
|
104
|
+
// generate tiny droplets since the last point
|
|
105
|
+
if (lastEvent != null)
|
|
106
|
+
{
|
|
107
|
+
let sinceLastTick = this.events[i].time - lastEvent.time;
|
|
108
|
+
if (sinceLastTick > 80)
|
|
109
|
+
{
|
|
110
|
+
let timeBetweenTiny = sinceLastTick;
|
|
111
|
+
while (timeBetweenTiny > 100) timeBetweenTiny /= 2;
|
|
112
|
+
for (let t = timeBetweenTiny; t < sinceLastTick; t += timeBetweenTiny) {
|
|
113
|
+
let repeat = (t + lastEvent.time - this.time) * this.repeat / this.duration;
|
|
114
|
+
repeat %= 2;
|
|
115
|
+
if (repeat > 1) repeat = 2 - repeat;
|
|
116
|
+
var point = this.curve.pointAt(repeat);
|
|
117
|
+
this.nested.push(new PalpableCatchHitObject({
|
|
118
|
+
type: "TinyDroplet",
|
|
119
|
+
time: t + lastEvent.time,
|
|
120
|
+
x: point.x,
|
|
121
|
+
// x: this.curve.pointAt(lastEvent.pathProgress + (t / sinceLastTick) * (this.events[i].pathProgress - lastEvent.pathProgress)).x,
|
|
122
|
+
color: this.color,
|
|
123
|
+
radius: this.beatmap.tinyRadius,
|
|
124
|
+
}, this.beatmap));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// this also includes LegacyLastTick and this is used for TinyDroplet generation above.
|
|
130
|
+
// this means that the final segment of TinyDroplets are increasingly mistimed where LegacyLastTickOffset is being applied.
|
|
131
|
+
lastEvent = this.events[i];
|
|
132
|
+
|
|
133
|
+
switch (this.events[i].type)
|
|
134
|
+
{
|
|
135
|
+
case "tick":
|
|
136
|
+
this.nested.push(new PalpableCatchHitObject({
|
|
137
|
+
type: "Droplet",
|
|
138
|
+
time: this.events[i].time,
|
|
139
|
+
x: this.curve.pointAt(this.events[i].pathProgress).x,
|
|
140
|
+
color: this.color,
|
|
141
|
+
radius: this.beatmap.smallRadius,
|
|
142
|
+
}, this.beatmap));
|
|
143
|
+
break;
|
|
144
|
+
|
|
145
|
+
case "head":
|
|
146
|
+
case "tail":
|
|
147
|
+
case "repeat":
|
|
148
|
+
this.nested.push(new PalpableCatchHitObject({
|
|
149
|
+
type: "Fruit",
|
|
150
|
+
time: this.events[i].time,
|
|
151
|
+
x: this.curve.pointAt(this.events[i].pathProgress).x,
|
|
152
|
+
color: this.color,
|
|
153
|
+
radius: this.beatmap.circleRadius,
|
|
154
|
+
}, this.beatmap));
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* TODO BUG!!!
|
|
160
|
+
* 在预览 #4057684 时第一个滑条出现了
|
|
161
|
+
* PalpableCatchHitObject {beatmap: Catch, type: 'TinyDroplet', time: 464.57142857142895, …}
|
|
162
|
+
* PalpableCatchHitObject {beatmap: Catch, type: 'Droplet', time: 464.571428571429, …}
|
|
163
|
+
* 物件数量偏差导致后续随机数错误
|
|
164
|
+
* 暂时找不到原因,可能因为计算精度问题,临时手动将其剔除
|
|
165
|
+
*/
|
|
166
|
+
let tmp_droplets = this.nested.filter((item) => item.type === "Droplet");
|
|
167
|
+
this.nested = this.nested.filter((item) => {
|
|
168
|
+
if (item.type != "TinyDroplet") return true;
|
|
169
|
+
for (let td = 0; td < tmp_droplets.length; td++) {
|
|
170
|
+
if (Math.abs(item.time - tmp_droplets[td].time) < 0.01) return false;
|
|
171
|
+
}
|
|
172
|
+
return true;
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
return this;
|
|
176
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function HitNote(data, beatmap)
|
|
2
|
+
{
|
|
3
|
+
HitObject.call(this, data, beatmap);
|
|
4
|
+
|
|
5
|
+
this.column = Math.max(1, Math.min((this.position.x / this.beatmap.columnSize + 1) | 0, this.beatmap.keyCount)) - 1;
|
|
6
|
+
}
|
|
7
|
+
HitNote.prototype = Object.create(HitObject.prototype);
|
|
8
|
+
HitNote.prototype.constructor = HitNote;
|
|
9
|
+
HitNote.ID = 1;
|
|
10
|
+
Mania.prototype.hitObjectTypes[HitNote.ID] = HitNote;
|
|
11
|
+
HitNote.prototype.draw = function(scroll, ctx)
|
|
12
|
+
{
|
|
13
|
+
ctx.beginPath();
|
|
14
|
+
ctx.rect(this.position.x, this.beatmap.calcY(this.position.y, scroll) - Mania.COLUMN_WIDTH / 3,
|
|
15
|
+
Mania.COLUMN_WIDTH, Mania.COLUMN_WIDTH / 3);
|
|
16
|
+
ctx.fillStyle = this.color;
|
|
17
|
+
ctx.fill();
|
|
18
|
+
ctx.strokeStyle = '#ccc';
|
|
19
|
+
ctx.lineWidth = 1;
|
|
20
|
+
ctx.stroke();
|
|
21
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
function HoldNote(data, beatmap)
|
|
2
|
+
{
|
|
3
|
+
HitNote.call(this, data, beatmap);
|
|
4
|
+
|
|
5
|
+
this.endTime = data[5].split(':')[0] | 0;
|
|
6
|
+
}
|
|
7
|
+
HoldNote.prototype = Object.create(HitNote.prototype);
|
|
8
|
+
HoldNote.prototype.constructor = HoldNote;
|
|
9
|
+
HoldNote.ID = 128;
|
|
10
|
+
Mania.prototype.hitObjectTypes[HoldNote.ID] = HoldNote;
|
|
11
|
+
HoldNote.WIDTH_SCALE = 0.8;
|
|
12
|
+
HoldNote.OPACITY = 0.88;
|
|
13
|
+
HoldNote.prototype.draw = function(scroll, ctx)
|
|
14
|
+
{
|
|
15
|
+
var sy = this.beatmap.calcY(this.position.y, scroll) - Mania.COLUMN_WIDTH / 3,
|
|
16
|
+
ey = this.beatmap.calcY(this.endPosition.y, scroll) - Mania.COLUMN_WIDTH / 3;
|
|
17
|
+
|
|
18
|
+
var w = Mania.COLUMN_WIDTH * HoldNote.WIDTH_SCALE;
|
|
19
|
+
ctx.globalAlpha = HoldNote.OPACITY;
|
|
20
|
+
ctx.beginPath();
|
|
21
|
+
ctx.rect(this.position.x + (Mania.COLUMN_WIDTH - w) / 2, ey, w, sy - ey);
|
|
22
|
+
ctx.fillStyle = this.color;
|
|
23
|
+
ctx.fill();
|
|
24
|
+
ctx.globalAlpha = 1;
|
|
25
|
+
|
|
26
|
+
ctx.beginPath();
|
|
27
|
+
ctx.rect(this.position.x, sy, Mania.COLUMN_WIDTH, Mania.COLUMN_WIDTH / 3);
|
|
28
|
+
ctx.fill();
|
|
29
|
+
ctx.strokeStyle = '#ccc';
|
|
30
|
+
ctx.lineWidth = 1;
|
|
31
|
+
ctx.stroke();
|
|
32
|
+
|
|
33
|
+
ctx.beginPath();
|
|
34
|
+
ctx.rect(this.position.x, ey, Mania.COLUMN_WIDTH, Mania.COLUMN_WIDTH / 3);
|
|
35
|
+
ctx.fill();
|
|
36
|
+
ctx.stroke();
|
|
37
|
+
};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
function Mania(osu)
|
|
2
|
+
{
|
|
3
|
+
Scroll.call(this, osu);
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
this.scrollSpeed = Mania.SCROLL_SPEED;
|
|
7
|
+
//this.columnStart = Mania.COLUMN_START;
|
|
8
|
+
this.columnStart = (Beatmap.WIDTH - Mania.COLUMN_WIDTH * this.keyCount) / 2
|
|
9
|
+
|
|
10
|
+
for (var i = 0; i < this.keyCount; i++)
|
|
11
|
+
{
|
|
12
|
+
this.Colors[i] = Mania.DEFAULT_COLORS[i & 1];
|
|
13
|
+
}
|
|
14
|
+
var p = this.keyCount / 2;
|
|
15
|
+
if (this.keyCount & 1)
|
|
16
|
+
{
|
|
17
|
+
this.Colors[p | 0] = Mania.DEFAULT_COLORS[2];
|
|
18
|
+
}
|
|
19
|
+
else
|
|
20
|
+
{
|
|
21
|
+
this.Colors = this.Colors.slice(0, p).concat(this.Colors.slice(p - 1));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
for (var i = 0; i < this.HitObjects.length; i++)
|
|
26
|
+
{
|
|
27
|
+
var hitObject = this.HitObjects[i];
|
|
28
|
+
hitObject.color = this.Colors[hitObject.column];
|
|
29
|
+
hitObject.position.x = Mania.COLUMN_WIDTH * hitObject.column;
|
|
30
|
+
hitObject.position.y = this.scrollAt(hitObject.time);
|
|
31
|
+
hitObject.endPosition.y = this.scrollAt(hitObject.endTime);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
Mania.prototype = Object.create(Scroll.prototype, {
|
|
35
|
+
keyCount: {
|
|
36
|
+
get: function()
|
|
37
|
+
{
|
|
38
|
+
return this.CircleSize;
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
columnSize: {
|
|
42
|
+
get: function()
|
|
43
|
+
{
|
|
44
|
+
return Beatmap.MAX_X / this.keyCount;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
Mania.prototype.constructor = Mania;
|
|
49
|
+
Mania.prototype.hitObjectTypes = {};
|
|
50
|
+
Mania.ID = 3;
|
|
51
|
+
Beatmap.modes[Mania.ID] = Mania;
|
|
52
|
+
Mania.DEFAULT_COLORS = [
|
|
53
|
+
'#5bf',
|
|
54
|
+
'#ccc',
|
|
55
|
+
'#da2'
|
|
56
|
+
];
|
|
57
|
+
Mania.COLUMN_START = 130;
|
|
58
|
+
Mania.HIT_POSITION = 400;
|
|
59
|
+
Mania.COLUMN_WIDTH = 30;
|
|
60
|
+
let savedSpeed = window.localStorage.getItem("SCROLL_SPEED");
|
|
61
|
+
Mania.SCROLL_SPEED = (savedSpeed) ? parseInt(savedSpeed) : 20;
|
|
62
|
+
Mania.prototype.calcY = function(y, scroll)
|
|
63
|
+
{
|
|
64
|
+
return Mania.HIT_POSITION - (y - scroll) * this.scrollSpeed * 0.035;
|
|
65
|
+
};
|
|
66
|
+
Mania.prototype.update = function(ctx)
|
|
67
|
+
{
|
|
68
|
+
ctx.translate(this.columnStart, 0);
|
|
69
|
+
};
|
|
70
|
+
Mania.prototype.draw = function(time, ctx)
|
|
71
|
+
{
|
|
72
|
+
if (typeof this.tmp.first == 'undefined')
|
|
73
|
+
{
|
|
74
|
+
this.tmp.first = 0;
|
|
75
|
+
this.tmp.last = -1;
|
|
76
|
+
this.tmp.barLine = 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
var scroll = this.scrollAt(time);
|
|
80
|
+
while (this.tmp.first < this.HitObjects.length &&
|
|
81
|
+
time > this.HitObjects[this.tmp.first].endTime)
|
|
82
|
+
{
|
|
83
|
+
this.tmp.first++;
|
|
84
|
+
}
|
|
85
|
+
while (this.tmp.last + 1 < this.HitObjects.length)
|
|
86
|
+
{
|
|
87
|
+
var hitObject = this.HitObjects[this.tmp.last + 1];
|
|
88
|
+
if (this.calcY(hitObject.position.y, scroll) < -Mania.COLUMN_WIDTH)
|
|
89
|
+
{
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
this.tmp.last++;
|
|
93
|
+
}
|
|
94
|
+
while (this.tmp.barLine < this.barLines.length &&
|
|
95
|
+
this.calcY(this.barLines[this.tmp.barLine], scroll) > Beatmap.MAX_Y)
|
|
96
|
+
{
|
|
97
|
+
this.tmp.barLine++;
|
|
98
|
+
}
|
|
99
|
+
for (var i = this.tmp.barLine; i < this.barLines.length && this.calcY(this.barLines[i], scroll) > -Mania.COLUMN_WIDTH; i++)
|
|
100
|
+
{
|
|
101
|
+
var barLine = this.calcY(this.barLines[i], scroll);
|
|
102
|
+
ctx.beginPath();
|
|
103
|
+
ctx.moveTo(0, barLine);
|
|
104
|
+
ctx.lineTo(Mania.COLUMN_WIDTH * this.keyCount, barLine);
|
|
105
|
+
ctx.strokeStyle = '#fff';
|
|
106
|
+
ctx.lineWidth = 1;
|
|
107
|
+
ctx.stroke();
|
|
108
|
+
}
|
|
109
|
+
for (var i = this.tmp.first; i <= this.tmp.last; i++)
|
|
110
|
+
{
|
|
111
|
+
var hitObject = this.HitObjects[i];
|
|
112
|
+
if (time > hitObject.endTime)
|
|
113
|
+
{
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
hitObject.draw(scroll, ctx);
|
|
117
|
+
}
|
|
118
|
+
ctx.clearRect(0, Mania.HIT_POSITION, Beatmap.WIDTH, Beatmap.HEIGHT - Mania.HIT_POSITION);
|
|
119
|
+
};
|
|
120
|
+
Mania.prototype.processBG = function(ctx)
|
|
121
|
+
{
|
|
122
|
+
ctx.beginPath();
|
|
123
|
+
ctx.rect(0, 0, Mania.COLUMN_WIDTH * this.keyCount, Beatmap.HEIGHT);
|
|
124
|
+
ctx.strokeStyle = '#ddd';
|
|
125
|
+
ctx.lineWidth = 8;
|
|
126
|
+
ctx.stroke();
|
|
127
|
+
ctx.fillStyle = '#000';
|
|
128
|
+
ctx.fill();
|
|
129
|
+
|
|
130
|
+
for (var i = 0; i < this.keyCount; i++)
|
|
131
|
+
{
|
|
132
|
+
var x = Mania.COLUMN_WIDTH * i;
|
|
133
|
+
|
|
134
|
+
ctx.beginPath();
|
|
135
|
+
ctx.moveTo(x, 0);
|
|
136
|
+
ctx.lineTo(x, Mania.HIT_POSITION);
|
|
137
|
+
ctx.strokeStyle = '#fff';
|
|
138
|
+
ctx.lineWidth = 1;
|
|
139
|
+
ctx.stroke();
|
|
140
|
+
|
|
141
|
+
ctx.beginPath();
|
|
142
|
+
ctx.rect(x, Mania.HIT_POSITION, Mania.COLUMN_WIDTH, Beatmap.HEIGHT - Mania.HIT_POSITION);
|
|
143
|
+
ctx.fillStyle = this.Colors[i];
|
|
144
|
+
ctx.fill();
|
|
145
|
+
ctx.strokeStyle = '#fff';
|
|
146
|
+
ctx.lineWidth = 3;
|
|
147
|
+
ctx.stroke();
|
|
148
|
+
}
|
|
149
|
+
var x = Mania.COLUMN_WIDTH * this.keyCount;
|
|
150
|
+
ctx.beginPath();
|
|
151
|
+
ctx.moveTo(x, 0);
|
|
152
|
+
ctx.lineTo(x, Mania.HIT_POSITION);
|
|
153
|
+
ctx.strokeStyle = '#fff';
|
|
154
|
+
ctx.lineWidth = 1;
|
|
155
|
+
ctx.stroke();
|
|
156
|
+
// HIT POSITION
|
|
157
|
+
ctx.beginPath();
|
|
158
|
+
ctx.rect(0, Mania.HIT_POSITION, Mania.COLUMN_WIDTH * this.keyCount, Mania.COLUMN_WIDTH / 3);
|
|
159
|
+
ctx.strokeStyle = '#fff';
|
|
160
|
+
ctx.lineWidth = 2;
|
|
161
|
+
ctx.stroke();
|
|
162
|
+
ctx.fillStyle = '#568';
|
|
163
|
+
ctx.fill();
|
|
164
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
var bgblob;
|
|
2
|
+
function Preview(SCALE = 0.2) {
|
|
3
|
+
this.screen = document.createElement('canvas');
|
|
4
|
+
this.screen.width = Beatmap.WIDTH;
|
|
5
|
+
this.screen.height = Beatmap.HEIGHT;
|
|
6
|
+
this.ctx = this.screen.getContext('2d');
|
|
7
|
+
this.ctx.scale(SCALE, SCALE);
|
|
8
|
+
this.startTime = 0;
|
|
9
|
+
this.endTime = 0;
|
|
10
|
+
this.previewTime = -1;
|
|
11
|
+
|
|
12
|
+
var self = this;
|
|
13
|
+
}
|
|
14
|
+
Preview.prototype.load = function (osufile, success, fail) {
|
|
15
|
+
if (typeof this.xhr != 'undefined') {
|
|
16
|
+
this.xhr.abort();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
var self = this;
|
|
20
|
+
try {
|
|
21
|
+
self.beatmap = Beatmap.parse(osufile);
|
|
22
|
+
|
|
23
|
+
self.ctx.restore();
|
|
24
|
+
self.ctx.save();
|
|
25
|
+
self.beatmap.update(self.ctx);
|
|
26
|
+
self.at(0);
|
|
27
|
+
|
|
28
|
+
self.previewTime = self.beatmap.PreviewTime > 0 ? self.beatmap.PreviewTime : -1;
|
|
29
|
+
|
|
30
|
+
self.startTime = self.beatmap.HitObjects.length > 0 ? self.beatmap.HitObjects[0].time - 1000 : 0;
|
|
31
|
+
if (self.startTime < 0) {
|
|
32
|
+
self.startTime = 0;
|
|
33
|
+
}
|
|
34
|
+
self.endTime = self.beatmap.HitObjects.length > 0 ? self.beatmap.HitObjects[self.beatmap.HitObjects.length - 1].endTime : 0;
|
|
35
|
+
|
|
36
|
+
if (typeof success == 'function') {
|
|
37
|
+
success.call(self);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
if (typeof fail == 'function') {
|
|
42
|
+
fail.call(self, e);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
Preview.prototype.at = function (time) {
|
|
47
|
+
if (time > this.endTime) {
|
|
48
|
+
time = this.endTime;
|
|
49
|
+
}
|
|
50
|
+
if (time < this.startTime) {
|
|
51
|
+
time = this.startTime;
|
|
52
|
+
}
|
|
53
|
+
this.ctx.save();
|
|
54
|
+
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
55
|
+
this.ctx.clearRect(0, 0, Beatmap.WIDTH, Beatmap.HEIGHT);
|
|
56
|
+
this.ctx.restore();
|
|
57
|
+
if (typeof this.beatmap.processBG != 'undefined') {
|
|
58
|
+
this.beatmap.processBG(this.ctx);
|
|
59
|
+
}
|
|
60
|
+
this.beatmap.draw(time, this.ctx);
|
|
61
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
function Bezier2(points)
|
|
2
|
+
{
|
|
3
|
+
// https://github.com/itdelatrisu/opsu/blob/master/src/itdelatrisu/opsu/objects/curves/Bezier2.java
|
|
4
|
+
if (points.length < 2)
|
|
5
|
+
{
|
|
6
|
+
throw 'invalid data';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
this.points = points;
|
|
10
|
+
var approxLength = 0;
|
|
11
|
+
for (var i = 1; i < this.points.length; i++)
|
|
12
|
+
{
|
|
13
|
+
approxLength += this.points[i].distanceTo(this.points[i - 1]);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
CurveType.call(this, approxLength);
|
|
17
|
+
}
|
|
18
|
+
Bezier2.prototype = Object.create(CurveType.prototype);
|
|
19
|
+
Bezier2.prototype.constructor = Bezier2;
|
|
20
|
+
Bezier2.prototype.pointAt = function(t)
|
|
21
|
+
{
|
|
22
|
+
var n = this.points.length - 1,
|
|
23
|
+
point = new Point(),
|
|
24
|
+
combination = 1;
|
|
25
|
+
for (var i = 0; i <= n; i++)
|
|
26
|
+
{
|
|
27
|
+
var bernstein = combination * Math.pow(t, i) * Math.pow(1 - t, n - i);
|
|
28
|
+
point.x += this.points[i].x * bernstein;
|
|
29
|
+
point.y += this.points[i].y * bernstein;
|
|
30
|
+
combination = combination * (n - i) / (i + 1);
|
|
31
|
+
}
|
|
32
|
+
return point;
|
|
33
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
function CatmullCurve(points, pixelLength)
|
|
2
|
+
{
|
|
3
|
+
// https://github.com/itdelatrisu/opsu/blob/master/src/itdelatrisu/opsu/objects/curves/CatmullCurve.java
|
|
4
|
+
var catmulls = [],
|
|
5
|
+
controls = [];
|
|
6
|
+
if (!points[0].equalTo(points[1]))
|
|
7
|
+
{
|
|
8
|
+
controls.push(points[0]);
|
|
9
|
+
}
|
|
10
|
+
for (var i = 0; i < points.length; i++)
|
|
11
|
+
{
|
|
12
|
+
controls.push(points[i]);
|
|
13
|
+
try
|
|
14
|
+
{
|
|
15
|
+
catmulls.push(new CentripetalCatmullRom(controls));
|
|
16
|
+
controls.shift();
|
|
17
|
+
}
|
|
18
|
+
catch (e) {}
|
|
19
|
+
}
|
|
20
|
+
var point2 = points.slice(-2);
|
|
21
|
+
if (!point2[1].equalTo(point2[0]))
|
|
22
|
+
{
|
|
23
|
+
controls.push(point2[1]);
|
|
24
|
+
}
|
|
25
|
+
try
|
|
26
|
+
{
|
|
27
|
+
catmulls.push(new CentripetalCatmullRom(controls));
|
|
28
|
+
}
|
|
29
|
+
catch (e) {}
|
|
30
|
+
|
|
31
|
+
EqualDistanceMultiCurve.call(this, catmulls, pixelLength);
|
|
32
|
+
};
|
|
33
|
+
CatmullCurve.prototype = Object.create(EqualDistanceMultiCurve.prototype);
|
|
34
|
+
CatmullCurve.prototype.constructor = CatmullCurve;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
function CentripetalCatmullRom(points)
|
|
2
|
+
{
|
|
3
|
+
// https://github.com/itdelatrisu/opsu/blob/master/src/itdelatrisu/opsu/objects/curves/CentripetalCatmullRom.java
|
|
4
|
+
// needs 4 points
|
|
5
|
+
if (points.length != 4)
|
|
6
|
+
{
|
|
7
|
+
throw 'invalid data';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
this.points = points;
|
|
11
|
+
var approxLength = 0;
|
|
12
|
+
for (var i = 1; i < 4; i++)
|
|
13
|
+
{
|
|
14
|
+
approxLength += this.points[i].distanceTo(this.points[i - 1]);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
CurveType.call(this, approxLength / 2);
|
|
18
|
+
}
|
|
19
|
+
CentripetalCatmullRom.prototype = Object.create(CurveType.prototype);
|
|
20
|
+
CentripetalCatmullRom.prototype.constructor = CentripetalCatmullRom;
|
|
21
|
+
CentripetalCatmullRom.prototype.pointAt = function(t)
|
|
22
|
+
{
|
|
23
|
+
t = Math.lerp(1, 2, t);
|
|
24
|
+
var A1 = this.points[0].clone().scale(1 - t).translate(this.points[1].clone().scale(t));
|
|
25
|
+
var A2 = this.points[1].clone().scale(2 - t).translate(this.points[2].clone().scale(t - 1));
|
|
26
|
+
var A3 = this.points[2].clone().scale(3 - t).translate(this.points[3].clone().scale(t - 2));
|
|
27
|
+
var B1 = A1.clone().scale(2 - t).translate(A2.clone().scale(t));
|
|
28
|
+
var B2 = A2.clone().scale(3 - t).translate(A3.clone().scale(t - 1));
|
|
29
|
+
return B1.clone().scale(2 - t).translate(B2.clone().scale(t - 1)).scale(0.5);
|
|
30
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
function CircumscribedCircle(points, pixelLength)
|
|
2
|
+
{
|
|
3
|
+
var a = points[0].x - points[1].x, b = points[0].y - points[1].y,
|
|
4
|
+
c = points[1].x - points[2].x, d = points[1].y - points[2].y,
|
|
5
|
+
q = (a * d - b * c) * 2,
|
|
6
|
+
l0 = points[0].x * points[0].x + points[0].y * points[0].y,
|
|
7
|
+
l1 = points[1].x * points[1].x + points[1].y * points[1].y,
|
|
8
|
+
l2 = points[2].x * points[2].x + points[2].y * points[2].y,
|
|
9
|
+
x = ((l0 - l1) * d + (l1 - l2) * -b) / q,
|
|
10
|
+
y = ((l0 - l1) * -c + (l1 - l2) * a) / q,
|
|
11
|
+
dx = points[0].x - x,
|
|
12
|
+
dy = points[0].y - y,
|
|
13
|
+
r = Math.hypot(dx, dy),
|
|
14
|
+
base = Math.atan2(dy, dx),
|
|
15
|
+
t = pixelLength / r * Math.ccw(points[0], points[1], points[2]);
|
|
16
|
+
if (!t)
|
|
17
|
+
{
|
|
18
|
+
// when points[2] is missing or vectors are parallel
|
|
19
|
+
throw 'invalid data';
|
|
20
|
+
}
|
|
21
|
+
this.circle = {
|
|
22
|
+
x: x,
|
|
23
|
+
y: y,
|
|
24
|
+
radius: r
|
|
25
|
+
};
|
|
26
|
+
this.angle = {
|
|
27
|
+
base: base,
|
|
28
|
+
delta: t
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
var nCurve = pixelLength / Curve.PRECISION | 0;
|
|
32
|
+
this.path = [];
|
|
33
|
+
for (var i = 0; i <= nCurve; i++)
|
|
34
|
+
{
|
|
35
|
+
this.path[i] = this.pointAt(i / nCurve);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
Curve.call(this);
|
|
39
|
+
};
|
|
40
|
+
CircumscribedCircle.prototype = Object.create(Curve.prototype);
|
|
41
|
+
CircumscribedCircle.prototype.constructor = CircumscribedCircle;
|
|
42
|
+
CircumscribedCircle.prototype.pointAt = function(t)
|
|
43
|
+
{
|
|
44
|
+
var angle = this.angle.base + this.angle.delta * t;
|
|
45
|
+
return new Point(this.circle.x + Math.cos(angle) * this.circle.radius,
|
|
46
|
+
this.circle.y + Math.sin(angle) * this.circle.radius);
|
|
47
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function Curve()
|
|
2
|
+
{
|
|
3
|
+
this.startAngle = this.path[0].angleTo(this.path[1]);
|
|
4
|
+
var path2 = this.path.slice(-2);
|
|
5
|
+
this.endAngle = path2[1].angleTo(path2[0]);
|
|
6
|
+
}
|
|
7
|
+
Curve.prototype.path = undefined;
|
|
8
|
+
Curve.prototype.pointAt = undefined;
|
|
9
|
+
Curve.PRECISION = 5;
|
|
10
|
+
Curve.parse = function(sliderType, points, pixelLength)
|
|
11
|
+
{
|
|
12
|
+
try
|
|
13
|
+
{
|
|
14
|
+
if (sliderType == 'P')
|
|
15
|
+
{
|
|
16
|
+
return new CircumscribedCircle(points, pixelLength);
|
|
17
|
+
}
|
|
18
|
+
if (sliderType == 'C')
|
|
19
|
+
{
|
|
20
|
+
return new CatmullCurve(points, pixelLength);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch(e) {}
|
|
24
|
+
return new LinearBezier(points, pixelLength, sliderType == 'L');
|
|
25
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function CurveType(approxLength)
|
|
2
|
+
{
|
|
3
|
+
// https://github.com/itdelatrisu/opsu/blob/master/src/itdelatrisu/opsu/objects/curves/CurveType.java
|
|
4
|
+
var points = (approxLength / 4 | 0) + 1;
|
|
5
|
+
this.path = [];
|
|
6
|
+
for (var i = 0; i <= points; i++)
|
|
7
|
+
{
|
|
8
|
+
this.path[i] = this.pointAt(i / points);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
this.distance = [ 0 ];
|
|
12
|
+
for (var i = 1; i <= points; i++)
|
|
13
|
+
{
|
|
14
|
+
this.distance[i] = this.path[i].distanceTo(this.path[i - 1]);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
CurveType.prototype.pointAt = undefined;
|