Direction operators in event-function

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Direction operators in event-function

Urs Liska-3
I'm scratching my head  thanks to some weird behaviour (at least it
looks like that for me). In a simple event-function any explicit
direction operator used when calling the event will be propagated to the
created objects:

\version "2.19.82"

propagate-direction =
#(define-event-function (text)(markup?)
    #{
      -\markup #text
    #})

{
   g'1 ^\propagate-direction "Up"
}

When I use explicit tweaks I can specify directions for multiple
elements as well (but independently from any direction operators):

propagate-direction =
#(define-event-function (text)(markup?)
    #{
      -\tweak direction #UP
      -(
      -\tweak direction #UP
      -\markup #text
    #})

{
   g'1 \propagate-direction "Up" g' )
}

But if I simply create two elements in the event-function the explicit
direction operator takes no effect:

propagate-direction =
#(define-event-function (text)(markup?)
    #{
      -(
      -\markup #text
    #})

{
   g'1 ^\propagate-direction "Up" g' )
}

(here both the slur and the text are printed below the staff.

Why is that?
And more importantly: how can I achieve the goal of creating more than
one element in an event-function and still have the explicit directions
from the calling code be applied?

And why can't I access the explicit direction operator from within the
event-function? I understand that the *generated* direction isn't
accessible at that moment, but an explicit setting should be known at
that point, isn't it?

Thanks
Urs


_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user
Reply | Threaded
Open this post in threaded view
|

Re: Direction operators in event-function

David Kastrup
Urs Liska <[hidden email]> writes:

> But if I simply create two elements in the event-function the explicit
> direction operator takes no effect:
>
> propagate-direction =
> #(define-event-function (text)(markup?)
>    #{
>      -(
>      -\markup #text
>    #})
>
> {
>   g'1 ^\propagate-direction "Up" g' )
> }
>
> (here both the slur and the text are printed below the staff.
>
> Why is that?

Multiple post events in one post event expression are temporarily
wrapped in one PostEvents music event.  This is then what gets the
up/down direction.  When it is unwrapped in use, the direction gets
lost.

Arguably, dissolving a PostEvents into separate events should try
applying some fields (tweaks, color, direction?).  Unfortunately, there
are a lot.  Alternatively, directions and tweaks should bypass
PostEvents and go through the enclosed events.  Either would have some
performance impact.  Maybe just walk the property list of a PostEvents
and copy _everything_ found there?

> And more importantly: how can I achieve the goal of creating more than
> one element in an event-function and still have the explicit
> directions from the calling code be applied?
>
> And why can't I access the explicit direction operator from within the
> event-function? I understand that the *generated* direction isn't
> accessible at that moment, but an explicit setting should be known at
> that point, isn't it?

I have no idea what you are talking about.  What do you mean with
"explicit direction operator" here?  What do you mean with "generated"
direction?  The only direction operator I see here is clearly applied
_after_ calling the event function.  It cannot magically affect
expressions you create inside of the function before the function even
returns.

--
David Kastrup

_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user
Reply | Threaded
Open this post in threaded view
|

Re: Direction operators in event-function

Urs Liska-3


Am 21.10.2018 um 16:58 schrieb David Kastrup:

> Urs Liska <[hidden email]> writes:
>
>> But if I simply create two elements in the event-function the explicit
>> direction operator takes no effect:
>>
>> propagate-direction =
>> #(define-event-function (text)(markup?)
>>     #{
>>       -(
>>       -\markup #text
>>     #})
>>
>> {
>>    g'1 ^\propagate-direction "Up" g' )
>> }
>>
>> (here both the slur and the text are printed below the staff.
>>
>> Why is that?
> Multiple post events in one post event expression are temporarily
> wrapped in one PostEvents music event.  This is then what gets the
> up/down direction.  When it is unwrapped in use, the direction gets
> lost.

I see, this explains the observations.

>
> Arguably, dissolving a PostEvents into separate events should try
> applying some fields (tweaks, color, direction?).  Unfortunately, there
> are a lot.  Alternatively, directions and tweaks should bypass
> PostEvents and go through the enclosed events.  Either would have some
> performance impact.  Maybe just walk the property list of a PostEvents
> and copy _everything_ found there?
>
>> And more importantly: how can I achieve the goal of creating more than
>> one element in an event-function and still have the explicit
>> directions from the calling code be applied?
>>
>> And why can't I access the explicit direction operator from within the
>> event-function? I understand that the *generated* direction isn't
>> accessible at that moment, but an explicit setting should be known at
>> that point, isn't it?
> I have no idea what you are talking about.

Somehow I was afraid I didn't express myself clearly enough :-(

> What do you mean with
> "explicit direction operator" here?  What do you mean with "generated"
> direction?

With explicit I refer to a direction explicitly assigned, either thorugh
^/_ or an \override like \slurUp etc. If I call my function with
^\propagate-direction there is an explicit direction in place while the
event-function is called, isn't it? If OTOH I call it with
-\propagate-direction or without an operator the direction will only be
generated/calculated at some later point, depending on the layout
algorithms.
Is that correct or am I missing something?

What I would *like* to do is a function like

propagate-direction =
#(define-event-function (text)(markup?)
    #{
      -\tweak direction #UP
      -(
      -\tweak direction #UP
      -\markup #text
    #})

but instead of hard-coding #UP I'd like to calculate the values based on
something. For example let the text have the opposite direction of the
slur and have the slur accept the ^\_ operator. From what I can
understand this information *should* be present at that moment, while
I'm aware that it is *not* possible to do the same relying on the
automatically determined direction of the slur (which is only calculated
later).

Does that make my question clearer?

Urs

> The only direction operator I see here is clearly applied
> _after_ calling the event function.  It cannot magically affect
> expressions you create inside of the function before the function even
> returns.
>


_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user
Reply | Threaded
Open this post in threaded view
|

Re: Direction operators in event-function

David Kastrup
Urs Liska <[hidden email]> writes:

> Am 21.10.2018 um 16:58 schrieb David Kastrup:
>> Urs Liska <[hidden email]> writes:
>>
>>> But if I simply create two elements in the event-function the explicit
>>> direction operator takes no effect:
>>>
>>> propagate-direction =
>>> #(define-event-function (text)(markup?)
>>>     #{
>>>       -(
>>>       -\markup #text
>>>     #})
>>>
>>> {
>>>    g'1 ^\propagate-direction "Up" g' )
>>> }
>>>
>>> (here both the slur and the text are printed below the staff.
>>>
>>> Why is that?
>> Multiple post events in one post event expression are temporarily
>> wrapped in one PostEvents music event.  This is then what gets the
>> up/down direction.  When it is unwrapped in use, the direction gets
>> lost.
>
> I see, this explains the observations.

It's also arguably a bug or at least a disservice (just because it's
straightforward to explain how behavior comes about does not make it
correct).

>>> And why can't I access the explicit direction operator from within the
>>> event-function? I understand that the *generated* direction isn't
>>> accessible at that moment, but an explicit setting should be known at
>>> that point, isn't it?
>> I have no idea what you are talking about.
>
> Somehow I was afraid I didn't express myself clearly enough :-(
>
>> What do you mean with
>> "explicit direction operator" here?  What do you mean with "generated"
>> direction?
>
> With explicit I refer to a direction explicitly assigned, either
> thorugh ^/_ or an \override like \slurUp etc. If I call my function
> with ^\propagate-direction there is an explicit direction in place
> while the event-function is called, isn't it?

No.  I have no idea how you think direction operators work.  They don't
magically change the meaning of expressions such as

#{ -\markup #text #}

Expressions are evaluated from inside to outside, like with basically
every computer language implementing operators.

> If OTOH I call it with -\propagate-direction or without an operator
> the direction will only be generated/calculated at some later point,
> depending on the layout algorithms.  Is that correct or am I missing
> something?

You are missing something.  -postevent leaves postevent as-is,
^postevent sets it direction to #UP , _postevent sets it direction to
#DOWN .  Before it can do anything with that postevent, the postevent
has to be _there_ in the first place, like it is when being returned by
an event function.

> What I would *like* to do is a function like
>
> propagate-direction =
> #(define-event-function (text)(markup?)
>    #{
>      -\tweak direction #UP
>      -(
>      -\tweak direction #UP
>      -\markup #text
>    #})
>
> but instead of hard-coding #UP I'd like to calculate the values based
> on something. For example let the text have the opposite direction of
> the slur and have the slur accept the ^\_ operator.

Even assuming PostEvents are fixed, you'd still be stuck having to look
at one event from another, independent one.  You'd be missing a reliable
handle for that.  You'd need to use an engraver for doing that kind of
interaction.

> From what I can understand this information *should* be present at
> that moment,

I have no idea what you mean with "that moment".  There is no musical
moment while music is being input, that is only available when
iterating.  And if you mean "that point of input processing" this is
nonsense since ^ and _ cannot affect an input expression before it has
been returned by the event function.

> while I'm aware that it is *not* possible to do the same relying on
> the automatically determined direction of the slur (which is only
> calculated later).
>
> Does that make my question clearer?

Not to me.  The words you use do not make sense with regard how LilyPond
can be reasonably expected to process input.  I just don't see any
viable connection between the handwaving expectations expressed therein
and any feasible manner of implementation.  So when you use sort-of
technical terms, I have no idea how to map them to the actual things
happening.

>> The only direction operator I see here is clearly applied _after_
>> calling the event function.  It cannot magically affect expressions
>> you create inside of the function before the function even returns.

Still the essence of my problem with your statements.

--
David Kastrup

_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user
Reply | Threaded
Open this post in threaded view
|

Re: Direction operators in event-function

David Kastrup
David Kastrup <[hidden email]> writes:

> Urs Liska <[hidden email]> writes:
>
>> What I would *like* to do is a function like
>>
>> propagate-direction =
>> #(define-event-function (text)(markup?)
>>    #{
>>      -\tweak direction #UP
>>      -(
>>      -\tweak direction #UP
>>      -\markup #text
>>    #})
>>
>> but instead of hard-coding #UP I'd like to calculate the values based
>> on something. For example let the text have the opposite direction of
>> the slur and have the slur accept the ^\_ operator.
>
> Even assuming PostEvents are fixed, you'd still be stuck having to
> look at one event from another, independent one.  You'd be missing a
> reliable handle for that.  You'd need to use an engraver for doing
> that kind of interaction.

Correction: you could put a callback into a direction tweak on the text
event and this callback could check the _text_ event's direction and
then assume the _opposite_.  So after "assuming PostEvents are fixed"
should more or less work for this particular scenario, but

\tweak direction #UP \propagate-direction

would then override both tweaks.  I mean, you could still override with
a callback that reverses direction only on markup grobs but things get
increasingly murky and awkward when trying to do stuff like that.

--
David Kastrup

_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user
Reply | Threaded
Open this post in threaded view
|

Re: Direction operators in event-function

Urs Liska-3
In reply to this post by David Kastrup



Am 21.10.2018 um 17:52 schrieb David Kastrup:
With explicit I refer to a direction explicitly assigned, either
thorugh ^/_ or an \override like \slurUp etc. If I call my function
with ^\propagate-direction there is an explicit direction in place
while the event-function is called, isn't it?
No.  I have no idea how you think direction operators work.  They don't
magically change the meaning of expressions such as

#{ -\markup #text #}

Expressions are evaluated from inside to outside, like with basically
every computer language implementing operators.

If OTOH I call it with -\propagate-direction or without an operator
the direction will only be generated/calculated at some later point,
depending on the layout algorithms.  Is that correct or am I missing
something?
You are missing something.  -postevent leaves postevent as-is,
^postevent sets it direction to #UP , _postevent sets it direction to
#DOWN .  Before it can do anything with that postevent, the postevent
has to be _there_ in the first place, like it is when being returned by
an event function.


Well, this explains my misunderstanding, and there's not much sense in trying to clarify all the follow-up misunderstandings. I mistook the direction operators to work like arguments passing information into the event-function which would then transparently be used inside.

If I have a fresh mind tomorrow I'll see how I can use this new understanding to solve my tasks ...

Urs


_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user
Reply | Threaded
Open this post in threaded view
|

Re: Direction operators in event-function

Urs Liska-3
In reply to this post by David Kastrup


Am 21.10.2018 um 18:17 schrieb David Kastrup:

> David Kastrup <[hidden email]> writes:
>
>> Urs Liska <[hidden email]> writes:
>>
>>> What I would *like* to do is a function like
>>>
>>> propagate-direction =
>>> #(define-event-function (text)(markup?)
>>>     #{
>>>       -\tweak direction #UP
>>>       -(
>>>       -\tweak direction #UP
>>>       -\markup #text
>>>     #})
>>>
>>> but instead of hard-coding #UP I'd like to calculate the values based
>>> on something. For example let the text have the opposite direction of
>>> the slur and have the slur accept the ^\_ operator.
>> Even assuming PostEvents are fixed, you'd still be stuck having to
>> look at one event from another, independent one.  You'd be missing a
>> reliable handle for that.  You'd need to use an engraver for doing
>> that kind of interaction.
> Correction: you could put a callback into a direction tweak on the text
> event and this callback could check the _text_ event's direction and
> then assume the _opposite_.  So after "assuming PostEvents are fixed"
> should more or less work for this particular scenario,

My impression is: no. When I tried that I got a
"calculation-in-progress" error.

It seems that my initial misunderstanding led me to try getting
something that isn't really available, so I finally changed the approach
and seem to be reasonably successful. If the user wants slur and text on
opposite sides this has to be explicitly specified, and then the
directions can be taken from the given argument. If OTOH they are on the
same side then the text will not be printed by creating a second event
but by combining both in a modified slur stencil where the staff-padding
property is emulated by manually calculating the necessary distance from
the slur. (

Thank you anyway for the explanations.
Urs

PS: For future reference here's the implementation I arrived at
(expecting oll-core for the option handling)

\registerOption markup-staff-padding 2.5
annotateSlur =
#(define-event-function (min-padding text)((number? 1) markup?)
    "Create a slur with an attached markup."
    #{
      -\tweak after-line-breaking
      #(lambda (grob)
         (let*
          ((dir (ly:grob-property grob 'direction))
           ;; staff-padding from the options
           (staff-padding (getOption '(markup-staff-padding)))
           ;; The original slur stencil
           (stencil (ly:slur::print grob))
           ;; A new stencil for the markup
           (markup-stencil (grob-interpret-markup grob text))
           ;; Y-extent of the original slur for later reference
           (slur-extent (ly:grob-property grob 'Y-extent))
           ;; total height of slur
           (slur-height (- (cdr slur-extent) (car slur-extent)))
           ;; absolute distance of outer slur edge from middle staffline
           (outer-slur-edge-abs
            (abs (if (> dir 0) (cdr slur-extent) (car slur-extent))))
           ;; Y-extent of the added markup stencil
           (markup-extent (ly:stencil-extent markup-stencil Y))
           ;; total height of markup
           (markup-height (- (cdr markup-extent) (car markup-extent)))
           ;; height of lower extender or X height, depending on direction
           (markup-inner-height
            (if (> dir 0)
                (* -1 (car markup-extent))
                (cdr markup-extent)))
           ;; offset because staff-padding *below* staff is increased by 1
           (direction-offset (if (> dir 0) 0 -1))
           ;; padding between slur and markup, based on both the min-padding
           ;; argument and the global markup-staff-padding option
           (effective-padding
            (max
             (- (+ staff-padding 2)
               markup-inner-height
               direction-offset
               outer-slur-edge-abs)
             min-padding))
           ;; necessary horizontal shift to center the markup against the slur
           (hshift (- (interval-center (ly:stencil-extent stencil X))
                     (interval-center (ly:stencil-extent markup-stencil X))))
           ;; combined stencil from slur and text
           (new-stencil
            (ly:stencil-combine-at-edge stencil Y dir
              (ly:stencil-translate-axis markup-stencil hshift X)
              effective-padding)))
          ;; enclose the *new* stencil by the modified Y-extent
          ;; NOTE: this only makes the whole thing *clickable*, it doesn't
          ;; help with pushing the staff towards the bottom of the page.
          (ly:grob-set-property! grob 'Y-extent
            (if (> dir 0)
                (cons
                 (car slur-extent)
                 (+ (car slur-extent) slur-height effective-padding markup-height))
                (cons
                 (- (car slur-extent) effective-padding markup-height)
                 (cdr slur-extent))))
          (ly:grob-set-property! grob 'stencil new-stencil)))
      % NOTE: this is a slur-event, not a misplaced parenthesis
      (
    #})

> but
>
> \tweak direction #UP \propagate-direction
>
> would then override both tweaks.  I mean, you could still override with
> a callback that reverses direction only on markup grobs but things get
> increasingly murky and awkward when trying to do stuff like that.
>


_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user
Reply | Threaded
Open this post in threaded view
|

Re: Direction operators in event-function

David Kastrup
Urs Liska <[hidden email]> writes:

> Am 21.10.2018 um 18:17 schrieb David Kastrup:
>> David Kastrup <[hidden email]> writes:
>>
>>> Urs Liska <[hidden email]> writes:
>>>
>>>> What I would *like* to do is a function like
>>>>
>>>> propagate-direction =
>>>> #(define-event-function (text)(markup?)
>>>>     #{
>>>>       -\tweak direction #UP
>>>>       -(
>>>>       -\tweak direction #UP
>>>>       -\markup #text
>>>>     #})
>>>>
>>>> but instead of hard-coding #UP I'd like to calculate the values based
>>>> on something. For example let the text have the opposite direction of
>>>> the slur and have the slur accept the ^\_ operator.
>>> Even assuming PostEvents are fixed, you'd still be stuck having to
>>> look at one event from another, independent one.  You'd be missing a
>>> reliable handle for that.  You'd need to use an engraver for doing
>>> that kind of interaction.
>> Correction: you could put a callback into a direction tweak on the text
>> event and this callback could check the _text_ event's direction and
>> then assume the _opposite_.  So after "assuming PostEvents are fixed"
>> should more or less work for this particular scenario,
>
> My impression is: no. When I tried that I got a
> "calculation-in-progress" error.

Event properties are not evaluated using callbacks, so checking the text
event's direction cannot result in calculation-in-progress.  You
probably checked the text grob's direction instead.

--
David Kastrup

_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user
Reply | Threaded
Open this post in threaded view
|

Re: Direction operators in event-function

David Kastrup
In reply to this post by David Kastrup
David Kastrup <[hidden email]> writes:

> Urs Liska <[hidden email]> writes:
>
>> But if I simply create two elements in the event-function the explicit
>> direction operator takes no effect:
>>
>> propagate-direction =
>> #(define-event-function (text)(markup?)
>>    #{
>>      -(
>>      -\markup #text
>>    #})
>>
>> {
>>   g'1 ^\propagate-direction "Up" g' )
>> }
>>
>> (here both the slur and the text are printed below the staff.
>>
>> Why is that?
>
> Multiple post events in one post event expression are temporarily
> wrapped in one PostEvents music event.  This is then what gets the
> up/down direction.  When it is unwrapped in use, the direction gets
> lost.
>
> Arguably, dissolving a PostEvents into separate events should try
> applying some fields (tweaks, color, direction?).  Unfortunately, there
> are a lot.  Alternatively, directions and tweaks should bypass
> PostEvents and go through the enclosed events.  Either would have some
> performance impact.  Maybe just walk the property list of a PostEvents
> and copy _everything_ found there?

Tracker issue: 5433 (https://sourceforge.net/p/testlilyissues/issues/5433/)
Rietveld issue: 343440043 (https://codereview.appspot.com/343440043)
Issue description:
  Transfer post-event-wrapper properties when unwrapping  Sometimes
  multiple post-events are wrapped in one PostEvents music event
  temporarily.  When tweaks or direction modifiers or other property
  changes are applied to those, they are now transfered to the
  contained elements when unwrapping in order not to get lost.

--
David Kastrup

_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user