├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── api-change-notice.md
│ ├── book-error.md
│ ├── new-faq-entry.md
│ └── new-topic-proposal.md
└── workflows
│ └── cd.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── book.toml
├── config
└── mdbook-admonish.css
└── src
├── SUMMARY.md
├── advanced
├── custom-godot.md
├── index.md
├── migrate-0-10.md
├── migrate-0-8.md
└── migrate-0-9.md
├── bind
├── calling-gdscript.md
├── classes.md
├── index.md
├── methods.md
├── properties.md
└── traits.md
├── export
├── android.md
├── html5.md
├── index.md
├── ios.md
└── macosx.md
├── faq
├── code.md
├── community.md
├── configuration.md
├── godot4.md
├── img
│ ├── completion.png
│ └── no-completion.png
├── index.md
├── multithreading.md
└── support.md
├── index.md
├── intro
├── hello-world.md
├── img
│ ├── attach_resource.png
│ ├── attach_script.png
│ ├── create_resource.png
│ ├── create_resource_type.png
│ ├── create_script.png
│ ├── resource_path.png
│ └── resource_save.png
├── index.md
└── setup.md
├── overview
├── architecture.md
├── data-representations.md
├── img
│ ├── in-tree.png
│ ├── rust-game.png
│ └── rust-module.png
├── index.md
└── wrappers.md
├── projects
├── applications.md
├── games.md
├── img
│ ├── bendyworm.png
│ ├── bitgun.jpg
│ ├── cake-thieves.jpg
│ ├── godot-egui.gif
│ ├── the-process.jpg
│ └── the-recall-singularity.jpg
├── index.md
└── tools.md
└── recipes
├── async-tokio.md
├── custom-node-plugin.md
├── external-resources.md
├── index.md
├── logging.md
├── nix-build-system.md
└── panic-handler.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set the default behavior, in case people don't have core.autocrlf set.
2 | * text=auto eol=lf
3 | *.png binary
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/api-change-notice.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Outdated API
3 | about: 'This should be used when an API change in the main repo would invalidate information in the user-guide.'
4 | title: ''
5 | labels: outdated-api
6 | assignees: jacobsky
7 |
8 | ---
9 |
10 |
14 |
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/book-error.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Book error
3 | about: 'Report incorrect or confusing sections. For typos and grammar issues, please directly create a pull request instead.'
4 | title: ''
5 | labels: error
6 | assignees: ''
7 |
8 | ---
9 |
10 |
14 |
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/new-faq-entry.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: New question for the FAQ
3 | about: This is intended to request a specific question to be addressed that appears to be missing from the FAQ
4 | title: ""
5 | labels: faq
6 | assignees: ''
7 |
8 | ---
9 |
10 |
14 |
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/new-topic-proposal.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Propose a new topic
3 | about: Propose a new topic to be added to the godot-rust book.
4 | title: ''
5 | labels: new-topic
6 | assignees: ''
7 |
8 | ---
9 |
10 |
14 |
15 |
--------------------------------------------------------------------------------
/.github/workflows/cd.yml:
--------------------------------------------------------------------------------
1 | name: "Deploy to GitHub Pages"
2 |
3 | on:
4 | push:
5 | branches: [master]
6 |
7 | env:
8 | # Use fixed versions for now, replace with 'latest' to auto-use latest
9 | # Note: during build, there's a warning when using mdbook-toc compiled against an older mdbook version, should work though.
10 | MDBOOK_VERSION: "0.4.44"
11 | MDBOOK_TOC_VERSION: "0.14.2"
12 | MDBOOK_ADMONISH_VERSION: "1.18.0"
13 | MDBOOK_BIN: "/tmp/mdbook-bin"
14 |
15 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
16 | permissions:
17 | contents: read
18 | pages: write
19 | id-token: write
20 |
21 | jobs:
22 | build_and_deploy:
23 | runs-on: ubuntu-latest
24 |
25 | steps:
26 | # If using actions/checkout@v2, persist-credentials must be set to false in most cases for the deployment to work correctly.
27 | - name: "Checkout"
28 | uses: actions/checkout@v4
29 |
30 | # Note: actions-rs/install@v0.1 was considered, but a full 'cargo install' is unnecessarily slow and the cache mechanism is not reliable
31 | # (error "Unable to download mdbook == 0.4.14 from the tool cache: Error: Unexpected HTTP response: 403")
32 | # So, directly pull the release from GitHub
33 | - name: "Install mdbook, mdbook-toc, mdbook-admonish"
34 | run: |
35 | wget https://github.com/rust-lang/mdBook/releases/download/v${MDBOOK_VERSION}/mdbook-v${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz \
36 | -O /tmp/mdbook.tar.gz
37 | wget https://github.com/badboy/mdbook-toc/releases/download/${MDBOOK_TOC_VERSION}/mdbook-toc-${MDBOOK_TOC_VERSION}-x86_64-unknown-linux-gnu.tar.gz \
38 | -O /tmp/mdbook-toc.tar.gz
39 | wget https://github.com/tommilligan/mdbook-admonish/releases/download/v${MDBOOK_ADMONISH_VERSION}/mdbook-admonish-v${MDBOOK_ADMONISH_VERSION}-x86_64-unknown-linux-gnu.tar.gz \
40 | -O /tmp/mdbook-admonish.tar.gz
41 |
42 | mkdir ${MDBOOK_BIN}
43 | echo ${MDBOOK_BIN} >> $GITHUB_PATH
44 | tar -xvzf /tmp/mdbook.tar.gz -C ${MDBOOK_BIN}
45 | tar -xvzf /tmp/mdbook-toc.tar.gz -C ${MDBOOK_BIN}
46 | tar -xvzf /tmp/mdbook-admonish.tar.gz -C ${MDBOOK_BIN}
47 |
48 | - name: "Build book"
49 | run: mdbook build
50 |
51 | - name: "Upload Pages artifact"
52 | uses: actions/upload-pages-artifact@v3
53 | with:
54 | path: book
55 |
56 | - name: "Deploy to GitHub Pages"
57 | uses: actions/deploy-pages@v4
58 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | book/
2 | *~
3 | .DS_Store
4 | target
5 | tmp
6 | .vscode/
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # gdnative book
2 |
3 | The gdnative book is a user guide for the [gdnative library][gdnative], the Rust bindings to Godot 3.
4 |
5 | An online version of the book is available at [godot-rust.github.io/gdnative-book][book-web].
6 | For the gdext book (Godot 4), check out [gdext-book].
7 |
8 | The book is built with [mdBook] and the plugins [mdbook-toc] and [mdbook-admonish]. To install them and build the book locally, you can run:
9 | ```bash
10 | $ cargo install mdbook mdbook-toc mdbook-admonish
11 | $ mdbook build
12 | ```
13 |
14 | To run a local server with automatic updates while editing the book, use:
15 | ```bash
16 | $ mdbook serve --open
17 | ```
18 |
19 |
20 | ## Contributing
21 |
22 | This repository is for documentation only. Please open pull requests targeting the libraries themselves in the main repos for the [Godot 3] and [Godot 4] bindings.
23 |
24 | For contributions, see the contributing guidelines under `CONTRIBUTING.md` in the above-mentioned repositories.
25 |
26 |
27 | ## License
28 |
29 | Any contribution intentionally submitted for inclusion in the work by you shall be licensed under the [MIT license], without any additional terms or conditions.
30 |
31 | [gdnative]: https://github.com/godot-rust/gdnative
32 | [book-web]: https://godot-rust.github.io/gdnative-book
33 | [gdext-book]: https://github.com/godot-rust/book
34 | [mdBook]: https://github.com/rust-lang-nursery/mdBook
35 | [mdbook-toc]: https://github.com/badboy/mdbook-toc
36 | [mdbook-admonish]: https://github.com/tommilligan/mdbook-admonish
37 | [Godot 3]: https://github.com/godot-rust/gdnative
38 | [Godot 4]: https://github.com/godot-rust/gdext
39 | [MIT license]: LICENSE.md
40 |
--------------------------------------------------------------------------------
/book.toml:
--------------------------------------------------------------------------------
1 | [book]
2 | authors = ["The godot-rust developers"]
3 | multilingual = false
4 | src = "src"
5 | title = "The gdnative book"
6 |
7 | [preprocessor.toc]
8 | max-level = 3
9 | command = "mdbook-toc"
10 | renderer = ["html"]
11 |
12 | [preprocessor.admonish]
13 | command = "mdbook-admonish"
14 | assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
15 |
16 | [output.html]
17 | git-repository-url = "https://github.com/godot-rust/gdnative-book"
18 | additional-css = ["config/mdbook-admonish.css"]
19 |
20 | [output.html.redirect]
21 | # None, this is a fresh URL prefix.
22 |
--------------------------------------------------------------------------------
/config/mdbook-admonish.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | :is(.admonition) {
3 | display: flow-root;
4 | margin: 1.5625em 0;
5 | padding: 0 1.2rem;
6 | color: var(--fg);
7 | page-break-inside: avoid;
8 | background-color: var(--bg);
9 | border: 0 solid black;
10 | border-inline-start-width: 0.4rem;
11 | border-radius: 0.2rem;
12 | box-shadow: 0 0.2rem 1rem rgba(0, 0, 0, 0.05), 0 0 0.1rem rgba(0, 0, 0, 0.1);
13 | }
14 | @media print {
15 | :is(.admonition) {
16 | box-shadow: none;
17 | }
18 | }
19 | :is(.admonition) > * {
20 | box-sizing: border-box;
21 | }
22 | :is(.admonition) :is(.admonition) {
23 | margin-top: 1em;
24 | margin-bottom: 1em;
25 | }
26 | :is(.admonition) > .tabbed-set:only-child {
27 | margin-top: 0;
28 | }
29 | html :is(.admonition) > :last-child {
30 | margin-bottom: 1.2rem;
31 | }
32 |
33 | a.admonition-anchor-link {
34 | display: none;
35 | position: absolute;
36 | left: -1.2rem;
37 | padding-right: 1rem;
38 | }
39 | a.admonition-anchor-link:link, a.admonition-anchor-link:visited {
40 | color: var(--fg);
41 | }
42 | a.admonition-anchor-link:link:hover, a.admonition-anchor-link:visited:hover {
43 | text-decoration: none;
44 | }
45 | a.admonition-anchor-link::before {
46 | content: "§";
47 | }
48 |
49 | :is(.admonition-title, summary.admonition-title) {
50 | position: relative;
51 | min-height: 4rem;
52 | margin-block: 0;
53 | margin-inline: -1.6rem -1.2rem;
54 | padding-block: 0.8rem;
55 | padding-inline: 4.4rem 1.2rem;
56 | font-weight: 700;
57 | background-color: rgba(68, 138, 255, 0.1);
58 | print-color-adjust: exact;
59 | -webkit-print-color-adjust: exact;
60 | display: flex;
61 | }
62 | :is(.admonition-title, summary.admonition-title) p {
63 | margin: 0;
64 | }
65 | html :is(.admonition-title, summary.admonition-title):last-child {
66 | margin-bottom: 0;
67 | }
68 | :is(.admonition-title, summary.admonition-title)::before {
69 | position: absolute;
70 | top: 0.625em;
71 | inset-inline-start: 1.6rem;
72 | width: 2rem;
73 | height: 2rem;
74 | background-color: #448aff;
75 | print-color-adjust: exact;
76 | -webkit-print-color-adjust: exact;
77 | mask-image: url('data:image/svg+xml;charset=utf-8,');
78 | -webkit-mask-image: url('data:image/svg+xml;charset=utf-8,');
79 | mask-repeat: no-repeat;
80 | -webkit-mask-repeat: no-repeat;
81 | mask-size: contain;
82 | -webkit-mask-size: contain;
83 | content: "";
84 | }
85 | :is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link {
86 | display: initial;
87 | }
88 |
89 | details.admonition > summary.admonition-title::after {
90 | position: absolute;
91 | top: 0.625em;
92 | inset-inline-end: 1.6rem;
93 | height: 2rem;
94 | width: 2rem;
95 | background-color: currentcolor;
96 | mask-image: var(--md-details-icon);
97 | -webkit-mask-image: var(--md-details-icon);
98 | mask-repeat: no-repeat;
99 | -webkit-mask-repeat: no-repeat;
100 | mask-size: contain;
101 | -webkit-mask-size: contain;
102 | content: "";
103 | transform: rotate(0deg);
104 | transition: transform 0.25s;
105 | }
106 | details[open].admonition > summary.admonition-title::after {
107 | transform: rotate(90deg);
108 | }
109 |
110 | :root {
111 | --md-details-icon: url("data:image/svg+xml;charset=utf-8,");
112 | }
113 |
114 | :root {
115 | --md-admonition-icon--admonish-note: url("data:image/svg+xml;charset=utf-8,");
116 | --md-admonition-icon--admonish-abstract: url("data:image/svg+xml;charset=utf-8,");
117 | --md-admonition-icon--admonish-info: url("data:image/svg+xml;charset=utf-8,");
118 | --md-admonition-icon--admonish-tip: url("data:image/svg+xml;charset=utf-8,");
119 | --md-admonition-icon--admonish-success: url("data:image/svg+xml;charset=utf-8,");
120 | --md-admonition-icon--admonish-question: url("data:image/svg+xml;charset=utf-8,");
121 | --md-admonition-icon--admonish-warning: url("data:image/svg+xml;charset=utf-8,");
122 | --md-admonition-icon--admonish-failure: url("data:image/svg+xml;charset=utf-8,");
123 | --md-admonition-icon--admonish-danger: url("data:image/svg+xml;charset=utf-8,");
124 | --md-admonition-icon--admonish-bug: url("data:image/svg+xml;charset=utf-8,");
125 | --md-admonition-icon--admonish-example: url("data:image/svg+xml;charset=utf-8,");
126 | --md-admonition-icon--admonish-quote: url("data:image/svg+xml;charset=utf-8,");
127 | }
128 |
129 | :is(.admonition):is(.admonish-note) {
130 | border-color: #448aff;
131 | }
132 |
133 | :is(.admonish-note) > :is(.admonition-title, summary.admonition-title) {
134 | background-color: rgba(68, 138, 255, 0.1);
135 | }
136 | :is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before {
137 | background-color: #448aff;
138 | mask-image: var(--md-admonition-icon--admonish-note);
139 | -webkit-mask-image: var(--md-admonition-icon--admonish-note);
140 | mask-repeat: no-repeat;
141 | -webkit-mask-repeat: no-repeat;
142 | mask-size: contain;
143 | -webkit-mask-repeat: no-repeat;
144 | }
145 |
146 | :is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) {
147 | border-color: #00b0ff;
148 | }
149 |
150 | :is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) {
151 | background-color: rgba(0, 176, 255, 0.1);
152 | }
153 | :is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before {
154 | background-color: #00b0ff;
155 | mask-image: var(--md-admonition-icon--admonish-abstract);
156 | -webkit-mask-image: var(--md-admonition-icon--admonish-abstract);
157 | mask-repeat: no-repeat;
158 | -webkit-mask-repeat: no-repeat;
159 | mask-size: contain;
160 | -webkit-mask-repeat: no-repeat;
161 | }
162 |
163 | :is(.admonition):is(.admonish-info, .admonish-todo) {
164 | border-color: #00b8d4;
165 | }
166 |
167 | :is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) {
168 | background-color: rgba(0, 184, 212, 0.1);
169 | }
170 | :is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before {
171 | background-color: #00b8d4;
172 | mask-image: var(--md-admonition-icon--admonish-info);
173 | -webkit-mask-image: var(--md-admonition-icon--admonish-info);
174 | mask-repeat: no-repeat;
175 | -webkit-mask-repeat: no-repeat;
176 | mask-size: contain;
177 | -webkit-mask-repeat: no-repeat;
178 | }
179 |
180 | :is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) {
181 | border-color: #00bfa5;
182 | }
183 |
184 | :is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) {
185 | background-color: rgba(0, 191, 165, 0.1);
186 | }
187 | :is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before {
188 | background-color: #00bfa5;
189 | mask-image: var(--md-admonition-icon--admonish-tip);
190 | -webkit-mask-image: var(--md-admonition-icon--admonish-tip);
191 | mask-repeat: no-repeat;
192 | -webkit-mask-repeat: no-repeat;
193 | mask-size: contain;
194 | -webkit-mask-repeat: no-repeat;
195 | }
196 |
197 | :is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) {
198 | border-color: #00c853;
199 | }
200 |
201 | :is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) {
202 | background-color: rgba(0, 200, 83, 0.1);
203 | }
204 | :is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before {
205 | background-color: #00c853;
206 | mask-image: var(--md-admonition-icon--admonish-success);
207 | -webkit-mask-image: var(--md-admonition-icon--admonish-success);
208 | mask-repeat: no-repeat;
209 | -webkit-mask-repeat: no-repeat;
210 | mask-size: contain;
211 | -webkit-mask-repeat: no-repeat;
212 | }
213 |
214 | :is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) {
215 | border-color: #64dd17;
216 | }
217 |
218 | :is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) {
219 | background-color: rgba(100, 221, 23, 0.1);
220 | }
221 | :is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before {
222 | background-color: #64dd17;
223 | mask-image: var(--md-admonition-icon--admonish-question);
224 | -webkit-mask-image: var(--md-admonition-icon--admonish-question);
225 | mask-repeat: no-repeat;
226 | -webkit-mask-repeat: no-repeat;
227 | mask-size: contain;
228 | -webkit-mask-repeat: no-repeat;
229 | }
230 |
231 | :is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) {
232 | border-color: #ff9100;
233 | }
234 |
235 | :is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) {
236 | background-color: rgba(255, 145, 0, 0.1);
237 | }
238 | :is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before {
239 | background-color: #ff9100;
240 | mask-image: var(--md-admonition-icon--admonish-warning);
241 | -webkit-mask-image: var(--md-admonition-icon--admonish-warning);
242 | mask-repeat: no-repeat;
243 | -webkit-mask-repeat: no-repeat;
244 | mask-size: contain;
245 | -webkit-mask-repeat: no-repeat;
246 | }
247 |
248 | :is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) {
249 | border-color: #ff5252;
250 | }
251 |
252 | :is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) {
253 | background-color: rgba(255, 82, 82, 0.1);
254 | }
255 | :is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before {
256 | background-color: #ff5252;
257 | mask-image: var(--md-admonition-icon--admonish-failure);
258 | -webkit-mask-image: var(--md-admonition-icon--admonish-failure);
259 | mask-repeat: no-repeat;
260 | -webkit-mask-repeat: no-repeat;
261 | mask-size: contain;
262 | -webkit-mask-repeat: no-repeat;
263 | }
264 |
265 | :is(.admonition):is(.admonish-danger, .admonish-error) {
266 | border-color: #ff1744;
267 | }
268 |
269 | :is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) {
270 | background-color: rgba(255, 23, 68, 0.1);
271 | }
272 | :is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before {
273 | background-color: #ff1744;
274 | mask-image: var(--md-admonition-icon--admonish-danger);
275 | -webkit-mask-image: var(--md-admonition-icon--admonish-danger);
276 | mask-repeat: no-repeat;
277 | -webkit-mask-repeat: no-repeat;
278 | mask-size: contain;
279 | -webkit-mask-repeat: no-repeat;
280 | }
281 |
282 | :is(.admonition):is(.admonish-bug) {
283 | border-color: #f50057;
284 | }
285 |
286 | :is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) {
287 | background-color: rgba(245, 0, 87, 0.1);
288 | }
289 | :is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before {
290 | background-color: #f50057;
291 | mask-image: var(--md-admonition-icon--admonish-bug);
292 | -webkit-mask-image: var(--md-admonition-icon--admonish-bug);
293 | mask-repeat: no-repeat;
294 | -webkit-mask-repeat: no-repeat;
295 | mask-size: contain;
296 | -webkit-mask-repeat: no-repeat;
297 | }
298 |
299 | :is(.admonition):is(.admonish-example) {
300 | border-color: #7c4dff;
301 | }
302 |
303 | :is(.admonish-example) > :is(.admonition-title, summary.admonition-title) {
304 | background-color: rgba(124, 77, 255, 0.1);
305 | }
306 | :is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before {
307 | background-color: #7c4dff;
308 | mask-image: var(--md-admonition-icon--admonish-example);
309 | -webkit-mask-image: var(--md-admonition-icon--admonish-example);
310 | mask-repeat: no-repeat;
311 | -webkit-mask-repeat: no-repeat;
312 | mask-size: contain;
313 | -webkit-mask-repeat: no-repeat;
314 | }
315 |
316 | :is(.admonition):is(.admonish-quote, .admonish-cite) {
317 | border-color: #9e9e9e;
318 | }
319 |
320 | :is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) {
321 | background-color: rgba(158, 158, 158, 0.1);
322 | }
323 | :is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before {
324 | background-color: #9e9e9e;
325 | mask-image: var(--md-admonition-icon--admonish-quote);
326 | -webkit-mask-image: var(--md-admonition-icon--admonish-quote);
327 | mask-repeat: no-repeat;
328 | -webkit-mask-repeat: no-repeat;
329 | mask-size: contain;
330 | -webkit-mask-repeat: no-repeat;
331 | }
332 |
333 | .navy :is(.admonition) {
334 | background-color: var(--sidebar-bg);
335 | }
336 |
337 | .ayu :is(.admonition),
338 | .coal :is(.admonition) {
339 | background-color: var(--theme-hover);
340 | }
341 |
342 | .rust :is(.admonition) {
343 | background-color: var(--sidebar-bg);
344 | color: var(--sidebar-fg);
345 | }
346 | .rust .admonition-anchor-link:link, .rust .admonition-anchor-link:visited {
347 | color: var(--sidebar-fg);
348 | }
349 |
--------------------------------------------------------------------------------
/src/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | - [Introduction](index.md)
4 | - [Getting Started](intro/index.md)
5 | - [Setup](intro/setup.md)
6 | - [Hello, world!](intro/hello-world.md)
7 | - [An Overview of GDNative](overview/index.md)
8 | - [Data representations](overview/data-representations.md)
9 | - [Ref, TRef and Instance](overview/wrappers.md)
10 | - [Game architecture](overview/architecture.md)
11 | - [Binding to Rust code](bind/index.md)
12 | - [Class registration](bind/classes.md)
13 | - [Exported methods](bind/methods.md)
14 | - [Exported properties](bind/properties.md)
15 | - [ToVariant, FromVariant and Export](bind/traits.md)
16 | - [Calling into GDScript from Rust](bind/calling-gdscript.md)
17 | - [FAQ](faq/index.md)
18 | - [Common code questions](faq/code.md)
19 | - [Multithreading](faq/multithreading.md)
20 | - [Configuration](faq/configuration.md)
21 | - [Versioning and supported platforms](faq/support.md)
22 | - [Community](faq/community.md)
23 | - [Godot 4.0 Status](faq/godot4.md)
24 | - [Recipes](recipes/index.md)
25 | - [Async with Tokio runtime](recipes/async-tokio.md)
26 | - [Custom node plugin](recipes/custom-node-plugin.md)
27 | - [Loading external resources](recipes/external-resources.md)
28 | - [Logging](recipes/logging.md)
29 | - [Nix as development environment](recipes/nix-build-system.md)
30 | - [Rust panic handler](recipes/panic-handler.md)
31 | - [Exporting](export/index.md)
32 | - [Android](export/android.md)
33 | - [(TODO) iOS](export/ios.md)
34 | - [Mac OS X](export/macosx.md)
35 | - [HTML5](export/html5.md)
36 | - [Advanced Guides](advanced/index.md)
37 | - [Using custom Godot versions](advanced/custom-godot.md)
38 | - [Migrating from godot-rust 0.8](advanced/migrate-0-8.md)
39 | - [Migrating from godot-rust 0.9](advanced/migrate-0-9.md)
40 | - [Migrating from godot-rust 0.10](advanced/migrate-0-10.md)
41 | - [Third-party projects](./projects/index.md)
42 | - [Games](./projects/games.md)
43 | - [Tools and integrations](./projects/tools.md)
44 | - [Applications](./projects/applications.md)
45 |
--------------------------------------------------------------------------------
/src/advanced/custom-godot.md:
--------------------------------------------------------------------------------
1 | # Using custom builds of Godot
2 |
3 | As you probably know, godot-rust interacts with Godot via the GDNative interface. This interface is formally specified in a file called `api.json`, which lists all the classes, functions, constants and other symbols. In its build step, godot-rust reads this file and generates Rust code reflecting the GDNative interface.
4 |
5 | By default, godot-rust ships an `api.json` compatible with the latest Godot 3.x release. This makes it easy to use the latest version. But there are cases where you might want to use an older Godot version, or one that you built yourself (with custom compiler flags or modules). In the past, this needed quite a few manual steps; in the meantime, this process has been simplified.
6 |
7 | For using custom Godot builds, the first thing you need to do is to add the feature flag `custom-godot` when adding godot-rust as a dependency.
8 | For example, if you depend on the latest GitHub version of godot-rust, Cargo.toml would look like this:
9 | ```toml
10 | gdnative = { git = "https://github.com/godot-rust/godot-rust.git", features = ["custom-godot"] }
11 | ```
12 |
13 | Next, godot-rust must be able to locate the Godot engine executable on your system.
14 | There are two options:
15 |
16 | 1. Your executable is called `godot` and available in the system PATH.
17 | On Windows systems, this would also find a `godot.bat`, for example.
18 | 2. You define an environment variable `GODOT_BIN` with the absolute path to your executable.
19 | It is important that you include the filename -- this is not a directory path.
20 |
21 | That's it. During build, godot-rust will invoke Godot to generate a matching `api.json` -- you might see a short Godot window popping up.
22 |
23 | Keep in mind that we only support Godot versions >= 3.2 and < 4.0 for now. Also, the GDNative API varies between versions, so you may need to adjust your client code.
24 |
25 |
26 | ## Previous approach
27 |
28 | > _**Note:** this guide is now obsolete._
29 | > _You can still use it when working with godot-rust 0.9 or `master` versions before December 2021._
30 |
31 | Sometimes, users might need to use a different version of the engine that is different from the default one, or is a custom build. In order to use `godot-rust` with them, one would need to create a custom version of the `gdnative-bindings` crate, generated from an `api.json` from the custom build. This guide walks through the necessary steps to do so.
32 |
33 | First, obtain the source code for `gdnative-bindings` from crates.io. For this guide, we'll use [`cargo-download`](https://github.com/Xion/cargo-download/) to accomplish this:
34 |
35 | ```
36 | # Install the `cargo-download` sub-command if it isn't installed yet
37 | cargo install cargo-download
38 |
39 | # Download and unpack the crate
40 | cargo download gdnative-bindings==0.9.0 >gdnative-bindings.tar.gz
41 | tar -xf gdnative-bindings.tar.gz
42 | ```
43 |
44 | You should be able to find the source code for the crate in a `gdnative-bindings-{version}` directory. Rename it to a distinctive name like `gdnative-bindings-custom` and update the `Cargo.toml`:
45 |
46 | ```toml
47 | [package]
48 | name = "gdnative-bindings-custom"
49 | ```
50 |
51 | When downloading the crate, please specify the exact version of the crate that is specified in the `Cargo.toml` of `gdnative`. This is necessary because the generated bindings depend on internal interfaces that may change between non-breaking versions of `gdnative`.
52 |
53 | After source is obtained, replace the API description file with one generated by your specific Godot build:
54 |
55 | ```
56 | cd /path/to/gdnative-bindings-custom
57 | /path/to/godot --gdnative-generate-json-api api.json
58 |
59 | # Try to build and see if it works
60 | cargo build
61 | ```
62 |
63 | If everything goes well, you can now update the dependencies of your GDNative library to use this custom bindings crate:
64 |
65 | ```toml
66 | [dependencies]
67 |
68 | # Use the exact version corresponding to `gdnative-bindings`
69 | # and disable the default re-export.
70 | gdnative = { version = "=0.9.0", default-features = false, features = [] }
71 |
72 | # Use your custom bindings crate as a path dependency
73 | gdnative-bindings-custom = { path = "/path/to/gdnative-bindings-custom" }
74 | ```
75 |
76 | Here, `gdnative` is specified using an exact version because the bindings generator is an internal dependency. When using custom binding crates, care must be taken to ensure that the version of the bindings crate used as the base matches the one specified in the `Cargo.toml` of the `gdnative` crate exactly, even for updates that are considered non-breaking in the `gdnative` crate. Using an exact version bound here helps prevent unintentional updates that may break the build.
77 |
78 | Finally, replace references to `gdnative::api` with `gdnative-bindings-custom`. You should now be able to use the APIs in your custom build in Rust!
79 |
80 |
81 | ## Generating documentation
82 |
83 | However, if you try to generate documentation with rustdoc at this point, you might notice that documentation might be missing or wrong for some of the types or methods. This is due to documentation being stored separately from the API description itself, and can be easily fixed if you have access to the source code from which your custom Godot binary is built.
84 |
85 | To get updated documentation, you only need to copy all the documentation XMLs from `doc/classes` in the Godot source tree, to the `docs` directory in the `gdnative-bindings` source. After the files are copied, you should be able to get correct documentation for the API.
86 |
--------------------------------------------------------------------------------
/src/advanced/index.md:
--------------------------------------------------------------------------------
1 | # Advanced Guides
2 |
--------------------------------------------------------------------------------
/src/advanced/migrate-0-10.md:
--------------------------------------------------------------------------------
1 | # Migrating from godot-rust 0.10.x to 0.11
2 |
3 | Version 0.11 is a relatively small release, primarily adding support for the latest stable Godot version, 3.5.1 at the time.
4 |
5 | Due to some breaking changes in the GDNative API, this is a SemVer-breaking release, but in practice you can reuse your 0.10.x
6 | based code with near-zero changes. This migration guide is correspondingly brief.
7 |
8 | For a detailed list of changes, refer to the [changelog](https://github.com/godot-rust/godot-rust/blob/master/CHANGELOG.md).
9 |
10 | ## Supported Godot version
11 |
12 | The underlying Godot version changes from **3.4** (for gdnative 0.10) to **3.5.1**.
13 |
14 | Note that we explicitly recommend Godot 3.5.1 and not just 3.5; the reason being that GDNative had minor (but breaking) changes
15 | for this patch release.
16 |
17 | If you want to keep using Godot 3.4 with latest godot-rust (or any Godot version for that matter), take a look at the
18 | [Cargo feature `custom-godot`](https://godot-rust.github.io/docs/gdnative/#feature-flags).
19 |
20 |
21 | ## Minimum supported Rust version
22 |
23 | The MSRV has been increased to **1.63**.
24 | If you have an older toolchain, run `rustup update`.
25 |
26 |
27 | ## API Changes
28 |
29 | ### Method export syntax
30 |
31 | Up until gdnative 0.10.0, methods need to be exported using the `#[export]` syntax.
32 | If you did not need that parameter, the convention was to prefix it with `_`:
33 |
34 | ```rust
35 | #[export]
36 | fn _ready(&mut self, owner: &Node, delta: f32) {...}
37 |
38 | #[export]
39 | fn _process(&mut self, _owner: &Node, delta: f32) {...}
40 | ```
41 |
42 | This changes starting from 0.10.1: `#[method]` is the new attribute for the method, and `#[base]` annotates
43 | the parameter `base` (previously called `owner`). If the base parameter is not needed, simply omit it.
44 |
45 | `base` still needs to be in 2nd position, immediately after the receiver (`&self`/`&mut self`).
46 |
47 | ```rust
48 | #[method]
49 | fn _ready(&mut self, #[base] base: &Node, delta: f32) {...}
50 |
51 | #[method]
52 | fn _process(&mut self, delta: f32) {...}
53 | ```
54 |
55 | The old syntax is deprecated and stays valid throughout 0.11, so there is no urge to migrate.
56 |
57 | ### Removals
58 |
59 | The constructor `Transform2D::from_rotation_translation_scale()` was removed, due to its unintuitive semantics.
60 | It has been replaced with `from_scale_rotation_origin()`.
61 |
62 | Symbols already deprecated in 0.10 have also been removed, with the exception of `#[export]`. In particular, the
63 | type aliases `RefInstance` (now `TInstance`) and `TypedArray` (now `PoolArray`) no longer exist.
64 |
--------------------------------------------------------------------------------
/src/advanced/migrate-0-9.md:
--------------------------------------------------------------------------------
1 | # Migrating from godot-rust 0.9.x to 0.10.x
2 |
3 | Version 0.10 implements many improvements to ergonomics, naming consistency and bugfixes. Tooling and CI has been majorly overhauled, providing fast
4 | feedback cycles, higher confidence and easier-to-read documentation.
5 |
6 | This guide outlines what actions users of godot-rust need to take to update their code.
7 |
8 |
9 | ## Minimum supported Rust version
10 |
11 | The MSRV has been increased to 1.56. When migrating, you will need to ensure that you are using **at least** Rust 1.56 or later or your projects may fail to build.
12 |
13 | We use the Rust 2021 edition; in your own code you may use any edition.
14 |
15 |
16 | ## Breaking API changes
17 |
18 | This is a brief overview of the smaller breaking changes in the library API. Please refer to the [changelog](https://github.com/godot-rust/godot-rust/blob/master/CHANGELOG.md) for a comprehensive list.
19 |
20 | More sophisticated breaking changes are explained further down in section [_Migrations_](#Migrations).
21 |
22 | ### Changes to modules
23 |
24 | The module structure has been simplified to ensure there is only one module per symbol:
25 | - Module `nativescript` has been renamed to `export`.
26 | - Types `nativescript::{Instance, RefInstance}` have been moved to `object`.
27 | - Less often used macros `godot_gdnative_init`, `godot_gdnative_terminate`, `godot_nativescript_init`, `godot_site` have been removed from the prelude.
28 | - Unnecessarily nested modules have also been removed. If you were depending upon the exact path, you will need to use the new path.
29 |
30 | ### Changes to core types
31 |
32 | - The euclid vector library has been removed and replaced with [glam](https://docs.rs/glam/latest/glam/).
33 |
34 | - `Variant` has a redesigned conversion API.
35 |
36 | - Matrix types -- `Transform2D`, `Transform` and `Basis` -- have had their basis vectors renamed from `x/y/z` to `a/b/c`, to avoid confusion with the `x/y/z` vector components.
37 |
38 | - The following deprecated symbols have been removed:
39 | - `Reference::init_ref`(unsound)
40 | - `ClassBuilder::add_method`, `add_method_advanced`, `add_method_with_rpc_mode`
41 | - `ScriptMethod`
42 | - `ScriptMethodFn`
43 | - `ScriptMethodAttributes`
44 |
45 | - The following methods were removed due to being redundant:
46 | - unsafe access methods for `VariantArray` (available in `VariantArray`)
47 | - `Basis::invert`
48 | - `Basis::orthonormalize`
49 | - `Basis::rotate`
50 | - `Basis::tdotx`
51 | - `Basis::tdoty`
52 | - `Basis::tdotz`
53 | - `Rid::operator_less`
54 | - `StringName::operator_less`
55 |
56 |
57 | Various type names have been changed to improve clarity and consistency:
58 |
59 | | Old Type Name | New Type Name |
60 | |------------------|---------------|
61 | | `RefInstance` | `TInstance` |
62 | | `RefKind` | `Memory` |
63 | | `ThreadAccess` | `Ownership` |
64 | | `TypedArray` | `PoolArray` |
65 | | `Element` | `PoolElement` |
66 | | `SignalArgument` | `SignalParam` |
67 | | `Point2` | `Vector2` |
68 | | `Size2` | `Vector2` |
69 |
70 | The following methods have been renamed:
71 |
72 | | Old Method | New Method |
73 | |---------------------------------|------------------------|
74 | | `{String,Variant}::forget` | `leak` |
75 | | `Color::{rgb,rgba}` | `{from_rgb,from_rgba}` |
76 | | `Rid::is_valid` | `is_occupied` |
77 | | `Basis::to_scale` | `scale` |
78 | | `Basis::from_elements` | `from_rows` |
79 | | `Transform2D::from_axis_origin` | `from_basis_origin` |
80 | | `StringName::get_name` | `to_godot_string` |
81 |
82 |
83 | ### Changes to procedural macros
84 |
85 | - `#[inherit]` is now optional and defaults to `Reference` instead of `Node`.
86 | - `#[property(before_set)]` and its siblings are replaced with `#[property(set)]` etc.; see below.
87 |
88 | ### Ownership Changes
89 |
90 | - `Instance` and `TInstance` now use `Own=Shared` by default. Some adjustments to your assumptions should be re-evaluated as needed.
91 |
92 |
93 | ## New features
94 |
95 | In addition to new functionality outlined here, it can be interesting to check the _Added_ section in the changelog.
96 |
97 | ### Cargo features
98 |
99 | While these are not breaking changes, the following may be useful to consider when migrating, particularly if you were previously using a custom solution for either of the following:
100 |
101 | - [serde](https://serde.rs/) is now supported for `VariantDispatch` and types in the `core_types` module.
102 | - Async Foundations have been completed, so you can now make use of Rust `async` runtimes with Godot more easily. We have a recipe for using [async with the tokio runtime](../recipes/async-tokio.md).
103 | - Custom Godot builds are now supported. The advanced guide for [Custom Godot](./custom-godot.md) has been updated accordingly.
104 |
105 | ### Custom property exports
106 |
107 | In godot-rust 0.9, it was necessary to manually register properties using the class builder such as the following:
108 |
109 | ```rust
110 | #[derive(NativeClass)]
111 | #[inherit(Reference)]
112 | struct Foo {
113 | #[property]
114 | bar: i64,
115 | }
116 |
117 | #[methods]
118 | impl Foo {
119 | fn register_properties(builder: &ClassBuilder) {
120 | builder
121 | .add_property::("bar")
122 | .with_getter(get_bar)
123 | .with_setter(set_bar)
124 | .with_default(0)
125 | .done();
126 | }
127 | #[export]
128 | fn set_bar(&mut self, _owner: &Reference, value: i64) {
129 | self.bar = value;
130 | }
131 |
132 | #[export]
133 | fn get_bar(&mut self, _owner: &Reference) -> i64 {
134 | self.bar
135 | }
136 | }
137 | ```
138 |
139 | In 0.10, this can be automated with the `#[property]` procedural macro, such as the following:
140 | ```rust
141 | #[derive(NativeClass)]
142 | #[inherit(Reference)]
143 | struct Foo {
144 | #[property(name = "bar", set = "set_bar", get = "get_bar", default = 0)]
145 | bar: i64,
146 | }
147 |
148 | #[methods]
149 | impl Foo {
150 | #[export]
151 | fn set_bar(&mut self, _owner: &Reference, value: i64) {
152 | self.bar = value;
153 | }
154 |
155 | #[export]
156 | fn get_bar(&mut self, _owner: &Reference) -> i64 {
157 | self.bar
158 | }
159 | }
160 | ```
161 |
162 | ### `VariantDispatch`
163 |
164 | `VariantDispatch` is an newly introduced type in godot-rust 0.10. This enum lets you treat `Variant` in a more rust-idiomatic way, e.g. by pattern-matching its contents:
165 |
166 | ```rust
167 | let variant = 42.to_variant();
168 |
169 | let number_as_float = match variant.dispatch() {
170 | VariantDispatch::I64(i) => i as f64,
171 | VariantDispatch::F64(f) => f,
172 | _ => panic!("not a number"),
173 | };
174 |
175 | approx::assert_relative_eq!(42.0, number_as_float);
176 | ```
177 |
178 |
179 | ## Migrations
180 |
181 | This section elaborates on APIs with non-trivial changes and guides you through the process of updating your code.
182 |
183 | ### `Variant`
184 |
185 | If you were using the `Variant::from_*` methods, those no longer exist.
186 |
187 | In 0.9.x you would need to use the specific constructor, such as the following:
188 |
189 | ```rust
190 | let variant = Variant::from_i64(42);
191 | let variant = Variant::from_f64(42.0);
192 | let variant2 = Variant::from_object(object);
193 | ```
194 |
195 | In 0.10.x, `new()` is sufficient for any type that implements `ToVariant`, such as the following:
196 |
197 | ```rust
198 | let variant = Variant::new(42);
199 | let variant = Variant::new(42.0);
200 | let variant2 = Variant::new(object);
201 | ```
202 |
203 | When converting from a variant to a Rust type, it previously was necessary to do the following:
204 |
205 | ```rust
206 | let integer64 = i64::from_variant(&variant_i64).unwrap();
207 | let float64 = f64::from_variant(&variant_f64).unwrap();
208 | let object = ObjectType::from_variant(&variant_object).unwrap();
209 | ```
210 |
211 | In 0.10.x, you can now cast your variants by using the `to()` function on `FromVariant`-enabled types, such as the following:
212 |
213 | ```rust
214 | // Note: If the compiler can infer your type, the turbofish `::` is optional
215 | let integer64 = variant.to::().unwrap();
216 | let float64 = variant.to::().unwrap();
217 | let object = variant.to_object::().unwrap(); // returns Ref
218 | ```
219 |
220 |
221 | ### Transforms
222 |
223 | Previously, transforms were defined by the matrix identities such as `m11`, `m12`; now, they are referred by the vector name for consistency.
224 |
225 | For example: When creating an identity `Transform2D` in 0.9.x, you would create it using the following code:
226 |
227 | ```rust
228 | let tform = Transform2D::new(1.0, 0.0, 0.0, 1.0, 1.0, 1.0);
229 | ```
230 |
231 | In 0.10.x you now need to create it using `from_basis_origin` and use `a`, `b`, and `origin` vectors, such as the following:
232 |
233 | ```rust
234 | let tform = Transform2D::from_basis_origin(
235 | Vector2::new(1.0, 0.0),
236 | Vector2::new(0.0, 1.0),
237 | Vector2::new(1.0, 1.0),
238 | );
239 | ```
240 |
241 | ### Vector types
242 |
243 | The underlying vector library as well as the implementation have been fundamentally replaced. In 0.9.x, many of the goemetric types were thinly wrapping a separate library. This led to several wrapping classes such as `Point2`, `Size2` being removed now. In addition, other geometric types -- for example `Rect2`, `Quat`, `Transform`, `Plane` -- have all been changed, and certain convenience functions may not be available anymore, depending upon the struct.
244 |
245 | For example: `Rect2` no longer has `width()` or `height()`, but lets you directly access its `size.x` or `size.y` fields.
246 |
247 | ### `ClassBuilder`
248 |
249 | The [`ClassBuilder`](https://docs.rs/gdnative/latest/gdnative/prelude/struct.ClassBuilder.html) type has been extended to use the builder pattern when registering signals and properties.
250 |
251 | In 0.9, registering a signal would look like the following:
252 |
253 | ```rust
254 | fn register_signals(builder: &ClassBuilder) {
255 | builder.add_signal(
256 | Signal {
257 | name: "signal1",
258 | args: &[],
259 | }
260 | );
261 | builder.add_signal(
262 | Signal {
263 | name: "signal2",
264 | args: &[SignalArgument {
265 | name: "myArg",
266 | default: 42.0.to_variant(),
267 | export_info: ExportInfo::new(VariantType::F64),
268 | usage: PropertyUsage::DEFAULT,
269 | }],
270 | });
271 | }
272 | ```
273 |
274 | In 0.10, this changes to:
275 |
276 | ```rust
277 | fn register_signals(builder: &ClassBuilder) {
278 | builder.signal("signal1").done();
279 |
280 | builder.signal("signal2")
281 | .with_param_custom(
282 | SignalParam {
283 | name: "myArg",
284 | default: 42.0.to_variant(),
285 | export_info: ExportInfo::new(VariantType::F64),
286 | usage: PropertyUsage::DEFAULT,
287 | },
288 | ).done();
289 |
290 | // If you only need a default value, you can also register a signal like this:
291 | builder.signal("signal3")
292 | .with_param_default("myArg", 42.0.to_variant())
293 | .done()
294 | }
295 | ```
296 |
297 |
298 | ### Server singletons
299 |
300 | Godot's server singletons have received a safety overhaul. As a result, all functions that take one or more parameters of type `Rid` are now marked `unsafe` and thus require being used inside an `unsafe` block or `unsafe` function.
301 |
302 | In 0.9.x, creating a canvas_item and attaching it to a parent would be done as follows:
303 | ```rust
304 | let vs = unsafe { VisualServer::godot_singleton() };
305 | let canvas = vs.canvas_create();
306 | let ci = vs.canvas_item_create();
307 | vs.canvas_item_set_parent(ci, canvas);
308 | ```
309 |
310 | In 0.10.x, you now must wrap the `canvas_item_set_parent` function in an `unsafe` block, such as follows:
311 |
312 | ```rust
313 | let vs = unsafe { VisualServer::godot_singleton() };
314 | let canvas = vs.canvas_create();
315 | let ci = vs.canvas_item_create();
316 | unsafe {
317 | vs.canvas_item_set_parent(ci, canvas);
318 | }
319 | ```
320 |
321 | #### Additional UB notes
322 |
323 | The reason for this change was due to [issue #836](https://github.com/godot-rust/godot-rust/issues/836) being raised. Developers were able to demonstrate that you could easily cause undefined behavior when using any function that accepted `Rid` as a parameter, such as the following:
324 |
325 | ```rust
326 | let vs = unsafe { VisualServer::godot_singleton() };
327 | let canvas = vs.canvas_create();
328 | let vp = vs.viewport_create();
329 | vs.canvas_item_set_parent(vp, canvas); // crashes immediately
330 | vs.canvas_item_set_parent(canvas, canvas); // crashes at shutdown
331 | ```
332 |
--------------------------------------------------------------------------------
/src/bind/calling-gdscript.md:
--------------------------------------------------------------------------------
1 |
2 | # Calling GDScript from Rust
3 |
4 | To transport information from Rust back to GDScript, you have three options (of which the last can be achieved in different ways):
5 |
6 | * Use return values in exported methods
7 | * Use exported properties
8 | * Call a Godot class method from Rust
9 | * invoke built-in method as part of the API (e.g. `set_position()` above)
10 | * invoke custom GDScript method, through `call()` and overloads
11 | * emit a signal, through `emit_signal()`
12 |
13 | Which one you need depends on your goals and your architecture. If you see Rust as a deterministic, functional machine in the sense of _input -> processing -> output_, you could stick to only returning data from Rust methods, and never directly calling a Godot method. This can be limiting however, and depending on your use case you end up manually dispatching back to different nodes on the GDScript side.
14 |
15 |
16 | ## Passing custom classes to GDScript
17 |
18 | On the previous pages, we explained how to export a class, so it can be instantiated and called from GDScript. This section explains how to construct a class locally in Rust.
19 |
20 | Let's define a class `Enemy` which acts as a simple data bundle, i.e. no functionality. We inherit it from `Reference`, such that memory is managed automatically. In addition, we define `_to_string()` and delegate it to the derived `Debug` trait implementation, to make it printable from GDScript.
21 |
22 | ```rust
23 | #[derive(NativeClass, Debug)]
24 | // no #[inherit], thus inherits Reference by default
25 | #[no_constructor]
26 | pub struct Enemy {
27 | #[property]
28 | pos: Vector2,
29 |
30 | #[property]
31 | health: f32,
32 |
33 | #[property]
34 | name: String,
35 | }
36 |
37 | #[methods]
38 | impl Enemy {
39 | #[method]
40 | fn _to_string(&self) -> String {
41 | format!("{:?}", self) // calls Debug::fmt()
42 | }
43 | }
44 | ```
45 | Godot can only use classes that are registered, so let's do that:
46 | ```rust
47 | fn init(handle: InitHandle) {
48 | // ...
49 | handle.add_class::();
50 | }
51 | ```
52 | Now, it's not possible to directly return `Enemy` instances in exported methods, so this won't work:
53 | ```rust
54 | #[method]
55 | fn create_enemy(&mut self) -> Enemy {...}
56 | ```
57 | Instead, you can wrap the object in a `Instance`, using `emplace()`. For an in-depth explanation of the `Instance` class, read [this section](../overview/wrappers.md#instance-reference-with-attached-rust-class).
58 | ```rust
59 | #[method]
60 | fn create_enemy(&self) -> Instance {
61 | let enemy = Enemy {
62 | pos: Vector2::new(7.0, 2.0),
63 | health: 100.0,
64 | name: "MyEnemy".to_string(),
65 | };
66 |
67 | enemy.emplace()
68 | }
69 | ```
70 |
71 | When calling this method in GDScript:
72 | ```python
73 | var api = GodotApi.new()
74 | var enemy = api.create_enemy()
75 | print("Enemy created: ", enemy)
76 | ```
77 | the output will be:
78 | ```
79 | Enemy created: Enemy { pos: (7.0, 2.0), health: 100.0, name: "MyEnemy" }
80 | ```
81 |
82 | If you want types to be default-constructible, e.g. to allow construction from GDScript, omit the `#[no_constructor]` attribute. You can default-construct from Rust using `Instance::new_instance()`.
83 |
84 |
85 | ## Function calls
86 |
87 | While you can export Rust methods to be called from GDScript, the opposite is also possible. Typical use cases for this include:
88 |
89 | * Read or modify the scene tree directly from Rust (e.g. moving a node)
90 | * Synchronizing logic state (Rust) with visual representation (Godot)
91 | * Notify code in GDScript about changes in Rust
92 |
93 | Methods provided by Godot classes are mapped to regular Rust functions. Examples for these are `Node2D::rotate()`, `Button::set_text()`, `StaticBody::bounce()`. They can usually be invoked safely on a `&T` or `TRef` reference to the respective object.
94 |
95 | Custom GDScript methods (defined in .gd files) on the other hand need to be invoked dynamically. This means that there is no type-safe Rust signature, so you will use the `Variant` type. All Godot-compatible types can be converted to variants. For the actual call, `Object` provides multiple methods. Since every Godot class eventually dereferences to `Object`, you can invoke them on any Godot class object.
96 |
97 | The following GDScript method:
98 | ```python
99 | # in UserInterface.gd
100 | extends CanvasItem
101 |
102 | func update_stats(mission_name: String, health: float, score: int) -> bool:
103 | # ...
104 | ```
105 | can be invoked from Rust as follows:
106 | ```rust
107 | use gdnative::core_types::ToVariant;
108 |
109 | fn update_mission_ui(ui_node: Ref) {
110 | let mission_name = "Thunderstorm".to_variant();
111 | let health = 37.2.to_variant();
112 | let score = 140.to_variant();
113 |
114 | // both assume_safe() and call() are unsafe
115 | let node: TRef = unsafe { ui_node.assume_safe() };
116 | let result: Variant = unsafe {
117 | node.call("update_stats", &[mission_name, health, score])
118 | };
119 |
120 | let success: bool = result.try_to_bool().expect("returns bool");
121 | }
122 | ```
123 |
124 | Besides [`Object::call()`](https://docs.rs/gdnative/latest/gdnative/api/struct.Object.html#method.call), alternative methods `callv()` (accepting a `VariantArray`) and `call_deferred()` (calling at the end of the frame) exist, but the principle stays the same.
125 |
126 | For long parameter lists, it often makes sense to bundle related functionality into a new class, let's say `Stats` in the above example. When working with classes, you can convert both `Ref` (for Godot/GDScript classes) and `Instance` (for native classes) to `Variant` by means of the `OwnedToVariant` trait:
127 |
128 | ```rust
129 | use gdnative::core_types::OwnedToVariant; // owned_to_variant()
130 | use gdnative::nativescript::NativeClass; // emplace()
131 |
132 | // Native class bundling the update information
133 | #[derive(NativeClass)]
134 | #[no_constructor]
135 | struct Stats {
136 | #[property]
137 | mission_name: String,
138 |
139 | #[property]
140 | health: f32,
141 |
142 | #[property]
143 | score: i32,
144 | }
145 |
146 | fn update_mission_ui(ui_node: Ref) {
147 | let stats = Stats {
148 | mission_name: "Thunderstorm".to_variant(),
149 | health: 37.2.to_variant(),
150 | score: 140.to_variant(),
151 | };
152 |
153 | let instance: Instance = stats.emplace();
154 | let variant: Variant = instance.owned_to_variant();
155 |
156 | let node: TRef = unsafe { ui_node.assume_safe() };
157 |
158 | // let's say the method now returns a Stats object with previous stats
159 | let result: Variant = unsafe { node.call("update_stats", &[variant]) };
160 |
161 | // convert Variant -> Ref -> Instance
162 | let base_obj: Ref = result.try_to_object().expect("is Reference");
163 | let instance: Instance = Instance::from_base(base_obj).unwrap();
164 |
165 | instance.map(|prev_stats: &Stats, _base| {
166 | // read prev_stats here
167 | });
168 | }
169 | ```
170 |
171 | ### Warning
172 |
173 | When calling GDScript functions from Rust, a few things need to be kept in mind.
174 |
175 | **Safety:** Since the calls are dynamic, it is possible to invoke any other functions through them, including unsafe ones like `free()`. As a result, `call()` and its alternatives are unsafe.
176 |
177 | **Re-entrancy:** When calling from Rust to GDScript, your Rust code is usually already running in an exported `#[method]` method, meaning that it has bound its receiver object via `&T` or `&mut T` reference. In the GDScript code, you must not invoke any method on the same Rust receiver, which would violate safety rules (aliasing of `&mut`).
178 |
179 |
180 | ## Signal emissions
181 |
182 | Like methods, signals defined in GDScript can be emitted dynamically from Rust.
183 |
184 | The mechanism works analogously to function invocation, except that you use [`Object::emit_signal()`](https://docs.rs/gdnative/latest/gdnative/api/struct.Object.html#method.emit_signal) instead of `Object::call()`.
--------------------------------------------------------------------------------
/src/bind/classes.md:
--------------------------------------------------------------------------------
1 | # Class registration
2 |
3 | Classes are a fundamental data type of GDNative. They are used for Godot's own types (such as nodes) as well as custom ones defined by you. Here, we focus on defining _custom_ classes and exposing them to Godot.
4 |
5 |
6 | ## The Rust entry point
7 |
8 | When working with godot-rust, your Rust code sits inside a dynamic library with C ABI (`cdylib`), which is loaded at runtime from the Godot engine. The engine works as the host application with the entry and exit point, and your Rust code will be loaded at some point after Godot starts and unloaded before it ends.
9 |
10 | This workflow implies that when you want to execute Rust code, you need to first pass control from Godot to it. To achieve this, every godot-rust application integrated with the engine must expose a public interface, through which Godot can invoke Rust code.
11 |
12 | Somewhere in your code, usually in `lib.rs`, you need to declare the functions that will be called by the engine when the native library is loaded and unloaded, as well as the registration function for native classes exposed to the engine. godot-rust provides the following macros (consult [their documentation](https://docs.rs/gdnative/latest/gdnative/index.html#macros) for further info and customization):
13 | ```rust
14 | godot_gdnative_init!();
15 | godot_nativescript_init!(init);
16 | godot_gdnative_terminate!();
17 | ```
18 | Or the equivalent short-hand:
19 | ```rust
20 | godot_init!(init);
21 | ```
22 |
23 | The argument `init` refers to the function registering native script classes, which is also defined by you. For this chapter, let's assume you want to write a class `GodotApi`, which exposes a public interface to be invoked from Godot. The registration is then as follows:
24 | ```rust
25 | // see details later
26 | struct GodotApi { ... }
27 |
28 | fn init(handle: InitHandle) {
29 | handle.add_class::();
30 | }
31 | ```
32 |
33 |
34 | ## Class definition
35 |
36 | Similar to the [Hello World](../getting-started/hello-world.md#overriding-a-godot-method) example, we can define the `GodotApi` native class as follows:
37 | ```rust
38 | // Tell godot-rust that this struct is exported as a native class
39 | // (implements NativeClass trait)
40 | #[derive(NativeClass)]
41 |
42 | // Specify the base class (corresponds to 'extends' statement in GDScript).
43 | // * Like 'extends' in GDScript, this can be omitted.
44 | // In that case, the 'Reference' class is used as a base.
45 | // * Unlike 'extends' however, only existing Godot types are permitted,
46 | // no other user-defined scripts.
47 | #[inherit(Node)]
48 | pub struct GodotApi {}
49 |
50 | // Exactly one impl block can have the #[methods] annotation,
51 | // which registers methods in the background.
52 | #[methods]
53 | impl GodotApi {
54 | // Constructor, either:
55 | fn new(base: &Node) -> Self { ... }
56 | // or:
57 | fn new(base: TRef) -> Self { ... }
58 | }
59 | ```
60 |
61 | The [`#[derive(NativeClass)]` macro](https://docs.rs/gdnative/latest/gdnative/derive.NativeClass.html) enables a Rust type to be usable as a _native class_ in Godot. It implements [the `NativeClass` trait](https://docs.rs/gdnative/latest/gdnative/nativescript/trait.NativeClass.html), which fills in the glue code required to make the class available in Godot. Among other information, this includes class name and registry of exported methods and properties. For the user, the utility methods `new_instance()` and `emplace()` are provided for constructing `Instance` objects.
62 |
63 | The function `new()` corresponds to `_init()` in GDScript. The _base_ is the base object of the script, and must correspond to the class specified in the `#[inherit]` attribute (or `Reference` if the attribute is absent). The parameter can be a shared reference `&T` or a `TRef`.
64 |
65 | With a `new()` method, you are able to write `GodotApi.new()` in GDScript. If you don't need this, you can add the `#[no_constructor]` attribute to the struct declaration.
66 |
67 | At this point, arguments cannot be passed into the constructor. Consult [this FAQ entry](../faq.md#passing-additional-arguments-to-a-class-constructor) for available workarounds.
--------------------------------------------------------------------------------
/src/bind/index.md:
--------------------------------------------------------------------------------
1 | # Binding to Rust code
2 |
3 | This chapter provides an exhaustive list of mechanisms to pass data through the Rust GDNative binding, in both directions:
4 | * **GDScript -> Rust**, e.g. to react to an input event with custom Rust logic
5 | * **Rust -> GDScript**, e.g. to apply a game logic change to a graphics node in Godot
6 |
7 | The goal is to serve as both an in-depth learning resource for newcomers and a reference to look up specific mechanisms at a later stage. Before delving into this chapter, make sure to read [An Overview of GDNative](gdnative-overview.md), which explains several fundamental concepts used here.
8 |
9 | The subchapters are intended to be read in order, but you can navigate to them directly:
10 |
11 | 1. [Class registration](rust-binding/classes.md)
12 | 1. [Exported methods](rust-binding/methods.md)
13 | 1. [Exported properties](rust-binding/properties.md)
14 | 1. [Calling into GDScript from Rust](./rust-binding/calling-gdscript.md)
--------------------------------------------------------------------------------
/src/bind/methods.md:
--------------------------------------------------------------------------------
1 | # Exported methods
2 |
3 | In order to receive data from Godot, you can export methods. With the `#[method]` attribute, godot-rust takes care of method registration and serialization. Note that the constructor is not annotated with `#[method]`.
4 |
5 | > #### Recent API changes
6 | > `#[export]` has been renamed to `#[method]` and is now deprecated.
7 | > It keeps working for the time being though (i.e. gdnative 0.11).
8 | >
9 | > For more information, see [`gdnative::derive::NativeClass`](https://godot-rust.github.io/docs/gdnative/derive/derive.NativeClass.html).
10 |
11 | The exported method's first parameter is always `&self` or `&mut self` (operating on the Rust object), and the second parameter is `&T` or `TRef` (operating on the Godot base object, with `T` being the inherited type).
12 |
13 | ```rust
14 | #[derive(NativeClass)]
15 | #[inherit(Node)]
16 | pub struct GodotApi {
17 | enemy_count: i32,
18 | }
19 |
20 | #[methods]
21 | impl GodotApi {
22 | fn new(_base: &Node) -> Self {
23 | // Print to both shell and Godot editor console
24 | godot_print!("_init()");
25 | Self { enemy_count: 0 }
26 | }
27 |
28 | #[method]
29 | fn create_enemy(
30 | &mut self,
31 | typ: String,
32 | pos: Vector2
33 | ) {
34 | godot_print!("create_enemy(): type '{}' at position {:?}", typ, pos);
35 | self.enemy_count += 1;
36 | }
37 |
38 | #[method]
39 | fn create_enemy2(
40 | &mut self,
41 | typ: GodotString,
42 | pos: Variant
43 | ) {
44 | godot_print!("create_enemy2(): type '{}' at position {:?}", typ, pos);
45 | self.enemy_count += 1;
46 | }
47 |
48 | #[method]
49 | fn count_enemies(&self) -> i32 {
50 | self.enemy_count
51 | }
52 | }
53 | ```
54 | The two creation methods are semantically equivalent, yet they demonstrate how godot-rust implicitly converts the values to the parameter types (unmarshalling). You could use `Variant` everywhere, however it is more type-safe and expressive to use specific types. The same applies to return types, you could use `Variant` instead of `i32`.
55 | `GodotString` is the Godot engine string type, but it can be converted to standard `String`. To choose between the two, consult [the docs](https://docs.rs/gdnative/latest/gdnative/core_types/struct.GodotString.html).
56 |
57 | In GDScript, you can then write this code:
58 | ```python
59 | var api = GodotApi.new()
60 |
61 | api.create_enemy("Orc", Vector2(10, 20));
62 | api.create_enemy2("Elf", Vector2(50, 70));
63 |
64 | print("enemies: ", api.count_enemies())
65 |
66 | # don't forget to add it to the scene tree, otherwise memory must be managed manually
67 | self.add_child(api)
68 | ```
69 |
70 | The output is:
71 | ```
72 | _init()
73 | create_enemy(): type 'Orc' at position (10.0, 20.0)
74 | create_enemy2(): type 'Elf' at position Vector2((50, 70))
75 | enemies: 2
76 | ```
77 |
78 | ## Passing classes
79 |
80 | The above examples have dealt with simple types such as strings and integers. What if we want to pass entire classes to Rust?
81 |
82 | Let's say we want to pass in an enemy from GDScript, instead of creating one locally. It could be represented by the `Node2D` class and directly configured in the Godot editor. What you then would do is use [the `Ref` wrapper](../overview/wrappers.md):
83 | ```rust
84 | #[derive(NativeClass)]
85 | #[inherit(Node)]
86 | pub struct GodotApi {
87 | // Store references to all enemy nodes
88 | enemies: Vec>,
89 | }
90 |
91 | #[methods]
92 | impl GodotApi {
93 | // new() etc...
94 |
95 | #[method]
96 | fn add_enemy(
97 | &mut self,
98 | enemy: Ref // pass in enemy
99 | ) {
100 | self.enemies.push(enemy);
101 | }
102 |
103 | // You can even return the enemies directly with Vec.
104 | // In GDScript, you will get an array of nodes.
105 | // An alternative would be VariantArray, able to hold different types.
106 | #[method]
107 | fn get_enemies(
108 | &self,
109 | ) -> Vec> {
110 | self.enemies.clone()
111 | }
112 | }
113 | ```
114 |
115 | ## Special methods
116 |
117 | Godot offers some special methods. Most of them implement [notifications](https://docs.godotengine.org/en/stable/getting_started/workflow/best_practices/godot_notifications.html), i.e. callbacks from the engine to notify the class about a change.
118 |
119 | If you need to override a Godot special method, just declare it as a normal exported method, with the same name and signature as in GDScript. You can also omit the base parameter if you don't need it.
120 | ```rust
121 | #[method]
122 | fn _ready(&mut self, #[base] base: &Node) {...}
123 |
124 | #[method]
125 | fn _process(&mut self, #[base] base: &Node, delta: f32) {...}
126 |
127 | #[method]
128 | fn _physics_process(&mut self, #[base] base: &Node, delta: f32) {...}
129 | ```
130 |
131 | If you want to change how GDScript's default formatter in functions like `str()` or `print()` works, you can overload the `to_string` GDScript method, which corresponds to the following Rust method:
132 | ```rust
133 | #[method]
134 | fn _to_string(&self, #[base] base: &Node) -> String {...}
135 | ```
136 |
137 |
138 | ## Errors
139 |
140 | If you pass arguments from GDScript that are incompatible with the Rust method's signature, the method invocation will fail. In this case, the code inside the method is not executed. An error message is printed on the Godot console, and the value `null` is returned for the GDScript function call.
141 |
142 | If code inside your method panics (e.g. by calling `unwrap()` on an empty option/result), the same happens: error message and return value `null`.
143 |
--------------------------------------------------------------------------------
/src/bind/properties.md:
--------------------------------------------------------------------------------
1 | # Exported properties
2 |
3 | Like methods, properties can be exported. The `#[property]` attribute above a field declaration makes the field available to Godot, with its name and type.
4 |
5 | In the previous example, we could replace the `count_enemies()` method with a property `enemy_count`.
6 | ```rust
7 | #[derive(NativeClass)]
8 | #[inherit(Node)]
9 | pub struct GodotApi {
10 | #[property]
11 | enemy_count: i32,
12 | }
13 | ```
14 |
15 | The GDScript code would be changed as follows.
16 | ```python
17 | print("enemies: ", api.enemy_count)
18 | ```
19 |
20 | That's it.
21 |
22 | ## Export options
23 |
24 | The `#[property]` attribute can accept a several options to refine the export behavior.
25 |
26 | You can specify default property value with the following argument:
27 |
28 | ```rust
29 | #[property(default = 10)]
30 | enemy_count: i32,
31 | ```
32 |
33 | If you need to hide this property in Godot editor, use `no_editor` option:
34 |
35 | ```rust
36 | #[property(no_editor)]
37 | enemy_count: i32,
38 | ```
39 |
40 | ## Property get/set
41 |
42 | Properties can register `set` and `get` methods to be called from Godot.
43 |
44 | Default get/set functions can be registered as per the following example:
45 |
46 | ```rs
47 |
48 | #[derive(NativeClass, Default)]
49 | #[inherit(Node)]
50 | struct GodotApi {
51 | // property registration
52 | // Note: This is actually equivalent to #[property]
53 | #[property(get, set)]
54 | prop: i32,
55 | }
56 | ```
57 |
58 | If you need custom setters and getters, you can set them in the `property` attribute such as in the following example:
59 |
60 | ```rust
61 | #[derive(NativeClass)]
62 | #[inherit(Node)]
63 | struct HelloWorld {
64 | // property registration
65 | #[property(get = "Self::get", set = "Self::set")]
66 | prop: i32,
67 | }
68 |
69 | impl HelloWorld {
70 | fn new(_base: &Node) -> Self {
71 | HelloWorld { prop: 0i32 }
72 | }
73 | }
74 |
75 | #[methods]
76 | impl HelloWorld {
77 | fn get(&self, _base: TRef) -> i32 {
78 | godot_print!("get() -> {}", &self.prop);
79 | self.prop
80 | }
81 |
82 | fn set(&mut self, _base: TRef, value: i32) {
83 | godot_print!("set({})", &value);
84 | self.prop = value;
85 | }
86 | }
87 | ```
88 |
89 | ### Note: `get` vs `get_ref`
90 |
91 | There are two ways to return the property.
92 | - `get` will return a value of `T` which _must_ result in the value being cloned.
93 | - `get_ref` must point to a function that returns `&T`, this is useful when working with large data that would be very expensive to copy unnecessarily.
94 |
95 | Modifying the previous example accordingly results in the following:
96 |
97 | ```rust
98 | #[derive(NativeClass)]
99 | #[inherit(Node)]
100 | struct GodotApi {
101 | // property registration
102 | #[property(get_ref = "Self::get", set = "Self::set")]
103 | prop: String,
104 | }
105 |
106 | impl GodotApi {
107 | fn new(_base: &Node) -> Self {
108 | GodotApi { prop: String::new() }
109 | }
110 | }
111 |
112 | #[methods]
113 | impl GodotApi {
114 | fn get(&self, _base: TRef) -> &String {
115 | godot_print!("get() -> {}", &self.prop);
116 | &self.prop
117 | }
118 |
119 | fn set(&mut self, _base: TRef, value: String) {
120 | godot_print!("set({})", &value);
121 | self.prop = value;
122 | }
123 | }
124 | ```
125 |
126 | ## Manual property registration
127 |
128 | For cases not covered by the `#[property]` attribute, it may be necessary to manually register the properties instead.
129 |
130 | This is often the case where custom hint behavior is desired for primitive types, such as an Integer value including an `IntEnum` hint.
131 |
132 | To do so, you can use the [`ClassBuilder`](https://docs.rs/gdnative/latest/gdnative/prelude/struct.ClassBuilder.html) -- such as in the following examples -- to manually register each property and customize how they interface in the editor.
133 |
134 | ```rust
135 |
136 | #[derive(NativeClass)]
137 | #[inherit(Node)]
138 | #[register_with(Self::register_properties)]
139 | #[no_constructor]
140 | pub struct MyNode {
141 | number: i32,
142 | number_enum: i32,
143 | float_range: f64,
144 | my_filepath: String,
145 | }
146 |
147 | #[methods]
148 | impl MyNode {
149 | fn register_properties(builder: &ClassBuilder) {
150 | use gdnative::export::hint::*;
151 | // Add a number with a getter and setter.
152 | // (This is the equivalent of adding the `#[property]` attribute for `number`)
153 | builder
154 | .property::("number")
155 | .with_getter(Self::number_getter)
156 | .with_setter(Self::number_setter)
157 | .done();
158 |
159 | // Register the number as an Enum
160 | builder
161 | .property::("number_enum")
162 | .with_getter(move |my_node: &MyNode, _base: TRef| my_node.number_enum)
163 | .with_setter(move |my_node: &mut MyNode, _base: TRef, new_value| my_node.number_enum = new_value)
164 | .with_default(1)
165 | .with_hint(IntHint::Enum(EnumHint::new(vec!["a".to_owned(), "b".to_owned(), "c".to_owned(), "d".to_owned()])))
166 | .done();
167 |
168 | // Register a floating point value with a range from 0.0 to 100.0 with a step of 0.1
169 | builder
170 | .property::("float_range")
171 | .with_getter(move |my_node: &MyNode, _base: TRef| my_node.float_range)
172 | .with_setter(move |my_node: &mut MyNode, _base: TRef, new_value| my_node.float_range = new_value)
173 | .with_default(1.0)
174 | .with_hint(FloatHint::Range(RangeHint::new(0.0, 100.0).with_step(0.1)))
175 | .done();
176 |
177 | // Manually register a string as a file path for .txt and .dat files.
178 | builder
179 | .property::("my_filepath")
180 | .with_ref_getter(move |my_node: &MyNode, _base: TRef| &my_node.my_filepath)
181 | .with_setter(move |my_node: &mut MyNode, _base: TRef, new_value: String| my_node.my_filepath = new_value)
182 | .with_default("".to_owned())
183 | .with_hint(StringHint::File(EnumHint::new(vec!["*.txt".to_owned(), "*.dat".to_owned()])))
184 | .done();
185 | }
186 | fn number_getter(&self, _base: TRef) -> i32 {
187 | self.number
188 | }
189 |
190 | fn number_setter(&mut self, _base: TRef, new_value: i32) {
191 | self.number = new_value
192 | }
193 | }
194 | ```
195 |
196 | ## `Property` and when to use it
197 |
198 | Sometimes it can be useful to expose a value as a property instead of as a function. Properties of this type serve as a _marker_ that can be registered with Godot and viewed in the editor without containing any data in Rust.
199 |
200 | This can be useful for data (similar to the first sample) where the count serves more as a property of `enemies` rather than as its own distinct data, such as the following:
201 |
202 | ```rs
203 | struct Enemy {
204 | // Enemy Data
205 | }
206 | #[derive(NativeClass)]
207 | struct GodotApi {
208 | enemies: Vec,
209 | // Note: As the property is a "marker" property, this will never be used in code.
210 | #[allow(dead_code)]
211 | #[property(get = "Self::get_size")]
212 | enemy_count: Property,
213 | }
214 |
215 | #[methods]
216 | impl GodotApi {
217 | //...
218 |
219 | fn get_size(&self, _base: TRef) -> u32 {
220 | self.enemies.len() as u32
221 | }
222 | }
223 | ```
--------------------------------------------------------------------------------
/src/bind/traits.md:
--------------------------------------------------------------------------------
1 | # ToVariant, FromVariant and Export
2 |
3 | As seen in [the previous section](./properties.md), the `#[property]` attribute of the [`NativeClass`](https://docs.rs/gdnative/latest/gdnative/derive.NativeClass.html) procedural macro is a powerful tool to automatically configure properties with Godot.
4 |
5 | One constraint of the `#[property]` attribute is that it requires that all attributed property types implement `ToVariant`, `FromVariant` and `Export` in order to interface with Godot.
6 |
7 | ## ToVariant/FromVariant traits
8 |
9 | In Godot all types inherit from Variant.
10 |
11 | As per the [official Godot docs](https://docs.godotengine.org/en/stable/classes/class_variant.html), Variant is "The most important data type in Godot." This is a wrapper type that can store any [Godot Engine type](https://docs.godotengine.org/en/stable/classes/class_%40globalscope.html#enum-globalscope-variant-type)
12 |
13 | The `ToVariant` and `FromVariant` are conversion traits that allow Rust types to be converted between these types. All properties must implement both `ToVariant` and `FromVariant` while exported methods require `FromVariant` to be implemented for optional parameters and `ToVariant` to be implemented for return types.
14 |
15 | For many datatypes, it is possible to use the derive macros such as in the following example:
16 |
17 | ```rust
18 | // Note: This struct does not implement `Export` and cannot be used as a property, see the following section for more information.
19 | #[derive(ToVariant, FromVariant)]
20 | struct Foo {
21 | number: i32,
22 | float: f32,
23 | string: String
24 | }
25 | ```
26 |
27 | For more information about how you can customize the behavior of the dervive macros, please refer to the official documentation for the latest information.
28 |
29 | - [ToVariant](https://docs.rs/gdnative/latest/gdnative/core_types/trait.ToVariant.html)
30 | - [FromVariant](https://docs.rs/gdnative/latest/gdnative/core_types/trait.FromVariant.html)
31 |
32 | ## Export Trait
33 |
34 | The Godot editor retrieves property information from [Object::get_property_list](https://docs.godotengine.org/en/stable/classes/class_object.html#id2). To populate this data, `godot-rust` requires that the [`Export`](https://docs.rs/gdnative/latest/gdnative/nativescript/trait.Export.html) trait be implemented for each type Rust struct.
35 |
36 | There are no derive macros that can be used for `Export` but many of the primitive types have it implemented by default.
37 |
38 | To implement `Export` for the previous Rust data type, you can do so as in the following example:
39 |
40 | ```rust
41 | // Note: By default `struct` will be converted to and from a Dictionary where property corresponds to a key-value pair.
42 | #[derive(ToVariant, FromVariant)]
43 | struct Foo {
44 | number: i32,
45 | float: f32,
46 | string: String
47 | }
48 |
49 | impl Export for Foo {
50 | // This type should normally be one of the types defined in [gdnative::export::hint](https://docs.rs/gdnative/latest/gdnative/export/hint/index.html).
51 | // Or it can be any custom type for differentiating the hint types.
52 | // In this case it is unused, so it is left as ()
53 | type Hint = ();
54 | fn export_info(hint: Option) -> ExportInfo {
55 | // As `Foo` is a struct that will be converted to a Dictionary when converted to a variant, we can just add this as the VariantType.
56 | ExportInfo::new(VariantType::Dictionary)
57 | }
58 | }
59 | ```
60 |
61 | ## Case study: exporting Rust enums to Godot and back
62 |
63 | A common challenge that many developers may encounter when using godot-rust is that while [Rust enums](https://doc.rust-lang.org/std/keyword.enum.html) are [Algebraic Data Types](https://en.wikipedia.org/wiki/Algebraic_data_type), [Godot enums](https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/gdscript_basics.html#enums) are constants that correspond to integer types.
64 |
65 | By default, Rust enums are converted to a Dictionary representation. Its keys correspond to the name of the enum variants, while the values correspond to a Dictionary with fields as key-value pairs.
66 |
67 | For example:
68 |
69 | ```rust
70 | #[derive(ToVariant, FromVariant)]
71 | enum MyEnum {
72 | A,
73 | B { inner: i32 },
74 | C { inner: String }
75 | }
76 | ```
77 |
78 | Will convert to the following dictionary:
79 |
80 | ```gdscript
81 | # MyEnum::A
82 | "{ "A": {} }
83 | # MyEnum::B { inner: 0 }
84 | { "B": { "inner": 0 } }
85 | # MyEnum::C { inner: "value" }
86 | { "C": {"inner": "value" } }
87 | ```
88 |
89 | As of writing (gdnative 0.9.3), this default case is not configurable. If you want different behavior, it is necessary to implement `FromVariant` and `Export` manually for this data-type.
90 |
91 | ### Case 1: Rust Enum -> Godot Enum
92 |
93 | Consider the following code:
94 |
95 | ```rust
96 | enum MyIntEnum {
97 | A=0, B=1, C=2,
98 | }
99 |
100 | #[derive(NativeClass)]
101 | #[inherit(Node)]
102 | #[no_constructor]
103 | struct MyNode {
104 | #[property]
105 | int_enum: MyIntEnum
106 | }
107 | ```
108 |
109 | This code defines the enum `MyIntEnum`, where each enum value refers to an integer value.
110 |
111 | Without implementing the `FromVariant` and `Export` traits, attempting to export `MyIntEnum` as a property of `MyNode` will result in the following error:
112 |
113 | ```sh
114 | the trait bound `MyIntEnum: gdnative::prelude::FromVariant` is not satisfied
115 | required because of the requirements on the impl of `property::accessor::RawSetter` for `property::accessor::invalid::InvalidSetter<'_>`2
116 |
117 | the trait bound `MyIntEnum: Export` is not satisfied
118 | the trait `Export` is not implemented for `MyIntEnum`
119 | ```
120 |
121 | This indicates that `MyIntEnum` does not have the necessary traits implemented for `FromVariant` and `Export`. Since the default derived behavior may not be quite what we want, we can implement this with the following:
122 |
123 | ```rust
124 | impl FromVariant for MyIntEnum {
125 | fn from_variant(variant: &Variant) -> Result {
126 | let result = i64::from_variant(variant)?;
127 | match result {
128 | 0 => Ok(MyIntEnum::A),
129 | 1 => Ok(MyIntEnum::B),
130 | 2 => Ok(MyIntEnum::C),
131 | _ => Err(FromVariantError::UnknownEnumVariant {
132 | variant: "i64".to_owned(),
133 | expected: &["0", "1", "2"],
134 | }),
135 | }
136 | }
137 | }
138 |
139 | impl Export for MyIntEnum {
140 | type Hint = IntHint;
141 |
142 | fn export_info(_hint: Option) -> ExportInfo {
143 | Self::Hint::Enum(EnumHint::new(vec![
144 | "A".to_owned(),
145 | "B".to_owned(),
146 | "C".to_owned(),
147 | ]))
148 | .export_info()
149 | }
150 | }
151 |
152 | ```
153 |
154 | After implementing `FromVariant` and `Export`, running `cargo check` would result in the following additional error:
155 |
156 | ```sh
157 | the trait bound `MyIntEnum: gdnative::prelude::ToVariant` is not satisfied
158 | the trait `gdnative::prelude::ToVariant` is not implemented for `MyIntEnum`
159 | ```
160 |
161 | If the default implementation were sufficient, we could use `#[derive(ToVariant)]` for `MyIntEnum` or implement it manually with the following code:
162 |
163 | ```rust
164 | use gdnative::core_types::ToVariant;
165 | impl ToVariant for MyIntEnum {
166 | fn to_variant(&self) -> Variant {
167 | match self {
168 | MyIntEnum::A => { 0.to_variant() },
169 | MyIntEnum::B => { 1.to_variant() },
170 | MyIntEnum::C => { 2.to_variant() },
171 | }
172 | }
173 | }
174 | ```
175 |
176 | At this point, there should be no problem in using `MyIntEnum` as a property in your native class that is exported to the editor.
177 |
--------------------------------------------------------------------------------
/src/export/android.md:
--------------------------------------------------------------------------------
1 | # Android
2 |
3 | **Disclaimer**: _Currently, the following steps are tested and confirmed to work on Linux only._
4 |
5 | In order to export to Android, we need to compile our Rust source for the appropriate targets. Unlike compiling for our native targets, there are a few extra steps involved with cross-compiling for another target.
6 |
7 |
8 | ## Installing prerequisites
9 |
10 | First, we need to install the **Android SDK** with **NDK** enabled. This contains the necessary tools for each architecture. Once the Android SDK is installed, open Editor Settings in the Godot GUI (*Editor > Editor Settings > Export > Android*) and set the **absolute paths** to `adb`, `jarsigner`, and the debug keystore (`debug.keystore`), all of which can be found in the Android SDK installation.
11 |
12 | > ### About NDK versions
13 | >
14 | > `libgcc` was removed in Android NDK version `r23-beta3`. Although Rust was updated accordingly (see [this issue](https://github.com/rust-lang/rust/pull/85806)), it's not available in stable Rust yet (as of 2023-03-04). Therefore, you need to use the **nightly toolchain** if you have **Android NDK version 23 or higher**.
15 | >
16 | > ```bash
17 | > # Install nightly toolchain
18 | > rustup toolchain install nightly
19 | > ```
20 | >
21 | > After that, run all `rustup` or `cargo` commands in this tutorial using the nightly toolchain by adding `+nightly` argument. For example:
22 | >
23 | > ```bash
24 | > rustup +nightly target add aarch64-linux-android
25 | > ```
26 | >
27 | > Alternatively, you can change the toolchain for your project using `rust-toolchain.toml` file, or you can change the global default toolchain. See [rustup book](https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file) for more information.
28 |
29 | Then, we'll install the Rust toolchains for the targets we want to support:
30 |
31 | ```bash
32 | rustup target add aarch64-linux-android # for arm64 (64-bit)
33 | rustup target add x86_64-linux-android # for x86_64 (64-bit)
34 | ```
35 |
36 | ### 32-bit targets
37 |
38 | The `aarch64-linux-android` and `x86_64-linux-android` toolchains are our top priorities, because Google [has been requiring 64-bit binaries](https://android-developers.googleblog.com/2019/01/get-your-apps-ready-for-64-bit.html) for all new apps on Play Store since August 2019, and will stop serving 32-bit apps in 2021. If you, nevertheless, want to support 32-bit targets, there are a few more dependencies to install.
39 |
40 | > ### A bit of context
41 | >
42 | > There are two major CPU providers in the Android ecosystem: ARM and Intel.
43 | >
44 | > They were primarily supporting 32-bit OS, with notably [**ARMv7**](https://en.wikipedia.org/wiki/ARM_architecture#32-bit_architecture) and [**x86**](https://en.wikipedia.org/wiki/X86) architectures, until they started supporting 64-bit OS, by introducing [**ARMv8-A**](https://en.wikipedia.org/wiki/ARM_architecture#64/32-bit_architecture) (often called **ARM64**) and [**x86-64**](https://en.wikipedia.org/wiki/X86-64) (often called **Intel 64** or **AMD64**, in reference to a [long-time conflict](https://en.wikipedia.org/wiki/X86-64#History_2) between Intel and AMD).
45 | >
46 | > **Aarch64** is the 64-bit execution state that is introduced in ARM64 chips. [**i686**](https://en.wikipedia.org/wiki/P6_%28microarchitecture%29) (also called **P6**) is actually the sixth-generation Intel x86 microarchitecture.
47 | >
48 | > Generally speaking, 32-bit programs can run on 64-bit systems, but 64-bit programs won't run on 32-bit systems.
49 |
50 | #### Rust toolchains for 32-bit targets
51 |
52 | ```bash
53 | rustup target add armv7-linux-androideabi # for armv7 (32-bit)
54 | rustup target add i686-linux-android # for x86 (32-bit)
55 | ```
56 |
57 | #### `gcc` libraries for cross-compilation
58 |
59 | On Windows, we will need to setup a [32-bit/64-bit compatible MinGW](https://sourceforge.net/projects/mingw-w64/) instance.
60 |
61 | On UNIX-like systems, the required packages are usually available under different names in the package managers for each distribution. On Debian-based Linuxes (including Ubuntu), for example, the required libraries can be installed using `apt`:
62 |
63 | ```bash
64 | apt-get update
65 | apt-get install g++-multilib gcc-multilib libc6-dev-i386 -y
66 | ```
67 |
68 | ### Custom Godot build
69 |
70 | Note that if you are using GDNative with `custom-godot` setting, you need to compile Godot for Android yourself. Follow [the instructions](https://docs.godotengine.org/en/3.6/development/compiling/compiling_for_android.html) in official Godot documentation and make sure that GDNative support is enabled (which will be enabled by default unless you add `module_gdnative_enabled=no`).
71 |
72 |
73 | ## Setting up Cargo
74 |
75 | To make Cargo aware of the proper platform-specific linkers that it needs to use for Android targets, we need to put the paths to the binaries in the Cargo configuration file, which can be found (or created) at `$HOME/.cargo/config.toml` on UNIX-like systems, or `%USERPROFILE%\.cargo\config.toml` on Windows), using [`[target]` tables](https://doc.rust-lang.org/cargo/reference/config.html#targettriplelinker):
76 |
77 | ```toml
78 | [target.armv7-linux-androideabi]
79 | linker = "/usr/local/lib/android/sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi29-clang"
80 | ```
81 |
82 | ... where the value of `linker` is an **absolute path** to the Android SDK linker for the target triple. Assuming `$ANDROID_SDK_ROOT` is the Android SDK path and `$ANDROID_NDK_VERSION` is the installed NDK instance version, these binaries can be found at:
83 |
84 | - Windows: `$ANDROID_SDK_ROOT\ndk\$ANDROID_NDK_VERSION\toolchains\llvm\prebuilt\windows-x86_64\bin\`
85 | - UNIX-like systems: `$ANDROID_SDK_ROOT/ndk/$ANDROID_NDK_VERSION/toolchains/llvm/prebuilt/linux-x86_64/bin/`
86 |
87 | > Alternatively, the NDK can be located under `$ANDROID_SDK_ROOT/ndk-bundle` instead of `$ANDROID_SDK_ROOT/ndk/$ANDROID_NDK_VERSION`, but this folder is deprecated because it doesn't allow for parallel versions installation.
88 |
89 | Repeat for all targets installed in the previous step, until we get something that looks like:
90 |
91 | ```toml
92 | # Example configuration on an UNIX-like system. `29` is the Android API version.
93 |
94 | [target.armv7-linux-androideabi]
95 | linker = "/usr/local/lib/android/sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi29-clang"
96 |
97 | [target.aarch64-linux-android]
98 | linker = "/usr/local/lib/android/sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang"
99 |
100 | [target.i686-linux-android]
101 | linker = "/usr/local/lib/android/sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android29-clang"
102 |
103 | [target.x86_64-linux-android]
104 | linker = "/usr/local/lib/android/sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android29-clang"
105 | ```
106 |
107 | Alternatively, you can use cargo config environment variables:
108 |
109 | ```bash
110 | export CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER="/usr/local/lib/android/sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi29-clang"
111 | export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="/usr/local/lib/android/sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang"
112 | export CARGO_TARGET_I686_LINUX_ANDROID_LINKER="/usr/local/lib/android/sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android29-clang"
113 | export CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER="/usr/local/lib/android/sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android29-clang"
114 | ```
115 |
116 |
117 | ## Setting up environment variables for `gdnative-sys`
118 |
119 | The `gdnative-sys` crate can infer include paths for Android targets, but it requires the following environment variables:
120 |
121 | - `$ANDROID_SDK_ROOT`, which should point to the Android SDK root (which contains the `ndk` or `ndk-bundle` directory).
122 | - `$ANDROID_NDK_VERSION`, which should contain the selected ndk version (if omitted, the latest version available is used and a warning is issued).
123 |
124 | Depending on your installation, these environment variables might have already been set. Otherwise, the variables may be set in bash:
125 |
126 | ```bash
127 | export ANDROID_SDK_ROOT=/path/to/android/sdk
128 | export ANDROID_NDK_VERSION=21.4.7075529
129 | ```
130 |
131 | ... or in PowerShell on Windows:
132 |
133 | ```powershell
134 | $env:ANDROID_SDK_ROOT = "C:\path\to\android\sdk"
135 | $env:ANDROID_NDK_VERSION = "21.4.7075529"
136 | ```
137 |
138 |
139 | ## Building the GDNative library
140 |
141 | Finally, we can now build the GDNative library with Cargo for one or multiple targets:
142 |
143 | ```bash
144 | cargo build --release --target x86_64-linux-android
145 | ```
146 |
147 | **Important note**: ARM and x86 are, by design, different architectures. It is normal to get errors while running `cargo test` with a Rust library targeting ARMv7 on a x86-64 CPU, for example, since the CPU is unable to handle it.
148 |
149 |
150 | ## Exporting in Godot
151 |
152 | ### Linking to Android binaries in `.gdns`
153 |
154 | After building the GDNative libraries, we need to link them to Godot, by adding new entries in the GDNative library declaration file (`*.gdnlib`) for `Android.armeabi-v7a` (ARMv7), `arm64-v8a` (ARM64), `Android.x86` (x86) and/or `Android.x86_64` (x86-64), depending of the toolchains we actually used in previous steps:
155 |
156 | ```
157 | [entry]
158 |
159 | Android.armeabi-v7a="res://target/armv7-linux-androideabi/release/lib.so"
160 | Android.arm64-v8a="res://target/aarch64-linux-android/release/lib.so"
161 | Android.x86="res://target/i686-linux-android/release/lib.so"
162 | Android.x86_64="res://target/x86_64-linux-android/release/lib.so"
163 |
164 | [dependencies]
165 |
166 | Android.armeabi-v7a=[ ]
167 | Android.arm64-v8a=[ ]
168 | Android.x86=[ ]
169 | Android.x86_64=[ ]
170 | ```
171 |
172 | ### APK signing for publication
173 |
174 | Usually, we can choose between releasing an app in **Debug** or **Release** mode. However, the Release mode is required when officially releasing to Play Store.
175 |
176 | In order to configure Godot to sign Release APKs, we'll first need to generate a project-specific Release keystore using `keytool`, and set up an alias and a single password (as explained in the [Godot docs](https://docs.godotengine.org/en/3.2/getting_started/workflow/export/exporting_for_android.html#exporting-for-google-play-store), `-storepass` and `-keypass` option values must be the same):
177 |
178 | ```bash
179 | keytool -genkeypair -v -keystore path/to/my.keystore -alias some-alias -keyalg RSA -keysize 2048 -validity 10000 -storepass my-password -keypass my-password
180 | ```
181 |
182 | Then, we will register its path in Export Settings (*Project > Export*) or `export_presets.cfg`. Please note that passwords entered in the GUI will be stored in `export_presets.cfg`. Be sure to not commit it into any VCS!
183 |
184 | ```
185 | # Remember to not commit the password as is in VCS!
186 | keystore/release="path/to/my.keystore"
187 | keystore/release_user="some-alias"
188 | keystore/release_password="my-password"
189 | ```
190 |
191 | ### Exporting
192 |
193 | Finally, we can now export the project using the GUI (*Project > Export... > Android (Runnable)*) and uncheck "*Export with Debug*" in GUI when being asked to enter APK file name. We may also use one of the following commands from the CLI to do the same:
194 |
195 | ```bash
196 | # Debug mode
197 | godot --export-debug "Android" path/to/my.apk
198 |
199 | # Release mode
200 | godot --export "Android" path/to/my.apk
201 | ```
202 |
203 | When trying to install the app directly from the APK on an Android device, Play Protect may display a warning explaining that _the app developers are not recognized, so the app may be unsafe_. This is the expected behavior for an APK in Release mode that isn't actually released on Play Store.
204 |
205 | If not planning to release on Play Store, one may file an appeal from Play Protect using [a form provided by Google](https://support.google.com/googleplay/android-developer/contact/protectappeals).
206 |
207 | # Troubleshooting
208 |
209 | Compile time:
210 | - `unable to find library -lgcc`: You need the nightly version of Rust toolchain. See ["About NDK versions"](#about-ndk-versions) section.
211 |
212 | Runtime:
213 | - `ERROR: No loader found for resource: res://*.gdns`: Your Godot APK was compiled without GDNative support. Make sure that you compile without `module_gdnative_enabled=no` setting in your build command.
214 |
--------------------------------------------------------------------------------
/src/export/html5.md:
--------------------------------------------------------------------------------
1 | # HTML5
2 |
3 | Exporting to HTML5 works just like exporting to other platforms, however there are some things that can make the process a bit tricky and require extra attention.
4 |
5 | ## What you need (to know)
6 |
7 | The Godot HTML5 export templates are built with [Emscripten](https://emscripten.org/), so you need to build your Rust code for the `wasm32-unknown-emscripten` target (`wasm32-unknown-unknown` will not work). Since Emscripten does not offer a stable ABI between versions, your code and the Godot export template have to be built with the same Emscripten version, which also needs to be compatible with the Rust compiler version you are using.
8 |
9 | In practice, this means you probably have to do some or all of these things:
10 |
11 | * install a specific version of Emscripten
12 | * [build the HTML5 export template yourself](https://docs.godotengine.org/en/stable/development/compiling/compiling_for_web.html)
13 | * use a specific version of Rust
14 |
15 | You can check which versions of Emscripten/Rust you are using like this:
16 |
17 | ```bash
18 | emcc -v
19 | rustc --version --verbose
20 | ```
21 |
22 | A list of compatible Rust and Emscripten versions are given in the next section.
23 |
24 | Emscripten uses a cache to store build artifacts and header files. This means that the order in which steps are completed matters. In particular, Godot export template should be built before the GDNative library.
25 |
26 | Also note that `wasm32-unknown-emscripten` is a 32-bit target, which can cause problems with crates incorrectly assuming that `usize` is 64 bits wide.
27 |
28 | ### Limitations
29 |
30 | * Multi-threading is not supported. See [this issue](https://github.com/godot-rust/gdnative/issues/1022) for more details and instructions for failing experimental build.
31 | * Debug builds may not work due to their large size. See [the corresponding issue](https://github.com/godot-rust/gdnative/issues/1021).
32 | * As a workaround, you can set `opt-level = 1` in debug builds, which reduces the build size. Add the following to your workspace's/project's `Cargo.toml`:
33 | ```toml
34 | [profile.dev]
35 | opt-level = 1
36 | ```
37 |
38 | ## Godot 3.5
39 |
40 | **Disclaimer**: _Currently, the following steps are only tested and confirmed to work on Linux._
41 |
42 | [Godot 3.5's prebuilt HTML5 export template is built with Emscripten 3.1.10](https://github.com/godotengine/godot/blob/3.5/.github/workflows/javascript_builds.yml). It might be possible to use it if build your Rust code with that exact version, but extra compiler flags may be needed. This guide focuses on building the export template yourself with a recent version of Emscripten.
43 |
44 | As of 2023-01-28 you also need to use a Rust nightly build.
45 |
46 | Confirmed working versions are:
47 |
48 | * Rust toolchain `nightly-2023-01-27` and `Emscripten 3.1.21 (f9e81472f1ce541eddece1d27c3632e148e9031a)`
49 | * This combination will be used in the following sections of this tutorial.
50 | * `rustc 1.65.0-nightly (8c6ce6b91 2022-09-02)` and `Emscripten 3.1.21-git (3ce1f726b449fd1b90803a6150a881fc8dc711da)`
51 |
52 | The compatibility problems between Rust and Emscripten versions are assumed to stem from differing LLVM versions. You can use the following commands to check the LLVM versions of the currently installed nightly toolchain and the currently active emcc:
53 |
54 | ```bash
55 | rustc +nightly --version --verbose
56 | emcc -v
57 | ```
58 |
59 | `emcc -v` reports the version number of `clang`, which is equal to the version number of the overall LLVM release.
60 |
61 | ### Install Rust toolchain
62 |
63 | Following bash commands install `nightly-2023-01-27` toolchain with `wasm32-unknown-emscripten` target:
64 |
65 | ```bash
66 | # Install the specific version of Rust toolchain.
67 | rustup toolchain install nightly-2023-01-27
68 |
69 | # Add wasm32-unknown-emscripten target to this toolchain.
70 | rustup +nightly-2023-01-27 target add wasm32-unknown-emscripten
71 | ```
72 |
73 | ### Installing and configuring Emscripten
74 |
75 | Use the following bash commands to install Emscripten 3.1.21, which is known to be compatible with Rust `nightly-2023-01-27`:
76 |
77 | ```bash
78 | # Get the emsdk repo.
79 | git clone https://github.com/emscripten-core/emsdk.git
80 |
81 | # Enter the cloned directory.
82 | cd emsdk
83 |
84 | # Download and install a compatible SDK version.
85 | ./emsdk install 3.1.21
86 |
87 | # Make this SDK version "active" for the current user. (writes .emscripten file)
88 | ./emsdk activate 3.1.21
89 |
90 | # Activate PATH and other environment variables in the current terminal
91 | source ./emsdk_env.sh
92 | ```
93 |
94 | ### Building Godot
95 |
96 | Build the Godot Export template according to the [instructions](https://docs.godotengine.org/en/stable/development/compiling/compiling_for_web.html):
97 |
98 | ```bash
99 | source "/path/to/emsdk-portable/emsdk_env.sh"
100 | scons platform=javascript tools=no gdnative_enabled=yes target=release
101 | mv bin/godot.javascript.opt.gdnative.zip bin/webassembly_gdnative_release.zip
102 | ```
103 |
104 | Since this is a web build, you might want to disable unused modules and optimize your build for size [as shown in Godot documentation](https://docs.godotengine.org/en/stable/development/compiling/optimizing_for_size.html).
105 |
106 | Set the newly built export template as a [custom template](https://user-images.githubusercontent.com/2171264/175822720-bcd2f1ff-0a1d-4495-9f9c-892d42e9bdcd.png) in Godot and be sure to set the export type as GDNative. When exporting, uncheck "Export With Debug".
107 |
108 | ### Building your Rust code
109 |
110 | In your project's `.cargo/config.toml` [(see Cargo Docs)](https://doc.rust-lang.org/cargo/reference/config.html), add the following:
111 |
112 | ```toml
113 | [target.wasm32-unknown-emscripten]
114 | rustflags = [
115 | "-Clink-arg=-sSIDE_MODULE=2", # build a side module that Godot can load
116 | "-Zlink-native-libraries=no", # workaround for a wasm-ld error during linking
117 | "-Cpanic=abort", # workaround for a runtime error related to dyncalls
118 | ]
119 | ```
120 |
121 | Build like this:
122 |
123 | ```bash
124 | source "/path/to/emsdk-portable/emsdk_env.sh"
125 | export C_INCLUDE_PATH=$EMSDK/upstream/emscripten/cache/sysroot/include
126 |
127 | cargo +nightly-2023-01-27 build --target=wasm32-unknown-emscripten --release
128 | ```
129 |
130 | This will produce a `.wasm` file in `target/wasm32-unknown-emscripten/release/` directory. Add this file to `GDNativeLibrary` properties under `entry/HTML5.wasm32`, just like you would add a `.so` or a `.dll` for Linux or Windows.
131 |
132 | ### Errors you might encounter
133 |
134 | Compile time:
135 | * `failed to run custom build command for gdnative-sys v0.10.1`, `fatal error: 'wchar.h' file not found`: Emscripten cache not populated, build Godot export template first
136 | * `undefined symbol: __cxa_is_pointer_type`: You need to build with `-Clink-arg=-sSIDE_MODULE=2`
137 | * `error: undefined symbol: main/__main_argc_argv (referenced by top-level compiled C/C++
138 | code)`: Your `.cargo/config.toml` was not loaded. See [Cargo Docs](https://doc.rust-lang.org/cargo/reference/config.html) and verify its location.
139 |
140 | Runtime:
141 | * `indirect call signature mismatch`: Possibly due to Emscripten version mismatch between Godot and Rust
142 | * `need the dylink section to be first`: Same as above
143 | * `WebAssembly.Module(): Compiling function #1 failed: invalid local index`: You need to build with `-Cpanic=abort`
144 | * `ERROR: Can't resolve symbol godot_gdnative_init. Error: Tried to lookup unknown symbol "godot_gdnative_init" in dynamic lib`: Possibly because Emscripten version is not compatible with Rust toolchain version. See the compatible version list above.
145 | * `wasm validation error: at offset 838450: too many locals`: Binary size is too big. See [limitations](#limitations) section for a workaround.
146 | * `WebAssembly.instantiate(): Compiling function #2262:"gdnative_sys::GodotApi::from_raw::..." failed: local count too large`: Binary size is too big. See [limitations](#limitations) section for a workaround.
147 |
148 | ### Further reading
149 |
150 | In the future, some of this will probably not be needed, for more info see:
151 | * [Tracking issue for godot-rust wasm support](https://github.com/godot-rust/godot-rust/issues/647)
152 | * [Rust](https://github.com/rust-lang/rust/issues/98155) and [Emscripten](https://github.com/rust-lang/rust/pull/98303#issuecomment-1162172132) issues that explain the need for `-Zlink-native-libraries=no`
153 | * [Emscripten PR that should have obsoleted `-Cpanic=abort`](https://github.com/emscripten-core/emscripten/pull/17328)
154 | * [Rust PR that would obsolete `-Clink-arg=-sSIDE_MODULE=2`](https://github.com/rust-lang/rust/pull/98358)
155 |
--------------------------------------------------------------------------------
/src/export/index.md:
--------------------------------------------------------------------------------
1 | # Exporting
2 |
3 | Exporting [Godot](https://godotengine.org/) projects using [godot-rust](https://github.com/godot-rust/godot-rust)
4 | is a 2 steps process:
5 |
6 | * build your Rust code with cargo, which triggers a build of [gdnative crate](https://crates.io/crates/gdnative) for the target platform;
7 | * do a standard [Godot export](https://docs.godotengine.org/en/stable/getting_started/workflow/export/exporting_projects.html).
8 |
9 | If the target you are exporting to is the same as the one you are developping on,
10 | the export is straightforward, however when cross-compiling (eg: exporting for a mobile platform,
11 | or building from a Docker image on a CI)
12 | you need to correctly set up a cross-compiler for the target platform. Rust does this very well,
13 | so provided you only write Rust code, cross-compiling is easy.
14 | However to build [gdnative-sys](https://crates.io/crates/gdnative-sys) you need a working C/C++
15 | cross compiler with, among other things, the correct headers and linker.
16 |
17 | How to set up such a cross-compiler depends on the source and the target platform.
18 |
--------------------------------------------------------------------------------
/src/export/ios.md:
--------------------------------------------------------------------------------
1 | # iOS
2 |
3 | TODO
--------------------------------------------------------------------------------
/src/export/macosx.md:
--------------------------------------------------------------------------------
1 | # Mac OS X
2 |
3 | **Disclaimer**: _Currently, the following steps are tested and confirmed to work on Linux only._
4 |
5 |
6 | ## Use case
7 |
8 | Exporting for Mac OS X is interesting if:
9 |
10 | * you do not have access to Apple hardware
11 | * you want to build from a CI, typically on a Docker image
12 |
13 | If you have access to a real Mac, building natively is easier.
14 |
15 |
16 | ## Why is this complex ?
17 |
18 | Cross-compiling Rust programs for Mac OS X is as simple as:
19 |
20 | ```sh
21 | rustup target add x86_64-apple-darwin
22 | cargo build --target x86_64-apple-darwin
23 | ```
24 |
25 | However to build [gdnative-sys](https://crates.io/crates/gdnative-sys) you
26 | need a Mac OS X C/C++ compiler, the Rust compiler is not enough. More precisely you need
27 | an SDK which usually comes with [Xcode](https://developer.apple.com/xcode/).
28 | For Mac users, this SDK is "just there" but when cross-compiling, it is
29 | typically missing, even if your compiler is able to produce Mac OS X compatible binaries.
30 |
31 | The most common error is:
32 |
33 | ```
34 | fatal error: 'TargetConditionals.h' file not found
35 | ```
36 |
37 | Installing just this file is not enough, this error is usually a consequence
38 | of the whole SDK missing, so there is no chance you can get a build.
39 |
40 | What you need to do is:
41 |
42 | * download the SDK
43 | * fix all paths and other details so that it ressembles a Mac OS X environment
44 | * then build with `cargo build --target x86_64-apple-darwin`
45 |
46 | Hopefully, the first two steps, downloading the SDK and fixing details,
47 | are handled by a tool called [osxcross](https://github.com/tpoechtrager/osxcross)
48 | which is just about setting up a working C/C++ compiler on Linux.
49 |
50 | ## Howto
51 |
52 | ```sh
53 | # make sure you have a proper C/C++ native compiler first, as a suggestion:
54 | sudo apt-get install llvm-dev libclang-dev clang libxml2-dev libz-dev
55 |
56 | # change the following path to match your setup
57 | export MACOSX_CROSS_COMPILER=$HOME/macosx-cross-compiler
58 |
59 | install -d $MACOSX_CROSS_COMPILER/osxcross
60 | install -d $MACOSX_CROSS_COMPILER/cross-compiler
61 | cd $MACOSX_CROSS_COMPILER
62 | git clone https://github.com/tpoechtrager/osxcross && cd osxcross
63 |
64 | # picked this version as they work well with godot-rust, feel free to change
65 | git checkout 7c090bd8cd4ad28cf332f1d02267630d8f333c19
66 | ```
67 |
68 | At this stage you need to [download and package the SDK](https://github.com/tpoechtrager/osxcross#packaging-the-sdk)
69 | which can not be distributed with osxcross for legal reasons.
70 | [Please ensure you have read and understood the Xcode license terms before continuing](https://www.apple.com/legal/sla/docs/xcode.pdf).
71 |
72 | You should now have an SDK file, for example `MacOSX10.10.sdk.tar.xz`.
73 |
74 | ```sh
75 | # move the file where osxcross expects it to be
76 | mv MacOSX10.10.sdk.tar.xz $MACOSX_CROSS_COMPILER/osxcross/tarballs/
77 | # build and install osxcross
78 | UNATTENDED=yes OSX_VERSION_MIN=10.7 TARGET_DIR=$MACOSX_CROSS_COMPILER/cross-compiler ./build.sh
79 | ```
80 |
81 | At this stage, you should have, in `$MACOSX_CROSS_COMPILER/cross-compiler`,
82 | a working cross-compiler.
83 |
84 | Now you need to tell Rust to use it when linking
85 | Mac OS X programs:
86 |
87 | ```sh
88 | echo "[target.x86_64-apple-darwin]" >> $HOME/.cargo/config
89 | find $MACOSX_CROSS_COMPILER -name x86_64-apple-darwin14-cc -printf 'linker = "%p"\n' >> $HOME/.cargo/config
90 | echo >> $HOME/.cargo/config
91 | ```
92 |
93 | After this, your `$HOME/.cargo/config` (not the `cargo.toml` file in your project, this is a different file)
94 | should contain:
95 |
96 | ```toml
97 | [target.x86_64-apple-darwin]
98 | linker = "/home/my-user-name/macosx-cross-compiler/cross-compiler/bin/x86_64-apple-darwin14-cc"
99 | ```
100 |
101 | Then, we need to also tell the compiler to use the right compiler and headers.
102 | In our example, with SDK 10.10, the env vars we need to export are:
103 |
104 | ```sh
105 | C_INCLUDE_PATH=$MACOSX_CROSS_COMPILER/cross-compiler/SDK/MacOSX10.10.sdk/usr/include
106 | CC=$MACOSX_CROSS_COMPILER/cross-compiler/bin/x86_64-apple-darwin14-cc
107 | ```
108 |
109 | You probably do not want to export those permanently as they are very
110 | specific to building for Mac OS X so they are typically passed at each
111 | call to `cargo`, eg:
112 |
113 | ```sh
114 | C_INCLUDE_PATH=$MACOSX_CROSS_COMPILER/cross-compiler/SDK/MacOSX10.10.sdk/usr/include CC=$MACOSX_CROSS_COMPILER/cross-compiler/bin/x86_64-apple-darwin14-cc cargo build --release --target x86_64-apple-darwin
115 | ```
116 |
117 | As a consequence, you do *not* need to put `$MACOSX_CROSS_COMPILER/cross-compiler/bin` in your `$PATH` if
118 | you only plan to export [godot-rust](https://github.com/godot-rust/godot-rust) based programs, as the
119 | binary needs to be explicitly overloaded.
120 |
121 |
122 | ## Exporting
123 |
124 | Once your `.dylib` file is built, a standard Godot export should work:
125 |
126 | ```sh
127 | godot --export "Mac OSX" path/to/my.zip
128 | ```
129 |
130 | Note that when exporting from a non Mac OS X platform, it is not possible to build a `.dmg`.
131 | Instead, a `.zip` is produced. Again, the tool required to build Mac OS X disk images is
132 | only available on Mac OS X. The `.zip` works fine though, it just contains `my.app`
133 | folder, ready to use.
134 |
135 | Double-check your `.dylib` file is there.
136 |
137 |
138 | ## Useful links
139 |
140 | * [https://github.com/tpoechtrager/osxcross](https://github.com/tpoechtrager/osxcross): tool used to install the Mac OS X SDK on Linux
141 | * [https://wapl.es/rust/2019/02/17/rust-cross-compile-linux-to-macos.html](https://wapl.es/rust/2019/02/17/rust-cross-compile-linux-to-macos.html): a complete tutorial on how to use osxcross
142 |
--------------------------------------------------------------------------------
/src/faq/community.md:
--------------------------------------------------------------------------------
1 | # FAQ: Community
2 |
3 | ## Table of contents
4 |
5 |
6 | ## I need help, where can I ask?
7 |
8 | The godot-rust project uses several sources for different kinds of information.
9 |
10 | ### 1 - API documentation
11 |
12 | The documentation of released crates is hosted at [docs.rs](https://docs.rs/gdnative).
13 | If you prefer to look up API details of the latest `master` in-development version, they are hosted on [GitHub pages](https://godot-rust.github.io/docs/gdnative/).
14 |
15 | The crate-level documentation of `gdnative` should guide you to more concrete places to look at.
16 | If you don't know where to start, look at the `prelude` module -- it contains the most commonly used symbols.
17 |
18 | ### 2 - Godot Docs
19 |
20 | As godot-rust is the layer that wraps the [Godot API](https://docs.godotengine.org/en/stable/classes/index.html), the behavior and use cases for many of the classes and methods are available in the official Godot documentation. Whenever you have questions for anything Godot-specific that is outside godot-rust's scope, this is the place to go as well.
21 |
22 | ### 3 - Discord Server
23 |
24 | For more complex questions, the fastest way to get an answer is to reach out to us and fellow developers on the [godot-rust Discord](https://discord.gg/aKUCJ8rJsc).
25 |
26 | ### 4 - Bug reports: GitHub issue
27 |
28 | If you find a bug or an issue with the godot-rust bindings or have an idea for future development, please feel free to open up a GitHub issue and we'd be happy to take a look.
29 |
30 | Please consider the [Contribution Guidelines](https://github.com/godot-rust/godot-rust/blob/master/CONTRIBUTING.md) if you plan to contribute.
31 |
32 | GitHub issues are not intended for general questions, as only project maintainers and contributors generally read and track new issues.
33 | As such, if you have a question about how to _use_ the library, we highly recommend seeking out one of the above options before opening an issue.
34 |
--------------------------------------------------------------------------------
/src/faq/configuration.md:
--------------------------------------------------------------------------------
1 | # FAQ: Configuration
2 |
3 | ## Table of contents
4 |
5 |
6 | ## How do I create the library file for my GDNative binary?
7 |
8 | You can create .gdnlib files with either of the following methods.
9 |
10 | ### Editor
11 |
12 | 1. In the editor, right click in the File System and Select _New Resource_.
13 | 2. Select _GDNativeLibrary_ from the menu.
14 | 3. Save as new GDNativeLibrary. The typical file extension is `.gdnlib`.
15 | 4. Select the GDNativeLibrary.
16 | 5. For each desired target, select a path to the location of the library created by Cargo.
17 |
18 | ### Manual
19 |
20 | Create a text file with the `.gdnlib` extension with the following content.
21 | Please note: you only need to include paths for the targets you plan on building for.
22 |
23 | ```toml
24 | [entry]
25 | X11.64="res://path/to/lib{binary-name}.so"
26 | OSX.64="res://path/to/lib{binary-name}.dylib"
27 | Windows.64="res://path/to/{binary-name}.dll"
28 |
29 | [dependencies]
30 | X11.64=[ ]
31 | OSX.64=[ ]
32 | Windows.64 = [ ]
33 |
34 | [general]
35 | singleton=false
36 | load_once=true
37 | symbol_prefix="godot_"
38 | reloadable=true
39 | ```
40 |
41 |
42 | ## Once I create the `.gdnlib` file, how do I create the native script, so that I can attach it to the nodes in the scene tree?
43 |
44 | Script files can be created in two ways.
45 |
46 | 1. From the editor.
47 | 2. Manually by creating a `.gdns` file with the following code snippet.
48 | ```toml
49 | [gd_resource type="NativeScript" load_steps=2 format=2]
50 |
51 | [ext_resource path="res://path/to/{filename}.gdnlib" type="GDNativeLibrary" id=1]
52 |
53 | [resource]
54 | resource_name = "{class-name}"
55 | class_name = "{class-name}"
56 | library = ExtResource( 1 )
57 | ```
58 |
59 |
60 | ## C headers not found by bindgen
61 |
62 | When building the library, `bindgen` may produce errors that look like this:
63 |
64 | ```
65 | godot-rust/gdnative-sys/godot_headers/gdnative/string.h:39:10: fatal error: 'wchar.h' file not found
66 | ```
67 |
68 | This means that `bindgen` was unable to find the C system headers for your platform. If you can locate the headers manually, you may try setting the `C_INCLUDE_PATH` environment variable so `libclang` could find them. If on Windows, you may try building from the Visual Studio "developer console", which should setup the appropriate variables for you.
69 |
70 |
71 | ## Why aren't my scripts showing up in the _Add Node_ portion of the editor, even though they inherit from `Node`, `Node2D`, `Spatial` or `Control`?
72 |
73 | Due to limitations with Godot 3.x's version of GDNative, NativeScript types do not get registered in the class database. As such, these classes are not included in the _Create New Node_ dialog.
74 |
75 | A workaround to this issue has been included in the recipe [Custom Nodes Plugin](../recipes/custom-node-plugin.md).
76 |
77 |
78 | ## Can I use Rust for a [tool script](https://docs.godotengine.org/en/stable/tutorials/misc/running_code_in_the_editor.html)?
79 |
80 | Yes, any Rust struct that inherits from `NativeClass` can be also used as a tool class by using the `InitHandle::add_tool_class` during native script initialization instead of `InitHandle::add_class`.
81 |
82 | ```rust
83 | #[derive(NativeClass)]
84 | #[inherit(Node)]
85 | stuct MyTool {}
86 | #[methods]
87 | impl MyTool {
88 | fn new (_base: &Node) -> Self {
89 | Self {}
90 | }
91 | }
92 |
93 | fn init(handle: InitHandle) {
94 | handle.add_tool_class::();
95 | }
96 | ```
97 |
98 | Please also see the [native-plugin](https://github.com/godot-rust/godot-rust/tree/master/examples/native-plugin) that is the Rust version of the [editor plugin](https://docs.godotengine.org/en/stable/tutorials/plugins/editor/index.html) tutorial.
99 |
100 | **Important**
101 |
102 | - Editor plugins do not support the hot reload feature. If making use of tool classes, your `GDNativeLibrary` must have `reloadable=false` or the plugins will crash when the editor loses focus.
103 | - It is advised that `GDNativeLibrary` files for editor plugins be compiled as a separate "cdylib" from the `GDNativeLibrary` that may need to be recompiled during development, such as game logic.
104 |
105 |
106 | ## Is it possible to use multiple libraries with GDNative?
107 |
108 | Yes. This is possible, but it should be avoided unless necessary. Generally you should create one `GDNativeLibrary` (`.gdnlib`) and associate many `NativeScript` (`.gdns`) files with the single library.
109 |
110 | The most common use-case for using multiple `GDNativeLibrary` files is when creating editor plugins in Rust that are either intended for distribution or cannot be hot reloaded.
111 |
112 | If you do have a scenario that requires multiple `GDNativeLibrary`, you can create as many libraries as you need for your project. Be mindful that it is possible for name collision to occur when loading from multiple dynamic libraries. This can occur in the event that multiple libraries attempt to register the same class in their init function.
113 |
114 | To avoid these collisions, rather than the `godot_init!` initialization macro, prefer the use of the individual macros.
115 |
116 | For example, if we want to define the symbol_prefix for our library "my_symbol_prefix", we can use the macros below.
117 |
118 | ```rust
119 | // _ indicates that we do not have any specific callbacks needed from the engine for initialization. So it will automatically create
120 | // We add the prefix onto the `gdnative_init` which is the name of the callback that Godot will use when attempting to run the library
121 | godot_gdnative_init!(_ as my_symbol_prefix_gdnative_init);
122 | // native script init requires that the registration function be defined. This is commonly named `fn init(init: InitHandle)` in most of the examples
123 | // We add the prefix onto the `native_script_init` which is the name of the callback that Godot will use when attempting to intialize the script classes
124 | godot_nativescript_init!(registration_function as my_symbol_prefix_nativescript_init);
125 | // _ indicates that we do not have any specific callbacks needed from the engine for initialization. So it will automatically create
126 | // We add the prefix onto the `gdnative_terminate` which is the name of the callback that Godot will use when shutting down the library
127 | godot_gdnative_terminate!(_ as my_symbol_prefix_gdnative_terminate);
128 | ```
129 |
130 | ## Can I expose {insert Rust crate name} for use with Godot and GDScript?
131 |
132 | Yes, with NativeScript so long as you can create a `NativeScript` wrapper you can create GDScript bindings for a Rust crate. See the [logging recipe](../recipes/logging.md) for an example of wrapping a Rust logging crate for use with GDScript.
133 |
134 | ## How do I get auto-completion with IntelliJ-Rust plugin?
135 |
136 | IntelliJ-Family IDEs struggle to autocomplete gdnative types generated at compile-time.
137 |
138 | There are two problems preventing autocompletion of gdnative types in IntelliJ-Rust.
139 |
140 | First, the features necessary are (as of writing) considered experimental and must be enabled. Press `shift` twice to open the find all dialog and type `Experimental features...` and click the checkbox for `org.rust.cargo.evaluate.build.scripts`. Note that `org.rust.cargo.fetch.out.dir` will also work, but is known to be less performant and may be phased out.
141 |
142 | Second, the bindings files generated (~8mb) are above the 2mb limit for files to be processed. As [reported](https://github.com/intellij-rust/intellij-rust/issues/6571#) you can increase the limit with the steps below.
143 | * open custom VM options dialog (`Help` | `Find Action` and type `Edit Custom VM Options`)
144 | * add `-Didea.max.intellisense.filesize=limitValue` line where `limitValue` is desired limit in KB, for example, 10240. Note, it cannot be more than 20 MB.
145 | * restart IDE
146 |
147 |
148 | ## How can I make my debug builds more performant?
149 |
150 | **Note**: These changes may slow down certain aspects of the build times for your game.
151 |
152 | Some simple ways to make your debug builds faster is to update the following profiles in your workspace cargo file.
153 |
154 | ```toml
155 | [profile.dev.package."*"]
156 | opt-level = 3
157 |
158 | [profile.dev]
159 | opt-level=1
160 | ```
161 |
--------------------------------------------------------------------------------
/src/faq/godot4.md:
--------------------------------------------------------------------------------
1 | # FAQ: Godot 4 Status
2 |
3 | ## Table of contents
4 |
5 |
6 | ## What is the status of Godot 4 Support?
7 |
8 | Godot 4 is supported [in the **gdext** GitHub repo][repo].
9 |
10 | For an up-to-date overview of implementation status, consult its ReadMe as well as [issue #24][features].
11 |
12 |
13 | ## What is GDExtension? Why don't we just upgrade GDNative?
14 |
15 | The Godot team has officially announced [GDExtension](https://godotengine.org/article/introducing-gd-extensions) as the **replacement** for GDNative. GDNative is no longer supported in Godot 4.
16 |
17 |
18 | ## Where can I read more about it?
19 |
20 | Check out the [gdext book](/book), which is still under construction.
21 |
22 | [repo]: https://github.com/godot-rust/gdext
23 | [features]: https://github.com/godot-rust/gdext/issues/24
24 |
--------------------------------------------------------------------------------
/src/faq/img/completion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/faq/img/completion.png
--------------------------------------------------------------------------------
/src/faq/img/no-completion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/faq/img/no-completion.png
--------------------------------------------------------------------------------
/src/faq/index.md:
--------------------------------------------------------------------------------
1 | # FAQ
2 |
3 | This is a list of frequently asked questions that have been pulled from various sources. This will be periodically updated with new information.
4 |
5 | Please select one of the categories in the side bar for more information.
6 |
--------------------------------------------------------------------------------
/src/faq/multithreading.md:
--------------------------------------------------------------------------------
1 | # FAQ: Multithreading
2 |
3 | ## Table of contents
4 |
5 |
6 | ## How do I use multithreading?
7 |
8 | Make sure you read [Godot's thread safety guidelines](https://docs.godotengine.org/en/stable/tutorials/performance/threads/thread_safe_apis.html).
9 |
10 | > This is **EXTREMELY IMPORTANT**.
11 |
12 | Read the guidelines again. Make sure you fully understand them.
13 | Anything not explicitly allowed there is a potential minefield.
14 |
15 | This cannot be stressed enough, because threading can easily turn a fun gamedev experience into a debugging nightmare. In fact, most occurrences
16 | of undefined behavior (UB) with godot-rust occur not because of FFI, dangling objects or broken C++ code, but because threads are used incorrectly.
17 | By understanding the implications of multithreading, you can save a lot of effort.
18 |
19 | A few points are worth highlighting in particular:
20 |
21 | 1. Do not mix GDScript's `Thread/Mutex` classes with Rust's [`std::thread`](https://doc.rust-lang.org/std/thread) and
22 | [`std::sync`](https://doc.rust-lang.org/stable/std/sync) modules; they are not compatible.
23 | If you absolutely must access GDScript threads from Rust, use the correct [`Thread`](https://docs.rs/gdnative/latest/gdnative/api/struct.Thread.html)
24 | and [`Mutex`](https://docs.rs/gdnative/latest/gdnative/api/struct.Mutex.html) APIs for it.
25 | 2. Prefer Rust threads whenever possible. Safe Rust statically guarantees that no race conditions can occur (deadlocks are still possible).
26 | In practice, this often means that:
27 | * your game logic (e.g. loading a map) can run in a separate thread, entirely without touching any Godot APIs
28 | * your main thread is exclusively accessing Godot APIs
29 | * the two threads can communicate via [channels](https://doc.rust-lang.org/std/sync/mpsc/fn.channel.html).
30 | 3. As elaborated in Godot's guidelines, most Godot classes are **simply not thread-safe**. This means you can absolutely not access them
31 | concurrently without synchronization. Even if things seem to work, you may invoke UB which can manifest in hard-to-find places.
32 | 4. It is tempting to think that synchronizing concurrent access to an object through `Mutex` solves threading issues. However, this may not be
33 | the case: sometimes there are hidden dependencies between _unrelated_ types -- for example, a `Resource` might access a global
34 | registry, which is currently written by a _different_ object in another thread. Some types internally use shared caches. A lot of these things
35 | are undocumented, which means you must know Godot's implementation to be sure. And the implementation can always change and introduce a bug in
36 | the future.
37 |
38 | **TLDR:** Be conservative regarding assumptions about the thread-safety of Godot APIs.
39 | Rust threads (without Godot APIs) are a very powerful tool -- use them!
40 |
41 |
42 | ## Why does my game freeze while using multiple threads?
43 |
44 | Make sure you have multi-threading enabled under _Project Settings > Rendering > Threading_.
45 |
46 | In addition, you will need to ensure that you are not ending up with a deadlock scenario within your Rust code.
47 |
48 | Last, you may have violated one of the multithreading guidelines and tips in the first section.
49 |
50 |
51 | ## Why is accessing the servers using multiple threads slow?
52 |
53 | Aside from deadlock issues, there are a few potential points to investigate when using Godot's servers.
54 |
55 | ### Potential cause #1 - command queue is too small
56 |
57 | For multi-threaded access the servers use a thread-safe command queue. This allows you to send multiple commands from any thread. These queues have a fixed size that can be set in the threading section of the Memory -> Limits section of the Project settings.
58 |
59 | ### Potential cause #2 - rayon parallel iterators
60 |
61 | The reference created by a server method such as `VisualServer::godot_singleton()` is not thread-safe. As such, you have to individually get a reference to the singleton.
62 | This can cause severe slowdown, that would not occur if the same job were run from a single thread.
63 |
64 | Multi-threading with servers requires that you manually create a thread pool that can hold the reference to the server.
65 | Additional testing is required to ensure that this is an actual optimization.
66 |
67 |
68 | ## Why do I get the `DifferentThread` error?
69 |
70 | For example, what does the following error indicate?
71 |
72 | ```rust
73 | ERROR: : gdnative-core: method call failed with error:
74 | DifferentThread { original: ThreadId(1), current: ThreadId(2) }
75 | At: src/path/to/class.rs:29
76 | ERROR: : gdnative-core: check module level documentation
77 | on gdnative::user_data for more information
78 | At: src/path/to/class.rs:29
79 | ```
80 |
81 | If you call certain code from Godot and receive the above error, it is likely that you need to change the `user_data` that comes with
82 | your `NativeClass` derive. If no type is specified, it defaults to `LocalCellData`, which can only be used from the thread it was created in.
83 |
84 | See the [official docs](https://docs.rs/gdnative/latest/gdnative/export/user_data) for more information on when you should use each type of data.
85 |
--------------------------------------------------------------------------------
/src/faq/support.md:
--------------------------------------------------------------------------------
1 | # FAQ: Versioning and supported platforms
2 |
3 | ## Table of contents
4 |
5 |
6 | ## What does godot-rust's version mean?
7 |
8 | godot-rust follows [Cargo's semantic versioning](https://doc.rust-lang.org/cargo/reference/semver.html) for the API breaking changes.
9 |
10 |
11 | ## Is godot-rust stable?
12 |
13 | godot-rust will not be considered stable until MAJOR version 1.x.x. As such, MINOR version upgrades are subject to potential API breaking changes, but PATCH versions will not break the API.
14 |
15 |
16 | ## Does godot-rust support Godot 4?
17 |
18 | See [dedicated FAQ Page](../faq/godot4.md).
19 |
20 |
21 | ## What is the scope of the godot-rust project?
22 |
23 | **Similar Questions**
24 |
25 | Why is X feature not available in the API?
26 | Why does X function take Y parameters and return Z?
27 |
28 | **Answer**
29 |
30 | The short answer is "that is how the Godot API works". As godot-rust is focused on the bindings to Godot, we follow the API.
31 |
32 | The longer answer is that the goal of the bindings is to ease the friction between using Rust and interacting with the Godot API. This is accomplished by use of Procedural Macros as well as clever use of traits and trait conversions to keep friction and `unsafe` blocks to a minimum.
33 |
34 | Types, which are not part of Godot's `Object` class hierarchy, have an implementation in Rust. This avoids FFI overhead and allows code to be more idiomatic. Examples are `Vector2`, `Vector3`, `Color`, `GodotString`, `Dictionary`, etc.
35 |
36 |
37 | ## Will godot-rust speed up my game in Godot?
38 |
39 | Short Answer: It depends on what you are building and the bottlenecks, but it's pretty fast(tm).
40 |
41 | Longer Answer: Generally speaking, compared to GDScript, Rust will (in most cases) be a large performance increase.
42 |
43 | Compared to an C or C++ GDNative, the performance should be similar.
44 |
45 | Compared to a C++ Engine module, the performance will probably be somewhat slower as GDNative modules cannot take advantage of certain optimizations and need to use the C Foreign Function Interface at runtime.
46 |
47 | Caveat: The above apply only to release builds with appropriate release settings. When comparing to debug builds in Rust can be very slow.
48 |
49 | Caveat 2: It is still possible to write Rust code that has poor performance. You will still need to be mindful of the specific algorithms that you are choosing.
50 |
51 | Caveat 3: A lot of code in a game is not performance-critical and as such, Rust will help only in limited ways. When deciding between GDScript and Rust, you should also consider other factors such as static type safety, scalability, ecosystem and prototyping speed. Try to use the best of both worlds, it's very well possible to have part of your code in GDScript and part in Rust.
52 |
53 |
54 | ## Which platforms are supported?
55 |
56 | Short Answer: Wherever you can get your code (and Godot) to run. :)
57 |
58 | Long Answer: Rust and Godot are natively available for Windows, Linux, Android and iOS export targets.
59 |
60 | As of writing, WASM targets are a tentatively doable, but it requires additional configuration and is currently not supported out of the box. The godot-rust bindings do not officially support this target. The progress in this regard can be tracked in [godot-rust/godot-rust#647](https://github.com/godot-rust/godot-rust/issues/647).
61 |
62 |
63 | ## Does godot-rust support consoles?
64 |
65 | The official position of the godot-rust project is that, we do not have the ability to offer console support due to a lacking access to the SDK.
66 |
67 | As for whether or not it is possible to compile Rust to run on a console, due to the Non-disclosure Agreements that are a part of the console SDKs, it is unlikely that anyone can give you a definitive answer.
68 |
69 | The official Godot documentation [goes into more details](https://docs.godotengine.org/en/stable/tutorials/platform/consoles.html) with how this works from a Godot perspective. Please keep in mind that this does not necessarily extend to GDNative.
70 |
71 | Regarding whether Rust can run on a console or not, as most modern consoles are using x86 processor architectures, it should be possible to compile for them. The primary issue will be whether the console manufacturer has a version of the Rust standard library that is building for their console. If not, it would be necessary to port it or leverage a port from another licensed developer.
--------------------------------------------------------------------------------
/src/index.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | Welcome to the **gdnative book**! This is a user guide for the Rust bindings to Godot 3.
4 |
5 | Note that `gdnative` is not as actively maintained anymore as its successor, `gdext`. If you are interested in Godot 4, check out the [gdext book](../book).
6 |
7 | If you're new to Rust, before getting started, it is highly recommended that you familiarize yourself with concepts outlined in the officially maintained [Rust Book](https://doc.rust-lang.org/book/) before you getting started with godot-rust.
8 |
9 |
10 | ## Navigating this chapter
11 |
12 | If you're new to `godot-rust`, try the [Getting Started](intro/index.md) tutorial first!
13 |
14 | For more information about architecture with `godot-rust`, the [GDNative Overview](overview/index.md) gives a broad overview of _how_ the library can be used with different use-cases, as well as in-depth information for the underlying API.
15 |
16 | If you have specific code questions that are not covered in the _Getting Started_ guide, please check out the [Frequently Asked Questions](faq) or [Recipes](recipes/index.md) for some additional resources related to configuring `godot-rust`.
17 |
18 | In case you are coming from earlier versions of `godot-rust` and would like to update, you can have a look at the [Advanced Guides](advanced) chapter for migration guides.
19 |
20 |
21 | ## About godot-rust
22 |
23 | This project specifically supports the [Rust Programming Language](https://www.rust-lang.org/) bindings to both [GDNative] and [GDExtension] APIs, for the Godot engine versions 3 and 4, respectively.
24 |
25 | Outside of personal preference, Rust may be a good choice for your game for the following reasons:
26 | - Native levels of performance.
27 | - Memory safety validated at compile time.*
28 | - [Fearless Concurrency](https://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html).*
29 | - The [cargo](https://doc.rust-lang.org/stable/cargo/) build system and dependency management.
30 | - The ability to leverage Rust's crate ecosystem from [crates.io](https://crates.io/).
31 |
32 | *: Compile time memory and thread safety guarantees only apply to the Rust code. As the user is allowed to call into the Godot engine (C++ code, via GDNative Foreign Function Interface) or into user-defined scripts (GDScript), some of the validity checks are outside godot-rust's control. However, godot-rust guides the user by making clear which operations are potentially unsafe.
33 |
34 |
35 | ## Terminology
36 |
37 | To avoid confusion, here is an explanation of names and technologies used within the book.
38 |
39 | * [**GDNative**]: C API provided by Godot 3.
40 | * [**GDExtension**]: C API provided by Godot 4.
41 | * **godot-rust**: The entire project, encompassing Rust bindings for Godot 3 and 4, as well as related efforts (book, community, etc.).
42 | * **gdnative** (lowercase): the Rust binding for GDNative (Godot 3).
43 | * **gdext** (lowercase): the Rust binding for GDExtension (Godot 4).
44 | * **Extension**: An extension is a C library developed using gdext. It can be loaded by Godot 4.
45 |
46 |
47 | ## Showcase
48 |
49 | If you would like to know about games and other projects in which godot-rust has been employed, check out the [Projects](projects) chapter. At the moment, this is mostly referring to projects built with the Godot 3 bindings, due to their maturity.
50 |
51 |
52 | ## Contributing
53 |
54 | The source repository for this book is [hosted on GitHub](https://github.com/godot-rust/book).
55 |
56 |
57 | ## License
58 |
59 | The GDNative bindings and this user guide are licensed under the MIT license.
60 | The GDExtension bindings are licensed under the [Mozilla Public License 2.0](https://www.mozilla.org/en-US/MPL).
61 |
62 |
63 | [**GDNative**]: https://docs.godotengine.org/en/3.5/tutorials/scripting/gdnative/what_is_gdnative.html
64 | [**GDExtension**]: https://docs.godotengine.org/en/stable/tutorials/scripting/gdextension/what_is_gdextension.html
65 |
--------------------------------------------------------------------------------
/src/intro/hello-world.md:
--------------------------------------------------------------------------------
1 | # Hello, world!
2 |
3 | Follow this tutorial to learn how to create an empty project that simply prints "Hello, world!" to the Godot console on ready. The code might not compile or work as intended while it's in-progress, but at the end of this section, the code will be compiling and working fine.
4 |
5 | The full, finished code is available in the main repo: [https://github.com/godot-rust/godot-rust/tree/master/examples/hello-world](https://github.com/godot-rust/godot-rust/tree/master/examples/hello-world).
6 |
7 |
8 | ## Creating the project
9 |
10 | First, create an empty project using the Godot GUI. Then, create an empty crate *beside* the project folder using `cargo`:
11 |
12 | ```sh
13 | cargo init --lib my-gdnative-lib
14 | ```
15 |
16 | Your file structure should look like this:
17 |
18 | ```
19 | .
20 | ├─── my-gdnative-lib
21 | │ ├─── src
22 | │ │ ├ lib.rs
23 | │ ├ Cargo.toml
24 | ├─── my-godot-project
25 | │ ├─── .import
26 | │ ├ icon.png
27 | │ ├ icon.png.import
28 | │ └ project.godot
29 | ```
30 |
31 | Once the project is created, open `Cargo.toml`, change the crate type to `cdylib`, and add `gdnative` as a dependency:
32 |
33 |
34 | ```toml
35 | [lib]
36 | crate-type = ["cdylib"]
37 |
38 | [dependencies]
39 | gdnative = "0.10"
40 | ```
41 |
42 | > ### Organization of Rust code
43 | >
44 | > While it's also possible to place the Rust crate within the Godot project, doing so might lead to problems with Godot's resource importer. It's best to place the Rust crate somewhere outside the Godot project directory.
45 | >
46 | > Previously, some third-party resources have recommended separating Rust code into multiple crates. While this is fine to do, godot-rust works best when there is a single `cdylib` crate acting as the entry point for all crates in the workspace. Script downcasting, for example, only works for types registered in the same GDNative library. Code from `std` and other dependencies can also lead to code bloat when duplicated in multiple binaries.
47 | >
48 | > We suggest that users start projects as a single crate, and only split code into workspaces when necessary.
49 |
50 |
51 | ## Boilerplate
52 |
53 | You should now be able to compile your crate into a dynamic library, but a little bit of boilerplate is required before Godot can actually be able to load it as a GDNative library. Replace the contents of `lib.rs` with the following code:
54 |
55 | ```rust
56 | use gdnative::prelude::*;
57 |
58 | // Function that registers all exposed classes to Godot
59 | fn init(handle: InitHandle) {
60 | }
61 |
62 | // Macro that creates the entry-points of the dynamic library.
63 | godot_init!(init);
64 | ```
65 |
66 | The code does several things:
67 |
68 | ```rust
69 | use gdnative::prelude::*;
70 | ```
71 |
72 | This imports a number of commonly used types and traits into the scope. Generally, you'll want this at the top of every file where you need to interact with GDNative.
73 |
74 | ```rust
75 | // Function that registers all exposed classes to Godot
76 | fn init(handle: InitHandle) {
77 | }
78 | ```
79 |
80 | This declares an empty callback function, which is called when the library is loaded by Godot. All script classes in the library should be "registered" here using `handle.add_class::()`. You only need *one* of this in the entire library.
81 |
82 | ```rust
83 | // Macro that creates the entry-points of the dynamic library.
84 | godot_init!(init);
85 | ```
86 |
87 | This macro defines the necessary C callbacks used by Godot. You only need *one* invocation of this macro in the entire library. Note how the `init` function defined earlier is given to the `godot_init!` macro as a callback.
88 |
89 | > ### GDNative internals
90 | >
91 | > The purposes of this macro will be discussed in detail in [_An Overview of GDNative_](../gdnative-overview.md). For now, treat it as a magic incantation.
92 |
93 |
94 | ## Your first script
95 |
96 | With the boilerplate put into place, you can now create your first Rust script! We will go step by step and discover what's needed to create script "classes". Intermediate code versions might not compile, but at the end of this section it should be working!
97 |
98 | A script is simply a Rust type that implements (derives) the `NativeClass` trait:
99 |
100 | ```rust
101 | /// The HelloWorld "class"
102 | #[derive(NativeClass)]
103 | #[inherit(Node)]
104 | pub struct HelloWorld;
105 |
106 | // Function that registers all exposed classes to Godot
107 | fn init(handle: InitHandle) {
108 | // Register the new `HelloWorld` type we just declared.
109 | handle.add_class::();
110 | }
111 | ```
112 |
113 | Similar to the GDScript `extends` directive, the `inherit` attribute tells godot-rust the most general base class your script can be attached to. Here, `Node` is the parent class of all nodes in the scene tree, so it would be possible to attach `HelloWorld` to any node or scene in Godot.
114 |
115 | Unfortunately, this won't compile just yet: Rust will complain about the lack of a `new` method and a `NativeClassMethods` trait. This is because all scripts must also have a zero-argument constructor and a set of exported methods. To fix this, simply add two `impl` blocks:
116 |
117 | ```rust
118 | // You may add any number of ordinary `impl` blocks as you want. However, ...
119 | impl HelloWorld {
120 | /// The "constructor" of the class.
121 | fn new(_base: &Node) -> Self {
122 | HelloWorld
123 | }
124 | }
125 |
126 | // Only __one__ `impl` block can have the `#[methods]` attribute, which
127 | // will generate code to automatically bind any exported methods to Godot.
128 | #[methods]
129 | impl HelloWorld {
130 | }
131 | ```
132 |
133 | The `HelloWorld` type is like any regular Rust type, and can have any number of ordinary `impl` blocks. However, it must have **one and only one** `impl` block with the `#[methods]` attribute, which tells godot-rust to generate code that automatically binds any exported methods to Godot.
134 |
135 |
136 | ## Creating the NativeScript resource
137 |
138 | You should now be able to build the dynamic library with a `HelloWorld` script class in it. However, we also need to tell Godot about it. To do this, build the library with `cargo build`.
139 |
140 | After building the library with `cargo build`, the resulting library should be in the `target/debug/` folder. Copy it (or create a symbolic link to it) somewhere inside the Godot project directory.
141 |
142 | To tell Godot about the `HelloWorld` class, a `GDNativeLibrary` resource has to be created. This can be done in the "Inspector" panel in the Godot editor by clicking the "new resource" button in the top left.
143 |
144 | 
145 | 
146 |
147 | With the `GDNativeLibrary` resource created, the path to the generated binary can be set in the editor.
148 |
149 | 
150 |
151 | After specifying the path, save the `GDNativeLibrary` resource. Be sure to change the file type to `GDNLIB`.
152 |
153 | 
154 |
155 | Now, the `HelloWorld` class can be added to any node by clicking the "attach script" button.
156 |
157 | 
158 |
159 | In the popup, select "NativeScript" as the language, and set the class name to `HelloWorld`.
160 |
161 | 
162 |
163 | Then, select the `NativeScript` resource in the Inspector, click the `library` field and point to the `GDNativeLibrary` resource that you created earlier.
164 |
165 | 
166 |
167 |
168 | ## Overriding a Godot method
169 |
170 | You can now run your project from the editor! If all goes correctly, it should launch but do nothing. That's because we haven't added any actual behaviors yet! To make our script actually do something, we can override the [`_ready`](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-ready) method in the `impl` block with the `#[methods]` attribute:
171 |
172 | ```rust
173 | // Only __one__ `impl` block can have the `#[methods]` attribute, which
174 | // will generate code to automatically bind any exported methods to Godot.
175 | #[methods]
176 | impl HelloWorld {
177 |
178 | // To make a method known to Godot, use the #[method] attribute.
179 | // In Godot, script "classes" do not actually inherit the parent class.
180 | // Instead, they are "attached" to the parent object, called the "base".
181 | //
182 | // If access to the base instance is desired, the 2nd parameter can be
183 | // annotated with #[base]. It must have type `&T` or `TRef`, where `T`
184 | // is the base type specified in #[inherit]. If you don't need this parameter,
185 | // feel free to omit it entirely.
186 | #[method]
187 | fn _ready(&self, #[base] base: &Node) {
188 | // The `godot_print!` macro works like `println!` but prints to the Godot-editor
189 | // output tab as well.
190 | godot_print!("Hello world from node {}!", base.to_string());
191 | }
192 | }
193 | ```
194 |
195 | Here, the `#[method]` attribute is used to tell godot-rust to expose your methods to Godot. In this case, we are overriding [`_ready`](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-ready) and printing a line of text.
196 |
197 | Now, re-compile the crate using `cargo build` and copy the resulting binary to the Godot project. Launch the project from the editor, and you should see `Hello, world!` in the Godot console!
198 |
199 |
200 | ## Wrapping it up
201 |
202 | Congratulations! You have just created your first Rust GDNative library. You have learned how to expose scripts and methods to Godot using the bindings, and how to use them in Godot. A lot of the details are still unexplained, but you're off to a good start!
203 |
204 | You can find the full code for this example in the main repo: [https://github.com/godot-rust/godot-rust/tree/master/examples/hello-world](https://github.com/godot-rust/godot-rust/tree/master/examples/hello-world).
205 |
206 |
207 | ## Work-in-progress
208 |
209 | **The Getting Started tutorial is a work-in-progress, and unfortunately it ends here for now!** To learn more about the API, you'll have to dive into the [documentation on docs.rs](https://docs.rs/gdnative/latest), and the [other examples in the main repo]( https://github.com/godot-rust/godot-rust/tree/master/examples/). If you have any questions using the bindings, ask away in the `#gdnative_dev` channel on the [Godot Engine community Discord server](https://godotengine.org/community)!
210 |
--------------------------------------------------------------------------------
/src/intro/img/attach_resource.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/intro/img/attach_resource.png
--------------------------------------------------------------------------------
/src/intro/img/attach_script.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/intro/img/attach_script.png
--------------------------------------------------------------------------------
/src/intro/img/create_resource.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/intro/img/create_resource.png
--------------------------------------------------------------------------------
/src/intro/img/create_resource_type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/intro/img/create_resource_type.png
--------------------------------------------------------------------------------
/src/intro/img/create_script.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/intro/img/create_script.png
--------------------------------------------------------------------------------
/src/intro/img/resource_path.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/intro/img/resource_path.png
--------------------------------------------------------------------------------
/src/intro/img/resource_save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/intro/img/resource_save.png
--------------------------------------------------------------------------------
/src/intro/index.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | The getting started tutorial will introduce you to basic godot-rust concepts. At the end of the tutorial, you'll have a working copy of the [dodge-the-creeps example](https://github.com/godot-rust/godot-rust/tree/master/examples/dodge-the-creeps) from the main repo.
4 |
5 | This tutorial assumes some experience with Godot's GUI and GDScript. It assumes a basic understanding of Rust itself.
6 |
7 | ## Work-in-progress
8 |
9 | **The Getting Started tutorial is a work-in-progress, and currently it only covers up to the hello-world example!** To learn more about the API after the tutorial, you'll have to dive into the [documentation on docs.rs](https://docs.rs/gdnative/latest), and the [other examples in the main repo](https://github.com/godot-rust/godot-rust/tree/master/examples/). If you have any questions using the bindings, ask away in the `#gdnative_dev` channel on the [Godot Engine community Discord server](https://godotengine.org/community)!
10 |
--------------------------------------------------------------------------------
/src/intro/setup.md:
--------------------------------------------------------------------------------
1 | # Setup
2 |
3 | Before we can start creating a hello-world project using godot-rust, we'll need to install the necessary software.
4 |
5 | ## Godot Engine
6 |
7 | The default API version is currently 3.2.3-stable. For the rest of the tutorial, we'll assume that you have Godot 3.2.3-stable installed, and available in your `PATH` as `godot`.
8 |
9 | You may download binaries of Godot 3.2.3-stable from the official repository: [https://downloads.tuxfamily.org/godotengine/3.2.3/](https://downloads.tuxfamily.org/godotengine/3.2.3/).
10 |
11 | > ### Using another build of the engine
12 | >
13 | > For simplicity, we assume that you use the official build of 3.2.3-stable for the Getting Started tutorial. If you want to use another version of the engine, see the [Using custom builds of Godot](../advanced/custom-godot.md) guide.
14 |
15 | ## Rust
16 |
17 | [rustup](https://rustup.rs/) is the recommended way to install the Rust toolchain, including the compiler, standard library, and Cargo, the package manager. Visit [https://rustup.rs/](https://rustup.rs/) to see instructions for your platform.
18 |
19 | After installation of rustup and the `stable` toolchain, check that they were installed properly:
20 |
21 | ```bash
22 | # Check Rust toolchain installer version
23 | rustup -V
24 | # Check Rust version
25 | rustc --version
26 | # Check Cargo version
27 | cargo -V
28 | ```
29 |
30 | ## Windows
31 |
32 | When working on Windows, it's also necessary to install the [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/), or the full Visual Studio (*not* Visual Studio Code). More details can be found on [Working with Rust on Windows](https://github.com/rust-lang/rustup#working-with-rust-on-windows). Note that LLVM is also required on top of those dependencies to build your godot-rust project, see the next section for more information.
33 |
34 | ## LLVM
35 |
36 | The godot-rust bindings depend on `bindgen`, which in turn [depends on LLVM](https://rust-lang.github.io/rust-bindgen/requirements.html). You may download LLVM binaries from [https://releases.llvm.org/](https://releases.llvm.org/).
37 |
38 | After installation, check that LLVM was installed properly:
39 |
40 | ```bash
41 | # Check if Clang is installed and registered in PATH
42 | clang -v
43 | ```
44 |
45 | `bindgen` may complain about a missing `llvm-config` binary, but it is not actually required to build the `gdnative` crate. If you see a warning about `llvm-config` and a failed build, it's likely that you're having a different problem!
46 |
47 |
48 | ## Using the template
49 |
50 | One way to get started with godot-rust is a full-fledged (inofficial) template, which can be found [here](https://github.com/macalimlim/godot-rust-template) to get you started right away. All the boilerplate stuff is already done for you, however, using the template requires you to set up extra dependencies and toolchains. Check out the [wiki](https://github.com/macalimlim/godot-rust-template/wiki) for instructions on how to get started with the template.
51 |
52 | The template is not maintained by us, and might not work in all setups where the base library would be compatible. If you encounter any issues with the template, please report them at its [issue tracker](https://github.com/macalimlim/godot-rust-template/issues/).
53 |
--------------------------------------------------------------------------------
/src/overview/architecture.md:
--------------------------------------------------------------------------------
1 | # Game architecture
2 |
3 | _This chapter assumes that you are developing a game with Godot and Rust; however, many of the points apply to other projects like simulations or visualizations._
4 |
5 | For users new to the godot-rust binding, there are a few questions that almost always come up:
6 | * How do I organize my Rust code the best way?
7 | * Should I still use GDScript or do everything in Rust?
8 | * Where should I write my game logic?
9 | * How can I use the Godot scene tree, if Rust has no inheritance?
10 |
11 | Regarding architecture, godot-rust offers a lot of freedom and does not force you into certain patterns. How much you want to develop in GDScript and how much in Rust, is entirely up to you. The choice may depend on your experience, the amount of existing code you already have in either language, the scope of your game or simply personal preference.
12 |
13 | Each language has their own strengths and weaknesses:
14 |
15 | * **GDScript** is close to the engine, allows for very fast prototyping and integrates well with the editor. However, its type system is limited and refactoring is often manual. There is no dependency management.
16 | * **Rust** focuses on type safety, performance and scalability, with mature tooling and ecosystem. The language is rather complex and enforces discipline, and Godot-related tasks tend to be more verbose.
17 |
18 | As a starting point, this chapter highlights three common patterns that have been successfully used with godot-rust. This does not mean you must adhere to any of them; depending upon your needs, hybrid solutions or entirely different designs are also worth considering. The three patterns are listed in ascending order with respect to complexity and scalability.
19 |
20 |
21 | ## 1. Godot game + Rust module
22 |
23 | In this architecture, you develop your game primarily in the Godot engine. Most of the game logic resides in GDScript, and the Godot editor is your tool of choice.
24 |
25 | During development, you encounter a feature which you wish to develop in Rust while making it accessible to GDScript. Reasons may include:
26 | * The code is performance-critical and GDScript is not fast enough.
27 | * There is a Rust-based library that you wish to use, for example pathfinding, AI, or physics.
28 | * You have a segment of your code with high complexity that is difficult to manage in GDScript.
29 |
30 | In this case, you can write a GDNative class in Rust, with an API that exposes precisely the functionality you need -- no more and no less. godot-rust is only needed at the interface with GDScript. There are no calls into Godot from your Rust code, only exported methods.
31 |
32 |
33 | 
34 |
35 | Pros:
36 | * Very easy to get started, especially for existing Godot codebases.
37 | * You can fully benefit from Godot's scene graph and the tooling around it.
38 | * You can test the Rust functionality independently, without running Godot.
39 |
40 | Cons:
41 | * As most of the game logic is in GDScript, your project will not benefit from Rust's features, type safety and refactoring capabilities.
42 | * Your game logic needs to fit Godot's scene graph model and you have little control about architecture.
43 |
44 |
45 | ## 2. Godot scene tree + native scripts
46 |
47 | The Godot engine encourages a certain pattern: each game entity is represented by a scene node, and the logic for each node is implemented in a GDScript file. You can follow the same architecture with godot-rust, the only difference being that scripts are implemented in Rust.
48 |
49 | Instead of `.gd` script files, you use `.rs` files to implement native scripts, and you register native classes in `.gdns` files. Each Rust script can call into Godot to interact with other nodes, set up or invoke signals, query engine state, etc. Godot types have an equivalent representation in Rust, and the `Object` hierarchy is emulated in Rust via [`Deref`](https://docs.rs/gdnative/latest/gdnative/api/struct.Node.html#impl-Deref) trait -- this means that e.g. `Node2D` references can be used to invoke methods on their parent class `Node`.
50 |
51 | It often makes sense to be pragmatic and not try to do everything in Rust. For example, tweaking parameters for particle emitters or animation works much better in GDScript and/or the Godot editor.
52 |
53 | 
54 |
55 | Pros:
56 | * You can make full use of Godot's scene graph architecture while still writing the logic in Rust.
57 | * Existing code and concepts from GDScript can be carried over quite easily.
58 |
59 | Cons:
60 | * You have little architectural freedom and are constrained by Godot's scene tree model.
61 | * As godot-rust is used throughout your entire codebase, this will tightly couple your game logic to Godot. Testing and isolating functionality can be harder and you are more subject to version changes of Godot and godot-rust.
62 |
63 |
64 | ## 3. Rust game + Godot I/O layer
65 |
66 | This architecture is the counterpart to section 1. Most of your game is written in Rust, and you use the engine primarily for input/output handling. You can have an entry point to your Rust library (the _Controller_) which coordinates the simulation.
67 |
68 | A typical workflow is as follows:
69 | 1. **Input:** You use the Godot engine to collect user input and events (key pressed, network packet arrived, timer elapsed, ...).
70 | 2. **Processing:** The collected input is passed to Rust. The Controller runs a step in your game simulation and produces results.
71 | 3. **Output:** These results are passed back to Godot and take effect in the scene (node positions, animations, sound effects, ...).
72 |
73 | If you follow this pattern strictly, the Godot scene graph can be entirely derived from your Rust state, as such it is only a visualization. There will be some GDScript glue code to tweak graphics/audio output.
74 |
75 | This can be the most scalable and "Rusty" workflow, but it also requires a lot of discipline. Several interactions, which the other workflows offer for free, need to be implemented manually.
76 |
77 |
78 | 
79 |
80 | Pros:
81 | * You are completely free how you organize your Rust game logic. You can have your own entity hierarchy, use an ECS, or simply a few linear collections.
82 | * As your game logic runs purely in Rust, you don't need Godot to run the simulation. This allows for the following:
83 | * Rust-only headless server
84 | * Rust-only unit and integration tests
85 | * Different/simplified visualization backends
86 |
87 | Cons:
88 | * A robust design for your Rust architecture is a must, with considerable up-front work.
89 | * You need to manually synchronize your Rust entities with the Godot scene tree. In many cases, this means duplication of state in Rust (e.g. tile coordinate + health) and in Godot (world position + healthbar), as well as mapping between the two.
90 |
--------------------------------------------------------------------------------
/src/overview/data-representations.md:
--------------------------------------------------------------------------------
1 | # Data representations
2 |
3 | The godot-rust library uses many different approaches to store and transport data. This chapter explains high-level concepts of related terminology used throughout the library and its documentation. It is not a usage guide however -- to see the concepts in action, check out [Binding to Rust code](../rust-binding.md).
4 |
5 |
6 | ## Object and class
7 |
8 | Godot is built around _classes_, object-oriented types in a hierarchy, with the base class `Object` at the top. When talking about classes, we explicitly mean classes in the `Object` hierarchy and not built-in types like `String`, `Vector2`, `Color`, even though they are technically classes in C++. In Rust, classes are represented as structs.
9 |
10 | Every user-defined class inherits `Object` directly or indirectly, and thus all methods defined in `Object` are accessible on _any_ instance of a user-defined class. This type includes functionality for:
11 | * object lifetime: `_init` (`new` in Rust), `free`
12 | * identification and printing: `to_string`, `get_instance_id`
13 | * reflection/introspection: `get_class`, `get`, `has_method`, ...
14 | * custom function invocation: `call`, `callv`, `call_deferred`
15 | * signal handling: `connect`, `emit_signal`, ...
16 |
17 | `Object` itself comes with manual memory management. All instances must be deallocated using the `free()` method. This is typically not what you want, instead you will most often work with the following classes inherited from `Object`:
18 |
19 | * **`Reference`**
20 | Reference-counted objects. This is the default base class if you don't use the `extends` keyword in GDScript. Allows to pass around instances of this type freely, managing memory automatically when the last reference goes out of scope.
21 | Do not confuse this type with the godot-rust `Ref` smart pointer.
22 | * **`Node`**
23 | Anything that's part of the scene tree, such as `Spatial` (3D), `CanvasItem` and `Node2D` (2D). Each node in the tree is responsible of its children and will deallocate them automatically when it is removed from the tree. At the latest, the entire tree will be destroyed when ending the application.
24 | **Important:** as long as a node is not attached to the scene tree, it behaves like an `Object` instance and must be freed manually. On the other hand, as long as it is part of the tree, it can be destroyed (e.g. when its parent is removed) and other references pointing to it become invalid.
25 | * **`Resource`**
26 | Data set that is loaded from disk and cached in memory, for example 3D meshes, materials, textures, fonts or music (see also [Godot tutorial](https://docs.godotengine.org/en/stable/getting_started/step_by_step/resources.html)).
27 | `Resource` inherits `Reference`, so in the context of godot-rust, it can be treated like a normal, reference-counted class.
28 |
29 | When talking about inheritance, we always mean the relationship in GDScript code. Rust does not have inheritance, instead godot-rust implements `Deref` traits to allow implicit upcasts. This enables to invoke all parent methods and makes the godot-rust API very close to GDScript.
30 |
31 | Classes need to be added as `NativeScript` resources inside the Godot editor, see [here](../intro/hello-world.html#creating-the-nativescript-resource) for a description.
32 |
33 | _See `Object` in
34 | [godot-rust docs](https://docs.rs/gdnative/latest/gdnative/api/struct.Object.html),
35 | [Godot docs](https://docs.godotengine.org/en/latest/classes/class_object.html)_
36 | _See `GodotObject`, the Rust trait implemented for all Godot classes, in [godot-rust docs](https://docs.rs/gdnative/latest/gdnative/trait.GodotObject.html)_
37 |
38 |
39 | ## Variant
40 |
41 | `Variant` is a type that can hold an instance of _any_ type in Godot. This includes all classes (of type `Object`) as well as all built-in types such as `int`, `String`, `Vector2` etc.
42 |
43 | Since GDScript is a dynamic language, you often deal with variants implicitly. Variables which are not type-annotated can have values of multiple types throughout their lifetime. In static languages like Rust, every value must have a defined type, thus untyped values in GDScript correspond to `Variant` in Rust. Godot APIs which accept any type as parameter are declared as `Variant` in the GDNative bindings (and thus godot-rust library). Sometimes, godot-rust also provides transparent mapping from/to concrete types behind the scenes.
44 |
45 | Variants also have a second role as a serialization format between Godot and Rust. It is possible to extend this beyond the built-in Godot types. To make your own types convertible from and to variants, implement the traits [`FromVariant`](https://docs.rs/gdnative/latest/gdnative/core_types/trait.FromVariant.html) and [`ToVariant`](https://docs.rs/gdnative/latest/gdnative/core_types/trait.ToVariant.html). Types that can only be safely converted to variants by giving up ownership can use [OwnedToVariant](https://docs.rs/gdnative/latest/gdnative/core_types/trait.OwnedToVariant.html), which is similar to the Rust `Into` trait.
46 |
47 | _See `Variant` in
48 | [godot-rust docs](https://docs.rs/gdnative/latest/gdnative/core_types/struct.Variant.html),
49 | [Godot docs](https://docs.godotengine.org/en/latest/classes/class_variant.html)_
50 |
51 |
52 | ## Script
53 |
54 | Scripts are programmable building blocks that can be attached to nodes in the scene tree, in order to customize their behavior. Depending on the language in which the script is written, there are different classes which inherit the `Script` class; relevant here will be `NativeScript` for classes defined in Rust, and `GDScript` for classes defined in GDScript. Scripts are stored as Godot resources (like materials, textures, shaders etc), usually in their own separate file.
55 |
56 | Scripts _always_ inherit another class from Godot's `Object` hierarchy, either an existing one from Godot or a user-defined one. In Rust, scripts are limited to inherit an existing Godot class; other scripts cannot be inherited. This makes each script a class on their own: they provide the properties and methods from their _base object_, plus all the properties and methods that you define in the script.
57 |
58 | _See `Script` in
59 | [godot-rust docs](https://docs.rs/gdnative/latest/gdnative/api/struct.Script.html),
60 | [Godot docs](https://docs.godotengine.org/en/latest/classes/class_script.html)_
61 |
--------------------------------------------------------------------------------
/src/overview/img/in-tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/overview/img/in-tree.png
--------------------------------------------------------------------------------
/src/overview/img/rust-game.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/overview/img/rust-game.png
--------------------------------------------------------------------------------
/src/overview/img/rust-module.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/overview/img/rust-module.png
--------------------------------------------------------------------------------
/src/overview/index.md:
--------------------------------------------------------------------------------
1 | # An Overview of GDNative
2 |
3 | GDNative is the interface between the Godot engine version 3 and bindings in native languages, such as C, C++ or Rust.
4 |
5 | This chapter gives a broad overview of basic GDNative concepts and godot-rust's approach to implement them in Rust. It is not a usage guide for exposing your Rust code to Godot; see chapter [Binding to Rust code](rust-binding.md) for concrete examples.
6 |
7 | Subchapters:
8 |
9 | 1. [Data representations](data-representations.md)
10 | 1. [`Ref`, `TRef` and `Instance`](wrappers.md)
11 | 1. [Game architecture](architecture.md)
12 |
--------------------------------------------------------------------------------
/src/overview/wrappers.md:
--------------------------------------------------------------------------------
1 | # `Ref`, `TRef` and `Instance`
2 |
3 | Objects from Godot, such as scene nodes, materials, or other resources are owned and maintained by the Godot engine. This means that your Rust code will store references to existing objects, not values. godot-rust provides special wrapper types to deal with these references, which are explained in this page.
4 |
5 | These classes stand in contrast to value types like `bool`, `int`, `Vector2`, `Color` etc., which are copied in GDScript, not referenced. In Rust, those types either map to built-in Rust types or structs implementing the `Copy` trait.
6 |
7 | ## `Ref`: persistent reference
8 |
9 | The generic smart pointer `gdnative::Ref` allows you to store `Object` instances in Rust. It comes with different access policies, depending on how the memory of the underlying object is managed (consult [the docs](https://docs.rs/gdnative/latest/gdnative/object/struct.Ref.html) for details). Most of the time, you will be working with `Ref`, which is the same as `Ref` and the only access policy that is explained here. Its memory management mirrors that of the underlying type:
10 | * for all Godot objects inheriting the `Reference` class, `Ref` is reference-counted like `Arc` and will clean up automatically.
11 | * for all other types (i.e. the type `Object` and inheritors of `Node`), `Ref` behaves like a raw pointer with manual memory management.
12 |
13 | For example, storing a reference to a Godot `Node2D` instance in a struct would look as follows:
14 | ```rust
15 | struct GodotNode {
16 | node_ref: Ref,
17 | }
18 | ```
19 |
20 | _See `Ref` in
21 | [godot-rust docs](https://docs.rs/gdnative/latest/gdnative/object/struct.Ref.html)_
22 |
23 |
24 | ## `TRef`: temporary reference
25 |
26 | While `Ref` is a persistent pointer to retain references to Godot objects for an extended period of time, it doesn't grant access to the underlying Godot object. The reason for this is that `Ref` cannot generally guarantee that the underlying object, which is managed by the Godot engine, is valid at the time of the access. However, you as a user are in control of GDScript code and the scene tree, thus you can assert that an object is valid at a certain point in time by using `assume_safe()`. This is an unsafe function that returns a `gdnative::TRef` object, which allows you to call methods on the node. You are responsible for this assumption to be correct; violating it can lead to undefined behavior.
27 |
28 | The following example demonstrates `TRef`. A node is stored inside a Rust struct, and its position is modified through `set_position()`. This approach could be used in an ECS (Entity-Component-System) architecture, where `GodotNode` is a component, updated by a system.
29 | ```rust
30 | struct GodotNode {
31 | node_ref: Ref,
32 | }
33 |
34 | fn update_position(node: &GodotNode) {
35 | let pos = Vector2::new(20, 30);
36 |
37 | // fetch temporary reference to the node
38 | let node: TRef = unsafe { node.node_ref.assume_safe() };
39 |
40 | // call into the Godot engine
41 | // this implicitly invokes deref(), turning TRef into &Node2D
42 | node.set_position(pos);
43 | }
44 | ```
45 | Note that the parameter type is `&GodotNode`, not `&mut GodotNode`. Then why is it possible to mutate the Godot object?
46 |
47 | All Godot classes in Rust (`Object` and its subtypes) have only methods that operate on `&self`, not `&mut self`. The reason for this choice is that `&mut` is -- strictly speaking -- not a mutable reference, but rather an [_exclusive_ reference](https://docs.rs/dtolnay/latest/dtolnay/macro._02__reference_types.html). The one and only thing it guarantees is that while it exists, no other reference to the same object can exist (no aliasing). Since all the Godot classes can be shared with the Godot engine, which is written in C++ and allows free aliasing, using `&mut` references would potentially violate the exclusivity, leading to UB. This is why `&T` is used, and just like e.g. `&RefCell` it _does_ allow mutation.
48 |
49 | This being said, it can still make sense to bring back some type safety on a higher level in your own code. For example, you could make the `update_position()` take a `&mut GodotNode` parameter, to make sure that access to this `GodotNode` object is exclusive.
50 |
51 |
52 | _See `TRef` in
53 | [godot-rust docs](https://docs.rs/gdnative/latest/gdnative/object/struct.TRef.html)_
54 |
55 |
56 | ## `Instance`: reference with attached Rust class
57 |
58 | When working with classes that are provided by the engine or defined in GDScript, the `Ref` smart pointer is the ideal type for interfacing between Rust and Godot. However, when defining a custom class in Rust, that is registered with the Godot engine, there are two parts that need to be stored together:
59 |
60 | 1. **GDNative script:** the Rust struct object that implements the entire custom logic. The Rust struct is written by you.
61 | 1. **Base object:** the base class from which the script inherits, with its own state. This is always a Godot built-in class such as `Object`, `Reference` or `Node`.
62 |
63 | The `Instance` class simply wraps the two parts into a single type.
64 |
65 | When passing around your own Rust types, you will thus be working with `Instance`. The traits `ToVariant`, `FromVariant` and `OwnedToVariant` are automatically implemented for `Instance` types, allowing you to pass them from and to the Godot engine.
66 |
67 |
68 | ### Construction
69 |
70 | Let's use a straightforward example: a player with name and score. Exported methods and properties are omitted for simplicity; the full interfacing will be explained later in [Calling into GDScript from Rust](../bind/calling-gdscript.md).
71 | ```rust
72 | #[derive(NativeClass)]
73 | // no #[inherit], thus inherits Reference by default
74 | pub struct Player {
75 | name: String,
76 | score: u32,
77 | }
78 |
79 | #[methods]
80 | impl Player {
81 | fn new(_base: &Reference) -> Self {
82 | Self {
83 | name: "New player".to_string(),
84 | score: 0
85 | }
86 | }
87 | }
88 | ```
89 |
90 | To create a default instance, use `Instance::new_instance()`.
91 | You can later use `map()` and `map_mut()` to access the `Instance` immutably and mutably.
92 |
93 | ```rust
94 | let instance: Instance = Instance::new();
95 | // or:
96 | let instance = Player::new_instance();
97 |
98 | // note: map_mut() takes &self, so above is not 'let mut'
99 | instance.map_mut(|p: &mut Player, _base: TRef| {
100 | p.name = "Joe".to_string();
101 | p.score = 120;
102 | });
103 | ```
104 |
105 | If you don't need a Godot-enabled default constructor, use the `#[no_constructor]` attribute and define your own Rust `new()` constructor.
106 | ```rust
107 | #[derive(NativeClass)]
108 | #[no_constructor]
109 | pub struct Player {
110 | name: String,
111 | score: u32,
112 | }
113 |
114 | #[methods]
115 | impl Player {
116 | pub fn new(name: &str, score: u32) -> Self {
117 | Self { name: name.to_string(), score }
118 | }
119 | }
120 | ```
121 |
122 | In this case, you can construct an `Instance` from an existing Rust object using `Instance::emplace()`:
123 | ```rust
124 | let player = Player::new("Joe", 120);
125 |
126 | let instance = Instance::emplace(player);
127 | // or:
128 | let instance = player.emplace();
129 | ```
130 |
131 |
132 |
133 |
134 | _See `Instance` in
135 | [godot-rust docs](https://docs.rs/gdnative/latest/gdnative/object/struct.Instance.html)_
136 |
137 |
--------------------------------------------------------------------------------
/src/projects/applications.md:
--------------------------------------------------------------------------------
1 | # Projects: Applications
2 |
3 | This page lists non-game applications developed with godot-rust. Libraries should be listed in [Tools](tools.md).
4 | Examples here include:
5 |
6 | * Tech demos
7 | * User interfaces
8 | * Data visualization
9 |
10 | ## (TODO: add project)
--------------------------------------------------------------------------------
/src/projects/games.md:
--------------------------------------------------------------------------------
1 | # Projects: Games
2 |
3 | Below you see a non-exhaustive list of games that have been developed with godot-rust.
4 |
5 | The page focuses on entries which are either in a playable state, or at least have some basic mechanics and graphics to show. For example, such an entry could be an indie game developed over many months, or also a polished game jam submission. The condition is that a notable part of the game is written in godot-rust, however it doesn't need to be the majority. For example, [one of the common architectures](../overview/architecture.md) entails using Rust for selective modules.
6 |
7 | ### Table of contents
8 |
9 |
10 | ## The Recall Singularity
11 |
12 | _by **Jump to Warp** (Tom Leys)_
13 | 🕊️ _[@RecallSingular1](https://twitter.com/RecallSingular1)_
14 |
15 | 
16 |
17 | The Recall Singularity is a factory game, set within a player-controlled fleet of space-ships.
18 | Players blast asteroids, collect rocks, grind them up and turn them into ship parts.
19 |
20 |
21 | ## The Process
22 |
23 | _by **setzer22**_
24 | 🕊️ _[@PlayTheProcess](https://twitter.com/PlayTheProcess)_
25 |
26 | 
27 |
28 | The Process is an upcoming game about factory building, process management, and carrot production, built with godot-rust!
29 |
30 | The game offers a similar experience to other titles in the factory building genre (Factorio, Satisfactory), but is more tailored towards a chill, lighthearted atmosphere.
31 |
32 |
33 | ## BITGUN
34 |
35 | _by **LogLogGames**_
36 | 🕹️ _[**Steam**](https://store.steampowered.com/app/1673940/BITGUN)_ | 🕊️ _[@LogLogGames](https://twitter.com/LogLogGames)_ | 🌐 _[Website](https://loglog.games)_
37 |
38 | 
39 |
40 | BITGUN is an action roguelike zombie shooter with lots of blood and guns.
41 |
42 |
43 | ## BENDYWORM
44 |
45 | _by **Bauxitedev**_
46 | 🕹️ _[**itch.io**](https://bauxite.itch.io/bendyworm)_ | 🕊️ _[@bauxitedev](https://twitter.com/bauxitedev)_ | 📜 _[GitHub](https://github.com/Bauxitedev/bendyworm) (game is open-source)_
47 |
48 | 
49 |
50 | BENDYWORM is a platformer with a twist: the entire world bends and twists around you as you progress through the level. Why? Because you're inside of a gigantic worm, and worms are bendy. Navigate the worm's slippery innards, collect the Mega Cannon, and destroy its brain to escape!
51 |
52 |
53 | ## Cake Thieves
54 |
55 | _by **GeTech**_
56 | 🕹️ _[**Google Play**](https://play.google.com/store/apps/details?id=com.GeTech.CakeThieves)_ | 🕊️ _[@GeTech8](https://twitter.com/GeTech8)_
57 |
58 | 
59 |
60 | Thieves have found your picnic and want to eat your delicious cake! Protect it by placing cannons on the field to defeat the ants. Improve your cannons to increase their power! How well will you do in this challenge?
61 |
--------------------------------------------------------------------------------
/src/projects/img/bendyworm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/projects/img/bendyworm.png
--------------------------------------------------------------------------------
/src/projects/img/bitgun.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/projects/img/bitgun.jpg
--------------------------------------------------------------------------------
/src/projects/img/cake-thieves.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/projects/img/cake-thieves.jpg
--------------------------------------------------------------------------------
/src/projects/img/godot-egui.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/projects/img/godot-egui.gif
--------------------------------------------------------------------------------
/src/projects/img/the-process.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/projects/img/the-process.jpg
--------------------------------------------------------------------------------
/src/projects/img/the-recall-singularity.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/godot-rust/gdnative-book/5a589da2d4a962ce1b15e186d65a8f9f19fa2944/src/projects/img/the-recall-singularity.jpg
--------------------------------------------------------------------------------
/src/projects/index.md:
--------------------------------------------------------------------------------
1 | # Third-party projects
2 |
3 | This chapter intends to provide an overview over the godot-rust ecosystem and list projects that use godot-rust across different domains.
4 |
5 | godot-rust is a popular choice for game development, but this chapter is not limited to games. We also list other applications, as well as tooling and libraries that extend godot-rust and integrate it with other parts of the ecosystem.
6 |
7 | While part of the book, this chapter is _not_ an official list of "featured" entries; project authors themselves are responsible for the up-to-dateness and accuracy of their description.
8 |
9 | Unless otherwise noted, projects are powered with Godot 3 and the GDNative-Rust binding.
10 |
--------------------------------------------------------------------------------
/src/projects/tools.md:
--------------------------------------------------------------------------------
1 | # Projects: Tools and integrations
2 |
3 | This page lists projects, which are intended to be used as an extension to godot-rust.
4 | Examples include:
5 |
6 | * CLI or other tools enhancing the development workflow
7 | * Libraries that directly enhance the godot-rust experience
8 | * Libraries that connect godot-rust with other crates in the Rust ecosystem
9 |
10 | This page should only provide a high-level description of each project (a couple sentences), plus relevant links and optionally one screenshot. It should _not_ include tutorials or extended code examples, as they tend to become outdated very quickly. Instead, the project's repository or homepage is a much better place for advertising the concrete functionality the tool offers and providing introductory examples.
11 |
12 |
13 | ### Table of contents
14 |
15 |
16 | ## godot-egui
17 |
18 | _[GitHub](https://github.com/setzer22/godot-egui)_
19 |
20 | 
21 |
22 | **godot-egui** is an [egui](https://github.com/emilk/egui) backend for godot-rust.
23 |
24 | This crate enables using the immediate-mode UI library egui within Godot applications and games. Updating UI widgets and properties directly from Rust code becomes straightforward, without going through Godot nodes, signals and the intricacies of GDNative's ownership semantics.
25 |
26 |
27 | ## godot-rust-cli
28 |
29 | _[GitHub](https://github.com/robertcorponoi/godot-rust-cli)_
30 |
31 | **Godot Rust CLI** is a simple command-line interface to help you create and update Rust components for your Godot projects.
32 |
33 | Example:
34 | ```sh
35 | # create a Rust library `rust_modules` for the `platformer` Godot project
36 | godot-rust-cli new rust_modules platformer
37 |
38 | # create player.rs + player.gdns
39 | godot-rust-cli create Player
40 |
41 | # generate dynamic library to be called by Godot, automatically watch changes
42 | godot-rust-cli build --watch
43 | ```
44 |
45 | Note that there is also [godot-rust-cli-upgrader](https://github.com/robertcorponoi/godot-rust-cli-upgrader) to upgrade the CLI.
46 |
47 |
48 | ## bevy-godot
49 |
50 | _[GitHub](https://github.com/rand0m-cloud/bevy_godot)_
51 |
52 | **bevy-godot** is an in-development crate for using Bevy with the Godot Engine.
53 |
54 | ```rust
55 | use bevy_godot::prelude::*;
56 |
57 | fn init(_handle: &InitHandle) {}
58 | fn build_app(app: &mut App) {
59 | app.add_startup_system(spawn_cube).add_system(move_cube);
60 | }
61 |
62 | bevy_godot_init!(init, build_app);
63 |
64 | #[derive(Component)]
65 | pub struct Cube {
66 | starting_position: Vector2,
67 | }
68 |
69 | fn spawn_cube(mut commands: Commands) {
70 | let starting_position = Vector2::new(500.0, 300.0);
71 | commands
72 | .spawn()
73 | .insert(GodotScene::from_path("res://simple_scene.tscn"))
74 | .insert(Cube { starting_position })
75 | .insert(Transform2D::from(
76 | GodotTransform2D::from_scale_rotation_origin(Vector2::ONE, 0.0, starting_position),
77 | ));
78 | }
79 |
80 | fn move_cube(mut cube: Query<(&Cube, &mut Transform2D)>, time: Res