-
-
Notifications
You must be signed in to change notification settings - Fork 922
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
fix: ViewportAwareBounds component and lifecycle issues #3276
fix: ViewportAwareBounds component and lifecycle issues #3276
Conversation
fix:
The ViewportAwareBounds
component and its lifecycle issuesfix:
The ViewportAwareBounds component and lifecycle issues
fix:
The ViewportAwareBounds component and lifecycle issuesThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the current behavior of the circle is fine, the behavior's main function is to restrict the movement of the viewfinder (the clipping can be done elsewhere).
Some tests would be good, so that we don't end up with regressions here later.
Here is the previous (very lacking) test:
https://github.com/flame-engine/flame/blob/main/packages/flame/test/camera/behaviors/viewport_aware_bounds_behavior_test.dart
void onChildrenChanged(Component child, ChildrenChangeType type) { | ||
super.onChildrenChanged(child, type); | ||
|
||
if (child is BoundedPositionBehavior) { | ||
final viewPortAwareBoundsBehavior = | ||
firstChild<ViewportAwareBoundsBehavior>(); | ||
if (type == ChildrenChangeType.added && camera.considerViewport) { | ||
final bounds = viewPortAwareBoundsBehavior?.boundsShape = child.bounds; | ||
// Failed to update because component was null. | ||
// We must add instead. | ||
if (bounds == null) { | ||
add( | ||
ViewportAwareBoundsBehavior( | ||
boundsShape: child.bounds, | ||
), | ||
); | ||
} | ||
} else { | ||
viewPortAwareBoundsBehavior?.removeFromParent(); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would do this within the setBounds
by listening to the mounted
completer of the BoundedPositionBehavior
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did at first but the code looked messy since the bound behavior can also be mounted already and that needed its own code-path to handle. The code was much simpler to read and understand here. Also, ViewportAwareBoundsBehavior
strictly depends on the existence of BoundedPositionBehavior
so trying to treat them as two separate classes seems incorrect to me. Putting the setup code here illustrates their relationship better.
If this is a final decision, I can revisit it tomorrow and move it back to the camera component setBounds
. Lemme know. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think that it is better to keep the code clean by not having dependencies in both directions here.
This way is also more expensive, even though it doesn't matter that much in the viewfinder, since it's quite rare to add many components it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about merging ViewportAwareBoundsBehavior
into BoundedPositionBehavior
and tossing the first?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The BoundedPositionBehavior
can be used without the ViewportAwareBoundsBehavior
, it can target anything that is a PositionProvider
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood.
@TheMaverickProgrammer any update on this? :) |
…sBehavior is now added as a side effect of mounting BoundedPositionBehavior by listening for Viewfinder.onChildrenChanged events. This gaurantees that Flames life cycle is respected and the components behave as expected. ViewportAwareBoundsBehavior._calculateViewportAwareBounds correctly calculates the new bounds by using viewport.virtualSize instead of the logical size. Also, some math was changed to be accurate. Tests pass on local project. Dry run completed successfully.
…nt's setBounds(). Expanded upon and verified unit tests.
cfa3230
to
41fb37f
Compare
Need to test something I forgot before pushing. I will re-open after verifying the mount operation happens correctly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one small comment, other than that it looks good
/// component is mounted correctly when the tree updates. | ||
/// | ||
/// The default value is false. | ||
bool get considerViewport => _considerViewport; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this should be clarified in the name that it is related to the viewfinder, since this is in the CameraComponent
. Or maybe the variable should live in the viewfinder instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it relates to a pre-existing convenience for the end-user, b/c of the effect of setBounds(considerViewport: true)
, adding a comment that this getter is related to the camera's view finder seems reasonable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This getter didn't exist before though, in the setBounds
method it is clear that considerViewport
is related to the bounds, meanwhile it isn't in the general CameraComponent
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you want to name it? The only thing that comes to mind is some variant of hasBoundsAwareViewport
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I can only come up with long names too, so I think it would be more natural to move it to the viewfinder, it's not something that the user should have to access often anyways (if ever).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super, thanks!
…. Changed description of the circle test cases to be more clear of their intention: the identical values are for two different outcomes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lgtm! Thanks for your contribution
# Description The behavior for `CameraComponent.setBounds` was not behaving correctly. The viewport-aware behavior was not triggering until a window resize event. All supported bound variants were not respecting the fixed resolution viewport, or in some cases, behaving unpredictably. The issue was with the fact the viewport-aware behavior component depends on the bounded position component to be in its parent, but was returning `null` during `onMount`. The viewport math was using the logical size instead of the virtual size. I made some math changes to be accurate. This PR adds new a getter `CameraComponent.considerViewport`. `ViewportAwareBoundsBehavior` is now added as a side effect of mounting `BoundedPositionBehavior` by waiting for the `mounted` future. This guarantees that Flames life cycle is respected and the components behave as expected. Tests pass on my own local project. Videos are linked on the discord thread [here](https://discord.com/channels/509714518008528896/1275814019235709003/1275888732481785925). Melos dry run completed successfully. ## Checklist - [x] I have followed the [Contributor Guide] when preparing my PR. - [x] I have updated/added tests for ALL new/updated/fixed functionality. - [x] I have updated/added relevant documentation in `docs` and added dartdoc comments with `///`. - [ ] I have updated/added relevant examples in `examples` or `docs`. ## Breaking Change? - [ ] Yes, this PR is a breaking change. - [x] No, this PR is not a breaking change. ### Migration instructions No work to be done. ## Related Issues #2769 ## QUESTIONS FOR THE DEVS So I'm not satisfied with the fixes for `Circle` bounds. The bounds uses the maxima of the viewport, and yes, creates a circle that stays within the size of the bounds circle, but I'd expect that `Circle` bounds should keep my viewport _inside_ the circle as it is documented to stay _inside_ the desired bounds shape. Therefore, I think `Circle` case should have 4 incident points to fit the viewport. That is to say, the viewport is not the maxima of the newly calculated `Circle`, but will be fully contained by this new `Circle`. This way, you'll never see outside of the bounds as it, seems to me anyway, implies. However I do not know if this is intuitive for others and expected behavior. Thoughts?
Description
The behavior for
CameraComponent.setBounds
was not behaving correctly. The viewport-aware behavior was not triggering until a window resize event. All supported bound variants were not respecting the fixed resolution viewport, or in some cases, behaving unpredictably.The issue was with the fact the viewport-aware behavior component depends on the bounded position component to be in its parent, but was returning
null
duringonMount
. The viewport math was using the logical size instead of the virtual size. I made some math changes to be accurate.This PR adds new a getter
CameraComponent.considerViewport
.ViewportAwareBoundsBehavior
is now added as a side effect of mountingBoundedPositionBehavior
by waiting for themounted
future. This guarantees thatFlames life cycle is respected and the components behave as expected.
Tests pass on my own local project.
Videos are linked on the discord thread here.
Melos dry run completed successfully.
Checklist
docs
and added dartdoc comments with///
.examples
ordocs
.Breaking Change?
Migration instructions
No work to be done.
Related Issues
#2769
QUESTIONS FOR THE DEVS
So I'm not satisfied with the fixes for
Circle
bounds. The bounds uses the maxima of the viewport, and yes, creates a circle that stays within the size of the bounds circle, but I'd expect thatCircle
bounds should keep my viewport inside the circle as it is documented to stay inside the desired bounds shape. Therefore, I thinkCircle
case should have 4 incident points to fit the viewport. That is to say, the viewport is not the maxima of the newly calculatedCircle
, but will be fully contained by this newCircle
. This way, you'll never see outside of the bounds as it, seems to me anyway, implies. However I do not know if this is intuitive for others and expected behavior. Thoughts?