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.

Files changed (81) hide show
  1. nonebot_plugin_osubot/api.py +7 -5
  2. nonebot_plugin_osubot/draw/bmap.py +19 -21
  3. nonebot_plugin_osubot/draw/bp.py +1 -1
  4. nonebot_plugin_osubot/draw/echarts.py +8 -2
  5. nonebot_plugin_osubot/draw/info.py +2 -0
  6. nonebot_plugin_osubot/draw/map.py +5 -2
  7. nonebot_plugin_osubot/draw/osu_preview.py +64 -0
  8. nonebot_plugin_osubot/draw/osu_preview_templates/css/style.css +258 -0
  9. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/README.md +109 -0
  10. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js +3 -0
  11. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js.map +1 -0
  12. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js +3 -0
  13. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js.map +1 -0
  14. nonebot_plugin_osubot/draw/osu_preview_templates/index.html +437 -0
  15. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/beatmap.js +211 -0
  16. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/hitobject.js +29 -0
  17. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/point.js +55 -0
  18. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/scroll.js +45 -0
  19. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/timingpoint.js +35 -0
  20. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/LegacyRandom.js +81 -0
  21. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/PalpableCatchHitObject.js +53 -0
  22. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/bananashower.js +33 -0
  23. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/catch.js +211 -0
  24. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/fruit.js +21 -0
  25. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/juicestream.js +176 -0
  26. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/hitnote.js +21 -0
  27. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/holdnote.js +37 -0
  28. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/mania.js +164 -0
  29. nonebot_plugin_osubot/draw/osu_preview_templates/js/preview.js +61 -0
  30. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/bezier2.js +33 -0
  31. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/catmullcurve.js +34 -0
  32. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/centripetalcatmullrom.js +30 -0
  33. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/circumstancedcircle.js +47 -0
  34. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curve.js +25 -0
  35. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curvetype.js +17 -0
  36. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/equaldistancemulticurve.js +70 -0
  37. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/linearbezier.js +40 -0
  38. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/hitcircle.js +85 -0
  39. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/slider.js +120 -0
  40. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/spinner.js +56 -0
  41. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/standard.js +170 -0
  42. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/donkat.js +40 -0
  43. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/drumroll.js +34 -0
  44. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/shaker.js +58 -0
  45. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/taiko.js +120 -0
  46. nonebot_plugin_osubot/draw/osu_preview_templates/js/util.js +61 -0
  47. nonebot_plugin_osubot/draw/osu_preview_templates/pic.html +115 -0
  48. nonebot_plugin_osubot/draw/score.py +4 -4
  49. nonebot_plugin_osubot/file.py +1 -12
  50. nonebot_plugin_osubot/mania/__init__.py +9 -10
  51. nonebot_plugin_osubot/matcher/bp_analyze.py +9 -9
  52. nonebot_plugin_osubot/matcher/guess.py +3 -3
  53. nonebot_plugin_osubot/matcher/map_convert.py +12 -7
  54. nonebot_plugin_osubot/matcher/preview.py +10 -3
  55. nonebot_plugin_osubot/matcher/recommend.py +7 -12
  56. nonebot_plugin_osubot/osufile/mods/AP.png +0 -0
  57. nonebot_plugin_osubot/osufile/mods/CL.png +0 -0
  58. nonebot_plugin_osubot/osufile/mods/DT.png +0 -0
  59. nonebot_plugin_osubot/osufile/mods/EZ.png +0 -0
  60. nonebot_plugin_osubot/osufile/mods/FI.png +0 -0
  61. nonebot_plugin_osubot/osufile/mods/FL.png +0 -0
  62. nonebot_plugin_osubot/osufile/mods/HD.png +0 -0
  63. nonebot_plugin_osubot/osufile/mods/HR.png +0 -0
  64. nonebot_plugin_osubot/osufile/mods/HT.png +0 -0
  65. nonebot_plugin_osubot/osufile/mods/MR.png +0 -0
  66. nonebot_plugin_osubot/osufile/mods/NC.png +0 -0
  67. nonebot_plugin_osubot/osufile/mods/NF.png +0 -0
  68. nonebot_plugin_osubot/osufile/mods/PF.png +0 -0
  69. nonebot_plugin_osubot/osufile/mods/RX.png +0 -0
  70. nonebot_plugin_osubot/osufile/mods/SD.png +0 -0
  71. nonebot_plugin_osubot/osufile/mods/SO.png +0 -0
  72. nonebot_plugin_osubot/osufile/mods/TD.png +0 -0
  73. nonebot_plugin_osubot/osufile/mods/V2.png +0 -0
  74. nonebot_plugin_osubot/pp.py +7 -0
  75. nonebot_plugin_osubot/schema/__init__.py +0 -2
  76. nonebot_plugin_osubot/schema/beatmapsets.py +42 -0
  77. nonebot_plugin_osubot/schema/score.py +1 -0
  78. {nonebot_plugin_osubot-6.23.1.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/METADATA +2 -2
  79. {nonebot_plugin_osubot-6.23.1.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/RECORD +80 -39
  80. nonebot_plugin_osubot/schema/sayo_beatmap.py +0 -59
  81. {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;