Hi Jean, I’m revisiting the engraver you defined for me above. I don’t understand how to pass a particular value from one place to another. Hopefully this can be answered without you studying up on what you developed back in December. We have
1.) a line drawing function #(define (make-switch-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))) 2.) a stencil drawn from properties of a VoiceFollower grob #(define (switching-bracket grob) (let* ((left (ly:spanner-bound grob LEFT)) (right (ly:spanner-bound grob RIGHT)) (x-proportion (assoc-get 'used-proportion (ly:grob-property grob 'details '()))) (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))) (x-distance-total (- end-x start-x)) (x-distance-proportion (* x-distance-total x-proportion)) (new-calculated-end-x (+ start-x x-distance-proportion)) (end-y (interval-center (ly:grob-extent right-head sys Y)))) (ly:stencil-translate (ly:stencil-add (make-switch-butt-line-stencil 0.5 (- start-x 0.2) start-y (+ new-calculated-end-x 0.05) start-y) (make-switch-butt-line-stencil 0.1 new-calculated-end-x start-y new-calculated-end-x end-y) (make-switch-butt-line-stencil 0.5 (- new-calculated-end-x 0.05) end-y (- end-x 2.5) end-y) ) (cons (- (ly:grob-relative-coordinate grob sys X)) (- (ly:grob-relative-coordinate grob sys Y)))))) 3.) an engraver which manages the process #(define (Switch_heads_engraver context) (let ((switched (make-hash-table))) (make-engraver (acknowledgers ((note-column-interface engraver grob source-engraver) (when (assoc-get 'switchable (ly:grob-property grob 'details '())) (for-each (match-lambda ((mom . elt) (when (and (grob::has-interface elt 'note-head-interface) (assoc-get 'switch (ly:grob-property elt 'details '())) (not (hashq-ref switched elt)) (not (equal? mom (ly:context-current-moment context)))) (hashq-set! switched 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 'color (assoc-get 'switch-color (ly:grob-property elt 'details '()))) (ly:grob-set-property! follower 'stencil switching-bracket) (ly:grob-set-property! follower 'details '((used-proportion . 0.5))) ;;; HERE I would like to have user-input instead of 0.5 ;; would prefer the above line to read something like: ;; (ly:grob-set-property! follower 'details '((used-proportion . (assoc-get 'used-proportion (ly:grob-property elt 'details '()))))) )))) (ly:context-property context 'busyGrobs)))))))) and 4.) some commands to locate the start and stop of the voice follower start-switch = \once \override Staff.NoteHead.details.switch = ##t switch-proportion = \once \override Staff.NoteHead.details.used-proportion = 0.5 stop-switch = \once \override Staff.NoteColumn.details.switchable = ##t I am trying to pass user-input to shorten an X-position by a proportion as you might see in the commented line. However any time I try to replace 0.5 with a variable or a returned value from a function, an error is returned. So I think I might not understand something about association lists in Scheme. Do you have advice for passing in this value? regards, greg evans On Sun, Jan 1, 2023 at 6:47 AM Jean Abou Samra <j...@abou-samra.fr> wrote: > Le 31/12/2022 à 19:43, Gregory Evans a écrit : > > > > It appears to be the case that there is a limitation to how far to the > > right notes can be checked. Let’s call the starting note |A| and the > > stopping note |B|. It seems like the boundary is if the start-offset > > of |B| is further forward than the stop-offset of |A|. In the above > > image, a line cannot be drawn between the 2nd note of the top staff > > and the 8th note of the middle staff. Can you explain why this is? Is > > this a situation where the note columns are not finished being spaced, > > similar to my initial confusion about the timing of skyline > > calculation? Anyway, the ability to draw lines between any arbitrary > > location is not precisely necessary for what I’m trying to accomplish, > > I would just like to understand what I don’t know! > > > > > The engraver iterates over busyGrobs (maintained by Grob_pq_engraver), > which is precisely, by definition, the set of grobs with a cause in events > that tells they are still "active" at the current moment. > > If you want different behavior, acknowledge note-head-interface yourself > and store the grobs in a variable in the engraver (adding a new binding > in (let ((followed ...) [here]) ...)). > > > > p.s. In the Johnston example, notes are able to be used as line > > anchors more than once. Would there be a way to include something like > > a spanner ID? > > > > > What about using a details.spanner-ids symbol list property? > You'd read it on the note column to know which spanners to start/stop. > > Best, > Jean > > > -- gregory rowland evans http://www.gregoryrowlandevans.com https://github.com/GregoryREvans https://soundcloud.com/gregory-rowland-evans