All files / src/packlets/editor-core/slices timing-slice.ts

93.54% Statements 29/31
68.18% Branches 15/22
100% Functions 8/8
100% Lines 29/29

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69                  1x   51x 51x     51x       216x 216x 216x 144x     72x   72x     25x 25x 25x     25x 25x 25x         8x   72x     7x 7x 7x     7x 7x 7x           2x   72x 72x 72x 72x      
import { Slice } from "../slice";
import type { EditorContext } from "../editor-context";
import { ProjectSlice } from "./project-slice";
import { ChartSlice } from "./chart-slice";
import { createTimingEngine } from "../../timing-engine";
import type { TimingEngine } from "../../timing-engine";
import { EVENT, BPM_CHANGE, TIME_SIGNATURE, CHART_REF } from "../components";
 
export class TimingSlice extends Slice {
  static readonly sliceKey = "timing";
 
  private cache: TimingEngine | null = null;
  private cacheVersion = 0;
 
  constructor(ctx: EditorContext) {
    super(ctx);
  }
 
  getTimingEngine(): TimingEngine {
    const em = this.ctx.get(ProjectSlice).entityManager;
    const currentVersion = em.getMutationVersion();
    if (this.cache && this.cacheVersion === currentVersion) {
      return this.cache;
    }
 
    const chartId = this.ctx.get(ChartSlice).$selectedChartId.get();
 
    const bpmChanges = em
      .entitiesWithComponent(BPM_CHANGE)
      .filter((entity) => {
        Iif (!chartId) return true;
        const ref = em.getComponent(entity, CHART_REF);
        return !ref || ref.chartId === chartId;
      })
      .map((entity) => {
        const event = em.getComponent(entity, EVENT);
        const bpm = em.getComponent(entity, BPM_CHANGE);
        return {
          pulse: event?.y ?? 0,
          bpm: bpm?.bpm ?? 60,
        };
      })
      .sort((a, b) => a.pulse - b.pulse);
 
    const timeSignatures = em
      .entitiesWithComponent(TIME_SIGNATURE)
      .filter((entity) => {
        Iif (!chartId) return true;
        const ref = em.getComponent(entity, CHART_REF);
        return !ref || ref.chartId === chartId;
      })
      .map((entity) => {
        const event = em.getComponent(entity, EVENT);
        const ts = em.getComponent(entity, TIME_SIGNATURE);
        return {
          pulse: event?.y ?? 0,
          numerator: ts?.numerator ?? 4,
          denominator: ts?.denominator ?? 4,
        };
      })
      .sort((a, b) => a.pulse - b.pulse);
 
    const engine = createTimingEngine(bpmChanges, timeSignatures);
    this.cache = engine;
    this.cacheVersion = currentVersion;
    return engine;
  }
}