Speed slider
This commit is contained in:
parent
3ddddc168b
commit
923848a156
9
nise-replay-viewer/package-lock.json
generated
9
nise-replay-viewer/package-lock.json
generated
@ -37,6 +37,7 @@
|
|||||||
"sonner": "^1.3.1",
|
"sonner": "^1.3.1",
|
||||||
"tailwind-merge": "^2.0.0",
|
"tailwind-merge": "^2.0.0",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
"ts-md5": "^1.3.1",
|
||||||
"zustand": "^4.4.1"
|
"zustand": "^4.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -3645,6 +3646,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
||||||
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
|
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/ts-md5": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-md5/-/ts-md5-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-DiwiXfwvcTeZ5wCE0z+2A9EseZsztaiZtGrtSaY5JOD7ekPnR/GoIVD5gXZAlK9Na9Kvpo9Waz5rW64WKAWApg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tslib": {
|
"node_modules/tslib": {
|
||||||
"version": "2.6.2",
|
"version": "2.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||||
|
|||||||
@ -46,6 +46,7 @@
|
|||||||
"sonner": "^1.3.1",
|
"sonner": "^1.3.1",
|
||||||
"tailwind-merge": "^2.0.0",
|
"tailwind-merge": "^2.0.0",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
"ts-md5": "^1.3.1",
|
||||||
"zustand": "^4.4.1"
|
"zustand": "^4.4.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { Button } from "../components/ui/button";
|
|||||||
import { ArrowLeft, ArrowRight, PauseIcon, PlayIcon } from "lucide-react";
|
import { ArrowLeft, ArrowRight, PauseIcon, PlayIcon } from "lucide-react";
|
||||||
|
|
||||||
export function SongSlider() {
|
export function SongSlider() {
|
||||||
const { beatmap, replay, playing, time } = state();
|
const { beatmap, replay, playing, time, speed } = state();
|
||||||
if (!beatmap || !replay) {
|
if (!beatmap || !replay) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -45,7 +45,6 @@ export function SongSlider() {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<Slider
|
<Slider
|
||||||
step={10}
|
step={10}
|
||||||
min={0}
|
min={0}
|
||||||
@ -55,6 +54,23 @@ export function SongSlider() {
|
|||||||
OsuRenderer.setTime(value[0]);
|
OsuRenderer.setTime(value[0]);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div className="flex flex-col items-start w-full ">
|
||||||
|
<p className="text-sm opacity-50">Current speed</p>
|
||||||
|
<p>{speed}x</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<Slider
|
||||||
|
step={0.1}
|
||||||
|
min={0.1}
|
||||||
|
max={2}
|
||||||
|
value={[speed]}
|
||||||
|
onValueChange={(value: any) => {
|
||||||
|
OsuRenderer.setSpeed(value[0]);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
import { Vector2 } from "osu-classes";
|
import { Vector2 } from "osu-classes";
|
||||||
import p5 from "p5";
|
import p5 from "p5";
|
||||||
import { loadImageAsync } from "@/utils";
|
import { loadImageAsync } from "@/utils";
|
||||||
|
import { Md5 } from "ts-md5";
|
||||||
|
|
||||||
export class Drawer {
|
export class Drawer {
|
||||||
|
|
||||||
|
private static imageCache: Record<string, p5.Graphics> = {};
|
||||||
|
|
||||||
static images = {
|
static images = {
|
||||||
cursor: undefined as any as p5.Image,
|
cursor: undefined as any as p5.Image,
|
||||||
cursortrail: undefined as any as p5.Image,
|
cursortrail: undefined as any as p5.Image,
|
||||||
@ -128,6 +131,8 @@ export class Drawer {
|
|||||||
static drawSliderBody(origin: Vector2, path: Vector2[], radius: number) {
|
static drawSliderBody(origin: Vector2, path: Vector2[], radius: number) {
|
||||||
Drawer.p.push();
|
Drawer.p.push();
|
||||||
|
|
||||||
|
const cacheKey = Md5.hashStr(JSON.stringify(origin) + JSON.stringify(path) + JSON.stringify(radius));
|
||||||
|
if (!this.imageCache[cacheKey]) {
|
||||||
const g = Drawer.p.createGraphics(512 * 4, 384 * 4);
|
const g = Drawer.p.createGraphics(512 * 4, 384 * 4);
|
||||||
g.scale(2);
|
g.scale(2);
|
||||||
g.translate(512 - 256, 384 - 192);
|
g.translate(512 - 256, 384 - 192);
|
||||||
@ -167,12 +172,15 @@ export class Drawer {
|
|||||||
g.endShape();
|
g.endShape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.imageCache[cacheKey] = g;
|
||||||
|
}
|
||||||
Drawer.p.imageMode(Drawer.p.CORNER);
|
Drawer.p.imageMode(Drawer.p.CORNER);
|
||||||
Drawer.p.image(g, -256, -192, 512 * 2, 384 * 2);
|
Drawer.p.image(this.imageCache[cacheKey], -256, -192, 512 * 2, 384 * 2);
|
||||||
|
|
||||||
Drawer.p.pop();
|
Drawer.p.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static drawCursorPath(
|
static drawCursorPath(
|
||||||
path: {
|
path: {
|
||||||
position: Vector2;
|
position: Vector2;
|
||||||
|
|||||||
@ -20,6 +20,7 @@ export enum OsuRendererEvents {
|
|||||||
LOAD = "LOAD",
|
LOAD = "LOAD",
|
||||||
PLAY = "PLAY",
|
PLAY = "PLAY",
|
||||||
TIME = "TIME",
|
TIME = "TIME",
|
||||||
|
SPEED = "SPEED",
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OsuRendererBridge extends EventEmitter {
|
export class OsuRendererBridge extends EventEmitter {
|
||||||
@ -37,6 +38,7 @@ export class OsuRenderer {
|
|||||||
|
|
||||||
static event = new OsuRendererBridge();
|
static event = new OsuRendererBridge();
|
||||||
|
|
||||||
|
static speedMultiplier = 0.5;
|
||||||
static time: number = 0;
|
static time: number = 0;
|
||||||
static beatmap: StandardBeatmap;
|
static beatmap: StandardBeatmap;
|
||||||
static og_beatmap: StandardBeatmap;
|
static og_beatmap: StandardBeatmap;
|
||||||
@ -64,7 +66,7 @@ export class OsuRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.playing) {
|
if (this.playing) {
|
||||||
this.setTime(this.time + (Date.now() - this.lastRender));
|
this.setTime(this.time + ((Date.now() - this.lastRender) * this.speedMultiplier));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lastRender = Date.now();
|
this.lastRender = Date.now();
|
||||||
@ -189,6 +191,11 @@ export class OsuRenderer {
|
|||||||
this.event.emit(OsuRendererEvents.TIME);
|
this.event.emit(OsuRendererEvents.TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static setSpeed(speed: number) {
|
||||||
|
this.speedMultiplier = speed;
|
||||||
|
this.event.emit(OsuRendererEvents.SPEED);
|
||||||
|
}
|
||||||
|
|
||||||
private static renderObject(hitObject: StandardHitObject) {
|
private static renderObject(hitObject: StandardHitObject) {
|
||||||
if (hitObject instanceof Circle) {
|
if (hitObject instanceof Circle) {
|
||||||
this.renderCircle(hitObject);
|
this.renderCircle(hitObject);
|
||||||
@ -318,15 +325,6 @@ export class OsuRenderer {
|
|||||||
Drawer.drawSliderFollowPoint(sliderPos, hitObject.radius);
|
Drawer.drawSliderFollowPoint(sliderPos, hitObject.radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (GameplayAnalyzer.renderJudgements[hitObject.startTime]) {
|
|
||||||
// Drawer.setDrawingOpacity(opacity / 2);
|
|
||||||
|
|
||||||
// Drawer.drawCircleJudgement(
|
|
||||||
// hitObject.stackedStartPosition,
|
|
||||||
// hitObject.radius,
|
|
||||||
// GameplayAnalyzer.renderJudgements[hitObject.startTime]
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
Drawer.endDrawing();
|
Drawer.endDrawing();
|
||||||
return arScale;
|
return arScale;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,5 +52,10 @@ export class Renderer {
|
|||||||
time: OsuRenderer.time,
|
time: OsuRenderer.time,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
OsuRenderer.event.on(OsuRendererEvents.SPEED, () => {
|
||||||
|
state.setState({
|
||||||
|
speed: OsuRenderer.speedMultiplier,
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,6 +55,7 @@ export const state = create<{
|
|||||||
mods: IMod[] | null;
|
mods: IMod[] | null;
|
||||||
playing: boolean;
|
playing: boolean;
|
||||||
time: number;
|
time: number;
|
||||||
|
speed: number;
|
||||||
}>(() => ({
|
}>(() => ({
|
||||||
metadataEditorDialog: false,
|
metadataEditorDialog: false,
|
||||||
openDialog: false,
|
openDialog: false,
|
||||||
@ -69,6 +70,7 @@ export const state = create<{
|
|||||||
mods: null,
|
mods: null,
|
||||||
playing: false,
|
playing: false,
|
||||||
time: 0,
|
time: 0,
|
||||||
|
speed: 1
|
||||||
}));
|
}));
|
||||||
|
|
||||||
state.subscribe((newState) => {
|
state.subscribe((newState) => {
|
||||||
|
|||||||
@ -1899,6 +1899,11 @@ ts-interface-checker@^0.1.9:
|
|||||||
resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz"
|
resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz"
|
||||||
integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
|
integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
|
||||||
|
|
||||||
|
ts-md5@^1.3.1:
|
||||||
|
version "1.3.1"
|
||||||
|
resolved "https://registry.npmjs.org/ts-md5/-/ts-md5-1.3.1.tgz"
|
||||||
|
integrity sha512-DiwiXfwvcTeZ5wCE0z+2A9EseZsztaiZtGrtSaY5JOD7ekPnR/GoIVD5gXZAlK9Na9Kvpo9Waz5rW64WKAWApg==
|
||||||
|
|
||||||
tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0:
|
tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0:
|
||||||
version "2.6.2"
|
version "2.6.2"
|
||||||
resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz"
|
resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user