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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | 1x 51x 15x 6x 4x 4x 89x 89x 11x 11x 11x 11x 11x 188x 188x 9x 3x 3x 3x 3x 3x 3x 3x 3x 3x 5x 5x 5x 5x 4x 4x 4x 4x 4x 4x 4x 4x 12x 4x 4x 4x 4x 4x 3x 3x 3x | import { Slice } from "../slice";
import { SelectionSlice } from "./selection-slice";
import { ColumnsSlice } from "./columns-slice";
import { EVENT, BPM_CHANGE, TIME_SIGNATURE, NOTE, LEVEL_REF } from "../components";
import type { Entity } from "../../entity-manager";
export class BoxSelectionSlice extends Slice {
static readonly sliceKey = "box-selection";
private boxSelection = {
active: false,
startCol: 0,
endCol: 0,
startPulse: 0,
endPulse: 0,
};
isActive(): boolean {
return this.boxSelection.active;
}
start(colIndex: number, pulse: number): void {
this.boxSelection = {
active: true,
startCol: colIndex,
endCol: colIndex,
startPulse: pulse,
endPulse: pulse,
};
}
update(colIndex: number, pulse: number): void {
this.boxSelection.endCol = colIndex;
this.boxSelection.endPulse = pulse;
}
isInBox(pulse: number, colIndex: number): boolean {
const box = this.boxSelection;
if (!box.active) return false;
const minCol = Math.min(box.startCol, box.endCol);
const maxCol = Math.max(box.startCol, box.endCol);
const minPulse = Math.min(box.startPulse, box.endPulse);
const maxPulse = Math.max(box.startPulse, box.endPulse);
return pulse >= minPulse && pulse <= maxPulse && colIndex >= minCol && colIndex <= maxCol;
}
getBoxRect(): { minCol: number; maxCol: number; minPulse: number; maxPulse: number } | null {
const box = this.boxSelection;
if (!box.active) return null;
return {
minCol: Math.min(box.startCol, box.endCol),
maxCol: Math.max(box.startCol, box.endCol),
minPulse: Math.min(box.startPulse, box.endPulse),
maxPulse: Math.max(box.startPulse, box.endPulse),
};
}
finalize(entities: Entity[]): Set<string> {
const box = this.boxSelection;
Iif (!box.active) return new Set();
const minCol = Math.min(box.startCol, box.endCol);
const maxCol = Math.max(box.startCol, box.endCol);
const minPulse = Math.min(box.startPulse, box.endPulse);
const maxPulse = Math.max(box.startPulse, box.endPulse);
const columns = this.ctx.get(ColumnsSlice).$columns.get();
const next = new Set(this.ctx.get(SelectionSlice).$selection.get());
for (const entity of entities) {
const event = entity.components[EVENT.key];
Iif (!event) continue;
const pulse = event.y;
if (pulse < minPulse || pulse > maxPulse) continue;
let colIndex = -1;
const note = entity.components[NOTE.key];
const levelRef = entity.components[LEVEL_REF.key];
Iif (note && levelRef) {
for (let i = 0; i < columns.length; i++) {
const col = columns[i]!;
if (col.levelId === levelRef.levelId && col.laneIndex === note.lane) {
colIndex = i;
break;
}
}
}
Eif (colIndex === -1) {
const bpm = entity.components[BPM_CHANGE.key];
Eif (bpm) {
for (let i = 0; i < columns.length; i++) {
if (columns[i]!.id === "bpm") {
colIndex = i;
break;
}
}
}
}
Iif (colIndex === -1) {
const ts = entity.components[TIME_SIGNATURE.key];
if (ts) {
for (let i = 0; i < columns.length; i++) {
if (columns[i]!.id === "time-sig") {
colIndex = i;
break;
}
}
}
}
Eif (colIndex >= minCol && colIndex <= maxCol) {
next.add(entity.id);
}
}
this.boxSelection = { active: false, startCol: 0, endCol: 0, startPulse: 0, endPulse: 0 };
this.ctx.get(SelectionSlice).$selection.set(next);
return next;
}
}
|