Skip to content

Commit caa7958

Browse files
committed
Added a recipe for loading godot-external recipes.
Fixed up requested additions to PR #34 Changes from additional feedback. Final fix to PR# 34 Squashing commits for final merge
1 parent 2bfa40c commit caa7958

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
- [Recipes](./recipes.md)
2525
- [Rust Panic Hook](./recipes/rust_panic_handler.md)
2626
- [Logging](./recipes/logging.md)
27+
- [Loading external resources](./recipes/loading_external_resources.md)
2728
- [Exporting](./exporting.md)
2829
- [Android](./exporting/android.md)
2930
- [(TODO) iOS](./exporting/ios.md)
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Loading External-Resource Files
2+
3+
If you need to use any files that aren't explicitly supported by Godot's [Resource Loader](https://docs.godotengine.org/en/stable/classes/class_resourceloader.html), it will be necessary to process and load the file yourself.
4+
5+
This recipe covers two methods of loading these files.
6+
7+
## Option 1 - Embed the File into the Binary
8+
9+
The simplest way is to embed the resource directly into your binary by using the `std::include_bytes` macro.
10+
11+
To embed the file directly into the binary you can use the following macro:
12+
13+
```rust
14+
// To have global immutable access to the file.
15+
const RESOURCE: &'static [u8] = include_bytes!("path/to/resource/file");
16+
17+
fn process_the_resource() {
18+
// Include the file locally
19+
let bytes = include_bytes!("path/to/resource/file");
20+
}
21+
```
22+
23+
This can be useful for embedding any information that should be included at build time.
24+
25+
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.
26+
27+
This approach is much more limited as it requires recompiling for all targets whenever changes to the resources are made.
28+
29+
## Option 2 - Embed the File in the PCK
30+
31+
For most other use-cases you can use Godot's PCK file to export your resources into the game.
32+
33+
This can be accomplished by using the `gdnative::api::File` module as follows.
34+
35+
```rust
36+
37+
fn load_resource_as_string(filepath: &str) -> String {
38+
use gdnative::api::File;
39+
let file = File::new();
40+
file.open(filepath, File::READ).expect(&format!("{} must exist", filepath));
41+
42+
let data: GodotString = file.get_as_text();
43+
// Depending upon your use-case you can also use the following methods depending upon your use-case.
44+
// let line: StringArray = file.get_csv_line(0);
45+
// let file_len = file.get_len();
46+
// let bytes: ByteArray = file.get_bytes(file_len);
47+
data.to_string()
48+
}
49+
```
50+
51+
See the [`File` Class Documentation](https://docs.rs/gdnative/latest/gdnative/api/struct.File.html) for every function that you use for loading the resources.
52+
53+
After you retrieve the data in the desired format, you can process it like you would normal Rust code.
54+
55+
## Option #3 Save and Load filedata as user_data
56+
57+
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
58+
59+
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.
60+
61+
Example on writing and reading string data.
62+
63+
```rust
64+
fn save_data_from_string(filepath: &str, data: &str) {
65+
use gdnative::api::File;
66+
let file = File::new();
67+
file.open(filepath, File::WRITE).expect(&format!("{} must exist", &filepath));
68+
69+
file.store_string(data);
70+
}
71+
72+
73+
fn load_data_as_string(filepath: &str) -> String {
74+
use gdnative::api::File;
75+
let file = File::new();
76+
file.open(filepath, File::READ).expect(&format!("{} must exist", &filepath));
77+
78+
let data: GodotString = file.get_as_text();
79+
data.to_string()
80+
}
81+
```
82+
83+
For more information on the paths, please refer to the [File System Tutorial](https://docs.godotengine.org/en/3.0/getting_started/step_by_step/filesystem.html#resource-path).
84+
85+
86+
### Testing
87+
88+
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.
89+
90+
In test configurations, you will need to ensure that your loading code uses `std::fs::File` or some equivalent to read your load.
91+
92+
### Exporting
93+
94+
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.
95+
96+
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.

0 commit comments

Comments
 (0)