bevy icon indicating copy to clipboard operation
bevy copied to clipboard

Improve `OrthographicCamera` consistency and usability

Open xgbwei opened this issue 3 years ago • 10 comments

Objective

  • Terminology used in field names and docs aren't accurate
  • window_origin doesn't have any effect when scaling_mode is ScalingMode::None
  • left, right, bottom, and top are set automatically unless scaling_mode is None. Fields that only sometimes give feedback are confusing.
  • Fixes #5818
  • Fixes #6190

Solution

  • Make public fields have an effect on every ScalingMode. They should also be much more intuitive. See changelog
  • Make left, right, bottom, and top private with getters; add constructor
  • Improve consistency in ScalingMode's arguments
  • Improve accuracy of terminology:
    • "Window" refers to the physical window managed by the desktop environment
    • "Viewport" refers to the part of the window (typically all of it) that images are drawn on
    • "View frustum" refers to the volume captured by the projection

Changelog

Added

  • Constructor using a pseudo builder pattern
  • Getters for left, right, bottom, and top
  • Argument to ScalingMode::WindowSize that specifies the number of pixels that equals one world unit. 1 pixel = 1 world unit usually makes the camera way too wide. This also makes it more consistent with other ScalingModes
  • Documentation for fields and enums

Changed

  • window_origin is renamed to viewport_origin and now affects every ScalingMode. It also takes a fraction of the viewport's width and height instead of an enum
  • Removed WindowOrigin enum as it's obsolete
  • ScalingMode::None to ScalingMode::Fixed, which now has arguments to specify the projection size
  • left, right, bottom, and top are made private
  • scale is applied before updating left, right, bottom, and top. Reading these values will now take scale into account
  • Documentation changes to make terminology more accurate and consistent

Migration Guide

  • Instantiate OrthographicProjection with constructor instead. Set the appropriate properties using builder methods
  • Change window_origin to viewport_origin; replace WindowOrigin::Center with (0.5, 0.5) and WindowOrigin::BottomLeft with (0.0, 0.0)
  • Change ScalingMode::None to ScalingMode::Fixed
  • Replace manual changes to left, right, bottom, and top with arguments in ScalingMode::Fixed to specify size and viewport_origin to specify offset
  • Replace reads from left, right, bottom, and top with corresponding getters
  • Change ScalingMode::WindowSize to ScalingMode::WindowSize(1.0)

xgbwei avatar Oct 08 '22 17:10 xgbwei

Ping @bzm3r for review.

alice-i-cecile avatar Oct 08 '22 17:10 alice-i-cecile

@alice-i-cecile shouldn't this be tagged with "breaking change"?

xgbwei avatar Oct 08 '22 19:10 xgbwei

Yep, thank you!

alice-i-cecile avatar Oct 08 '22 23:10 alice-i-cecile

I have a few minor suggestions but I like the changes! Worth noting this breaks the current 2d examples as is - they all appear way more zoomed in than they should be. But that's just a matter of adjusting the defaults to be closer to how it was before.

Oh, I didn't notice that. That's probably because I made the default for WindowSize 10 since the camera is usually way too zoomed out by default, but I can change it back.

xgbwei avatar Oct 09 '22 05:10 xgbwei

I’d like to take a look at this if I get time.

superdump avatar Oct 09 '22 12:10 superdump

I'm trying to add a separate "config" struct for initializing, but it's a bit of a mess (and might be unnecessarily complicated). Maybe using a builder or just a simple constructor would work better?

I'm not sure if there's enough fields to warrant a builder, but there's too many fields to fit into constructor parameters comfortably. Are there any methods that would make configurating the fields ergonomic but also allow defaults?

xgbwei avatar Oct 10 '22 19:10 xgbwei

Unfortunately no; you can't use struct update syntax unless the fields are pub. I think a builder pattern or an elaborate constructor is the way to go.

alice-i-cecile avatar Oct 10 '22 21:10 alice-i-cecile

Thanks for the change! I salute the documenting part which is much welcome ♥️ But I'm more skeptical about the builder pattern refactoring. For one, it feels those two changes are unrelated and should maybe be done in separate PRs. I also personally don't like the pattern so much, mostly as it increases inconsistency with the rest of the Bevy codebase.

I sort of agree with this. Do you have any suggestions for alternatives? Every other method I've looked at has had some other downside. I could also just leave the fields public.

xgbwei avatar Nov 08 '22 05:11 xgbwei

I sort of agree with this. Do you have any suggestions for alternatives? Every other method I've looked at has had some other downside. I could also just leave the fields public.

Because this is the recommended and promoted pattern in the rest of the codebase, yes I would just leave those as public fields for now. We can discuss whether this is the right pattern or not (I doubt we can convince anyone of a change at this point though), but I wouldn't make this object inconsistent unless there's an overwhelming benefit to the builder pattern, which I don't think we showed here.

djeedai avatar Nov 08 '22 07:11 djeedai

Because this is the recommended and promoted pattern in the rest of the codebase, yes I would just leave those as public fields for now. We can discuss whether this is the right pattern or not (I doubt we can convince anyone of a change at this point though), but I wouldn't make this object inconsistent unless there's an overwhelming benefit to the builder pattern, which I don't think we showed here.

That's fair. Clearly documenting that l/r/b/t should be for reading only should be fine for now.

xgbwei avatar Nov 08 '22 15:11 xgbwei

I've been kind of busy lately but I have some time this week for some minor fixes and to test examples. This should be ready for review after that.

xgbwei avatar Dec 07 '22 23:12 xgbwei

@xgbwei once this is rebased I'd like to merge it.

alice-i-cecile avatar Feb 06 '23 17:02 alice-i-cecile

Did I do that right?

xgbwei avatar Feb 08 '23 19:02 xgbwei

Rebase looks almost correct: you have an empty scene_viewer file :)

alice-i-cecile avatar Feb 08 '23 20:02 alice-i-cecile

bors r+

alice-i-cecile avatar Feb 08 '23 21:02 alice-i-cecile