-
-
Notifications
You must be signed in to change notification settings - Fork 899
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
feat: Implement Snapshot mixin on PositionComponent #2695
Merged
spydon
merged 20 commits into
flame-engine:main
from
projectitis:projectitis/2693-component-snapshot
Sep 12, 2023
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
08b7ed9
Implement Snapshot
projectitis a0f06aa
Documentation edits
projectitis 7e483eb
Update goldens
spydon 35996c2
Merge remote-tracking branch 'origin/main' into projectitis/2693-comp…
spydon 23cedb0
Merge branch 'main' into projectitis/2693-component-snapshot
spydon e624359
Merge branch 'main' into projectitis/2693-component-snapshot
spydon 6c0edf8
Merge branch 'main' into projectitis/2693-component-snapshot
spydon 55ddd83
Linting
projectitis 9701188
Merge branch 'main' into projectitis/2693-component-snapshot
projectitis 79f3bc8
Linting, docs
projectitis 4448db2
Revert introduced error in Layer docs
projectitis 3ae0edc
Trailing commas
projectitis 5bd4bfa
Example code fixes
projectitis 4e7a131
Spelling
projectitis 4730033
Fixed example code
projectitis 69db65f
Merge branch 'main' into projectitis/2693-component-snapshot
spydon 211c873
Update docs
projectitis ad9911b
md lint
projectitis 0b63e1e
Spelling
projectitis f689c08
Merge branch 'main' into projectitis/2693-component-snapshot
spydon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import 'dart:ui'; | ||
|
||
import 'package:flame/components.dart'; | ||
|
||
/// A mixin that enables caching a component and all its children. If | ||
/// [renderSnapshot] is set to `true`, the component and its children will be | ||
/// rendered to a cache. Subsequent renders use the cache, dramatically | ||
/// improving performance. This is only effective if the component and its | ||
/// children do not change - i.e. they are not animated and they do not move | ||
/// around relative to each other. | ||
/// | ||
/// The [takeSnapshot] and [snapshotAsImage] methods can also be used to take | ||
/// one-off snapshots for screen-grabs or other purposes. | ||
mixin Snapshot on PositionComponent { | ||
bool _renderSnapshot = true; | ||
Picture? _picture; | ||
|
||
/// If [renderSnapshot] is `true` then this component and all its children | ||
/// will be rendered once and cached. If [renderSnapshot] is `false` | ||
/// then this component will render normally. | ||
bool get renderSnapshot => _renderSnapshot; | ||
set renderSnapshot(bool value) { | ||
if (_renderSnapshot != value) { | ||
_renderSnapshot = value; | ||
if (_renderSnapshot == true) { | ||
_picture = null; | ||
} | ||
} | ||
} | ||
|
||
/// Check if a snapshot exists. | ||
bool get hasSnapshot => _picture != null; | ||
|
||
/// Grab the current snapshot. Check it exists first using [hasSnapshot]. | ||
Picture get snapshot { | ||
assert(_picture != null, 'No snapshot has been taken'); | ||
return _picture!; | ||
} | ||
|
||
/// Convert the snapshot to an image with the given [width] and [height]. | ||
/// Use [transform] to position the snapshot in the image, or to apply other | ||
/// transforms before the image is generated. | ||
Image snapshotAsImage(int width, int height, {Matrix4? transform}) { | ||
assert(_picture != null, 'No snapshot has been taken'); | ||
if (transform == null) { | ||
return _picture!.toImageSync(width, height); | ||
} else { | ||
final recorder = PictureRecorder(); | ||
final canvas = Canvas(recorder); | ||
canvas.transform(transform.storage); | ||
canvas.drawPicture(_picture!); | ||
final picture = recorder.endRecording(); | ||
return picture.toImageSync(width, height); | ||
} | ||
} | ||
|
||
/// Immediately take a snapshot and return it. If [renderSnapshot] is true | ||
/// then the snapshot is also used for rendering. A snapshot is always taken | ||
/// with no transformations (i.e. as if the Snapshot component is at position | ||
/// (0, 0) and has no scale or rotation applied). | ||
Picture takeSnapshot() { | ||
final recorder = PictureRecorder(); | ||
final canvas = Canvas(recorder); | ||
final matrix = transformMatrix.clone(); | ||
matrix.invert(); | ||
canvas.transform(matrix.storage); | ||
super.renderTree(canvas); | ||
_picture = recorder.endRecording(); | ||
return _picture!; | ||
} | ||
|
||
@override | ||
void renderTree(Canvas canvas) { | ||
if (renderSnapshot) { | ||
if (_picture == null) { | ||
takeSnapshot(); | ||
} | ||
canvas.save(); | ||
canvas.transform( | ||
transformMatrix.storage, | ||
); | ||
canvas.drawPicture(_picture!); | ||
canvas.restore(); | ||
} else { | ||
super.renderTree(canvas); | ||
} | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
while I think both sections below do a good job of describing each feature in a vacuum, I think this paragraph could give more details about what are the differences and what rationale I should use to choose one or the other
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've added a description. Please amend it if you don't agree!
To be honest, I'm not sure of when you might use a Layer instead of a Snapshot, unless you don't want the overhead of a position component. Layers support processors (of which there is only 1 so far, but more could be made). However processors are sort of doubling-up on
Effects
?This is what I have (below) -
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.
Layers and Snapshots
Layers and snapshots share some common features, including the ability to pre-render and cache
objects for improved performance. However, they also have unique features which make them better
suited for different use-cases.
Snapshot
is a mixin that can be added to anyPositionComponent
. Use this for:PositionComponents
).Layer
is a class. Use or extend this class for: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.
Let's keep it like that for now and then we can extend on that in a follow-up. :)