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

Handle Serialization and Deserialization #2306

Closed
wants to merge 6 commits into from

Conversation

lassade
Copy link
Contributor

@lassade lassade commented Jun 6, 2021

Objective

Add serialization for Handle this will allows every type of bevy to implement Serialize and Deserialize this will also allows for scene and others data to also load all the dependencies with ease;

Usage

struct MyDataType {
    mesh_asset: Handle<Mesh>,
}

let data = asset_server.with_asset_refs_serialization(|| MyDataType::deserialize(&mut de));

asset_server.with_asset_refs_serialization(|| data.serialize(&mut ser));

will result in:

r#"MyDataType(mesh: External("path/to/mesh.glb#Mesh2"))"#
// or when the asset wasn't loaded from a file
r#"MyDataType(mesh: Local("8ecbac0f-f545-4473-ad43-e1f4243af51e", 12031280123816238))"#

Requiriments

Solves

Allow #2216 to be merged

@NathanSWard NathanSWard added A-Assets Load files from disk to use for things like images, models, and sounds C-Feature A new feature, making something new possible labels Jun 6, 2021
@lassade
Copy link
Contributor Author

lassade commented Jun 6, 2021

We need still need a way of pointing to static handles like PBR_PIPELINE_HANDLE

Edit: Done!

Copy link
Contributor

@NathanSWard NathanSWard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for opening this PR!!
Handle serialization is definitely something we need to support 😄

I know that there is work to incorporate distill for our asset library.
This would also be nice, as distill supports handle (de)serialization already.
However, I'm not sure how long that will take, so I'm more than happy to support our own version of handle (de)serialization :)

I left some initial comments, please let me know if I need to clarify anything!

crates/bevy_asset/src/ser.rs Outdated Show resolved Hide resolved
crates/bevy_asset/src/ser.rs Outdated Show resolved Hide resolved
crates/bevy_asset/src/ser.rs Show resolved Hide resolved
crates/bevy_asset/src/ser.rs Outdated Show resolved Hide resolved
@NathanSWard
Copy link
Contributor

Could you also add some tests for this?


use crate::{Asset, AssetServer, Handle, HandleId, HandleUntyped};

///////////////////////////////////////////////////////////////////////////////
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
///////////////////////////////////////////////////////////////////////////////

@lassade
Copy link
Contributor Author

lassade commented Jun 6, 2021

Could you also add some tests for this?

I'm using it elsewhere, so maybe later;

About panics on missing AssetServer when deserializing (the review disappeared to me)

I'm not sure if panic or not to panic, maybe a warning/error log will be better

Any weird behavior the game makes because of a missing asset or this will better than a crash;

@NathanSWard
Copy link
Contributor

NathanSWard commented Jun 6, 2021

I'm using it elsewhere, so maybe later;

Not quite sure what this means haha 😅
However, since this is a new feature addition, before this gets merged I would like to see a few tests 😉

I'm not sure if panic or not to panic, maybe a warning/error log will be better

Yea I'm not sure either.
It just feels weird for someone to want to (de)serialize something that contains a Handle and purposefully not have it actually point to the actual associated asset. If they wanted this behavior I would suggest they use Option<Handle> instead.

@NathanSWard NathanSWard added the S-Blocked This cannot move forward until something else changes label Jun 6, 2021
@lassade
Copy link
Contributor Author

lassade commented Jun 6, 2021

It's possible to reduce the amount of locks needed to query the asset paths down to 1

