import {AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core'; import {getEvents} from "./decode-replay"; import {DecimalPipe, JsonPipe, NgForOf} from "@angular/common"; import {ReplayService} from "./replay-service"; import {FormsModule} from "@angular/forms"; import {parseHitObjects} from "./decode-beatmap"; import {processReplay} from "./process-replay"; import {ReplayViewerData} from "../../../app/replays"; export enum KeyPress { M1 = 1, M2 = 2, K1 = 5, K2 = 10, Smoke = 16, } export interface ReplayEvent { /** * Time in milliseconds since the previous action */ timeDelta: number; /** * x-coordinate of the cursor from 0 - 512 */ x: number; /** * y-coordinate of the cursor from 0 - 384 */ y: number; /** * Keys being pressed. */ keys: KeyPress[]; } @Component({ selector: 'app-replay-viewer', standalone: true, imports: [ JsonPipe, FormsModule, DecimalPipe, NgForOf ], templateUrl: './replay-viewer.component.html', styleUrl: './replay-viewer.component.css' }) export class ReplayViewerComponent implements OnInit, AfterViewInit { @ViewChild('replayCanvas') replayCanvas!: ElementRef; private ctx!: CanvasRenderingContext2D; @Input() replayViewerData!: ReplayViewerData; // TODO: Calculate AudioLeadIn // TODO: Hard-Rock, DT, Easy // TODO: Cursor trail and where keys are pressed // TODO: Button for -100 ms, +100 ms, etc (precise seeking) (or keyboard shortcuts) // TODO: UR bar // Todo: Customizable speed // TODO: Customizable zoom // TODO: Fullscreen mode // TODO: Hit/Miss, Combo, Accuracy // TODO: Compare two replays for similarity (different cursor color) constructor(public replayService: ReplayService) { } ngOnInit() { this.replayService.loadReplay(this.replayViewerData); } ngAfterViewInit() { this.ctx = this.replayCanvas.nativeElement.getContext('2d')!; this.replayService.setCanvasElement(this.replayCanvas); this.replayService.setCanvasContext(this.ctx); this.replayService.start(); // Start the animation loop } togglePlayPause() { if (this.replayService.getIsPlaying()) { this.replayService.pause(); } else { this.replayService.start(); } } seek(time: number) { this.replayService.seek(time); if (!this.replayService.getIsPlaying()) { // Redraw the canvas for the new current time without resuming playback } } }