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

Implement explicitly setting a center of rotation #783

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

mario-kr
Copy link

@mario-kr mario-kr commented May 25, 2023

Description

The transform-Widget provides "rotate" to rotate its child. However, the default center of rotation is (0, 0) (aka top-left), so it was not possible to, for example, rotate a child in-place.

This commit implements the additional options rotation-center-x and rotation-center-y. Both are optional, and the default value is 0.0 for each, so previous configurations should produce the same results.

Usage

(defwindow grid
  :stacking "fg"
  :windowtype "dock"
  :wm-ignore true
  :geometry (geometry
    :x "10px"
    :y "10px"
    :width "100px"
    :height "100px"
  )
  (transform
    :rotate {-percentloop}
    :rotation-center-x "50%"
    :rotation-center-y "50%"
    (box :orientation 'v' :style 'padding: 5px;'
      (box :orientation 'h'
        (label :style 'background-color: grey;' ' ')
        (label :style 'background-color: green;' ' ')
      )
      (box :orientation 'h'
        (label :style 'background-color: red;' ' ')
        (transform
          :rotate {2*percentloop}
          :rotation-center-x "50%"
          :rotation-center-y "50%"
          (box
            (box :space-evenly true
              (label :style 'background-color: yellow;' ' ')
              (label :style 'background-color: black;' ' ')
              (label :style 'background-color: yellow;' ' ')
            )
          )
        )
      )
    )
  )
)

(deflisten percentloop :initial 0 `i=0; while true; do let i=$i+1; echo $i; sleep .05; done`)
* {
    all: unset;
    margin: 0px;
    padding: 0px;
}

Showcase

I made a 5 second video of above configuration, but can't embed it here.

Additional Notes

  • There are artifacts, if, for example in the above configuration, the transform of the whole grid would be a static rotate. As this does not happen when everything is moving, maybe a redraw is missing somewhere.
  • The behaviour if both rotation-center-* and translate-* needs to be mentioned, though it is not "wrong". If an in-place/centered rotation is wanted, and a shift to the right, the shift to the right needs to be added on top of the rotation-center-value to get an in-place rotation.

Checklist

Please make sure you can check all the boxes that apply to this PR.

  • All widgets I've added are correctly documented.
  • I added my changes to CHANGELOG.md, if appropriate.
  • The documentation in the docs/content/main directory has been adjusted to reflect my changes.
  • I used cargo fmt to automatically format all code before committing

The transform-Widget provides "rotate" to rotate its child. However, the
default center of rotation is (0, 0) (aka top-left), so it was not
possible to, for example, rotate a child in-place.

This commit implements the additional options `rotation-center-x` and
`rotation-center-y`. Both are optional, and the default value is 0.0 for
each, so previous configurations should produce the same results.
@elkowar
Copy link
Owner

elkowar commented Jun 8, 2023

  • I feel like we would want the origin to be relative to the position of the widget, such that you don't need to add the translation to the rotation-center value -- especially given that you'll most likely want to use percentages for the origin
  • I'd just call it transform-origin, keeping the consistency with how the same thing is called in CSS
  • I'm not sure if I correctly understand the kind of artifacts you're referring to -- I'll see if I can reproduce them, but obviously optimally, there wouldn't be any visual artifacts here 😉

@mario-kr
Copy link
Author

mario-kr commented Jul 8, 2023

Hi, sorry for the late response; I'll try to answer point by point:

  • If I understand correctly, then the translate-x/-y values should be added onto the origin, so that e.g. 50%/50% origin will always turn out to be an in-place rotation? As for units, the current implementation understands both percentages and pixels, so maximum flexibility for the user.
  • I renamed the variables to transform-origin. I am a bit unsure, if this is the same as in CSS, though that may be based on my inexperience with CSS in general.
  • IIRC I only changed the first :rotate value to 95 or something similar.

According to the documentation, the current transform-order is: rotate -> translate -> scale. But, looking at the code (https://github.com/elkowar/eww/blob/master/crates/eww/src/widgets/transform.rs#L165) it seems to be: scale -> rotate -> translate
Point 1 might affect this order too; scale after all changes the size of a widget, so any other transformation might possibly be affected. On the other hand, the current implementation retrieves the allocated_width/height exactly once, and uses that same value for all transformations, so the transformation might currently actually be independent of each other (somewhat)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants