forked from flow/vue3js-app-proposal-for-sdk-claude
Simplify: remove dead code and redundancy across vue app
- Delete ObjectBasic (defined, never imported)
- ObjectShort: remove unused node prop
- exporter: export stressorToString; use in patchBarMeta (removes inline duplicate)
- PaneFO: import stressorToString from exporter; extract H4 style constant,
shapeSection() helper, instrOnChange() helper; remove apply param from
makeChangeHandler (was always () => markDirty()); remove unnecessary ?.
on always-initialized arrays (variations, labelSpecs, subvariations)
- PaneSubObjects: explicit hasChildren on all item kinds; bars at score
level get hasChildren based on voices; remove stale kind-list fallback
- ast-parser coerce(): remove unreachable s.trim() check ('' handled above)
- PaneCP: fix post-export synthesisStatus reset to use real field names
This commit is contained in:
parent
9eb4add695
commit
1706404b7e
@ -7,7 +7,7 @@ function coerce(s) {
|
|||||||
if (s === 'False' || s === 'N' || s === 'off' || s === 'false') return false;
|
if (s === 'False' || s === 'N' || s === 'off' || s === 'false') return false;
|
||||||
if (s === '') return s;
|
if (s === '') return s;
|
||||||
const n = Number(s);
|
const n = Number(s);
|
||||||
if (!isNaN(n) && s.trim() !== '') return n;
|
if (!isNaN(n)) return n;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +0,0 @@
|
|||||||
import { h } from 'vue';
|
|
||||||
|
|
||||||
// Inline identifier + a few key props — used for list rows.
|
|
||||||
export const ObjectBasic = {
|
|
||||||
props: ['label', 'meta'], // meta: array of {key, value} pairs
|
|
||||||
setup(props) {
|
|
||||||
return () => h('div', { class: 'se-object-label' }, [
|
|
||||||
h('strong', null, props.label),
|
|
||||||
...(props.meta ?? []).map(({ key, value }) =>
|
|
||||||
h('span', { style: 'color:#888;margin-left:0.5rem;font-size:0.8em' },
|
|
||||||
`${key}=${value}`)
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -2,7 +2,7 @@ import { h } from 'vue';
|
|||||||
|
|
||||||
// One-line summary row with a drill-down chevron.
|
// One-line summary row with a drill-down chevron.
|
||||||
export const ObjectShort = {
|
export const ObjectShort = {
|
||||||
props: ['node', 'label', 'typeTag', 'focused', 'hasChildren'],
|
props: ['label', 'typeTag', 'focused', 'hasChildren'],
|
||||||
emits: ['focus', 'drillDown'],
|
emits: ['focus', 'drillDown'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
return () => h('li', {
|
return () => h('li', {
|
||||||
|
|||||||
@ -49,7 +49,7 @@ export const PaneCP = {
|
|||||||
props.store.rawScoreText = raw;
|
props.store.rawScoreText = raw;
|
||||||
const patched = patchScore(raw, props.store.scoreModel.instruments, props.store.scoreModel.bars);
|
const patched = patchScore(raw, props.store.scoreModel.instruments, props.store.scoreModel.bars);
|
||||||
await putScoreText(patched, props.store.credentials);
|
await putScoreText(patched, props.store.credentials);
|
||||||
props.store.synthesisStatus = { frozen: false, progress: 0 };
|
props.store.synthesisStatus = { frozen: false, currently_rendered_notes: 0, notes_in_total: 0 };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
exportError.value = e.message;
|
exportError.value = e.message;
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@ -3,11 +3,9 @@ import { ObjectExtended } from './ObjectExtended.js';
|
|||||||
import { EnvelopeEditor } from './EnvelopeEditor.js';
|
import { EnvelopeEditor } from './EnvelopeEditor.js';
|
||||||
import { ShapeEditor } from './ShapeEditor.js';
|
import { ShapeEditor } from './ShapeEditor.js';
|
||||||
import { LinkedInstrumentModal } from './LinkedInstrumentModal.js';
|
import { LinkedInstrumentModal } from './LinkedInstrumentModal.js';
|
||||||
|
import { stressorToString } from '../exporter.js';
|
||||||
|
|
||||||
function stressorToString(s) {
|
const H4 = { style: 'margin:0 0 0.5rem' };
|
||||||
if (!s?.groups?.length) return '';
|
|
||||||
return s.groups.map(g => g.join(',')).join(';');
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseStressor(str) {
|
function parseStressor(str) {
|
||||||
const groups = str.split(';').map(seg =>
|
const groups = str.split(';').map(seg =>
|
||||||
@ -27,38 +25,42 @@ function scoreInfoFields(info) {
|
|||||||
|
|
||||||
function instrFields(instr) {
|
function instrFields(instr) {
|
||||||
return [
|
return [
|
||||||
{ key: 'name', value: instr.name, editable: false },
|
{ key: 'name', value: instr.name, editable: false },
|
||||||
{ key: 'linked', value: instr.isLinked, editable: false, type: 'boolean' },
|
{ key: 'linked', value: instr.isLinked, editable: false, type: 'boolean' },
|
||||||
{ key: 'NOT_CHANGED_SINCE', value: instr.notChangedSince ?? '—', editable: false },
|
{ key: 'NOT_CHANGED_SINCE', value: instr.notChangedSince ?? '—', editable: false },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function variationFields(v) {
|
function variationFields(v) {
|
||||||
return [
|
return [{ key: 'depends_on', value: v.dependsOn ?? '—', editable: true }];
|
||||||
{ key: 'depends_on', value: v.dependsOn ?? '—', editable: true },
|
}
|
||||||
];
|
|
||||||
|
function shapeSection(label, shape, onChange) {
|
||||||
|
if (!shape) return null;
|
||||||
|
return h('div', { style: 'margin-top:0.5rem' }, [
|
||||||
|
h('strong', null, label),
|
||||||
|
h(ShapeEditor, { shape, onChange }),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PaneFO = {
|
export const PaneFO = {
|
||||||
props: ['store'],
|
props: ['store'],
|
||||||
setup(props) {
|
setup(props) {
|
||||||
// Pending edit held while the linked-instrument modal is shown.
|
const pendingEdit = ref(null); // { instr, undo? }
|
||||||
const pendingEdit = ref(null); // { instr, apply: fn }
|
|
||||||
|
|
||||||
function focused() {
|
function focused() {
|
||||||
const fp = props.store.focusPath;
|
const fp = props.store.focusPath;
|
||||||
return fp.length ? fp[fp.length - 1] : null;
|
return fp.length ? fp[fp.length - 1] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a change handler that intercepts the first edit to a linked
|
// Intercepts the first edit to a linked instrument:
|
||||||
// instrument and shows the embed-or-discard modal before applying it.
|
// shows embed-or-discard modal before committing. `info.undo`
|
||||||
// `info` may carry { undo } forwarded from ShapeEditor / EnvelopeEditor.
|
// (forwarded from ShapeEditor/EnvelopeEditor) reverts the mutation on discard.
|
||||||
function makeChangeHandler(instr, apply) {
|
function makeChangeHandler(instr) {
|
||||||
return (info) => {
|
return (info) => {
|
||||||
if (instr.isLinked && !instr.isDirty) {
|
if (instr.isLinked && !instr.isDirty) {
|
||||||
pendingEdit.value = { instr, apply, undo: info?.undo };
|
pendingEdit.value = { instr, undo: info?.undo };
|
||||||
} else {
|
} else {
|
||||||
apply();
|
|
||||||
instr.isDirty = true;
|
instr.isDirty = true;
|
||||||
props.store.markDirty();
|
props.store.markDirty();
|
||||||
}
|
}
|
||||||
@ -69,7 +71,6 @@ export const PaneFO = {
|
|||||||
instr.name = instr.name.split('/').pop();
|
instr.name = instr.name.split('/').pop();
|
||||||
instr.isLinked = false;
|
instr.isLinked = false;
|
||||||
instr.isDirty = true;
|
instr.isDirty = true;
|
||||||
pendingEdit.value.apply();
|
|
||||||
pendingEdit.value = null;
|
pendingEdit.value = null;
|
||||||
props.store.markDirty();
|
props.store.markDirty();
|
||||||
}
|
}
|
||||||
@ -79,6 +80,12 @@ export const PaneFO = {
|
|||||||
pendingEdit.value = null;
|
pendingEdit.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function instrOnChange(instr) {
|
||||||
|
return instr
|
||||||
|
? makeChangeHandler(instr)
|
||||||
|
: () => props.store.markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const node = focused();
|
const node = focused();
|
||||||
const children = [];
|
const children = [];
|
||||||
@ -87,7 +94,7 @@ export const PaneFO = {
|
|||||||
const model = props.store.scoreModel;
|
const model = props.store.scoreModel;
|
||||||
if (!model) return h('div', { class: 'se-fo-pane' }, 'No score loaded');
|
if (!model) return h('div', { class: 'se-fo-pane' }, 'No score loaded');
|
||||||
return h('div', { class: 'se-fo-pane' }, [
|
return h('div', { class: 'se-fo-pane' }, [
|
||||||
h('h4', { style: 'margin:0 0 0.5rem' }, 'Score'),
|
h('h4', H4, 'Score'),
|
||||||
h(ObjectExtended, {
|
h(ObjectExtended, {
|
||||||
fields: scoreInfoFields(model.info),
|
fields: scoreInfoFields(model.info),
|
||||||
onChange: ({ key, value }) => {
|
onChange: ({ key, value }) => {
|
||||||
@ -101,22 +108,18 @@ export const PaneFO = {
|
|||||||
|
|
||||||
if (node.type === 'instrument') {
|
if (node.type === 'instrument') {
|
||||||
children.push(
|
children.push(
|
||||||
h('h4', { style: 'margin:0 0 0.5rem' }, `Instrument: ${node.name}`),
|
h('h4', H4, `Instrument: ${node.name}`),
|
||||||
h(ObjectExtended, { fields: instrFields(node), onChange: null }),
|
h(ObjectExtended, { fields: instrFields(node), onChange: null }),
|
||||||
);
|
);
|
||||||
} else if (node.type === 'variation') {
|
} else if (node.type === 'variation') {
|
||||||
// Find the ancestor instrument for linked-instrument gating.
|
const instr = props.store.scoreModel.instruments.find(
|
||||||
const instr = props.store.scoreModel?.instruments.find(
|
i => i.variations.includes(node) ||
|
||||||
i => i.variations?.includes(node) ||
|
i.variations.some(v => v.subvariations.includes(node))
|
||||||
i.variations?.some(v => v.subvariations?.includes(node))
|
|
||||||
) ?? null;
|
) ?? null;
|
||||||
|
const onChange = instrOnChange(instr);
|
||||||
const onChange = instr
|
|
||||||
? makeChangeHandler(instr, () => { props.store.markDirty(); })
|
|
||||||
: () => props.store.markDirty();
|
|
||||||
|
|
||||||
children.push(
|
children.push(
|
||||||
h('h4', { style: 'margin:0 0 0.5rem' }, 'Variation'),
|
h('h4', H4, 'Variation'),
|
||||||
h(ObjectExtended, { fields: variationFields(node), onChange: ({ key, value }) => {
|
h(ObjectExtended, { fields: variationFields(node), onChange: ({ key, value }) => {
|
||||||
if (key === 'depends_on') {
|
if (key === 'depends_on') {
|
||||||
const old = node.dependsOn;
|
const old = node.dependsOn;
|
||||||
@ -131,19 +134,16 @@ export const PaneFO = {
|
|||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
} else if (node.type === 'label_spec') {
|
} else if (node.type === 'label_spec') {
|
||||||
const instr = props.store.scoreModel?.instruments.find(
|
const instr = props.store.scoreModel.instruments.find(
|
||||||
i => i.variations?.some(v =>
|
i => i.variations.some(v =>
|
||||||
v.labelSpecs?.includes(node) ||
|
v.labelSpecs.includes(node) ||
|
||||||
v.subvariations?.some(sv => sv.labelSpecs?.includes(node))
|
v.subvariations.some(sv => sv.labelSpecs.includes(node))
|
||||||
)
|
)
|
||||||
) ?? null;
|
) ?? null;
|
||||||
|
const onChange = instrOnChange(instr);
|
||||||
const onChange = instr
|
|
||||||
? makeChangeHandler(instr, () => { props.store.markDirty(); })
|
|
||||||
: () => props.store.markDirty();
|
|
||||||
|
|
||||||
children.push(
|
children.push(
|
||||||
h('h4', { style: 'margin:0 0 0.5rem' }, `Label: ${node.label}`),
|
h('h4', H4, `Label: ${node.label}`),
|
||||||
node.basicProperties
|
node.basicProperties
|
||||||
? h(EnvelopeEditor, { basicProperties: node.basicProperties, onChange })
|
? h(EnvelopeEditor, { basicProperties: node.basicProperties, onChange })
|
||||||
: null,
|
: null,
|
||||||
@ -151,35 +151,26 @@ export const PaneFO = {
|
|||||||
} else if (node.type === 'bar') {
|
} else if (node.type === 'bar') {
|
||||||
const markBarDirty = () => { node.isDirty = true; props.store.markDirty(); };
|
const markBarDirty = () => { node.isDirty = true; props.store.markDirty(); };
|
||||||
children.push(
|
children.push(
|
||||||
h('h4', { style: 'margin:0 0 0.5rem' }, `Bar: ${node.id}`),
|
h('h4', H4, `Bar: ${node.id}`),
|
||||||
h(ObjectExtended, {
|
h(ObjectExtended, {
|
||||||
fields: [
|
fields: [
|
||||||
{ key: 'id', value: node.id, editable: false },
|
{ key: 'id', value: node.id, editable: false },
|
||||||
{ key: 'beats_per_minute', value: node.tempoLevels ?? '', editable: true, type: 'number' },
|
{ key: 'beats_per_minute', value: node.tempoLevels ?? '', editable: true, type: 'number' },
|
||||||
{ key: 'stress_pattern', value: stressorToString(node.stressor), editable: true },
|
{ key: 'stress_pattern', value: stressorToString(node.stressor), editable: true },
|
||||||
],
|
],
|
||||||
onChange: ({ key, value }) => {
|
onChange: ({ key, value }) => {
|
||||||
if (key === 'beats_per_minute') node.tempoLevels = isNaN(value) ? null : value;
|
if (key === 'beats_per_minute') node.tempoLevels = isNaN(value) ? null : value;
|
||||||
if (key === 'stress_pattern') node.stressor = parseStressor(value);
|
if (key === 'stress_pattern') node.stressor = parseStressor(value);
|
||||||
markBarDirty();
|
markBarDirty();
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
node.upperStressBound ? h('div', { style: 'margin-top:0.5rem' }, [
|
shapeSection('Upper stress bound', node.upperStressBound, markBarDirty),
|
||||||
h('strong', null, 'Upper stress bound'),
|
shapeSection('Lower stress bound', node.lowerStressBound, markBarDirty),
|
||||||
h(ShapeEditor, { shape: node.upperStressBound, onChange: markBarDirty }),
|
shapeSection('Tempo shape', node.tempoShape, markBarDirty),
|
||||||
]) : null,
|
|
||||||
node.lowerStressBound ? h('div', { style: 'margin-top:0.5rem' }, [
|
|
||||||
h('strong', null, 'Lower stress bound'),
|
|
||||||
h(ShapeEditor, { shape: node.lowerStressBound, onChange: markBarDirty }),
|
|
||||||
]) : null,
|
|
||||||
node.tempoShape ? h('div', { style: 'margin-top:0.5rem' }, [
|
|
||||||
h('strong', null, 'Tempo shape'),
|
|
||||||
h(ShapeEditor, { shape: node.tempoShape, onChange: markBarDirty }),
|
|
||||||
]) : null,
|
|
||||||
);
|
);
|
||||||
} else if (node.type === 'voice') {
|
} else if (node.type === 'voice') {
|
||||||
children.push(
|
children.push(
|
||||||
h('h4', { style: 'margin:0 0 0.5rem' }, `Voice: ${node.name}`),
|
h('h4', H4, `Voice: ${node.name}`),
|
||||||
h(ObjectExtended, {
|
h(ObjectExtended, {
|
||||||
fields: [
|
fields: [
|
||||||
{ key: 'articles', value: node.articles.join(', ') || '—', editable: false },
|
{ key: 'articles', value: node.articles.join(', ') || '—', editable: false },
|
||||||
@ -190,27 +181,26 @@ export const PaneFO = {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
} else if (node.type === 'offset') {
|
} else if (node.type === 'offset') {
|
||||||
const noteStr = n => `${n.pitch}${n.effLength != null ? ' ' + n.effLength : ''}`;
|
const noteStr = n => `${n.pitch}${n.effLength != null ? ' ' + n.effLength : ''}`;
|
||||||
const clusterStr = c => c.notes.length
|
const clusterStr = c => c.notes.length
|
||||||
? c.notes.map(n => `${n.letter ?? ''}${n.shift != null ? n.shift : ''}${n.length != null ? ' ' + n.length : ''}`).join(', ')
|
? c.notes.map(n => `${n.letter ?? ''}${n.shift != null ? n.shift : ''}${n.length != null ? ' ' + n.length : ''}`).join(', ')
|
||||||
: `cluster[${c.index}]`;
|
: `cluster[${c.index}]`;
|
||||||
|
const noteItem = (text, i) => h('li', { class: 'se-object-item', key: i },
|
||||||
|
h('span', { class: 'se-object-label' }, text));
|
||||||
|
|
||||||
children.push(
|
children.push(
|
||||||
h('h4', { style: 'margin:0 0 0.5rem' }, `Tick: ${node.tick}`),
|
h('h4', H4, `Tick: ${node.tick}`),
|
||||||
h(ObjectExtended, {
|
h(ObjectExtended, {
|
||||||
fields: [{ key: 'tick', value: node.tick, editable: false }],
|
fields: [{ key: 'tick', value: node.tick, editable: false }],
|
||||||
onChange: null,
|
onChange: null,
|
||||||
}),
|
}),
|
||||||
node.stemNotes.length ? h('div', { style: 'margin-top:0.5rem' }, [
|
node.stemNotes.length ? h('div', { style: 'margin-top:0.5rem' }, [
|
||||||
h('strong', null, 'Stem notes'),
|
h('strong', null, 'Stem notes'),
|
||||||
h('ul', { class: 'se-object-list' }, node.stemNotes.map((n, i) =>
|
h('ul', { class: 'se-object-list' }, node.stemNotes.map((n, i) => noteItem(noteStr(n), i))),
|
||||||
h('li', { class: 'se-object-item', key: i },
|
|
||||||
h('span', { class: 'se-object-label' }, noteStr(n))))),
|
|
||||||
]) : null,
|
]) : null,
|
||||||
node.clusters.length ? h('div', { style: 'margin-top:0.5rem' }, [
|
node.clusters.length ? h('div', { style: 'margin-top:0.5rem' }, [
|
||||||
h('strong', null, 'Clusters'),
|
h('strong', null, 'Clusters'),
|
||||||
h('ul', { class: 'se-object-list' }, node.clusters.map((c, i) =>
|
h('ul', { class: 'se-object-list' }, node.clusters.map((c, i) => noteItem(clusterStr(c), i))),
|
||||||
h('li', { class: 'se-object-item', key: i },
|
|
||||||
h('span', { class: 'se-object-label' }, clusterStr(c))))),
|
|
||||||
]) : null,
|
]) : null,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -223,8 +213,8 @@ export const PaneFO = {
|
|||||||
pendingEdit.value
|
pendingEdit.value
|
||||||
? h(LinkedInstrumentModal, {
|
? h(LinkedInstrumentModal, {
|
||||||
instrumentName: pendingEdit.value.instr.name,
|
instrumentName: pendingEdit.value.instr.name,
|
||||||
onEmbed: () => embedInstrument(pendingEdit.value.instr),
|
onEmbed: () => embedInstrument(pendingEdit.value.instr),
|
||||||
onDiscard: discardEdit,
|
onDiscard: discardEdit,
|
||||||
})
|
})
|
||||||
: null,
|
: null,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { h } from 'vue';
|
import { h } from 'vue';
|
||||||
import { ObjectShort } from './ObjectShort.js';
|
import { ObjectShort } from './ObjectShort.js';
|
||||||
|
|
||||||
// Shows sub-objects of the currently focused node — variations, bars, voices, etc.
|
|
||||||
export const PaneSubObjects = {
|
export const PaneSubObjects = {
|
||||||
props: ['store', 'onFocusFO'],
|
props: ['store', 'onFocusFO'],
|
||||||
setup(props) {
|
setup(props) {
|
||||||
@ -15,17 +14,17 @@ export const PaneSubObjects = {
|
|||||||
if (node.type === 'score') {
|
if (node.type === 'score') {
|
||||||
const items = [];
|
const items = [];
|
||||||
if (node.info)
|
if (node.info)
|
||||||
items.push({ kind: 'info', node: node.info, label: node.info.title ?? '(no title)', hasChildren: false });
|
items.push({ kind: 'info', node: node.info, label: node.info.title ?? '(no title)', hasChildren: false });
|
||||||
if (node.tuning)
|
if (node.tuning)
|
||||||
items.push({ kind: 'tuning', node: node.tuning, label: `base ${node.tuning.base ?? '?'}`, hasChildren: false });
|
items.push({ kind: 'tuning', node: node.tuning, label: `base ${node.tuning.base ?? '?'}`, hasChildren: false });
|
||||||
for (const a of (node.articles ?? []))
|
for (const a of (node.articles ?? []))
|
||||||
items.push({ kind: 'article', node: a, label: a.name, hasChildren: false });
|
items.push({ kind: 'article', node: a, label: a.name, hasChildren: false });
|
||||||
for (const sv of (node.stageVoices ?? []))
|
for (const sv of (node.stageVoices ?? []))
|
||||||
items.push({ kind: 'stage', node: sv, label: sv.name, hasChildren: false });
|
items.push({ kind: 'stage', node: sv, label: sv.name, hasChildren: false });
|
||||||
for (const i of node.instruments)
|
for (const i of node.instruments)
|
||||||
items.push({ kind: 'instrument', node: i, label: i.name, hasChildren: true });
|
items.push({ kind: 'instrument', node: i, label: i.name, hasChildren: true });
|
||||||
for (const b of node.bars)
|
for (const b of node.bars)
|
||||||
items.push({ kind: 'bar', node: b, label: b.id, hasChildren: false });
|
items.push({ kind: 'bar', node: b, label: b.id, hasChildren: Object.keys(b.voices).length > 0 });
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
if (node.type === 'instrument') {
|
if (node.type === 'instrument') {
|
||||||
@ -33,12 +32,13 @@ export const PaneSubObjects = {
|
|||||||
kind: 'variation',
|
kind: 'variation',
|
||||||
node: v,
|
node: v,
|
||||||
label: `variation ${idx + 1}${v.dependsOn ? ` (${v.dependsOn})` : ''}`,
|
label: `variation ${idx + 1}${v.dependsOn ? ` (${v.dependsOn})` : ''}`,
|
||||||
|
hasChildren: true,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
if (node.type === 'variation') {
|
if (node.type === 'variation') {
|
||||||
return [
|
return [
|
||||||
...node.labelSpecs.map(ls => ({
|
...node.labelSpecs.map(ls => ({
|
||||||
kind: 'label_spec', node: ls, label: ls.label ?? '(no label)',
|
kind: 'label_spec', node: ls, label: ls.label ?? '(no label)', hasChildren: false,
|
||||||
})),
|
})),
|
||||||
...node.subvariations.map((sv, idx) => {
|
...node.subvariations.map((sv, idx) => {
|
||||||
const dep = sv.dependsOn;
|
const dep = sv.dependsOn;
|
||||||
@ -56,9 +56,7 @@ export const PaneSubObjects = {
|
|||||||
}
|
}
|
||||||
if (node.type === 'voice') {
|
if (node.type === 'voice') {
|
||||||
return node.offsets.map((o, idx) => ({
|
return node.offsets.map((o, idx) => ({
|
||||||
kind: 'offset', node: o,
|
kind: 'offset', node: o, label: `tick ${o.tick ?? idx}`, hasChildren: false,
|
||||||
label: `tick ${o.tick ?? idx}`,
|
|
||||||
hasChildren: false,
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
@ -69,20 +67,19 @@ export const PaneSubObjects = {
|
|||||||
const items = subItems(node);
|
const items = subItems(node);
|
||||||
if (!items.length) return h('div', null, h('em', null, 'No sub-objects'));
|
if (!items.length) return h('div', null, h('em', null, 'No sub-objects'));
|
||||||
|
|
||||||
return h('div', null, [
|
return h('div', null,
|
||||||
h('ul', { class: 'se-object-list' }, items.map((item, idx) =>
|
h('ul', { class: 'se-object-list' }, items.map((item, idx) =>
|
||||||
h(ObjectShort, {
|
h(ObjectShort, {
|
||||||
key: idx,
|
key: idx,
|
||||||
node: item.node,
|
|
||||||
label: item.label,
|
label: item.label,
|
||||||
typeTag: item.kind,
|
typeTag: item.kind,
|
||||||
focused: props.store.focusPath.includes(item.node),
|
focused: props.store.focusPath.includes(item.node),
|
||||||
hasChildren: item.hasChildren ?? (item.kind !== 'bar' && item.kind !== 'voice'),
|
hasChildren: item.hasChildren,
|
||||||
onFocus: () => { props.store.pushFocus(item.node); props.onFocusFO?.(); },
|
onFocus: () => { props.store.pushFocus(item.node); props.onFocusFO?.(); },
|
||||||
onDrillDown: () => { props.store.pushFocus(item.node); props.onFocusFO?.(); },
|
onDrillDown: () => { props.store.pushFocus(item.node); props.onFocusFO?.(); },
|
||||||
})
|
})
|
||||||
)),
|
))
|
||||||
]);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -171,10 +171,15 @@ function patchInstrumentHeader(text, instruments) {
|
|||||||
return result.join('\n');
|
return result.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function stressorToString(s) {
|
||||||
|
if (!s?.groups?.length) return '';
|
||||||
|
return s.groups.map(g => g.join(',')).join(';');
|
||||||
|
}
|
||||||
|
|
||||||
function patchBarMeta(doc, bar) {
|
function patchBarMeta(doc, bar) {
|
||||||
const props = [];
|
const props = [];
|
||||||
if (bar.stressor?.groups?.length)
|
const sp = stressorToString(bar.stressor);
|
||||||
props.push(` stress_pattern: ${bar.stressor.groups.map(g => g.join(',')).join(';')}`);
|
if (sp) props.push(` stress_pattern: ${sp}`);
|
||||||
if (bar.tempoLevels != null)
|
if (bar.tempoLevels != null)
|
||||||
props.push(` beats_per_minute: ${bar.tempoLevels}`);
|
props.push(` beats_per_minute: ${bar.tempoLevels}`);
|
||||||
const ub = serializeShape(bar.upperStressBound);
|
const ub = serializeShape(bar.upperStressBound);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user