Le 26/12/2022 à 19:18, Gregory Evans a écrit :
Hi Jean, I apologize for my delayed reply.I do not think I can use the VoiceFollower grob because I am not using staff changes.
You can. A VoiceFollower won't be created automatically without a staff change, but you can create it yourself in your Scheme engraver.
Attached is a pdf of what I am trying to do. It works successfully if I input the y-position by hand but ideally it would be calculated automatically. You see, they are completely unrelated voices. Also see this image of hocket indications in Ben Johnston's 3rd string quartet which I think would not be done with VoiceFollower:I have also included the lilypond file for my interruptive polyphony example if that is of any use to you even though it is quite large. While it's true that certain aspects of the process could be simplified (such as removing the use of 'meta as you suggest), there is little reason to revise it if the callback cannot be delayed until after the skyline calculation. Is there no way to simply trigger callback at a later time?
"Trigger callback at a later time" sounds like you are thinking too much in imperative programming terms of "get parameters, set stencil to what I want". That's not how most of LilyPond's backend works, with the exception of after-line-breaking and a few other properties. Instead, you build callbacks that compute the initial values of properties (instead of getting their values and changing them). See also this recent discussion: https://lists.gnu.org/archive/html/lilypond-user/2022-12/msg00001.html Thus, the question is not "how to trigger this callback at a later time, so it knows everything" but "how to ensure that nothing this callback depends on also depends on it, so there are no cyclic dependencies". The answer is the cross-staff property, as I explained previously, on a grob that supports it like VoiceFollower (but not NoteHead). See the attached file for an implementation of your graphical notation. I basically started from scratch because it was simpler, so its exact behavior might deviate from what you wanted (there were some oddities in your original code and I don't know which of them were intentional), but it outputs the same thing on the excerpt you give, and it should get you going. By the way, not sure if you or Piaras is the author of the PostScript code, but if you are, please read the documentation of \postscript <https://lilypond.org/doc/v2.24/Documentation/notation/graphic> on why you should only use embedded PostScript code if you absolutely need it, which is not the case here (make-path-stencil does the job). Best, Jean
\version "2.24.0" \language "english" #(set-global-staff-size 30) #(set-default-paper-size "a3landscape") #(define (make-butt-line-stencil width start-x start-y end-x end-y) (let ((path `(moveto ,start-x ,start-y lineto ,end-x ,end-y))) (make-path-stencil path width 1 1 #t #:line-cap-style 'butt))) #(define (interrupting-bracket grob) (let* ((left (ly:spanner-bound grob LEFT)) (right (ly:spanner-bound grob RIGHT)) (sys (ly:grob-system grob)) (start-x (interval-end (ly:grob-extent left sys X))) (start-y (interval-center (ly:grob-extent left sys Y))) (right-stem (ly:grob-object right 'stem)) (right-stem-dir (ly:grob-property right-stem 'direction)) (right-head (reduce (lambda (head prev) (if ((if (eqv? UP right-stem-dir) not identity) (ly:grob-vertical<? head prev)) head prev)) 'dummy (ly:grob-array->list (ly:grob-object right 'note-heads)))) (end-x (interval-index (interval-widen (ly:grob-extent right-head sys X) -0.07) (- right-stem-dir))) (end-y (interval-center (ly:grob-extent right-head sys Y)))) (ly:stencil-translate (ly:stencil-add (make-butt-line-stencil 0.5 (- start-x 0.2) start-y (+ end-x 0.05) start-y) (make-butt-line-stencil 0.1 end-x start-y end-x end-y)) (cons (- (ly:grob-relative-coordinate grob sys X)) (- (ly:grob-relative-coordinate grob sys Y)))))) #(define (Interrupt_heads_engraver context) (let ((interrupted (make-hash-table))) (make-engraver (acknowledgers ((note-column-interface engraver grob source-engraver) (when (not (ly:grob-object grob 'rest #f)) (for-each (match-lambda ((mom . elt) (when (and (grob::has-interface elt 'note-head-interface) (assoc-get 'interrupt (ly:grob-property elt 'details '())) (not (hashq-ref interrupted elt)) (not (equal? mom (ly:context-current-moment context)))) (hashq-set! interrupted elt #t) (let ((follower (ly:engraver-make-grob engraver 'VoiceFollower '()))) (ly:spanner-set-bound! follower LEFT elt) (ly:spanner-set-bound! follower RIGHT grob) (ly:grob-set-property! follower 'stencil interrupting-bracket))))) (ly:context-property context 'busyGrobs)))))))) interrupt = \once \override Staff.NoteHead.details.interrupt = ##t \layout { \context { \Score \override Beam.beam-thickness = #0.6 \override Beam.length-fraction = #1.05 \override Beam.damping = #200 \override Stem.details.beamed-lengths = #'(3 5) proportionalNotationDuration = #(ly:make-moment 1/70) \consists Grob_pq_engraver \consists #Interrupt_heads_engraver } \context { \Staff \override BarLine.transparent = ##t \override TupletNumber.font-size = #-5 \override TupletNumber.text = #tuplet-number::calc-fraction-text \override TupletBracket.full-length-padding = #1 tupletFullLength = ##t tupletFullLengthNote = ##f } } \new StaffGroup << \new Staff = "one" { \time 5/16 \stemUp \tuplet 9/8 { r32 \interrupt <c'' f''\harmonic>8[ \interrupt <c'' e''\harmonic>8] } \tuplet 7/4 { dqf''64 [ c'' c'' cqs' r32. ] } \time 3/8 \tuplet 5/6 { \tuplet 9/11 { c''64 \afterGrace 8/10 <cqs'' fqs''\harmonic>16\glissando { <d'' g''\harmonic>8 } \interrupt <d' g' cs''>64 r32. } r64 \interrupt c''16[ r32 \interrupt cs''32] } } \new Staff = "two" { \stemDown \tupletUp \time 5/16 \tuplet 11/7 { r8 cs''32. } \tuplet 13/12 { \interrupt c''8 \interrupt bqs'32. r32 } r64 \time 3/8 \tuplet 5/6 { r16 \tuplet 5/4 { \once \override Dots.extra-offset = #'(0 . -1) \interrupt aqf'32. [ \tieDown aqs'32 ] ~ } \tuplet 3/2 { \single\stemUp aqs'16 r32 } \tuplet 3/2 { r16 \tuplet 5/4 { \afterGrace 7/10 a'8 [ \glissando {\stemDown dqs'8} <a' bf' ef''>64 r64 ] } } } } >>
terrain.pdf
Description: Adobe PDF document
OpenPGP_signature
Description: OpenPGP digital signature