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 <[email protected]> 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