From 410c9c595313626ff5aee30534b4ade104275dda Mon Sep 17 00:00:00 2001 From: TrialDragon <31419708+TrialDragon@users.noreply.github.com> Date: Sun, 4 Feb 2024 12:51:37 -0800 Subject: [PATCH] Merge `new-book` into `main` (#893) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: Alice Cecile Co-authored-by: KDecay Co-authored-by: IceSentry Co-authored-by: Carter Anderson Co-authored-by: Asier Illarramendi Co-authored-by: Federico Rinaldi Co-authored-by: Rob Parrett Co-authored-by: Forest Anderson Co-authored-by: SuperSamus <40663462+SuperSamus@users.noreply.github.com> Co-authored-by: Roryl-c <5150427+Roryl-c@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: François Co-authored-by: raffimolero <49224759+raffimolero@users.noreply.github.com> Co-authored-by: Afonso Lage Co-authored-by: Nathan Stocks Co-authored-by: Bude Co-authored-by: TimJentzsch Co-authored-by: Mike Co-authored-by: Fracey <42671542+Fracey@users.noreply.github.com> Co-authored-by: Pand9 Co-authored-by: Hank Jordan Co-authored-by: Nicola Papale Co-authored-by: Berlian Gur Co-authored-by: Charles Co-authored-by: Andre Popovitch Co-authored-by: Denis Pekdemir Co-authored-by: Lee Reilly Co-authored-by: Zearin Co-authored-by: thejohnbackes Co-authored-by: thejohnbackes Co-authored-by: Valentin Geyer Co-authored-by: Trayshar Co-authored-by: Lemonzy Co-authored-by: Tomasz Galkowski Co-authored-by: Gary R Krause <39040273+garyray-k@users.noreply.github.com> Co-authored-by: Erick Melo Co-authored-by: Caio Co-authored-by: Caio César Oliveira <54439337+oCaioOliveira@users.noreply.github.com> Co-authored-by: Mike Co-authored-by: Ida "Iyes Co-authored-by: MikaT-code <121306011+MikaT-code@users.noreply.github.com> Co-authored-by: Vezquex Co-authored-by: Ciro Costa Co-authored-by: Victor Lima Co-authored-by: Ame <104745335+ameknite@users.noreply.github.com> Co-authored-by: James Liu Co-authored-by: ickk Co-authored-by: Robert Swain Co-authored-by: 张林伟 Co-authored-by: Paul Kupper Co-authored-by: Boxy Co-authored-by: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Co-authored-by: Aevyrie Co-authored-by: Marco Buono Co-authored-by: Aceeri Co-authored-by: Jay Pavlina Co-authored-by: Greg Sparrow Co-authored-by: Andreas Weibye <13300393+Weibye@users.noreply.github.com> Co-authored-by: Adrian Kappel Co-authored-by: Kellen Cataldo Co-authored-by: Gian Zellweger <97334144+gianzellweger@users.noreply.github.com> Co-authored-by: laund Co-authored-by: Lars-Kristian Co-authored-by: Gingeh <39150378+Gingeh@users.noreply.github.com> Co-authored-by: Kenneth Brooks Co-authored-by: Paul Hansen Co-authored-by: ira Co-authored-by: Martin Lysell Co-authored-by: Sélène Amanita <134181069+Selene-Amanita@users.noreply.github.com> Co-authored-by: Leonardo Gatti Co-authored-by: Zeke Gabrielse Co-authored-by: Matt Fellenz Co-authored-by: Brian Merchant Co-authored-by: Jerome Humbert Co-authored-by: Nicola Papale Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com> Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com> Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com> Co-authored-by: mwbryant <65699744+mwbryant@users.noreply.github.com> Co-authored-by: Dot32 <61964090+Dot32IsCool@users.noreply.github.com> Co-authored-by: IDEDARY <49441831+IDEDARY@users.noreply.github.com> Co-authored-by: Nuutti Kotivuori Co-authored-by: Elabajaba Co-authored-by: Carl Engström Co-authored-by: Opstic <46141527+opstic@users.noreply.github.com> Co-authored-by: SpecificProtagonist Co-authored-by: Garden Gim <50333551+gardengim@users.noreply.github.com> Co-authored-by: NiseVoid Co-authored-by: lelo <15314665+hate@users.noreply.github.com> Co-authored-by: Dorian Bucur <6576777+d-bucur@users.noreply.github.com> Co-authored-by: Simon Kindström Co-authored-by: Max Heyer Co-authored-by: wackbyte Co-authored-by: Alex <12872500+alexmadeathing@users.noreply.github.com> Co-authored-by: alexmadeathing Co-authored-by: KshitijAucharmal <39955649+kshitijaucharmal@users.noreply.github.com> Co-authored-by: Connor King Co-authored-by: Matthew Miller Co-authored-by: Michael Tidwell Co-authored-by: BrayMatter <77391373+Braymatter@users.noreply.github.com> Co-authored-by: Tim Siegel Co-authored-by: DevinLeamy Co-authored-by: Cameron <51241057+maniwani@users.noreply.github.com> Co-authored-by: Noah Co-authored-by: Trashtalk217 Co-authored-by: Joona Aalto Co-authored-by: Nolan Darilek Co-authored-by: Pascal Hertleif Co-authored-by: NotAFile Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: cart Co-authored-by: pyu <86333848+pyudev-x@users.noreply.github.com> Co-authored-by: homersimpsons Co-authored-by: Konstantin Kostiuk Co-authored-by: Mikkel Rasmussen Co-authored-by: TheBlckbird Co-authored-by: Romain 'Maz' BILLOIR Co-authored-by: TheBlckbird Co-authored-by: Nia <7388349+conways-glider@users.noreply.github.com> Co-authored-by: Davide Paci Co-authored-by: Maz --- .github/bors.toml | 21 +- .github/workflows/ci.yml | 22 + .gitignore | 4 +- CONTRIBUTING.md | 185 + README.md | 4 +- code-validation/Cargo.toml | 10 + code-validation/rustfmt.toml | 2 + code-validation/src/lib.rs | 214 + content/{faq/_index.md => faq.md} | 0 content/learn/advanced-examples/_index.md | 6 + .../learn/advanced-examples/sudoku/_index.md | 5 + .../text-adventure/_index.md | 5 + content/learn/book/_index.md | 7 +- content/learn/book/assets/_index.md | 16 + .../learn/book/assets/custom-assets/_index.md | 15 + .../learn/book/assets/hot-reloading/_index.md | 16 + .../book/assets/loading-assets/_index.md | 17 + .../book/assets/scenes-reflection/_index.md | 19 + .../assets/working-with-handles/_index.md | 18 + content/learn/book/audio/_index.md | 16 + .../learn/book/audio/audio-basics/_index.md | 16 + .../book/development-practices/_index.md | 15 + .../boilerplate-reduction/_index.md | 16 + .../error-handling/_index.md | 17 + .../fast-compiles/_index.md | 57 + .../organizing-your-code/_index.md | 17 + .../development-practices/testing/_index.md | 18 + content/learn/book/ecs/_index.md | 85 + .../learn/book/ecs/change-detection/_index.md | 7 + content/learn/book/ecs/commands/_index.md | 9 + .../book/ecs/entities-components/_index.md | 376 ++ .../book/ecs/exclusive-world-access/_index.md | 17 + .../book/ecs/filtering-queries/_index.md | 7 + .../learn/book/ecs/generic-systems/_index.md | 7 + content/learn/book/ecs/resources/_index.md | 18 + .../learn/book/ecs/systems-queries/_index.md | 9 + content/learn/book/game-logic/_index.md | 15 + .../book/game-logic/async-tasks/_index.md | 18 + .../_index.md | 18 + .../learn/book/game-logic/events/_index.md | 18 + .../book/game-logic/run-criteria/_index.md | 18 + .../learn/book/game-logic/states/_index.md | 18 + .../book/game-logic/system-ordering/_index.md | 19 + .../book/game-logic/time-timers/_index.md | 20 + content/learn/book/getting-started/_index.md | 61 +- .../app-appbuilder-world/_index.md | 7 + .../learn/book/getting-started/apps/_index.md | 26 - .../getting-started/bevy-community/_index.md | 7 + .../getting-started/installation/_index.md | 7 + .../getting-started/modular-plugins/_index.md | 7 + .../book/getting-started/plugins/_index.md | 81 - .../book/getting-started/resources/_index.md | 66 - .../book/getting-started/why-bevy/_index.md | 7 + content/learn/book/graphics/2d/_index.md | 16 + .../book/graphics/2d/sprite-sheets/_index.md | 15 + .../learn/book/graphics/2d/sprites/_index.md | 15 + content/learn/book/graphics/3d/_index.md | 15 + .../learn/book/graphics/3d/meshes/_index.md | 16 + content/learn/book/graphics/3d/pbr/_index.md | 16 + content/learn/book/graphics/_index.md | 16 + content/learn/book/graphics/cameras/_index.md | 17 + .../graphics/parent-child-hierarchy/_index.md | 17 + .../graphics/rendering-internals/_index.md | 15 + .../shader-basics/_index.md | 16 + .../learn/book/graphics/transforms/_index.md | 17 + content/learn/book/graphics/windows/_index.md | 18 + content/learn/book/input/_index.md | 16 + content/learn/book/input/basics/_index.md | 18 + content/learn/book/input/gamepad/_index.md | 17 + content/learn/book/input/keyboard/_index.md | 17 + content/learn/book/input/mouse/_index.md | 18 + content/learn/book/input/touch/_index.md | 17 + .../book/performance-optimizations/_index.md | 15 + .../component-storage/_index.md | 16 + .../diagnostics-benchmarking/_index.md | 16 + .../indexes/_index.md | 18 + .../parallel-iteration/_index.md | 18 + content/learn/book/platforms/_index.md | 15 + .../learn/book/platforms/android/_index.md | 16 + content/learn/book/platforms/ios/_index.md | 16 + content/learn/book/platforms/web/_index.md | 16 + .../learn/book/plugin-development/_index.md | 2 + content/learn/book/ui/_index.md | 16 + content/learn/book/ui/basics/_index.md | 22 + content/learn/links.toml | 6 +- .../migration-guides/0.10-0.11/_index.md | 1 + .../migration-guides/0.11-0.12/_index.md | 1 + .../learn/migration-guides/0.4-0.5/_index.md | 19 +- .../learn/migration-guides/0.5-0.6/_index.md | 81 +- .../quick-start/3d-puzzle-game/_index.md | 7 + content/learn/quick-start/_index.md | 7 + content/learn/quick-start/breakout/_index.md | 7 + .../contributing/_index.md | 5 +- .../contributing/code/_index.md | 1 + .../contributing/docs/_index.md | 20 +- .../learn/quick-start/falling-sand/_index.md | 7 + .../quick-start/getting-started/_index.md | 65 + .../getting-started/apps/_index.md | 44 + .../getting-started/ecs/_index.md | 52 +- .../getting-started/plugins/_index.md | 107 + .../getting-started/resources/_index.md | 86 + .../getting-started/setup/_index.md | 27 +- .../introduction/_index.md | 9 +- .../next-steps/_index.md | 5 +- .../quick-start/plugin-development/_index.md | 161 + .../troubleshooting/_index.md | 1 + .../news/2020-08-10-introducing-bevy/index.md | 90 +- content/news/2020-09-19-bevy-0.2/index.md | 8 +- content/news/2020-11-03-bevy-0.3/index.md | 10 +- content/news/2020-12-19-bevy-0.4/index.md | 52 +- content/news/2021-04-06-bevy-0.5/index.md | 63 +- .../2021-08-10-bevys-first-birthday/index.md | 21 +- content/news/2022-01-08-bevy-0.6/index.md | 68 +- content/news/2022-04-15-bevy-0.7/index.md | 12 +- content/news/2022-07-30-bevy-0.8/index.md | 8 +- .../2022-08-10-bevys-second-birthday/index.md | 2 +- content/news/2022-11-12-bevy-0.9/index.md | 16 +- content/news/2023-03-06-bevy-0.10/index.md | 2 +- content/news/2023-05-17-bevy-webgpu/index.md | 2 +- content/news/2023-07-09-bevy-0.11/index.md | 2 +- .../2023-08-10-bevys-third-birthday/index.md | 2 +- .../index.md | 2 +- content/news/2023-11-04-bevy-0.12/index.md | 2 +- generate-assets/Cargo.lock | 94 +- generate-community/src/bin/generate.rs | 30 +- sass/_utils.scss | 67 +- sass/_vars.scss | 12 +- sass/components/_asset-card.scss | 234 +- sass/components/_card.scss | 146 +- sass/components/_header.scss | 130 +- sass/components/_logo.scss | 14 +- sass/components/_main-menu.scss | 326 +- sass/components/_page-with-menu.scss | 78 +- sass/components/_sponsors.scss | 116 +- sass/components/_todo.scss | 13 + sass/elements/_html.scss | 34 +- sass/pages/_assets.scss | 96 +- sass/pages/_community.scss | 6 +- sass/pages/_docs.scss | 68 +- sass/site.scss | 3 +- static/web-streams-adapter-0.1.0.mjs | 559 +++ static/web-streams-polyfill-3.2.1.mjs | 4203 +++++++++++++++++ templates/assets.html | 100 +- templates/example.html | 153 +- templates/examples.html | 72 +- templates/index.html | 5 +- templates/layouts/base.html | 249 +- templates/macros/assets.html | 120 +- templates/news.html | 48 +- templates/people.html | 468 +- templates/shortcodes/rust_mod.html | 24 - templates/shortcodes/rust_type.html | 28 - templates/shortcodes/todo.html | 4 + templates/sitemap.xml | 13 + write-rustdoc-hide-lines/.gitignore | 1 + write-rustdoc-hide-lines/Cargo.lock | 23 + write-rustdoc-hide-lines/Cargo.toml | 10 + write-rustdoc-hide-lines/README.md | 17 + .../src/code_block_definition.rs | 271 ++ write-rustdoc-hide-lines/src/formatter.rs | 207 + write-rustdoc-hide-lines/src/hidden_ranges.rs | 121 + write-rustdoc-hide-lines/src/lib.rs | 3 + write-rustdoc-hide-lines/src/main.rs | 16 + .../write_rustdoc_hide_lines.sh | 2 + 164 files changed, 9734 insertions(+), 1735 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 code-validation/Cargo.toml create mode 100644 code-validation/rustfmt.toml create mode 100644 code-validation/src/lib.rs rename content/{faq/_index.md => faq.md} (100%) create mode 100644 content/learn/advanced-examples/_index.md create mode 100644 content/learn/advanced-examples/sudoku/_index.md create mode 100644 content/learn/advanced-examples/text-adventure/_index.md create mode 100644 content/learn/book/assets/_index.md create mode 100644 content/learn/book/assets/custom-assets/_index.md create mode 100644 content/learn/book/assets/hot-reloading/_index.md create mode 100644 content/learn/book/assets/loading-assets/_index.md create mode 100644 content/learn/book/assets/scenes-reflection/_index.md create mode 100644 content/learn/book/assets/working-with-handles/_index.md create mode 100644 content/learn/book/audio/_index.md create mode 100644 content/learn/book/audio/audio-basics/_index.md create mode 100644 content/learn/book/development-practices/_index.md create mode 100644 content/learn/book/development-practices/boilerplate-reduction/_index.md create mode 100644 content/learn/book/development-practices/error-handling/_index.md create mode 100644 content/learn/book/development-practices/fast-compiles/_index.md create mode 100644 content/learn/book/development-practices/organizing-your-code/_index.md create mode 100644 content/learn/book/development-practices/testing/_index.md create mode 100644 content/learn/book/ecs/_index.md create mode 100644 content/learn/book/ecs/change-detection/_index.md create mode 100644 content/learn/book/ecs/commands/_index.md create mode 100644 content/learn/book/ecs/entities-components/_index.md create mode 100644 content/learn/book/ecs/exclusive-world-access/_index.md create mode 100644 content/learn/book/ecs/filtering-queries/_index.md create mode 100644 content/learn/book/ecs/generic-systems/_index.md create mode 100644 content/learn/book/ecs/resources/_index.md create mode 100644 content/learn/book/ecs/systems-queries/_index.md create mode 100644 content/learn/book/game-logic/_index.md create mode 100644 content/learn/book/game-logic/async-tasks/_index.md create mode 100644 content/learn/book/game-logic/custom-runners-headless-operations/_index.md create mode 100644 content/learn/book/game-logic/events/_index.md create mode 100644 content/learn/book/game-logic/run-criteria/_index.md create mode 100644 content/learn/book/game-logic/states/_index.md create mode 100644 content/learn/book/game-logic/system-ordering/_index.md create mode 100644 content/learn/book/game-logic/time-timers/_index.md create mode 100644 content/learn/book/getting-started/app-appbuilder-world/_index.md delete mode 100644 content/learn/book/getting-started/apps/_index.md create mode 100644 content/learn/book/getting-started/bevy-community/_index.md create mode 100644 content/learn/book/getting-started/installation/_index.md create mode 100644 content/learn/book/getting-started/modular-plugins/_index.md delete mode 100644 content/learn/book/getting-started/plugins/_index.md delete mode 100644 content/learn/book/getting-started/resources/_index.md create mode 100644 content/learn/book/getting-started/why-bevy/_index.md create mode 100644 content/learn/book/graphics/2d/_index.md create mode 100644 content/learn/book/graphics/2d/sprite-sheets/_index.md create mode 100644 content/learn/book/graphics/2d/sprites/_index.md create mode 100644 content/learn/book/graphics/3d/_index.md create mode 100644 content/learn/book/graphics/3d/meshes/_index.md create mode 100644 content/learn/book/graphics/3d/pbr/_index.md create mode 100644 content/learn/book/graphics/_index.md create mode 100644 content/learn/book/graphics/cameras/_index.md create mode 100644 content/learn/book/graphics/parent-child-hierarchy/_index.md create mode 100644 content/learn/book/graphics/rendering-internals/_index.md create mode 100644 content/learn/book/graphics/rendering-internals/shader-basics/_index.md create mode 100644 content/learn/book/graphics/transforms/_index.md create mode 100644 content/learn/book/graphics/windows/_index.md create mode 100644 content/learn/book/input/_index.md create mode 100644 content/learn/book/input/basics/_index.md create mode 100644 content/learn/book/input/gamepad/_index.md create mode 100644 content/learn/book/input/keyboard/_index.md create mode 100644 content/learn/book/input/mouse/_index.md create mode 100644 content/learn/book/input/touch/_index.md create mode 100644 content/learn/book/performance-optimizations/_index.md create mode 100644 content/learn/book/performance-optimizations/component-storage/_index.md create mode 100644 content/learn/book/performance-optimizations/diagnostics-benchmarking/_index.md create mode 100644 content/learn/book/performance-optimizations/indexes/_index.md create mode 100644 content/learn/book/performance-optimizations/parallel-iteration/_index.md create mode 100644 content/learn/book/platforms/_index.md create mode 100644 content/learn/book/platforms/android/_index.md create mode 100644 content/learn/book/platforms/ios/_index.md create mode 100644 content/learn/book/platforms/web/_index.md create mode 100644 content/learn/book/ui/_index.md create mode 100644 content/learn/book/ui/basics/_index.md create mode 100644 content/learn/quick-start/3d-puzzle-game/_index.md create mode 100644 content/learn/quick-start/_index.md create mode 100644 content/learn/quick-start/breakout/_index.md rename content/learn/{book => quick-start}/contributing/_index.md (84%) rename content/learn/{book => quick-start}/contributing/code/_index.md (96%) rename content/learn/{book => quick-start}/contributing/docs/_index.md (60%) create mode 100644 content/learn/quick-start/falling-sand/_index.md create mode 100644 content/learn/quick-start/getting-started/_index.md create mode 100644 content/learn/quick-start/getting-started/apps/_index.md rename content/learn/{book => quick-start}/getting-started/ecs/_index.md (75%) create mode 100644 content/learn/quick-start/getting-started/plugins/_index.md create mode 100644 content/learn/quick-start/getting-started/resources/_index.md rename content/learn/{book => quick-start}/getting-started/setup/_index.md (84%) rename content/learn/{book => quick-start}/introduction/_index.md (62%) rename content/learn/{book => quick-start}/next-steps/_index.md (85%) create mode 100644 content/learn/quick-start/plugin-development/_index.md rename content/learn/{book => quick-start}/troubleshooting/_index.md (97%) create mode 100644 sass/components/_todo.scss create mode 100644 static/web-streams-adapter-0.1.0.mjs create mode 100644 static/web-streams-polyfill-3.2.1.mjs delete mode 100644 templates/shortcodes/rust_mod.html delete mode 100644 templates/shortcodes/rust_type.html create mode 100644 templates/shortcodes/todo.html create mode 100644 templates/sitemap.xml create mode 100644 write-rustdoc-hide-lines/.gitignore create mode 100644 write-rustdoc-hide-lines/Cargo.lock create mode 100644 write-rustdoc-hide-lines/Cargo.toml create mode 100644 write-rustdoc-hide-lines/README.md create mode 100644 write-rustdoc-hide-lines/src/code_block_definition.rs create mode 100644 write-rustdoc-hide-lines/src/formatter.rs create mode 100644 write-rustdoc-hide-lines/src/hidden_ranges.rs create mode 100644 write-rustdoc-hide-lines/src/lib.rs create mode 100644 write-rustdoc-hide-lines/src/main.rs create mode 100755 write-rustdoc-hide-lines/write_rustdoc_hide_lines.sh diff --git a/.github/bors.toml b/.github/bors.toml index da9c575ce9..8ac35f13ae 100644 --- a/.github/bors.toml +++ b/.github/bors.toml @@ -1,10 +1,11 @@ -status = [ - "build-website", - "generate-wasm-examples", - "generate-assets", - "generate-errors", - "generate-community", - "markdownlint", -] - -use_squash_merge = true +status = [ + "build-website", + "generate-wasm-examples", + "generate-assets", + "generate-errors", + "generate-community", + "markdownlint", + "test-code", +] + +use_squash_merge = true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8811fd5935..09239fc796 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,7 @@ on: jobs: generate-assets: + needs: [markdownlint, test-code] runs-on: ubuntu-latest steps: - uses: actions/checkout@master @@ -47,6 +48,7 @@ jobs: retention-days: 1 generate-errors: + needs: [markdownlint, test-code] runs-on: ubuntu-latest steps: - uses: actions/checkout@master @@ -73,10 +75,16 @@ jobs: retention-days: 1 generate-wasm-examples: + needs: [markdownlint, test-code] runs-on: ubuntu-latest steps: - uses: actions/checkout@master + - name: "Clone Bevy" + run: > + cd generate-wasm-examples && + ./clone_bevy.sh + - uses: actions/cache@v3 with: path: | @@ -84,6 +92,8 @@ jobs: ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ + generate-wasm-examples/bevy/target/ + content/examples/**/*.wasm key: ${{ runner.os }}-generate-wasm-examples-${{ hashFiles('generate-wasm-examples/bevy/Cargo.toml') }} - uses: dtolnay/rust-toolchain@stable @@ -108,6 +118,7 @@ jobs: retention-days: 1 generate-community: + needs: [markdownlint, test-code] runs-on: ubuntu-latest steps: - uses: actions/checkout@master @@ -147,6 +158,17 @@ jobs: VALIDATE_MARKDOWN: true DEFAULT_BRANCH: main + test-code: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + + - uses: actions/upload-artifact@master + with: + name: generated-errors + path: content/learn/errors + retention-days: 1 + build-website: runs-on: ubuntu-latest needs: [markdownlint, generate-assets, generate-errors, generate-wasm-examples, generate-community] diff --git a/.gitignore b/.gitignore index efd7777d7f..dd5ca563f9 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ content/community/people content/community/donate static/assets/examples static/processed_images -.vscode/ \ No newline at end of file +.vscode/ +code-validation/target +code-validation/Cargo.lock diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..d4b3b56c52 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,185 @@ +# Contributing + +So, you want to help with the [Bevy website](https://bevyengine.org/)? +(If you want to help with the [Bevy engine](https://github.com/bevyengine/bevy), then see the engine [CONTRIBUTING.md](https://github.com/bevyengine/bevy/blob/main/CONTRIBUTING.md)). + +## Building the website + +The Bevy website is built using the Zola static site engine. In our experience, it is fast, flexible, and straightforward to use. + +To check out any local changes you've made: + +1. [Download Zola](https://www.getzola.org/). +2. Clone the Bevy Website git repo and enter that directory: + 1. `git clone https://github.com/bevyengine/bevy-website.git` + 2. `cd bevy-website` +3. Start the Zola server with `zola serve`. + +A local server should start and you should be able to access a local version of the website from there. + +## Testing changes to book code snippets + +The code in the book is compiled and tested to make sure that the examples work for readers. + +To check your local changes, move into the `code-validation` folder of this project using `cd code-validation`, and then run `cargo test`. If you write a new section of the book, you have to add it in `code-validation/src/lib.rs` to enable code validation for it. + +## Learning material structure + +As you probably noticed, our introductory learning material is split into two main sections: + +1. **Bevy Quick Start:** "Get started making your first game now!" +2. **Bevy Book:** "Understand how Bevy works, and how you can use it" + +This is intended to cater to two different types of learners, without compromising the experience for either: + +- **Example-first:** These users want to dive right in, see everything in action and get a working game as quickly as possible. +These users often have an idea in their mind that they want to start prototyping as quickly as possible. +- **Definition-first:** These users want to carefully build up a mental model of Bevy, thoroughly understanding each new concept before moving on. +These users tend to be driven by curiosity, or are aiming to carefully develop a new skill. + +Crucially, these paths are independent of the experience levels of the learner! +Bevy intentionally aims to be inclusive of both complete beginners who have never programmed before, and professionals coming from other engines. + +| | **Beginner** | **Professional** | +| -------------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------- | +| **Example-first** | Enthusiastic, wants to create a new version of the game they love. | Exploratory, wants to dive in and see how Bevy holds up in practice. | +| **Definition-first** | Curious, wants to understand how making games works. | Critical, wants to understand Bevy's unique design choices. | + +Each of these requires their own complementary learning paths that branch as soon as they get to the [Learn page](https://bevyengine.org/learn/) to ensure that the first experience that they have with Bevy matches what they need. + +Once users have completed the introductory learning materials in their path of choice, they can begin creating their own games or move on to our advanced examples to see how everything comes together in a realistic way. + +### Bevy Quick Start: the example-first path + +Users following the example-first path will tend to take the following route: + +1. Encounter the Bevy homepage due to social media or word of mouth. +2. Navigate to the Learn page. +3. Choose one of the most relevant **quick start games**. +4. Complete that tutorial. +5. Dive into making the game they have in mind, accessing the following resources as needed when they encounter road-blocks: + 1. Official Examples. + 2. The Bevy book. + 3. Community tutorials and template games. + 4. Various community support forums. + 5. Streams, YouTube channels and blogs. + 6. Advanced examples. + +Each quick start game should: + +1. Assume zero existing knowledge of Bevy. +2. Begin with a initial high-level explanation of what we're trying to build. +3. Introduce commented code first, then explain what each of the critical terms means as they come up. +4. Be broken into compilable, playable sections: one per page of the guide. +5. Gradually refactor the code to add more functionality. +6. End with a list of suggestions (with appropriate links) on how you could extend the game in interesting ways. + +This path should prioritize: + +1. Rapid time-to-fun. +2. Functional, good-enough explanations that are tied to the code in front of them. +3. Relevance of quick-start game to the genre of game they want to make. +4. High asset quality. +5. Ease of extending the quick-start game with their own tweaks. +6. Explaining how to get unstuck, through documentation, community help and filing issues. + +### The Bevy Book: the definition-first path + +Users following the definition-first path will tend to take the following route: + +1. Encounter the Bevy homepage due to social media or word of mouth. +2. Navigate to the Learn page. +3. Select the **Bevy book**. +4. Read through the book, largely in order. +5. Once they feel they have a good enough understanding of the engine, they will begin to make their own games, typically by jumping over onto the example-first path. +6. As they explore, they will also browse: + 1. The source code. + 2. [docs.rs](https://docs.rs/bevy/) + 3. CONTRIBUTING.md, GitHub issues and pull requests. + 4. Release notes. + 5. The engine development channels on Discord. + 6. Advanced examples to see how everything comes together. + +Each chapter of the Bevy Book should: + +1. Have a clear topic, and give a high-level overview of the subtopics it is going to cover and how they fit together. +2. Be broken down into several sections / pages to focus on detailed topics. + 1. These should have simple, minimal examples explaining how that functionality works. +3. Link to appropriate sections of quick start guides that demonstrate the ideas being taught in a more coherent way. + +This path should prioritize: + +1. Clear, thorough explanations. +2. Carefully introducing one concept at a time in an organized fashion. +3. Connecting concepts to each other in context. +4. Explaining the technical details of how things work, but only in clearly marked asides. +5. Communicating all of the supporting development practices that make Bevy productive: + 1. How to set up your dev environment. + 2. Code organization. + 3. Design patterns and best practices. + 4. Testing, benchmarking and debugging. + 5. Contributing to Bevy itself. +6. Linking to further reading: official examples, `docs.rs` and (very sparingly) source code links. + +## Contributor's style guide + +When writing and reviewing learning material for the Bevy Book and Quick Start Games, please try to follow these guidelines: + +### Writing + +1. Use clear, simple language. +2. Prefer short sentences. Remove extra words. +3. **Bold** new vocabulary words where they are defined. + 1. Define them as soon as is reasonable after they are introduced. +4. Make sure your grammar and spelling are correct. +5. Avoid idioms and slang. +6. Speak directly to the reader in an approachable tone. Use "we" and "you" pronouns. +7. It can be useful to create specific, named characters to demonstrate a point. + 1. If you do, pick a pronoun set for them and stick to it. + 2. Otherwise, use "they/them" third-person pronouns to refer to the reader or others. +8. Keep humor light. + 1. Avoid off-color or offensive humor. + 2. Be mindful not to overuse in-jokes or cultural references. + 3. Don't drag your jokes out: that's not what the audience is here to read. + +### Organizational + +1. Carefully organize your work into separate pages, headings, paragraphs and code blocks. +2. Clearly signal when you are explaining a concept in technical depth so it can be skipped. +3. Use lists, numbered lists and sub-lists to present information in bite-sized ways. + 1. Refer back to these items by number! +4. Provide plenty of links, but be sure that what you are linking to is obvious by context. + 1. Link to other sections of the book / example / web page when you mention them. + 2. Always link to the most specific location you can, whether that's a section on a page or a method on a struct. + 3. Use the `latest` tag when linking to Bevy docs and source code so it won't go stale every time the version is updated. + 4. When linking to detailed explanations or discussions, summarize the most important points in addition to providing a link. + +### Technical + +1. All examples must be able to be compiled and run. +2. Prefer game-relevant, descriptive examples and variable names over generic ones like `MyEvent`. Avoid meaningless names like `foo` at all times. +3. It's good practice to break your code into blocks with comments or explanatory text, but you need to link to a cohesive, copy-able whole at the end. +4. Examples must pass Bevy's standard `clippy` lints. +5. The polish level of your examples should correspond to the point you're trying to make. + 1. If you're demonstrating a new feature, show only the most basic syntax as locally as possible. + 2. When trying to explain how a game can be made, organize and polish your code to showcase best practices. + 3. Lack of polish should serve an end: don't show bad or sloppy practices without a good reason. + 4. Showing how (and why!) to refactor your code is a very powerful teaching tool. +6. Stick to a consistent style (e.g. for loops vs map) within each example. +7. If you need to give advice that will only matter to some of your audience (e.g. how to handle an edge case, or support a specific platform), do so in a clearly marked aside or list. +8. Examples should not use or rely on third-party plugins. +These may be appropriate to link in "next steps" however at the end of the examples. + 1. Third-party crates should be limited to the most essential, such as `rand`. +9. If additional code block attributes like `no_run` or `hide-lines=x-y` need to be specified, you should always order these so that the language is the last attribute. If we would specify `rust,no_run` the syntax highlighting wouldn't work, but changing it to `no_run,rust` makes it work. +10. To validate if local code changes are compiling you can `cd` into the `code-validation` folder and test your code using `cargo test`. +11. To make sure your markdown files are formatted correctly run `markdownlint -f -c .github/linters/.markdown-lint.yml .` in the root directory of your local Bevy website repository. +12. To reference Rust API docs you can use markdown's reference-style links like so: + [`HashMap`] + + ```md + [`HashMap`] + + [`HashMap`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html + ``` + + [`HashMap`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html diff --git a/README.md b/README.md index 7eef99c69c..59063db408 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Bevy Website -The source files for . This includes official Bevy news and docs, so if you would like to contribute feel free to create a pull request! +The source files for . This includes official Bevy news, docs, and interactive examples. + +If you would like to contribute, check out [CONTRIBUTING.md] and then submit a pull request! ## Zola diff --git a/code-validation/Cargo.toml b/code-validation/Cargo.toml new file mode 100644 index 0000000000..750d9cafe1 --- /dev/null +++ b/code-validation/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "code-validation" +version = "0.1.0" +edition = "2021" + +[dependencies] +# This should point to `main` when we are preparing for the next release, +# but should be fixed at the latest release once it is published on crates.io +# bevy = "0.7" +bevy = { git = "https://github.com/bevyengine/bevy" } diff --git a/code-validation/rustfmt.toml b/code-validation/rustfmt.toml new file mode 100644 index 0000000000..a4607a5fa4 --- /dev/null +++ b/code-validation/rustfmt.toml @@ -0,0 +1,2 @@ +use_field_init_shorthand = true +newline_style = "Unix" diff --git a/code-validation/src/lib.rs b/code-validation/src/lib.rs new file mode 100644 index 0000000000..55c2018e88 --- /dev/null +++ b/code-validation/src/lib.rs @@ -0,0 +1,214 @@ +//! This crate is used to validate the rust code of the `bevy` website. +//! +//! It is currently used to validate the rust code of the offical `bevy` book. +//! The modules represents the folder structure of the website. + +mod learn { + #[doc = include_str!("../../content/learn/quick-start/_index.md")] + mod quick_start { + #[doc = include_str!("../../content/learn/quick-start/introduction/_index.md")] + mod introduction {} + #[doc = include_str!("../../content/learn/quick-start/getting-started/_index.md")] + mod getting_started { + #[doc = include_str!("../../content/learn/quick-start/getting-started/apps/_index.md")] + mod apps {} + #[doc = include_str!("../../content/learn/quick-start/getting-started/ecs/_index.md")] + mod ecs {} + #[doc = include_str!("../../content/learn/quick-start/getting-started/plugins/_index.md")] + mod plugins {} + #[doc = include_str!("../../content/learn/quick-start/getting-started/resources/_index.md")] + mod resources {} + } + #[doc = include_str!("../../content/learn/quick-start/contributing/_index.md")] + mod contributing { + #[doc = include_str!("../../content/learn/quick-start/contributing/docs/_index.md")] + mod docs {} + #[doc = include_str!("../../content/learn/quick-start/contributing/code/_index.md")] + mod code {} + } + #[doc = include_str!("../../content/learn/quick-start/plugin-development/_index.md")] + mod plugin_development {} + #[doc = include_str!("../../content/learn/quick-start/troubleshooting/_index.md")] + mod troubleshooting {} + #[doc = include_str!("../../content/learn/quick-start/next-steps/_index.md")] + mod next_steps {} + + #[doc = include_str!("../../content/learn/quick-start/breakout/_index.md")] + mod breakout {} + #[doc = include_str!("../../content/learn/quick-start/3d-puzzle-game/_index.md")] + mod three_dimensional_puzzle_game {} + #[doc = include_str!("../../content/learn/quick-start/falling-sand/_index.md")] + mod falling_sand {} + } + #[doc = include_str!("../../content/learn/advanced-examples/_index.md")] + mod advanced_examples { + #[doc = include_str!("../../content/learn/advanced-examples/sudoku/_index.md")] + mod sudoku {} + #[doc = include_str!("../../content/learn/advanced-examples/text-adventure/_index.md")] + mod text_adventure {} + } + #[doc = include_str!("../../content/learn/book/_index.md")] + mod book { + #[doc = include_str!("../../content/learn/book/assets/_index.md")] + mod assets { + #[doc = include_str!("../../content/learn/book/assets/custom-assets/_index.md")] + mod custom_assets {} + #[doc = include_str!("../../content/learn/book/assets/hot-reloading/_index.md")] + mod hot_reloading {} + #[doc = include_str!("../../content/learn/book/assets/loading-assets/_index.md")] + mod loading_assets {} + #[doc = include_str!("../../content/learn/book/assets/scenes-reflection/_index.md")] + mod scenes_reflection {} + #[doc = include_str!("../../content/learn/book/assets/working-with-handles/_index.md")] + mod working_with_handles {} + } + + #[doc = include_str!("../../content/learn/book/audio/_index.md")] + mod audio { + #[doc = include_str!("../../content/learn/book/audio/audio-basics/_index.md")] + mod audio_basics {} + } + + #[doc = include_str!("../../content/learn/book/development-practices/_index.md")] + mod development_practices { + #[doc = include_str!("../../content/learn/book/development-practices/boilerplate-reduction/_index.md")] + mod boilerplate_reduction {} + #[doc = include_str!("../../content/learn/book/development-practices/error-handling/_index.md")] + mod error_handling {} + #[doc = include_str!("../../content/learn/book/development-practices/fast-compiles/_index.md")] + mod fast_compiles {} + #[doc = include_str!("../../content/learn/book/development-practices/organizing-your-code/_index.md")] + mod organizing_your_code {} + #[doc = include_str!("../../content/learn/book/development-practices/testing/_index.md")] + mod testing {} + } + + #[doc = include_str!("../../content/learn/book/ecs/_index.md")] + mod ecs { + #[doc = include_str!("../../content/learn/book/ecs/change-detection/_index.md")] + mod change_detection {} + #[doc = include_str!("../../content/learn/book/ecs/commands/_index.md")] + mod commands {} + #[doc = include_str!("../../content/learn/book/ecs/entities-components/_index.md")] + mod entities_components {} + #[doc = include_str!("../../content/learn/book/ecs/exclusive-world-access/_index.md")] + mod exclusive_world_access {} + #[doc = include_str!("../../content/learn/book/ecs/filtering-queries/_index.md")] + mod filtering_queries {} + #[doc = include_str!("../../content/learn/book/ecs/generic-systems/_index.md")] + mod generic_systems {} + #[doc = include_str!("../../content/learn/book/ecs/resources/_index.md")] + mod resources {} + #[doc = include_str!("../../content/learn/book/ecs/systems-queries/_index.md")] + mod systems_queries {} + } + + #[doc = include_str!("../../content/learn/book/game-logic/_index.md")] + mod game_logic { + #[doc = include_str!("../../content/learn/book/game-logic/async-tasks/_index.md")] + mod async_tasks {} + #[doc = include_str!("../../content/learn/book/game-logic/custom-runners-headless-operations/_index.md")] + mod custom_runners_headless_operation {} + #[doc = include_str!("../../content/learn/book/game-logic/events/_index.md")] + mod events {} + #[doc = include_str!("../../content/learn/book/game-logic/run-criteria/_index.md")] + mod run_criteria {} + #[doc = include_str!("../../content/learn/book/game-logic/states/_index.md")] + mod states {} + #[doc = include_str!("../../content/learn/book/game-logic/system-ordering/_index.md")] + mod system_ordering {} + #[doc = include_str!("../../content/learn/book/game-logic/time-timers/_index.md")] + mod time_timers {} + } + + #[doc = include_str!("../../content/learn/book/getting-started/_index.md")] + mod getting_started { + #[doc = include_str!("../../content/learn/book/getting-started/app-appbuilder-world/_index.md")] + mod app_appbuilder_world {} + #[doc = include_str!("../../content/learn/book/getting-started/bevy-community/_index.md")] + mod bevy_community {} + #[doc = include_str!("../../content/learn/book/getting-started/installation/_index.md")] + mod installation {} + #[doc = include_str!("../../content/learn/book/getting-started/modular-plugins/_index.md")] + mod modular_plugins {} + #[doc = include_str!("../../content/learn/book/getting-started/why-bevy/_index.md")] + mod why_bevy {} + } + + #[doc = include_str!("../../content/learn/book/graphics/_index.md")] + mod graphics { + #[doc = include_str!("../../content/learn/book/graphics/2d/_index.md")] + mod two_dimensional { + #[doc = include_str!("../../content/learn/book/graphics/2d/sprite-sheets/_index.md")] + mod sprite_sheets {} + #[doc = include_str!("../../content/learn/book/graphics/2d/sprites/_index.md")] + mod sprites {} + } + #[doc = include_str!("../../content/learn/book/graphics/3d/_index.md")] + mod three_dimensional { + #[doc = include_str!("../../content/learn/book/graphics/3d/meshes/_index.md")] + mod meshes {} + #[doc = include_str!("../../content/learn/book/graphics/3d/pbr/_index.md")] + mod pbr {} + } + #[doc = include_str!("../../content/learn/book/graphics/cameras/_index.md")] + mod cameras {} + #[doc = include_str!("../../content/learn/book/graphics/parent-child-hierarchy/_index.md")] + mod parent_child_hierarchy {} + #[doc = include_str!("../../content/learn/book/graphics/rendering-internals/_index.md")] + mod rendering_internals { + #[doc = include_str!("../../content/learn/book/graphics/rendering-internals/shader-basics/_index.md")] + mod shader_basics {} + } + #[doc = include_str!("../../content/learn/book/graphics/transforms/_index.md")] + mod transforms {} + #[doc = include_str!("../../content/learn/book/graphics/windows/_index.md")] + mod windows {} + } + + #[doc = include_str!("../../content/learn/book/input/_index.md")] + mod input { + #[doc = include_str!("../../content/learn/book/input/gamepad/_index.md")] + mod gamepad {} + #[doc = include_str!("../../content/learn/book/input/basics/_index.md")] + mod basics {} + #[doc = include_str!("../../content/learn/book/input/keyboard/_index.md")] + mod keyboard {} + #[doc = include_str!("../../content/learn/book/input/mouse/_index.md")] + mod mouse {} + #[doc = include_str!("../../content/learn/book/input/touch/_index.md")] + mod touch {} + } + + // Not testing migration guides, because of breaking API changes. + mod migration_guides {} + + #[doc = include_str!("../../content/learn/book/performance-optimizations/_index.md")] + mod performance_optimizations { + #[doc = include_str!("../../content/learn/book/performance-optimizations/component-storage/_index.md")] + mod component_storage {} + #[doc = include_str!("../../content/learn/book/performance-optimizations/diagnostics-benchmarking/_index.md")] + mod diagnostics_benchmarking {} + #[doc = include_str!("../../content/learn/book/performance-optimizations/indexes/_index.md")] + mod indexes {} + #[doc = include_str!("../../content/learn/book/performance-optimizations/parallel-iteration/_index.md")] + mod parallel_iteration {} + } + + #[doc = include_str!("../../content/learn/book/platforms/_index.md")] + mod platforms { + #[doc = include_str!("../../content/learn/book/platforms/android/_index.md")] + mod android {} + #[doc = include_str!("../../content/learn/book/platforms/ios/_index.md")] + mod ios {} + #[doc = include_str!("../../content/learn/book/platforms/web/_index.md")] + mod web {} + } + + #[doc = include_str!("../../content/learn/book/ui/_index.md")] + mod ui { + #[doc = include_str!("../../content/learn/book/ui/basics/_index.md")] + mod basics {} + } + } +} diff --git a/content/faq/_index.md b/content/faq.md similarity index 100% rename from content/faq/_index.md rename to content/faq.md diff --git a/content/learn/advanced-examples/_index.md b/content/learn/advanced-examples/_index.md new file mode 100644 index 0000000000..a94c3d6aea --- /dev/null +++ b/content/learn/advanced-examples/_index.md @@ -0,0 +1,6 @@ ++++ +title = "Advanced Examples" +template = "docs-section.html" +[extra] +public_draft = 877 ++++ diff --git a/content/learn/advanced-examples/sudoku/_index.md b/content/learn/advanced-examples/sudoku/_index.md new file mode 100644 index 0000000000..e19bc97e57 --- /dev/null +++ b/content/learn/advanced-examples/sudoku/_index.md @@ -0,0 +1,5 @@ ++++ +title = "Sudoku" +weight = 2 +template = "docs-section.html" ++++ diff --git a/content/learn/advanced-examples/text-adventure/_index.md b/content/learn/advanced-examples/text-adventure/_index.md new file mode 100644 index 0000000000..0a090525ba --- /dev/null +++ b/content/learn/advanced-examples/text-adventure/_index.md @@ -0,0 +1,5 @@ ++++ +title = "Text Adventure" +weight = 1 +template = "docs-section.html" ++++ diff --git a/content/learn/book/_index.md b/content/learn/book/_index.md index 1906ee994e..e72dcdf0c0 100644 --- a/content/learn/book/_index.md +++ b/content/learn/book/_index.md @@ -3,6 +3,9 @@ title = "Book" sort_by = "weight" template = "docs-section.html" page_template = "docs-section.html" -redirect_to = "learn/book/introduction" +redirect_to = "learn/book/getting-started" insert_anchor_links = "right" -+++ \ No newline at end of file +[extra] +status = 'hidden' +public_draft = 874 ++++ diff --git a/content/learn/book/assets/_index.md b/content/learn/book/assets/_index.md new file mode 100644 index 0000000000..1101d686a1 --- /dev/null +++ b/content/learn/book/assets/_index.md @@ -0,0 +1,16 @@ ++++ +title = "Assets" +weight = 5 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Explain what an asset is. +* Give a high-level overview of asset loading in Bevy. Make sure to describe how handles work. +{% end %} diff --git a/content/learn/book/assets/custom-assets/_index.md b/content/learn/book/assets/custom-assets/_index.md new file mode 100644 index 0000000000..4b36fe528a --- /dev/null +++ b/content/learn/book/assets/custom-assets/_index.md @@ -0,0 +1,15 @@ ++++ +title = "Custom Assets" +weight = 3 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Demonstrate how to write a custom asset loader. +{% end %} diff --git a/content/learn/book/assets/hot-reloading/_index.md b/content/learn/book/assets/hot-reloading/_index.md new file mode 100644 index 0000000000..b54c0e341a --- /dev/null +++ b/content/learn/book/assets/hot-reloading/_index.md @@ -0,0 +1,16 @@ ++++ +title = "Hot Reloading" +weight = 4 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Demonstrate how to watch for changes to automatically hot reload assets when modified +* Steal from [hot reloading example](https://github.com/bevyengine/bevy/blob/main/examples/asset/hot_asset_reloading.rs) +{% end %} diff --git a/content/learn/book/assets/loading-assets/_index.md b/content/learn/book/assets/loading-assets/_index.md new file mode 100644 index 0000000000..f465907c6a --- /dev/null +++ b/content/learn/book/assets/loading-assets/_index.md @@ -0,0 +1,17 @@ ++++ +title = "Loading Assets" +weight = 1 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Demonstrate how to load assets. +* Discuss how to change the asset loading folder. +* Discuss asset loading patterns to deal with async nature. +{% end %} diff --git a/content/learn/book/assets/scenes-reflection/_index.md b/content/learn/book/assets/scenes-reflection/_index.md new file mode 100644 index 0000000000..76d2ec077b --- /dev/null +++ b/content/learn/book/assets/scenes-reflection/_index.md @@ -0,0 +1,19 @@ ++++ +title = "Scenes and Reflection" +weight = 5 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Explain what scenes are +* Explain what reflection is +* Demonstrate how to use scenes to load a prefab +* Demonstrate how to use scenes to load a level +* Demonstrate how to use scenes to save and load a game +{% end %} diff --git a/content/learn/book/assets/working-with-handles/_index.md b/content/learn/book/assets/working-with-handles/_index.md new file mode 100644 index 0000000000..abf1625da1 --- /dev/null +++ b/content/learn/book/assets/working-with-handles/_index.md @@ -0,0 +1,18 @@ ++++ +title = "Working With Handles" +weight = 2 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Explain what a handle is, and point to resources on reference counting in Rust +* Demonstrate handle storage patterns +* Demonstrate how to change materials of an asset +* Explain what weak handles are +{% end %} diff --git a/content/learn/book/audio/_index.md b/content/learn/book/audio/_index.md new file mode 100644 index 0000000000..19cbcd0d7f --- /dev/null +++ b/content/learn/book/audio/_index.md @@ -0,0 +1,16 @@ ++++ +title = "Audio" +weight = 7 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Tiny blurb about audio +* Disclaim WIP status, point to `bevy_kira_audio` and competing community crates +{% end %} diff --git a/content/learn/book/audio/audio-basics/_index.md b/content/learn/book/audio/audio-basics/_index.md new file mode 100644 index 0000000000..f53a5e4a08 --- /dev/null +++ b/content/learn/book/audio/audio-basics/_index.md @@ -0,0 +1,16 @@ ++++ +title = "Audio basics" +weight = 1 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Demonstrate how to load and play sounds +* Discuss compatible file formats +{% end %} diff --git a/content/learn/book/development-practices/_index.md b/content/learn/book/development-practices/_index.md new file mode 100644 index 0000000000..535fcebe51 --- /dev/null +++ b/content/learn/book/development-practices/_index.md @@ -0,0 +1,15 @@ ++++ +title = "Development Practices" +weight = 9 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* This chapter covers practices that help you write larger Bevy apps in a clearer, safer and more productive way +{% end %} diff --git a/content/learn/book/development-practices/boilerplate-reduction/_index.md b/content/learn/book/development-practices/boilerplate-reduction/_index.md new file mode 100644 index 0000000000..8fdf5733bf --- /dev/null +++ b/content/learn/book/development-practices/boilerplate-reduction/_index.md @@ -0,0 +1,16 @@ ++++ +title = "Boilerplate Reduction" +weight = 5 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Link to resources on macros +* Discuss custom system parameters +{% end %} diff --git a/content/learn/book/development-practices/error-handling/_index.md b/content/learn/book/development-practices/error-handling/_index.md new file mode 100644 index 0000000000..ff126d7f57 --- /dev/null +++ b/content/learn/book/development-practices/error-handling/_index.md @@ -0,0 +1,17 @@ ++++ +title = "Error Handling" +weight = 4 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Discuss errors in Rust, link to other good resources +* Explain system chaining, and demonstrate how to apply it to error handling +* Explain and demonstrate [error handling in commands](https://github.com/bevyengine/bevy/pull/2241) +{% end %} diff --git a/content/learn/book/development-practices/fast-compiles/_index.md b/content/learn/book/development-practices/fast-compiles/_index.md new file mode 100644 index 0000000000..c89b2fc96c --- /dev/null +++ b/content/learn/book/development-practices/fast-compiles/_index.md @@ -0,0 +1,57 @@ ++++ +title = "Fast Compiles" +weight = 2 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Explain why you might want faster compiles +{% end %} + +* **Enable Bevy's Dynamic Linking Feature**: This is the most impactful compilation time decrease! If `bevy` is a dependency you can compile the binary with the "dynamic" feature flag (enables dynamic linking): + + ```sh + cargo run --features bevy/dynamic + ``` + + If you don't want to add the `--features bevy/dynamic` to each run, this flag can permanently be set via `Cargo.toml`: + + ```toml + [dependencies] + bevy = { version = "0.5.0", features = ["dynamic"] } + ``` + + NOTE: Remember to revert this before releasing your game! Otherwise you will need to include `libbevy_dylib` alongside your game if you want it to run. If you remove the "dynamic" feature, your game executable can run standalone. + +* **LLD linker**: The Rust compiler spends a lot of time in the "link" step. LLD is _much faster_ at linking than the default Rust linker. To install LLD, find your OS below and run the given command: + * **Ubuntu**: `sudo apt-get install lld` + * **Arch**: `sudo pacman -S lld` + * **Windows**: Ensure you have the latest [cargo-binutils](https://github.com/rust-embedded/cargo-binutils) + + ```sh + cargo install -f cargo-binutils + rustup component add llvm-tools-preview + ``` + +* **MacOS**: Modern LLD does not yet support MacOS, but we can use zld instead: `brew install michaeleisel/zld/zld` +* **Nightly Rust Compiler**: This gives access to the latest performance improvements and "unstable" optimizations + + ```sh + # Install the nightly toolchain + rustup toolchain install nightly + # Configure your current project to use nightly (run this command within the project) + rustup override set nightly + # OR configure cargo to use nightly for all projects -- switch back with `rustup default stable` + rustup default nightly + ``` + + * You can use `cargo +nightly ...` if you don't want to change the default to nightly. +* **Generic Sharing**: Allows crates to share monomorphized generic code instead of duplicating it. In some cases this allows us to "precompile" generic code so it doesn't affect iterative compiles. This is only available on nightly Rust. + +To enable fast compiles, install the nightly rust compiler and LLD. Then copy [this file](https://github.com/bevyengine/bevy/blob/main/.cargo/config_fast_builds) to `YOUR_WORKSPACE/.cargo/config.toml`. For the project in this guide, that would be `my_bevy_game/.cargo/config.toml`. diff --git a/content/learn/book/development-practices/organizing-your-code/_index.md b/content/learn/book/development-practices/organizing-your-code/_index.md new file mode 100644 index 0000000000..aa671e4002 --- /dev/null +++ b/content/learn/book/development-practices/organizing-your-code/_index.md @@ -0,0 +1,17 @@ ++++ +title = "Organizing Your Code" +weight = 1 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Refresh on Rust modules, link to official docs +* Discuss plugins as a code organization tool +* Discuss how to split your code out into libraries +{% end %} diff --git a/content/learn/book/development-practices/testing/_index.md b/content/learn/book/development-practices/testing/_index.md new file mode 100644 index 0000000000..cf7fd44b0c --- /dev/null +++ b/content/learn/book/development-practices/testing/_index.md @@ -0,0 +1,18 @@ ++++ +title = "Testing" +weight = 3 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Discuss unit testing using the examples framework +* Discuss strategies for integration testing +* Discuss input mocking +* Discuss setting up CI +{% end %} diff --git a/content/learn/book/ecs/_index.md b/content/learn/book/ecs/_index.md new file mode 100644 index 0000000000..0e43d320d2 --- /dev/null +++ b/content/learn/book/ecs/_index.md @@ -0,0 +1,85 @@ ++++ +title = "Entities, Components and Systems" +weight = 2 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +In Bevy, game objects are stored as **entities**, whose data is stored as **components**. +**Systems** operate on this data, modifying the **world** to carry out the behavior that brings your game to life. +Together, these these form the basis of Bevy's **ECS**, which unsurprisingly stands for ["Entity-Component-System"](https://en.wikipedia.org/wiki/Entity_component_system). +Let's go over the most important definitions: + +- **World:** A unifying collection of all of the data stored in the ECS. + - Access to the [`World`] follows Rust's borrow checker rules: you can read from the same data any number of times, but you must have exclusive access to modify a piece of data. +- **Entities:** Game objects (either abstract, like a camera, or tangible, like a player character), whose data is stored as components. + - The [`Entity`] type is just a simple identifier (like a URL address, a unique name, or a row number in a database). +- **Components:** Data stored on an entity, that can be manipulated in systems. + - Each component has a different Rust type that implements the [`Component`] trait, and only one component of each type can exist for each entity. + - Components without data are called **marker components**, and can be used to efficiently select entities that have a specific property (like being `Poisoned`, or defining a `Player`). + - Any combination of components can be added to each entity, allowing us to extend and share behavior through composition. +- **Systems:** Special functions that operate on data from the [`World`]: most commonly modifying the data stored in components on entities. + - Any function whose parameters all implement the [`SystemParam`] type can be converted into a [`System`]. + +Suppose we wanted to make a [Breakout game](https://github.com/bevyengine/bevy/blob/latest/examples/games/breakout.rs) in Bevy. +Let's think about what entities we might want, what components they might have, and what systems we might create: + +- A paddle entity + - a `Paddle` marker component, to allow us to uniquely identify the paddle + - a [`Sprite`] component, which describes how to draw our paddle + - in reality, this is a bit more complex, and requires a [`SpriteBundle`] collection of components + - a [`Transform`] component, to let us know the translation (position), rotation (orientation) and scale (size) of our paddles + - a `Velocity` component, giving us more realistic movement + - a `Collidable` component, to let us know that the ball can bounce off of it +- A ball entity + - a `Ball` marker component, so we can uniquely identify our ball + - a [`Sprite`] component + - a [`Transform`] component + - a `Velocity` component, to ensure the ball keeps moving +- Brick entities + - a [`Brick`] marker component + - a [`Sprite`] component + - a [`Transform`] component + - a `Collidable` component +- Wall entities + - a `Collidable` component, to make sure our ball bounces off the walls + - a `Transform` component, so we know where the boundaries are + +As you can see, each component implies specific behavior, but does not provide it on it. Components are just data (although they often have simple methods), and only act when systems use them. +Each of our components is quite small, allowing us to reuse these types and share behavior across entities using systems. +For our simple Breakout game, we may have: + +- `setup`: a simple **startup system** that runs a single time when our game is launched, **spawning** our paddles, ball and walls +- `apply_velocity`: a system that operates on all entities with a `Transform` and `Velocity`, and moves the entity according to its velocity +- `handle_collisions`: a system that operates on the `Ball` entity, and any entity with both a `Collidable` component and a `Transform` component, to bounce the ball appropriately +- `destroy_bricks`: a system that **despawns** entities with the `Brick` marker component when they are collided with + +In order to start working with Bevy, you should know a few other critical pieces of ECS vocabulary: + +- **Resources:** Globally unique stores of data that live in the [`World`], but are not associated with a specific entity. + - Events, configuration and global game state are all commonly stored as resources, which can be accessed with the [`Res`] system parameter. +- **Queries:** Requests for specific entity-component data from the [`World`]. + - The [`Query`] type has two type parameters: the first describes what component data should be fetched, and the second filters down which entities with that data should be returned when looping over the query. +- **Commands:** Instructions to modify the [`World`] at a later point in time. + - Most commonly, this is used to spawn and despawn entities, or insert and remove components. + - [`Commands`] require [exclusive world access](./exclusive-world-access/), and so are deferred until there are no other systems running. + +While there's much more to learn about Bevy's ECS, this basic overview should give you the vocabulary you need to start exploring the rest of this chapter. +Don't worry if some concepts are too abstract, advanced or impractical for you at this point: +this book is intended to be skimmed on the first read. +Refer back to it later for more detailed explanations as you start building your own awesome projects in Bevy! + +[`Entity`]: https://docs.rs/bevy/latest/bevy/ecs/entity/struct.Entity.html +[`Component`]: https://docs.rs/bevy/latest/bevy/ecs/component/trait.Component.html +[`World`]: https://docs.rs/bevy/latest/bevy/ecs/world/struct.World.html +[`SystemParam`]: https://docs.rs/bevy/latest/bevy/ecs/system/trait.SystemParam.html +[`System`]: https://docs.rs/bevy/latest/bevy/ecs/system/trait.System.html +[`Sprite`]: https://docs.rs/bevy/latest/bevy/sprite/struct.Sprite.html +[`SpriteBundle`]: https://docs.rs/bevy/latest/bevy/sprite/struct.SpriteBundle.html +[`Res`]: https://docs.rs/bevy/latest/bevy/ecs/system/struct.Res.html +[`Query`]: https://docs.rs/bevy/latest/bevy/ecs/system/struct.Query.html +[`Commands`]: https://docs.rs/bevy/latest/bevy/ecs/system/struct.Commands.html diff --git a/content/learn/book/ecs/change-detection/_index.md b/content/learn/book/ecs/change-detection/_index.md new file mode 100644 index 0000000000..f90e99a869 --- /dev/null +++ b/content/learn/book/ecs/change-detection/_index.md @@ -0,0 +1,7 @@ ++++ +title = "Reliable Change Detection" +weight = 6 +template = "docs-section.html" +[extra] +status = 'hidden' ++++ diff --git a/content/learn/book/ecs/commands/_index.md b/content/learn/book/ecs/commands/_index.md new file mode 100644 index 0000000000..a3fc516a12 --- /dev/null +++ b/content/learn/book/ecs/commands/_index.md @@ -0,0 +1,9 @@ ++++ +title = "Manipulating Entities With Commands" +weight = 4 +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ diff --git a/content/learn/book/ecs/entities-components/_index.md b/content/learn/book/ecs/entities-components/_index.md new file mode 100644 index 0000000000..93b5fd133f --- /dev/null +++ b/content/learn/book/ecs/entities-components/_index.md @@ -0,0 +1,376 @@ ++++ +title = "Entities Have Components" +weight = 1 +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +**Entities** are the fundamental objects of your game world, whizzing around, storing cameras, being controlled by the player or tracking the state of a button. +On its own, the [`Entity`] type is a simple identifer: it has neither behavior nor data. +Components store this data, and define the overlapping categories that the entity belongs to. + +Informally, we use the term "entity" to refer to the conceptual entry in our [`World`]: all of the component data with the correct identifier, although it's very rare to use all of the data for a single entity at once. +If you're an experienced programmer, you can reason about the [`World`] as something like a (very fast) [`HashMap`] from [`Entity`] to a collection of components. + +[`Entity`]: https://docs.rs/bevy/latest/bevy/ecs/entity/struct.Entity.html +[`HashMap`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html +[`World`]: https://docs.rs/bevy/latest/bevy/ecs/world/struct.World.html + +## Spawning and Despawning Entities + +Before you can do much of anything in Bevy, you'll need to **spawn** your first entity, adding it to the app's [`World`]. +Once entities exist, they can likewise be despawned, deleting all of the data stored in their components and removing it from the world. + +Spawning and despawning entities can have far-reaching effects, and so cannot be done immediately (unless you are using an [exclusive system](../exclusive-world-access)). +As a result, we must use [`Commands`], which queue up work to do later. + +```rust +# use bevy::ecs::system::Commands; + +// The `Commands` system parameter allows us to generate commands +// which operate on the `World` once all of the current systems have finished running +fn spawning_system(mut commands: Commands){ + // Spawning a single entity with no components + commands.spawn(()); + // Getting the `Entity` identifier of a new entity + let my_entity = commands.spawn(()).id(); + // Selecting and then despawning the just-spawned second entity + commands.entity(my_entity).despawn(); +} +``` + +[`Commands`]: https://docs.rs/bevy/latest/bevy/ecs/system/struct.Commands.html + +## Working With Components + +Spawning an entity doesn't add any behavior or create a "physical object" in our game like it might in other engines. +Instead, all it does is provide us an [`Entity`] identifer for a collection of component data. + +In order to make this useful, we need to be able to add, remove and modify component data for each entity. + +### Defining Components + +To define a component type, we simply implement the [`Component`] [trait](https://doc.rust-lang.org/book/ch10-02-traits.html) for a Rust type of our choice. +You will almost always want to use the `#[derive(Component)]` [macro](https://doc.rust-lang.org/reference/attributes/derive.html) to do this for you; which quickly and reliably generates the correct trait implementation. + +With the theory out of the way, let's define some components! + +```rust +# use bevy::ecs::component::Component; + +// This is a "unit struct", which holds no data of its own. +#[derive(Component)] +struct Combatant; + +// This simple component wraps a u8 in a tuple struct +#[derive(Component)] +struct Life(u8); + +// Naming your components' fields makes them easier to refer to +#[derive(Component)] +struct Stats { + strength: u8, + dexterity: u8, + intelligence: u8, +} + +// Enum components are great for storing mutually exclusive states +#[derive(Component)] +enum Allegiance { + Friendly, + Hostile +} +``` + +[`Component`]: https://docs.rs/bevy/latest/bevy/ecs/component/trait.Component.html + +### Spawning Entities With Components + +Now that we have some components defined, let's try adding them to our entities using [`Commands`]. + +```rust +# use bevy::ecs::prelude::*; +# +# #[derive(Component)] +# struct Combatant; +# +# #[derive(Component)] +# struct Life(u8); +# +# #[derive(Component)] +# struct Stats { +# strength: u8, +# dexterity: u8, +# intelligence: u8, +# } +# +# #[derive(Component)] +# enum Allegiance { +# Friendly, +# Hostile +# } + +fn spawn_combatants_system(mut commands: Commands) { + commands.spawn(( + // This inserts a data-less `Combatant` component into the entity we're spawning + Combatant, + // We configure starting component values by passing in concrete instances of our types + Life(10), + // By chaining .insert method calls like this, we continue to add more components to our entity + // Instances of named structs are constructed with {field_name: value} + Stats { + strength: 15, + dexterity: 10, + intelligence: 8, + }, + // Instances of enums are created by picking one of their variants + Allegiance::Friendly, + )); + + // We've ended our Commands method chain using a ;, + // and so now we can create a second entity + // by calling .spawn() again + commands.spawn(( + Combatant, + Life(10), + Stats { + strength: 17, + dexterity: 8, + intelligence: 6, + }, + Allegiance::Hostile, + )); +} +``` + +### Adding and Removing Components + +Once an entity is spawned, you can use [`Commands`] to add and remove components from them dynamically. + +```rust +# use bevy::ecs::prelude::*; +# +# #[derive(Component)] +# struct Combatant; + +#[derive(Component)] +struct InCombat; + +// This query returns the `Entity` identifier of all entities +// that have the `Combatant` component but do not yet have the `InCombat` component +fn start_combat_system(query: Query, Without)>, mut commands: Commands){ + for entity in query.iter() { + // The component will be inserted at the end of the current stage + commands.entity(entity).insert(InCombat); + } +} + +// Now to undo our hard work +fn end_combat_system(query: Query, With)>, mut commands: Commands){ + for entity in query.iter() { + // The component will be removed at the end of the current stage + // It is provided as a type parameter, + // as we do not need to know a specific value in order to remove a component of the correct type + commands.entity(entity).remove::(); + } +} +``` + +Entities can only ever store one component of each type: inserting another component of the same type will instead overwrite the existing data. + +## Bundles + +As you might guess, the one-at-a-time component insertion syntax can be both tedious and error-prone as your project grows. +To get around this, Bevy allows you to group components into **component bundles**. +These are defined by deriving the [`Bundle`] trait for a struct; turning each of its fields into a distinct component on your entity when the bundle is inserted. + +Let's try rewriting that code from above. + +```rust +# use bevy::prelude::*; +# +# #[derive(Component)] +# struct Combatant; +# +# #[derive(Component)] +# struct Life(u8); +# +# #[derive(Component)] +# struct Stats { +# strength: u8, +# dexterity: u8, +# intelligence: u8, +# } +# +# #[derive(Component)] +# enum Allegiance { +# Friendly, +# Hostile +# } + +#[derive(Bundle)] +struct CombatantBundle { + combatant: Combatant, + life: Life, + stats: Stats, + allegiance: Allegiance, +} + +// We can add new methods to our bundle type that return Self +// to create principled APIs for entity creation. +// The Default trait is the standard tool for creating +// new struct instances without configuration +impl Default for CombatantBundle { + fn default() -> Self { + CombatantBundle { + combatant: Combatant, + life: Life(10), + stats: Stats { + strength: 10, + dexterity: 10, + intelligence: 10, + }, + allegiance: Allegiance::Hostile, + } + } +} + +fn spawn_combatants_system(mut commands: Commands) { + commands.spawn(( + // We're using struct-update syntax to modify + // the instance of `CombatantBundle` returned by its default() method + // See the page on Rust Tips and Tricks at the end of this chapter for more info! + CombatantBundle{ + stats: Stats { + strength: 15, + dexterity: 10, + intelligence: 8, + }, + allegiance: Allegiance::Friendly, + ..default() + }, + )); + + commands.spawn(( + CombatantBundle{ + stats: Stats { + strength: 17, + dexterity: 8, + intelligence: 6, + }, + allegiance: Allegiance::Hostile, + ..default() + }, + )); +} +``` + +[`Bundle`]: https://docs.rs/bevy/latest/bevy/ecs/bundle/trait.Bundle.html + +### Nested Bundles + +As your game grows further in complexity, you may find that you want to reuse various bundles across entities that share some but not all behavior. +One of the tools you can use to do so is **nested bundles**; embedding one bundle of components within another. +Try to stick to a single layer of nesting at most; multiple layers of nesting can get quite confusing. +Including duplicate components in your bundles in this way will cause a panic. + +With those caveats out of the way, let's take a look at the syntax by converting the bundle above to a nested one by creating a bundle of components that deal with related functionality. + +```rust +# use bevy::prelude::*; +# +# #[derive(Component)] +# struct Combatant; +# +# #[derive(Component)] +# struct Life(u8); +# +# #[derive(Component)] +# struct Attack(u8); +# +# #[derive(Component)] +# struct Defense(u8); +# +# #[derive(Component)] +# enum Allegiance { +# Friendly, +# Hostile +# } + +#[derive(Bundle)] +struct AttackableBundle{ + life: Life, + attack: Attack, + defense: Defense, +} + +#[derive(Bundle)] +struct CombatantBundle { + combatant: Combatant, + // The #[bundle] attribute marks our attackable_bundle field as a bundle (rather than a component), + // allowing Bevy to properly flatten it out when building the final entity + // #[bundle] // commenting out to make code validator run; should be looked at TODO + attackable_bundle: AttackableBundle, + allegiance: Allegiance, +} + +impl Default for CombatantBundle { + fn default() -> Self { + CombatantBundle { + combatant: Combatant, + attackable_bundle: AttackableBundle { + life: Life(10), + attack: Attack(5), + defense: Defense(1), + }, + allegiance: Allegiance::Hostile, + } + } +} +``` + +## Component Design + +Over time, the Bevy community has converged on a few standard pieces of advice for how to structure and define component data: + +- try to keep your components relatively small + - combine common functionality into bundles, not large components + - small modular systems based on common behavior work well + - reducing the amount of data stored improves cache performance and system-parallelism + - keep it as a single component if you need to maintain invariants (such as current life is always less than or equal to max life) + - keep it as a single component if you need methods that operate across several pieces of data (e.g. computing the distance between two points) +- simple methods on components are a good tool for clean, testable code + - logic that is inherent to how the component works (like rolling dice or healing life points) is a great fit + - logic that will only be repeated once generally belongs in systems + - methods make it easier to understand the actual gameplay logic in your systems, and fix bugs in a single place +- marker components are incredibly valuable for extending your design + - it is very common to want to quickly look for "all entities that are a `Tower`", or "all entities that are `Chilled` + - filtering by component presence/absence is (generally) faster and clearer than looping through a list of boolean values + - try to model meaningful groups at several levels of abstraction / along multiple axes: e.g. `Unit`, `Ant`, `Combatant` +- enum components are very expressive, and help reduce bugs + - enums can hold different data in each variant, allowing you to capture information effectively + - if you have a fixed number of options for a value, store it as an enum +- implementing traits like [`Add`] or [`Display`] can provide useful behavior in an idiomatic way +- use [`Deref`] and [`DerefMut`] for tuple structs with a single item ([newtypes]) + - this allows you to access the internal data with `*my_component` instead of `my_component.0` + - more importantly, this allows you to call methods that belong to the wrapped type directly on your component +- define builder methods for your [`Bundle`] types that return [`Self`] + - this is useful to define a friendly interface for how entities of this sort tend to vary + - not as useful as you might hope for upholding invariants; components will be able to be accidentally modified independently later +- use [struct update syntax] to modify component bundles + - [`..default()`] is a particularly common idiom, to modify a struct from its default values +- consider definining traits for related components + - this allows you to ensure a consistent interface + - this can be very powerful in combination with generic systems that use trait bounds + +[`Add`]: https://doc.rust-lang.org/std/ops/trait.Add.html +[`Display`]: https://doc.rust-lang.org/std/path/struct.Display.html +[`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html +[`DerefMut`]: https://doc.rust-lang.org/std/ops/trait.DerefMut.html +[`Self`]: https://doc.rust-lang.org/reference/paths.html#self-1 +[`..default()`]: https://docs.rs/bevy/latest/bevy/prelude/fn.default.html +[newtypes]: https://doc.rust-lang.org/rust-by-example/generics/new_types.html +[struct update syntax]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax diff --git a/content/learn/book/ecs/exclusive-world-access/_index.md b/content/learn/book/ecs/exclusive-world-access/_index.md new file mode 100644 index 0000000000..6f6446a915 --- /dev/null +++ b/content/learn/book/ecs/exclusive-world-access/_index.md @@ -0,0 +1,17 @@ ++++ +title = "Exclusive World Access" +weight = 8 +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Show how to work with a raw world +* Discuss and demonstrate custom commands +* Discuss and demonstrate exclusive systems +* Discuss and demonstrate `NonSend` resources +{% end %} diff --git a/content/learn/book/ecs/filtering-queries/_index.md b/content/learn/book/ecs/filtering-queries/_index.md new file mode 100644 index 0000000000..b18d4cad0a --- /dev/null +++ b/content/learn/book/ecs/filtering-queries/_index.md @@ -0,0 +1,7 @@ ++++ +title = "Filtering Queries" +weight = 5 +template = "docs-section.html" +[extra] +status = 'hidden' ++++ diff --git a/content/learn/book/ecs/generic-systems/_index.md b/content/learn/book/ecs/generic-systems/_index.md new file mode 100644 index 0000000000..a8e0e95330 --- /dev/null +++ b/content/learn/book/ecs/generic-systems/_index.md @@ -0,0 +1,7 @@ ++++ +title = "Generic Systems" +weight = 7 +template = "docs-section.html" +[extra] +status = 'hidden' ++++ diff --git a/content/learn/book/ecs/resources/_index.md b/content/learn/book/ecs/resources/_index.md new file mode 100644 index 0000000000..dd33a6cb08 --- /dev/null +++ b/content/learn/book/ecs/resources/_index.md @@ -0,0 +1,18 @@ ++++ +title = "Resources Are Global Singletons" +weight = 3 +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Explain what a resource is +* Explain why you might want a resource +* Show how to create and access Resources +* Show how to modify resources +* Compare and contrast with `query.single()` +{% end %} diff --git a/content/learn/book/ecs/systems-queries/_index.md b/content/learn/book/ecs/systems-queries/_index.md new file mode 100644 index 0000000000..3f211fa1ac --- /dev/null +++ b/content/learn/book/ecs/systems-queries/_index.md @@ -0,0 +1,9 @@ ++++ +title = "Systems Access Data Through Queries" +weight = 2 +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ diff --git a/content/learn/book/game-logic/_index.md b/content/learn/book/game-logic/_index.md new file mode 100644 index 0000000000..dfa531c44a --- /dev/null +++ b/content/learn/book/game-logic/_index.md @@ -0,0 +1,15 @@ ++++ +title = "Game Logic" +weight = 3 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Discuss what's in this chapter +{% end %} diff --git a/content/learn/book/game-logic/async-tasks/_index.md b/content/learn/book/game-logic/async-tasks/_index.md new file mode 100644 index 0000000000..1b8f6dce4b --- /dev/null +++ b/content/learn/book/game-logic/async-tasks/_index.md @@ -0,0 +1,18 @@ ++++ +title = "Async Tasks" +weight = 6 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Motivate why you may want to do things asynchronously +* Refresh on async, point to other resources +* Explain how bevy_tasks works +* Demonstrate how to use async tasks +{% end %} diff --git a/content/learn/book/game-logic/custom-runners-headless-operations/_index.md b/content/learn/book/game-logic/custom-runners-headless-operations/_index.md new file mode 100644 index 0000000000..14ab82909e --- /dev/null +++ b/content/learn/book/game-logic/custom-runners-headless-operations/_index.md @@ -0,0 +1,18 @@ ++++ +title = "Custom Runners and Headless Operation" +weight = 7 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Explain custom runners, and how they can be useful for interop +* Demonstrate how to change the execution model +* Demonstrate how to step through the app one tick at a time +* Demonstrate how to connect Bevy to a CLI +{% end %} diff --git a/content/learn/book/game-logic/events/_index.md b/content/learn/book/game-logic/events/_index.md new file mode 100644 index 0000000000..eb35f29102 --- /dev/null +++ b/content/learn/book/game-logic/events/_index.md @@ -0,0 +1,18 @@ ++++ +title = "Events" +weight = 2 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Explain what events are, and why you might want to use them +* Demonstrate EventWriter, EventReader and app.add_event +* Explain automatic cleanup, show how to bypass it +* Demonstrate the component-as-event pattern +{% end %} diff --git a/content/learn/book/game-logic/run-criteria/_index.md b/content/learn/book/game-logic/run-criteria/_index.md new file mode 100644 index 0000000000..bfa23fefb9 --- /dev/null +++ b/content/learn/book/game-logic/run-criteria/_index.md @@ -0,0 +1,18 @@ ++++ +title = "Run Criteria and Fixed Timestep" +weight = 5 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Explain what a run criteria is +* Discuss evaluation model +* Discuss FixedTimestep run criteria +* Explain how to use .pipe +{% end %} diff --git a/content/learn/book/game-logic/states/_index.md b/content/learn/book/game-logic/states/_index.md new file mode 100644 index 0000000000..b3e833e9b9 --- /dev/null +++ b/content/learn/book/game-logic/states/_index.md @@ -0,0 +1,18 @@ ++++ +title = "States" +weight = 3 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Explain what a state is, and why you might want to use it +* Demonstrate how to use simple state +* Discuss queue model, and demonstrate how to use it +* Discuss state caveats: implemented as a run criteria, can't use across stages +{% end %} diff --git a/content/learn/book/game-logic/system-ordering/_index.md b/content/learn/book/game-logic/system-ordering/_index.md new file mode 100644 index 0000000000..9627e14074 --- /dev/null +++ b/content/learn/book/game-logic/system-ordering/_index.md @@ -0,0 +1,19 @@ ++++ +title = "Stages and System Ordering" +weight = 1 +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Explain stages +* Explain startup stages +* Explain explicit system ordering +* Explain SystemSets in the context of labels +* Explain ambiguities +* Steal from [ECS Guide](https://github.com/bevyengine/bevy/blob/main/examples/ecs/ecs_guide.rs#L282) +{% end %} diff --git a/content/learn/book/game-logic/time-timers/_index.md b/content/learn/book/game-logic/time-timers/_index.md new file mode 100644 index 0000000000..528dfb5b45 --- /dev/null +++ b/content/learn/book/game-logic/time-timers/_index.md @@ -0,0 +1,20 @@ ++++ +title = "Time and Timers" +weight = 4 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +status = 'hidden' ++++ + +{% todo() %} + +* Explain Time resource +* Demonstrate how to access the Time resource +* Discuss Duration and instant in Rust +* Demonstrate how to use a timers +* Demonstrate how to store timers in components +* Mention FixedTimestep run criteria +{% end %} diff --git a/content/learn/book/getting-started/_index.md b/content/learn/book/getting-started/_index.md index 1de686807c..4ef57895de 100644 --- a/content/learn/book/getting-started/_index.md +++ b/content/learn/book/getting-started/_index.md @@ -1,64 +1,9 @@ +++ title = "Getting Started" -weight = 2 -sort_by = "weight" +weight = 1 template = "docs-section.html" page_template = "docs-section.html" insert_anchor_links = "right" +[extra] +status = 'hidden' +++ - -This section will help you get started on your Bevy journey as quickly as possible. It will walk you through setting up your development environment and writing a simple Bevy app. - -## Quick Start - -If you want to dive in immediately and you already have a working Rust setup, feel free to follow this "quick start" guide. Otherwise, move on to the next page. - -Note: the "fast compiles" setup is on the next page, so you might want to read that section first. - -### Try the Examples - -1. Clone the [Bevy repo](https://github.com/bevyengine/bevy): - - ```sh - git clone https://github.com/bevyengine/bevy - ``` - -2. Navigate to the new "bevy" folder - - ```sh - cd bevy - ``` - -3. Switch to the correct Bevy version (as the default is the git main development branch) - - ```sh - # use the latest Bevy release - git checkout latest - # or a specific version - git checkout v0.11.0 - ``` - -4. Try the examples in the [examples folder](https://github.com/bevyengine/bevy/tree/latest/examples#examples) - - ```sh - cargo run --example breakout - ``` - -### Add Bevy as a Dependency - -Bevy is [available as a library on crates.io](https://crates.io/crates/bevy). - -The easiest way to add it to your project is to use `cargo add`: - -```sh -cargo add bevy -``` - -Alternatively, you can manually add it to your project's Cargo.toml like this: - -```toml -[dependencies] -bevy = "0.12" # make sure this is the latest version -``` - -Make sure to use the latest `bevy` crate version ([![Crates.io](https://img.shields.io/crates/v/bevy.svg)](https://crates.io/crates/bevy)). diff --git a/content/learn/book/getting-started/app-appbuilder-world/_index.md b/content/learn/book/getting-started/app-appbuilder-world/_index.md new file mode 100644 index 0000000000..54b37be54e --- /dev/null +++ b/content/learn/book/getting-started/app-appbuilder-world/_index.md @@ -0,0 +1,7 @@ ++++ +title = "App, Appbuilder, and World" +weight = 3 +template = "docs-section.html" +[extra] +status = 'hidden' ++++ diff --git a/content/learn/book/getting-started/apps/_index.md b/content/learn/book/getting-started/apps/_index.md deleted file mode 100644 index 953a04993a..0000000000 --- a/content/learn/book/getting-started/apps/_index.md +++ /dev/null @@ -1,26 +0,0 @@ -+++ -title = "Apps" -weight = 2 -sort_by = "weight" -template = "docs-section.html" -page_template = "docs-section.html" -insert_anchor_links = "right" -+++ - -Bevy programs are referred to as {{rust_type(type="struct", crate="bevy_app", name="App", no_mod=true)}}s. The simplest Bevy app looks like this: - -```rs -use bevy::prelude::*; - -fn main() { - App::new().run(); -} -``` - -Nice and simple right? Copy the code above into your ```main.rs``` file, then run: - -```sh -cargo run -``` - -in your project folder. You will notice that ... nothing happens. This is because we haven't told our app to do anything yet! Apps are just empty shells capable of running our application logic. Let's add some logic to our App using Bevy ECS. diff --git a/content/learn/book/getting-started/bevy-community/_index.md b/content/learn/book/getting-started/bevy-community/_index.md new file mode 100644 index 0000000000..6992a57a69 --- /dev/null +++ b/content/learn/book/getting-started/bevy-community/_index.md @@ -0,0 +1,7 @@ ++++ +title = "The Bevy Community" +weight = 5 +template = "docs-section.html" +[extra] +status = 'hidden' ++++ diff --git a/content/learn/book/getting-started/installation/_index.md b/content/learn/book/getting-started/installation/_index.md new file mode 100644 index 0000000000..6b1e8674f5 --- /dev/null +++ b/content/learn/book/getting-started/installation/_index.md @@ -0,0 +1,7 @@ ++++ +title = "Installing Rust and Bevy" +weight = 2 +template = "docs-section.html" +[extra] +status = 'hidden' ++++ diff --git a/content/learn/book/getting-started/modular-plugins/_index.md b/content/learn/book/getting-started/modular-plugins/_index.md new file mode 100644 index 0000000000..ba3cb9dc04 --- /dev/null +++ b/content/learn/book/getting-started/modular-plugins/_index.md @@ -0,0 +1,7 @@ ++++ +title = "Plugins as Modular Building Blocks" +weight = 4 +template = "docs-section.html" +[extra] +status = 'hidden' ++++ \ No newline at end of file diff --git a/content/learn/book/getting-started/plugins/_index.md b/content/learn/book/getting-started/plugins/_index.md deleted file mode 100644 index a8b62132f6..0000000000 --- a/content/learn/book/getting-started/plugins/_index.md +++ /dev/null @@ -1,81 +0,0 @@ -+++ -title = "Plugins" -weight = 4 -sort_by = "weight" -template = "docs-section.html" -page_template = "docs-section.html" -insert_anchor_links = "right" -+++ - -One of Bevy's core principles is modularity. All Bevy engine features are implemented as plugins. This includes internal features like the renderer, but games themselves are also implemented as plugins! This empowers developers to pick and choose which features they want. Don't need a UI? Don't register the {{rust_type(type="struct" crate="bevy_ui", name="UiPlugin")}}. Want to build a headless server? Don't register the {{rust_type(type="struct" crate="bevy_render" name="RenderPlugin")}}. - -This also means you are free to replace any components you don't like. If you feel the need, you are welcome to build your own {{rust_type(type="struct" crate="bevy_ui" name="UiPlugin")}}, but consider [contributing it back to Bevy](/learn/book/contributing) if you think it would be useful! - -However, most developers don't need a custom experience and just want the "full engine" experience with no hassle. For this, Bevy provides a set of "default plugins". - -## Bevy's Default Plugins - -Let's make our app more interesting by adding the "default Bevy plugins". -`add_plugins(DefaultPlugins)` adds the features most people expect from an engine, such as a 2D / 3D renderer, asset loading, a UI system, windows, and input. - -```rs -fn main() { - App::new() - .add_plugins(DefaultPlugins) - .add_systems(Startup, add_people) - .add_systems(Update, (hello_world, greet_people)) - .run(); -} -``` - -Once again run `cargo run`. - -You should hopefully notice two things: - -* **A window should pop up**. This is because we now have {{rust_type(type="struct" crate="bevy_window" name="WindowPlugin")}}, which defines the window interface (but doesn't actually know how to make windows), and {{rust_type(type="struct" crate="bevy_winit" name="WinitPlugin")}} which uses the [winit library](https://github.com/rust-windowing/winit) to create a window using your OS's native window API. -* **Your console is now full of "hello" messages**: This is because {{rust_type(type="struct" crate="bevy" name="DefaultPlugins")}} adds an "event loop" to our application. Our App's ECS Schedule now runs in a loop once per "frame". We will resolve the console spam in a moment. - -## Creating your first plugin - -For better organization, let's move all of our "hello" logic to a plugin. To create a plugin we just need to implement the {{rust_type(type="trait" name="Plugin" crate="bevy_app" no_mod=true)}} interface. Add the following code to your `main.rs` file: - -```rs -pub struct HelloPlugin; - -impl Plugin for HelloPlugin { - fn build(&self, app: &mut App) { - // add things to your app here - } -} -``` - -Then register the plugin in your App like this: - -```rs -fn main() { - App::new() - .add_plugins((DefaultPlugins, HelloPlugin)) - .add_systems(Startup, add_people) - .add_systems(Update, (hello_world, greet_people)) - .run(); -} -``` - -Note `add_plugins` can add any number of plugins (or plugin groups like `DefaultPlugins`) by passing in a tuple of them. Now all that's left is to move our systems into `HelloPlugin`, which is just a matter of cut and paste. The `app` variable in our plugin's `build()` function is the same builder type we use in our `main()` function: - -```rs -impl Plugin for HelloPlugin { - fn build(&self, app: &mut App) { - app.add_systems(Startup, add_people) - .add_systems(Update, (hello_world, greet_people)); - } -} - -fn main() { - App::new() - .add_plugins((DefaultPlugins, HelloPlugin)) - .run(); -} -``` - -Try running the app again. It should do exactly what it did before. In the next section, we'll fix the "hello" spam using Resources. diff --git a/content/learn/book/getting-started/resources/_index.md b/content/learn/book/getting-started/resources/_index.md deleted file mode 100644 index fc1f9700ee..0000000000 --- a/content/learn/book/getting-started/resources/_index.md +++ /dev/null @@ -1,66 +0,0 @@ -+++ -title = "Resources" -weight = 5 -sort_by = "weight" -template = "docs-section.html" -page_template = "docs-section.html" -insert_anchor_links = "right" -+++ - -**Entities** and **Components** are great for representing complex, query-able groups of data. But most Apps will also require "globally unique" data of some kind. In Bevy ECS, we represent globally unique data using **Resources**. - -Here are some examples of data that could be encoded as **Resources**: - -* Elapsed Time -* Asset Collections (sounds, textures, meshes) -* Renderers - -## Tracking Time with Resources - -Let's solve our App's "hello spam" problem by only printing "hello" once every two seconds. We'll do this by using the {{rust_type(type="struct" crate="bevy_time" name="Time")}} resource, which is automatically added to our App via `add_plugins(DefaultPlugins)`. - -For simplicity, remove the `hello_world` system from your App. This way we only need to adapt the `greet_people` system. - -Resources are accessed in much the same way that we access components. You can access the `Time` resource in your system like this: - -```rs -fn greet_people(time: Res