smoosic 1.0.20 → 1.0.21
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/build/smoosic.js +5 -5
- package/package.json +1 -1
- package/release/smoosic.js +5 -5
- package/src/render/sui/scoreViewOperations.ts +1 -0
- package/src/render/sui/tracker.ts +3 -0
- package/src/render/vex/vxMeasure.ts +2 -1
- package/src/smo/data/measure.ts +10 -2
- package/src/ui/menus/voices.ts +62 -18
|
@@ -454,6 +454,7 @@ export class SuiScoreViewOperations extends SuiScoreView {
|
|
|
454
454
|
SmoOperation.setActiveVoice(this.score, index);
|
|
455
455
|
this._renderChangedMeasures(measuresToAdd);
|
|
456
456
|
await this.renderer.updatePromise();
|
|
457
|
+
this.tracker.selectActiveVoice();
|
|
457
458
|
}
|
|
458
459
|
async swapVoices(voice1: number, voice2: number): Promise<void> {
|
|
459
460
|
const selections = this.tracker.getSelectedMeasures();
|
|
@@ -666,6 +666,9 @@ export class SuiTracker extends SuiMapper implements TrackerKeyHandler {
|
|
|
666
666
|
selection.box = JSON.parse(JSON.stringify(this.suggestion.box));
|
|
667
667
|
selection.scrollBox = JSON.parse(JSON.stringify(this.suggestion.scrollBox));
|
|
668
668
|
this.selections = [selection];
|
|
669
|
+
// There is a single selection, make sure the active voice is set to it.
|
|
670
|
+
selection.measure.setActiveVoice(selection.selector.voice);
|
|
671
|
+
this.selectActiveVoice();
|
|
669
672
|
}
|
|
670
673
|
}
|
|
671
674
|
if (preselected && this.modifierSelections.length) {
|
|
@@ -219,7 +219,8 @@ export class VxMeasure implements VxMeasureIf {
|
|
|
219
219
|
if (smoNote.fillStyle && !this.printing) {
|
|
220
220
|
vexNote.setStyle({ fillStyle: smoNote.fillStyle });
|
|
221
221
|
} else if (voiceIx > 0 && !this.printing) {
|
|
222
|
-
|
|
222
|
+
const voiceFill = ['#115511','#555511','#883344']
|
|
223
|
+
vexNote.setStyle({ fillStyle: voiceFill[voiceIx - 1] });
|
|
223
224
|
} else if (smoNote.isHidden() && this.printing) {
|
|
224
225
|
vexNote.setStyle({ fillStyle: "#ffffff00" });
|
|
225
226
|
}
|
package/src/smo/data/measure.ts
CHANGED
|
@@ -989,8 +989,16 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
989
989
|
*/
|
|
990
990
|
alignNotesWithTimeSignature() {
|
|
991
991
|
const tsTicks = SmoMusic.timeSignatureToTicks(this.timeSignature.timeSignature);
|
|
992
|
-
|
|
993
|
-
|
|
992
|
+
let aligned = true;
|
|
993
|
+
for (let i = 0; i < this.voices.length; ++i) {
|
|
994
|
+
const voice = this.voices[i];
|
|
995
|
+
if (this.getTicksFromVoice(i) !== tsTicks) {
|
|
996
|
+
aligned = false;
|
|
997
|
+
break;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
if (aligned) {
|
|
1001
|
+
return true;
|
|
994
1002
|
}
|
|
995
1003
|
const replaceNoteWithDuration = (target: number, ar: SmoNote[], note: SmoNote) => {
|
|
996
1004
|
const fitNote = new SmoNote(SmoNote.defaults);
|
package/src/ui/menus/voices.ts
CHANGED
|
@@ -10,14 +10,6 @@ declare var $: any;
|
|
|
10
10
|
export class SuiVoiceMenu extends SuiConfiguredMenu {
|
|
11
11
|
constructor(params: SuiMenuParams) {
|
|
12
12
|
super(params, 'Voices', SuiVoiceMenuOptions);
|
|
13
|
-
const measures = this.view.tracker.getSelectedMeasures();
|
|
14
|
-
if (measures.length > 0) {
|
|
15
|
-
const sel = measures[0];
|
|
16
|
-
const swaps = sel.measure.getSwapVoicePairs();
|
|
17
|
-
swaps.forEach((pair: number[]) => {
|
|
18
|
-
this.menuOptions.push(new voiceSwapperMenuOption(pair[0], pair[1]));
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
13
|
}
|
|
22
14
|
}
|
|
23
15
|
class voiceSwapperMenuOption implements SuiConfiguredMenuOption {
|
|
@@ -35,14 +27,57 @@ class voiceSwapperMenuOption implements SuiConfiguredMenuOption {
|
|
|
35
27
|
constructor(voice1: number, voice2: number) {
|
|
36
28
|
this.voice1 = voice1;
|
|
37
29
|
this.voice2 = voice2;
|
|
38
|
-
this.label = `Swap ${voice1} and ${voice2}`;
|
|
30
|
+
this.label = `Swap ${voice1 + 1} and ${voice2 + 1}`;
|
|
39
31
|
this.cmd = `${voice1}To${voice2}`;
|
|
40
32
|
}
|
|
41
33
|
async handler(menu: SuiMenuBase) {
|
|
42
34
|
menu.view.swapVoices(this.voice1, this.voice2);
|
|
43
35
|
}
|
|
44
|
-
display() {
|
|
45
|
-
|
|
36
|
+
display(menu: SuiMenuBase) {
|
|
37
|
+
const measures = menu.view.tracker.getSelectedMeasures();
|
|
38
|
+
if (measures.length > 0) {
|
|
39
|
+
const sel = measures[0];
|
|
40
|
+
const swaps = sel.measure.getSwapVoicePairs();
|
|
41
|
+
for (let i = 0; i < swaps.length; ++i) {
|
|
42
|
+
const pair = swaps[i];
|
|
43
|
+
if (this.voice1 == pair[0] && this.voice2 == pair[1]) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
class selectVoiceMenuOption implements SuiConfiguredMenuOption {
|
|
52
|
+
voice: number;
|
|
53
|
+
constructor(voice: number) {
|
|
54
|
+
this.voice = voice;
|
|
55
|
+
}
|
|
56
|
+
async handler (menu: SuiMenuBase) {
|
|
57
|
+
await menu.view.populateVoice(this.voice);
|
|
58
|
+
}
|
|
59
|
+
display (menu: SuiMenuBase) {
|
|
60
|
+
for (let i = 0; i < menu.view.tracker.selections.length; ++i) {
|
|
61
|
+
const mm = menu.view.tracker.selections[i].measure;
|
|
62
|
+
if (mm.voices.length === 1) {
|
|
63
|
+
return this.voice === 1;
|
|
64
|
+
}
|
|
65
|
+
// If there are n voices, and I am n+1, show option
|
|
66
|
+
if (mm.voices.length === this.voice) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
if (mm.voices.length > this.voice && mm.getActiveVoice() !== this.voice) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
get menuChoice() {
|
|
76
|
+
return {
|
|
77
|
+
icon: '',
|
|
78
|
+
text: `Voice ${this.voice + 1}`,
|
|
79
|
+
value: `voice${this.voice.toString()}`
|
|
80
|
+
};
|
|
46
81
|
}
|
|
47
82
|
}
|
|
48
83
|
/**
|
|
@@ -50,7 +85,7 @@ class voiceSwapperMenuOption implements SuiConfiguredMenuOption {
|
|
|
50
85
|
*/
|
|
51
86
|
const selectVoiceOneMenuOption: SuiConfiguredMenuOption = {
|
|
52
87
|
handler: async (menu: SuiMenuBase) => {
|
|
53
|
-
menu.view.populateVoice(0);
|
|
88
|
+
await menu.view.populateVoice(0);
|
|
54
89
|
}, display: (menu: SuiMenuBase) => {
|
|
55
90
|
for (let i = 0; i < menu.view.tracker.selections.length; ++i) {
|
|
56
91
|
const mm = menu.view.tracker.selections[i].measure;
|
|
@@ -71,11 +106,11 @@ const selectVoiceOneMenuOption: SuiConfiguredMenuOption = {
|
|
|
71
106
|
*/
|
|
72
107
|
const selectVoiceTwoMenuOption: SuiConfiguredMenuOption = {
|
|
73
108
|
handler: async (menu: SuiMenuBase) => {
|
|
74
|
-
menu.view.populateVoice(1);
|
|
109
|
+
await menu.view.populateVoice(1);
|
|
75
110
|
}, display: (menu: SuiMenuBase) => {
|
|
76
111
|
for (let i = 0; i < menu.view.tracker.selections.length; ++i) {
|
|
77
112
|
const mm = menu.view.tracker.selections[i].measure;
|
|
78
|
-
if (mm.voices.length
|
|
113
|
+
if (mm.voices.length <= 4 && mm.voices.length > 1) {
|
|
79
114
|
return true;
|
|
80
115
|
}
|
|
81
116
|
}
|
|
@@ -92,7 +127,7 @@ const selectVoiceTwoMenuOption: SuiConfiguredMenuOption = {
|
|
|
92
127
|
*/
|
|
93
128
|
const selectVoiceThreeMenuOption: SuiConfiguredMenuOption = {
|
|
94
129
|
handler: async (menu: SuiMenuBase) => {
|
|
95
|
-
menu.view.populateVoice(2);
|
|
130
|
+
await menu.view.populateVoice(2);
|
|
96
131
|
}, display: (menu: SuiMenuBase) => {
|
|
97
132
|
for (let i = 0; i < menu.view.tracker.selections.length; ++i) {
|
|
98
133
|
const mm = menu.view.tracker.selections[i].measure;
|
|
@@ -113,7 +148,7 @@ const selectVoiceThreeMenuOption: SuiConfiguredMenuOption = {
|
|
|
113
148
|
*/
|
|
114
149
|
const selectVoiceFourMenuOption: SuiConfiguredMenuOption = {
|
|
115
150
|
handler: async (menu: SuiMenuBase) => {
|
|
116
|
-
menu.view.populateVoice(3);
|
|
151
|
+
await menu.view.populateVoice(3);
|
|
117
152
|
}, display: (menu: SuiMenuBase) => {
|
|
118
153
|
for (let i = 0; i < menu.view.tracker.selections.length; ++i) {
|
|
119
154
|
const mm = menu.view.tracker.selections[i].measure;
|
|
@@ -134,7 +169,7 @@ const selectVoiceFourMenuOption: SuiConfiguredMenuOption = {
|
|
|
134
169
|
*/
|
|
135
170
|
const removeVoiceMenuOption: SuiConfiguredMenuOption = {
|
|
136
171
|
handler: async (menu: SuiMenuBase) => {
|
|
137
|
-
menu.view.depopulateVoice();
|
|
172
|
+
await menu.view.depopulateVoice();
|
|
138
173
|
}, display: (menu: SuiMenuBase) => {
|
|
139
174
|
for (let i = 0; i < menu.view.tracker.selections.length; ++i) {
|
|
140
175
|
const mm = menu.view.tracker.selections[i].measure;
|
|
@@ -155,6 +190,15 @@ const removeVoiceMenuOption: SuiConfiguredMenuOption = {
|
|
|
155
190
|
* @category SuiMenu
|
|
156
191
|
*/
|
|
157
192
|
const SuiVoiceMenuOptions: SuiConfiguredMenuOption[] = [
|
|
158
|
-
|
|
193
|
+
new selectVoiceMenuOption(0),
|
|
194
|
+
new selectVoiceMenuOption(1),
|
|
195
|
+
new selectVoiceMenuOption(2),
|
|
196
|
+
new selectVoiceMenuOption(3),
|
|
197
|
+
new voiceSwapperMenuOption(0, 1),
|
|
198
|
+
new voiceSwapperMenuOption(0, 2),
|
|
199
|
+
new voiceSwapperMenuOption(0, 3),
|
|
200
|
+
new voiceSwapperMenuOption(1, 2),
|
|
201
|
+
new voiceSwapperMenuOption(1, 3),
|
|
202
|
+
new voiceSwapperMenuOption(2, 3),
|
|
159
203
|
removeVoiceMenuOption
|
|
160
204
|
];
|