2018-08-03 23:14 GMT+02:00 Saul Tobin <[email protected]>: > Hi all, > > I just put together a snippet to make managing shared wind staves more > automatic, particularly with triple winds that may be combined in different > ways. > > \version "2.19.82" > > #(define remove-if-sibling > (lambda (offsets) > (lambda (grob) > (let* ( > ;; The parent of a VerticalAxisGroup is a VerticalAlignment > (parent (ly:grob-parent grob 1)) > ;; Get the children VerticalAxisGroups of the parent > (siblings (ly:grob-object parent 'elements)) > (siblings-list > (if (ly:grob-array? siblings) > (ly:grob-array->list siblings) > '())) > ;; Find the siblings above or below me by offsets > (my-vindex (ly:grob-get-vertical-axis-group-index grob)) > (enemy-indices (map (lambda (offset) (+ offset my-vindex)) > offsets)) > (enemy-vaxis? (lambda (v) (member > (ly:grob-get-vertical-axis-group-index v) > enemy-indices))) > (enemy-vaxes > (filter enemy-vaxis? siblings-list)) > ) > ;; Suicide if an enemy sibling is alive > (map > (lambda (enemy-vaxis) > (ly:pointer-group-interface::add-grob grob 'make-dead-when > enemy-vaxis)) > enemy-vaxes) > ) > ) > ) > ) > > %% Two Staff Example > > global = { > s1 > \break > s1 > \break > s1*2 > } > > I = { > c'''1 > \context Staff = "1" { \set Staff.keepAliveInterfaces = #'() } > c'''1 > c'''1 > \context Staff = "1" { \unset Staff.keepAliveInterfaces } > c'''1 > } > > II = { > e''1 > e''1 > e''1 > e''1 > } > > << > \new Staff = "1+2" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(1)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \partcombine \I \II >> > \new Staff = "1" \with { > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \I >> > \new Staff = "2" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(-2)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \II >> >>> > > %% Three Staff Example > > global = { > s1 > \break > s1 > \break > s1 > \break > s1*2 > } > > I = { > c'''1 > \context Staff = "1" { \set Staff.keepAliveInterfaces = #'() } > c'''1 > c'''1 > c'''1 > \context Staff = "1" { \unset Staff.keepAliveInterfaces } > c'''1 > } > > II = { > e''1 > e''1 > e''1 > e''1 > e''1 > } > > III = { > a'1 > a'1 > \context Staff = "3" { \set Staff.keepAliveInterfaces = #'() } > a'1 > a'1 > a'1 > } > > << > \new Staff = "1+2+3" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(2 5)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \I \II \III >> > \new Staff = "1+2" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(1 -1)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \partcombine \I \II >> > \new Staff = "1" \with { > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \I >> > \new Staff = "2+3" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(2 -3)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \partcombine \II \III >> > \new Staff = "2" \with { > \override VerticalAxisGroup.before-line-breaking = #(remove-if-sibling > '(-1 -3 -4)) > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \II >> > \new Staff = "3" \with { > \override VerticalAxisGroup.remove-empty = ##t > \override VerticalAxisGroup.remove-first = ##t > } << \global \III >> >>> > > _______________________________________________ > lilypond-user mailing list > [email protected] > https://lists.gnu.org/mailman/listinfo/lilypond-user >
Hi, I had a closer look at your code. You select via vertical-axis-group-index. This makes for a not intuitive argument of your `remove-if-sibling`-procedure. Even worse, the needed arguments may need to be changed if other staves are added to the score. Also I think divisis should be controlled, well, from the divisi-staves. Inspired by your work I come up with the attached. Cheers, Harm
divisi-saul-02-test.pdf
Description: Adobe PDF document
\version "2.19.82"
\pointAndClickOff
%% relies on:
%%
%% VerticalAxisGroup.details.catch-me
%% VerticalAxisGroup.details.combined
%% VerticalAxisGroup.details.geediness
%%
%% see inline comments below
%%
%%
%% Limitations/TODOs:
%% Staves can't be started/ended mid-line.
%% For divisi of two instrument one divisi-Staff needs to be initiated.
%% For divisi of three instrument three divisi-Staves need to be initiated.
#(define (divisis divisi-groups)
;; Kill selected other Staffs, if divisi-Staffs are alive.
;; Do it separatly for every instrument-group specified by `divisi-groups`.
(lambda (grob)
;; `grob` is supposed to be `VerticalAlignment`, per default living in
;; Score-context
;;
;; Apply the procedure to every element of `divisi-groups`,
;; p.e. '("flutes" "trumpets")
(for-each
(lambda (group)
(let* (
;; Get all `VerticalAxisGroup`s from `VerticalAlignment`
;; Those are the relevant grobs to look at to make others dead
;; or not
(vags-array (ly:grob-object grob 'elements))
(vags-list
(if (null? vags-array)
'()
(ly:grob-array->list vags-array)))
;; Select only those `VerticalAxisGroup`s related to current
;; `group`
;; Done by comparing the property `details.catch-me` with `group`
(splitted-vags-list
(call-with-values
(lambda ()
(partition
(lambda (vag)
(equal?
group
(assoc-get
'catch-me (ly:grob-property vag 'details))))
vags-list))
(lambda (x y) (list x y))))
;; Split them into those supposed to contain combinations and
;; others.
;; Done by reading the property `details.combined`. Which is
;; supposed to be a boolean, if set.
;;
;; The resulting list contains two sublists, each ordered
;; after increasing `details.greediness`.
;;
;; `greediness` should be set like:
;; single:
;; flute-I greediness 1
;; flute-II greediness 2
;; flute-III greediness 3
;; combined
;; flute-1+2+3 greediness 1
;; flute-1+2 greediness 2
;; flute-2+3 greediness 3
;; or similar increasing numerical values.
(splitted
(call-with-values
(lambda ()
(partition
(lambda (vag)
(assoc-get
'combined (ly:grob-property vag 'details) #f))
(car splitted-vags-list)))
(lambda (x y)
(let (
(greediness-sorting-proc
(lambda (p q)
(<
(assoc-get
'greediness (ly:grob-property p 'details) 0)
(assoc-get
'greediness (ly:grob-property q 'details) 0)))))
(list
(sort x greediness-sorting-proc)
(sort y greediness-sorting-proc)))))))
;; (length (cadr splitted)) is the amount of instruments which may
;; be combined in divisi staves
(case (length (cadr splitted))
;; Two instruments
((2)
;; Kill all other, if "1+2", i.e. (list-ref (car splitted) 0)),
;; is alive
(for-each
(lambda (x)
(ly:pointer-group-interface::add-grob
x 'make-dead-when (list-ref (car splitted) 0)))
(remove
(lambda (x)
(equal? (list-ref (car splitted) 0) x))
(car splitted-vags-list))))
;; Three instruments
((3)
;; Kill all other, if "1+2+3", i.e. (list-ref (car splitted) 0)),
;; is alive
(for-each
(lambda (x)
(ly:pointer-group-interface::add-grob
x 'make-dead-when (list-ref (car splitted) 0)))
(remove
(lambda (x)
(equal? (list-ref (car splitted) 0) x))
(car splitted-vags-list)))
;; Additionally:
;; Kill all but "3", if "1+2", i.e. (list-ref (car splitted) 1)),
;; is alive
(for-each
(lambda (x)
(ly:pointer-group-interface::add-grob x
'make-dead-when (list-ref (car splitted) 1)))
;; all but "3":
(take (cadr splitted) 2))
;; Additionally:
;; Kill all but "1", if "2+3", i.e. (list-ref (car splitted) 2)),
;; is alive
(for-each
(lambda (x)
(ly:pointer-group-interface::add-grob x
'make-dead-when (list-ref (car splitted) 2)))
;; all but "1":
(drop (cadr splitted) 1)))
;; divisi for 4 instruments is not yet coded
(else '()))))
divisi-groups)))
%% Short-cuts to switch on/off Staves
%% They should be inserted at line-breaks.
switchOff = \set Staff.keepAliveInterfaces = #'()
switchOn = \unset Staff.keepAliveInterfaces
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#(set-default-paper-size "a3")
#(set-global-staff-size 15)
\paper {
indent = 20
short-indent = 20
}
%%
%% the actual music
%%
fluteI = \repeat unfold 12 c''2
fluteII = \repeat unfold 12 e'2
trumpetI = \repeat unfold 6 { g'4 c'' e'' c'' }
trumpetII = \repeat unfold 6 { e'4 g' c'' g' }
trumpetIII = \repeat unfold 6 { c'4 e' g' e' }
%%
%% controlling divisis (colors only for better viewing)
%%
%% divisi-Staffs are switched off per default, they may be switched on as wished
%%
%% flutes
combined-flutes-I-II = {
%% 1
\switchOff
s1 \break
%% 2
\switchOn
\override NoteHead.color = #green
s1 \break
%% 3
s1 \break
%% 4
\revert NoteHead.color
\switchOff
s1 \break
%% 5
\switchOn
\override NoteHead.color = #green
s1 \break
%% 6
s1 \break
\revert NoteHead.color
}
%% trumpets
combined-trumpets-I-II-III = {
%% 1
\switchOff
s1 \break
%% 2
s1 \break
%% 3
\switchOn
\override NoteHead.color = #red
s1 \break
%% 4
\revert NoteHead.color
\switchOff
s1 \break
%% 5
s1 \break
%% 6
s1 \break
}
combined-trumpets-I-II = {
%% 1
\switchOff
s1 \break
%% 2
s1 \break
%% 3
s1 \break
%% 4
\switchOn
\override NoteHead.color = #(x11-color 'orange)
s1 \break
%% 5
\revert NoteHead.color
\switchOff
s1 \break
%% 6
s1 \break
}
combined-trumpets-II-III = {
%% 1
\switchOff
s1 \break
%% 2
s1 \break
%% 3
s1 \break
%% 4
s1 \break
%% 5
s1 \break
%% 6
\switchOn
\override NoteHead.color = #yellow
s1 \break
}
%% For divisi instruments initiate Staff-contexts for every single instrument.
%% Set `VerticalAxisGroup.details.catch-me` and
%% `VerticalAxisGroup.details.greediness` appropiate. The latter may left unset,
%% if only two instruments participate.
%% Initiate every desired divisi-Staff.
%% Staves meant for divisi should be labed with
%% `VerticalAxisGroup.details.combined = ##t`, appropriate `catch-me` and
%% `greediness'.
%% Again, the latter may left unset, if only two instruments participate.
%% Apply \RemoveAllEmptyStaves to every divisi-Staff.
\score {
<<
%% A Staff which should not become part of any divisi
\new Staff = "0"
\with {
instrumentName = "Picc"
shortInstrumentName = "picc"
}
{ \repeat unfold 48 c''8 }
%% FLUTES
\new StaffGroup
\with {
\override SystemStartBracket.collapse-height = 1
instrumentName = \markup { \rotate #90 "FLUTES" \hspace #12 }
shortInstrumentName = \markup { \rotate #90 "FLUTES" \hspace #12 }
}
<<
\new Staff = "fl1"
\with {
instrumentName = "Fl 1"
shortInstrumentName = "Fl 1"
\override VerticalAxisGroup.details.catch-me = "flutes"
}
\fluteI
\new Staff = "fl2"
\with {
instrumentName = "Fl 2"
shortInstrumentName = "Fl 2"
\override VerticalAxisGroup.details.catch-me = "flutes"
}
\fluteII
\new Staff = "fl1+2"
\with {
instrumentName = "Fl 1+2"
shortInstrumentName = "Fl 1+2"
\RemoveAllEmptyStaves
\override VerticalAxisGroup.details.catch-me = "flutes"
\override VerticalAxisGroup.details.combined = ##t
%\override VerticalAxisGroup.details.greediness = 1
}
\new Voice
<<
\combined-flutes-I-II
\fluteI \fluteII
>>
>>
%% TRUMPETS
\new StaffGroup
\with {
\override SystemStartBracket.collapse-height = 1
instrumentName = \markup { \rotate #90 "TUMPETS" \hspace #12 }
shortInstrumentName = \markup { \rotate #90 "TRUMPETS" \hspace #12 }
}
<<
\new Staff = "tr1"
\with {
instrumentName = "Tr 1"
shortInstrumentName = "Tr 1"
\override VerticalAxisGroup.details.catch-me = "trumpets"
\override VerticalAxisGroup.details.greediness = 1
}
\trumpetI
\new Staff = "tr2"
\with {
instrumentName = "Tr 2"
shortInstrumentName = "Tr 2"
\override VerticalAxisGroup.details.catch-me = "trumpets"
\override VerticalAxisGroup.details.greediness = 2
}
\trumpetII
\new Staff = "tr3"
\with {
instrumentName = "Tr 3"
shortInstrumentName = "Tr 3"
\override VerticalAxisGroup.details.catch-me = "trumpets"
\override VerticalAxisGroup.details.greediness = 3
}
\trumpetIII
\new Staff = "tr1+2+3"
\with {
instrumentName = "Tr 1+2+3"
shortInstrumentName = "Tr 1+2+3"
\RemoveAllEmptyStaves
\override VerticalAxisGroup.details.combined = ##t
\override VerticalAxisGroup.details.catch-me = "trumpets"
\override VerticalAxisGroup.details.greediness = 1
}
\new Voice
<<
\combined-trumpets-I-II-III
\trumpetI \trumpetII \trumpetIII
>>
\new Staff = "tr1+2"
\with {
instrumentName = "Tr 1+2"
shortInstrumentName = "Tr 1+2"
\RemoveAllEmptyStaves
\override VerticalAxisGroup.details.catch-me = "trumpets"
\override VerticalAxisGroup.details.combined = ##t
\override VerticalAxisGroup.details.greediness = 2
alignAboveContext = "tr3"
}
\new Voice
<<
\combined-trumpets-I-II
\trumpetI \trumpetII
>>
\new Staff = "tr2+3"
\with {
instrumentName = "Tr 2+3"
shortInstrumentName = "Tr 2+3"
\RemoveAllEmptyStaves
\override VerticalAxisGroup.details.catch-me = "trumpets"
\override VerticalAxisGroup.details.combined = ##t
\override VerticalAxisGroup.details.greediness = 3
alignBelowContext = "tr1+2"
}
\new Voice
<<
\combined-trumpets-II-III
\trumpetII \trumpetIII
>>
>>
%% A Staff which should not become part of any divisi
\new Staff = "7"
\with {
instrumentName = "Bass"
shortInstrumentName = "Bass"
}
{ \clef bass \repeat unfold 6 c1 }
>>
\layout {
\context {
\Score
\override VerticalAlignment.before-line-breaking =
#(divisis '("flutes" "trumpets"))
}
}
}
_______________________________________________ lilypond-user mailing list [email protected] https://lists.gnu.org/mailman/listinfo/lilypond-user
