Recipe: Loading external resource files

If you need to use any files that aren't explicitly supported by Godot's Resource Loader, it will be necessary to process and load the file yourself.

This recipe covers two methods of loading these files.

Option 1 - Embed the File into the Binary

The simplest way is to embed the resource directly into your binary by using the std::include_bytes macro.

To embed the file directly into the binary you can use the following macro:

#![allow(unused)]
fn main() {
// To have global immutable access to the file.
const RESOURCE: &'static [u8] = include_bytes!("path/to/resource/file");

fn process_the_resource() {
    // Include the file locally
    let bytes = include_bytes!("path/to/resource/file");
}
}

This can be useful for embedding any information that should be included at build time.

For example: such as if you wish to hard-code certain features like cheat codes, developer consoles, or default user configuration as a file rather than a build flag.

This approach is much more limited as it requires recompiling for all targets whenever changes to the resources are made.

Option 2 - Embed the File in the PCK

For most other use-cases you can use Godot's PCK file to export your resources into the game.

This can be accomplished by using the gdnative::api::File module as follows.

#![allow(unused)]

fn main() {
fn load_resource_as_string(filepath: &str) -> String {
    use gdnative::api::File;
    let file = File::new();
    file.open(filepath, File::READ).expect(&format!("{} must exist", filepath));
    
    let data: GodotString = file.get_as_text();
    // Depending upon your use-case you can also use the following methods depending upon your use-case.
    // let line: StringArray = file.get_csv_line(0);
    // let file_len = file.get_len();
    // let bytes: ByteArray = file.get_bytes(file_len);
    data.to_string()
}
}

See the File Class Documentation for every function that you use for loading the resources.

After you retrieve the data in the desired format, you can process it like you would normal Rust code.

Option #3 Save and Load filedata as user_data

Godot allows access to device side user directory for the project under "user://". This works very similar to loading above and it uses the gdnative::api::File API

Note: Saving only works on resource paths (paths starting with "res://") when Godot is being run in the editor. After exporting "res://" becomes read-only.

Example on writing and reading string data.

#![allow(unused)]
fn main() {
fn save_data_from_string(filepath: &str, data: &str) {
    use gdnative::api::File;
    let file = File::new();
    file.open(filepath, File::WRITE).expect(&format!("{} must exist", &filepath));
    
    file.store_string(data);
}


fn load_data_as_string(filepath: &str) -> String {
    use gdnative::api::File;
    let file = File::new();
    file.open(filepath, File::READ).expect(&format!("{} must exist", &filepath));
    
    let data: GodotString = file.get_as_text();
    data.to_string()
}
}

For more information on the paths, please refer to the File System Tutorial.

Testing

This section is for unit testing from Rust without loading Godot. As gdnative::api::File requires that Godot be running, any Rust-only unit tests will require a separate method to be implemented in order to load the resources. This can be accomplished by creating separate code paths or functions #[cfg(test)] and #[cfg(not(test))] attributes to differentiate between test configuration and Godot library configurations.

In test configurations, you will need to ensure that your loading code uses std::fs::File or some equivalent to read your load.

Exporting

When exporting your game, under the Resources Tab you will need to add a filter so that godot will pack those resources into the .pck file.

For example: If you are using .json, .csv and .ron files, you will need to use include *.json, *.csv, *.ron in the "Filters to Export non-resource files/folders" field.