Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

We must stop using the "Offset" property to determine the default position of items #22622

Open
mike-spa opened this issue Apr 29, 2024 · 1 comment
Assignees

Comments

@mike-spa
Copy link
Contributor

mike-spa commented Apr 29, 2024

Issue type

A disastrous combination of UX and Engraving jank.

Summary

What follows is just an explanation and a collection of the most obvious issues which arise from this. I am sure parts of this have been reported before. All of these problems come back to one single original design error:

The "Offset" property must be reserved for the user's offset. It must not be used for the default positions of the program.

This is something which I've encountered over and over again. It has now surfaced yet again as a blocker for the new "Center between staves" feature, unless I find I way to circumvent the issue. I'm logging this now as an issue of its own, so it's there for when we can get to it. It will be a big project, not only because we will need to rewrite all the default positions of all the items without using offsets, but also because we have years and years of scores that were generated this way, so we'll have to do migrations etc.

Explanation and examples

In Musescore, the default position of many items is determined by pre-applying an offset to them. See for instance:
image

Essentially, we have a concept of "default offset". This is a disaster, and it keeps causing an insane amount of engraving issues and general UX jank (which corresponds to code jank and hacks and workarounds underneath).

  1. The concept of "default offset" is in itself contradictory. You offset something with respect to a default, or a reference point. A "default offset" is... not an offset. It is just the default position of the item on the score.

  2. From a UX point of view, it is confusing and inconsistent. If I click on other items, like notes, I find their default position to have zero offset. So I (correctly) interpret the "Offset" property to represent the user's chosen position with respect to the default one. But when I select the hairpin, like above, I'm contradicted, and I have to guess that in that case the offset is meant with respect to the bottom of the staff. So which is it?
    image

  3. The "default offset" is meant to determine the default position. But the default position is also determined by the autoplace system. Then consider this: what does a 2sp offset mean in this case? (Spoiler: nothing, it's absolutely meaningless).
    image

  4. The "Offset" property is still supposed to hold the user's customized movement, so we have one single variable (the offset) representing both a default position and a user position. Let's say I want that hairpin to be slightly further away from the note. So I enter 3sp in the vertical offset field and... nothing happens. Why? Because the autoplace has already moved that hairpin to a point that's further than 3sp from the staff.
    image

  5. When mouse-dragging an item, the dragging operation has to move the item with respect to the position that the user sees on screen. But that position was calculated by autoplace. But autoplace already took an offset into account (the default one). But now I'm dragging so I'm also adding new offset. This can (and does, often) cause things to "explode" when dragging items, cause it's easy to run into infinite loops. To avoid this, we do a hack of "rebasing" the offset. "Rebasing" means that we add to the offset value the movement that had already been done by the autoplace. So, as soon as I start draggins this hairpin, the offset value jumps from 2sp to 5sp, even though I haven't even moved it yet.
    image
    Then, say, I want to put the hairpin back to the default position. I would imagine that that's what I'd get if I'd reset the offset.
    image
    But no: because we're now in a "offset rebased" state, the offset will indeed go back to 2sp, but meant as the original "2sp below the staff", which means we get this.
    image

  6. Notice from the previous example that, when the hairpin ends up overlapping the note, the "Minimum distance" property has suddenly been updated to an inexplicable negative value. That's not a bug, it's done intentionally. Why? Because, since the offset is also used to determine default positions, the autoplace system must take offsets into account, ending up with a situation where the offset of an item affects the autoplace of itself. Say, in the next example, I need to save space, so I move that dynamic inside the staff. I do that by dragging (i.e. applying an offset to) it. If we left "Minimum distance" as normal, the autoplace would take my offset into account and therefore "offset my offset" in order to prevent the collision with the staff, effectively disallowing me to move the dynamic inside the staff. To circumvent this problem, we hack the minimum distance and set it to a large negative value, so that the autoplace will not interpret that as a collision and let us do what we want.
    image

Steps to reproduce

Just try using the offset property on basically any item for more than 30 seconds.

Screenshots/Screen recordings

No response

MuseScore Version

Current master

Regression

No.

Operating system

Any

Additional context

No response

@MarcSabatella
Copy link
Contributor

As you say, this is pretty deeply ingrained into the program and has definitely caused a lot of headache over the years as we tried to improve default layout without breaking existing scores. FWIW, the offset was originally always measured from a single reference point: the top staff line. So items below the staff like dynamics had offsets like 6 sp, which was obviously a huge problem when considering single-line staves, tab, etc. The ability to define separate default positions above/below was grafted on somewhat later. And then autoplace system later still.

Anyhow, I am definitely all in favor of a better system here. If/when you get around to this, I do have some insight into how older scores are represented, if that can be useful. Be aware that 1.x vs 2.x vs 3.x are all a bit different. Also, 3.0 is different from 3.1 and later - that's when the negative min distance hack was added to the original autoplace implementation, which required disabling autoplace to do almost anything useful and resulted in enormous pushback from users.

@oktophonie oktophonie added the P1 Priority: High label Jun 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: First release after the upcoming one
Development

No branches or pull requests

6 participants