{
ASSET_SERVER.with(|key| {
key.replace(Some(self.clone()));
let result = T::deserialize(deserializer);
let result = (f)();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have an example use case of how this API is better than the previous one?
It worries me here that T is not constrained on Serialize or Deserialize

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the last API didn't allow to de::DeserializeSeed to be used for stateful de-serialization

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that makes sense.
However, I'm still not a big fan of just having the parameter be f: impl FnOnce() -> T.
you could give this any f that returns any type, which as a user of the function, isn't very informative.
If we could come up with some way to constrain T to better express that T needs to be serializable/deserializable via the AssetServer context, that would be best IMO.

value: &T,
) -> Result<S::Ok, S::Error>
/// Enables asset references to be serialized or deserialized
pub fn with_asset_refs_serialization<F, T>(&self, f: F) -> T
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you give f a more descriptive name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f, func are commonly used in this situations, anything in mind?

Copy link
Contributor

@NathanSWard NathanSWard Jun 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like serde_func (that expresses the functions does some sort of (de)serialization) would be nice.

@NathanSWard
Copy link
Contributor

This PR makes me wish serde had support for stateful (de)serialization

@lassade
Copy link
Contributor Author

lassade commented Jun 7, 2021

This PR makes me wish serde had support for stateful (de)serialization

But it does! but it you must do it manually implement it (witch is hard), that's why no one think it supports I guess, but you can find it on the docs.

This PR is motivated by this prefab plugin (https://github.com/lassade/bevy_prefab) it uses only stateful de-serialization to describe prefabs and entities and it's a WIP btw

@NathanSWard
Copy link
Contributor

But it does! but it you must do it manually implement it (witch is hard), that's why no one think it supports I guess, but you can find it on the docs.

Oh? I was aware of DeseralizeSeed however i didn't think there's was something similar for Seralize.

Perhaps I was conflating the word stateful with context.

More specifically I would like it to be able to have some context parameter that gets passed to the serialize function. So ideally our code would look like:

handle.seralze(&mut serializer, &asset_server);

So we can avoid the global state.

@lassade
Copy link
Contributor Author

lassade commented Jun 7, 2021

In that case you can do:

(&my_data, &mut my_state).serialize(serializer);

impl<'a> Serialize for (&'a MyData, &'a mut MyState) { ... }

But again, it must be impl down the chain to work, many types lets say pet_graph::Graph will not support stateful serialization/deserialization unless you run a hand made custom impl for it.

Thats just too much work to ask from users I think

@NathanSWard NathanSWard removed the S-Blocked This cannot move forward until something else changes label Jun 9, 2021
@cart cart added the S-Pre-Relicense This PR was made before Bevy added the Apache license. Cannot be merged or used for other work label Jul 23, 2021
@mockersf mockersf removed the S-Pre-Relicense This PR was made before Bevy added the Apache license. Cannot be merged or used for other work label Jul 24, 2021
@alice-i-cecile alice-i-cecile added the X-Controversial There is active debate or serious implications around merging this PR label Apr 25, 2022
.with(|cell| {
let server = cell.replace(None);
let path = server.as_ref().and_then(|server| {
// TODO: `get_handle_path` does absolutely nothing issue #1290
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been resolved.

Copy link
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts

I think the foundations of this are good, but it needs clean up.

I would like to see:

  • docs for AssetRef
  • an example or two for how this works
  • cleanup of the small nits
  • a trait bound on the serialization method

Due to the age, I'm going to apply the Adopt-Me label.

@alice-i-cecile alice-i-cecile added the S-Adopt-Me The original PR author has no intent to complete this work. Pick me up! label Oct 10, 2022
@MrGVSV
Copy link
Member

MrGVSV commented Oct 10, 2022

I wonder if this should instead be achieved through reflection, using something like #5923. Reflection would probably better integrate with scenes and such, as well as allow better control over these assets.

For example, the type registry could contain more metadata about an asset that is inserted on load, such as external URLs, dependencies, etc.— either in ReflectHandle or on a new type data.

@alice-i-cecile
Copy link
Member

Yep, I agree with your analysis there. Closing this out, but we can learn from this going forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Assets Load files from disk to use for things like images, models, and sounds C-Feature A new feature, making something new possible S-Adopt-Me The original PR author has no intent to complete this work. Pick me up! X-Controversial There is active debate or serious implications around merging this PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants