bevy icon indicating copy to clipboard operation
bevy copied to clipboard

Panic on Loading Asset from Absolute Path

Open HulloImJay opened this issue 1 year ago • 2 comments

Bevy version

0.12.1 Also tested on commit hash: https://github.com/bevyengine/bevy/commit/41c362051cbfc57ecbaca57b8546a5695717b727

Relevant system information

Dell Precision 7670 Windows 11 Enterprise (10.0.22621 Build 22621)

What you did

I've been trying to load assets from absolute file paths (I'm making a small GLTF viewer which does not come pre-packaged with its models). Loading with asset_server.load() (where asset_server is Res<AssetServer>) worked okay in Bevy 0.11 but in 0.12 I hit problems.

For example:

commands.spawn((
    SceneBundle {
        // scene: asset_server.load(r"C:\Users\user\my-proj\assets\models\model.glb#Scene0"), // throws error
        scene: asset_server.load(r"models\model.glb#Scene0"), // works!
        ..default()
    },
    ModelInstance {},
));

I also tested this against absolute paths provided from drag-and-drop events.

What went wrong

I expected the two load() lines above to be equivalent, but if I use the one with the absolute path I get the following error and my application panics:

thread 'Compute Task Pool (15)' panicked at C:\Users\koceom0\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_asset-0.12.0\src\path.rs:458:70:
called `Result::unwrap()` on an `Err` value: InvalidSourceSyntax

I don't see anything about this specifically in the migration guide, so I'm assuming this is not expected behaviour.

Additional information

I was able to work around this issue by using the pathdiff crate to convert the absolute path into one which is relative to the current working directory. With this work-around it seems I'm able to load assets from anywhere on the system, confirming for me that issue above is not an access one.

HulloImJay avatar Jan 09 '24 18:01 HulloImJay

After looking at the line number from the panic message, I believe it is raised in AssetPath::parse_internal.

https://github.com/bevyengine/bevy/blob/4778fbeb65d840eb39bda017fd428ebfc17a1153/crates/bevy_asset/src/path.rs#L138-L150

My guess is that the code does not like the C:\ syntax at the beginning of the path. I think it was designed to extract the :// syntax commonly seen in URLs, but got tripped up when it saw the backslash.

BD103 avatar Jan 14 '24 17:01 BD103

So after some testing, absolute paths still seem to work on Unix-based systems, just not Windows.

use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn(Camera2dBundle::default());

    commands.spawn(SpriteBundle {
        texture: asset_server.load("/Users/bd103/Downloads/random_image.png"),
        ..default()
    });
}

I think an important to ask is whether you should load absolute paths outside of the assets/ folder. I could imagine some code making incorrect assumptions and breaking, such as what you just encountered.

On the other hand, Bevy doesn't really provide any other good way to load user-provided paths (such as through drag-and-drop). It seems to shame to have to manually call fs::open when a lot of useful logic is already pre-defined.

Edit: After talking on Discord, it seems like maybe a custom asset source should be created for paths outside of the assets folder.

BD103 avatar Jan 14 '24 18:01 BD103