DigiScore / neoscore

A python library for notating music in a graphics-first paradigm
https://neoscore.org
BSD 3-Clause "New" or "Revised" License
108 stars 9 forks source link

Rotation #9

Open ajyoon opened 2 years ago

ajyoon commented 2 years ago

This is a tracking issue for support gaps relating to object rotation. Most of this is likely out of scope for the current release plan, but they are outlined here for tracking purposes.

Xavman42 commented 2 years ago

I would like to start tackling this issue. My hope is to get to the point where I can rotate staves about an axis and their children will also rotate about the same axis. I'm not worried about flowables or clipping issues - I can work around those for now.

Any suggestions on where how I can start?

ajyoon commented 2 years ago

That would be great! I'll need to take some time to sketch out a dev plan for this, but something we definitely need to support is low level rotation-about-an-axis. If you want to go ahead and add a transform_origin: Point field to the various interface classes which have a rotation field already, then integrate those fields into their underlying Qt objects, that would be a great start. You should be able to test this new field similarly to how rotation is tested, for example see TestTextInterface.test_rotation().

It looks like the corresponding Qt field for this is https://doc.qt.io/qt-5/qgraphicsitem.html#transformOriginPoint, which seems to set the scale origin point too. I'm fine with this change, but the docstrings around scaling should be updated to indicate this. (For now doc updates at the interface layer alone are enough, since this functionality isn't exposed to core yet.)

I've also just opened a new rotation development branch; please make your PRs against this branch then we'll merge it all together into main when it's ready.

ajyoon commented 2 years ago

Ok @Xavman42 the next step is to add the transform_origin field to the core layer and similarly plug it into the created interface objects and add unit tests for the plumbing.

After that, in a separate PR, will be the difficult step of figuring out how to actually compound translation, scaling, and rotation transformations. I have a feeling this might involve doing proper affine transforms instead of my bad homemade mapping methods (see PositionedObject.map_to), though maybe there's a way to hack it in the meantime..

ajyoon commented 2 years ago

another idea would be to change the interface layer so interface objects actually have parents, so we can use Qt's transform inheritance for free. off the top of my head I can't think of a reason this wouldn't work, and it's probably much simpler and faster than building our own parallel transform system.

ajyoon commented 2 years ago

yeah the more I think about it the more I like the idea of using the Qt scene graph to do the work for us. I may just do this myself since I think it would be fairly quick once your work is done, but I may ask for help depending on the time I have available.

I think the main complication is inside flowables, where we can't directly use the scene graph. maybe it's not so unreasonable to use the current system for flowable contexts, then use Qt's outside of them and say that rotation and scaling are not well supported inside flowables (which is already the case)

ajyoon commented 2 years ago

Ok transform origins seem to be working now! I'm going to take a crack at building out inherited transforms this week, will update on progress when I can

ajyoon commented 2 years ago

Still a ways to go, but today I made some progress - this is made with the following simple script:

prev = Text((ZERO, Mm(150)), None, "root")

for i in range(1, 11):
    prev = Text((Mm(20), ZERO), prev, f"desc_{i}", scale=1.1, rotation=5)

transforms

(ignore the dark background - it's a bug caused by this stuff)

ajyoon commented 2 years ago

I think I got it! Just need to clean up and update docs for this. Hoping to cut a release today or tomorrow.

rotation

Xavman42 commented 2 years ago

Wow! That looks perfect - thank you so much!

ajyoon commented 2 years ago

Support for inherited rotation and scaling has now been release in 0.1.7. See the release announcement here for more information. It required a few breaking changes so I recommend reading over it and the changelog.