-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
One-to-many asset processing #21889
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
base: main
Are you sure you want to change the base?
One-to-many asset processing #21889
Conversation
08313c5 to
77091f1
Compare
JMS55
left a comment
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.
Very exciting! Left some feedback
- I really don't like the single vs multi naming. I think we need better naming.
- As someone not very familiar with the asset system, I don't quite get how the multi files get mapped to asset server concepts. Sub assets? Or?
- Do we support asset savers besides filesystems? How does this work with those?
| } | ||
| for (i, line) in bytes.lines().map(Result::unwrap).enumerate() { | ||
| let mut writer = writer_context | ||
| .write_multiple(Path::new(&format!("Line{i}.line"))) |
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.
write_multiple() in the loop, for writing a single item, feels kind of weird to me. Can we call it something else?
write_part, write_subasset, write_new_asset, ?
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.
Fair point! I tried renaming write_single and write_multiple to write_full and write_partial respectively. The naming here really sucks. We shouldn't use subasset because that's already taken and it has a completely different meaning here.
I want to make sure that the "full" vs "partial" are like antonyms (like single vs multiple). Just to give the intuition that these can't be mixed.
| } | ||
| ``` | ||
|
|
||
| Then if you have an asset like `shakespeare.txt`, you can load these separate files as |
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.
Can we show some code for that?
How are these represented in terms of bevy's asset system? Are they subassets? I don't remember how things like meshes within gltf files are represented and how to load subparts of it and the different asset_server.load() syntax, and how that all maps together.
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 gave one example.
They are effectively completely separate assets. The Process trait has no idea about subassets. Writing "multiple"/"partial" files just writes a new file that you can point the asset server at.
| from scratch within the asset processor! | ||
|
|
||
| We plan to use this to break apart large glTF files into smaller, easier-to-load pieces - | ||
| particularly for producing meshlets. |
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.
| particularly for producing meshlets. | |
| particularly for producing virtual geometry meshes. |
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!
| Process { | ||
| processor: String, | ||
| settings: ProcessSettings, | ||
| }, |
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 is essentially saying "once an asset is processed into multiple new assets, you can't load the original asset anymore"? Can we state it more like that if so?
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.
That's a much more obvious way to put it! I slightly reworded it, but overall the same.
|
|
||
| /// Start writing a single output file, which can be loaded with the `load_settings`. | ||
| /// | ||
| /// Returns an error if you have previously started writing. |
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.
started writing <with either of the two apis>
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 actually changed this to specifically mention "partial" writes - since it's now impossible to call single twice (since it takes an owned self).
andriyDev
left a comment
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.
To respond to your questions:
- Good point! Discussed in a comment.
- Multi-files are just treated as individual assets. There is no requirement that subassets map to some multi-file. If the process wants to throw out the bytes of the original asset and write 100 copies of the Bee Movie script, that's totally up to it!
- The
Processtrait has no inherent relationship toAssetSaver, both before and after this PR. TheAssetSaveris used by the particularProcessimplementationLoadTransformAndSave, which makes it slightly more convenient to writeProcessimplementations. We could figure out a similar convenience for one-to-many, but I think we should leave that for another PR, since that seems a little tricky to get right, and I don't think we need it for a glTF processor.
| Process { | ||
| processor: String, | ||
| settings: ProcessSettings, | ||
| }, |
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.
That's a much more obvious way to put it! I slightly reworded it, but overall the same.
| } | ||
| ``` | ||
|
|
||
| Then if you have an asset like `shakespeare.txt`, you can load these separate files as |
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 gave one example.
They are effectively completely separate assets. The Process trait has no idea about subassets. Writing "multiple"/"partial" files just writes a new file that you can point the asset server at.
|
|
||
| /// Start writing a single output file, which can be loaded with the `load_settings`. | ||
| /// | ||
| /// Returns an error if you have previously started writing. |
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 actually changed this to specifically mention "partial" writes - since it's now impossible to call single twice (since it takes an owned self).
| from scratch within the asset processor! | ||
|
|
||
| We plan to use this to break apart large glTF files into smaller, easier-to-load pieces - | ||
| particularly for producing meshlets. |
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!
| } | ||
| for (i, line) in bytes.lines().map(Result::unwrap).enumerate() { | ||
| let mut writer = writer_context | ||
| .write_multiple(Path::new(&format!("Line{i}.line"))) |
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.
Fair point! I tried renaming write_single and write_multiple to write_full and write_partial respectively. The naming here really sucks. We shouldn't use subasset because that's already taken and it has a completely different meaning here.
I want to make sure that the "full" vs "partial" are like antonyms (like single vs multiple). Just to give the intuition that these can't be mixed.
…cessing doesn't rerun if nothing has changed.
…nd "ghost meta files".
… an asset to prevent failing to process.
…y asset processing.
7cf4977 to
c8f2933
Compare
Objective
Solution
&mut WritertoProcess, instead we pass aWriterContext. Users then just callwrite_singleorwrite_multipleto decide whether they want a single file or multiple files. Once users are done writing, they callSingleWriter::finishorMultipleWriter::finish.Decomposed. This makes it more obvious to callers that they are querying for the wrong asset.This means if you have an asset path like
path/to/my_asset.json, and theProcessproduces files "part1.thing", "part2.thing", and "dir/mesh.gltf", these assets will be accessible atpath/to/my_asset.json/part1.thing,path/to/my_asset.json/part2.thing, andpath/to/my_asset.json/dir/mesh.gltf. In essence, the asset in the unprocessed directory becomes a folder in the processed directory.Testing
asset_processingexample works and has been updated to include a "multiple" processor.