@real-music-packages/web-core 0.43.0 → 0.44.1
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.
- package/dist/scene/index.d.ts +26 -1
- package/dist/scene/index.js +125 -0
- package/dist/scene/index.js.map +1 -1
- package/package.json +1 -1
package/dist/scene/index.d.ts
CHANGED
|
@@ -1773,4 +1773,29 @@ interface CompositeRhythmProps {
|
|
|
1773
1773
|
}
|
|
1774
1774
|
declare const compositeRhythmFactory: LayerFactory<CompositeRhythmProps>;
|
|
1775
1775
|
|
|
1776
|
-
|
|
1776
|
+
interface HandIndicatorProps {
|
|
1777
|
+
/** Top of the hand band, world px. Required — the caller owns this route's
|
|
1778
|
+
* vertical layout; this layer only draws at the given y. */
|
|
1779
|
+
y: number;
|
|
1780
|
+
/** Band height, world px. Default 60. */
|
|
1781
|
+
height?: number;
|
|
1782
|
+
/** Hand colours — the SAME tokens the keyboard/composite-rhythm layers use.
|
|
1783
|
+
* Default R = theme.accent, L = theme.gold. */
|
|
1784
|
+
handColors?: HandColors;
|
|
1785
|
+
/** How fast a hand fades from lit back to its resting outline after its
|
|
1786
|
+
* last active note ends, ms. Default 200 (the "quickly" in ~150-250ms). */
|
|
1787
|
+
fadeMs?: number;
|
|
1788
|
+
/** Icon size, px (roughly the glyph's bounding box). Default height*0.78. */
|
|
1789
|
+
size?: number;
|
|
1790
|
+
/** LH icon x, fraction of safeBox width from its left edge. Default 0.26
|
|
1791
|
+
* (under the lower/bass register). */
|
|
1792
|
+
leftXFrac?: number;
|
|
1793
|
+
/** RH icon x, fraction of safeBox width from its left edge. Default 0.74
|
|
1794
|
+
* (under the upper/treble register). */
|
|
1795
|
+
rightXFrac?: number;
|
|
1796
|
+
/** Baseline (resting/unlit) outline alpha. Default 0.32. */
|
|
1797
|
+
restAlpha?: number;
|
|
1798
|
+
}
|
|
1799
|
+
declare const handIndicatorFactory: LayerFactory<HandIndicatorProps>;
|
|
1800
|
+
|
|
1801
|
+
export { type Affine, AudioClock, type AudioEvent, type BackgroundProps, type BeatGridOpts, type BeatPulseProps, type BeatTick, type BrandingProps, type BufferFactory, type BuildSceneOpts, type BuiltScene, type CameraState, type CaptionCue, type CaptionProps, type CaptionScript, type CaptionStyle, type ChordRibbonProps, type ChordSpan, type CircleOfFifthsProps, type CirclePoint, type ClickTrackOpts, type ColorBy, type CompositeRhythmProps, type ContourPlot, type ContourPoint, type CountInOpts, type CountdownProps, type CountingTrackProps, type CtaProps, DEFAULT_FUNCTION_COLORS, type DegreeLabel, type DegreeLabelsProps, type DroneOpts, type DuckWindow, type Easing, type EndCardProps, type ExtendedDemoOpts, FIFTHS_MAJOR, FIFTHS_MINOR, type FallingKeyboardDemoOpts, type FallingNotesProps, type FretboardProps, type FunctionColors, type FunctionalHarmonyProps, type GateError, type GateInput, type HandColors, type HandIndicatorProps, type HarmonicFunction, type HarmonyMode, type HighlightRegion, type HookProps, type ImageRevealMode, type ImageRevealProps, type IntervalArcsProps, type KaraokeCaptionProps, type KaraokeWord, type KeyRect, type KeyboardLayout, type KeyboardLayoutOpts, type KeyboardProps, type KineticMode, type KineticTextProps, type LabelMode, LayerFactory, type McqCardProps, type NotationEngraving, NotationLayout, type NotationProps, type OutputProbe, PIANO_HIGH, PIANO_LOW, type ParticleBurstProps, type PitchContourProps, type Placement, type PortraitProps, type ProgressRingProps, type PromoCardsDemoOpts, type PulseStyle, type Quiz, type QuizOption, type QuizPhase, type RadialSpectrumProps, type RayEndpoints, type RecordSceneSpecOpts, type Rect, RenderCtx, type ResolvedSegment, type RevealEasing, type RevealProps, SCALE_INTERVALS, type SafeGuidesProps, type ScaleHighlightProps, type SceneSpec, type ScheduleTarget, Score, ScoreFromMusicXMLOpts, ScoreNote, type ScrollCursorProps, type Section, type SectionMinimapProps, type SegmentAudio, type SegmentAudioCtx, type SegmentTransition, type SpecLayer, type StaffKeyboardRayProps, type StatCounterProps, TempoMap, type TensionGraphProps, type TensionPoint, type TextureProps, type TimeAnchor, type TimelineSegment, activeChord, activeCue, activeSection, animatedSlot, applySchedule, applyToContext, assertGate, ballArc, ballX, beatGrid, beatPhase, beatPulseFactory, blackKeys, bpmOf, brandingFactory, buildScene, cameraForFollow, cameraTransform, chordRibbonFactory, circleOfFifthsDemoSpec, circleOfFifthsFactory, clamp, clickTrackSchedule, compositeRhythmFactory, contourMinimapDemoSpec, contourPoints, contourPolyline, countInLeadSec, countInSchedule, countdownFactory, countdownRemaining, countdownSeconds, countingDegreeDemoSpec, countingTrackFactory, ctaFactory, cueOpacity, degreeLabel, degreeLabelsFactory, dotAt, drawCaption, drawHighlight, droneSchedule, duckGainAt, easeIn, easeInOut, easeOut, endCardFactory, fallingKeyboardDemoScore, fallingKeyboardDemoSpec, fallingNotesFactory, followSrcBox, fracSlotPoint, frameRect, fretboardFactory, functionColor, functionalHarmonyFactory, getKeyboardLayout, getLayerFactory, getNotationEngraving, handIndicatorFactory, harmonyDemoSpec, highlightIntensity, hookFactory, identityCamera, imageRevealFactory, inRange, intervalArcsFactory, invLerp, isBlackKey, karaokeCaptionFactory, kenBurns, keyCenterX, keyColumnWidth, keyRect, keySlot, keyboardFactory, keyboardLayout, kineticTextFactory, lerp, lerpCamera, linear, mapBoxThroughLayout, mcqCardFactory, mcqDemoSpec, measureSpans, timeToX as minimapTimeToX, msPerBeat, notationFactory, noteColor, noteSetXRange, parseKey, parseTimeSig, particleBurstFactory, pcToSlot, pitchAt, pitchContourFactory, pitchRange, portraitFactory, progress01, progressRingFactory, projectPoint, promoCardsDemoSpec, pulseAt, quizPhase, radialSpectrumFactory, rayEndpoints, rayPointAt, recordSceneSpec, registerLayer, registeredKeys, resolveAnchor, resolveKeyboardLayout, resolveTimeline, revealFactory, revealProgress, runGate, safeGuidesFactory, scaleHighlightFactory, scorePitchSpan, scrollCursorFactory, sectionMinimapFactory, setFollowLayoutProvider, setKeyboardLayout, setNotationEngraving, slotAngle, slotPc, slotPoint, staffAnchor, staffKeyboardRayFactory, staffRayDemoSpec, statCounterFactory, tensionGraphFactory, textureFactory, transitionProgress, validateChordTrack, validateQuiz, validateSections, visualTimelineMs, whiteKeys, worldToViewport };
|
package/dist/scene/index.js
CHANGED
|
@@ -4585,6 +4585,129 @@ var compositeRhythmFactory = {
|
|
|
4585
4585
|
}
|
|
4586
4586
|
};
|
|
4587
4587
|
|
|
4588
|
+
// src/scene/layers/handIndicator.ts
|
|
4589
|
+
function activeOpacity(notes, tMs, fadeMs) {
|
|
4590
|
+
let lastEnd = -Infinity;
|
|
4591
|
+
for (const n of notes) {
|
|
4592
|
+
const end = n.onsetMs + n.durMs;
|
|
4593
|
+
if (tMs >= n.onsetMs && tMs < end) return 1;
|
|
4594
|
+
if (end <= tMs && end > lastEnd) lastEnd = end;
|
|
4595
|
+
}
|
|
4596
|
+
if (lastEnd === -Infinity) return 0;
|
|
4597
|
+
const dt = tMs - lastEnd;
|
|
4598
|
+
if (dt >= fadeMs) return 0;
|
|
4599
|
+
return 1 - dt / fadeMs;
|
|
4600
|
+
}
|
|
4601
|
+
function roundedPath2(c, x, y, w, h, r) {
|
|
4602
|
+
c.beginPath();
|
|
4603
|
+
const rr = c.roundRect;
|
|
4604
|
+
if (typeof rr === "function") {
|
|
4605
|
+
rr.call(c, x, y, w, h, r);
|
|
4606
|
+
return;
|
|
4607
|
+
}
|
|
4608
|
+
c.rect(x, y, w, h);
|
|
4609
|
+
}
|
|
4610
|
+
function drawHandGlyph(c, cx, cy, size, mirror, mode) {
|
|
4611
|
+
const paint = () => {
|
|
4612
|
+
if (mode === "fill") c.fill();
|
|
4613
|
+
else c.stroke();
|
|
4614
|
+
};
|
|
4615
|
+
const palmW = size * 0.66, palmH = size * 0.56;
|
|
4616
|
+
const px0 = cx - palmW / 2, py0 = cy - palmH * 0.1;
|
|
4617
|
+
roundedPath2(c, px0, py0, palmW, palmH, palmW * 0.32);
|
|
4618
|
+
paint();
|
|
4619
|
+
const fingerW = palmW * 0.17;
|
|
4620
|
+
const lens = [0.36, 0.46, 0.42, 0.32];
|
|
4621
|
+
for (let i = 0; i < 4; i++) {
|
|
4622
|
+
const fx = px0 + palmW * (0.12 + i * 0.25) - fingerW / 2;
|
|
4623
|
+
const fLen = size * lens[i];
|
|
4624
|
+
const fy = py0 - fLen + size * 0.06;
|
|
4625
|
+
roundedPath2(c, fx, fy, fingerW, fLen, fingerW / 2);
|
|
4626
|
+
paint();
|
|
4627
|
+
}
|
|
4628
|
+
const thumbW = palmW * 0.24, thumbLen = size * 0.3;
|
|
4629
|
+
const sign = mirror ? -1 : 1;
|
|
4630
|
+
c.save();
|
|
4631
|
+
c.translate(cx + sign * palmW * 0.42, py0 + palmH * 0.32);
|
|
4632
|
+
c.rotate(sign * 0.55);
|
|
4633
|
+
roundedPath2(c, -thumbW / 2, 0, thumbW, thumbLen, thumbW / 2);
|
|
4634
|
+
paint();
|
|
4635
|
+
c.restore();
|
|
4636
|
+
}
|
|
4637
|
+
function handIndicatorLayer() {
|
|
4638
|
+
let y = 0;
|
|
4639
|
+
let height = 60;
|
|
4640
|
+
let hands = { R: "#7b2436", L: "#c8a55b" };
|
|
4641
|
+
let fadeMs = 200;
|
|
4642
|
+
let size = 0;
|
|
4643
|
+
let leftXFrac = 0.26;
|
|
4644
|
+
let rightXFrac = 0.74;
|
|
4645
|
+
let restAlpha = 0.32;
|
|
4646
|
+
let lNotes = [];
|
|
4647
|
+
let rNotes = [];
|
|
4648
|
+
return {
|
|
4649
|
+
key: "hand-indicator",
|
|
4650
|
+
init(ctx, props) {
|
|
4651
|
+
y = props.y;
|
|
4652
|
+
height = props.height ?? 60;
|
|
4653
|
+
hands = props.handColors ?? { R: ctx.theme.accent, L: ctx.theme.gold };
|
|
4654
|
+
fadeMs = props.fadeMs ?? 200;
|
|
4655
|
+
size = props.size ?? height * 0.78;
|
|
4656
|
+
leftXFrac = props.leftXFrac ?? 0.26;
|
|
4657
|
+
rightXFrac = props.rightXFrac ?? 0.74;
|
|
4658
|
+
restAlpha = props.restAlpha ?? 0.32;
|
|
4659
|
+
const notes = ctx.score?.notes ?? [];
|
|
4660
|
+
lNotes = notes.filter((n) => n.hand === "L").map((n) => ({ onsetMs: n.onsetMs, durMs: n.durMs }));
|
|
4661
|
+
rNotes = notes.filter((n) => n.hand === "R").map((n) => ({ onsetMs: n.onsetMs, durMs: n.durMs }));
|
|
4662
|
+
},
|
|
4663
|
+
draw(ctx, tMs) {
|
|
4664
|
+
const c = ctx.ctx2d;
|
|
4665
|
+
const sb = ctx.safeBox;
|
|
4666
|
+
const cy = y + height / 2;
|
|
4667
|
+
const drawHand = (frac, color, notes, mirror) => {
|
|
4668
|
+
const cx = sb.left + sb.w * frac;
|
|
4669
|
+
const op = activeOpacity(notes, tMs, fadeMs);
|
|
4670
|
+
c.save();
|
|
4671
|
+
c.globalAlpha = restAlpha;
|
|
4672
|
+
c.strokeStyle = color;
|
|
4673
|
+
c.lineWidth = Math.max(1.5, size * 0.035);
|
|
4674
|
+
drawHandGlyph(c, cx, cy, size, mirror, "stroke");
|
|
4675
|
+
c.restore();
|
|
4676
|
+
if (op > 0.01) {
|
|
4677
|
+
c.save();
|
|
4678
|
+
c.globalAlpha = op;
|
|
4679
|
+
c.fillStyle = color;
|
|
4680
|
+
drawHandGlyph(c, cx, cy, size, mirror, "fill");
|
|
4681
|
+
c.restore();
|
|
4682
|
+
}
|
|
4683
|
+
};
|
|
4684
|
+
drawHand(leftXFrac, hands.L, lNotes, true);
|
|
4685
|
+
drawHand(rightXFrac, hands.R, rNotes, false);
|
|
4686
|
+
},
|
|
4687
|
+
dispose() {
|
|
4688
|
+
lNotes = [];
|
|
4689
|
+
rNotes = [];
|
|
4690
|
+
}
|
|
4691
|
+
};
|
|
4692
|
+
}
|
|
4693
|
+
var handIndicatorFactory = {
|
|
4694
|
+
key: "hand-indicator",
|
|
4695
|
+
create: handIndicatorLayer,
|
|
4696
|
+
validateProps(props) {
|
|
4697
|
+
if (props == null || typeof props !== "object") return ["hand-indicator: props must be an object"];
|
|
4698
|
+
const p = props;
|
|
4699
|
+
const errs = [];
|
|
4700
|
+
if (typeof p.y !== "number") errs.push("hand-indicator.y is required and must be a number");
|
|
4701
|
+
if (p.height != null && (typeof p.height !== "number" || p.height <= 0)) errs.push("hand-indicator.height must be a positive number");
|
|
4702
|
+
if (p.fadeMs != null && (typeof p.fadeMs !== "number" || p.fadeMs <= 0)) errs.push("hand-indicator.fadeMs must be a positive number");
|
|
4703
|
+
if (p.size != null && (typeof p.size !== "number" || p.size <= 0)) errs.push("hand-indicator.size must be a positive number");
|
|
4704
|
+
if (p.leftXFrac != null && typeof p.leftXFrac !== "number") errs.push("hand-indicator.leftXFrac must be a number");
|
|
4705
|
+
if (p.rightXFrac != null && typeof p.rightXFrac !== "number") errs.push("hand-indicator.rightXFrac must be a number");
|
|
4706
|
+
if (p.restAlpha != null && (typeof p.restAlpha !== "number" || p.restAlpha < 0 || p.restAlpha > 1)) errs.push("hand-indicator.restAlpha must be a number in [0,1]");
|
|
4707
|
+
return errs;
|
|
4708
|
+
}
|
|
4709
|
+
};
|
|
4710
|
+
|
|
4588
4711
|
// src/scene/registry.ts
|
|
4589
4712
|
var REGISTRY = /* @__PURE__ */ new Map();
|
|
4590
4713
|
function registerLayer(factory) {
|
|
@@ -4635,6 +4758,7 @@ registerLayer(statCounterFactory);
|
|
|
4635
4758
|
registerLayer(endCardFactory);
|
|
4636
4759
|
registerLayer(imageRevealFactory);
|
|
4637
4760
|
registerLayer(compositeRhythmFactory);
|
|
4761
|
+
registerLayer(handIndicatorFactory);
|
|
4638
4762
|
|
|
4639
4763
|
// src/scene/audioLayers.ts
|
|
4640
4764
|
function countInSchedule(opts) {
|
|
@@ -5452,6 +5576,7 @@ export {
|
|
|
5452
5576
|
getKeyboardLayout,
|
|
5453
5577
|
getLayerFactory,
|
|
5454
5578
|
getNotationEngraving,
|
|
5579
|
+
handIndicatorFactory,
|
|
5455
5580
|
harmonyDemoSpec,
|
|
5456
5581
|
highlightIntensity,
|
|
5457
5582
|
hookFactory,
|