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

Attachment: 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

Reply via email to