Show a Pan node as a one-knob device in cyan (#392)
After the Gain, the Pitch and the Mix, the Pan is the next node that is just one number. It now gets the same device in the graph instead of a row for its pan. - PAN_DEVICE: the Gain's 160x160 plate in cyan with one bipolar knob for Pan. The middle stands straight up, and the turn goes evenly to L and R, which are engraved at its ends like A and B on the Mix. - PAN_TAPER in hardwareView is 1, so left and right are heard alike. Device and unit test read the same constant. - PAN_ROW is exported from the core, so the knob has the node's range. - A linked Pan greys the knob, as for the Gain. - The test hook __gm.pan.panel returns the same shape as the Gain's. - No instrument preset uses a Pan, so no preset columns change. Tests: - Unit hardware-view: 17 tests, 2 new (the turn, and L and R inside the plate and clear of the screws). Counter-check: PAN_TAPER 2 turns the turn test red. - e2e 34 (melektaus-atx): 135 checks, 1 new. - Gate (melektaus-atx): 287 files, 4399 tests. - Pictures looked at: Gain, Pitch, Mix and Pan in a row, Pan at -0.35. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fe4e0d9f1a
commit
389d9555fa
8 files changed
+102
-12
No files matched your search
@@ -274,12 +274,13 @@ export function graphHooks({ state, editor }: HookContext) {
|
||||
},
|
||||
},
|
||||
/**
|
||||
* The panel a Gain node shows (#384), and a Pitch or a Mix (#390): whether it is shown and where,
|
||||
* The panel a Gain node shows (#384), a Pitch or a Mix (#390), a Pan (#392): whether it is shown and where,
|
||||
* its knob, the Mix's lever and the node's ports.
|
||||
*/
|
||||
gain: { panel: (nodeId: string) => knobPanel(nodeId) },
|
||||
pitch: { panel: (nodeId: string) => knobPanel(nodeId) },
|
||||
mix: { panel: (nodeId: string) => knobPanel(nodeId) },
|
||||
pan: { panel: (nodeId: string) => knobPanel(nodeId) },
|
||||
/**
|
||||
* The panel a Chip node shows in the instrument graph (#386): whether it is shown and where, its
|
||||
* knobs, which settings are idle, the picked wave, the lever, both screens and the node's ports.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* The devices with one big chrome knob, what their nodes show in the graph: the Gain (#384) on an
|
||||
* orange plate, the Pitch (#390) on a green one, and the Mix (#390) on a blue one with a lever for
|
||||
* its curve. All on the Compressor's plate (#379).
|
||||
* orange plate, the Pitch (#390) on a green one, the Mix (#390) on a blue one with a lever for
|
||||
* its curve, and the Pan (#392) on a cyan one. All on the Compressor's plate (#379).
|
||||
*/
|
||||
import { Graphics, type Text } from 'pixi.js';
|
||||
import { Knob, Widget } from '../../ui';
|
||||
@@ -9,9 +9,11 @@ import {
|
||||
GAIN_ROW,
|
||||
MIX_CURVE_ROW,
|
||||
MIX_ROW,
|
||||
PAN_ROW,
|
||||
PITCH_ROW,
|
||||
SoundFxGain,
|
||||
SoundFxMix,
|
||||
SoundFxPan,
|
||||
SoundFxPitch,
|
||||
} from '../../core/soundfx/nodes';
|
||||
import { drawPlate, engrave, INK, Lever, placeEngraving, type PlateLook } from './CompressorPanel';
|
||||
@@ -23,6 +25,7 @@ import {
|
||||
knobEnds,
|
||||
MIX_LAYOUT,
|
||||
MIX_PANEL,
|
||||
PAN_TAPER,
|
||||
PITCH_TAPER,
|
||||
} from './hardwareView';
|
||||
|
||||
@@ -114,6 +117,26 @@ export const MIX_DEVICE: KnobDevice = {
|
||||
},
|
||||
};
|
||||
|
||||
export const PAN_DEVICE: KnobDevice = {
|
||||
type: SoundFxPan.type,
|
||||
caption: 'PAN',
|
||||
row: PAN_ROW,
|
||||
taper: PAN_TAPER,
|
||||
bipolar: true,
|
||||
decimals: 2,
|
||||
plate: {
|
||||
stops: [
|
||||
[0, 0x8ff0ea],
|
||||
[0.5, 0x52d6cf],
|
||||
[1, 0x2fb5ae],
|
||||
],
|
||||
rim: 0x1f8a85,
|
||||
grain: 0x0e5c58,
|
||||
},
|
||||
arc: 0x07393a,
|
||||
ends: ['L', 'R'],
|
||||
};
|
||||
|
||||
export class KnobPanel extends Widget {
|
||||
private readonly plate = new Graphics();
|
||||
readonly knob: Knob;
|
||||
|
||||
@@ -96,6 +96,9 @@ export const GAIN_TAPER = 0.26;
|
||||
/** The Pitch's knob (#390), ±64 semitones round 0: an octave either way takes 43 % of a half turn. */
|
||||
export const PITCH_TAPER = 2;
|
||||
|
||||
/** The Pan's knob (#392), -1 to 1 round the middle: evenly, so left and right are heard alike. */
|
||||
export const PAN_TAPER = 1;
|
||||
|
||||
/** How much lower the Mix's knob sits than the Gain's, for its curve lever above it. */
|
||||
const MIX_LEVER_ROOM = 40;
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@ import { EnvelopeFace } from './EnvelopeFace';
|
||||
import { EqPanel } from './EqPanel';
|
||||
import { FilterPanel } from './FilterPanel';
|
||||
import { KnobFace } from './KnobFace';
|
||||
import { GAIN_DEVICE, MIX_DEVICE, PITCH_DEVICE } from './KnobPanel';
|
||||
import { GAIN_DEVICE, MIX_DEVICE, PAN_DEVICE, PITCH_DEVICE } from './KnobPanel';
|
||||
import { ReverbFace } from './ReverbFace';
|
||||
|
||||
/** The nodes drawn as a face of their own instead of rows (#380, #381, #384–#386, #388–#390), by type. */
|
||||
/** The nodes drawn as a face of their own instead of rows (#380, #381, #384–#386, #388–#390, #392), by type. */
|
||||
export function nodeFaceFor(state: EditorState, assetId: string, node: GraphNode): NodeFace | null {
|
||||
if (node.type === InstrumentChip.type) return new ChipFace(state, assetId, node.id);
|
||||
if (node.type === InstrumentEnvelope.type) return new EnvelopeFace(state, assetId, node.id);
|
||||
@@ -26,7 +26,9 @@ export function nodeFaceFor(state: EditorState, assetId: string, node: GraphNode
|
||||
if (node.type === SoundFxParametricEq.type)
|
||||
return new CurveFace(new EqPanel(state, true), assetId, node.id);
|
||||
if (node.type === SoundFxFilter.type) return new CurveFace(new FilterPanel(state, true), assetId, node.id);
|
||||
const knobbed = [GAIN_DEVICE, PITCH_DEVICE, MIX_DEVICE].find((device) => device.type === node.type);
|
||||
const knobbed = [GAIN_DEVICE, PITCH_DEVICE, MIX_DEVICE, PAN_DEVICE].find(
|
||||
(device) => device.type === node.type,
|
||||
);
|
||||
if (knobbed) return new KnobFace(state, assetId, node.id, knobbed);
|
||||
if (node.type === SoundFxReverb.type) return new ReverbFace(state, assetId, node.id);
|
||||
return null;
|
||||
|
||||
Reference in new issue
Block a user