Search code examples
rustrust-piston

What is the idiomatic way in Rust to store a collection of objects to be used as Piston textures or sprites?


All the examples I've seen for getting access to a texture object is to do something like the following:

let img = Texture::from_path(...) 

This gives the impression that in order to have an array of textures it should be something like let mut images: Vec<Texture>;, but from_path returns a Result<Texture<R>, String>.

And its the Texture<R> that is really getting in the way. In order to be able make a Texture<R>, an awful lot of crates and use ... are needed and it feels completely wrong.

Is the right thing:

let loaded_textures:Vec<Option<T>> = Texture::from_path(...)

Or pull in almost everything that Piston has? Or something else?

My goal is to have

struct Drawables {
    obj_name: &'static str,
    image: Texture<gfx_device_gl::Resources>, // or something else
}

let mut my_objects: Vec<Drawable>;

fn LoadDrawables(window: &mut PistonWindow) -> Vec<Drawable> {
    let assets = find_folder::Search::ParentsThenKids(3, 3)
        .for_folder("assets")
        .unwrap();
    let img1 = assets.join("some_img0.png");
    let img1 = Texture::from_path(
        &mut window.factory,
        &img1,
        Flip::None,
        &TextureSettings::new(),
    ).unwrap();
    let img2 = assets.join("some_img1.png");
    let img2 = Texture::from_path(
        &mut window.factory,
        &img2,
        Flip::None,
        &TextureSettings::new(),
    ).unwrap();
    vec![
        Drawable {
            obj_name: "orc",
            image: rogue,
        },
        Drawable {
            obj_name: "bat",
            image: floor,
        },
    ]
}

The crate I'm trying to avoid pulling in is gfx_device_gl. This create feels wrong to include, its seems a little to low level if I'm already including a game engine such as Piston.


Solution

  • You probably want to map over a collection of paths and create a texture for each. When collecting on an iterator of Results you can have them unwrapped and move the result to the outside of the final collection:

    let images: Result<Vec<Texture<_>>, String> = paths.iter()
        .map(|path| Texture::from_path(
                &mut *window.factory.borrow_mut(),
                &path,
                Flip::None,
                &TextureSettings::new())
        )
        .collect();
    

    You shouldn't need the R parameter for Texture<R> because it can be inferred from the Factory<R> instance that you get from PistonWindow, which is why I just put a _. In fact, you can reduce the type of images to just Result<Vec<_>> if you wanted to, as even that can be inferred.

    Disclaimer: I wasn't able to actually run this code where I am. But it should only need small changes if it doesn't work.