From 764eb1f522d0f2ab988fe400a91e4b1c8ca6b0df Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Wed, 24 Jan 2024 10:12:28 -0500 Subject: [PATCH 1/9] Stub out the migration guide --- content/learn/migration-guides/0.12-0.13/_index.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 content/learn/migration-guides/0.12-0.13/_index.md diff --git a/content/learn/migration-guides/0.12-0.13/_index.md b/content/learn/migration-guides/0.12-0.13/_index.md new file mode 100644 index 0000000000..ac8e6df5a5 --- /dev/null +++ b/content/learn/migration-guides/0.12-0.13/_index.md @@ -0,0 +1,14 @@ ++++ +title = "0.12 to 0.13" +weight = 8 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +long_title = "Migration Guide: 0.12 to 0.13" ++++ + +Bevy relies heavily on improvements in the Rust language and compiler. +As a result, the Minimum Supported Rust Version (MSRV) is "the latest stable release" of Rust. +
From 1a09b10f599d4d86a69135f11a877c19889fc8ba Mon Sep 17 00:00:00 2001 From: IceSentry Date: Fri, 16 Feb 2024 15:12:57 -0500 Subject: [PATCH 2/9] 0.13: generate migration guide (#965) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: Doonv <58695417+doonv@users.noreply.github.com> Co-authored-by: Joona Aalto Co-authored-by: TrialDragon <31419708+TrialDragon@users.noreply.github.com> Co-authored-by: Alice Cecile Co-authored-by: KDecay 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: 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: 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 Co-authored-by: cuppar Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com> Co-authored-by: Henriquelay <37563861+Henriquelay@users.noreply.github.com> --- .gitattributes | 32 + .github/bors.toml | 10 - .github/linters/.markdown-lint.yml | 10 +- .github/workflows/build-wasm-examples.yml | 8 +- .github/workflows/ci.yml | 133 +- .github/workflows/deploy.yml | 6 +- .github/workflows/update-screenshots.yml | 12 +- .gitignore | 4 +- .markdownlint.yml | 10 +- CONTRIBUTING.md | 186 + 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 | 8 + .../learn/advanced-examples/sudoku/_index.md | 7 + .../text-adventure/_index.md | 7 + content/learn/book/_index.md | 10 +- content/learn/book/assets/_index.md | 14 + content/learn/book/assets/custom-assets.md | 12 + content/learn/book/assets/hot-reloading.md | 13 + content/learn/book/assets/loading-assets.md | 14 + .../learn/book/assets/scenes-reflection.md | 16 + .../learn/book/assets/working-with-handles.md | 15 + content/learn/book/audio/_index.md | 14 + content/learn/book/audio/audio-basics.md | 13 + .../book/development-practices/_index.md | 13 + .../boilerplate-reduction.md | 13 + .../development-practices/error-handling.md | 14 + .../development-practices/fast-compiles.md | 54 + .../organizing-your-code.md | 14 + .../book/development-practices/testing.md | 15 + content/learn/book/ecs/_index.md | 83 + content/learn/book/ecs/change-detection.md | 6 + content/learn/book/ecs/commands.md | 7 + content/learn/book/ecs/entities-components.md | 368 ++ .../learn/book/ecs/exclusive-world-access.md | 15 + content/learn/book/ecs/filtering-queries.md | 6 + content/learn/book/ecs/generic-systems.md | 6 + content/learn/book/ecs/resources.md | 16 + content/learn/book/ecs/systems-queries.md | 7 + content/learn/book/game-logic/_index.md | 13 + content/learn/book/game-logic/async-tasks.md | 15 + .../custom-runners-headless-operations.md | 15 + content/learn/book/game-logic/events.md | 15 + content/learn/book/game-logic/run-criteria.md | 15 + content/learn/book/game-logic/states.md | 15 + .../learn/book/game-logic/system-ordering.md | 17 + content/learn/book/game-logic/time-timers.md | 17 + content/learn/book/getting-started/_index.md | 62 +- .../getting-started/app-appbuilder-world.md | 6 + .../learn/book/getting-started/apps/_index.md | 26 - .../book/getting-started/bevy-community.md | 6 + .../book/getting-started/installation.md | 6 + .../book/getting-started/modular-plugins.md | 6 + .../book/getting-started/plugins/_index.md | 81 - .../book/getting-started/resources/_index.md | 66 - .../learn/book/getting-started/why-bevy.md | 6 + content/learn/book/graphics/2d/_index.md | 14 + .../learn/book/graphics/2d/sprite-sheets.md | 12 + content/learn/book/graphics/2d/sprites.md | 12 + content/learn/book/graphics/3d/_index.md | 13 + content/learn/book/graphics/3d/meshes.md | 13 + content/learn/book/graphics/3d/pbr.md | 13 + content/learn/book/graphics/_index.md | 14 + content/learn/book/graphics/cameras.md | 14 + .../book/graphics/parent-child-hierarchy.md | 14 + .../graphics/rendering-internals/_index.md | 13 + .../rendering-internals/shader-basics.md | 13 + content/learn/book/graphics/transforms.md | 14 + content/learn/book/graphics/windows.md | 15 + content/learn/book/input/_index.md | 14 + content/learn/book/input/gamepad.md | 14 + content/learn/book/input/input-basics.md | 15 + content/learn/book/input/keyboard.md | 14 + content/learn/book/input/mouse.md | 15 + content/learn/book/input/touch.md | 14 + .../book/performance-optimizations/_index.md | 14 + .../component-storage.md | 14 + .../diagnostics-benchmarking.md | 14 + .../book/performance-optimizations/indexes.md | 16 + .../parallel-iteration.md | 16 + content/learn/book/platforms/_index.md | 14 + content/learn/book/platforms/android.md | 14 + content/learn/book/platforms/ios.md | 14 + content/learn/book/platforms/web.md | 14 + .../learn/book/plugin-development/_index.md | 4 +- content/learn/book/ui/_index.md | 14 + content/learn/book/ui/ui-basics.md | 19 + content/learn/links.toml | 6 +- .../{0.10-0.11/_index.md => 0.10-to-0.11.md} | 3100 ++++++------ .../{0.11-0.12/_index.md => 0.11-to-0.12.md} | 3106 ++++++------ .../learn/migration-guides/0.12-to-0.13.md | 1712 +++++++ .../{0.4-0.5/_index.md => 0.4-to-0.5.md} | 24 +- .../{0.5-0.6/_index.md => 0.5-to-0.6.md} | 86 +- .../{0.6-0.7/_index.md => 0.6-to-0.7.md} | 5 +- .../{0.7-0.8/_index.md => 0.7-to-0.8.md} | 5 +- .../{0.8-0.9/_index.md => 0.8-to-0.9.md} | 1635 ++++--- .../{0.9-0.10/_index.md => 0.9-to-0.10.md} | 2467 +++++----- content/learn/migration-guides/_index.md | 5 +- .../_index.md => introduction.md} | 4 +- .../quick-start/3d-puzzle-game/_index.md | 8 + content/learn/quick-start/_index.md | 7 + content/learn/quick-start/breakout/_index.md | 8 + .../contributing/_index.md | 9 +- .../contributing/code.md} | 6 +- .../contributing/docs.md} | 25 +- .../learn/quick-start/falling-sand/_index.md | 8 + .../quick-start/getting-started/_index.md | 64 + .../learn/quick-start/getting-started/apps.md | 41 + .../getting-started/ecs.md} | 75 +- .../quick-start/getting-started/plugins.md | 101 + .../quick-start/getting-started/resources.md | 81 + .../getting-started/setup.md} | 33 +- .../_index.md => quick-start/introduction.md} | 15 +- .../_index.md => quick-start/next-steps.md} | 9 +- .../learn/quick-start/plugin-development.md | 159 + .../troubleshooting.md} | 7 +- .../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-assets/src/bin/generate.rs | 2 +- generate-assets/src/gitlab_client.rs | 152 +- generate-assets/src/lib.rs | 51 +- generate-community/src/bin/generate.rs | 21 +- generate-community/src/bin/validate.rs | 4 +- generate-community/src/lib.rs | 8 +- generate-errors/src/bin/generate.rs | 2 +- generate-errors/src/lib.rs | 2 +- generate-release/src/changelog.rs | 124 +- generate-release/src/github_client.rs | 585 ++- generate-release/src/helpers.rs | 226 +- generate-release/src/main.rs | 4 +- generate-release/src/markdown.rs | 268 +- generate-release/src/migration_guide.rs | 218 +- generate-release/src/release_notes.rs | 168 +- generate-release/src/release_notes_website.rs | 174 +- 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/elements/_table.scss | 18 + sass/pages/_assets.scss | 96 +- sass/pages/_community.scss | 6 +- sass/pages/_docs.scss | 68 +- sass/pages/_migration_guide.scss | 66 +- sass/site.scss | 4 +- static/assets/Pixeljam.png | Bin 0 -> 378 bytes static/web-streams-adapter-0.1.0.mjs | 559 +++ static/web-streams-polyfill-3.2.1.mjs | 4203 +++++++++++++++++ templates/assets.html | 100 +- templates/docs-base.html | 161 + templates/docs-page.html | 28 + templates/docs-section.html | 130 +- templates/example.html | 151 +- templates/examples.html | 72 +- templates/index.html | 8 +- templates/layouts/base.html | 267 +- templates/macros/assets.html | 120 +- templates/macros/docs.html | 82 +- 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 | 68 + write-rustdoc-hide-lines/Cargo.toml | 11 + write-rustdoc-hide-lines/README.md | 17 + .../src/code_block_definition.rs | 267 ++ write-rustdoc-hide-lines/src/formatter.rs | 269 ++ write-rustdoc-hide-lines/src/hidden_ranges.rs | 128 + write-rustdoc-hide-lines/src/lib.rs | 3 + write-rustdoc-hide-lines/src/main.rs | 16 + .../write_rustdoc_hide_lines.sh | 3 + 199 files changed, 18022 insertions(+), 8166 deletions(-) create mode 100644 .gitattributes delete mode 100644 .github/bors.toml 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.md create mode 100644 content/learn/book/assets/hot-reloading.md create mode 100644 content/learn/book/assets/loading-assets.md create mode 100644 content/learn/book/assets/scenes-reflection.md create mode 100644 content/learn/book/assets/working-with-handles.md create mode 100644 content/learn/book/audio/_index.md create mode 100644 content/learn/book/audio/audio-basics.md create mode 100644 content/learn/book/development-practices/_index.md create mode 100644 content/learn/book/development-practices/boilerplate-reduction.md create mode 100644 content/learn/book/development-practices/error-handling.md create mode 100644 content/learn/book/development-practices/fast-compiles.md create mode 100644 content/learn/book/development-practices/organizing-your-code.md create mode 100644 content/learn/book/development-practices/testing.md create mode 100644 content/learn/book/ecs/_index.md create mode 100644 content/learn/book/ecs/change-detection.md create mode 100644 content/learn/book/ecs/commands.md create mode 100644 content/learn/book/ecs/entities-components.md create mode 100644 content/learn/book/ecs/exclusive-world-access.md create mode 100644 content/learn/book/ecs/filtering-queries.md create mode 100644 content/learn/book/ecs/generic-systems.md create mode 100644 content/learn/book/ecs/resources.md create mode 100644 content/learn/book/ecs/systems-queries.md create mode 100644 content/learn/book/game-logic/_index.md create mode 100644 content/learn/book/game-logic/async-tasks.md create mode 100644 content/learn/book/game-logic/custom-runners-headless-operations.md create mode 100644 content/learn/book/game-logic/events.md create mode 100644 content/learn/book/game-logic/run-criteria.md create mode 100644 content/learn/book/game-logic/states.md create mode 100644 content/learn/book/game-logic/system-ordering.md create mode 100644 content/learn/book/game-logic/time-timers.md create mode 100644 content/learn/book/getting-started/app-appbuilder-world.md delete mode 100644 content/learn/book/getting-started/apps/_index.md create mode 100644 content/learn/book/getting-started/bevy-community.md create mode 100644 content/learn/book/getting-started/installation.md create mode 100644 content/learn/book/getting-started/modular-plugins.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.md create mode 100644 content/learn/book/graphics/2d/_index.md create mode 100644 content/learn/book/graphics/2d/sprite-sheets.md create mode 100644 content/learn/book/graphics/2d/sprites.md create mode 100644 content/learn/book/graphics/3d/_index.md create mode 100644 content/learn/book/graphics/3d/meshes.md create mode 100644 content/learn/book/graphics/3d/pbr.md create mode 100644 content/learn/book/graphics/_index.md create mode 100644 content/learn/book/graphics/cameras.md create mode 100644 content/learn/book/graphics/parent-child-hierarchy.md create mode 100644 content/learn/book/graphics/rendering-internals/_index.md create mode 100644 content/learn/book/graphics/rendering-internals/shader-basics.md create mode 100644 content/learn/book/graphics/transforms.md create mode 100644 content/learn/book/graphics/windows.md create mode 100644 content/learn/book/input/_index.md create mode 100644 content/learn/book/input/gamepad.md create mode 100644 content/learn/book/input/input-basics.md create mode 100644 content/learn/book/input/keyboard.md create mode 100644 content/learn/book/input/mouse.md create mode 100644 content/learn/book/input/touch.md create mode 100644 content/learn/book/performance-optimizations/_index.md create mode 100644 content/learn/book/performance-optimizations/component-storage.md create mode 100644 content/learn/book/performance-optimizations/diagnostics-benchmarking.md create mode 100644 content/learn/book/performance-optimizations/indexes.md create mode 100644 content/learn/book/performance-optimizations/parallel-iteration.md create mode 100644 content/learn/book/platforms/_index.md create mode 100644 content/learn/book/platforms/android.md create mode 100644 content/learn/book/platforms/ios.md create mode 100644 content/learn/book/platforms/web.md create mode 100644 content/learn/book/ui/_index.md create mode 100644 content/learn/book/ui/ui-basics.md rename content/learn/migration-guides/{0.10-0.11/_index.md => 0.10-to-0.11.md} (97%) rename content/learn/migration-guides/{0.11-0.12/_index.md => 0.11-to-0.12.md} (97%) create mode 100644 content/learn/migration-guides/0.12-to-0.13.md rename content/learn/migration-guides/{0.4-0.5/_index.md => 0.4-to-0.5.md} (88%) rename content/learn/migration-guides/{0.5-0.6/_index.md => 0.5-to-0.6.md} (50%) rename content/learn/migration-guides/{0.6-0.7/_index.md => 0.6-to-0.7.md} (99%) rename content/learn/migration-guides/{0.7-0.8/_index.md => 0.7-to-0.8.md} (99%) rename content/learn/migration-guides/{0.8-0.9/_index.md => 0.8-to-0.9.md} (97%) rename content/learn/migration-guides/{0.9-0.10/_index.md => 0.9-to-0.10.md} (97%) rename content/learn/migration-guides/{introduction/_index.md => introduction.md} (89%) 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 (77%) rename content/learn/{book/contributing/code/_index.md => quick-start/contributing/code.md} (93%) rename content/learn/{book/contributing/docs/_index.md => quick-start/contributing/docs.md} (57%) 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.md rename content/learn/{book/getting-started/ecs/_index.md => quick-start/getting-started/ecs.md} (71%) create mode 100644 content/learn/quick-start/getting-started/plugins.md create mode 100644 content/learn/quick-start/getting-started/resources.md rename content/learn/{book/getting-started/setup/_index.md => quick-start/getting-started/setup.md} (83%) rename content/learn/{book/introduction/_index.md => quick-start/introduction.md} (60%) rename content/learn/{book/next-steps/_index.md => quick-start/next-steps.md} (80%) create mode 100644 content/learn/quick-start/plugin-development.md rename content/learn/{book/troubleshooting/_index.md => quick-start/troubleshooting.md} (95%) create mode 100644 sass/components/_todo.scss create mode 100644 sass/elements/_table.scss create mode 100644 static/assets/Pixeljam.png create mode 100644 static/web-streams-adapter-0.1.0.mjs create mode 100644 static/web-streams-polyfill-3.2.1.mjs create mode 100644 templates/docs-base.html create mode 100644 templates/docs-page.html 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/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..270ab23cab --- /dev/null +++ b/.gitattributes @@ -0,0 +1,32 @@ +# From: https://docs.github.com/en/github/getting-started-with-github/configuring-git-to-handle-line-endings +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.rs text eol=lf +*.toml text eol=lf +*.frag text eol=lf +*.vert text eol=lf +*.wgsl text eol=lf +*.md text eof=lf +*.html text eof=lf +*.scss text eof=lf +*.js text eof=lf +*.mjs text eof=lf +*.svg text eof=lf +*.txt text eof=lf +*.xml text eof=lf +*.yml text eof=lf +*.sh text eof=lf + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary +*.gif binary +*.webp binary +*.ttf binary +*.woff binary +*.woff2 binary +*.eot binary +*.mp4 binary diff --git a/.github/bors.toml b/.github/bors.toml deleted file mode 100644 index da9c575ce9..0000000000 --- a/.github/bors.toml +++ /dev/null @@ -1,10 +0,0 @@ -status = [ - "build-website", - "generate-wasm-examples", - "generate-assets", - "generate-errors", - "generate-community", - "markdownlint", -] - -use_squash_merge = true diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml index 6d963c55d3..15a497ff09 100644 --- a/.github/linters/.markdown-lint.yml +++ b/.github/linters/.markdown-lint.yml @@ -1,5 +1,5 @@ -# Keep synced with duplicate in project root - -line-length: false -no-inline-html: false -no-trailing-punctuation: false +# Keep synced with duplicate in project root + +line-length: false +no-inline-html: false +no-trailing-punctuation: false diff --git a/.github/workflows/build-wasm-examples.yml b/.github/workflows/build-wasm-examples.yml index 83301bce53..45a1d0c64e 100644 --- a/.github/workflows/build-wasm-examples.yml +++ b/.github/workflows/build-wasm-examples.yml @@ -18,14 +18,14 @@ jobs: steps: - name: Checkout Bevy latest tag - uses: actions/checkout@master + uses: actions/checkout@v4 with: repository: 'bevyengine/bevy' ref: 'latest' # temporary: fetch tools from main branch - name: Checkout Bevy Tools - uses: actions/checkout@master + uses: actions/checkout@v4 with: repository: 'bevyengine/bevy' ref: 'main' @@ -52,7 +52,7 @@ jobs: cargo run -p example-showcase -- --per-page ${{ env.PER_PAGE }} --page ${{ matrix.page }} build-wasm-examples --content-folder wasm-examples --api ${{ matrix.api }} --website-hacks --optimize-size - name: Upload Generated Files - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.api }}-examples-${{ matrix.page }} path: wasm-examples @@ -67,7 +67,7 @@ jobs: steps: - name: Download all artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 - name: Group examples in one folder run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8811fd5935..4099a97020 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,12 +9,77 @@ on: - 'trying' jobs: + markdownlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + # Full git history is needed to get a proper list of changed files within `super-linter` + fetch-depth: 0 + - name: Run Markdown Lint + uses: docker://ghcr.io/github/super-linter:slim-v4 + env: + VALIDATE_ALL_CODEBASE: false + VALIDATE_MARKDOWN: true + DEFAULT_BRANCH: main + + test-code-examples: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Install alsa and udev + run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev + + - name: Build & run doc tests + run: cd code-validation && cargo test + + lint-tools: + runs-on: ubuntu-latest + env: + TOOLS: | + code-validation generate-assets generate-community generate-errors generate-release write-rustdoc-hide-lines + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Install alsa and udev + run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev + + - name: Check formatting + run: | + for CRATE in $TOOLS; do + cd $CRATE + + echo Checking $CRATE + cargo fmt --check + + cd .. + done + + - name: Check clippy + run: | + for CRATE in $TOOLS; do + cd $CRATE + + echo Checking $CRATE + cargo clippy -- -Dwarnings + + cd .. + done + generate-assets: + needs: [markdownlint, test-code-examples, lint-tools] runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v4 - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: | ~/.cargo/bin/ @@ -26,10 +91,10 @@ jobs: - name: Get cache key id: cache-key - run: echo "::set-output name=key::$(date +'%Y-%m-%d')" + run: echo "key=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT - name: Get crates.io datadump from cache - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: generate-assets/data key: ${{ runner.os }}-${{ steps.cache-key.outputs.key }} @@ -40,18 +105,19 @@ jobs: export GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} && ./generate_assets.sh - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v4 with: name: generated-assets path: content/assets retention-days: 1 generate-errors: + needs: [markdownlint, test-code-examples, lint-tools] runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v4 - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: | ~/.cargo/bin/ @@ -66,24 +132,32 @@ jobs: cd generate-errors && ./generate_errors.sh - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v4 with: name: generated-errors path: content/learn/errors retention-days: 1 generate-wasm-examples: + needs: [markdownlint, test-code-examples, lint-tools] runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v4 + + - name: "Clone Bevy" + run: > + cd generate-wasm-examples && + ./clone_bevy.sh - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: | ~/.cargo/bin/ ~/.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 @@ -95,24 +169,25 @@ jobs: cd generate-wasm-examples && ./generate_wasm_examples.sh - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v4 with: name: generated-wasm-examples path: content/examples retention-days: 1 - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v4 with: name: generated-wasm-examples-webgpu path: content/examples-webgpu retention-days: 1 generate-community: + needs: [markdownlint, test-code-examples, lint-tools] runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v4 - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: | ~/.cargo/bin/ @@ -127,53 +202,39 @@ jobs: cd generate-community && ./generate_community.sh - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v4 with: name: generated-community path: content/community/people retention-days: 1 - markdownlint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - # Full git history is needed to get a proper list of changed files within `super-linter` - fetch-depth: 0 - - name: Run Markdown Lint - uses: docker://ghcr.io/github/super-linter:slim-v4 - env: - VALIDATE_ALL_CODEBASE: false - VALIDATE_MARKDOWN: true - DEFAULT_BRANCH: main - build-website: runs-on: ubuntu-latest - needs: [markdownlint, generate-assets, generate-errors, generate-wasm-examples, generate-community] + needs: [markdownlint, test-code-examples, lint-tools, generate-assets, generate-errors, generate-wasm-examples, generate-community] steps: - - uses: actions/checkout@master - - uses: actions/download-artifact@master + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 with: name: generated-assets path: content/assets - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v4 with: name: generated-errors path: content/learn/errors - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v4 with: name: generated-wasm-examples path: content/examples - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v4 with: name: generated-wasm-examples-webgpu path: content/examples-webgpu - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v4 with: name: generated-community path: content/community/people diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 8284efe396..f8c7db5909 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -11,14 +11,14 @@ jobs: build_and_deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v4 - name: Get current date id: date - run: echo "::set-output name=date::$(date +'%Y-%m-%d')" + run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT - name: Cache multiple crates.io datadump - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: generate-assets/data key: ${{ runner.os }}-${{ steps.date.outputs.date }} diff --git a/.github/workflows/update-screenshots.yml b/.github/workflows/update-screenshots.yml index 7e343ab64b..9484fac9e3 100644 --- a/.github/workflows/update-screenshots.yml +++ b/.github/workflows/update-screenshots.yml @@ -17,14 +17,14 @@ jobs: steps: - name: Checkout Bevy latest tag - uses: actions/checkout@master + uses: actions/checkout@v4 with: repository: 'bevyengine/bevy' ref: 'latest' # temporary: fetch tools from main branch - name: Checkout Bevy Tools - uses: actions/checkout@master + uses: actions/checkout@v4 with: repository: 'bevyengine/bevy' ref: 'main' @@ -56,7 +56,7 @@ jobs: xvfb-run cargo run -p example-showcase -- --page ${{ matrix.page }} --per-page ${{ env.PER_PAGE }} run --screenshot --in-ci - name: Upload Generated Files - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: screenshots-${{ matrix.page }} path: screenshots @@ -71,10 +71,10 @@ jobs: steps: - name: Clone bevy-website repo - uses: actions/checkout@master + uses: actions/checkout@v4 - name: Download all artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 - name: Move examples to the correct folder run: | @@ -87,7 +87,7 @@ jobs: done - name: Create Pull Request - uses: peter-evans/create-pull-request@v5 + uses: peter-evans/create-pull-request@v6 with: delete-branch: true branch-suffix: random 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/.markdownlint.yml b/.markdownlint.yml index 6601d4e409..afff32bd5a 100644 --- a/.markdownlint.yml +++ b/.markdownlint.yml @@ -1,5 +1,5 @@ -# Keep synced with duplicate in `.github/linters` folder - -line-length: false -no-inline-html: false -no-trailing-punctuation: false +# Keep synced with duplicate in `.github/linters` folder + +line-length: false +no-inline-html: false +no-trailing-punctuation: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..61cb49eb55 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,186 @@ +# 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 hide lines of code in Zola Rust code blocks of the book you should: a. Mark each line you wish to hide with a `#` with an empty space afterwards like `# //...line_of_code_here...` although you were hiding lines in rustdoc. b. Run the [utility tool](write-rustdoc-hide-lines) in `/write_rustdoc-hide-lines/` named `write_rustdoc_hide_lines.sh`. +13. 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..c7f3acc83e 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](/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..1768769841 --- /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.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.md")] + mod apps {} + #[doc = include_str!("../../content/learn/quick-start/getting-started/ecs.md")] + mod ecs {} + #[doc = include_str!("../../content/learn/quick-start/getting-started/plugins.md")] + mod plugins {} + #[doc = include_str!("../../content/learn/quick-start/getting-started/resources.md")] + mod resources {} + } + #[doc = include_str!("../../content/learn/quick-start/contributing/_index.md")] + mod contributing { + #[doc = include_str!("../../content/learn/quick-start/contributing/docs.md")] + mod docs {} + #[doc = include_str!("../../content/learn/quick-start/contributing/code.md")] + mod code {} + } + #[doc = include_str!("../../content/learn/quick-start/plugin-development.md")] + mod plugin_development {} + #[doc = include_str!("../../content/learn/quick-start/troubleshooting.md")] + mod troubleshooting {} + #[doc = include_str!("../../content/learn/quick-start/next-steps.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.md")] + mod custom_assets {} + #[doc = include_str!("../../content/learn/book/assets/hot-reloading.md")] + mod hot_reloading {} + #[doc = include_str!("../../content/learn/book/assets/loading-assets.md")] + mod loading_assets {} + #[doc = include_str!("../../content/learn/book/assets/scenes-reflection.md")] + mod scenes_reflection {} + #[doc = include_str!("../../content/learn/book/assets/working-with-handles.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.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.md")] + mod boilerplate_reduction {} + #[doc = include_str!("../../content/learn/book/development-practices/error-handling.md")] + mod error_handling {} + #[doc = include_str!("../../content/learn/book/development-practices/fast-compiles.md")] + mod fast_compiles {} + #[doc = include_str!("../../content/learn/book/development-practices/organizing-your-code.md")] + mod organizing_your_code {} + #[doc = include_str!("../../content/learn/book/development-practices/testing.md")] + mod testing {} + } + + #[doc = include_str!("../../content/learn/book/ecs/_index.md")] + mod ecs { + #[doc = include_str!("../../content/learn/book/ecs/change-detection.md")] + mod change_detection {} + #[doc = include_str!("../../content/learn/book/ecs/commands.md")] + mod commands {} + #[doc = include_str!("../../content/learn/book/ecs/entities-components.md")] + mod entities_components {} + #[doc = include_str!("../../content/learn/book/ecs/exclusive-world-access.md")] + mod exclusive_world_access {} + #[doc = include_str!("../../content/learn/book/ecs/filtering-queries.md")] + mod filtering_queries {} + #[doc = include_str!("../../content/learn/book/ecs/generic-systems.md")] + mod generic_systems {} + #[doc = include_str!("../../content/learn/book/ecs/resources.md")] + mod resources {} + #[doc = include_str!("../../content/learn/book/ecs/systems-queries.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.md")] + mod async_tasks {} + #[doc = include_str!("../../content/learn/book/game-logic/custom-runners-headless-operations.md")] + mod custom_runners_headless_operation {} + #[doc = include_str!("../../content/learn/book/game-logic/events.md")] + mod events {} + #[doc = include_str!("../../content/learn/book/game-logic/run-criteria.md")] + mod run_criteria {} + #[doc = include_str!("../../content/learn/book/game-logic/states.md")] + mod states {} + #[doc = include_str!("../../content/learn/book/game-logic/system-ordering.md")] + mod system_ordering {} + #[doc = include_str!("../../content/learn/book/game-logic/time-timers.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.md")] + mod app_appbuilder_world {} + #[doc = include_str!("../../content/learn/book/getting-started/bevy-community.md")] + mod bevy_community {} + #[doc = include_str!("../../content/learn/book/getting-started/installation.md")] + mod installation {} + #[doc = include_str!("../../content/learn/book/getting-started/modular-plugins.md")] + mod modular_plugins {} + #[doc = include_str!("../../content/learn/book/getting-started/why-bevy.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.md")] + mod sprite_sheets {} + #[doc = include_str!("../../content/learn/book/graphics/2d/sprites.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.md")] + mod meshes {} + #[doc = include_str!("../../content/learn/book/graphics/3d/pbr.md")] + mod pbr {} + } + #[doc = include_str!("../../content/learn/book/graphics/cameras.md")] + mod cameras {} + #[doc = include_str!("../../content/learn/book/graphics/parent-child-hierarchy.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.md")] + mod shader_basics {} + } + #[doc = include_str!("../../content/learn/book/graphics/transforms.md")] + mod transforms {} + #[doc = include_str!("../../content/learn/book/graphics/windows.md")] + mod windows {} + } + + #[doc = include_str!("../../content/learn/book/input/_index.md")] + mod input { + #[doc = include_str!("../../content/learn/book/input/gamepad.md")] + mod gamepad {} + #[doc = include_str!("../../content/learn/book/input/input-basics.md")] + mod input_basics {} + #[doc = include_str!("../../content/learn/book/input/keyboard.md")] + mod keyboard {} + #[doc = include_str!("../../content/learn/book/input/mouse.md")] + mod mouse {} + #[doc = include_str!("../../content/learn/book/input/touch.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.md")] + mod component_storage {} + #[doc = include_str!("../../content/learn/book/performance-optimizations/diagnostics-benchmarking.md")] + mod diagnostics_benchmarking {} + #[doc = include_str!("../../content/learn/book/performance-optimizations/indexes.md")] + mod indexes {} + #[doc = include_str!("../../content/learn/book/performance-optimizations/parallel-iteration.md")] + mod parallel_iteration {} + } + + #[doc = include_str!("../../content/learn/book/platforms/_index.md")] + mod platforms { + #[doc = include_str!("../../content/learn/book/platforms/android.md")] + mod android {} + #[doc = include_str!("../../content/learn/book/platforms/ios.md")] + mod ios {} + #[doc = include_str!("../../content/learn/book/platforms/web.md")] + mod web {} + } + + #[doc = include_str!("../../content/learn/book/ui/_index.md")] + mod ui { + #[doc = include_str!("../../content/learn/book/ui/ui-basics.md")] + mod ui_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..612f22e2b0 --- /dev/null +++ b/content/learn/advanced-examples/_index.md @@ -0,0 +1,8 @@ ++++ +title = "Advanced Examples" +template = "docs-section.html" +page_template = "docs-page.html" +[extra] +public_draft = 877 +status = "hidden" ++++ diff --git a/content/learn/advanced-examples/sudoku/_index.md b/content/learn/advanced-examples/sudoku/_index.md new file mode 100644 index 0000000000..551dec70c9 --- /dev/null +++ b/content/learn/advanced-examples/sudoku/_index.md @@ -0,0 +1,7 @@ ++++ +title = "Sudoku" +template = "docs-section.html" +[extra] +weight = 2 +status = "hidden" ++++ 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..85e73c6993 --- /dev/null +++ b/content/learn/advanced-examples/text-adventure/_index.md @@ -0,0 +1,7 @@ ++++ +title = "Text Adventure" +template = "docs-section.html" +[extra] +weight = 1 +status = "hidden" ++++ diff --git a/content/learn/book/_index.md b/content/learn/book/_index.md index 1906ee994e..ec5c61a17e 100644 --- a/content/learn/book/_index.md +++ b/content/learn/book/_index.md @@ -1,8 +1,10 @@ +++ title = "Book" -sort_by = "weight" template = "docs-section.html" -page_template = "docs-section.html" -redirect_to = "learn/book/introduction" +page_template = "docs-page.html" insert_anchor_links = "right" -+++ \ No newline at end of file +redirect_to = "learn/book/getting-started" +[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..789aaf12de --- /dev/null +++ b/content/learn/book/assets/_index.md @@ -0,0 +1,14 @@ ++++ +title = "Assets" +template = "docs-section.html" +insert_anchor_links = "right" +[extra] +weight = 5 +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.md b/content/learn/book/assets/custom-assets.md new file mode 100644 index 0000000000..120f790b18 --- /dev/null +++ b/content/learn/book/assets/custom-assets.md @@ -0,0 +1,12 @@ ++++ +title = "Custom Assets" +insert_anchor_links = "right" +[extra] +weight = 3 +status = 'hidden' ++++ + +{% todo() %} + +* Demonstrate how to write a custom asset loader. +{% end %} diff --git a/content/learn/book/assets/hot-reloading.md b/content/learn/book/assets/hot-reloading.md new file mode 100644 index 0000000000..6b49acbbb1 --- /dev/null +++ b/content/learn/book/assets/hot-reloading.md @@ -0,0 +1,13 @@ ++++ +title = "Hot Reloading" +insert_anchor_links = "right" +[extra] +weight = 4 +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.md b/content/learn/book/assets/loading-assets.md new file mode 100644 index 0000000000..a01ac0a62a --- /dev/null +++ b/content/learn/book/assets/loading-assets.md @@ -0,0 +1,14 @@ ++++ +title = "Loading Assets" +insert_anchor_links = "right" +[extra] +weight = 1 +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.md b/content/learn/book/assets/scenes-reflection.md new file mode 100644 index 0000000000..d64c00d1f5 --- /dev/null +++ b/content/learn/book/assets/scenes-reflection.md @@ -0,0 +1,16 @@ ++++ +title = "Scenes and Reflection" +insert_anchor_links = "right" +[extra] +weight = 5 +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.md b/content/learn/book/assets/working-with-handles.md new file mode 100644 index 0000000000..a942db4770 --- /dev/null +++ b/content/learn/book/assets/working-with-handles.md @@ -0,0 +1,15 @@ ++++ +title = "Working With Handles" +insert_anchor_links = "right" +[extra] +weight = 2 +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..3964784e65 --- /dev/null +++ b/content/learn/book/audio/_index.md @@ -0,0 +1,14 @@ ++++ +title = "Audio" +template = "docs-section.html" +insert_anchor_links = "right" +[extra] +weight = 7 +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.md b/content/learn/book/audio/audio-basics.md new file mode 100644 index 0000000000..c25b9243ce --- /dev/null +++ b/content/learn/book/audio/audio-basics.md @@ -0,0 +1,13 @@ ++++ +title = "Audio basics" +insert_anchor_links = "right" +[extra] +weight = 1 +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..045f3b0a1f --- /dev/null +++ b/content/learn/book/development-practices/_index.md @@ -0,0 +1,13 @@ ++++ +title = "Development Practices" +template = "docs-section.html" +insert_anchor_links = "right" +[extra] +weight = 9 +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.md b/content/learn/book/development-practices/boilerplate-reduction.md new file mode 100644 index 0000000000..06399b8e8e --- /dev/null +++ b/content/learn/book/development-practices/boilerplate-reduction.md @@ -0,0 +1,13 @@ ++++ +title = "Boilerplate Reduction" +insert_anchor_links = "right" +[extra] +weight = 5 +status = 'hidden' ++++ + +{% todo() %} + +* Link to resources on macros +* Discuss custom system parameters +{% end %} diff --git a/content/learn/book/development-practices/error-handling.md b/content/learn/book/development-practices/error-handling.md new file mode 100644 index 0000000000..5f02dc0f1d --- /dev/null +++ b/content/learn/book/development-practices/error-handling.md @@ -0,0 +1,14 @@ ++++ +title = "Error Handling" +insert_anchor_links = "right" +[extra] +weight = 4 +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.md b/content/learn/book/development-practices/fast-compiles.md new file mode 100644 index 0000000000..270e01060a --- /dev/null +++ b/content/learn/book/development-practices/fast-compiles.md @@ -0,0 +1,54 @@ ++++ +title = "Fast Compiles" +insert_anchor_links = "right" +[extra] +weight = 2 +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.toml) 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.md b/content/learn/book/development-practices/organizing-your-code.md new file mode 100644 index 0000000000..12dea11d37 --- /dev/null +++ b/content/learn/book/development-practices/organizing-your-code.md @@ -0,0 +1,14 @@ ++++ +title = "Organizing Your Code" +insert_anchor_links = "right" +[extra] +weight = 1 +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.md b/content/learn/book/development-practices/testing.md new file mode 100644 index 0000000000..7d68526efc --- /dev/null +++ b/content/learn/book/development-practices/testing.md @@ -0,0 +1,15 @@ ++++ +title = "Testing" +insert_anchor_links = "right" +[extra] +weight = 3 +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..a95dc16366 --- /dev/null +++ b/content/learn/book/ecs/_index.md @@ -0,0 +1,83 @@ ++++ +title = "Entities, Components and Systems" +template = "docs-section.html" +insert_anchor_links = "right" +[extra] +weight = 2 +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.md b/content/learn/book/ecs/change-detection.md new file mode 100644 index 0000000000..8e84b4d953 --- /dev/null +++ b/content/learn/book/ecs/change-detection.md @@ -0,0 +1,6 @@ ++++ +title = "Reliable Change Detection" +[extra] +weight = 6 +status = 'hidden' ++++ diff --git a/content/learn/book/ecs/commands.md b/content/learn/book/ecs/commands.md new file mode 100644 index 0000000000..ab594b350a --- /dev/null +++ b/content/learn/book/ecs/commands.md @@ -0,0 +1,7 @@ ++++ +title = "Manipulating Entities With Commands" +insert_anchor_links = "right" +[extra] +weight = 4 +status = 'hidden' ++++ diff --git a/content/learn/book/ecs/entities-components.md b/content/learn/book/ecs/entities-components.md new file mode 100644 index 0000000000..404c06a333 --- /dev/null +++ b/content/learn/book/ecs/entities-components.md @@ -0,0 +1,368 @@ ++++ +title = "Entities Have Components" +insert_anchor_links = "right" +[extra] +weight = 1 +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,hide_lines=1 +# 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,hide_lines=1 +# 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,hide_lines=1-20 +# 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,hide_lines=1-4 +# 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,hide_lines=1-20 +# 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,hide_lines=1-19 +# 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.md b/content/learn/book/ecs/exclusive-world-access.md new file mode 100644 index 0000000000..cd296d8add --- /dev/null +++ b/content/learn/book/ecs/exclusive-world-access.md @@ -0,0 +1,15 @@ ++++ +title = "Exclusive World Access" +insert_anchor_links = "right" +[extra] +weight = 8 +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.md b/content/learn/book/ecs/filtering-queries.md new file mode 100644 index 0000000000..5f9a89df1e --- /dev/null +++ b/content/learn/book/ecs/filtering-queries.md @@ -0,0 +1,6 @@ ++++ +title = "Filtering Queries" +[extra] +weight = 5 +status = 'hidden' ++++ diff --git a/content/learn/book/ecs/generic-systems.md b/content/learn/book/ecs/generic-systems.md new file mode 100644 index 0000000000..cdf27de71d --- /dev/null +++ b/content/learn/book/ecs/generic-systems.md @@ -0,0 +1,6 @@ ++++ +title = "Generic Systems" +[extra] +weight = 7 +status = 'hidden' ++++ diff --git a/content/learn/book/ecs/resources.md b/content/learn/book/ecs/resources.md new file mode 100644 index 0000000000..a95ec3bded --- /dev/null +++ b/content/learn/book/ecs/resources.md @@ -0,0 +1,16 @@ ++++ +title = "Resources Are Global Singletons" +insert_anchor_links = "right" +[extra] +weight = 3 +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.md b/content/learn/book/ecs/systems-queries.md new file mode 100644 index 0000000000..32ca33bec1 --- /dev/null +++ b/content/learn/book/ecs/systems-queries.md @@ -0,0 +1,7 @@ ++++ +title = "Systems Access Data Through Queries" +insert_anchor_links = "right" +[extra] +weight = 2 +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..bd7d718cc3 --- /dev/null +++ b/content/learn/book/game-logic/_index.md @@ -0,0 +1,13 @@ ++++ +title = "Game Logic" +template = "docs-section.html" +insert_anchor_links = "right" +[extra] +weight = 3 +status = 'hidden' ++++ + +{% todo() %} + +* Discuss what's in this chapter +{% end %} diff --git a/content/learn/book/game-logic/async-tasks.md b/content/learn/book/game-logic/async-tasks.md new file mode 100644 index 0000000000..bdd234a72e --- /dev/null +++ b/content/learn/book/game-logic/async-tasks.md @@ -0,0 +1,15 @@ ++++ +title = "Async Tasks" +insert_anchor_links = "right" +[extra] +weight = 6 +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.md b/content/learn/book/game-logic/custom-runners-headless-operations.md new file mode 100644 index 0000000000..f6373dc79f --- /dev/null +++ b/content/learn/book/game-logic/custom-runners-headless-operations.md @@ -0,0 +1,15 @@ ++++ +title = "Custom Runners and Headless Operation" +insert_anchor_links = "right" +[extra] +weight = 7 +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.md b/content/learn/book/game-logic/events.md new file mode 100644 index 0000000000..60e6070c22 --- /dev/null +++ b/content/learn/book/game-logic/events.md @@ -0,0 +1,15 @@ ++++ +title = "Events" +insert_anchor_links = "right" +[extra] +weight = 2 +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.md b/content/learn/book/game-logic/run-criteria.md new file mode 100644 index 0000000000..b14f8e8bfd --- /dev/null +++ b/content/learn/book/game-logic/run-criteria.md @@ -0,0 +1,15 @@ ++++ +title = "Run Criteria and Fixed Timestep" +insert_anchor_links = "right" +[extra] +weight = 5 +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.md b/content/learn/book/game-logic/states.md new file mode 100644 index 0000000000..ebaa2933e9 --- /dev/null +++ b/content/learn/book/game-logic/states.md @@ -0,0 +1,15 @@ ++++ +title = "States" +insert_anchor_links = "right" +[extra] +weight = 3 +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.md b/content/learn/book/game-logic/system-ordering.md new file mode 100644 index 0000000000..f12105daa1 --- /dev/null +++ b/content/learn/book/game-logic/system-ordering.md @@ -0,0 +1,17 @@ ++++ +title = "Stages and System Ordering" +insert_anchor_links = "right" +[extra] +weight = 1 +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.md b/content/learn/book/game-logic/time-timers.md new file mode 100644 index 0000000000..fb06672488 --- /dev/null +++ b/content/learn/book/game-logic/time-timers.md @@ -0,0 +1,17 @@ ++++ +title = "Time and Timers" +insert_anchor_links = "right" +[extra] +weight = 4 +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..1cbebc0f56 100644 --- a/content/learn/book/getting-started/_index.md +++ b/content/learn/book/getting-started/_index.md @@ -1,64 +1,8 @@ +++ title = "Getting Started" -weight = 2 -sort_by = "weight" template = "docs-section.html" -page_template = "docs-section.html" insert_anchor_links = "right" +[extra] +weight = 1 +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.md b/content/learn/book/getting-started/app-appbuilder-world.md new file mode 100644 index 0000000000..a58bb4f787 --- /dev/null +++ b/content/learn/book/getting-started/app-appbuilder-world.md @@ -0,0 +1,6 @@ ++++ +title = "App, Appbuilder, and World" +[extra] +weight = 3 +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.md b/content/learn/book/getting-started/bevy-community.md new file mode 100644 index 0000000000..503f882e81 --- /dev/null +++ b/content/learn/book/getting-started/bevy-community.md @@ -0,0 +1,6 @@ ++++ +title = "The Bevy Community" +[extra] +weight = 5 +status = 'hidden' ++++ diff --git a/content/learn/book/getting-started/installation.md b/content/learn/book/getting-started/installation.md new file mode 100644 index 0000000000..00b1a80a59 --- /dev/null +++ b/content/learn/book/getting-started/installation.md @@ -0,0 +1,6 @@ ++++ +title = "Installing Rust and Bevy" +[extra] +weight = 2 +status = 'hidden' ++++ diff --git a/content/learn/book/getting-started/modular-plugins.md b/content/learn/book/getting-started/modular-plugins.md new file mode 100644 index 0000000000..5361b535ba --- /dev/null +++ b/content/learn/book/getting-started/modular-plugins.md @@ -0,0 +1,6 @@ ++++ +title = "Plugins as Modular Building Blocks" +[extra] +weight = 4 +status = 'hidden' ++++ 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

Past Sponsors

diff --git a/templates/layouts/base.html b/templates/layouts/base.html index 584f00dee5..c59e2b57b6 100644 --- a/templates/layouts/base.html +++ b/templates/layouts/base.html @@ -4,139 +4,164 @@ {% set current_path = current_path | default(value="/") %} {% if section and section.title %} - {% if section.path is starting_with("/learn/book/") %} - {% set page_title = "Bevy Book: " ~ section.title %} - {% elif section.path is starting_with("/assets") %} - {% set page_title = "Bevy Assets" %} - {% else %} - {% set page_title = section.title %} - {% endif %} +{% if section.path is starting_with("/learn/book/") %} +{% set page_title = "Bevy Book: " ~ section.title %} +{% elif section.path is starting_with("/assets") %} +{% set page_title = "Bevy Assets" %} +{% else %} +{% set page_title = section.title %} +{% endif %} {% elif page and page.title %} - {% set page_title = page.title %} +{% if page.path is starting_with("/learn/book/") %} +{% set page_title = "Bevy Book: " ~ page.title %} +{% elif page.path is starting_with("/assets") %} +{% set page_title = "Bevy Assets" %} {% else %} - {% set page_title = "Bevy Engine"%} +{% set page_title = page.title %} +{% endif %} +{% else %} +{% set page_title = "Bevy Engine"%} {% endif %} {% if section and section.path %} - {% set path = "/" ~ section.path %} +{% set path = "/" ~ section.path %} {% elif page and page.path %} - {% set path = "/" ~ page.path %} +{% set path = "/" ~ page.path %} {% else %} - {% set path = ""%} +{% set path = ""%} {% endif %} {% if section %} - {% if section.path is starting_with("/learn/book/") %} - {% set show_nav_toggle = true %} - {% elif section.path is starting_with("/learn/migration-guides/") %} - {% set show_nav_toggle = true %} - {% elif section.path is starting_with("/assets/") %} - {% set show_nav_toggle = true %} - {% endif %} +{% if section.path is starting_with("/learn/book/") %} +{% set show_nav_toggle = true %} +{% elif section.path is starting_with("/learn/migration-guides/") %} +{% set show_nav_toggle = true %} +{% elif section.path is starting_with("/assets/") %} +{% set show_nav_toggle = true %} +{% endif %} +{% elif page %} +{% if page.path is starting_with("/learn/book/") or page.path is starting_with("/learn/migration-guides/") or page.path +is starting_with("/assets/") %} +{% set show_nav_toggle = true %} +{% endif %} {% endif %} - - - - - - - - - - - - {{page_title}} - {% block head_extensions %} {% endblock %} - - -
- -
-
- - -
- -
- {% if section and section.extra.header_message %} - {{section.extra.header_message}} - {% elif page and page.extra.header_message %} - {{page.extra.header_message}} - {% elif section and section.path is starting_with("/learn/book/") %} - The Book - {% elif section and section.path is starting_with("/learn/migration-guides/") %} - Migration Guides - {% elif section and section.path is starting_with("/news/") %} - News - {% elif page and page.path is starting_with("/news/") %} - News - {% else %} - Features - {% endif %} -
-
- {% block mobile_page_menu_state %}{% endblock %} - - -
-
-
-
- {% if section %} - {{ public_draft::warning(section=section) }} - {% endif %} - {% block content %}{% endblock %} -
-
+ + + + + + + + + + + + + {{page_title}} + {% block head_extensions %} {% endblock %} + + + +
+ +
+
+ + +
+ +
+ {% if section and section.extra.header_message %} + {{section.extra.header_message}} + {% elif page and page.extra.header_message %} + {{page.extra.header_message}} + {% elif section and section.path is starting_with("/learn/book/") or page and page.path is + starting_with("/learn/book/") %} + The Book + {% elif section and section.path is starting_with("/learn/quick-start/") or page and page.path is + starting_with("/learn/quick-start/") %} + Quick Start + {% elif section and section.path is starting_with("/learn/migration-guides/") or page and page.path is + starting_with("/learn/migration-guides/") %} + Migration Guides + {% elif section and section.path is starting_with("/news/") %} + News + {% elif page and page.path is starting_with("/news/") %} + News + {% else %} + Features + {% endif %} +
- - - + {% block mobile_page_menu_state %}{% endblock %} + + +
+
+
+
+ {% if section %} + {{ public_draft::warning(section=section) }} + {% elif page %} + {{ public_draft::warning(section=page) }} + {% endif %} + {% block content %}{% endblock %} +
+
+
+ + + + \ No newline at end of file diff --git a/templates/macros/assets.html b/templates/macros/assets.html index e7a6082cc7..be47fd6c6e 100644 --- a/templates/macros/assets.html +++ b/templates/macros/assets.html @@ -2,54 +2,55 @@ {% macro init_svg() %} - - - - < - - - + + + + + < + + {% endmacro init_svg %} {% macro card(post) %}
- -
-
{{post.title}}
- {% if post.extra.image %} - Showcase image - {% endif %} -
-
- {{ post.description | striptags | safe }} + +
+
{{post.title}}
+ {% if post.extra.image %} + Showcase image + {% endif %} +
+
+ {{ post.description | striptags | safe }} +
+
{% endmacro card %} @@ -64,30 +65,29 @@ {% endif %}
  • -
    - {{ section.title }} - {% if section.subsections %} - - {% endif %} -
    +
    + {{ section.title }} {% if section.subsections %} -
      - {% for s in section.subsections %} - {{ self::assets_menu_row(prefix=prefix, section_path=s) }} - {% endfor %} -
    + {% endif %} +
    + {% if section.subsections %} +
      + {% for s in section.subsections %} + {{ self::assets_menu_row(prefix=prefix, section_path=s) }} + {% endfor %} +
    + {% endif %}
  • {% endmacro %} {% macro assets_menu(root, prefix) %}
      - {% for s in root.subsections %} - {{ self::assets_menu_row(prefix=prefix, section_path=s)}} - {% endfor %} + {% for s in root.subsections %} + {{ self::assets_menu_row(prefix=prefix, section_path=s)}} + {% endfor %}
    -{% endmacro %} +{% endmacro %} \ No newline at end of file diff --git a/templates/macros/docs.html b/templates/macros/docs.html index 100b5d169d..9d3ba0096b 100644 --- a/templates/macros/docs.html +++ b/templates/macros/docs.html @@ -1,5 +1,4 @@ -{% macro docs_menu_row(prefix, section_path) %} - {% set menu_section = get_section(path=section_path, metadata_only=true) %} +{% macro docs_menu_section_row(prefix, menu_section) %} {% set is_in_branch = menu_section.path in current_path %} {% set is_active = current_path == menu_section.path %} {% set id = prefix ~ '-' ~ menu_section.path | slugify %} @@ -17,7 +16,13 @@ {% endif %} {% endif %} - {% if menu_section.subsections %} + {% set subsections = [] %} + {% for section in menu_section.subsections %} + {% set_global subsections = subsections | concat(with=get_section(path=section)) %} + {% endfor %} + {% set pages_and_sections = menu_section.pages | concat(with=subsections) | sort(attribute="extra.weight") %} + + {% if pages_and_sections %} {% set label_class = label_class ~ " tree-menu__label--with-chevron" %} {% endif %} @@ -25,34 +30,77 @@
  • {{ menu_section.title }} - {% if menu_section.subsections %} + {% if pages_and_sections %} {% endif %}
    - {% if menu_section.subsections %} + {% if pages_and_sections %}
      - {% for s in menu_section.subsections %} - {{ self::docs_menu_row(prefix=prefix, section_path=s) }} + {% for p in pages_and_sections %} + {% if subsections is containing(p) %} + {{ self::docs_menu_section_row(prefix=prefix, menu_section=p) }} + {% elif menu_section.pages is containing(p) %} + {{ self::docs_menu_page_row(prefix=prefix, menu_page=p) }} + {% endif %} {% endfor %}
    {% endif %}
  • -{% endmacro docs_menu_row %} +{% endmacro docs_menu_section_row %} + +{% macro docs_menu_page_row(prefix, menu_page) %} + {% set is_in_branch = menu_page.path in current_path %} + {% set is_active = current_path == menu_page.path %} + {% set id = prefix ~ '-' ~ menu_page.path | slugify %} + {% set class = "tree-menu__item" %} + {% set label_class = "tree-menu__label" %} + + {% if is_active %} + {% set class = class ~ " tree-menu__item--active" %} + {% endif %} + + {% if menu_page.extra and menu_page.extra.public_draft %} + {% set class = class ~ " public_draft" %} + {% if is_in_branch %} + {% set class = class ~ " active_draft" %} + {% endif %} + {% endif %} + +
  • + +
  • +{% endmacro docs_menu_page_row %} {% macro docs_menu(root, prefix) %}
      - {# Migration Guides #} - {% if section and section.path is starting_with("/learn/migration-guides") %} - {% for s in root.subsections | reverse %} - {{ self::docs_menu_row(prefix=prefix, section_path=s) }} - {% endfor %} - {# Other #} + {% set is_migration_guide = current_path is starting_with("/learn/migration-guides") %} + + {% set subsections = [] %} + {% for subsection in root.subsections %} + {% set proper_section = get_section(path=subsection) %} + {% set_global subsections = subsections | concat(with=proper_section) %} + {% endfor %} + {% set pages_and_sections = root.pages | concat(with=subsections) | sort(attribute="extra.weight") %} + {% if is_migration_guide %} + {% for p in pages_and_sections | reverse %} + {% if subsections is containing(p) %} + {{ self::docs_menu_section_row(prefix=prefix, menu_section=p) }} + {% elif root.pages is containing(p) %} + {{ self::docs_menu_page_row(prefix=prefix, menu_page=p) }} + {% endif %} + {% endfor %} {% else %} - {% for s in root.subsections %} - {{ self::docs_menu_row(prefix=prefix, section_path=s) }} - {% endfor %} + {% for p in pages_and_sections %} + {% if subsections is containing(p) %} + {{ self::docs_menu_section_row(prefix=prefix, menu_section=p) }} + {% elif root.pages is containing(p) %} + {{ self::docs_menu_page_row(prefix=prefix, menu_page=p) }} + {% endif %} + {% endfor %} {% endif %}
    {% endmacro %} diff --git a/templates/news.html b/templates/news.html index 753d9990ac..45ec984d97 100644 --- a/templates/news.html +++ b/templates/news.html @@ -3,28 +3,30 @@ {% block content %} {% endblock content %} diff --git a/templates/people.html b/templates/people.html index bedf306247..4d7adb4561 100644 --- a/templates/people.html +++ b/templates/people.html @@ -13,242 +13,258 @@ {% block page_content %} - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    -
    - The Bevy community! If you want to see yourself here, submit a pull request! +
    + The Bevy community! If you want to see yourself here, submit + a pull request! +
    + {% for subsection in section.subsections %} + {% set section = get_section(path=subsection) %} + + +

    + {{ section.title }}# +

    + + {% if section.title == "The Bevy Organization" %} +
    +

    + The Bevy Organization is the group of people responsible for stewarding the Bevy project. It handles things + like choosing project direction, merging pull requests, managing bugs / issues / feature requests, running + the Bevy website, controlling access to secrets, defining and enforcing best practices, etc. +

    +

    + Anyone with a history of contributing to Bevy can join the Bevy Organization. Reach out to the Project Lead + if you would like to join! +

    +

    + +

    + Roles# +

    +
    +
    +
    Project Leads
    +
    have the final call on all design and code changes within Bevy. They + are responsible for representing the project publicly and they choose how the project is organized.
    +
    +
    +
    Maintainers
    +
    have merge rights in Bevy repos. They assess the scope of pull + requests and whether they fit into the Bevy project's vision. They also serve as representatives of the Bevy + project.
    +
    +
    +
    SMEs
    +
    (Subject Matter Experts) have proven themselves to be experts in a + given development area. They help guide Bevy's direction in their area and they are great people to reach out + to if you have questions about a given area.
    +
    +
    +
    Other members, without a special role, are part of the GitHub + organization. They have the power to manage GitHub issues and pull requests.
    +
    - {% for subsection in section.subsections %} - {% set section = get_section(path=subsection) %} - - -

    - {{ section.title }}# -

    - - {% if section.title == "The Bevy Organization" %} -
    -

    - The Bevy Organization is the group of people responsible for stewarding the Bevy project. It handles things - like choosing project direction, merging pull requests, managing bugs / issues / feature requests, running - the Bevy website, controlling access to secrets, defining and enforcing best practices, etc. -

    -

    - Anyone with a history of contributing to Bevy can join the Bevy Organization. Reach out to the Project Lead - if you would like to join! -

    -

    - -

    - Roles# -

    -
    -
    -
    Project Leads
    -
    have the final call on all design and code changes within Bevy. They are responsible for representing the project publicly and they choose how the project is organized.
    -
    -
    -
    Maintainers
    -
    have merge rights in Bevy repos. They assess the scope of pull requests and whether they fit into the Bevy project's vision. They also serve as representatives of the Bevy project.
    -
    -
    -
    SMEs
    -
    (Subject Matter Experts) have proven themselves to be experts in a given development area. They help guide Bevy's direction in their area and they are great people to reach out to if you have questions about a given area.
    -
    -
    -
    Other members, without a special role, are part of the GitHub organization. They have the power to manage GitHub issues and pull requests.
    -
    -
    -

    -
    - {% endif %} - - {% if section.title == "The Bevy Organization" %} - -

    - Members# -

    - {% endif %} - - {% if section.title == "Community Members" %} -
    -

    - People in the Bevy community who are not part of the organization. -

    -

    - Anyone can add themselves here! Submit a pull request! -

    -
    - {% endif %} +

    +
    + {% endif %} + + {% if section.title == "The Bevy Organization" %} + +

    + Members# +

    + {% endif %} + + {% if section.title == "Community Members" %} +
    +

    + People in the Bevy community who are not part of the organization. +

    +

    + Anyone can add themselves here! Submit a pull request! +

    +
    + {% endif %} - {% if section.pages %} -
    - {% set pages = section.pages %} - {% if section.extra.sort_order_reversed %} - {% set pages = section.pages | reverse %} + {% if section.pages %} +
    + {% set pages = section.pages %} + {% if section.extra.sort_order_reversed %} + {% set pages = section.pages | reverse %} + {% endif %} + + {% for post in pages %} + +
    +
    +
    +
    + {{ post.title }} +
    + {% if post.extra.profile_picture %} +
    + {% if post.extra.profile_picture is starting_with("https://") %} + + {% else %} + {% endif %} - - {% for post in pages %} - -
    -
    -
    -
    - {{ post.title }} -
    - {% if post.extra.profile_picture %} -
    - {% if post.extra.profile_picture is starting_with("https://") %} - - {% else %} - - {% endif %} -
    - {% endif %} -
    -
    - - {% if post.extra.roles %} -
    - {% for role in post.extra.roles %} - {% if role == "Project Lead" %} -
    {{ role }}
    - {% elif role == "Maintainer" %} -
    {{ role }}
    - {% elif role is starting_with("SME-") %} -
    {{ role }}
    - {% else %} -
    {{ role }}
    - {% endif %} - {% endfor %} -
    - {% endif %} - {% if post.extra.bio %} -
    - {{ post.extra.bio }} -
    - {% endif %} - {% if post.extra.sponsor %} -
    - - - - Sponsor me! -
    - {% endif %} - -
    -
    +
    + {% endif %} +
    +
    + + {% if post.extra.roles %} +
    + {% for role in post.extra.roles %} + {% if role == "Project Lead" %} +
    {{ role }}
    + {% elif role == "Maintainer" %} +
    {{ role }}
    + {% elif role is starting_with("SME-") %} +
    {{ role }}
    + {% else %} +
    {{ role }}
    + {% endif %} {% endfor %} +
    + {% endif %} + {% if post.extra.bio %} +
    + {{ post.extra.bio }} +
    + {% endif %} + {% if post.extra.sponsor %} +
    + + + + Sponsor me! +
    + {% endif %} +
    - {% endif %} +
    +
    {% endfor %} +
    + {% endif %} + + {% endfor %}
    {% endblock content %} diff --git a/templates/shortcodes/rust_mod.html b/templates/shortcodes/rust_mod.html deleted file mode 100644 index 37958705a2..0000000000 --- a/templates/shortcodes/rust_mod.html +++ /dev/null @@ -1,24 +0,0 @@ - -{% if not crate %} -{% set crate = "std" %} -{% endif %} - -{% if not version %} -{% set version = "latest" %} -{% endif %} - -{% if mod %} -{% set mod_path = "/" ~ mod | replace(from="::", to="/") %} -{% else %} -{% set mod_path = "" %} -{% endif %} - -{% if crate == "std" %} -{% set url = "https://doc.rust-lang.org" %} -{% set path = "stable/" ~ crate %} -{% else %} -{% set url = "https://docs.rs" %} -{% set path = crate ~ "/" ~ version ~ "/" ~ crate %} -{% endif %} - -{% if not no_crate and crate%}{{crate}}{% if not no_mod and mod%}::{{mod}}{% endif %}{% elif not no_mod and mod%}{{mod}}{% endif %} diff --git a/templates/shortcodes/rust_type.html b/templates/shortcodes/rust_type.html deleted file mode 100644 index 11e52f882b..0000000000 --- a/templates/shortcodes/rust_type.html +++ /dev/null @@ -1,28 +0,0 @@ -{% if not crate %} -{% set crate = "std" %} -{% endif %} - -{% if not version %} -{% set version = "latest" %} -{% endif %} - -{% if not mod %} -{% set mod_path = "" %} -{% set mod = "" %} -{% else %} -{% set mod_path = "/" ~ mod | replace(from="::", to="/") %} -{% endif %} - -{% if crate == "std" %} -{% set url = "https://doc.rust-lang.org" %} -{% set path = "stable/" ~ crate %} -{% else %} -{% set url = "https://docs.rs" %} -{% set path = crate ~ "/" ~ version ~ "/" ~ crate %} -{% endif %} - -{% if plural %} -{{ throw(message="the plural option is no longer used. just put an 's' after the shortcode.") }} -{% endif %} - -{% if not no_crate and crate and not no_mod and mod %}{{crate}}::{% if not no_mod and mod%}{{mod}}::{% endif %}{% elif not no_mod and mod%}{{mod}}::{% endif %}{% if not no_struct %}{{name}}{% endif %}{% if method %}{% if not no_struct %}::{% endif %}{{method}}(){% endif %} \ No newline at end of file diff --git a/templates/shortcodes/todo.html b/templates/shortcodes/todo.html new file mode 100644 index 0000000000..22b73c5a46 --- /dev/null +++ b/templates/shortcodes/todo.html @@ -0,0 +1,4 @@ +
    +

    TODO

    + {{ body | markdown | safe }} +
    \ No newline at end of file diff --git a/templates/sitemap.xml b/templates/sitemap.xml new file mode 100644 index 0000000000..5a7d82b1b6 --- /dev/null +++ b/templates/sitemap.xml @@ -0,0 +1,13 @@ + + + {% for sitemap_entry in entries %} + {% if not sitemap_entry.extra.status %} + + {{ sitemap_entry.permalink | escape_xml | safe }} + {% if sitemap_entry.updated %} + {{ sitemap_entry.updated }} + {% endif %} + + {% endif %} + {% endfor %} + \ No newline at end of file diff --git a/write-rustdoc-hide-lines/.gitignore b/write-rustdoc-hide-lines/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/write-rustdoc-hide-lines/.gitignore @@ -0,0 +1 @@ +/target diff --git a/write-rustdoc-hide-lines/Cargo.lock b/write-rustdoc-hide-lines/Cargo.lock new file mode 100644 index 0000000000..83409b5557 --- /dev/null +++ b/write-rustdoc-hide-lines/Cargo.lock @@ -0,0 +1,68 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" + +[[package]] +name = "indoc" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da2d6f23ffea9d7e76c53eee25dfb67bcd8fde7f1198b0855350698c9f07c780" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "write-rustdoc-hide-lines" +version = "0.1.0" +dependencies = [ + "anyhow", + "indoc", + "regex", +] diff --git a/write-rustdoc-hide-lines/Cargo.toml b/write-rustdoc-hide-lines/Cargo.toml new file mode 100644 index 0000000000..43f01bf13b --- /dev/null +++ b/write-rustdoc-hide-lines/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "write-rustdoc-hide-lines" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0" +regex = "1.5" + +[dev-dependencies] +indoc = "1.0" diff --git a/write-rustdoc-hide-lines/README.md b/write-rustdoc-hide-lines/README.md new file mode 100644 index 0000000000..5e57d787ef --- /dev/null +++ b/write-rustdoc-hide-lines/README.md @@ -0,0 +1,17 @@ +# Write `rustdoc` `hide_lines` annotations + +This utility iterates over the Markdown files on the given folder. +Searches `rust` code blocks and ensures that the [`hide_lines` Zola annotation] match the code block "hidden" lines (the ones starting with `#`). +If the annotation doesn't match the code block this utility will update it. + +[`hide_lines` Zola annotation]: https://www.getzola.org/documentation/content/syntax-highlighting/#annotations + +## Usage + +Just run: + +```sh +./write_rustdoc_hide_lines.sh +``` + +This will run the utility over the Book Markdown files. diff --git a/write-rustdoc-hide-lines/src/code_block_definition.rs b/write-rustdoc-hide-lines/src/code_block_definition.rs new file mode 100644 index 0000000000..c374f615fd --- /dev/null +++ b/write-rustdoc-hide-lines/src/code_block_definition.rs @@ -0,0 +1,267 @@ +use std::ops::Range; + +use regex::Regex; + +use crate::hidden_ranges::HiddenRanges; + +#[derive(Debug, PartialEq)] +enum Annotation { + HideLines(HiddenRanges), + Other(String), +} + +impl From<&str> for Annotation { + fn from(text: &str) -> Self { + const HIDE_LINES: &str = "hide_lines="; + let is_hide_lines = text.starts_with(HIDE_LINES); + + if is_hide_lines { + Annotation::HideLines( + text.get(HIDE_LINES.len()..) + .unwrap_or("") + .split(' ') + .filter(|r| r.trim() != "") + .map(|range| { + let is_range = range.contains('-'); + + if is_range { + let range = range.split('-').collect::>(); + let start = range[0].parse().unwrap(); + let end = range[1].parse().unwrap(); + + Range { start, end } + } else { + let line_no = range.parse::().unwrap(); + Range { + start: line_no, + end: line_no, + } + } + }) + .collect(), + ) + } else { + Annotation::Other(String::from(text)) + } + } +} + +impl Annotation { + fn into_string(self) -> String { + match self { + Annotation::HideLines(ranges) => { + let ranges = ranges + .iter() + .map(|r| { + if r.start == r.end { + format!("{}", r.start) + } else { + format!("{}-{}", r.start, r.end) + } + }) + .collect::>() + .join(" "); + + format!("hide_lines={}", ranges) + } + Annotation::Other(content) => content, + } + } +} + +#[derive(Debug, PartialEq)] +pub struct CodeBlockDefinition { + tag: String, + annotations: Vec, + hide_lines_idx: Option, +} + +impl CodeBlockDefinition { + pub fn new(line: &str) -> Option { + let lang_re = Regex::new(r"(\s*)```(.+)").ok()?; + let captures = lang_re.captures(line)?; + + let whitespace = captures.get(1).map(|mat| mat.as_str())?; + let lang = captures.get(2).map(|mat| mat.as_str())?; + + let mut hide_lines_idx = None; + + let mut parts = lang.split(','); + let tag = parts.next()?; + + if tag != "rs" && tag != "rust" { + return None; + } + + let annotations = parts + .enumerate() + .map(|(idx, a)| { + let annotation = Annotation::from(a); + + if let Annotation::HideLines(_) = annotation { + hide_lines_idx = Some(idx); + } + + annotation + }) + .collect(); + + Some(CodeBlockDefinition { + tag: format!("{}```{}", whitespace, tag), + annotations, + hide_lines_idx, + }) + } + + pub fn get_hidden_ranges(&self) -> Option<&HiddenRanges> { + self.hide_lines_idx.map(|idx| match &self.annotations[idx] { + Annotation::HideLines(ranges) => ranges, + Annotation::Other(_) => unreachable!(), + }) + } + + pub fn into_string(self) -> String { + let mut out = self.tag; + + if !self.annotations.is_empty() { + out.push(','); + } + + out.push_str( + &self + .annotations + .into_iter() + .map(|a| a.into_string()) + .collect::>() + .join(","), + ); + + out + } + + pub fn set_hidden_ranges(&mut self, hidden_ranges: HiddenRanges) { + if hidden_ranges.is_empty() { + // Remove + if let Some(idx) = self.hide_lines_idx { + self.annotations.remove(idx); + self.hide_lines_idx = None; + } + } else { + // Add + let annotation = Annotation::HideLines(hidden_ranges); + + match self.hide_lines_idx { + Some(idx) => self.annotations[idx] = annotation, + None => { + self.annotations.push(annotation); + self.hide_lines_idx = Some(self.annotations.len() - 1); + } + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_ignore_malformed_lines() { + let cases = vec!["text line", "```", "```js"]; + + for case in cases { + let definition = CodeBlockDefinition::new(case); + assert_eq!(definition, None); + } + } + + #[test] + fn should_parse_simple_lines() { + let cases = vec!["```rust", "```rs"]; + + for case in cases { + let definition = CodeBlockDefinition::new(case).unwrap(); + + assert_eq!( + definition, + CodeBlockDefinition { + tag: case.into(), + annotations: vec![], + hide_lines_idx: None, + } + ); + + assert_eq!(definition.into_string(), String::from(case)); + } + } + + #[test] + fn should_parse_other_annotations() { + let line = "```rs,linenos,linenostart=10 , hl_lines=3-4 8-9"; + let definition = CodeBlockDefinition::new(line).unwrap(); + + assert_eq!( + definition, + CodeBlockDefinition { + tag: "```rs".into(), + annotations: vec![ + Annotation::Other(String::from("linenos")), + Annotation::Other(String::from("linenostart=10 ")), + Annotation::Other(String::from(" hl_lines=3-4 8-9")), + ], + hide_lines_idx: None, + } + ); + + assert_eq!(definition.into_string(), String::from(line)); + } + + fn new_range(start: usize, end: usize) -> Range { + Range { start, end } + } + + #[test] + fn should_parse_hide_lines_annotations() { + let line = "```rust,hide_lines=3-4 9"; + let definition = CodeBlockDefinition::new(line).unwrap(); + + assert_eq!( + definition, + CodeBlockDefinition { + tag: "```rust".into(), + annotations: vec![Annotation::HideLines(vec![ + new_range(3, 4), + new_range(9, 9), + ])], + hide_lines_idx: Some(0), + } + ); + + assert_eq!(definition.into_string(), String::from(line)); + } + + #[test] + fn should_parse_annotations() { + let line = "```rust, linenos,hide_lines=3-9 ,linenostart=10 ,hl_lines=10-12"; + let definition = CodeBlockDefinition::new(line).unwrap(); + + assert_eq!( + definition, + CodeBlockDefinition { + tag: "```rust".into(), + annotations: vec![ + Annotation::Other(String::from(" linenos")), + Annotation::HideLines(vec![new_range(3, 9)]), + Annotation::Other(String::from("linenostart=10 ")), + Annotation::Other(String::from("hl_lines=10-12")), + ], + hide_lines_idx: Some(1), + } + ); + + assert_eq!( + definition.into_string(), + "```rust, linenos,hide_lines=3-9,linenostart=10 ,hl_lines=10-12" + ); + } +} diff --git a/write-rustdoc-hide-lines/src/formatter.rs b/write-rustdoc-hide-lines/src/formatter.rs new file mode 100644 index 0000000000..ad61c97c87 --- /dev/null +++ b/write-rustdoc-hide-lines/src/formatter.rs @@ -0,0 +1,269 @@ +use anyhow::Result; +use regex::Regex; +use std::{ + ffi::OsStr, + fmt::Write, + fs::{self, DirEntry, File}, + io::{self, BufRead}, + path::Path, +}; + +use crate::{code_block_definition::CodeBlockDefinition, hidden_ranges::get_hidden_ranges}; + +pub fn run(dir: &Path) -> Result<()> { + visit_dir_md_files(dir, &|entry| { + println!("{:?}", entry.path()); + + // Load and format file annotations + let file = File::open(entry.path())?; + let file_size = file.metadata().unwrap().len().try_into().unwrap(); + let contents = format_file( + io::BufReader::new(file) + .lines() + .map(|line| line.map_err(anyhow::Error::from)), + file_size, + )?; + + // Rewrite file + fs::write(entry.path(), contents)?; + + Ok(()) + }) +} + +fn visit_dir_md_files(dir: &Path, cb: &dyn Fn(&DirEntry) -> Result<()>) -> Result<()> { + if !dir.is_dir() { + return Ok(()); + } + + for entry in fs::read_dir(dir)? { + let entry = entry?; + let path = entry.path(); + + if path.is_dir() { + visit_dir_md_files(&path, cb)?; + } else if let Some(ext) = path.extension().and_then(OsStr::to_str) { + if ext.to_lowercase() == "md" { + cb(&entry)?; + } + } + } + + Ok(()) +} + +fn format_file(reader: impl Iterator>, file_size: usize) -> Result { + let mut contents = String::with_capacity(file_size); + let mut rust_block: Vec = vec![]; + let mut is_rust = false; + + let mut inside_code_block = false; + + // Find a code block delimiter and optionally the first specified language + let code_block_delim = Regex::new(r"\s*```(\w*)")?; + + for line in reader { + let line = line?; + + let code_block_delim_match = code_block_delim.captures(&line).and_then(|cap| cap.get(1)); + let is_code_block_delim = code_block_delim_match.is_some(); + + if !inside_code_block && is_code_block_delim { + let lang = code_block_delim_match.unwrap().as_str(); + if lang == "rust" || lang == "rs" { + is_rust = true; + } + + inside_code_block = true; + } else if inside_code_block && is_code_block_delim { + inside_code_block = false; + } + + // Pass through non-rust code block contents and contents outside of code blocks. + if !is_rust { + writeln!(&mut contents, "{}", &line)?; + continue; + } + + rust_block.push(line); + + if inside_code_block { + continue; + } + + // Process the `rust `code block + let code = &rust_block[1..rust_block.len() - 1]; + let real_hidden_ranges = get_hidden_ranges(code); + let mut definition = CodeBlockDefinition::new(&rust_block[0]).unwrap(); + + match definition.get_hidden_ranges() { + Some(annotation_hidden_ranges) => { + if *annotation_hidden_ranges != real_hidden_ranges { + definition.set_hidden_ranges(real_hidden_ranges); + } + } + None => { + if !real_hidden_ranges.is_empty() { + definition.set_hidden_ranges(real_hidden_ranges); + } + } + } + + // Rewrite code block Zola annotations + rust_block[0] = definition.into_string(); + + // Write code block + writeln!(&mut contents, "{}", &rust_block.join("\n"))?; + + // Reset state + inside_code_block = false; + rust_block = vec![]; + is_rust = false; + } + + Ok(contents) +} + +#[cfg(test)] +mod tests { + use super::*; + use indoc::indoc; + + fn lines_iter(code: &str) -> impl Iterator> + '_ { + code.split('\n').map(|line| Ok(String::from(line))) + } + + #[test] + fn add_missing_annotation() { + let markdown = indoc! {r#" + ```rust + # test + # test 2 + fn not_hidden() { + + } + # test 3 + #[derive(Component)] + struct A; + # #[derive(Component)] + struct B; + ``` + "#}; + + let contents = format_file(lines_iter(markdown), markdown.len()); + + assert_eq!( + contents.unwrap(), + indoc! {r#" + ```rust,hide_lines=1-2 6 9 + # test + # test 2 + fn not_hidden() { + + } + # test 3 + #[derive(Component)] + struct A; + # #[derive(Component)] + struct B; + ``` + + "#} + ); + } + + #[test] + fn update_wrong_annotation() { + let markdown = indoc! {r#" + ```rust,hide_lines=2-3 7 + # test + # test 2 + fn not_hidden() { + + } + # test 3 + ``` + "#}; + + let contents = format_file(lines_iter(markdown), markdown.len()); + + assert_eq!( + contents.unwrap(), + indoc! {r#" + ```rust,hide_lines=1-2 6 + # test + # test 2 + fn not_hidden() { + + } + # test 3 + ``` + + "#} + ); + } + + #[test] + fn remove_annotation() { + let markdown = indoc! {r#" + ```rust,hide_lines=2-3 7 + fn not_hidden() { + + } + ``` + "#}; + + let contents = format_file(lines_iter(markdown), markdown.len()); + + assert_eq!( + contents.unwrap(), + indoc! {r#" + ```rust + fn not_hidden() { + + } + ``` + + "#} + ); + } + + #[test] + fn indented() { + let markdown = r#" + ```rust + # test + # test 2 + fn not_hidden() { + + } + # test 3 + #[derive(Component)] + struct A; + # #[derive(Component)] + struct B; + ``` +"#; + + let contents = format_file(lines_iter(markdown), markdown.len()); + + assert_eq!( + contents.unwrap(), + r#" + ```rust,hide_lines=1-2 6 9 + # test + # test 2 + fn not_hidden() { + + } + # test 3 + #[derive(Component)] + struct A; + # #[derive(Component)] + struct B; + ``` + +"# + ); + } +} diff --git a/write-rustdoc-hide-lines/src/hidden_ranges.rs b/write-rustdoc-hide-lines/src/hidden_ranges.rs new file mode 100644 index 0000000000..758cf913d6 --- /dev/null +++ b/write-rustdoc-hide-lines/src/hidden_ranges.rs @@ -0,0 +1,128 @@ +use std::ops::Range; + +use regex::Regex; + +pub type HiddenRanges = Vec>; + +// The generic is to allow both `&[String]` (slice of `Vec`) and `&[&str]` (slice of `Vec<&str>`) +// See: https://stackoverflow.com/a/41180422/379923 +pub fn get_hidden_ranges>(code: &[T]) -> HiddenRanges { + let mut ranges = vec![]; + let mut curr_range: Option> = None; + + // Match lines starting with a potentially indented `#` followed by a space or EOL. + let Ok(is_hidden_re) = Regex::new(r"^\s*#(?: |$)") else { + return ranges; + }; + + for (idx, line) in code.iter().enumerate() { + let n = idx + 1; + let line = line.as_ref(); + let is_hidden = is_hidden_re.is_match(line); + + if is_hidden { + if let Some(range) = curr_range.as_mut() { + range.end = n; + } else { + curr_range = Some(Range { start: n, end: n }); + } + } else { + if let Some(curr_range) = curr_range { + ranges.push(curr_range); + } + + curr_range = None; + } + } + + if let Some(curr_range) = curr_range { + ranges.push(curr_range); + } + + ranges +} + +#[cfg(test)] +mod tests { + use super::*; + use indoc::indoc; + + fn split_lines(code: &str) -> Vec<&str> { + code.split('\n').collect::>() + } + + #[test] + fn empty_block() { + let code = split_lines(indoc! {r#""#}); + + assert!(get_hidden_ranges(&code).is_empty()); + } + + #[test] + fn no_hidden() { + let code = split_lines(indoc! {r#" + 1 + 2 + 3 + 4 + 5 + "#}); + + assert!(get_hidden_ranges(&code).is_empty()); + } + + #[test] + fn single_range() { + let code = split_lines(indoc! {r#" + # 1 + # 2 + # 3 + 4 + 5 + "#}); + + assert_eq!(get_hidden_ranges(&code), vec![Range { start: 1, end: 3 }]); + } + + #[test] + fn single_range_no_content() { + let code = split_lines(indoc! {r#" + # + # + # + 4 + 5 + "#}); + + assert_eq!(get_hidden_ranges(&code), vec![Range { start: 1, end: 3 }]); + } + + #[test] + fn multi_range() { + let code = split_lines(indoc! {r#" + # 1 + # 2 + 3 + # 4 + # 5 + "#}); + + assert_eq!( + get_hidden_ranges(&code), + vec![Range { start: 1, end: 2 }, Range { start: 4, end: 5 }] + ); + } + + #[test] + fn single_line_range() { + let code = split_lines(indoc! {r#" + 1 + 2 + 3 + 4 + # 5 + "#}); + + assert_eq!(get_hidden_ranges(&code), vec![Range { start: 5, end: 5 }]); + } +} diff --git a/write-rustdoc-hide-lines/src/lib.rs b/write-rustdoc-hide-lines/src/lib.rs new file mode 100644 index 0000000000..82aa54b5f4 --- /dev/null +++ b/write-rustdoc-hide-lines/src/lib.rs @@ -0,0 +1,3 @@ +pub mod code_block_definition; +pub mod formatter; +pub mod hidden_ranges; diff --git a/write-rustdoc-hide-lines/src/main.rs b/write-rustdoc-hide-lines/src/main.rs new file mode 100644 index 0000000000..e21278efe4 --- /dev/null +++ b/write-rustdoc-hide-lines/src/main.rs @@ -0,0 +1,16 @@ +use std::{env, path::Path}; + +use write_rustdoc_hide_lines::formatter; + +fn main() { + let args: Vec = env::args().collect(); + let folder = args.get(1).expect("Please provide a folder"); + let path = Path::new(&folder); + + println!("Formatting folder: {:?}", path); + + match formatter::run(path) { + Ok(_) => println!("Done!"), + Err(error) => println!("Error: {}", error), + } +} diff --git a/write-rustdoc-hide-lines/write_rustdoc_hide_lines.sh b/write-rustdoc-hide-lines/write_rustdoc_hide_lines.sh new file mode 100755 index 0000000000..79d4eca815 --- /dev/null +++ b/write-rustdoc-hide-lines/write_rustdoc_hide_lines.sh @@ -0,0 +1,3 @@ +#!/bin/sh +cargo run --release -- ../content/learn/book +cargo run --release -- ../content/learn/quick-start From f235e7e4a95e56e10fa6767943f1e75ec88df510 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Fri, 16 Feb 2024 15:17:11 -0500 Subject: [PATCH 3/9] Revert "0.13: generate migration guide (#965)" This reverts commit 1a09b10f599d4d86a69135f11a877c19889fc8ba. --- .gitattributes | 32 - .github/bors.toml | 10 + .github/linters/.markdown-lint.yml | 10 +- .github/workflows/build-wasm-examples.yml | 8 +- .github/workflows/ci.yml | 133 +- .github/workflows/deploy.yml | 6 +- .github/workflows/update-screenshots.yml | 12 +- .gitignore | 4 +- .markdownlint.yml | 10 +- CONTRIBUTING.md | 186 - README.md | 4 +- code-validation/Cargo.toml | 10 - code-validation/rustfmt.toml | 2 - code-validation/src/lib.rs | 214 - content/{faq.md => faq/_index.md} | 0 content/learn/advanced-examples/_index.md | 8 - .../learn/advanced-examples/sudoku/_index.md | 7 - .../text-adventure/_index.md | 7 - content/learn/book/_index.md | 10 +- content/learn/book/assets/_index.md | 14 - content/learn/book/assets/custom-assets.md | 12 - content/learn/book/assets/hot-reloading.md | 13 - content/learn/book/assets/loading-assets.md | 14 - .../learn/book/assets/scenes-reflection.md | 16 - .../learn/book/assets/working-with-handles.md | 15 - content/learn/book/audio/_index.md | 14 - content/learn/book/audio/audio-basics.md | 13 - .../contributing/_index.md | 9 +- .../contributing/code/_index.md} | 6 +- .../contributing/docs/_index.md} | 25 +- .../book/development-practices/_index.md | 13 - .../boilerplate-reduction.md | 13 - .../development-practices/error-handling.md | 14 - .../development-practices/fast-compiles.md | 54 - .../organizing-your-code.md | 14 - .../book/development-practices/testing.md | 15 - content/learn/book/ecs/_index.md | 83 - content/learn/book/ecs/change-detection.md | 6 - content/learn/book/ecs/commands.md | 7 - content/learn/book/ecs/entities-components.md | 368 -- .../learn/book/ecs/exclusive-world-access.md | 15 - content/learn/book/ecs/filtering-queries.md | 6 - content/learn/book/ecs/generic-systems.md | 6 - content/learn/book/ecs/resources.md | 16 - content/learn/book/ecs/systems-queries.md | 7 - content/learn/book/game-logic/_index.md | 13 - content/learn/book/game-logic/async-tasks.md | 15 - .../custom-runners-headless-operations.md | 15 - content/learn/book/game-logic/events.md | 15 - content/learn/book/game-logic/run-criteria.md | 15 - content/learn/book/game-logic/states.md | 15 - .../learn/book/game-logic/system-ordering.md | 17 - content/learn/book/game-logic/time-timers.md | 17 - content/learn/book/getting-started/_index.md | 62 +- .../getting-started/app-appbuilder-world.md | 6 - .../learn/book/getting-started/apps/_index.md | 26 + .../book/getting-started/bevy-community.md | 6 - .../getting-started/ecs/_index.md} | 75 +- .../book/getting-started/installation.md | 6 - .../book/getting-started/modular-plugins.md | 6 - .../book/getting-started/plugins/_index.md | 81 + .../book/getting-started/resources/_index.md | 66 + .../getting-started/setup/_index.md} | 33 +- .../learn/book/getting-started/why-bevy.md | 6 - content/learn/book/graphics/2d/_index.md | 14 - .../learn/book/graphics/2d/sprite-sheets.md | 12 - content/learn/book/graphics/2d/sprites.md | 12 - content/learn/book/graphics/3d/_index.md | 13 - content/learn/book/graphics/3d/meshes.md | 13 - content/learn/book/graphics/3d/pbr.md | 13 - content/learn/book/graphics/_index.md | 14 - content/learn/book/graphics/cameras.md | 14 - .../book/graphics/parent-child-hierarchy.md | 14 - .../graphics/rendering-internals/_index.md | 13 - .../rendering-internals/shader-basics.md | 13 - content/learn/book/graphics/transforms.md | 14 - content/learn/book/graphics/windows.md | 15 - content/learn/book/input/_index.md | 14 - content/learn/book/input/gamepad.md | 14 - content/learn/book/input/input-basics.md | 15 - content/learn/book/input/keyboard.md | 14 - content/learn/book/input/mouse.md | 15 - content/learn/book/input/touch.md | 14 - .../introduction/_index.md} | 15 +- .../next-steps/_index.md} | 9 +- .../book/performance-optimizations/_index.md | 14 - .../component-storage.md | 14 - .../diagnostics-benchmarking.md | 14 - .../book/performance-optimizations/indexes.md | 16 - .../parallel-iteration.md | 16 - content/learn/book/platforms/_index.md | 14 - content/learn/book/platforms/android.md | 14 - content/learn/book/platforms/ios.md | 14 - content/learn/book/platforms/web.md | 14 - .../learn/book/plugin-development/_index.md | 4 +- .../troubleshooting/_index.md} | 7 +- content/learn/book/ui/_index.md | 14 - content/learn/book/ui/ui-basics.md | 19 - content/learn/links.toml | 6 +- .../{0.10-to-0.11.md => 0.10-0.11/_index.md} | 3100 ++++++------ .../{0.11-to-0.12.md => 0.11-0.12/_index.md} | 3106 ++++++------ .../learn/migration-guides/0.12-to-0.13.md | 1712 ------- .../{0.4-to-0.5.md => 0.4-0.5/_index.md} | 24 +- .../{0.5-to-0.6.md => 0.5-0.6/_index.md} | 86 +- .../{0.6-to-0.7.md => 0.6-0.7/_index.md} | 5 +- .../{0.7-to-0.8.md => 0.7-0.8/_index.md} | 5 +- .../{0.8-to-0.9.md => 0.8-0.9/_index.md} | 1635 +++---- .../{0.9-to-0.10.md => 0.9-0.10/_index.md} | 2467 +++++----- content/learn/migration-guides/_index.md | 5 +- .../_index.md} | 4 +- .../quick-start/3d-puzzle-game/_index.md | 8 - content/learn/quick-start/_index.md | 7 - content/learn/quick-start/breakout/_index.md | 8 - .../learn/quick-start/falling-sand/_index.md | 8 - .../quick-start/getting-started/_index.md | 64 - .../learn/quick-start/getting-started/apps.md | 41 - .../quick-start/getting-started/plugins.md | 101 - .../quick-start/getting-started/resources.md | 81 - .../learn/quick-start/plugin-development.md | 159 - .../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-assets/src/bin/generate.rs | 2 +- generate-assets/src/gitlab_client.rs | 152 +- generate-assets/src/lib.rs | 51 +- generate-community/src/bin/generate.rs | 21 +- generate-community/src/bin/validate.rs | 4 +- generate-community/src/lib.rs | 8 +- generate-errors/src/bin/generate.rs | 2 +- generate-errors/src/lib.rs | 2 +- generate-release/src/changelog.rs | 124 +- generate-release/src/github_client.rs | 585 +-- generate-release/src/helpers.rs | 226 +- generate-release/src/main.rs | 4 +- generate-release/src/markdown.rs | 268 +- generate-release/src/migration_guide.rs | 218 +- generate-release/src/release_notes.rs | 168 +- generate-release/src/release_notes_website.rs | 174 +- 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/elements/_table.scss | 18 - sass/pages/_assets.scss | 96 +- sass/pages/_community.scss | 6 +- sass/pages/_docs.scss | 68 +- sass/pages/_migration_guide.scss | 66 +- sass/site.scss | 4 +- static/assets/Pixeljam.png | Bin 378 -> 0 bytes static/web-streams-adapter-0.1.0.mjs | 559 --- static/web-streams-polyfill-3.2.1.mjs | 4203 ----------------- templates/assets.html | 100 +- templates/docs-base.html | 161 - templates/docs-page.html | 28 - templates/docs-section.html | 130 +- templates/example.html | 151 +- templates/examples.html | 72 +- templates/index.html | 8 +- templates/layouts/base.html | 267 +- templates/macros/assets.html | 120 +- templates/macros/docs.html | 82 +- 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 | 68 - write-rustdoc-hide-lines/Cargo.toml | 11 - write-rustdoc-hide-lines/README.md | 17 - .../src/code_block_definition.rs | 267 -- write-rustdoc-hide-lines/src/formatter.rs | 269 -- write-rustdoc-hide-lines/src/hidden_ranges.rs | 128 - write-rustdoc-hide-lines/src/lib.rs | 3 - write-rustdoc-hide-lines/src/main.rs | 16 - .../write_rustdoc_hide_lines.sh | 3 - 199 files changed, 8166 insertions(+), 18022 deletions(-) delete mode 100644 .gitattributes create mode 100644 .github/bors.toml delete mode 100644 CONTRIBUTING.md delete mode 100644 code-validation/Cargo.toml delete mode 100644 code-validation/rustfmt.toml delete mode 100644 code-validation/src/lib.rs rename content/{faq.md => faq/_index.md} (100%) delete mode 100644 content/learn/advanced-examples/_index.md delete mode 100644 content/learn/advanced-examples/sudoku/_index.md delete mode 100644 content/learn/advanced-examples/text-adventure/_index.md delete mode 100644 content/learn/book/assets/_index.md delete mode 100644 content/learn/book/assets/custom-assets.md delete mode 100644 content/learn/book/assets/hot-reloading.md delete mode 100644 content/learn/book/assets/loading-assets.md delete mode 100644 content/learn/book/assets/scenes-reflection.md delete mode 100644 content/learn/book/assets/working-with-handles.md delete mode 100644 content/learn/book/audio/_index.md delete mode 100644 content/learn/book/audio/audio-basics.md rename content/learn/{quick-start => book}/contributing/_index.md (77%) rename content/learn/{quick-start/contributing/code.md => book/contributing/code/_index.md} (93%) rename content/learn/{quick-start/contributing/docs.md => book/contributing/docs/_index.md} (57%) delete mode 100644 content/learn/book/development-practices/_index.md delete mode 100644 content/learn/book/development-practices/boilerplate-reduction.md delete mode 100644 content/learn/book/development-practices/error-handling.md delete mode 100644 content/learn/book/development-practices/fast-compiles.md delete mode 100644 content/learn/book/development-practices/organizing-your-code.md delete mode 100644 content/learn/book/development-practices/testing.md delete mode 100644 content/learn/book/ecs/_index.md delete mode 100644 content/learn/book/ecs/change-detection.md delete mode 100644 content/learn/book/ecs/commands.md delete mode 100644 content/learn/book/ecs/entities-components.md delete mode 100644 content/learn/book/ecs/exclusive-world-access.md delete mode 100644 content/learn/book/ecs/filtering-queries.md delete mode 100644 content/learn/book/ecs/generic-systems.md delete mode 100644 content/learn/book/ecs/resources.md delete mode 100644 content/learn/book/ecs/systems-queries.md delete mode 100644 content/learn/book/game-logic/_index.md delete mode 100644 content/learn/book/game-logic/async-tasks.md delete mode 100644 content/learn/book/game-logic/custom-runners-headless-operations.md delete mode 100644 content/learn/book/game-logic/events.md delete mode 100644 content/learn/book/game-logic/run-criteria.md delete mode 100644 content/learn/book/game-logic/states.md delete mode 100644 content/learn/book/game-logic/system-ordering.md delete mode 100644 content/learn/book/game-logic/time-timers.md delete mode 100644 content/learn/book/getting-started/app-appbuilder-world.md create mode 100644 content/learn/book/getting-started/apps/_index.md delete mode 100644 content/learn/book/getting-started/bevy-community.md rename content/learn/{quick-start/getting-started/ecs.md => book/getting-started/ecs/_index.md} (71%) delete mode 100644 content/learn/book/getting-started/installation.md delete mode 100644 content/learn/book/getting-started/modular-plugins.md create mode 100644 content/learn/book/getting-started/plugins/_index.md create mode 100644 content/learn/book/getting-started/resources/_index.md rename content/learn/{quick-start/getting-started/setup.md => book/getting-started/setup/_index.md} (83%) delete mode 100644 content/learn/book/getting-started/why-bevy.md delete mode 100644 content/learn/book/graphics/2d/_index.md delete mode 100644 content/learn/book/graphics/2d/sprite-sheets.md delete mode 100644 content/learn/book/graphics/2d/sprites.md delete mode 100644 content/learn/book/graphics/3d/_index.md delete mode 100644 content/learn/book/graphics/3d/meshes.md delete mode 100644 content/learn/book/graphics/3d/pbr.md delete mode 100644 content/learn/book/graphics/_index.md delete mode 100644 content/learn/book/graphics/cameras.md delete mode 100644 content/learn/book/graphics/parent-child-hierarchy.md delete mode 100644 content/learn/book/graphics/rendering-internals/_index.md delete mode 100644 content/learn/book/graphics/rendering-internals/shader-basics.md delete mode 100644 content/learn/book/graphics/transforms.md delete mode 100644 content/learn/book/graphics/windows.md delete mode 100644 content/learn/book/input/_index.md delete mode 100644 content/learn/book/input/gamepad.md delete mode 100644 content/learn/book/input/input-basics.md delete mode 100644 content/learn/book/input/keyboard.md delete mode 100644 content/learn/book/input/mouse.md delete mode 100644 content/learn/book/input/touch.md rename content/learn/{quick-start/introduction.md => book/introduction/_index.md} (60%) rename content/learn/{quick-start/next-steps.md => book/next-steps/_index.md} (80%) delete mode 100644 content/learn/book/performance-optimizations/_index.md delete mode 100644 content/learn/book/performance-optimizations/component-storage.md delete mode 100644 content/learn/book/performance-optimizations/diagnostics-benchmarking.md delete mode 100644 content/learn/book/performance-optimizations/indexes.md delete mode 100644 content/learn/book/performance-optimizations/parallel-iteration.md delete mode 100644 content/learn/book/platforms/_index.md delete mode 100644 content/learn/book/platforms/android.md delete mode 100644 content/learn/book/platforms/ios.md delete mode 100644 content/learn/book/platforms/web.md rename content/learn/{quick-start/troubleshooting.md => book/troubleshooting/_index.md} (95%) delete mode 100644 content/learn/book/ui/_index.md delete mode 100644 content/learn/book/ui/ui-basics.md rename content/learn/migration-guides/{0.10-to-0.11.md => 0.10-0.11/_index.md} (97%) rename content/learn/migration-guides/{0.11-to-0.12.md => 0.11-0.12/_index.md} (97%) delete mode 100644 content/learn/migration-guides/0.12-to-0.13.md rename content/learn/migration-guides/{0.4-to-0.5.md => 0.4-0.5/_index.md} (88%) rename content/learn/migration-guides/{0.5-to-0.6.md => 0.5-0.6/_index.md} (50%) rename content/learn/migration-guides/{0.6-to-0.7.md => 0.6-0.7/_index.md} (99%) rename content/learn/migration-guides/{0.7-to-0.8.md => 0.7-0.8/_index.md} (99%) rename content/learn/migration-guides/{0.8-to-0.9.md => 0.8-0.9/_index.md} (97%) rename content/learn/migration-guides/{0.9-to-0.10.md => 0.9-0.10/_index.md} (97%) rename content/learn/migration-guides/{introduction.md => introduction/_index.md} (89%) delete mode 100644 content/learn/quick-start/3d-puzzle-game/_index.md delete mode 100644 content/learn/quick-start/_index.md delete mode 100644 content/learn/quick-start/breakout/_index.md delete mode 100644 content/learn/quick-start/falling-sand/_index.md delete mode 100644 content/learn/quick-start/getting-started/_index.md delete mode 100644 content/learn/quick-start/getting-started/apps.md delete mode 100644 content/learn/quick-start/getting-started/plugins.md delete mode 100644 content/learn/quick-start/getting-started/resources.md delete mode 100644 content/learn/quick-start/plugin-development.md delete mode 100644 sass/components/_todo.scss delete mode 100644 sass/elements/_table.scss delete mode 100644 static/assets/Pixeljam.png delete mode 100644 static/web-streams-adapter-0.1.0.mjs delete mode 100644 static/web-streams-polyfill-3.2.1.mjs delete mode 100644 templates/docs-base.html delete mode 100644 templates/docs-page.html create mode 100644 templates/shortcodes/rust_mod.html create mode 100644 templates/shortcodes/rust_type.html delete mode 100644 templates/shortcodes/todo.html delete mode 100644 templates/sitemap.xml delete mode 100644 write-rustdoc-hide-lines/.gitignore delete mode 100644 write-rustdoc-hide-lines/Cargo.lock delete mode 100644 write-rustdoc-hide-lines/Cargo.toml delete mode 100644 write-rustdoc-hide-lines/README.md delete mode 100644 write-rustdoc-hide-lines/src/code_block_definition.rs delete mode 100644 write-rustdoc-hide-lines/src/formatter.rs delete mode 100644 write-rustdoc-hide-lines/src/hidden_ranges.rs delete mode 100644 write-rustdoc-hide-lines/src/lib.rs delete mode 100644 write-rustdoc-hide-lines/src/main.rs delete mode 100755 write-rustdoc-hide-lines/write_rustdoc_hide_lines.sh diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 270ab23cab..0000000000 --- a/.gitattributes +++ /dev/null @@ -1,32 +0,0 @@ -# From: https://docs.github.com/en/github/getting-started-with-github/configuring-git-to-handle-line-endings -# Set the default behavior, in case people don't have core.autocrlf set. -* text=auto - -# Explicitly declare text files you want to always be normalized and converted -# to native line endings on checkout. -*.rs text eol=lf -*.toml text eol=lf -*.frag text eol=lf -*.vert text eol=lf -*.wgsl text eol=lf -*.md text eof=lf -*.html text eof=lf -*.scss text eof=lf -*.js text eof=lf -*.mjs text eof=lf -*.svg text eof=lf -*.txt text eof=lf -*.xml text eof=lf -*.yml text eof=lf -*.sh text eof=lf - -# Denote all files that are truly binary and should not be modified. -*.png binary -*.jpg binary -*.gif binary -*.webp binary -*.ttf binary -*.woff binary -*.woff2 binary -*.eot binary -*.mp4 binary diff --git a/.github/bors.toml b/.github/bors.toml new file mode 100644 index 0000000000..da9c575ce9 --- /dev/null +++ b/.github/bors.toml @@ -0,0 +1,10 @@ +status = [ + "build-website", + "generate-wasm-examples", + "generate-assets", + "generate-errors", + "generate-community", + "markdownlint", +] + +use_squash_merge = true diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml index 15a497ff09..6d963c55d3 100644 --- a/.github/linters/.markdown-lint.yml +++ b/.github/linters/.markdown-lint.yml @@ -1,5 +1,5 @@ -# Keep synced with duplicate in project root - -line-length: false -no-inline-html: false -no-trailing-punctuation: false +# Keep synced with duplicate in project root + +line-length: false +no-inline-html: false +no-trailing-punctuation: false diff --git a/.github/workflows/build-wasm-examples.yml b/.github/workflows/build-wasm-examples.yml index 45a1d0c64e..83301bce53 100644 --- a/.github/workflows/build-wasm-examples.yml +++ b/.github/workflows/build-wasm-examples.yml @@ -18,14 +18,14 @@ jobs: steps: - name: Checkout Bevy latest tag - uses: actions/checkout@v4 + uses: actions/checkout@master with: repository: 'bevyengine/bevy' ref: 'latest' # temporary: fetch tools from main branch - name: Checkout Bevy Tools - uses: actions/checkout@v4 + uses: actions/checkout@master with: repository: 'bevyengine/bevy' ref: 'main' @@ -52,7 +52,7 @@ jobs: cargo run -p example-showcase -- --per-page ${{ env.PER_PAGE }} --page ${{ matrix.page }} build-wasm-examples --content-folder wasm-examples --api ${{ matrix.api }} --website-hacks --optimize-size - name: Upload Generated Files - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: ${{ matrix.api }}-examples-${{ matrix.page }} path: wasm-examples @@ -67,7 +67,7 @@ jobs: steps: - name: Download all artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v3 - name: Group examples in one folder run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4099a97020..8811fd5935 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,77 +9,12 @@ on: - 'trying' jobs: - markdownlint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - # Full git history is needed to get a proper list of changed files within `super-linter` - fetch-depth: 0 - - name: Run Markdown Lint - uses: docker://ghcr.io/github/super-linter:slim-v4 - env: - VALIDATE_ALL_CODEBASE: false - VALIDATE_MARKDOWN: true - DEFAULT_BRANCH: main - - test-code-examples: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - - - name: Install alsa and udev - run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev - - - name: Build & run doc tests - run: cd code-validation && cargo test - - lint-tools: - runs-on: ubuntu-latest - env: - TOOLS: | - code-validation generate-assets generate-community generate-errors generate-release write-rustdoc-hide-lines - steps: - - uses: actions/checkout@v4 - - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - - - name: Install alsa and udev - run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev - - - name: Check formatting - run: | - for CRATE in $TOOLS; do - cd $CRATE - - echo Checking $CRATE - cargo fmt --check - - cd .. - done - - - name: Check clippy - run: | - for CRATE in $TOOLS; do - cd $CRATE - - echo Checking $CRATE - cargo clippy -- -Dwarnings - - cd .. - done - generate-assets: - needs: [markdownlint, test-code-examples, lint-tools] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@master - - uses: actions/cache@v4 + - uses: actions/cache@v3 with: path: | ~/.cargo/bin/ @@ -91,10 +26,10 @@ jobs: - name: Get cache key id: cache-key - run: echo "key=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + run: echo "::set-output name=key::$(date +'%Y-%m-%d')" - name: Get crates.io datadump from cache - uses: actions/cache@v4 + uses: actions/cache@v2 with: path: generate-assets/data key: ${{ runner.os }}-${{ steps.cache-key.outputs.key }} @@ -105,19 +40,18 @@ jobs: export GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} && ./generate_assets.sh - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@master with: name: generated-assets path: content/assets retention-days: 1 generate-errors: - needs: [markdownlint, test-code-examples, lint-tools] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@master - - uses: actions/cache@v4 + - uses: actions/cache@v3 with: path: | ~/.cargo/bin/ @@ -132,32 +66,24 @@ jobs: cd generate-errors && ./generate_errors.sh - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@master with: name: generated-errors path: content/learn/errors retention-days: 1 generate-wasm-examples: - needs: [markdownlint, test-code-examples, lint-tools] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - - name: "Clone Bevy" - run: > - cd generate-wasm-examples && - ./clone_bevy.sh + - uses: actions/checkout@master - - uses: actions/cache@v4 + - uses: actions/cache@v3 with: path: | ~/.cargo/bin/ ~/.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 @@ -169,25 +95,24 @@ jobs: cd generate-wasm-examples && ./generate_wasm_examples.sh - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@master with: name: generated-wasm-examples path: content/examples retention-days: 1 - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@master with: name: generated-wasm-examples-webgpu path: content/examples-webgpu retention-days: 1 generate-community: - needs: [markdownlint, test-code-examples, lint-tools] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@master - - uses: actions/cache@v4 + - uses: actions/cache@v3 with: path: | ~/.cargo/bin/ @@ -202,39 +127,53 @@ jobs: cd generate-community && ./generate_community.sh - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@master with: name: generated-community path: content/community/people retention-days: 1 + markdownlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + # Full git history is needed to get a proper list of changed files within `super-linter` + fetch-depth: 0 + - name: Run Markdown Lint + uses: docker://ghcr.io/github/super-linter:slim-v4 + env: + VALIDATE_ALL_CODEBASE: false + VALIDATE_MARKDOWN: true + DEFAULT_BRANCH: main + build-website: runs-on: ubuntu-latest - needs: [markdownlint, test-code-examples, lint-tools, generate-assets, generate-errors, generate-wasm-examples, generate-community] + needs: [markdownlint, generate-assets, generate-errors, generate-wasm-examples, generate-community] steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 + - uses: actions/checkout@master + - uses: actions/download-artifact@master with: name: generated-assets path: content/assets - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@master with: name: generated-errors path: content/learn/errors - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@master with: name: generated-wasm-examples path: content/examples - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@master with: name: generated-wasm-examples-webgpu path: content/examples-webgpu - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@master with: name: generated-community path: content/community/people diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f8c7db5909..8284efe396 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -11,14 +11,14 @@ jobs: build_and_deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@master - name: Get current date id: date - run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + run: echo "::set-output name=date::$(date +'%Y-%m-%d')" - name: Cache multiple crates.io datadump - uses: actions/cache@v4 + uses: actions/cache@v2 with: path: generate-assets/data key: ${{ runner.os }}-${{ steps.date.outputs.date }} diff --git a/.github/workflows/update-screenshots.yml b/.github/workflows/update-screenshots.yml index 9484fac9e3..7e343ab64b 100644 --- a/.github/workflows/update-screenshots.yml +++ b/.github/workflows/update-screenshots.yml @@ -17,14 +17,14 @@ jobs: steps: - name: Checkout Bevy latest tag - uses: actions/checkout@v4 + uses: actions/checkout@master with: repository: 'bevyengine/bevy' ref: 'latest' # temporary: fetch tools from main branch - name: Checkout Bevy Tools - uses: actions/checkout@v4 + uses: actions/checkout@master with: repository: 'bevyengine/bevy' ref: 'main' @@ -56,7 +56,7 @@ jobs: xvfb-run cargo run -p example-showcase -- --page ${{ matrix.page }} --per-page ${{ env.PER_PAGE }} run --screenshot --in-ci - name: Upload Generated Files - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: screenshots-${{ matrix.page }} path: screenshots @@ -71,10 +71,10 @@ jobs: steps: - name: Clone bevy-website repo - uses: actions/checkout@v4 + uses: actions/checkout@master - name: Download all artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v3 - name: Move examples to the correct folder run: | @@ -87,7 +87,7 @@ jobs: done - name: Create Pull Request - uses: peter-evans/create-pull-request@v6 + uses: peter-evans/create-pull-request@v5 with: delete-branch: true branch-suffix: random diff --git a/.gitignore b/.gitignore index dd5ca563f9..efd7777d7f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,4 @@ content/community/people content/community/donate static/assets/examples static/processed_images -.vscode/ -code-validation/target -code-validation/Cargo.lock +.vscode/ \ No newline at end of file diff --git a/.markdownlint.yml b/.markdownlint.yml index afff32bd5a..6601d4e409 100644 --- a/.markdownlint.yml +++ b/.markdownlint.yml @@ -1,5 +1,5 @@ -# Keep synced with duplicate in `.github/linters` folder - -line-length: false -no-inline-html: false -no-trailing-punctuation: false +# Keep synced with duplicate in `.github/linters` folder + +line-length: false +no-inline-html: false +no-trailing-punctuation: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 61cb49eb55..0000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,186 +0,0 @@ -# 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 hide lines of code in Zola Rust code blocks of the book you should: a. Mark each line you wish to hide with a `#` with an empty space afterwards like `# //...line_of_code_here...` although you were hiding lines in rustdoc. b. Run the [utility tool](write-rustdoc-hide-lines) in `/write_rustdoc-hide-lines/` named `write_rustdoc_hide_lines.sh`. -13. 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 c7f3acc83e..7eef99c69c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # Bevy Website -The source files for . This includes official Bevy news, docs, and interactive examples. - -If you would like to contribute, check out [CONTRIBUTING.md](/CONTRIBUTING.md) and then submit a pull request! +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! ## Zola diff --git a/code-validation/Cargo.toml b/code-validation/Cargo.toml deleted file mode 100644 index 750d9cafe1..0000000000 --- a/code-validation/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[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 deleted file mode 100644 index a4607a5fa4..0000000000 --- a/code-validation/rustfmt.toml +++ /dev/null @@ -1,2 +0,0 @@ -use_field_init_shorthand = true -newline_style = "Unix" diff --git a/code-validation/src/lib.rs b/code-validation/src/lib.rs deleted file mode 100644 index 1768769841..0000000000 --- a/code-validation/src/lib.rs +++ /dev/null @@ -1,214 +0,0 @@ -//! 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.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.md")] - mod apps {} - #[doc = include_str!("../../content/learn/quick-start/getting-started/ecs.md")] - mod ecs {} - #[doc = include_str!("../../content/learn/quick-start/getting-started/plugins.md")] - mod plugins {} - #[doc = include_str!("../../content/learn/quick-start/getting-started/resources.md")] - mod resources {} - } - #[doc = include_str!("../../content/learn/quick-start/contributing/_index.md")] - mod contributing { - #[doc = include_str!("../../content/learn/quick-start/contributing/docs.md")] - mod docs {} - #[doc = include_str!("../../content/learn/quick-start/contributing/code.md")] - mod code {} - } - #[doc = include_str!("../../content/learn/quick-start/plugin-development.md")] - mod plugin_development {} - #[doc = include_str!("../../content/learn/quick-start/troubleshooting.md")] - mod troubleshooting {} - #[doc = include_str!("../../content/learn/quick-start/next-steps.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.md")] - mod custom_assets {} - #[doc = include_str!("../../content/learn/book/assets/hot-reloading.md")] - mod hot_reloading {} - #[doc = include_str!("../../content/learn/book/assets/loading-assets.md")] - mod loading_assets {} - #[doc = include_str!("../../content/learn/book/assets/scenes-reflection.md")] - mod scenes_reflection {} - #[doc = include_str!("../../content/learn/book/assets/working-with-handles.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.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.md")] - mod boilerplate_reduction {} - #[doc = include_str!("../../content/learn/book/development-practices/error-handling.md")] - mod error_handling {} - #[doc = include_str!("../../content/learn/book/development-practices/fast-compiles.md")] - mod fast_compiles {} - #[doc = include_str!("../../content/learn/book/development-practices/organizing-your-code.md")] - mod organizing_your_code {} - #[doc = include_str!("../../content/learn/book/development-practices/testing.md")] - mod testing {} - } - - #[doc = include_str!("../../content/learn/book/ecs/_index.md")] - mod ecs { - #[doc = include_str!("../../content/learn/book/ecs/change-detection.md")] - mod change_detection {} - #[doc = include_str!("../../content/learn/book/ecs/commands.md")] - mod commands {} - #[doc = include_str!("../../content/learn/book/ecs/entities-components.md")] - mod entities_components {} - #[doc = include_str!("../../content/learn/book/ecs/exclusive-world-access.md")] - mod exclusive_world_access {} - #[doc = include_str!("../../content/learn/book/ecs/filtering-queries.md")] - mod filtering_queries {} - #[doc = include_str!("../../content/learn/book/ecs/generic-systems.md")] - mod generic_systems {} - #[doc = include_str!("../../content/learn/book/ecs/resources.md")] - mod resources {} - #[doc = include_str!("../../content/learn/book/ecs/systems-queries.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.md")] - mod async_tasks {} - #[doc = include_str!("../../content/learn/book/game-logic/custom-runners-headless-operations.md")] - mod custom_runners_headless_operation {} - #[doc = include_str!("../../content/learn/book/game-logic/events.md")] - mod events {} - #[doc = include_str!("../../content/learn/book/game-logic/run-criteria.md")] - mod run_criteria {} - #[doc = include_str!("../../content/learn/book/game-logic/states.md")] - mod states {} - #[doc = include_str!("../../content/learn/book/game-logic/system-ordering.md")] - mod system_ordering {} - #[doc = include_str!("../../content/learn/book/game-logic/time-timers.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.md")] - mod app_appbuilder_world {} - #[doc = include_str!("../../content/learn/book/getting-started/bevy-community.md")] - mod bevy_community {} - #[doc = include_str!("../../content/learn/book/getting-started/installation.md")] - mod installation {} - #[doc = include_str!("../../content/learn/book/getting-started/modular-plugins.md")] - mod modular_plugins {} - #[doc = include_str!("../../content/learn/book/getting-started/why-bevy.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.md")] - mod sprite_sheets {} - #[doc = include_str!("../../content/learn/book/graphics/2d/sprites.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.md")] - mod meshes {} - #[doc = include_str!("../../content/learn/book/graphics/3d/pbr.md")] - mod pbr {} - } - #[doc = include_str!("../../content/learn/book/graphics/cameras.md")] - mod cameras {} - #[doc = include_str!("../../content/learn/book/graphics/parent-child-hierarchy.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.md")] - mod shader_basics {} - } - #[doc = include_str!("../../content/learn/book/graphics/transforms.md")] - mod transforms {} - #[doc = include_str!("../../content/learn/book/graphics/windows.md")] - mod windows {} - } - - #[doc = include_str!("../../content/learn/book/input/_index.md")] - mod input { - #[doc = include_str!("../../content/learn/book/input/gamepad.md")] - mod gamepad {} - #[doc = include_str!("../../content/learn/book/input/input-basics.md")] - mod input_basics {} - #[doc = include_str!("../../content/learn/book/input/keyboard.md")] - mod keyboard {} - #[doc = include_str!("../../content/learn/book/input/mouse.md")] - mod mouse {} - #[doc = include_str!("../../content/learn/book/input/touch.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.md")] - mod component_storage {} - #[doc = include_str!("../../content/learn/book/performance-optimizations/diagnostics-benchmarking.md")] - mod diagnostics_benchmarking {} - #[doc = include_str!("../../content/learn/book/performance-optimizations/indexes.md")] - mod indexes {} - #[doc = include_str!("../../content/learn/book/performance-optimizations/parallel-iteration.md")] - mod parallel_iteration {} - } - - #[doc = include_str!("../../content/learn/book/platforms/_index.md")] - mod platforms { - #[doc = include_str!("../../content/learn/book/platforms/android.md")] - mod android {} - #[doc = include_str!("../../content/learn/book/platforms/ios.md")] - mod ios {} - #[doc = include_str!("../../content/learn/book/platforms/web.md")] - mod web {} - } - - #[doc = include_str!("../../content/learn/book/ui/_index.md")] - mod ui { - #[doc = include_str!("../../content/learn/book/ui/ui-basics.md")] - mod ui_basics {} - } - } -} diff --git a/content/faq.md b/content/faq/_index.md similarity index 100% rename from content/faq.md rename to content/faq/_index.md diff --git a/content/learn/advanced-examples/_index.md b/content/learn/advanced-examples/_index.md deleted file mode 100644 index 612f22e2b0..0000000000 --- a/content/learn/advanced-examples/_index.md +++ /dev/null @@ -1,8 +0,0 @@ -+++ -title = "Advanced Examples" -template = "docs-section.html" -page_template = "docs-page.html" -[extra] -public_draft = 877 -status = "hidden" -+++ diff --git a/content/learn/advanced-examples/sudoku/_index.md b/content/learn/advanced-examples/sudoku/_index.md deleted file mode 100644 index 551dec70c9..0000000000 --- a/content/learn/advanced-examples/sudoku/_index.md +++ /dev/null @@ -1,7 +0,0 @@ -+++ -title = "Sudoku" -template = "docs-section.html" -[extra] -weight = 2 -status = "hidden" -+++ diff --git a/content/learn/advanced-examples/text-adventure/_index.md b/content/learn/advanced-examples/text-adventure/_index.md deleted file mode 100644 index 85e73c6993..0000000000 --- a/content/learn/advanced-examples/text-adventure/_index.md +++ /dev/null @@ -1,7 +0,0 @@ -+++ -title = "Text Adventure" -template = "docs-section.html" -[extra] -weight = 1 -status = "hidden" -+++ diff --git a/content/learn/book/_index.md b/content/learn/book/_index.md index ec5c61a17e..1906ee994e 100644 --- a/content/learn/book/_index.md +++ b/content/learn/book/_index.md @@ -1,10 +1,8 @@ +++ title = "Book" +sort_by = "weight" template = "docs-section.html" -page_template = "docs-page.html" +page_template = "docs-section.html" +redirect_to = "learn/book/introduction" insert_anchor_links = "right" -redirect_to = "learn/book/getting-started" -[extra] -status = 'hidden' -public_draft = 874 -+++ ++++ \ No newline at end of file diff --git a/content/learn/book/assets/_index.md b/content/learn/book/assets/_index.md deleted file mode 100644 index 789aaf12de..0000000000 --- a/content/learn/book/assets/_index.md +++ /dev/null @@ -1,14 +0,0 @@ -+++ -title = "Assets" -template = "docs-section.html" -insert_anchor_links = "right" -[extra] -weight = 5 -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.md b/content/learn/book/assets/custom-assets.md deleted file mode 100644 index 120f790b18..0000000000 --- a/content/learn/book/assets/custom-assets.md +++ /dev/null @@ -1,12 +0,0 @@ -+++ -title = "Custom Assets" -insert_anchor_links = "right" -[extra] -weight = 3 -status = 'hidden' -+++ - -{% todo() %} - -* Demonstrate how to write a custom asset loader. -{% end %} diff --git a/content/learn/book/assets/hot-reloading.md b/content/learn/book/assets/hot-reloading.md deleted file mode 100644 index 6b49acbbb1..0000000000 --- a/content/learn/book/assets/hot-reloading.md +++ /dev/null @@ -1,13 +0,0 @@ -+++ -title = "Hot Reloading" -insert_anchor_links = "right" -[extra] -weight = 4 -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.md b/content/learn/book/assets/loading-assets.md deleted file mode 100644 index a01ac0a62a..0000000000 --- a/content/learn/book/assets/loading-assets.md +++ /dev/null @@ -1,14 +0,0 @@ -+++ -title = "Loading Assets" -insert_anchor_links = "right" -[extra] -weight = 1 -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.md b/content/learn/book/assets/scenes-reflection.md deleted file mode 100644 index d64c00d1f5..0000000000 --- a/content/learn/book/assets/scenes-reflection.md +++ /dev/null @@ -1,16 +0,0 @@ -+++ -title = "Scenes and Reflection" -insert_anchor_links = "right" -[extra] -weight = 5 -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.md b/content/learn/book/assets/working-with-handles.md deleted file mode 100644 index a942db4770..0000000000 --- a/content/learn/book/assets/working-with-handles.md +++ /dev/null @@ -1,15 +0,0 @@ -+++ -title = "Working With Handles" -insert_anchor_links = "right" -[extra] -weight = 2 -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 deleted file mode 100644 index 3964784e65..0000000000 --- a/content/learn/book/audio/_index.md +++ /dev/null @@ -1,14 +0,0 @@ -+++ -title = "Audio" -template = "docs-section.html" -insert_anchor_links = "right" -[extra] -weight = 7 -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.md b/content/learn/book/audio/audio-basics.md deleted file mode 100644 index c25b9243ce..0000000000 --- a/content/learn/book/audio/audio-basics.md +++ /dev/null @@ -1,13 +0,0 @@ -+++ -title = "Audio basics" -insert_anchor_links = "right" -[extra] -weight = 1 -status = 'hidden' -+++ - -{% todo() %} - -* Demonstrate how to load and play sounds -* Discuss compatible file formats -{% end %} diff --git a/content/learn/quick-start/contributing/_index.md b/content/learn/book/contributing/_index.md similarity index 77% rename from content/learn/quick-start/contributing/_index.md rename to content/learn/book/contributing/_index.md index dad436d70a..2ed13c2326 100644 --- a/content/learn/quick-start/contributing/_index.md +++ b/content/learn/book/contributing/_index.md @@ -1,16 +1,17 @@ +++ title = "Contributing" +weight = 4 +sort_by = "weight" template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" -aliases = ["learn/book/contributing"] [extra] subtitle = "join the bevy" -weight = 4 +++ Bevy is built by volunteers. If you want to help us build the next great game engine, [please reach out](/community)! We need all the help we can get: -* If you are a software developer and you want to help out, check out the [Contributing Code](code) section. -* If you are good at teaching or writing, consider [contributing to our docs](docs). +* If you are a software developer and you want to help out, check out the [Contributing Code](/learn/book/contributing/code) section. +* If you are good at teaching or writing, consider [contributing to our docs](/learn/book/contributing/docs). We want Bevy to be a vibrant developer community ... that's actually why we chose the name! A Bevy is a group of birds, just like we are a group of game developers. Join the Bevy! diff --git a/content/learn/quick-start/contributing/code.md b/content/learn/book/contributing/code/_index.md similarity index 93% rename from content/learn/quick-start/contributing/code.md rename to content/learn/book/contributing/code/_index.md index 1bff1cb277..8109b24e1c 100644 --- a/content/learn/quick-start/contributing/code.md +++ b/content/learn/book/contributing/code/_index.md @@ -1,10 +1,12 @@ +++ title = "Code" +weight = 1 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" -aliases = ["learn/book/contributing/code"] [extra] long_title = "Contributing Code" -weight = 1 +++ Would you like to contribute code to Bevy? Here's how! diff --git a/content/learn/quick-start/contributing/docs.md b/content/learn/book/contributing/docs/_index.md similarity index 57% rename from content/learn/quick-start/contributing/docs.md rename to content/learn/book/contributing/docs/_index.md index f9d8232f8e..b760eb2ad3 100644 --- a/content/learn/quick-start/contributing/docs.md +++ b/content/learn/book/contributing/docs/_index.md @@ -1,10 +1,12 @@ +++ title = "Docs" +weight = 2 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" -aliases = ["learn/book/contributing/docs"] [extra] long_title = "Contributing Docs" -weight = 2 +++ ## The Bevy Book @@ -32,15 +34,22 @@ A local server should start and you should be able to access a local version of ### Rust API Doc Syntax -We use Markdown reference-style links to nicely link to the Rust API docs: +We made an extension to the markdown syntax that makes linking to Rust API docs nicer. It also gives the links special formatting. Here are some examples: -* [`HashMap`] +* Full Type Path: {{rust_type(type="struct" crate="std", mod="collections", name="HashMap")}} - ```md - [`Hashmap`]: https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html - ``` + ```{{/*rust_type(type="struct" crate="std" mod="collections" name="HashMap")*/}}``` +* Short Type: {{rust_type(type="struct", crate="std" mod="collections", name="HashMap", no_mod=true)}} + + ```{{/*rust_type(type="struct" crate="std" mod="collections" name="HashMap" no_mod=true)*/}}``` +* Function: {{rust_type(type="struct" crate="std" mod="collections" name="HashMap" no_mod=true method="insert")}} + + ```{{/*rust_type(type="struct" crate="std" mod="collections" name="HashMap" no_mod=true method="insert")*/}}``` +* Module: {{rust_mod(crate="std" mod="collections")}} + + ```{{/*rust_mod(crate="std" mod="collections")*/}}``` -[`HashMap`]: https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html +Modules from {{rust_mod(crate="std")}} will link to [https://doc.rust-lang.org](https://doc.rust-lang.org/std/index.html). Other modules (like {{rust_mod(crate="bevy_render" mod="render_graph")}} ) will link to [https://docs.rs](https://docs.rs). ## Rust API Docs diff --git a/content/learn/book/development-practices/_index.md b/content/learn/book/development-practices/_index.md deleted file mode 100644 index 045f3b0a1f..0000000000 --- a/content/learn/book/development-practices/_index.md +++ /dev/null @@ -1,13 +0,0 @@ -+++ -title = "Development Practices" -template = "docs-section.html" -insert_anchor_links = "right" -[extra] -weight = 9 -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.md b/content/learn/book/development-practices/boilerplate-reduction.md deleted file mode 100644 index 06399b8e8e..0000000000 --- a/content/learn/book/development-practices/boilerplate-reduction.md +++ /dev/null @@ -1,13 +0,0 @@ -+++ -title = "Boilerplate Reduction" -insert_anchor_links = "right" -[extra] -weight = 5 -status = 'hidden' -+++ - -{% todo() %} - -* Link to resources on macros -* Discuss custom system parameters -{% end %} diff --git a/content/learn/book/development-practices/error-handling.md b/content/learn/book/development-practices/error-handling.md deleted file mode 100644 index 5f02dc0f1d..0000000000 --- a/content/learn/book/development-practices/error-handling.md +++ /dev/null @@ -1,14 +0,0 @@ -+++ -title = "Error Handling" -insert_anchor_links = "right" -[extra] -weight = 4 -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.md b/content/learn/book/development-practices/fast-compiles.md deleted file mode 100644 index 270e01060a..0000000000 --- a/content/learn/book/development-practices/fast-compiles.md +++ /dev/null @@ -1,54 +0,0 @@ -+++ -title = "Fast Compiles" -insert_anchor_links = "right" -[extra] -weight = 2 -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.toml) 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.md b/content/learn/book/development-practices/organizing-your-code.md deleted file mode 100644 index 12dea11d37..0000000000 --- a/content/learn/book/development-practices/organizing-your-code.md +++ /dev/null @@ -1,14 +0,0 @@ -+++ -title = "Organizing Your Code" -insert_anchor_links = "right" -[extra] -weight = 1 -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.md b/content/learn/book/development-practices/testing.md deleted file mode 100644 index 7d68526efc..0000000000 --- a/content/learn/book/development-practices/testing.md +++ /dev/null @@ -1,15 +0,0 @@ -+++ -title = "Testing" -insert_anchor_links = "right" -[extra] -weight = 3 -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 deleted file mode 100644 index a95dc16366..0000000000 --- a/content/learn/book/ecs/_index.md +++ /dev/null @@ -1,83 +0,0 @@ -+++ -title = "Entities, Components and Systems" -template = "docs-section.html" -insert_anchor_links = "right" -[extra] -weight = 2 -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.md b/content/learn/book/ecs/change-detection.md deleted file mode 100644 index 8e84b4d953..0000000000 --- a/content/learn/book/ecs/change-detection.md +++ /dev/null @@ -1,6 +0,0 @@ -+++ -title = "Reliable Change Detection" -[extra] -weight = 6 -status = 'hidden' -+++ diff --git a/content/learn/book/ecs/commands.md b/content/learn/book/ecs/commands.md deleted file mode 100644 index ab594b350a..0000000000 --- a/content/learn/book/ecs/commands.md +++ /dev/null @@ -1,7 +0,0 @@ -+++ -title = "Manipulating Entities With Commands" -insert_anchor_links = "right" -[extra] -weight = 4 -status = 'hidden' -+++ diff --git a/content/learn/book/ecs/entities-components.md b/content/learn/book/ecs/entities-components.md deleted file mode 100644 index 404c06a333..0000000000 --- a/content/learn/book/ecs/entities-components.md +++ /dev/null @@ -1,368 +0,0 @@ -+++ -title = "Entities Have Components" -insert_anchor_links = "right" -[extra] -weight = 1 -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,hide_lines=1 -# 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,hide_lines=1 -# 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,hide_lines=1-20 -# 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,hide_lines=1-4 -# 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,hide_lines=1-20 -# 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,hide_lines=1-19 -# 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.md b/content/learn/book/ecs/exclusive-world-access.md deleted file mode 100644 index cd296d8add..0000000000 --- a/content/learn/book/ecs/exclusive-world-access.md +++ /dev/null @@ -1,15 +0,0 @@ -+++ -title = "Exclusive World Access" -insert_anchor_links = "right" -[extra] -weight = 8 -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.md b/content/learn/book/ecs/filtering-queries.md deleted file mode 100644 index 5f9a89df1e..0000000000 --- a/content/learn/book/ecs/filtering-queries.md +++ /dev/null @@ -1,6 +0,0 @@ -+++ -title = "Filtering Queries" -[extra] -weight = 5 -status = 'hidden' -+++ diff --git a/content/learn/book/ecs/generic-systems.md b/content/learn/book/ecs/generic-systems.md deleted file mode 100644 index cdf27de71d..0000000000 --- a/content/learn/book/ecs/generic-systems.md +++ /dev/null @@ -1,6 +0,0 @@ -+++ -title = "Generic Systems" -[extra] -weight = 7 -status = 'hidden' -+++ diff --git a/content/learn/book/ecs/resources.md b/content/learn/book/ecs/resources.md deleted file mode 100644 index a95ec3bded..0000000000 --- a/content/learn/book/ecs/resources.md +++ /dev/null @@ -1,16 +0,0 @@ -+++ -title = "Resources Are Global Singletons" -insert_anchor_links = "right" -[extra] -weight = 3 -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.md b/content/learn/book/ecs/systems-queries.md deleted file mode 100644 index 32ca33bec1..0000000000 --- a/content/learn/book/ecs/systems-queries.md +++ /dev/null @@ -1,7 +0,0 @@ -+++ -title = "Systems Access Data Through Queries" -insert_anchor_links = "right" -[extra] -weight = 2 -status = 'hidden' -+++ diff --git a/content/learn/book/game-logic/_index.md b/content/learn/book/game-logic/_index.md deleted file mode 100644 index bd7d718cc3..0000000000 --- a/content/learn/book/game-logic/_index.md +++ /dev/null @@ -1,13 +0,0 @@ -+++ -title = "Game Logic" -template = "docs-section.html" -insert_anchor_links = "right" -[extra] -weight = 3 -status = 'hidden' -+++ - -{% todo() %} - -* Discuss what's in this chapter -{% end %} diff --git a/content/learn/book/game-logic/async-tasks.md b/content/learn/book/game-logic/async-tasks.md deleted file mode 100644 index bdd234a72e..0000000000 --- a/content/learn/book/game-logic/async-tasks.md +++ /dev/null @@ -1,15 +0,0 @@ -+++ -title = "Async Tasks" -insert_anchor_links = "right" -[extra] -weight = 6 -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.md b/content/learn/book/game-logic/custom-runners-headless-operations.md deleted file mode 100644 index f6373dc79f..0000000000 --- a/content/learn/book/game-logic/custom-runners-headless-operations.md +++ /dev/null @@ -1,15 +0,0 @@ -+++ -title = "Custom Runners and Headless Operation" -insert_anchor_links = "right" -[extra] -weight = 7 -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.md b/content/learn/book/game-logic/events.md deleted file mode 100644 index 60e6070c22..0000000000 --- a/content/learn/book/game-logic/events.md +++ /dev/null @@ -1,15 +0,0 @@ -+++ -title = "Events" -insert_anchor_links = "right" -[extra] -weight = 2 -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.md b/content/learn/book/game-logic/run-criteria.md deleted file mode 100644 index b14f8e8bfd..0000000000 --- a/content/learn/book/game-logic/run-criteria.md +++ /dev/null @@ -1,15 +0,0 @@ -+++ -title = "Run Criteria and Fixed Timestep" -insert_anchor_links = "right" -[extra] -weight = 5 -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.md b/content/learn/book/game-logic/states.md deleted file mode 100644 index ebaa2933e9..0000000000 --- a/content/learn/book/game-logic/states.md +++ /dev/null @@ -1,15 +0,0 @@ -+++ -title = "States" -insert_anchor_links = "right" -[extra] -weight = 3 -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.md b/content/learn/book/game-logic/system-ordering.md deleted file mode 100644 index f12105daa1..0000000000 --- a/content/learn/book/game-logic/system-ordering.md +++ /dev/null @@ -1,17 +0,0 @@ -+++ -title = "Stages and System Ordering" -insert_anchor_links = "right" -[extra] -weight = 1 -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.md b/content/learn/book/game-logic/time-timers.md deleted file mode 100644 index fb06672488..0000000000 --- a/content/learn/book/game-logic/time-timers.md +++ /dev/null @@ -1,17 +0,0 @@ -+++ -title = "Time and Timers" -insert_anchor_links = "right" -[extra] -weight = 4 -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 1cbebc0f56..1de686807c 100644 --- a/content/learn/book/getting-started/_index.md +++ b/content/learn/book/getting-started/_index.md @@ -1,8 +1,64 @@ +++ title = "Getting Started" +weight = 2 +sort_by = "weight" template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" -[extra] -weight = 1 -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.md b/content/learn/book/getting-started/app-appbuilder-world.md deleted file mode 100644 index a58bb4f787..0000000000 --- a/content/learn/book/getting-started/app-appbuilder-world.md +++ /dev/null @@ -1,6 +0,0 @@ -+++ -title = "App, Appbuilder, and World" -[extra] -weight = 3 -status = 'hidden' -+++ diff --git a/content/learn/book/getting-started/apps/_index.md b/content/learn/book/getting-started/apps/_index.md new file mode 100644 index 0000000000..953a04993a --- /dev/null +++ b/content/learn/book/getting-started/apps/_index.md @@ -0,0 +1,26 @@ ++++ +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.md b/content/learn/book/getting-started/bevy-community.md deleted file mode 100644 index 503f882e81..0000000000 --- a/content/learn/book/getting-started/bevy-community.md +++ /dev/null @@ -1,6 +0,0 @@ -+++ -title = "The Bevy Community" -[extra] -weight = 5 -status = 'hidden' -+++ diff --git a/content/learn/quick-start/getting-started/ecs.md b/content/learn/book/getting-started/ecs/_index.md similarity index 71% rename from content/learn/quick-start/getting-started/ecs.md rename to content/learn/book/getting-started/ecs/_index.md index 2575f6e360..3a1391ddb5 100644 --- a/content/learn/quick-start/getting-started/ecs.md +++ b/content/learn/book/getting-started/ecs/_index.md @@ -1,9 +1,10 @@ +++ title = "ECS" -insert_anchor_links = "right" -aliases = ["learn/book/getting-started/ecs"] -[extra] weight = 3 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +++ All app logic in Bevy uses the Entity Component System paradigm, which is often shortened to ECS. ECS is a software pattern that involves breaking your program up into **Entities**, **Components**, and **Systems**. **Entities** are unique "things" that are assigned groups of **Components**, which are then processed using **Systems**. @@ -16,18 +17,16 @@ The ECS pattern encourages clean, decoupled designs by forcing you to break up y Bevy ECS is Bevy's implementation of the ECS pattern. Unlike other Rust ECS implementations, which often require complex lifetimes, traits, builder patterns, or macros, Bevy ECS uses normal Rust datatypes for all of these concepts: -* **Components**: Rust structs that implement the [`Component`] trait +* **Components**: Rust structs that implement the `Component` trait - ```rs,hide_lines=1 - # use bevy::prelude::*; + ```rs #[derive(Component)] struct Position { x: f32, y: f32 } ``` * **Systems**: normal Rust functions - ```rs,hide_lines=1 - # use bevy::prelude::*; + ```rs fn print_position_system(query: Query<&Position>) { for position in &query { println!("position: {} {}", position.x, position.y); @@ -37,30 +36,27 @@ Bevy ECS is Bevy's implementation of the ECS pattern. Unlike other Rust ECS impl * **Entities**: a simple type containing a unique integer - ```rs,hide_lines=1 - # use bevy::prelude::*; + ```rs struct Entity(u64); ``` Now let's see how this works in practice! -[`Component`]: https://docs.rs/bevy/latest/bevy/ecs/component/trait.Component.html - ## Your First System Paste the following function into your `main.rs` file: -```rs,hide_lines=1 -# use bevy::prelude::*; +```rs fn hello_world() { println!("hello world!"); } ``` -This will be our first system. The only remaining step is to add it to our [`App`]! +This will be our first system. The only remaining step is to add it to our `App`! + +```rs +use bevy::prelude::*; -```rs,hide_lines=1 -# use bevy::prelude::*; fn main() { App::new() .add_systems(Update, hello_world) @@ -68,39 +64,31 @@ fn main() { } ``` -The [`add_systems`] function adds the system to your App's [`Update`] [`Schedule`], but we'll cover that more later. +The {{rust_type(type="struct" crate="bevy_app", name="App" method="add_systems" no_struct=true)}} function adds the system to your App's {{rust_type(type="struct", crate="bevy_app", name="Update")}} {{rust_type(type="struct", crate="bevy_ecs", mod="schedule" no_mod=true name="Schedule")}}, but we'll cover that more later. Now run your app again using `cargo run`. You should see `hello world!` printed once in your terminal. -[`add_systems`]: https://docs.rs/bevy_app/latest/bevy_app/struct.App.html#method.add_systems -[`Update`]: https://docs.rs/bevy/latest/bevy/app/struct.Update.html -[`Schedule`]: https://docs.rs/bevy_ecs/latest/bevy_ecs/schedule/struct.Schedule.html -[`App`]: https://docs.rs/bevy/latest/bevy/app/struct.App.html - ## Your First Components Greeting the whole world is great, but what if we want to greet specific people? In ECS, you would generally model people as entities with a set of components that define them. Let's start simple with a `Person` component. Add this struct to your `main.rs` file: -```rs,hide_lines=1 -# use bevy::prelude::*; +```rs #[derive(Component)] struct Person; ``` But what if we want our people to have a name? In a more traditional design, we might just tack on a `name: String` field to `Person`. But other entities might have names too! For example, dogs should probably also have a name. It often makes sense to break datatypes up in to small pieces to encourage code reuse. So let's make `Name` its own component: -```rs,hide_lines=1 -# use bevy::prelude::*; +```rs #[derive(Component)] struct Name(String); ``` -We can then add people to our [`World`] using a "startup system". Startup systems are just like normal systems, but they run exactly once, before all other systems, right when our app starts. Let's use [`Commands`] to spawn some entities into our [`World`]\: +We can then add people to our {{rust_type(type="struct" crate="bevy_ecs" mod="world" no_mod=true name="World")}} using a "startup system". Startup systems are just like normal systems, but they run exactly once, before all other systems, right when our app starts. Let's use {{rust_type(type="struct" crate="bevy_ecs" mod="system" no_mod=true name="Commands")}} to spawn some entities into our {{rust_type(type="struct" crate="bevy_ecs" mod="world" no_mod=true name="World")}}: -```rs,hide_lines=1 -# use bevy::prelude::*; +```rs fn add_people(mut commands: Commands) { commands.spawn((Person, Name("Elaina Proctor".to_string()))); commands.spawn((Person, Name("Renzo Hume".to_string()))); @@ -110,8 +98,7 @@ fn add_people(mut commands: Commands) { Now register the startup system like this: -```rs,hide_lines=1 -# use bevy::prelude::*; +```rs fn main() { App::new() .add_systems(Startup, add_people) @@ -120,15 +107,11 @@ fn main() { } ``` -[`World`]: https://docs.rs/bevy/latest/bevy/ecs/world/struct.World.html -[`Commands`]: https://docs.rs/bevy/latest/bevy/ecs/system/struct.Commands.html - ## Your First Query -We could run this now and the `add_people` system would run first, followed by `hello_world`. But our new people don't have anything to do yet! Let's make a system that properly greets the new citizens of our [`World`]: +We could run this now and the `add_people` system would run first, followed by `hello_world`. But our new people don't have anything to do yet! Let's make a system that properly greets the new citizens of our {{rust_type(type="struct" crate="bevy_ecs" mod="world" no_mod=true name="World")}}: -```rs,hide_lines=1 -# use bevy::prelude::*; +```rs fn greet_people(query: Query<&Name, With>) { for name in &query { println!("hello {}!", name.0); @@ -138,13 +121,11 @@ fn greet_people(query: Query<&Name, With>) { The parameters we pass into a "system function" define what data the system runs on. In this case, `greet_people` will run on all entities with the `Person` and `Name` component. -You can interpret the [`Query`] above as: "iterate over every `Name` component for entities that also have a `Person` component". +You can interpret the `Query` above as: "iterate over every `Name` component for entities that also have a `Person` component". Now we just register the system in our `App`. Note that you can pass more than one system into an `add_systems` call by using a tuple! -[`Query`]: -```rs,hide_lines=1 -# use bevy::prelude::*; +```rs fn main() { App::new() .add_systems(Startup, add_people) @@ -170,8 +151,7 @@ Marvelous! If we want to change the names of some people (perhaps they got married!), for example, we can do this using a mutable query: -```rs,hide_lines=1 -# use bevy::prelude::*; +```rs fn update_people(mut query: Query<&mut Name, With>) { for mut name in &mut query { if name.0 == "Elaina Proctor" { @@ -184,10 +164,9 @@ fn update_people(mut query: Query<&mut Name, With>) { We need to make `query` mutable, and use a mutable reference (`&mut`) to the components we want to change. -Don’t forget to add the system to the [`Update`] schedule: +Don’t forget to add the system to the {{rust_type(type="struct", crate="bevy_app", name="Update")}} schedule: -```rs,hide_lines=1 -# use bevy::prelude::*; +```rs fn main() { App::new() .add_systems(Startup, add_people) @@ -196,7 +175,7 @@ fn main() { } ``` -Note that we have used `.chain()` on the two systems. This is because we want them two to run in exactly the order they're listed in the code: with `update_people` occurring before `greet_people`. +Note that we have used `.chain()` on the two systems. This is because we want both of them to run in exactly the order they're listed in the code: with `update_people` occurring before `greet_people`. If they weren’t, the name might change after we greet the people. But we don’t add the `hello_world` system to the chain, because it doesn’t matter when it runs. This way, Bevy can run `hello_world` in parallel while the other systems are running. diff --git a/content/learn/book/getting-started/installation.md b/content/learn/book/getting-started/installation.md deleted file mode 100644 index 00b1a80a59..0000000000 --- a/content/learn/book/getting-started/installation.md +++ /dev/null @@ -1,6 +0,0 @@ -+++ -title = "Installing Rust and Bevy" -[extra] -weight = 2 -status = 'hidden' -+++ diff --git a/content/learn/book/getting-started/modular-plugins.md b/content/learn/book/getting-started/modular-plugins.md deleted file mode 100644 index 5361b535ba..0000000000 --- a/content/learn/book/getting-started/modular-plugins.md +++ /dev/null @@ -1,6 +0,0 @@ -+++ -title = "Plugins as Modular Building Blocks" -[extra] -weight = 4 -status = 'hidden' -+++ diff --git a/content/learn/book/getting-started/plugins/_index.md b/content/learn/book/getting-started/plugins/_index.md new file mode 100644 index 0000000000..a8b62132f6 --- /dev/null +++ b/content/learn/book/getting-started/plugins/_index.md @@ -0,0 +1,81 @@ ++++ +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 new file mode 100644 index 0000000000..fc1f9700ee --- /dev/null +++ b/content/learn/book/getting-started/resources/_index.md @@ -0,0 +1,66 @@ ++++ +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

    Past Sponsors

    diff --git a/templates/layouts/base.html b/templates/layouts/base.html index c59e2b57b6..584f00dee5 100644 --- a/templates/layouts/base.html +++ b/templates/layouts/base.html @@ -4,164 +4,139 @@ {% set current_path = current_path | default(value="/") %} {% if section and section.title %} -{% if section.path is starting_with("/learn/book/") %} -{% set page_title = "Bevy Book: " ~ section.title %} -{% elif section.path is starting_with("/assets") %} -{% set page_title = "Bevy Assets" %} -{% else %} -{% set page_title = section.title %} -{% endif %} + {% if section.path is starting_with("/learn/book/") %} + {% set page_title = "Bevy Book: " ~ section.title %} + {% elif section.path is starting_with("/assets") %} + {% set page_title = "Bevy Assets" %} + {% else %} + {% set page_title = section.title %} + {% endif %} {% elif page and page.title %} -{% if page.path is starting_with("/learn/book/") %} -{% set page_title = "Bevy Book: " ~ page.title %} -{% elif page.path is starting_with("/assets") %} -{% set page_title = "Bevy Assets" %} + {% set page_title = page.title %} {% else %} -{% set page_title = page.title %} -{% endif %} -{% else %} -{% set page_title = "Bevy Engine"%} + {% set page_title = "Bevy Engine"%} {% endif %} {% if section and section.path %} -{% set path = "/" ~ section.path %} + {% set path = "/" ~ section.path %} {% elif page and page.path %} -{% set path = "/" ~ page.path %} + {% set path = "/" ~ page.path %} {% else %} -{% set path = ""%} + {% set path = ""%} {% endif %} {% if section %} -{% if section.path is starting_with("/learn/book/") %} -{% set show_nav_toggle = true %} -{% elif section.path is starting_with("/learn/migration-guides/") %} -{% set show_nav_toggle = true %} -{% elif section.path is starting_with("/assets/") %} -{% set show_nav_toggle = true %} -{% endif %} -{% elif page %} -{% if page.path is starting_with("/learn/book/") or page.path is starting_with("/learn/migration-guides/") or page.path -is starting_with("/assets/") %} -{% set show_nav_toggle = true %} -{% endif %} + {% if section.path is starting_with("/learn/book/") %} + {% set show_nav_toggle = true %} + {% elif section.path is starting_with("/learn/migration-guides/") %} + {% set show_nav_toggle = true %} + {% elif section.path is starting_with("/assets/") %} + {% set show_nav_toggle = true %} + {% endif %} {% endif %} - - - - - - - - - - - - - {{page_title}} - {% block head_extensions %} {% endblock %} - - - -
    - -
    -
    - - -
    - -
    - {% if section and section.extra.header_message %} - {{section.extra.header_message}} - {% elif page and page.extra.header_message %} - {{page.extra.header_message}} - {% elif section and section.path is starting_with("/learn/book/") or page and page.path is - starting_with("/learn/book/") %} - The Book - {% elif section and section.path is starting_with("/learn/quick-start/") or page and page.path is - starting_with("/learn/quick-start/") %} - Quick Start - {% elif section and section.path is starting_with("/learn/migration-guides/") or page and page.path is - starting_with("/learn/migration-guides/") %} - Migration Guides - {% elif section and section.path is starting_with("/news/") %} - News - {% elif page and page.path is starting_with("/news/") %} - News - {% else %} - Features - {% endif %} -
    + + + + + + + + + + + + {{page_title}} + {% block head_extensions %} {% endblock %} + + +
    + +
    +
    + + +
    + +
    + {% if section and section.extra.header_message %} + {{section.extra.header_message}} + {% elif page and page.extra.header_message %} + {{page.extra.header_message}} + {% elif section and section.path is starting_with("/learn/book/") %} + The Book + {% elif section and section.path is starting_with("/learn/migration-guides/") %} + Migration Guides + {% elif section and section.path is starting_with("/news/") %} + News + {% elif page and page.path is starting_with("/news/") %} + News + {% else %} + Features + {% endif %} +
    +
    + {% block mobile_page_menu_state %}{% endblock %} + + +
    +
    +
    +
    + {% if section %} + {{ public_draft::warning(section=section) }} + {% endif %} + {% block content %}{% endblock %} +
    +
    - {% block mobile_page_menu_state %}{% endblock %} - - -
    -
    -
    -
    - {% if section %} - {{ public_draft::warning(section=section) }} - {% elif page %} - {{ public_draft::warning(section=page) }} - {% endif %} - {% block content %}{% endblock %} -
    -
    -
    - - - - \ No newline at end of file + + + diff --git a/templates/macros/assets.html b/templates/macros/assets.html index be47fd6c6e..e7a6082cc7 100644 --- a/templates/macros/assets.html +++ b/templates/macros/assets.html @@ -2,55 +2,54 @@ {% macro init_svg() %} - - - - - < - - + + + + < + + + {% endmacro init_svg %} {% macro card(post) %}
    - -
    -
    {{post.title}}
    - {% if post.extra.image %} - Showcase image - {% endif %} -
    -
    - {{ post.description | striptags | safe }} -
    -
    - {% if post.extra.bevy_versions %} -
    - - {% endif %} - {% if post.extra.licenses %} -
    -
    - - - +
    + {{ post.description | striptags | safe }}
    - {% for license in post.extra.licenses %} - {{license}} - {% endfor %} -
    - {% endif %} -
    -
    +
    + {% if post.extra.bevy_versions %} +
    +
    + Supported bevy versions +
    + {% for version in post.extra.bevy_versions %} + {{version}} + {% endfor %} +
    + {% endif %} + {% if post.extra.licenses %} +
    +
    + + + +
    + {% for license in post.extra.licenses %} + {{license}} + {% endfor %} +
    + {% endif %} +
    +
    {% endmacro card %} @@ -65,29 +64,30 @@ {% endif %}
  • -
    - {{ section.title }} +
    + {{ section.title }} + {% if section.subsections %} + + {% endif %} +
    {% if section.subsections %} - +
      + {% for s in section.subsections %} + {{ self::assets_menu_row(prefix=prefix, section_path=s) }} + {% endfor %} +
    {% endif %} -
    - {% if section.subsections %} -
      - {% for s in section.subsections %} - {{ self::assets_menu_row(prefix=prefix, section_path=s) }} - {% endfor %} -
    - {% endif %}
  • {% endmacro %} {% macro assets_menu(root, prefix) %}
      - {% for s in root.subsections %} - {{ self::assets_menu_row(prefix=prefix, section_path=s)}} - {% endfor %} + {% for s in root.subsections %} + {{ self::assets_menu_row(prefix=prefix, section_path=s)}} + {% endfor %}
    -{% endmacro %} \ No newline at end of file +{% endmacro %} diff --git a/templates/macros/docs.html b/templates/macros/docs.html index 9d3ba0096b..100b5d169d 100644 --- a/templates/macros/docs.html +++ b/templates/macros/docs.html @@ -1,4 +1,5 @@ -{% macro docs_menu_section_row(prefix, menu_section) %} +{% macro docs_menu_row(prefix, section_path) %} + {% set menu_section = get_section(path=section_path, metadata_only=true) %} {% set is_in_branch = menu_section.path in current_path %} {% set is_active = current_path == menu_section.path %} {% set id = prefix ~ '-' ~ menu_section.path | slugify %} @@ -16,13 +17,7 @@ {% endif %} {% endif %} - {% set subsections = [] %} - {% for section in menu_section.subsections %} - {% set_global subsections = subsections | concat(with=get_section(path=section)) %} - {% endfor %} - {% set pages_and_sections = menu_section.pages | concat(with=subsections) | sort(attribute="extra.weight") %} - - {% if pages_and_sections %} + {% if menu_section.subsections %} {% set label_class = label_class ~ " tree-menu__label--with-chevron" %} {% endif %} @@ -30,77 +25,34 @@
  • {{ menu_section.title }} - {% if pages_and_sections %} + {% if menu_section.subsections %} {% endif %}
    - {% if pages_and_sections %} + {% if menu_section.subsections %}
      - {% for p in pages_and_sections %} - {% if subsections is containing(p) %} - {{ self::docs_menu_section_row(prefix=prefix, menu_section=p) }} - {% elif menu_section.pages is containing(p) %} - {{ self::docs_menu_page_row(prefix=prefix, menu_page=p) }} - {% endif %} + {% for s in menu_section.subsections %} + {{ self::docs_menu_row(prefix=prefix, section_path=s) }} {% endfor %}
    {% endif %}
  • -{% endmacro docs_menu_section_row %} - -{% macro docs_menu_page_row(prefix, menu_page) %} - {% set is_in_branch = menu_page.path in current_path %} - {% set is_active = current_path == menu_page.path %} - {% set id = prefix ~ '-' ~ menu_page.path | slugify %} - {% set class = "tree-menu__item" %} - {% set label_class = "tree-menu__label" %} - - {% if is_active %} - {% set class = class ~ " tree-menu__item--active" %} - {% endif %} - - {% if menu_page.extra and menu_page.extra.public_draft %} - {% set class = class ~ " public_draft" %} - {% if is_in_branch %} - {% set class = class ~ " active_draft" %} - {% endif %} - {% endif %} - -
  • - -
  • -{% endmacro docs_menu_page_row %} +{% endmacro docs_menu_row %} {% macro docs_menu(root, prefix) %}
      - {% set is_migration_guide = current_path is starting_with("/learn/migration-guides") %} - - {% set subsections = [] %} - {% for subsection in root.subsections %} - {% set proper_section = get_section(path=subsection) %} - {% set_global subsections = subsections | concat(with=proper_section) %} - {% endfor %} - {% set pages_and_sections = root.pages | concat(with=subsections) | sort(attribute="extra.weight") %} - {% if is_migration_guide %} - {% for p in pages_and_sections | reverse %} - {% if subsections is containing(p) %} - {{ self::docs_menu_section_row(prefix=prefix, menu_section=p) }} - {% elif root.pages is containing(p) %} - {{ self::docs_menu_page_row(prefix=prefix, menu_page=p) }} - {% endif %} - {% endfor %} + {# Migration Guides #} + {% if section and section.path is starting_with("/learn/migration-guides") %} + {% for s in root.subsections | reverse %} + {{ self::docs_menu_row(prefix=prefix, section_path=s) }} + {% endfor %} + {# Other #} {% else %} - {% for p in pages_and_sections %} - {% if subsections is containing(p) %} - {{ self::docs_menu_section_row(prefix=prefix, menu_section=p) }} - {% elif root.pages is containing(p) %} - {{ self::docs_menu_page_row(prefix=prefix, menu_page=p) }} - {% endif %} - {% endfor %} + {% for s in root.subsections %} + {{ self::docs_menu_row(prefix=prefix, section_path=s) }} + {% endfor %} {% endif %}
    {% endmacro %} diff --git a/templates/news.html b/templates/news.html index 45ec984d97..753d9990ac 100644 --- a/templates/news.html +++ b/templates/news.html @@ -3,30 +3,28 @@ {% block content %} {% endblock content %} diff --git a/templates/people.html b/templates/people.html index 4d7adb4561..bedf306247 100644 --- a/templates/people.html +++ b/templates/people.html @@ -13,258 +13,242 @@ {% block page_content %} - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    -
    - The Bevy community! If you want to see yourself here, submit - a pull request! -
    - {% for subsection in section.subsections %} - {% set section = get_section(path=subsection) %} - - -

    - {{ section.title }}# -

    - - {% if section.title == "The Bevy Organization" %} -
    -

    - The Bevy Organization is the group of people responsible for stewarding the Bevy project. It handles things - like choosing project direction, merging pull requests, managing bugs / issues / feature requests, running - the Bevy website, controlling access to secrets, defining and enforcing best practices, etc. -

    -

    - Anyone with a history of contributing to Bevy can join the Bevy Organization. Reach out to the Project Lead - if you would like to join! -

    -

    - -

    - Roles# -

    -
    -
    -
    Project Leads
    -
    have the final call on all design and code changes within Bevy. They - are responsible for representing the project publicly and they choose how the project is organized.
    -
    -
    -
    Maintainers
    -
    have merge rights in Bevy repos. They assess the scope of pull - requests and whether they fit into the Bevy project's vision. They also serve as representatives of the Bevy - project.
    -
    -
    -
    SMEs
    -
    (Subject Matter Experts) have proven themselves to be experts in a - given development area. They help guide Bevy's direction in their area and they are great people to reach out - to if you have questions about a given area.
    -
    -
    -
    Other members, without a special role, are part of the GitHub - organization. They have the power to manage GitHub issues and pull requests.
    -
    +
    + The Bevy community! If you want to see yourself here, submit a pull request!
    -

    -
    - {% endif %} - - {% if section.title == "The Bevy Organization" %} - -

    - Members# -

    - {% endif %} - - {% if section.title == "Community Members" %} -
    -

    - People in the Bevy community who are not part of the organization. -

    -

    - Anyone can add themselves here! Submit a pull request! -

    -
    - {% endif %} - - {% if section.pages %} -
    - {% set pages = section.pages %} - {% if section.extra.sort_order_reversed %} - {% set pages = section.pages | reverse %} - {% endif %} - - {% for post in pages %} - -
    -
    -
    -
    - {{ post.title }} -
    - {% if post.extra.profile_picture %} -
    - {% if post.extra.profile_picture is starting_with("https://") %} - - {% else %} - - {% endif %} -
    - {% endif %} -
    -
    - + {% endif %} {% endfor %} -
    - {% endif %} - - {% endfor %}
    {% endblock content %} diff --git a/templates/shortcodes/rust_mod.html b/templates/shortcodes/rust_mod.html new file mode 100644 index 0000000000..37958705a2 --- /dev/null +++ b/templates/shortcodes/rust_mod.html @@ -0,0 +1,24 @@ + +{% if not crate %} +{% set crate = "std" %} +{% endif %} + +{% if not version %} +{% set version = "latest" %} +{% endif %} + +{% if mod %} +{% set mod_path = "/" ~ mod | replace(from="::", to="/") %} +{% else %} +{% set mod_path = "" %} +{% endif %} + +{% if crate == "std" %} +{% set url = "https://doc.rust-lang.org" %} +{% set path = "stable/" ~ crate %} +{% else %} +{% set url = "https://docs.rs" %} +{% set path = crate ~ "/" ~ version ~ "/" ~ crate %} +{% endif %} + +{% if not no_crate and crate%}{{crate}}{% if not no_mod and mod%}::{{mod}}{% endif %}{% elif not no_mod and mod%}{{mod}}{% endif %} diff --git a/templates/shortcodes/rust_type.html b/templates/shortcodes/rust_type.html new file mode 100644 index 0000000000..11e52f882b --- /dev/null +++ b/templates/shortcodes/rust_type.html @@ -0,0 +1,28 @@ +{% if not crate %} +{% set crate = "std" %} +{% endif %} + +{% if not version %} +{% set version = "latest" %} +{% endif %} + +{% if not mod %} +{% set mod_path = "" %} +{% set mod = "" %} +{% else %} +{% set mod_path = "/" ~ mod | replace(from="::", to="/") %} +{% endif %} + +{% if crate == "std" %} +{% set url = "https://doc.rust-lang.org" %} +{% set path = "stable/" ~ crate %} +{% else %} +{% set url = "https://docs.rs" %} +{% set path = crate ~ "/" ~ version ~ "/" ~ crate %} +{% endif %} + +{% if plural %} +{{ throw(message="the plural option is no longer used. just put an 's' after the shortcode.") }} +{% endif %} + +{% if not no_crate and crate and not no_mod and mod %}{{crate}}::{% if not no_mod and mod%}{{mod}}::{% endif %}{% elif not no_mod and mod%}{{mod}}::{% endif %}{% if not no_struct %}{{name}}{% endif %}{% if method %}{% if not no_struct %}::{% endif %}{{method}}(){% endif %} \ No newline at end of file diff --git a/templates/shortcodes/todo.html b/templates/shortcodes/todo.html deleted file mode 100644 index 22b73c5a46..0000000000 --- a/templates/shortcodes/todo.html +++ /dev/null @@ -1,4 +0,0 @@ -
    -

    TODO

    - {{ body | markdown | safe }} -
    \ No newline at end of file diff --git a/templates/sitemap.xml b/templates/sitemap.xml deleted file mode 100644 index 5a7d82b1b6..0000000000 --- a/templates/sitemap.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - {% for sitemap_entry in entries %} - {% if not sitemap_entry.extra.status %} - - {{ sitemap_entry.permalink | escape_xml | safe }} - {% if sitemap_entry.updated %} - {{ sitemap_entry.updated }} - {% endif %} - - {% endif %} - {% endfor %} - \ No newline at end of file diff --git a/write-rustdoc-hide-lines/.gitignore b/write-rustdoc-hide-lines/.gitignore deleted file mode 100644 index ea8c4bf7f3..0000000000 --- a/write-rustdoc-hide-lines/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/write-rustdoc-hide-lines/Cargo.lock b/write-rustdoc-hide-lines/Cargo.lock deleted file mode 100644 index 83409b5557..0000000000 --- a/write-rustdoc-hide-lines/Cargo.lock +++ /dev/null @@ -1,68 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "anyhow" -version = "1.0.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" - -[[package]] -name = "indoc" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2d6f23ffea9d7e76c53eee25dfb67bcd8fde7f1198b0855350698c9f07c780" - -[[package]] -name = "memchr" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" - -[[package]] -name = "regex" -version = "1.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "write-rustdoc-hide-lines" -version = "0.1.0" -dependencies = [ - "anyhow", - "indoc", - "regex", -] diff --git a/write-rustdoc-hide-lines/Cargo.toml b/write-rustdoc-hide-lines/Cargo.toml deleted file mode 100644 index 43f01bf13b..0000000000 --- a/write-rustdoc-hide-lines/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "write-rustdoc-hide-lines" -version = "0.1.0" -edition = "2021" - -[dependencies] -anyhow = "1.0" -regex = "1.5" - -[dev-dependencies] -indoc = "1.0" diff --git a/write-rustdoc-hide-lines/README.md b/write-rustdoc-hide-lines/README.md deleted file mode 100644 index 5e57d787ef..0000000000 --- a/write-rustdoc-hide-lines/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Write `rustdoc` `hide_lines` annotations - -This utility iterates over the Markdown files on the given folder. -Searches `rust` code blocks and ensures that the [`hide_lines` Zola annotation] match the code block "hidden" lines (the ones starting with `#`). -If the annotation doesn't match the code block this utility will update it. - -[`hide_lines` Zola annotation]: https://www.getzola.org/documentation/content/syntax-highlighting/#annotations - -## Usage - -Just run: - -```sh -./write_rustdoc_hide_lines.sh -``` - -This will run the utility over the Book Markdown files. diff --git a/write-rustdoc-hide-lines/src/code_block_definition.rs b/write-rustdoc-hide-lines/src/code_block_definition.rs deleted file mode 100644 index c374f615fd..0000000000 --- a/write-rustdoc-hide-lines/src/code_block_definition.rs +++ /dev/null @@ -1,267 +0,0 @@ -use std::ops::Range; - -use regex::Regex; - -use crate::hidden_ranges::HiddenRanges; - -#[derive(Debug, PartialEq)] -enum Annotation { - HideLines(HiddenRanges), - Other(String), -} - -impl From<&str> for Annotation { - fn from(text: &str) -> Self { - const HIDE_LINES: &str = "hide_lines="; - let is_hide_lines = text.starts_with(HIDE_LINES); - - if is_hide_lines { - Annotation::HideLines( - text.get(HIDE_LINES.len()..) - .unwrap_or("") - .split(' ') - .filter(|r| r.trim() != "") - .map(|range| { - let is_range = range.contains('-'); - - if is_range { - let range = range.split('-').collect::>(); - let start = range[0].parse().unwrap(); - let end = range[1].parse().unwrap(); - - Range { start, end } - } else { - let line_no = range.parse::().unwrap(); - Range { - start: line_no, - end: line_no, - } - } - }) - .collect(), - ) - } else { - Annotation::Other(String::from(text)) - } - } -} - -impl Annotation { - fn into_string(self) -> String { - match self { - Annotation::HideLines(ranges) => { - let ranges = ranges - .iter() - .map(|r| { - if r.start == r.end { - format!("{}", r.start) - } else { - format!("{}-{}", r.start, r.end) - } - }) - .collect::>() - .join(" "); - - format!("hide_lines={}", ranges) - } - Annotation::Other(content) => content, - } - } -} - -#[derive(Debug, PartialEq)] -pub struct CodeBlockDefinition { - tag: String, - annotations: Vec, - hide_lines_idx: Option, -} - -impl CodeBlockDefinition { - pub fn new(line: &str) -> Option { - let lang_re = Regex::new(r"(\s*)```(.+)").ok()?; - let captures = lang_re.captures(line)?; - - let whitespace = captures.get(1).map(|mat| mat.as_str())?; - let lang = captures.get(2).map(|mat| mat.as_str())?; - - let mut hide_lines_idx = None; - - let mut parts = lang.split(','); - let tag = parts.next()?; - - if tag != "rs" && tag != "rust" { - return None; - } - - let annotations = parts - .enumerate() - .map(|(idx, a)| { - let annotation = Annotation::from(a); - - if let Annotation::HideLines(_) = annotation { - hide_lines_idx = Some(idx); - } - - annotation - }) - .collect(); - - Some(CodeBlockDefinition { - tag: format!("{}```{}", whitespace, tag), - annotations, - hide_lines_idx, - }) - } - - pub fn get_hidden_ranges(&self) -> Option<&HiddenRanges> { - self.hide_lines_idx.map(|idx| match &self.annotations[idx] { - Annotation::HideLines(ranges) => ranges, - Annotation::Other(_) => unreachable!(), - }) - } - - pub fn into_string(self) -> String { - let mut out = self.tag; - - if !self.annotations.is_empty() { - out.push(','); - } - - out.push_str( - &self - .annotations - .into_iter() - .map(|a| a.into_string()) - .collect::>() - .join(","), - ); - - out - } - - pub fn set_hidden_ranges(&mut self, hidden_ranges: HiddenRanges) { - if hidden_ranges.is_empty() { - // Remove - if let Some(idx) = self.hide_lines_idx { - self.annotations.remove(idx); - self.hide_lines_idx = None; - } - } else { - // Add - let annotation = Annotation::HideLines(hidden_ranges); - - match self.hide_lines_idx { - Some(idx) => self.annotations[idx] = annotation, - None => { - self.annotations.push(annotation); - self.hide_lines_idx = Some(self.annotations.len() - 1); - } - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn should_ignore_malformed_lines() { - let cases = vec!["text line", "```", "```js"]; - - for case in cases { - let definition = CodeBlockDefinition::new(case); - assert_eq!(definition, None); - } - } - - #[test] - fn should_parse_simple_lines() { - let cases = vec!["```rust", "```rs"]; - - for case in cases { - let definition = CodeBlockDefinition::new(case).unwrap(); - - assert_eq!( - definition, - CodeBlockDefinition { - tag: case.into(), - annotations: vec![], - hide_lines_idx: None, - } - ); - - assert_eq!(definition.into_string(), String::from(case)); - } - } - - #[test] - fn should_parse_other_annotations() { - let line = "```rs,linenos,linenostart=10 , hl_lines=3-4 8-9"; - let definition = CodeBlockDefinition::new(line).unwrap(); - - assert_eq!( - definition, - CodeBlockDefinition { - tag: "```rs".into(), - annotations: vec![ - Annotation::Other(String::from("linenos")), - Annotation::Other(String::from("linenostart=10 ")), - Annotation::Other(String::from(" hl_lines=3-4 8-9")), - ], - hide_lines_idx: None, - } - ); - - assert_eq!(definition.into_string(), String::from(line)); - } - - fn new_range(start: usize, end: usize) -> Range { - Range { start, end } - } - - #[test] - fn should_parse_hide_lines_annotations() { - let line = "```rust,hide_lines=3-4 9"; - let definition = CodeBlockDefinition::new(line).unwrap(); - - assert_eq!( - definition, - CodeBlockDefinition { - tag: "```rust".into(), - annotations: vec![Annotation::HideLines(vec![ - new_range(3, 4), - new_range(9, 9), - ])], - hide_lines_idx: Some(0), - } - ); - - assert_eq!(definition.into_string(), String::from(line)); - } - - #[test] - fn should_parse_annotations() { - let line = "```rust, linenos,hide_lines=3-9 ,linenostart=10 ,hl_lines=10-12"; - let definition = CodeBlockDefinition::new(line).unwrap(); - - assert_eq!( - definition, - CodeBlockDefinition { - tag: "```rust".into(), - annotations: vec![ - Annotation::Other(String::from(" linenos")), - Annotation::HideLines(vec![new_range(3, 9)]), - Annotation::Other(String::from("linenostart=10 ")), - Annotation::Other(String::from("hl_lines=10-12")), - ], - hide_lines_idx: Some(1), - } - ); - - assert_eq!( - definition.into_string(), - "```rust, linenos,hide_lines=3-9,linenostart=10 ,hl_lines=10-12" - ); - } -} diff --git a/write-rustdoc-hide-lines/src/formatter.rs b/write-rustdoc-hide-lines/src/formatter.rs deleted file mode 100644 index ad61c97c87..0000000000 --- a/write-rustdoc-hide-lines/src/formatter.rs +++ /dev/null @@ -1,269 +0,0 @@ -use anyhow::Result; -use regex::Regex; -use std::{ - ffi::OsStr, - fmt::Write, - fs::{self, DirEntry, File}, - io::{self, BufRead}, - path::Path, -}; - -use crate::{code_block_definition::CodeBlockDefinition, hidden_ranges::get_hidden_ranges}; - -pub fn run(dir: &Path) -> Result<()> { - visit_dir_md_files(dir, &|entry| { - println!("{:?}", entry.path()); - - // Load and format file annotations - let file = File::open(entry.path())?; - let file_size = file.metadata().unwrap().len().try_into().unwrap(); - let contents = format_file( - io::BufReader::new(file) - .lines() - .map(|line| line.map_err(anyhow::Error::from)), - file_size, - )?; - - // Rewrite file - fs::write(entry.path(), contents)?; - - Ok(()) - }) -} - -fn visit_dir_md_files(dir: &Path, cb: &dyn Fn(&DirEntry) -> Result<()>) -> Result<()> { - if !dir.is_dir() { - return Ok(()); - } - - for entry in fs::read_dir(dir)? { - let entry = entry?; - let path = entry.path(); - - if path.is_dir() { - visit_dir_md_files(&path, cb)?; - } else if let Some(ext) = path.extension().and_then(OsStr::to_str) { - if ext.to_lowercase() == "md" { - cb(&entry)?; - } - } - } - - Ok(()) -} - -fn format_file(reader: impl Iterator>, file_size: usize) -> Result { - let mut contents = String::with_capacity(file_size); - let mut rust_block: Vec = vec![]; - let mut is_rust = false; - - let mut inside_code_block = false; - - // Find a code block delimiter and optionally the first specified language - let code_block_delim = Regex::new(r"\s*```(\w*)")?; - - for line in reader { - let line = line?; - - let code_block_delim_match = code_block_delim.captures(&line).and_then(|cap| cap.get(1)); - let is_code_block_delim = code_block_delim_match.is_some(); - - if !inside_code_block && is_code_block_delim { - let lang = code_block_delim_match.unwrap().as_str(); - if lang == "rust" || lang == "rs" { - is_rust = true; - } - - inside_code_block = true; - } else if inside_code_block && is_code_block_delim { - inside_code_block = false; - } - - // Pass through non-rust code block contents and contents outside of code blocks. - if !is_rust { - writeln!(&mut contents, "{}", &line)?; - continue; - } - - rust_block.push(line); - - if inside_code_block { - continue; - } - - // Process the `rust `code block - let code = &rust_block[1..rust_block.len() - 1]; - let real_hidden_ranges = get_hidden_ranges(code); - let mut definition = CodeBlockDefinition::new(&rust_block[0]).unwrap(); - - match definition.get_hidden_ranges() { - Some(annotation_hidden_ranges) => { - if *annotation_hidden_ranges != real_hidden_ranges { - definition.set_hidden_ranges(real_hidden_ranges); - } - } - None => { - if !real_hidden_ranges.is_empty() { - definition.set_hidden_ranges(real_hidden_ranges); - } - } - } - - // Rewrite code block Zola annotations - rust_block[0] = definition.into_string(); - - // Write code block - writeln!(&mut contents, "{}", &rust_block.join("\n"))?; - - // Reset state - inside_code_block = false; - rust_block = vec![]; - is_rust = false; - } - - Ok(contents) -} - -#[cfg(test)] -mod tests { - use super::*; - use indoc::indoc; - - fn lines_iter(code: &str) -> impl Iterator> + '_ { - code.split('\n').map(|line| Ok(String::from(line))) - } - - #[test] - fn add_missing_annotation() { - let markdown = indoc! {r#" - ```rust - # test - # test 2 - fn not_hidden() { - - } - # test 3 - #[derive(Component)] - struct A; - # #[derive(Component)] - struct B; - ``` - "#}; - - let contents = format_file(lines_iter(markdown), markdown.len()); - - assert_eq!( - contents.unwrap(), - indoc! {r#" - ```rust,hide_lines=1-2 6 9 - # test - # test 2 - fn not_hidden() { - - } - # test 3 - #[derive(Component)] - struct A; - # #[derive(Component)] - struct B; - ``` - - "#} - ); - } - - #[test] - fn update_wrong_annotation() { - let markdown = indoc! {r#" - ```rust,hide_lines=2-3 7 - # test - # test 2 - fn not_hidden() { - - } - # test 3 - ``` - "#}; - - let contents = format_file(lines_iter(markdown), markdown.len()); - - assert_eq!( - contents.unwrap(), - indoc! {r#" - ```rust,hide_lines=1-2 6 - # test - # test 2 - fn not_hidden() { - - } - # test 3 - ``` - - "#} - ); - } - - #[test] - fn remove_annotation() { - let markdown = indoc! {r#" - ```rust,hide_lines=2-3 7 - fn not_hidden() { - - } - ``` - "#}; - - let contents = format_file(lines_iter(markdown), markdown.len()); - - assert_eq!( - contents.unwrap(), - indoc! {r#" - ```rust - fn not_hidden() { - - } - ``` - - "#} - ); - } - - #[test] - fn indented() { - let markdown = r#" - ```rust - # test - # test 2 - fn not_hidden() { - - } - # test 3 - #[derive(Component)] - struct A; - # #[derive(Component)] - struct B; - ``` -"#; - - let contents = format_file(lines_iter(markdown), markdown.len()); - - assert_eq!( - contents.unwrap(), - r#" - ```rust,hide_lines=1-2 6 9 - # test - # test 2 - fn not_hidden() { - - } - # test 3 - #[derive(Component)] - struct A; - # #[derive(Component)] - struct B; - ``` - -"# - ); - } -} diff --git a/write-rustdoc-hide-lines/src/hidden_ranges.rs b/write-rustdoc-hide-lines/src/hidden_ranges.rs deleted file mode 100644 index 758cf913d6..0000000000 --- a/write-rustdoc-hide-lines/src/hidden_ranges.rs +++ /dev/null @@ -1,128 +0,0 @@ -use std::ops::Range; - -use regex::Regex; - -pub type HiddenRanges = Vec>; - -// The generic is to allow both `&[String]` (slice of `Vec`) and `&[&str]` (slice of `Vec<&str>`) -// See: https://stackoverflow.com/a/41180422/379923 -pub fn get_hidden_ranges>(code: &[T]) -> HiddenRanges { - let mut ranges = vec![]; - let mut curr_range: Option> = None; - - // Match lines starting with a potentially indented `#` followed by a space or EOL. - let Ok(is_hidden_re) = Regex::new(r"^\s*#(?: |$)") else { - return ranges; - }; - - for (idx, line) in code.iter().enumerate() { - let n = idx + 1; - let line = line.as_ref(); - let is_hidden = is_hidden_re.is_match(line); - - if is_hidden { - if let Some(range) = curr_range.as_mut() { - range.end = n; - } else { - curr_range = Some(Range { start: n, end: n }); - } - } else { - if let Some(curr_range) = curr_range { - ranges.push(curr_range); - } - - curr_range = None; - } - } - - if let Some(curr_range) = curr_range { - ranges.push(curr_range); - } - - ranges -} - -#[cfg(test)] -mod tests { - use super::*; - use indoc::indoc; - - fn split_lines(code: &str) -> Vec<&str> { - code.split('\n').collect::>() - } - - #[test] - fn empty_block() { - let code = split_lines(indoc! {r#""#}); - - assert!(get_hidden_ranges(&code).is_empty()); - } - - #[test] - fn no_hidden() { - let code = split_lines(indoc! {r#" - 1 - 2 - 3 - 4 - 5 - "#}); - - assert!(get_hidden_ranges(&code).is_empty()); - } - - #[test] - fn single_range() { - let code = split_lines(indoc! {r#" - # 1 - # 2 - # 3 - 4 - 5 - "#}); - - assert_eq!(get_hidden_ranges(&code), vec![Range { start: 1, end: 3 }]); - } - - #[test] - fn single_range_no_content() { - let code = split_lines(indoc! {r#" - # - # - # - 4 - 5 - "#}); - - assert_eq!(get_hidden_ranges(&code), vec![Range { start: 1, end: 3 }]); - } - - #[test] - fn multi_range() { - let code = split_lines(indoc! {r#" - # 1 - # 2 - 3 - # 4 - # 5 - "#}); - - assert_eq!( - get_hidden_ranges(&code), - vec![Range { start: 1, end: 2 }, Range { start: 4, end: 5 }] - ); - } - - #[test] - fn single_line_range() { - let code = split_lines(indoc! {r#" - 1 - 2 - 3 - 4 - # 5 - "#}); - - assert_eq!(get_hidden_ranges(&code), vec![Range { start: 5, end: 5 }]); - } -} diff --git a/write-rustdoc-hide-lines/src/lib.rs b/write-rustdoc-hide-lines/src/lib.rs deleted file mode 100644 index 82aa54b5f4..0000000000 --- a/write-rustdoc-hide-lines/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod code_block_definition; -pub mod formatter; -pub mod hidden_ranges; diff --git a/write-rustdoc-hide-lines/src/main.rs b/write-rustdoc-hide-lines/src/main.rs deleted file mode 100644 index e21278efe4..0000000000 --- a/write-rustdoc-hide-lines/src/main.rs +++ /dev/null @@ -1,16 +0,0 @@ -use std::{env, path::Path}; - -use write_rustdoc_hide_lines::formatter; - -fn main() { - let args: Vec = env::args().collect(); - let folder = args.get(1).expect("Please provide a folder"); - let path = Path::new(&folder); - - println!("Formatting folder: {:?}", path); - - match formatter::run(path) { - Ok(_) => println!("Done!"), - Err(error) => println!("Error: {}", error), - } -} diff --git a/write-rustdoc-hide-lines/write_rustdoc_hide_lines.sh b/write-rustdoc-hide-lines/write_rustdoc_hide_lines.sh deleted file mode 100755 index 79d4eca815..0000000000 --- a/write-rustdoc-hide-lines/write_rustdoc_hide_lines.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -cargo run --release -- ../content/learn/book -cargo run --release -- ../content/learn/quick-start From ba7d09e961038aca72e462dd8b06a80bd3ce3201 Mon Sep 17 00:00:00 2001 From: icesentry Date: Thu, 15 Feb 2024 19:40:14 -0500 Subject: [PATCH 4/9] generate --- .../learn/migration-guides/0.12-to-0.13.md | 1836 +++++++++++++++++ 1 file changed, 1836 insertions(+) create mode 100644 content/learn/migration-guides/0.12-to-0.13.md diff --git a/content/learn/migration-guides/0.12-to-0.13.md b/content/learn/migration-guides/0.12-to-0.13.md new file mode 100644 index 0000000000..ec0734d8d0 --- /dev/null +++ b/content/learn/migration-guides/0.12-to-0.13.md @@ -0,0 +1,1836 @@ ++++ +title = "0.12 to 0.13" +insert_anchor_links = "right" +[extra] +weight = 8 +long_title = "Migration Guide: 0.12 to 0.13" ++++ + +Bevy relies heavily on improvements in the Rust language and compiler. +As a result, the Minimum Supported Rust Version (MSRV) is "the latest stable release" of Rust. +
    + +### [support all types of animation interpolation from gltf](https://github.com/bevyengine/bevy/pull/10755) + +
    +
    Animation
    +
    + +When manually specifying an animation `VariableCurve`, the interpolation type must be specified: + +- Bevy 0.12 + +```rust + VariableCurve { + keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0], + keyframes: Keyframes::Rotation(vec![ + Quat::IDENTITY, + Quat::from_axis_angle(Vec3::Y, PI / 2.), + Quat::from_axis_angle(Vec3::Y, PI / 2. * 2.), + Quat::from_axis_angle(Vec3::Y, PI / 2. * 3.), + Quat::IDENTITY, + ]), + }, +``` + +- Bevy 0.13 + +```rust + VariableCurve { + keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0], + keyframes: Keyframes::Rotation(vec![ + Quat::IDENTITY, + Quat::from_axis_angle(Vec3::Y, PI / 2.), + Quat::from_axis_angle(Vec3::Y, PI / 2. * 2.), + Quat::from_axis_angle(Vec3::Y, PI / 2. * 3.), + Quat::IDENTITY, + ]), + interpolation: Interpolation::Linear, + }, +``` + +### [`ReadAssetBytesError::Io` exposes failing path](https://github.com/bevyengine/bevy/pull/10450) + +
    +
    Assets
    +
    + +- The `ReadAssetBytesError::Io` variant now contains two named fields instead of converting from `std::io::Error`. + - `path`: The requested (failing) path (`PathBuf`) + - `source`: The source `std::io::Error` + +### [Ensure consistency between Un/Typed `AssetId` and `Handle`](https://github.com/bevyengine/bevy/pull/10628) + +
    +
    Assets
    +
    + +If you relied on any of the panicing `From` implementations, simply call the existing `typed` methods instead. Alternatively, use the new `TryFrom` implementation instead to directly expose possible mistakes. + +### [Add GltfLoaderSettings](https://github.com/bevyengine/bevy/pull/10804) + +
    +
    Assets
    +
    + + + +### [Use `impl Into` for `Assets::add`](https://github.com/bevyengine/bevy/pull/10878) + +
    +
    Assets
    +
    + +Some `into` calls that worked previously might now be broken because of the new trait bounds. You need to either remove `into` or perform the conversion explicitly with `from`: + +```rust +// Doesn't compile +let mesh_handle = meshes.add(shape::Cube { size: 1.0 }.into()), + +// These compile +let mesh_handle = meshes.add(shape::Cube { size: 1.0 }), +let mesh_handle = meshes.add(Mesh::from(shape::Cube { size: 1.0 })), +``` + +### [GLTF extension support](https://github.com/bevyengine/bevy/pull/11138) + +
    +
    Assets
    +
    + +This will have issues with “asset migrations”, as there is currently no way for .meta files to be migrated. Attempting to migrate .meta files without the new flag will yield the following error: + +```rust +bevy_asset::server: Failed to deserialize meta for asset test_platform.gltf: Failed to deserialize asset meta: SpannedError { code: MissingStructField { field: "include_source", outer: Some("GltfLoaderSettings") }, position: Position { line: 9, col: 9 } } +``` + +This means users who want to migrate their .meta files will have to add the `include_source: true,` setting to their meta files by hand. + +### [Allow TextureAtlasBuilder in AssetLoader](https://github.com/bevyengine/bevy/pull/11548) + +
    +
    Assets
    +
    + +- For `add_texture` you need to wrap your AssetId in Some +- `finish` now returns the atlas texture image directly instead of a handle. Provide the atlas texture to `add` on Assets to get a Handle + +### [Fix embedded asset path manipulation](https://github.com/bevyengine/bevy/pull/10383) + +
    +
    Assets
    +
    + +No API changes. + +### [Remove the ability to ignore global volume](https://github.com/bevyengine/bevy/pull/11092) + +
    +
    Audio
    +
    + +The option to ignore the global volume using `Volume::Absolute` has been removed and `Volume` now stores the volume level directly, removing the need for the `VolumeLevel` struct. + +### [Optional override for global spatial scale](https://github.com/bevyengine/bevy/pull/10419) + +
    +
    Audio
    +
    + +`AudioPlugin::spatial_scale` has been renamed to `default_spatial_scale` and the default spatial scale can now be overridden on individual audio sources with `PlaybackSettings::spatial_scale`. + +If you were modifying or reading `SpatialScale` at run time, use `DefaultSpatialScale` instead. + +```rust +// before +app.add_plugins(DefaultPlugins.set(AudioPlugin { + spatial_scale: SpatialScale::new(AUDIO_SCALE), + ..default() +})); + +// after +app.add_plugins(DefaultPlugins.set(AudioPlugin { + default_spatial_scale: SpatialScale::new(AUDIO_SCALE), + ..default() +})); +``` + +### [Add support for updating the tracing subscriber in LogPlugin](https://github.com/bevyengine/bevy/pull/10822) + +
    +
    Diagnostics
    +
    + +> +This section is optional. If there are no breaking changes, you can delete this section. + +- Added a new field `update_subscriber` in the `LogPlugin` + +### [Replace `DiagnosticId` by `DiagnosticPath`](https://github.com/bevyengine/bevy/pull/9266) + +
    +
    Diagnostics
    +
    + +```diff +- const UNIQUE_DIAG_ID: DiagnosticId = DiagnosticId::from_u128(42); ++ const UNIQUE_DIAG_PATH: DiagnosticPath = DiagnosticPath::const_new("foo/bar"); + +- Diagnostic::new(UNIQUE_DIAG_ID, "example", 10) ++ Diagnostic::new(UNIQUE_DIAG_PATH).with_max_history_length(10) + +- diagnostics.add_measurement(UNIQUE_DIAG_ID, || 42); ++ diagnostics.add_measurement(&UNIQUE_DIAG_ID, || 42); +``` + +### [Use `EntityHashMap` for `EntityMapper`](https://github.com/bevyengine/bevy/pull/10415) + +
    +
    ECS
    +
    + +If you are using the following types, update their listed methods to use the new `EntityHashMap`. `EntityHashMap` has the same methods as the normal `HashMap`, so you just need to replace the name. + +__`EntityMapper`__ + +- `get_map` +- `get_mut_map` +- `new` +- `world_scope` + +__`ReflectMapEntities`__ + +- `map_all_entities` +- `map_entities` +- `write_to_world` + +__`InstanceInfo`__ + +- `entity_map` + - This is a property, not a method. + +--- + +This is my first time contributing in a while, and I’m not familiar with the usage of `EntityMapper`. I changed the type definition and fixed all errors, but there may have been things I’ve missed. Please keep an eye out for me! + +### [Optimize `Entity::eq`](https://github.com/bevyengine/bevy/pull/10519) + +
    +
    ECS
    +
    + +(I really hope nobody was using this on uninitialized entities where sufficiently tortured `unsafe` could could technically notice that this has changed.) + +### [Update `Event` send methods to return `EventId`](https://github.com/bevyengine/bevy/pull/10551) + +
    +
    ECS
    +
    + +__`send` / `send_default` / `send_batch`__ + +For the following methods: + +- `Events::send` +- `Events::send_default` +- `Events::send_batch` +- `EventWriter::send` +- `EventWriter::send_default` +- `EventWriter::send_batch` +- `World::send_event` +- `World::send_event_default` +- `World::send_event_batch` + +Ensure calls to these methods either handle the returned value, or suppress the result with `;`. + +```rust +// Now fails to compile due to mismatched return type +fn send_my_event(mut events: EventWriter) { + events.send_default() +} + +// Fix +fn send_my_event(mut events: EventWriter) { + events.send_default(); +} +``` + +This will most likely be noticed within `match` statements: + +```rust +// Before +match is_pressed { + true => events.send(PlayerAction::Fire), +// ^--^ No longer returns () + false => {} +} + +// After +match is_pressed { + true => { + events.send(PlayerAction::Fire); + }, + false => {} +} +``` + +### [Optimise `Entity` with repr align & manual `PartialOrd`/`Ord`](https://github.com/bevyengine/bevy/pull/10558) + +
    +
    ECS
    +
    + +Any `unsafe` code relying on field ordering of `Entity` or sufficiently cursed shenanigans should change to reflect the different internal representation and alignment requirements of `Entity`. + +Co-authored-by: james7132 [contact@jamessliu.com](contact@jamessliu.com) +Co-authored-by: NathanW [nathansward@comcast.net](nathansward@comcast.net) + +### [Split WorldQuery into WorldQueryData and WorldQueryFilter](https://github.com/bevyengine/bevy/pull/9918) + +
    +
    ECS
    +
    + +- Update derives + +```rust +// old +#[derive(WorldQuery)] +#[world_query(mutable, derive(Debug))] +struct CustomQuery { + entity: Entity, + a: &'static mut ComponentA +} + +#[derive(WorldQuery)] +struct QueryFilter { + _c: With +} + +// new +#[derive(WorldQueryData)] +#[world_query_data(mutable, derive(Debug))] +struct CustomQuery { + entity: Entity, + a: &'static mut ComponentA, +} + +#[derive(WorldQueryFilter)] +struct QueryFilter { + _c: With +} +``` + +- Replace `Option>` with `Has` + +```rust +/// old +fn my_system(query: Query<(Entity, Option>)>) +{ + for (entity, has_a_option) in query.iter(){ + let has_a:bool = has_a_option.is_some(); + //todo!() + } +} + +/// new +fn my_system(query: Query<(Entity, Has)>) +{ + for (entity, has_a) in query.iter(){ + //todo!() + } +} +``` + +- Fix queries which had filters in the data position or vice versa. + +```rust +// old +fn my_system(query: Query<(Entity, With)>) +{ + for (entity, _) in query.iter(){ + //todo!() + } +} + +// new +fn my_system(query: Query>) +{ + for entity in query.iter(){ + //todo!() + } +} + +// old +fn my_system(query: Query)>>) +{ + for (entity, _) in query.iter(){ + //todo!() + } +} + +// new +fn my_system(query: Query, Or<(With, With)>>) +{ + for entity in query.iter(){ + //todo!() + } +} + +``` + +### [Reduced `TableRow` `as` Casting](https://github.com/bevyengine/bevy/pull/10811) + +
    +
    ECS
    +
    + +- `TableRow::new` -> `TableRow::from_usize` +- `TableRow::index` -> `TableRow::as_usize` +- `TableId::new` -> `TableId::from_usize` +- `TableId::index` -> `TableId::as_usize` + +--- + +### [Rename `WorldQueryData` & `WorldQueryFilter` to `QueryData` & `QueryFilter`](https://github.com/bevyengine/bevy/pull/10779) + +
    +
    ECS
    +
    + +Note: if merged before 0.13 is released, this should instead modify the migration guide of #10776 with the updated names. + +- Rename `WorldQueryData` & `WorldQueryFilter` trait usages to `QueryData` & `QueryFilter` and their respective derive macro attributes `world_query_data` & `world_query_filter` to `query_data` & `query_filter`. +- Rename the following trait type usages: + - Trait’s `ExtractComponent` type `Query` to `Data`. + - Trait’s `GetBatchData` type `Query` to `Data`. + - Trait’s `ExtractInstance` type `Query` to `Data`. + - Trait’s `ViewNode` type `ViewQuery` to `ViewData`’ + - Trait’s `RenderCommand` types `ViewWorldQuery` & `ItemWorldQuery` to `ViewData` & `ItemData`, respectively. + +```rust +// Before +#[derive(WorldQueryData)] +#[world_query_data(derive(Debug))] +struct EmptyQuery { + empty: (), +} + +// After +#[derive(QueryData)] +#[query_data(derive(Debug))] +struct EmptyQuery { + empty: (), +} + +// Before +#[derive(WorldQueryFilter)] +struct CustomQueryFilter { + _c: With, + _d: With, + _or: Or<(Added, Changed, Without)>, + _generic_tuple: (With, With

    ), +} + +// After +#[derive(QueryFilter)] +struct CustomQueryFilter { + _c: With, + _d: With, + _or: Or<(Added, Changed, Without)>, + _generic_tuple: (With, With

    ), +} + +// Before +impl ExtractComponent for ContrastAdaptiveSharpeningSettings { + type Query = &'static Self; + type Filter = With; + type Out = (DenoiseCAS, CASUniform); + + fn extract_component(item: QueryItem) -> Option { + //... + } +} + +// After +impl ExtractComponent for ContrastAdaptiveSharpeningSettings { + type Data = &'static Self; + type Filter = With; + type Out = (DenoiseCAS, CASUniform); + + fn extract_component(item: QueryItem) -> Option { + //... + } +} + +// Before +impl GetBatchData for MeshPipeline { + type Param = SRes; + type Query = Entity; + type QueryFilter = With; + type CompareData = (MaterialBindGroupId, AssetId); + type BufferData = MeshUniform; + + fn get_batch_data( + mesh_instances: &SystemParamItem, + entity: &QueryItem, + ) -> (Self::BufferData, Option) { + // .... + } +} + +// After +impl GetBatchData for MeshPipeline { + type Param = SRes; + type Data = Entity; + type Filter = With; + type CompareData = (MaterialBindGroupId, AssetId); + type BufferData = MeshUniform; + + fn get_batch_data( + mesh_instances: &SystemParamItem, + entity: &QueryItem, + ) -> (Self::BufferData, Option) { + // .... + } +} + +// Before +impl ExtractInstance for AssetId +where + A: Asset, +{ + type Query = Read>; + type Filter = (); + + fn extract(item: QueryItem<'_, Self::Query>) -> Option { + Some(item.id()) + } +} + +// After +impl ExtractInstance for AssetId +where + A: Asset, +{ + type Data = Read>; + type Filter = (); + + fn extract(item: QueryItem<'_, Self::Data>) -> Option { + Some(item.id()) + } +} + +// Before +impl ViewNode for PostProcessNode { + type ViewQuery = ( + &'static ViewTarget, + &'static PostProcessSettings, + ); + + fn run( + &self, + _graph: &mut RenderGraphContext, + render_context: &mut RenderContext, + (view_target, _post_process_settings): QueryItem, + world: &World, + ) -> Result<(), NodeRunError> { + // ... + } +} + +// After +impl ViewNode for PostProcessNode { + type ViewData = ( + &'static ViewTarget, + &'static PostProcessSettings, + ); + + fn run( + &self, + _graph: &mut RenderGraphContext, + render_context: &mut RenderContext, + (view_target, _post_process_settings): QueryItem, + world: &World, + ) -> Result<(), NodeRunError> { + // ... + } +} + +// Before +impl RenderCommand

    for SetItemPipeline { + type Param = SRes; + type ViewWorldQuery = (); + type ItemWorldQuery = (); + #[inline] + fn render<'w>( + item: &P, + _view: (), + _entity: (), + pipeline_cache: SystemParamItem<'w, '_, Self::Param>, + pass: &mut TrackedRenderPass<'w>, + ) -> RenderCommandResult { + // ... + } +} + +// After +impl RenderCommand

    for SetItemPipeline { + type Param = SRes; + type ViewData = (); + type ItemData = (); + #[inline] + fn render<'w>( + item: &P, + _view: (), + _entity: (), + pipeline_cache: SystemParamItem<'w, '_, Self::Param>, + pass: &mut TrackedRenderPass<'w>, + ) -> RenderCommandResult { + // ... + } +} +``` + +### [Allow the editing of startup schedules](https://github.com/bevyengine/bevy/pull/10969) + +

    + +- Added a new field to `MainScheduleOrder`, `startup_labels`, for editing the startup schedule order. + +### [Auto insert sync points](https://github.com/bevyengine/bevy/pull/9822) + +
    +
    ECS
    +
    + +- `apply_deferred` points are added automatically when there is ordering relationship with a system that has deferred parameters like `Commands`. If you want to opt out of this you can switch from `after`, `before`, and `chain` to the corresponding `ignore_deferred` API, `after_ignore_deferred`, `before_ignore_deferred` or `chain_ignore_deferred` for your system/set ordering. +- You can also set `ScheduleBuildSettings::auto_insert_sync_points` to `false` if you want to do it for the whole schedule. Note that in this mode you can still add `apply_deferred` points manually. +- For most manual insertions of `apply_deferred` you should remove them as they cannot be merged with the automatically inserted points and might reduce parallelizability of the system graph. +- If you were manually deriving `SystemParam`, you will need to add `system_meta.set_has_deferred` if you use `SystemParam::apply` and want sync points auto inserted after use of your `SystemParam`. + +### [Add insert_state to App.](https://github.com/bevyengine/bevy/pull/11043) + +
    +
    ECS
    +
    + +- Renamed `App::add_state` to `init_state`. + +### [Rename `ArchetypeEntity::entity` into `ArchetypeEntity::id`](https://github.com/bevyengine/bevy/pull/11118) + +
    +
    ECS
    +
    + +The method `ArchetypeEntity::entity` has been renamed to `ArchetypeEntity::id` + +### [StateTransitionEvent](https://github.com/bevyengine/bevy/pull/11089) + +
    +
    ECS
    +
    + +N/A no breaking changes + +### [Restore support for running `fn` `EntityCommands` on entities that might be despawned](https://github.com/bevyengine/bevy/pull/11107) + +
    +
    ECS
    +
    + +All `Command` types in `bevy_ecs`, such as `Spawn`, `SpawnBatch`, `Insert`, etc., have been made private. Use the equivalent methods on `Commands` or `EntityCommands` instead. + +If you were working with `ChildBuilder`, recreate these commands using a closure. For example, you might migrate a Command to insert components like: + +```rust +// Before (0.12) +parent.add_command(Insert { + entity: ent_text, + bundle: Capitalizable, +}); + +// After (0.13) +parent.add_command(move |world: &mut World| { + world.entity_mut(ent_text).insert(Capitalizable); +}); +``` + +### [Simplify conditions](https://github.com/bevyengine/bevy/pull/11316) + +
    +
    ECS
    +
    + +- resource_exists() -> resource_exists +- resource_added() -> resource_added +- resource_changed() -> resource_changed +- resource_exists_and_changed() -> resource_exists_and_changed +- state_exists() -> state_exists +- state_changed() -> state_changed +- any_with_component() -> any_with_component + +### [refactor: Simplify lifetimes for `Commands` and related types](https://github.com/bevyengine/bevy/pull/11445) + +
    +
    ECS
    +
    + +The lifetimes for `EntityCommands` have been simplified. + +```rust +// Before (Bevy 0.12) +struct MyStruct<'w, 's, 'a> { + commands: EntityCommands<'w, 's, 'a>, +} + +// After (Bevy 0.13) +struct MyStruct<'a> { + commands: EntityCommands<'a>, +} +``` + +The method `EntityCommands::commands` now returns `Commands` rather than `&mut Commands`. + +```rust +// Before (Bevy 0.12) +let commands = entity_commands.commands(); +commands.spawn(...); + +// After (Bevy 0.13) +let mut commands = entity_commands.commands(); +commands.spawn(...); +``` + +### [Deprecated Various Component Methods from `Query` and `QueryState`](https://github.com/bevyengine/bevy/pull/9920) + +
    +
    ECS
    +
    + +__`QueryState::get_component_unchecked_mut`__ + +Use `QueryState::get_unchecked_manual` and select for the exact component based on the structure of the exact query as required. + +__`Query::(get_)component(_unchecked)(_mut)`__ + +Use `Query::get` and select for the exact component based on the structure of the exact query as required. + +- For mutable access (`_mut`), use `Query::get_mut` +- For unchecked access (`_unchecked`), use `Query::get_unchecked` +- For panic variants (non-`get_`), add `.unwrap()` + +For example: + +```rust +fn system(query: Query<(&A, &B, &C)>) { + // Before + let b = query.get_component::(entity).unwrap(); + + // Alternative 1 (using tuple destructuring) + let (_, b, _) = query.get(entity).unwrap(); + + // Alternative 2 (using tuple item indexing) + let b = query.get(entity).unwrap().1; +} +``` + +### [`System::type_id` Consistency](https://github.com/bevyengine/bevy/pull/11728) + +
    +
    ECS
    +
    + +If you use `System::type_id()` on function systems (exclusive or not), ensure you are comparing its value to other `System::type_id()` calls, or `IntoSystem::system_type_id()`. + +This code wont require any changes, because `IntoSystem`’s are directly compared to each other. + +```rust +fn test_system() {} + +let type_id = test_system.type_id(); + +// ... + +// No change required +assert_eq!(test_system.type_id(), type_id); +``` + +Likewise, this code wont, because `System`’s are directly compared. + +```rust +fn test_system() {} + +let type_id = IntoSystem::into_system(test_system).type_id(); + +// ... + +// No change required +assert_eq!(IntoSystem::into_system(test_system).type_id(), type_id); +``` + +The below _does_ require a change, since you’re comparing a `System` type to a `IntoSystem` type. + +```rust +fn test_system() {} + +// Before +assert_eq!(test_system.type_id(), IntoSystem::into_system(test_system).type_id()); + +// After +assert_eq!(test_system.system_type_id(), IntoSystem::into_system(test_system).type_id()); +``` + +### [System Stepping implemented as Resource](https://github.com/bevyengine/bevy/pull/8453) + +
    +
    ECS
    +
    Editor
    +
    App
    +
    Diagnostics
    +
    + +- Add a call to `Schedule::set_label()` for any custom `Schedule` + - This is only required if the `Schedule` will be stepped + +### [Make the MapEntities trait generic over Mappers, and add a simpler EntityMapper](https://github.com/bevyengine/bevy/pull/11428) + +
    +
    ECS
    +
    Scenes
    +
    + +- + +The existing `EntityMapper` (notably used to replicate `Scenes` across different `World`s) has been renamed to `SceneEntityMapper` + +- + +The `MapEntities` trait now works with a generic `EntityMapper` instead of the specific struct `EntityMapper`. +Calls to `fn map_entities(&mut self, entity_mapper: &mut EntityMapper)` need to be updated to +`fn map_entities(&mut self, entity_mapper: &mut M)` + +- + +The new trait `EntityMapper` has been added to the prelude + +### [Async channel v2](https://github.com/bevyengine/bevy/pull/10692) + +
    +
    ECS
    +
    Tasks
    +
    + +- The `PipelinedRendering` plugin is no longer exported on wasm. If you are including it in your wasm builds you should remove it. + +```rust +#[cfg(all(not(target_arch = "wasm32"))] +app.add_plugins(bevy_render::pipelined_rendering::PipelinedRenderingPlugin); +``` + +### [Add First/Pre/Post/Last schedules to the Fixed timestep](https://github.com/bevyengine/bevy/pull/10977) + +
    +
    ECS
    +
    Time
    +
    + +- Usage of `RunFixedUpdateLoop` should be renamed to `RunFixedMainLoop`. + +### [Move `EntityHash` related types into `bevy_ecs`](https://github.com/bevyengine/bevy/pull/11498) + +
    +
    ECS
    +
    Utils
    +
    + +- Uses of `bevy::utils::{EntityHash, EntityHasher, EntityHashMap, EntityHashSet}` now have to be imported from `bevy::ecs::entity::hash`. +- Uses of `EntityHashMap` no longer have to specify the first generic parameter. It is now hardcoded to always be `Entity`. + +### [Gizmo Arrows](https://github.com/bevyengine/bevy/pull/10550) + +
    +
    Gizmos
    +
    + +N/A + +### [Move Circle Gizmos to Their Own File](https://github.com/bevyengine/bevy/pull/10631) + +
    +
    Gizmos
    +
    + +- change `gizmos::CircleBuilder` to `gizmos::circles::Circle2dBuilder` +- change `gizmos::Circle2dBuilder` to `gizmos::circles::Circle2dBuilder` + +### [move gizmo arcs to their own file](https://github.com/bevyengine/bevy/pull/10660) + +
    +
    Gizmos
    +
    + +- `gizmos::Arc2dBuilder` -> `gizmos::arcs::Arc2dBuilder` + +### [Multiple Configurations for Gizmos](https://github.com/bevyengine/bevy/pull/10342) + +
    +
    Gizmos
    +
    + +- `GizmoConfig` is no longer a resource and has to be accessed through `GizmoConfigStore` resource. The default config group is `DefaultGizmoGroup`, but consider using your own custom config group if applicable. + +### [Use Direction3d for gizmos.circle normal](https://github.com/bevyengine/bevy/pull/11422) + +
    +
    Gizmos
    +
    + +- Pass a Direction3d for gizmos.circle normal, eg. `Direction3d::new(vec).unwrap_or(default)` or potentially `Direction3d::new_unchecked(vec)` if you know your vec is definitely normalized. + +### [Rename "AddChild" to "PushChild"](https://github.com/bevyengine/bevy/pull/11194) + +
    +
    Hierarchy
    +
    + +The struct `AddChild` has been renamed to `PushChild`, and the struct `AddChildInPlace` has been renamed to `PushChildInPlace`. + +### [Rename `Input` to `ButtonInput`](https://github.com/bevyengine/bevy/pull/10859) + +
    +
    Input
    +
    + +- Breaking Change: Users need to rename `Input` to `ButtonInput` in their projects. + +### [Add window entity to TouchInput events](https://github.com/bevyengine/bevy/pull/11128) + +
    +
    Input
    +
    + +- Add a `window` field when constructing or destructuring a `TouchInput` struct. + +### [Add delta to CursorMoved event](https://github.com/bevyengine/bevy/pull/11710) + +
    +
    Input
    +
    + +- You need to add `delta` to any manually created `CursorMoved` struct. + +### [Remove `Default` impl for `CubicCurve`](https://github.com/bevyengine/bevy/pull/11335) + +
    +
    Math
    +
    + +- Remove `CubicCurve` from any structs that implement `Default`. +- Wrap `CubicCurve` in a new type and provide your own default. + +```rust +#[derive(Deref)] +struct MyCubicCurve(pub CubicCurve

    ); + +impl Default for MyCubicCurve { + fn default() -> Self { + let points = [[ + vec2(-1.0, -20.0), + vec2(3.0, 2.0), + vec2(5.0, 3.0), + vec2(9.0, 8.0), + ]]; + + Self(CubicBezier::new(points).to_curve()) + } +} +``` + +### [Direction: Rename `from_normalized` to `new_unchecked`](https://github.com/bevyengine/bevy/pull/11425) + +

    +
    Math
    +
    + +- Renamed `Direction2d::from_normalized` and `Direction3d::from_normalized` to `new_unchecked`. + +### [Add `Capsule2d` primitive](https://github.com/bevyengine/bevy/pull/11585) + +
    +
    Math
    +
    + + + +### [Rename RayTest to RayCast](https://github.com/bevyengine/bevy/pull/11635) + +
    +
    Math
    +
    + + + +### [Use `IntersectsVolume` for breakout example collisions](https://github.com/bevyengine/bevy/pull/11500) + +
    +
    Physics
    +
    + +`sprite::collide_aabb::collide` and `sprite::collide_aabb::Collision` were removed. + +```rust +// Before +let collision = bevy::sprite::collide_aabb::collide(a_pos, a_size, b_pos, b_size); +if collision.is_some() { + // ... +} + +// After +let collision = Aabb2d::new(a_pos.truncate(), a_size / 2.) + .intersects(&Aabb2d::new(b_pos.truncate(), b_size / 2.)); +if collision { + // ... +} +``` + +If you were making use `collide_aabb::Collision`, see the new `collide_with_side` function in the [`breakout` example](https://bevyengine.org/examples/Games/breakout/). + +### [Add `ReflectFromWorld` and replace the `FromWorld` requirement on `ReflectComponent` and `ReflectBundle` with `FromReflect`](https://github.com/bevyengine/bevy/pull/9623) + +
    +
    Reflection
    +
    + +- Existing uses of `ReflectComponent::from_world` and `ReflectBundle::from_world` will have to be changed to `ReflectFromWorld::from_world`. +- Users of `#[reflect(Component)]` and `#[reflect(Bundle)]` will need to also implement/derive `FromReflect`. +- Users of `#[reflect(Component)]` and `#[reflect(Bundle)]` may now want to also add `FromWorld` to the list of reflected traits in case their `FromReflect` implementation may fail. +- Users of `ReflectComponent` will now need to pass a `&TypeRegistry` to its `insert`, `apply_or_insert` and `copy` methods. + +### [Fix reflected serialization/deserialization on `Name` component](https://github.com/bevyengine/bevy/pull/11447) + +
    +
    Reflection
    +
    + +- Existing scene files containing the former (incorrect) serialization of the `Name` component will require patching. Search for `bevy_core::name::Name`, and replace the following structure `( "name": "My Entity Name", "hash": ... )` with just a string: `"My Entity Name"`. + +### [Remove TypeUuid](https://github.com/bevyengine/bevy/pull/11497) + +
    +
    Reflection
    +
    + +Convert any uses of `#[derive(TypeUuid)]` with `#[derive(TypePath]` for more complex uses see the relevant [documentation](https://docs.rs/bevy/latest/bevy/prelude/trait.TypePath.html) for more information. + +### [bevy_reflect: Type parameter bounds](https://github.com/bevyengine/bevy/pull/9046) + +
    +
    Reflection
    +
    + +When deriving `Reflect`, generic type params that do not need the automatic reflection bounds (such as `Reflect`) applied to them will need to opt-out using a custom where clause like: `#[reflect(where T: Trait, U::Assoc: Trait, ...)]`. + +The attribute can define custom bounds only used by the reflection impls. To simply opt-out all the type params, we can pass in an empty where clause: `#[reflect(where)]`. + +```rust +// BEFORE: +#[derive(Reflect)] +struct Foo(#[reflect(ignore)] T); + +// AFTER: +#[derive(Reflect)] +#[reflect(where)] +struct Foo(#[reflect(ignore)] T); +``` + +### [bevy_reflect: Split `#[reflect(where)]`](https://github.com/bevyengine/bevy/pull/11597) + +
    +
    Reflection
    +
    + +> +[!important] +This PR shouldn’t be a breaking change relative to the current version of Bevy (v0.12). And since it removes the breaking parts of #9046, that PR also won’t need a migration guide. + +### [Add the ability to manually create ParsedPaths (+ cleanup)](https://github.com/bevyengine/bevy/pull/11029) + +
    +
    Reflection
    +
    + +- `bevy::reflect::AccessError` has been refactored. + +That should be it I think, everything else that was changed was private before this PR. + +### [Explicit color conversion methods](https://github.com/bevyengine/bevy/pull/10321) + +
    +
    Rendering
    +
    + +`Color::from(Vec4)` is now `Color::rgba_from_array(impl Into<[f32; 4]>)` +`Vec4::from(Color)` is now `Color::rgba_to_vec4(&self)` + +Before: + +```rust +let color_vec4 = Vec4::new(0.5, 0.5, 0.5); +let color_from_vec4 = Color::from(color_vec4); + +let color_array = [0.5, 0.5, 0.5]; +let color_from_array = Color::from(color_array); +``` + +After: + +```rust +let color_vec4 = Vec4::new(0.5, 0.5, 0.5); +let color_from_vec4 = Color::rgba_from_array(color_vec4); + +let color_array = [0.5, 0.5, 0.5]; +let color_from_array = Color::rgba_from_array(color_array); +``` + +### [Add a `depth_bias` to `Material2d`](https://github.com/bevyengine/bevy/pull/10683) + +
    +
    Rendering
    +
    + +`PreparedMaterial2d` has a new `depth_bias` field. A value of 0.0 can be used to get the previous behavior. + +### [Bind group layout entries](https://github.com/bevyengine/bevy/pull/10224) + +
    +
    Rendering
    +
    + +`RenderDevice::create_bind_group_layout()` doesn’t take a `BindGroupLayoutDescriptor` anymore. You need to provide the parameters separately + +```rust +// 0.12 +let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { + label: Some("post_process_bind_group_layout"), + entries: &[ + BindGroupLayoutEntry { + // ... + }, + ], +}); + +// 0.13 +let layout = render_device.create_bind_group_layout( + "post_process_bind_group_layout", + &[ + BindGroupLayoutEntry { + // ... + }, + ], +); +``` + +### [Swap material and mesh bind groups](https://github.com/bevyengine/bevy/pull/10485) + +
    +
    Rendering
    +
    + +- Custom 2d and 3d mesh/material shaders should now use bind group 2 `@group(2) @binding(x)` for their bound resources, instead of bind group 1. +- Many internal pieces of rendering code have changed so that mesh data is now in bind group 1, and material data is now in bind group 2. Semi-custom rendering setups (that don’t use the Material or Material2d APIs) should adapt to these changes. + +### [light renderlayers](https://github.com/bevyengine/bevy/pull/10742) + +
    +
    Rendering
    +
    + +Lights no longer affect all `RenderLayers` by default, now like cameras and meshes they default to `RenderLayers::layer(0)`. To recover the previous behaviour and have all lights affect all views, add a `RenderLayers::all()` component to the light entity. + +### [Update to wgpu 0.18](https://github.com/bevyengine/bevy/pull/10266) + +
    +
    Rendering
    +
    + +- `RenderPassDescriptor` `color_attachments` (as well as `RenderPassColorAttachment`, and `RenderPassDepthStencilAttachment`) now use `StoreOp::Store` or `StoreOp::Discard` instead of a `boolean` to declare whether or not they should be stored. +- `RenderPassDescriptor` now have `timestamp_writes` and `occlusion_query_set` fields. These can safely be set to `None`. +- `ComputePassDescriptor` now have a `timestamp_writes` field. This can be set to `None` for now. +- See the [wgpu changelog](https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md#v0180-2023-10-25) for additional details + +### [Keep track of when a texture is first cleared](https://github.com/bevyengine/bevy/pull/10325) + +
    +
    Rendering
    +
    + +- Remove arguments to `ViewTarget::get_color_attachment()` and `ViewTarget::get_unsampled_color_attachment()`. +- Configure clear color on `Camera` instead of on `Camera3d` and `Camera2d`. +- Moved `ClearColor` and `ClearColorConfig` from `bevy::core_pipeline::clear_color` to `bevy::render::camera`. +- `ViewDepthTexture` must now be created via the `new()` method + +### [Approximate indirect specular occlusion](https://github.com/bevyengine/bevy/pull/11152) + +
    +
    Rendering
    +
    + +- Renamed `PbrInput::occlusion` to `diffuse_occlusion`, and added `specular_occlusion`. + +### [Texture Atlas rework](https://github.com/bevyengine/bevy/pull/5103) + +
    +
    Rendering
    +
    + +- Sprites + +```diff +fn my_system( + mut images: ResMut>, +- mut atlases: ResMut>, ++ mut atlases: ResMut>, + asset_server: Res +) { + let texture_handle: asset_server.load("my_texture.png"); +- let layout = TextureAtlas::from_grid(texture_handle, Vec2::new(25.0, 25.0), 5, 5, None, None); ++ let layout = TextureAtlasLayout::from_grid(Vec2::new(25.0, 25.0), 5, 5, None, None); + let layout_handle = atlases.add(layout); + commands.spawn(SpriteSheetBundle { +- sprite: TextureAtlasSprite::new(0), +- texture_atlas: atlas_handle, ++ atlas: TextureAtlas { ++ layout: layout_handle, ++ index: 0 ++ }, ++ texture: texture_handle, + ..Default::default() + }); +} +``` + +- UI + +```diff +fn my_system( + mut images: ResMut>, +- mut atlases: ResMut>, ++ mut atlases: ResMut>, + asset_server: Res +) { + let texture_handle: asset_server.load("my_texture.png"); +- let layout = TextureAtlas::from_grid(texture_handle, Vec2::new(25.0, 25.0), 5, 5, None, None); ++ let layout = TextureAtlasLayout::from_grid(Vec2::new(25.0, 25.0), 5, 5, None, None); + let layout_handle = atlases.add(layout); + commands.spawn(AtlasImageBundle { +- texture_atlas_image: UiTextureAtlasImage { +- index: 0, +- flip_x: false, +- flip_y: false, +- }, +- texture_atlas: atlas_handle, ++ atlas: TextureAtlas { ++ layout: layout_handle, ++ index: 0 ++ }, ++ image: UiImage { ++ texture: texture_handle, ++ flip_x: false, ++ flip_y: false, ++ }, + ..Default::default() + }); +} +``` + +### [Exposure settings (adopted)](https://github.com/bevyengine/bevy/pull/11347) + +
    +
    Rendering
    +
    + +- If using a `Skybox` or `EnvironmentMapLight`, use the new `brightness` and `intensity` controls to adjust their strength. +- All 3D scene will now have different apparent brightnesses due to Bevy implementing proper exposure controls. You will have to adjust the intensity of your lights and/or your camera exposure via the new `ExposureSettings` component to compensate. + +### [Make `DynamicUniformBuffer::push` accept an `&T` instead of `T`](https://github.com/bevyengine/bevy/pull/11373) + +
    +
    Rendering
    +
    + +- Users of `DynamicUniformBuffer::push` now need to pass references to `DynamicUniformBuffer::push` (e.g. existing `uniforms.push(value)` will now become `uniforms.push(&value)`) + +### [Customizable camera main texture usage](https://github.com/bevyengine/bevy/pull/11412) + +
    +
    Rendering
    +
    + +Add `main_texture_usages: Default::default()` to your camera bundle. + +### [optimize batch_and_prepare_render_phase](https://github.com/bevyengine/bevy/pull/11323) + +
    +
    Rendering
    +
    + +trait `GetBatchData` no longer hold associated type `Data`and `Filter` +`get_batch_data` `query_item`type from `Self::Data` to `Entity` and return `Option<(Self::BufferData, Option)>` +`batch_and_prepare_render_phase` should not have a query + +### [add `storage_texture` option to as_bind_group macro](https://github.com/bevyengine/bevy/pull/9943) + +
    +
    Rendering
    +
    + +### [Revert rendering-related associated type name changes](https://github.com/bevyengine/bevy/pull/11027) + +
    +
    Rendering
    +
    + +- This PR amends the migration guide in + +### [Update to wgpu 0.19 and raw-window-handle 0.6](https://github.com/bevyengine/bevy/pull/11280) + +
    +
    Rendering
    +
    + +- `bevy_render::instance_index::get_instance_index()` has been removed as the webgl2 workaround is no longer required as it was fixed upstream in wgpu. The `BASE_INSTANCE_WORKAROUND` shaderdef has also been removed. +- WebGPU now requires the new `webgpu` feature to be enabled. The `webgpu` feature currently overrides the `webgl2` feature so you no longer need to disable all default features and re-add them all when targeting `webgpu`, but binaries built with both the `webgpu` and `webgl2` features will only target the webgpu backend, and will only work on browsers that support WebGPU. + - Places where you conditionally compiled things for webgl2 need to be updated because of this change, eg: + - `#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]` becomes `#[cfg(any(not(feature = "webgl") ,not(target_arch = "wasm32"), feature = "webgpu"))]` + - `#[cfg(all(feature = "webgl", target_arch = "wasm32"))]` becomes `#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]` + - `if cfg!(all(feature = "webgl", target_arch = "wasm32"))` becomes `if cfg!(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))` + +- `create_texture_with_data` now also takes a `TextureDataOrder`. You can probably just set this to `TextureDataOrder::default()` +- `TextureFormat`’s `block_size` has been renamed to `block_copy_size` +- See the `wgpu` changelog for anything I might’ve missed: +- `wgpu` now surfaces errors at instance creation time, which may have you run into this error (we’ve also seen it with nsight instead of EOSOverlay): + +```rust +2024-01-27T02:11:58.491767Z ERROR wgpu_hal::vulkan::instance: GENERAL [Loader Message (0x0)] + loader_get_json: Failed to open JSON file C:\Program Files (x86)\Epic Games\Launcher\Portal\Extras\Overlay\EOSOverlayVkLayer-Win32.json +2024-01-27T02:11:58.492046Z ERROR wgpu_hal::vulkan::instance: objects: (type: INSTANCE, hndl: 0x1fbe55dc070, name: ?) +2024-01-27T02:11:58.492282Z ERROR wgpu_hal::vulkan::instance: GENERAL [Loader Message (0x0)] + loader_get_json: Failed to open JSON file C:\Program Files (x86)\Epic Games\Launcher\Portal\Extras\Overlay\EOSOverlayVkLayer-Win64.json +2024-01-27T02:11:58.492525Z ERROR wgpu_hal::vulkan::instance: objects: (type: INSTANCE, hndl: 0x1fbe55dc070, name: ?) +``` + +It just means that the program didn’t properly cleanup their registry keys on an update/uninstall, and vulkan uses those keys to load validation layers. The fix is to [backup your registry](https://support.microsoft.com/en-us/topic/how-to-back-up-and-restore-the-registry-in-windows-855140ad-e318-2a13-2829-d428a2ab0692#ID0EBD=Windows_11), then remove the offending keys in `"Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\ImplicitLayers"`. + +### [RenderAssetPersistencePolicy → RenderAssetUsages](https://github.com/bevyengine/bevy/pull/11399) + +
    +
    Rendering
    +
    + +- `RenderAssetPersistencePolicy::Keep` → `RenderAssetUsage::MAIN_WORLD | RenderAssetUsage::RENDER_WORLD` (or `RenderAssetUsage::default()`) +- `RenderAssetPersistencePolicy::Unload` → `RenderAssetUsage::RENDER_WORLD` +- For types implementing the `RenderAsset` trait, change `fn persistence_policy(&self) -> RenderAssetPersistencePolicy` to `fn asset_usage(&self) -> RenderAssetUsages`. +- Change any references to `cpu_persistent_access` (`RenderAssetPersistencePolicy`) to `asset_usage` (`RenderAssetUsage`). This applies to `Image`, `Mesh`, and a few other types. + +### [RenderGraph Labelization](https://github.com/bevyengine/bevy/pull/10644) + +
    +
    Rendering
    +
    + +For Nodes and SubGraphs, instead of using hardcoded strings, you now pass labels, which can be derived with structs and enums. + +```rs +// old +#[derive(Default)] +struct MyRenderNode; +impl MyRenderNode { + pub const NAME: &'static str = "my_render_node" +} + +render_app + .add_render_graph_node::>( + core_3d::graph::NAME, + MyRenderNode::NAME, + ) + .add_render_graph_edges( + core_3d::graph::NAME, + &[ + core_3d::graph::node::TONEMAPPING, + MyRenderNode::NAME, + core_3d::graph::node::END_MAIN_PASS_POST_PROCESSING, + ], + ); + +// new +use bevy::core_pipeline::core_3d::graph::{Labels3d, SubGraph3d}; + +#[derive(Debug, Hash, PartialEq, Eq, Clone, RenderLabel)] +pub struct MyRenderLabel; + +#[derive(Default)] +struct MyRenderNode; + +render_app + .add_render_graph_node::>( + SubGraph3d, + MyRenderLabel, + ) + .add_render_graph_edges( + SubGraph3d, + ( + Labels3d::Tonemapping, + MyRenderLabel, + Labels3d::EndMainPassPostProcessing, + ), + ); +``` + +If you still want to use dynamic labels, you can easily create those with tuple structs: + +```rs +#[derive(Debug, Hash, PartialEq, Eq, Clone, RenderLabel)] +pub struct MyDynamicLabel(&'static str); +``` + +__SubGraphs__ + +__in `bevy_core_pipeline::core_2d::graph`__ +old string-based pathnew label`NAME``SubGraph2d` +__in `bevy_core_pipeline::core_3d::graph`__ +old string-based pathnew label`NAME``SubGraph3d` +__in `bevy_ui::render`__ +old string-based pathnew label`draw_ui_graph::NAME``graph::SubGraphUi` +__Nodes__ + +__in `bevy_core_pipeline::core_2d::graph`__ +old string-based pathnew label`node::MSAA_WRITEBACK``Labels2d::MsaaWriteback``node::MAIN_PASS``Labels2d::MainPass``node::BLOOM``Labels2d::Bloom``node::TONEMAPPING``Labels2d::Tonemapping``node::FXAA``Labels2d::Fxaa``node::UPSCALING``Labels2d::Upscaling``node::CONTRAST_ADAPTIVE_SHARPENING``Labels2d::ConstrastAdaptiveSharpening``node::END_MAIN_PASS_POST_PROCESSING``Labels2d::EndMainPassPostProcessing` +__in `bevy_core_pipeline::core_3d::graph`__ +old string-based pathnew label`node::MSAA_WRITEBACK``Labels3d::MsaaWriteback``node::PREPASS``Labels3d::Prepass``node::DEFERRED_PREPASS``Labels3d::DeferredPrepass``node::COPY_DEFERRED_LIGHTING_ID``Labels3d::CopyDeferredLightingId``node::END_PREPASSES``Labels3d::EndPrepasses``node::START_MAIN_PASS``Labels3d::StartMainPass``node::MAIN_OPAQUE_PASS``Labels3d::MainOpaquePass``node::MAIN_TRANSMISSIVE_PASS``Labels3d::MainTransmissivePass``node::MAIN_TRANSPARENT_PASS``Labels3d::MainTransparentPass``node::END_MAIN_PASS``Labels3d::EndMainPass``node::BLOOM``Labels3d::Bloom``node::TONEMAPPING``Labels3d::Tonemapping``node::FXAA``Labels3d::Fxaa``node::UPSCALING``Labels3d::Upscaling``node::CONTRAST_ADAPTIVE_SHARPENING``Labels3d::ContrastAdaptiveSharpening``node::END_MAIN_PASS_POST_PROCESSING``Labels3d::EndMainPassPostProcessing` +__in `bevy_core_pipeline`__ +old string-based pathnew label`taa::draw_3d_graph::node::TAA``Labels3d::Taa` +__in `bevy_pbr`__ +old string-based pathnew label`draw_3d_graph::node::SHADOW_PASS``LabelsPbr::ShadowPass``ssao::draw_3d_graph::node::SCREEN_SPACE_AMBIENT_OCCLUSION``LabelsPbr::ScreenSpaceAmbientOcclusion``deferred::DEFFERED_LIGHTING_PASS``LabelsPbr::DeferredLightingPass` +__in `bevy_render`__ +old string-based pathnew label`main_graph::node::CAMERA_DRIVER``graph::CameraDriverLabel` +__in `bevy_ui::render`__ +old string-based pathnew label`draw_ui_graph::node::UI_PASS``graph::LabelsUi::UiPass`--- + +### [Gate diffuse and specular transmission behind shader defs](https://github.com/bevyengine/bevy/pull/11627) + +
    +
    Rendering
    +
    + +- If you were using `#ifdef STANDARDMATERIAL_NORMAL_MAP` on your shader code, make sure to update the name to `STANDARD_MATERIAL_NORMAL_MAP`; (with an underscore between `STANDARD` and `MATERIAL`) + +### [Async pipeline compilation](https://github.com/bevyengine/bevy/pull/10812) + +
    +
    Rendering
    +
    + +- Match on the new `Creating` variant for exhaustive matches of `CachedPipelineState` + +### [Mesh insert indices](https://github.com/bevyengine/bevy/pull/11745) + +
    +
    Rendering
    +
    + +- Use `Mesh::insert_indices` or `Mesh::with_inserted_indices` instead of `Mesh::set_indices` / `Mesh::with_indices`. +- If you have passed `None` to `Mesh::set_indices` or `Mesh::with_indices` you should use `Mesh::remove_indices` or `Mesh::with_removed_indices` instead. + +### [wait for render app when main world is dropped](https://github.com/bevyengine/bevy/pull/11737) + +
    +
    Rendering
    +
    + +- If you were using the pipelined rendering channels, `MainToRenderAppSender` and `RenderToMainAppReceiver`, they have been combined into the single resource `RenderAppChannels`. + +### [Deprecate shapes in `bevy_render::mesh::shape`](https://github.com/bevyengine/bevy/pull/11773) + +
    +
    Rendering
    +
    + +Bevy has previously used rendering-specific types like `UVSphere` and `Quad` for primitive mesh shapes. These have now been deprecated to use the geometric primitives newly introduced in version 0.13. + +Some examples: + +```rust +let before = meshes.add(shape::Box::new(5.0, 0.15, 5.0)); +let after = meshes.add(Cuboid::new(5.0, 0.15, 5.0)); + +let before = meshes.add(shape::Quad::default()); +let after = meshes.add(Rectangle::default()); + +let before = meshes.add(shape::Plane::from_size(5.0)); +// The surface normal can now also be specified when using `new` +let after = meshes.add(Plane3d::default().mesh().size(5.0, 5.0)); + +let before = meshes.add( + Mesh::try_from(shape::Icosphere { + radius: 0.5, + subdivisions: 5, + }) + .unwrap(), +); +let after = meshes.add(Sphere::new(0.5).mesh().ico(5).unwrap()); +``` + +### [Multithreaded render command encoding](https://github.com/bevyengine/bevy/pull/9172) + +
    +
    Rendering
    +
    + +`RenderContext::new()` now takes adapter info + +- Some render graph and Node related types and methods now have additional lifetime constraints. + +### [Stop extracting mesh entities to the render world.](https://github.com/bevyengine/bevy/pull/11803) + +
    +
    Rendering
    +
    + +- For efficiency reasons, some meshes in the render world may not have corresponding `Entity` IDs anymore. As a result, the `entity` parameter to `RenderCommand::render()` is now wrapped in an `Option`. Custom rendering code may need to be updated to handle the case in which no `Entity` exists for an object that is to be rendered. + +### [Change light defaults & fix light examples](https://github.com/bevyengine/bevy/pull/11581) + +
    +
    Rendering
    +
    + + + +### [New Exposure and Lighting Defaults (and calibrate examples)](https://github.com/bevyengine/bevy/pull/11868) + +
    +
    Rendering
    +
    + +- The increased `Exposure::ev100` means that all existing 3D lighting will need to be adjusted to match (DirectionalLights, PointLights, SpotLights, EnvironmentMapLights, etc). Or alternatively, you can adjust the `Exposure::ev100` on your cameras to work nicely with your current lighting values. If you are currently relying on default intensity values, you might need to change the intensity to achieve the same effect. Note that in Bevy 0.12, point/spot lights had a different hard coded ev100 value than directional lights. In Bevy 0.13, they use the same ev100, so if you have both in your scene, the _scale_ between these light types has changed and you will likely need to adjust one or both of them. + +### [Unload render assets from RAM](https://github.com/bevyengine/bevy/pull/10520) + +
    +
    Rendering
    +
    Assets
    +
    + +- Asset loaders (GLTF, etc) now load meshes and textures without `cpu_persistent_access`. These assets will be removed from `Assets` and `Assets` once `RenderAssets` and `RenderAssets` contain the GPU versions of these assets, in order to reduce memory usage. If you require access to the asset data from the CPU in future frames after the GLTF asset has been loaded, modify all dependent `Mesh` and `Image` assets and set `cpu_persistent_access` to `RenderAssetPersistencePolicy::Keep`. +- `Mesh` now requires a new `cpu_persistent_access` field. Set it to `RenderAssetPersistencePolicy::Keep` to mimic the previous behavior. +- `Image` now requires a new `cpu_persistent_access` field. Set it to `RenderAssetPersistencePolicy::Keep` to mimic the previous behavior. +- `MorphTargetImage::new()` now requires a new `cpu_persistent_access` parameter. Set it to `RenderAssetPersistencePolicy::Keep` to mimic the previous behavior. +- `DynamicTextureAtlasBuilder::add_texture()` now requires that the `TextureAtlas` you pass has an `Image` with `cpu_persistent_access: RenderAssetPersistencePolicy::Keep`. Ensure you construct the image properly for the texture atlas. +- The `RenderAsset` trait has significantly changed, and requires adapting your existing implementations. + - The trait now requires `Clone`. + - The `ExtractedAsset` associated type has been removed (the type itself is now extracted). + - The signature of `prepare_asset()` is slightly different + - A new `persistence_policy()` method is now required (return RenderAssetPersistencePolicy::Unload to match the previous behavior). + +- Match on the new `NoLongerUsed` variant for exhaustive matches of `AssetEvent`. + +### [Split `Ray` into `Ray2d` and `Ray3d` and simplify plane construction](https://github.com/bevyengine/bevy/pull/10856) + +
    +
    Rendering
    +
    Math
    +
    + +`Ray` has been renamed to `Ray3d`. + +__Ray creation__ + +Before: + +```rust +Ray { + origin: Vec3::ZERO, + direction: Vec3::new(0.5, 0.6, 0.2).normalize(), +} +``` + +After: + +```rust +// Option 1: +Ray3d { + origin: Vec3::ZERO, + direction: Direction3d::new(Vec3::new(0.5, 0.6, 0.2)).unwrap(), +} + +// Option 2: +Ray3d::new(Vec3::ZERO, Vec3::new(0.5, 0.6, 0.2)) +``` + +__Plane intersections__ + +Before: + +```rust +let result = ray.intersect_plane(Vec2::X, Vec2::Y); +``` + +After: + +```rust +let result = ray.intersect_plane(Vec2::X, Plane2d::new(Vec2::Y)); +``` + +### [Introduce AspectRatio struct](https://github.com/bevyengine/bevy/pull/10368) + +
    +
    Rendering
    +
    Math
    +
    + +- Anywhere where you are currently expecting a f32 when getting aspect ratios, you will now receive a `AspectRatio` struct. this still holds the same value. + +### [Include UI node size in the vertex inputs for UiMaterial.](https://github.com/bevyengine/bevy/pull/11722) + +
    +
    Rendering
    +
    UI
    +
    + +This change should be backwards compatible, using the new field is optional. + +Note to reviewers: render pipelines are a bit outside my comfort zone, so please make sure I haven’t made any mistakes. + +### [Optional ImageScaleMode](https://github.com/bevyengine/bevy/pull/11780) + +
    +
    Rendering
    +
    UI
    +
    + + + +### [Re-export `futures_lite` in `bevy_tasks`](https://github.com/bevyengine/bevy/pull/10670) + +
    +
    Tasks
    +
    + +- Remove `futures_lite` from `Cargo.toml`. + +```diff +[dependencies] +bevy = "0.12.0" +- futures-lite = "1.4.0" +``` + +- Replace `futures_lite` imports with `bevy::tasks::future`. + +```diff +- use futures_lite::poll_once; ++ use bevy::tasks::future::poll_once; +``` + +### [Rename `TextAlignment` to `JustifyText`.](https://github.com/bevyengine/bevy/pull/10854) + +
    +
    Text
    +
    + +- `TextAlignment` has been renamed to `JustifyText` +- `TextBundle::with_text_alignment` has been renamed to `TextBundle::with_text_justify` +- `Text::with_alignment` has been renamed to `Text::with_justify` +- The `text_alignment` field of `TextMeasureInfo` has been renamed to `justification` + +### [Rename `Time::::overstep_percentage()` and `Time::::overstep_percentage_f64()`](https://github.com/bevyengine/bevy/pull/10448) + +
    +
    Time
    +
    + +- `Time::::overstep_percentage()` has been renamed to `Time::::overstep_fraction()` +- `Time::::overstep_percentage_f64()` has been renamed to `Time::::overstep_fraction_f64()` + +### [Rename `Timer::{percent,percent_left}` to `Timer::{fraction,fraction_remaining}`](https://github.com/bevyengine/bevy/pull/10442) + +
    +
    Time
    +
    + +- `Timer::percent()` has been renamed to `Timer::fraction()` +- `Timer::percent_left()` has been renamed to `Timer::fraction_remaining()` + +### [return Direction3d from Transform::up and friends](https://github.com/bevyengine/bevy/pull/11604) + +
    +
    Transform
    +
    Math
    +
    + +Callers of `Transform::up()` and similar functions may have to dereference the returned `Direction3d` to get to the inner `Vec3`. + +### [Make clipped areas of UI nodes non-interactive](https://github.com/bevyengine/bevy/pull/10454) + +
    +
    UI
    +
    + +The clipped areas of UI nodes are no longer interactive. + +`RelativeCursorPostion` is now calculated relative to the whole node’s position and size, not only the visible part. Its `mouse_over` method only returns true when the cursor is over an unclipped part of the node. + +`RelativeCursorPosition` no longer implements `Deref` and `DerefMut`. + +### [Create serialize feature for bevy_ui](https://github.com/bevyengine/bevy/pull/11188) + +
    +
    UI
    +
    + +- If you want to use serialize and deserialize with types from bevy_ui, you need to use the feature serialize in your TOML + +```toml +[dependencies.bevy] +features = ["serialize"] +``` + +### [Camera-driven UI](https://github.com/bevyengine/bevy/pull/10559) + +
    +
    UI
    +
    + +If the world contains more than one camera, insert `TargetCamera(Entity)` component to each UI root node, where `Entity` is the ID of the camera you want this specific UI tree to be rendered to. Test for any required adjustments of UI positioning and scaling. + +```rust +// before +commands.spawn(Camera3dBundle { ... }); +commands.spawn(NodeBundle { ... }); + +// after +let camera = commands.spawn(Camera3dBundle { ... }).id(); +commands.spawn((TargetCamera(camera), NodeBundle { ... })); +``` + +Remove `UiCameraConfig` component from all cameras. If it was used to control UI visibility, insert `Visibility` component on UI root nodes instead. + +### [Save an instruction in `EntityHasher`](https://github.com/bevyengine/bevy/pull/10648) + +
    +
    Utils
    +
    + +(none needed) + +### [Change `Window` scale factor to f32 (adopted)](https://github.com/bevyengine/bevy/pull/10897) + +
    +
    Windowing
    +
    + + + +### [Update winit dependency to 0.29](https://github.com/bevyengine/bevy/pull/10702) + +
    +
    Windowing
    +
    + +This PR should have one. + +### [Remove CanvasParentResizePlugin](https://github.com/bevyengine/bevy/pull/11057) + +
    +
    Windowing
    +
    + +- Remove uses of `Window::fit_canvas_to_parent` in favor of CSS properties, for example: + +```css +canvas { + width: 100%; + height: 100%; +} +``` + +### [Cleanup bevy winit](https://github.com/bevyengine/bevy/pull/11489) + +
    +
    Windowing
    +
    + +`bevy::window::WindowMoved`’s `entity` field has been renamed to `window`. This is to be more consistent with other windowing events. + +Consider changing usage: + +```diff +-window_moved.entity ++window_moved.window +``` + +### [Add `name` to `bevy::window::Window`](https://github.com/bevyengine/bevy/pull/7650) + +
    +
    Windowing
    +
    + +- Set the `bevy_window::Window`’s `name` field when needed: + +```rust +App::new() + .add_plugins(DefaultPlugins.set(WindowPlugin { + primary_window: Some(Window { + title: "I am a window!".into(), + name: Some("SpaceGameCompany.SpaceShooter".into()), + ..default() + }), + ..default() + })) + .run(); +``` + +### [delete methods deprecated in 0.12](https://github.com/bevyengine/bevy/pull/10693) + +
    +
    No area label
    +
    + + + +### [Renamed Accessibility plugin to AccessKitPlugin in bevy_winit](https://github.com/bevyengine/bevy/pull/10914) + +
    +
    No area label
    +
    + +- `bevy_winit::AccessibilityPlugin` has been renamed to `AccessKitPlugin`. + +### [Use EntityHashMap whenever possible](https://github.com/bevyengine/bevy/pull/11353) + +
    +
    No area label
    +
    + +TODO + +### [Use TypeIdMap whenever possible](https://github.com/bevyengine/bevy/pull/11684) + +
    +
    No area label
    +
    + +- `TypeIdMap` now lives in `bevy_utils` +- `DrawFunctionsInternal::indices` now uses a `TypeIdMap`. + +### [bevy_render: use the non-send marker from bevy_core](https://github.com/bevyengine/bevy/pull/11725) + +
    +
    No area label
    +
    + +- If you were using `bevy::render::view::NonSendMarker` or `bevy::render::view::window::NonSendMarker`, use `bevy::core::NonSendMarker` instead + +
    From c03aedbab421f7d505843d6e391cc006b3fb1d46 Mon Sep 17 00:00:00 2001 From: icesentry Date: Thu, 15 Feb 2024 20:15:29 -0500 Subject: [PATCH 5/9] first clean up pass --- .../learn/migration-guides/0.12-to-0.13.md | 377 +++++++----------- .../learn/migration-guides/introduction.md | 2 +- 2 files changed, 147 insertions(+), 232 deletions(-) diff --git a/content/learn/migration-guides/0.12-to-0.13.md b/content/learn/migration-guides/0.12-to-0.13.md index ec0734d8d0..4f713b53bc 100644 --- a/content/learn/migration-guides/0.12-to-0.13.md +++ b/content/learn/migration-guides/0.12-to-0.13.md @@ -18,35 +18,31 @@ As a result, the Minimum Supported Rust Version (MSRV) is "the latest stable rel When manually specifying an animation `VariableCurve`, the interpolation type must be specified: -- Bevy 0.12 - ```rust - VariableCurve { - keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0], - keyframes: Keyframes::Rotation(vec![ - Quat::IDENTITY, - Quat::from_axis_angle(Vec3::Y, PI / 2.), - Quat::from_axis_angle(Vec3::Y, PI / 2. * 2.), - Quat::from_axis_angle(Vec3::Y, PI / 2. * 3.), - Quat::IDENTITY, - ]), - }, -``` - -- Bevy 0.13 +// 0.12 +VariableCurve { + keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0], + keyframes: Keyframes::Rotation(vec![ + Quat::IDENTITY, + Quat::from_axis_angle(Vec3::Y, PI / 2.), + Quat::from_axis_angle(Vec3::Y, PI / 2. * 2.), + Quat::from_axis_angle(Vec3::Y, PI / 2. * 3.), + Quat::IDENTITY, + ]), +}, -```rust - VariableCurve { - keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0], - keyframes: Keyframes::Rotation(vec![ - Quat::IDENTITY, - Quat::from_axis_angle(Vec3::Y, PI / 2.), - Quat::from_axis_angle(Vec3::Y, PI / 2. * 2.), - Quat::from_axis_angle(Vec3::Y, PI / 2. * 3.), - Quat::IDENTITY, - ]), - interpolation: Interpolation::Linear, - }, +// 0.13 +VariableCurve { + keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0], + keyframes: Keyframes::Rotation(vec![ + Quat::IDENTITY, + Quat::from_axis_angle(Vec3::Y, PI / 2.), + Quat::from_axis_angle(Vec3::Y, PI / 2. * 2.), + Quat::from_axis_angle(Vec3::Y, PI / 2. * 3.), + Quat::IDENTITY, + ]), + interpolation: Interpolation::Linear, +}, ``` ### [`ReadAssetBytesError::Io` exposes failing path](https://github.com/bevyengine/bevy/pull/10450) @@ -55,9 +51,10 @@ When manually specifying an animation `VariableCurve`, the interpolation type mu
    Assets
    -- The `ReadAssetBytesError::Io` variant now contains two named fields instead of converting from `std::io::Error`. - - `path`: The requested (failing) path (`PathBuf`) - - `source`: The source `std::io::Error` +The `ReadAssetBytesError::Io` variant now contains two named fields instead of converting from `std::io::Error`. + +- `path`: The requested (failing) path (`PathBuf`) +- `source`: The source `std::io::Error` ### [Ensure consistency between Un/Typed `AssetId` and `Handle`](https://github.com/bevyengine/bevy/pull/10628) @@ -84,10 +81,10 @@ If you relied on any of the panicing `From` implementations, simply Some `into` calls that worked previously might now be broken because of the new trait bounds. You need to either remove `into` or perform the conversion explicitly with `from`: ```rust -// Doesn't compile +// 0.12 let mesh_handle = meshes.add(shape::Cube { size: 1.0 }.into()), -// These compile +// 0.13 let mesh_handle = meshes.add(shape::Cube { size: 1.0 }), let mesh_handle = meshes.add(Mesh::from(shape::Cube { size: 1.0 })), ``` @@ -112,17 +109,9 @@ This means users who want to migrate their .meta files will have to add the `inc
    Assets
    -- For `add_texture` you need to wrap your AssetId in Some +- For `add_texture` you need to wrap your `AssetId` in `Some` - `finish` now returns the atlas texture image directly instead of a handle. Provide the atlas texture to `add` on Assets to get a Handle -### [Fix embedded asset path manipulation](https://github.com/bevyengine/bevy/pull/10383) - -
    -
    Assets
    -
    - -No API changes. - ### [Remove the ability to ignore global volume](https://github.com/bevyengine/bevy/pull/11092)
    @@ -142,13 +131,13 @@ The option to ignore the global volume using `Volume::Absolute` has been removed If you were modifying or reading `SpatialScale` at run time, use `DefaultSpatialScale` instead. ```rust -// before +// 0.12 app.add_plugins(DefaultPlugins.set(AudioPlugin { spatial_scale: SpatialScale::new(AUDIO_SCALE), ..default() })); -// after +// 0.13 app.add_plugins(DefaultPlugins.set(AudioPlugin { default_spatial_scale: SpatialScale::new(AUDIO_SCALE), ..default() @@ -161,10 +150,7 @@ app.add_plugins(DefaultPlugins.set(AudioPlugin {
    Diagnostics
    -> -This section is optional. If there are no breaking changes, you can delete this section. - -- Added a new field `update_subscriber` in the `LogPlugin` +Added a new field `update_subscriber` in the `LogPlugin` ### [Replace `DiagnosticId` by `DiagnosticPath`](https://github.com/bevyengine/bevy/pull/9266) @@ -209,18 +195,6 @@ __`InstanceInfo`__ - `entity_map` - This is a property, not a method. ---- - -This is my first time contributing in a while, and I’m not familiar with the usage of `EntityMapper`. I changed the type definition and fixed all errors, but there may have been things I’ve missed. Please keep an eye out for me! - -### [Optimize `Entity::eq`](https://github.com/bevyengine/bevy/pull/10519) - -
    -
    ECS
    -
    - -(I really hope nobody was using this on uninitialized entities where sufficiently tortured `unsafe` could could technically notice that this has changed.) - ### [Update `Event` send methods to return `EventId`](https://github.com/bevyengine/bevy/pull/10551)
    @@ -244,12 +218,12 @@ For the following methods: Ensure calls to these methods either handle the returned value, or suppress the result with `;`. ```rust -// Now fails to compile due to mismatched return type +// 0.12 fn send_my_event(mut events: EventWriter) { events.send_default() } -// Fix +// 0.13 fn send_my_event(mut events: EventWriter) { events.send_default(); } @@ -258,14 +232,14 @@ fn send_my_event(mut events: EventWriter) { This will most likely be noticed within `match` statements: ```rust -// Before +// 0.12 match is_pressed { true => events.send(PlayerAction::Fire), // ^--^ No longer returns () false => {} } -// After +// 0.13 match is_pressed { true => { events.send(PlayerAction::Fire); @@ -282,19 +256,16 @@ match is_pressed { Any `unsafe` code relying on field ordering of `Entity` or sufficiently cursed shenanigans should change to reflect the different internal representation and alignment requirements of `Entity`. -Co-authored-by: james7132 [contact@jamessliu.com](contact@jamessliu.com) -Co-authored-by: NathanW [nathansward@comcast.net](nathansward@comcast.net) - ### [Split WorldQuery into WorldQueryData and WorldQueryFilter](https://github.com/bevyengine/bevy/pull/9918)
    ECS
    -- Update derives +- You'll need to update your related derives ```rust -// old +// 0.12 #[derive(WorldQuery)] #[world_query(mutable, derive(Debug))] struct CustomQuery { @@ -307,7 +278,7 @@ struct QueryFilter { _c: With } -// new +// 0.13 #[derive(WorldQueryData)] #[world_query_data(mutable, derive(Debug))] struct CustomQuery { @@ -324,18 +295,16 @@ struct QueryFilter { - Replace `Option>` with `Has` ```rust -/// old -fn my_system(query: Query<(Entity, Option>)>) -{ +// 0.12 +fn my_system(query: Query<(Entity, Option>)>) { for (entity, has_a_option) in query.iter(){ let has_a:bool = has_a_option.is_some(); //todo!() } } -/// new -fn my_system(query: Query<(Entity, Has)>) -{ +// 0.13 +fn my_system(query: Query<(Entity, Has)>) { for (entity, has_a) in query.iter(){ //todo!() } @@ -345,33 +314,29 @@ fn my_system(query: Query<(Entity, Has)>) - Fix queries which had filters in the data position or vice versa. ```rust -// old -fn my_system(query: Query<(Entity, With)>) -{ +// 0.12 +fn my_system(query: Query<(Entity, With)>) { for (entity, _) in query.iter(){ //todo!() } } -// new -fn my_system(query: Query>) -{ +// 0.13 +fn my_system(query: Query>) { for entity in query.iter(){ //todo!() } } -// old -fn my_system(query: Query)>>) -{ +// 0.12 +fn my_system(query: Query)>>) { for (entity, _) in query.iter(){ //todo!() } } -// new -fn my_system(query: Query, Or<(With, With)>>) -{ +// 0.13 +fn my_system(query: Query, Or<(With, With)>>) { for entity in query.iter(){ //todo!() } @@ -390,40 +355,36 @@ fn my_system(query: Query, Or<(With, With `TableId::from_usize` - `TableId::index` -> `TableId::as_usize` ---- - ### [Rename `WorldQueryData` & `WorldQueryFilter` to `QueryData` & `QueryFilter`](https://github.com/bevyengine/bevy/pull/10779)
    ECS
    -Note: if merged before 0.13 is released, this should instead modify the migration guide of #10776 with the updated names. + - Rename `WorldQueryData` & `WorldQueryFilter` trait usages to `QueryData` & `QueryFilter` and their respective derive macro attributes `world_query_data` & `world_query_filter` to `query_data` & `query_filter`. - Rename the following trait type usages: - Trait’s `ExtractComponent` type `Query` to `Data`. - Trait’s `GetBatchData` type `Query` to `Data`. - Trait’s `ExtractInstance` type `Query` to `Data`. - - Trait’s `ViewNode` type `ViewQuery` to `ViewData`’ - - Trait’s `RenderCommand` types `ViewWorldQuery` & `ItemWorldQuery` to `ViewData` & `ItemData`, respectively. ```rust -// Before +// 0.12 #[derive(WorldQueryData)] #[world_query_data(derive(Debug))] struct EmptyQuery { empty: (), } -// After +// 0.13 #[derive(QueryData)] #[query_data(derive(Debug))] struct EmptyQuery { empty: (), } -// Before +// 0.12 #[derive(WorldQueryFilter)] struct CustomQueryFilter { _c: With, @@ -432,7 +393,7 @@ struct CustomQueryFilter { _generic_tuple: (With, With

    ), } -// After +// 0.13 #[derive(QueryFilter)] struct CustomQueryFilter { _c: With, @@ -441,7 +402,7 @@ struct CustomQueryFilter { _generic_tuple: (With, With

    ), } -// Before +// 0.12 impl ExtractComponent for ContrastAdaptiveSharpeningSettings { type Query = &'static Self; type Filter = With; @@ -452,7 +413,7 @@ impl ExtractComponent for ContrastAdaptiveSharpeningSettings { } } -// After +// 0.13 impl ExtractComponent for ContrastAdaptiveSharpeningSettings { type Data = &'static Self; type Filter = With; @@ -463,7 +424,7 @@ impl ExtractComponent for ContrastAdaptiveSharpeningSettings { } } -// Before +// 0.12 impl GetBatchData for MeshPipeline { type Param = SRes; type Query = Entity; @@ -479,7 +440,7 @@ impl GetBatchData for MeshPipeline { } } -// After +// 0.13 impl GetBatchData for MeshPipeline { type Param = SRes; type Data = Entity; @@ -495,7 +456,7 @@ impl GetBatchData for MeshPipeline { } } -// Before +// 0.12 impl ExtractInstance for AssetId where A: Asset, @@ -508,7 +469,7 @@ where } } -// After +// 0.13 impl ExtractInstance for AssetId where A: Asset, @@ -521,7 +482,7 @@ where } } -// Before +// 0.12 impl ViewNode for PostProcessNode { type ViewQuery = ( &'static ViewTarget, @@ -539,7 +500,7 @@ impl ViewNode for PostProcessNode { } } -// After +// 0.13 impl ViewNode for PostProcessNode { type ViewData = ( &'static ViewTarget, @@ -557,7 +518,7 @@ impl ViewNode for PostProcessNode { } } -// Before +// 0.12 impl RenderCommand

    for SetItemPipeline { type Param = SRes; type ViewWorldQuery = (); @@ -574,7 +535,7 @@ impl RenderCommand

    for SetItemPipeline { } } -// After +// 0.13 impl RenderCommand

    for SetItemPipeline { type Param = SRes; type ViewData = (); @@ -617,7 +578,7 @@ impl RenderCommand

    for SetItemPipeline {

    -- Renamed `App::add_state` to `init_state`. +Renamed `App::add_state` to `init_state`. ### [Rename `ArchetypeEntity::entity` into `ArchetypeEntity::id`](https://github.com/bevyengine/bevy/pull/11118) @@ -627,14 +588,6 @@ impl RenderCommand

    for SetItemPipeline { The method `ArchetypeEntity::entity` has been renamed to `ArchetypeEntity::id` -### [StateTransitionEvent](https://github.com/bevyengine/bevy/pull/11089) - -

    -
    ECS
    -
    - -N/A no breaking changes - ### [Restore support for running `fn` `EntityCommands` on entities that might be despawned](https://github.com/bevyengine/bevy/pull/11107)
    @@ -646,13 +599,13 @@ All `Command` types in `bevy_ecs`, such as `Spawn`, `SpawnBatch`, `Insert`, etc. If you were working with `ChildBuilder`, recreate these commands using a closure. For example, you might migrate a Command to insert components like: ```rust -// Before (0.12) +// 0.12 (0.12) parent.add_command(Insert { entity: ent_text, bundle: Capitalizable, }); -// After (0.13) +// 0.13 (0.13) parent.add_command(move |world: &mut World| { world.entity_mut(ent_text).insert(Capitalizable); }); @@ -681,12 +634,12 @@ parent.add_command(move |world: &mut World| { The lifetimes for `EntityCommands` have been simplified. ```rust -// Before (Bevy 0.12) +// 0.12 (Bevy 0.12) struct MyStruct<'w, 's, 'a> { commands: EntityCommands<'w, 's, 'a>, } -// After (Bevy 0.13) +// 0.13 (Bevy 0.13) struct MyStruct<'a> { commands: EntityCommands<'a>, } @@ -695,11 +648,11 @@ struct MyStruct<'a> { The method `EntityCommands::commands` now returns `Commands` rather than `&mut Commands`. ```rust -// Before (Bevy 0.12) +// 0.12 (Bevy 0.12) let commands = entity_commands.commands(); commands.spawn(...); -// After (Bevy 0.13) +// 0.13 (Bevy 0.13) let mut commands = entity_commands.commands(); commands.spawn(...); ``` @@ -726,7 +679,7 @@ For example: ```rust fn system(query: Query<(&A, &B, &C)>) { - // Before + // 0.12 let b = query.get_component::(entity).unwrap(); // Alternative 1 (using tuple destructuring) @@ -776,10 +729,10 @@ The below _does_ require a change, since you’re comparing a `System` type to a ```rust fn test_system() {} -// Before +// 0.12 assert_eq!(test_system.type_id(), IntoSystem::into_system(test_system).type_id()); -// After +// 0.13 assert_eq!(test_system.system_type_id(), IntoSystem::into_system(test_system).type_id()); ``` @@ -792,8 +745,7 @@ assert_eq!(test_system.system_type_id(), IntoSystem::into_system(test_system).ty
    Diagnostics
    -- Add a call to `Schedule::set_label()` for any custom `Schedule` - - This is only required if the `Schedule` will be stepped +Add a call to `Schedule::set_label()` for any custom `Schedule`. This is only required if the `Schedule` will be stepped ### [Make the MapEntities trait generic over Mappers, and add a simpler EntityMapper](https://github.com/bevyengine/bevy/pull/11428) @@ -802,19 +754,11 @@ assert_eq!(test_system.system_type_id(), IntoSystem::into_system(test_system).ty
    Scenes
    -- - -The existing `EntityMapper` (notably used to replicate `Scenes` across different `World`s) has been renamed to `SceneEntityMapper` - -- - -The `MapEntities` trait now works with a generic `EntityMapper` instead of the specific struct `EntityMapper`. +- The existing `EntityMapper` (notably used to replicate `Scenes` across different `World`s) has been renamed to `SceneEntityMapper` +- The `MapEntities` trait now works with a generic `EntityMapper` instead of the specific struct `EntityMapper`. Calls to `fn map_entities(&mut self, entity_mapper: &mut EntityMapper)` need to be updated to `fn map_entities(&mut self, entity_mapper: &mut M)` - -- - -The new trait `EntityMapper` has been added to the prelude +- The new trait `EntityMapper` has been added to the prelude ### [Async channel v2](https://github.com/bevyengine/bevy/pull/10692) @@ -823,7 +767,7 @@ The new trait `EntityMapper` has been added to the prelude
    Tasks
    -- The `PipelinedRendering` plugin is no longer exported on wasm. If you are including it in your wasm builds you should remove it. +The `PipelinedRendering` plugin is no longer exported on wasm. If you are including it in your wasm builds you should remove it. ```rust #[cfg(all(not(target_arch = "wasm32"))] @@ -837,7 +781,7 @@ app.add_plugins(bevy_render::pipelined_rendering::PipelinedRenderingPlugin);
    Time
    -- Usage of `RunFixedUpdateLoop` should be renamed to `RunFixedMainLoop`. +Usage of `RunFixedUpdateLoop` should be renamed to `RunFixedMainLoop`. ### [Move `EntityHash` related types into `bevy_ecs`](https://github.com/bevyengine/bevy/pull/11498) @@ -849,22 +793,14 @@ app.add_plugins(bevy_render::pipelined_rendering::PipelinedRenderingPlugin); - Uses of `bevy::utils::{EntityHash, EntityHasher, EntityHashMap, EntityHashSet}` now have to be imported from `bevy::ecs::entity::hash`. - Uses of `EntityHashMap` no longer have to specify the first generic parameter. It is now hardcoded to always be `Entity`. -### [Gizmo Arrows](https://github.com/bevyengine/bevy/pull/10550) - -
    -
    Gizmos
    -
    - -N/A - ### [Move Circle Gizmos to Their Own File](https://github.com/bevyengine/bevy/pull/10631)
    Gizmos
    -- change `gizmos::CircleBuilder` to `gizmos::circles::Circle2dBuilder` -- change `gizmos::Circle2dBuilder` to `gizmos::circles::Circle2dBuilder` +- Change `gizmos::CircleBuilder` to `gizmos::circles::Circle2dBuilder` +- Change `gizmos::Circle2dBuilder` to `gizmos::circles::Circle2dBuilder` ### [move gizmo arcs to their own file](https://github.com/bevyengine/bevy/pull/10660) @@ -872,7 +808,7 @@ N/A
    Gizmos
    -- `gizmos::Arc2dBuilder` -> `gizmos::arcs::Arc2dBuilder` +`gizmos::Arc2dBuilder` -> `gizmos::arcs::Arc2dBuilder` ### [Multiple Configurations for Gizmos](https://github.com/bevyengine/bevy/pull/10342) @@ -880,7 +816,7 @@ N/A
    Gizmos
    -- `GizmoConfig` is no longer a resource and has to be accessed through `GizmoConfigStore` resource. The default config group is `DefaultGizmoGroup`, but consider using your own custom config group if applicable. +`GizmoConfig` is no longer a resource and has to be accessed through `GizmoConfigStore` resource. The default config group is `DefaultGizmoGroup`, but consider using your own custom config group if applicable. ### [Use Direction3d for gizmos.circle normal](https://github.com/bevyengine/bevy/pull/11422) @@ -888,7 +824,7 @@ N/A
    Gizmos
    -- Pass a Direction3d for gizmos.circle normal, eg. `Direction3d::new(vec).unwrap_or(default)` or potentially `Direction3d::new_unchecked(vec)` if you know your vec is definitely normalized. +Pass a Direction3d for gizmos.circle normal, eg. `Direction3d::new(vec).unwrap_or(default)` or potentially `Direction3d::new_unchecked(vec)` if you know your vec is definitely normalized. ### [Rename "AddChild" to "PushChild"](https://github.com/bevyengine/bevy/pull/11194) @@ -904,7 +840,7 @@ The struct `AddChild` has been renamed to `PushChild`, and the struct `AddChildI
    Input
    -- Breaking Change: Users need to rename `Input` to `ButtonInput` in their projects. +Users need to rename `Input` to `ButtonInput` in their projects. ### [Add window entity to TouchInput events](https://github.com/bevyengine/bevy/pull/11128) @@ -912,7 +848,7 @@ The struct `AddChild` has been renamed to `PushChild`, and the struct `AddChildI
    Input
    -- Add a `window` field when constructing or destructuring a `TouchInput` struct. +Add a `window` field when constructing or destructuring a `TouchInput` struct. ### [Add delta to CursorMoved event](https://github.com/bevyengine/bevy/pull/11710) @@ -920,7 +856,7 @@ The struct `AddChild` has been renamed to `PushChild`, and the struct `AddChildI
    Input
    -- You need to add `delta` to any manually created `CursorMoved` struct. +You need to add `delta` to any manually created `CursorMoved` struct. ### [Remove `Default` impl for `CubicCurve`](https://github.com/bevyengine/bevy/pull/11335) @@ -955,7 +891,7 @@ impl Default for MyCubicCurve {
    Math
    -- Renamed `Direction2d::from_normalized` and `Direction3d::from_normalized` to `new_unchecked`. +Renamed `Direction2d::from_normalized` and `Direction3d::from_normalized` to `new_unchecked`. ### [Add `Capsule2d` primitive](https://github.com/bevyengine/bevy/pull/11585) @@ -982,13 +918,13 @@ impl Default for MyCubicCurve { `sprite::collide_aabb::collide` and `sprite::collide_aabb::Collision` were removed. ```rust -// Before +// 0.12 let collision = bevy::sprite::collide_aabb::collide(a_pos, a_size, b_pos, b_size); if collision.is_some() { // ... } -// After +// 0.13 let collision = Aabb2d::new(a_pos.truncate(), a_size / 2.) .intersects(&Aabb2d::new(b_pos.truncate(), b_size / 2.)); if collision { @@ -1015,7 +951,7 @@ If you were making use `collide_aabb::Collision`, see the new `collide_with_side
    Reflection
    -- Existing scene files containing the former (incorrect) serialization of the `Name` component will require patching. Search for `bevy_core::name::Name`, and replace the following structure `( "name": "My Entity Name", "hash": ... )` with just a string: `"My Entity Name"`. +Existing scene files containing the former (incorrect) serialization of the `Name` component will require patching. Search for `bevy_core::name::Name`, and replace the following structure `( "name": "My Entity Name", "hash": ... )` with just a string: `"My Entity Name"`. ### [Remove TypeUuid](https://github.com/bevyengine/bevy/pull/11497) @@ -1036,11 +972,11 @@ When deriving `Reflect`, generic type params that do not need the automatic refl The attribute can define custom bounds only used by the reflection impls. To simply opt-out all the type params, we can pass in an empty where clause: `#[reflect(where)]`. ```rust -// BEFORE: +// 0.12: #[derive(Reflect)] struct Foo(#[reflect(ignore)] T); -// AFTER: +// 0.13: #[derive(Reflect)] #[reflect(where)] struct Foo(#[reflect(ignore)] T); @@ -1062,9 +998,9 @@ This PR shouldn’t be a breaking change relative to the current version of Bevy
    Reflection
    -- `bevy::reflect::AccessError` has been refactored. + -That should be it I think, everything else that was changed was private before this PR. +`bevy::reflect::AccessError` has been refactored. ### [Explicit color conversion methods](https://github.com/bevyengine/bevy/pull/10321) @@ -1075,19 +1011,15 @@ That should be it I think, everything else that was changed was private before t `Color::from(Vec4)` is now `Color::rgba_from_array(impl Into<[f32; 4]>)` `Vec4::from(Color)` is now `Color::rgba_to_vec4(&self)` -Before: - ```rust +// 0.12 let color_vec4 = Vec4::new(0.5, 0.5, 0.5); let color_from_vec4 = Color::from(color_vec4); let color_array = [0.5, 0.5, 0.5]; let color_from_array = Color::from(color_array); -``` -After: - -```rust +// 0.13 let color_vec4 = Vec4::new(0.5, 0.5, 0.5); let color_from_vec4 = Color::rgba_from_array(color_vec4); @@ -1178,7 +1110,7 @@ Lights no longer affect all `RenderLayers` by default, now like cameras and mesh
    Rendering
    -- Renamed `PbrInput::occlusion` to `diffuse_occlusion`, and added `specular_occlusion`. +Renamed `PbrInput::occlusion` to `diffuse_occlusion`, and added `specular_occlusion`. ### [Texture Atlas rework](https://github.com/bevyengine/bevy/pull/5103) @@ -1261,7 +1193,7 @@ fn my_system(
    Rendering
    -- Users of `DynamicUniformBuffer::push` now need to pass references to `DynamicUniformBuffer::push` (e.g. existing `uniforms.push(value)` will now become `uniforms.push(&value)`) +Users of `DynamicUniformBuffer::push` now need to pass references to `DynamicUniformBuffer::push` (e.g. existing `uniforms.push(value)` will now become `uniforms.push(&value)`) ### [Customizable camera main texture usage](https://github.com/bevyengine/bevy/pull/11412) @@ -1277,8 +1209,8 @@ Add `main_texture_usages: Default::default()` to your camera bundle.
    Rendering
    -trait `GetBatchData` no longer hold associated type `Data`and `Filter` -`get_batch_data` `query_item`type from `Self::Data` to `Entity` and return `Option<(Self::BufferData, Option)>` +The trait `GetBatchData` no longer hold associated type `Data` and `Filter` +`get_batch_data` `query_item` type from `Self::Data` to `Entity` and return `Option<(Self::BufferData, Option)>` `batch_and_prepare_render_phase` should not have a query ### [add `storage_texture` option to as_bind_group macro](https://github.com/bevyengine/bevy/pull/9943) @@ -1287,13 +1219,7 @@ trait `GetBatchData` no longer hold associated type `Data`and `Filter`
    Rendering
    -### [Revert rendering-related associated type name changes](https://github.com/bevyengine/bevy/pull/11027) - -
    -
    Rendering
    -
    - -- This PR amends the migration guide in + ### [Update to wgpu 0.19 and raw-window-handle 0.6](https://github.com/bevyengine/bevy/pull/11280) @@ -1344,7 +1270,7 @@ It just means that the program didn’t properly cleanup their registry keys on For Nodes and SubGraphs, instead of using hardcoded strings, you now pass labels, which can be derived with structs and enums. ```rs -// old +// 0.12 #[derive(Default)] struct MyRenderNode; impl MyRenderNode { @@ -1365,7 +1291,7 @@ render_app ], ); -// new +// 0.13 use bevy::core_pipeline::core_3d::graph::{Labels3d, SubGraph3d}; #[derive(Debug, Hash, PartialEq, Eq, Clone, RenderLabel)] @@ -1396,7 +1322,7 @@ If you still want to use dynamic labels, you can easily create those with tuple pub struct MyDynamicLabel(&'static str); ``` -__SubGraphs__ +#### SubGraphs __in `bevy_core_pipeline::core_2d::graph`__ old string-based pathnew label`NAME``SubGraph2d` @@ -1404,20 +1330,27 @@ __in `bevy_core_pipeline::core_3d::graph`__ old string-based pathnew label`NAME``SubGraph3d` __in `bevy_ui::render`__ old string-based pathnew label`draw_ui_graph::NAME``graph::SubGraphUi` -__Nodes__ + +#### Nodes __in `bevy_core_pipeline::core_2d::graph`__ -old string-based pathnew label`node::MSAA_WRITEBACK``Labels2d::MsaaWriteback``node::MAIN_PASS``Labels2d::MainPass``node::BLOOM``Labels2d::Bloom``node::TONEMAPPING``Labels2d::Tonemapping``node::FXAA``Labels2d::Fxaa``node::UPSCALING``Labels2d::Upscaling``node::CONTRAST_ADAPTIVE_SHARPENING``Labels2d::ConstrastAdaptiveSharpening``node::END_MAIN_PASS_POST_PROCESSING``Labels2d::EndMainPassPostProcessing` +old string-based path +new label `node::MSAA_WRITEBACK``Labels2d::MsaaWriteback``node::MAIN_PASS``Labels2d::MainPass``node::BLOOM``Labels2d::Bloom``node::TONEMAPPING``Labels2d::Tonemapping``node::FXAA``Labels2d::Fxaa``node::UPSCALING``Labels2d::Upscaling``node::CONTRAST_ADAPTIVE_SHARPENING``Labels2d::ConstrastAdaptiveSharpening``node::END_MAIN_PASS_POST_PROCESSING``Labels2d::EndMainPassPostProcessing` __in `bevy_core_pipeline::core_3d::graph`__ -old string-based pathnew label`node::MSAA_WRITEBACK``Labels3d::MsaaWriteback``node::PREPASS``Labels3d::Prepass``node::DEFERRED_PREPASS``Labels3d::DeferredPrepass``node::COPY_DEFERRED_LIGHTING_ID``Labels3d::CopyDeferredLightingId``node::END_PREPASSES``Labels3d::EndPrepasses``node::START_MAIN_PASS``Labels3d::StartMainPass``node::MAIN_OPAQUE_PASS``Labels3d::MainOpaquePass``node::MAIN_TRANSMISSIVE_PASS``Labels3d::MainTransmissivePass``node::MAIN_TRANSPARENT_PASS``Labels3d::MainTransparentPass``node::END_MAIN_PASS``Labels3d::EndMainPass``node::BLOOM``Labels3d::Bloom``node::TONEMAPPING``Labels3d::Tonemapping``node::FXAA``Labels3d::Fxaa``node::UPSCALING``Labels3d::Upscaling``node::CONTRAST_ADAPTIVE_SHARPENING``Labels3d::ContrastAdaptiveSharpening``node::END_MAIN_PASS_POST_PROCESSING``Labels3d::EndMainPassPostProcessing` +old string-based path +new label `node::MSAA_WRITEBACK``Labels3d::MsaaWriteback``node::PREPASS``Labels3d::Prepass``node::DEFERRED_PREPASS``Labels3d::DeferredPrepass``node::COPY_DEFERRED_LIGHTING_ID``Labels3d::CopyDeferredLightingId``node::END_PREPASSES``Labels3d::EndPrepasses``node::START_MAIN_PASS``Labels3d::StartMainPass``node::MAIN_OPAQUE_PASS``Labels3d::MainOpaquePass``node::MAIN_TRANSMISSIVE_PASS``Labels3d::MainTransmissivePass``node::MAIN_TRANSPARENT_PASS``Labels3d::MainTransparentPass``node::END_MAIN_PASS``Labels3d::EndMainPass``node::BLOOM``Labels3d::Bloom``node::TONEMAPPING``Labels3d::Tonemapping``node::FXAA``Labels3d::Fxaa``node::UPSCALING``Labels3d::Upscaling``node::CONTRAST_ADAPTIVE_SHARPENING``Labels3d::ContrastAdaptiveSharpening``node::END_MAIN_PASS_POST_PROCESSING``Labels3d::EndMainPassPostProcessing` __in `bevy_core_pipeline`__ -old string-based pathnew label`taa::draw_3d_graph::node::TAA``Labels3d::Taa` +old string-based path +new label`taa::draw_3d_graph::node::TAA``Labels3d::Taa` __in `bevy_pbr`__ -old string-based pathnew label`draw_3d_graph::node::SHADOW_PASS``LabelsPbr::ShadowPass``ssao::draw_3d_graph::node::SCREEN_SPACE_AMBIENT_OCCLUSION``LabelsPbr::ScreenSpaceAmbientOcclusion``deferred::DEFFERED_LIGHTING_PASS``LabelsPbr::DeferredLightingPass` +old string-based path +new label `draw_3d_graph::node::SHADOW_PASS``LabelsPbr::ShadowPass``ssao::draw_3d_graph::node::SCREEN_SPACE_AMBIENT_OCCLUSION``LabelsPbr::ScreenSpaceAmbientOcclusion``deferred::DEFFERED_LIGHTING_PASS``LabelsPbr::DeferredLightingPass` __in `bevy_render`__ -old string-based pathnew label`main_graph::node::CAMERA_DRIVER``graph::CameraDriverLabel` +old string-based path +new label`main_graph::node::CAMERA_DRIVER``graph::CameraDriverLabel` __in `bevy_ui::render`__ -old string-based pathnew label`draw_ui_graph::node::UI_PASS``graph::LabelsUi::UiPass`--- +old string-based path +new label`draw_ui_graph::node::UI_PASS``graph::LabelsUi::UiPass`--- ### [Gate diffuse and specular transmission behind shader defs](https://github.com/bevyengine/bevy/pull/11627) @@ -1425,7 +1358,7 @@ old string-based pathnew label`draw_ui_graph::node::UI_PASS``graph::LabelsUi::Ui
    Rendering
    -- If you were using `#ifdef STANDARDMATERIAL_NORMAL_MAP` on your shader code, make sure to update the name to `STANDARD_MATERIAL_NORMAL_MAP`; (with an underscore between `STANDARD` and `MATERIAL`) +If you were using `#ifdef STANDARDMATERIAL_NORMAL_MAP` on your shader code, make sure to update the name to `STANDARD_MATERIAL_NORMAL_MAP`; (with an underscore between `STANDARD` and `MATERIAL`) ### [Async pipeline compilation](https://github.com/bevyengine/bevy/pull/10812) @@ -1433,7 +1366,7 @@ old string-based pathnew label`draw_ui_graph::node::UI_PASS``graph::LabelsUi::Ui
    Rendering
    -- Match on the new `Creating` variant for exhaustive matches of `CachedPipelineState` +Match on the new `Creating` variant for exhaustive matches of `CachedPipelineState` ### [Mesh insert indices](https://github.com/bevyengine/bevy/pull/11745) @@ -1441,7 +1374,7 @@ old string-based pathnew label`draw_ui_graph::node::UI_PASS``graph::LabelsUi::Ui
    Rendering
    -- Use `Mesh::insert_indices` or `Mesh::with_inserted_indices` instead of `Mesh::set_indices` / `Mesh::with_indices`. +- Use `Mesh::insert_indices` or `Mesh::with_inserted_indices` instead of `Mesh::set_indices` / `Mesh::with_indices`. - If you have passed `None` to `Mesh::set_indices` or `Mesh::with_indices` you should use `Mesh::remove_indices` or `Mesh::with_removed_indices` instead. ### [wait for render app when main world is dropped](https://github.com/bevyengine/bevy/pull/11737) @@ -1450,7 +1383,7 @@ old string-based pathnew label`draw_ui_graph::node::UI_PASS``graph::LabelsUi::Ui
    Rendering
    -- If you were using the pipelined rendering channels, `MainToRenderAppSender` and `RenderToMainAppReceiver`, they have been combined into the single resource `RenderAppChannels`. +If you were using the pipelined rendering channels, `MainToRenderAppSender` and `RenderToMainAppReceiver`, they have been combined into the single resource `RenderAppChannels`. ### [Deprecate shapes in `bevy_render::mesh::shape`](https://github.com/bevyengine/bevy/pull/11773) @@ -1491,7 +1424,7 @@ let after = meshes.add(Sphere::new(0.5).mesh().ico(5).unwrap()); `RenderContext::new()` now takes adapter info -- Some render graph and Node related types and methods now have additional lifetime constraints. +Some render graph and Node related types and methods now have additional lifetime constraints. ### [Stop extracting mesh entities to the render world.](https://github.com/bevyengine/bevy/pull/11803) @@ -1499,7 +1432,7 @@ let after = meshes.add(Sphere::new(0.5).mesh().ico(5).unwrap());
    Rendering
    -- For efficiency reasons, some meshes in the render world may not have corresponding `Entity` IDs anymore. As a result, the `entity` parameter to `RenderCommand::render()` is now wrapped in an `Option`. Custom rendering code may need to be updated to handle the case in which no `Entity` exists for an object that is to be rendered. + For efficiency reasons, some meshes in the render world may not have corresponding `Entity` IDs anymore. As a result, the `entity` parameter to `RenderCommand::render()` is now wrapped in an `Option`. Custom rendering code may need to be updated to handle the case in which no `Entity` exists for an object that is to be rendered. ### [Change light defaults & fix light examples](https://github.com/bevyengine/bevy/pull/11581) @@ -1515,7 +1448,7 @@ let after = meshes.add(Sphere::new(0.5).mesh().ico(5).unwrap());
    Rendering
    -- The increased `Exposure::ev100` means that all existing 3D lighting will need to be adjusted to match (DirectionalLights, PointLights, SpotLights, EnvironmentMapLights, etc). Or alternatively, you can adjust the `Exposure::ev100` on your cameras to work nicely with your current lighting values. If you are currently relying on default intensity values, you might need to change the intensity to achieve the same effect. Note that in Bevy 0.12, point/spot lights had a different hard coded ev100 value than directional lights. In Bevy 0.13, they use the same ev100, so if you have both in your scene, the _scale_ between these light types has changed and you will likely need to adjust one or both of them. +The increased `Exposure::ev100` means that all existing 3D lighting will need to be adjusted to match (DirectionalLights, PointLights, SpotLights, EnvironmentMapLights, etc). Or alternatively, you can adjust the `Exposure::ev100` on your cameras to work nicely with your current lighting values. If you are currently relying on default intensity values, you might need to change the intensity to achieve the same effect. Note that in Bevy 0.12, point/spot lights had a different hard coded ev100 value than directional lights. In Bevy 0.13, they use the same ev100, so if you have both in your scene, the _scale_ between these light types has changed and you will likely need to adjust one or both of them. ### [Unload render assets from RAM](https://github.com/bevyengine/bevy/pull/10520) @@ -1546,20 +1479,16 @@ let after = meshes.add(Sphere::new(0.5).mesh().ico(5).unwrap()); `Ray` has been renamed to `Ray3d`. -__Ray creation__ - -Before: +#### Ray creation ```rust +// 0.12 Ray { origin: Vec3::ZERO, direction: Vec3::new(0.5, 0.6, 0.2).normalize(), } -``` -After: - -```rust +// 0.13 // Option 1: Ray3d { origin: Vec3::ZERO, @@ -1570,17 +1499,13 @@ Ray3d { Ray3d::new(Vec3::ZERO, Vec3::new(0.5, 0.6, 0.2)) ``` -__Plane intersections__ - -Before: +#### Plane intersections ```rust +// 0.12 let result = ray.intersect_plane(Vec2::X, Vec2::Y); -``` - -After: -```rust +// 0.13 let result = ray.intersect_plane(Vec2::X, Plane2d::new(Vec2::Y)); ``` @@ -1591,7 +1516,7 @@ let result = ray.intersect_plane(Vec2::X, Plane2d::new(Vec2::Y));
    Math
    -- Anywhere where you are currently expecting a f32 when getting aspect ratios, you will now receive a `AspectRatio` struct. this still holds the same value. +Anywhere where you are currently expecting a f32 when getting aspect ratios, you will now receive a `AspectRatio` struct. this still holds the same value. ### [Include UI node size in the vertex inputs for UiMaterial.](https://github.com/bevyengine/bevy/pull/11722) @@ -1602,8 +1527,6 @@ let result = ray.intersect_plane(Vec2::X, Plane2d::new(Vec2::Y)); This change should be backwards compatible, using the new field is optional. -Note to reviewers: render pipelines are a bit outside my comfort zone, so please make sure I haven’t made any mistakes. - ### [Optional ImageScaleMode](https://github.com/bevyengine/bevy/pull/11780)
    @@ -1690,7 +1613,7 @@ The clipped areas of UI nodes are no longer interactive.
    UI
    -- If you want to use serialize and deserialize with types from bevy_ui, you need to use the feature serialize in your TOML +If you want to use serialize and deserialize with types from bevy_ui, you need to use the feature serialize in your TOML ```toml [dependencies.bevy] @@ -1706,25 +1629,17 @@ features = ["serialize"] If the world contains more than one camera, insert `TargetCamera(Entity)` component to each UI root node, where `Entity` is the ID of the camera you want this specific UI tree to be rendered to. Test for any required adjustments of UI positioning and scaling. ```rust -// before +// 0.12 commands.spawn(Camera3dBundle { ... }); commands.spawn(NodeBundle { ... }); -// after +// 0.13 let camera = commands.spawn(Camera3dBundle { ... }).id(); commands.spawn((TargetCamera(camera), NodeBundle { ... })); ``` Remove `UiCameraConfig` component from all cameras. If it was used to control UI visibility, insert `Visibility` component on UI root nodes instead. -### [Save an instruction in `EntityHasher`](https://github.com/bevyengine/bevy/pull/10648) - -
    -
    Utils
    -
    - -(none needed) - ### [Change `Window` scale factor to f32 (adopted)](https://github.com/bevyengine/bevy/pull/10897)
    @@ -1739,7 +1654,7 @@ Remove `UiCameraConfig` component from all cameras. If it was used to control UI
    Windowing
    -This PR should have one. + ### [Remove CanvasParentResizePlugin](https://github.com/bevyengine/bevy/pull/11057) @@ -1747,7 +1662,7 @@ This PR should have one.
    Windowing
    -- Remove uses of `Window::fit_canvas_to_parent` in favor of CSS properties, for example: +Remove uses of `Window::fit_canvas_to_parent` in favor of CSS properties, for example: ```css canvas { @@ -1777,7 +1692,7 @@ Consider changing usage:
    Windowing
    -- Set the `bevy_window::Window`’s `name` field when needed: +Set the `bevy_window::Window`’s `name` field when needed: ```rust App::new() @@ -1806,7 +1721,7 @@ App::new()
    No area label
    -- `bevy_winit::AccessibilityPlugin` has been renamed to `AccessKitPlugin`. +`bevy_winit::AccessibilityPlugin` has been renamed to `AccessKitPlugin`. ### [Use EntityHashMap whenever possible](https://github.com/bevyengine/bevy/pull/11353) @@ -1814,7 +1729,7 @@ App::new()
    No area label
    -TODO + ### [Use TypeIdMap whenever possible](https://github.com/bevyengine/bevy/pull/11684) @@ -1831,6 +1746,6 @@ TODO
    No area label
    -- If you were using `bevy::render::view::NonSendMarker` or `bevy::render::view::window::NonSendMarker`, use `bevy::core::NonSendMarker` instead +If you were using `bevy::render::view::NonSendMarker` or `bevy::render::view::window::NonSendMarker`, use `bevy::core::NonSendMarker` instead diff --git a/content/learn/migration-guides/introduction.md b/content/learn/migration-guides/introduction.md index 6e31571848..169cba4ba9 100644 --- a/content/learn/migration-guides/introduction.md +++ b/content/learn/migration-guides/introduction.md @@ -3,7 +3,7 @@ title = "Introduction" insert_anchor_links = "right" aliases = ["learn/book/migration-guides/introduction"] [extra] -weight = 8 +weight = 9 +++ Bevy is still in the "experimentation phase", which means each release has its fair share of breaking changes. We provide migration guides for major releases to help users migrate their apps to the latest and greatest Bevy release. From d96ade2f2b61c2fdb84dea18645cd039ca65e413 Mon Sep 17 00:00:00 2001 From: IceSentry Date: Fri, 16 Feb 2024 15:11:08 -0500 Subject: [PATCH 6/9] more clean ups --- .../learn/migration-guides/0.12-to-0.13.md | 63 ++++--------------- 1 file changed, 12 insertions(+), 51 deletions(-) diff --git a/content/learn/migration-guides/0.12-to-0.13.md b/content/learn/migration-guides/0.12-to-0.13.md index 4f713b53bc..9fccc1270d 100644 --- a/content/learn/migration-guides/0.12-to-0.13.md +++ b/content/learn/migration-guides/0.12-to-0.13.md @@ -64,14 +64,6 @@ The `ReadAssetBytesError::Io` variant now contains two named fields instead of c If you relied on any of the panicing `From` implementations, simply call the existing `typed` methods instead. Alternatively, use the new `TryFrom` implementation instead to directly expose possible mistakes. -### [Add GltfLoaderSettings](https://github.com/bevyengine/bevy/pull/10804) - -
    -
    Assets
    -
    - - - ### [Use `impl Into
    ` for `Assets::add`](https://github.com/bevyengine/bevy/pull/10878)
    @@ -899,7 +891,7 @@ Renamed `Direction2d::from_normalized` and `Direction3d::from_normalized` to `ne
    Math
    - +`Capsule` is now `Capsule3d`. If you were using it for 2d you need to use `Capsule2d` ### [Rename RayTest to RayCast](https://github.com/bevyengine/bevy/pull/11635) @@ -907,7 +899,7 @@ Renamed `Direction2d::from_normalized` and `Direction3d::from_normalized` to `ne
    Math
    - +RayTest2d and RayTest3d have been renamed to RayCast2d and RayCast3d ### [Use `IntersectsVolume` for breakout example collisions](https://github.com/bevyengine/bevy/pull/11500) @@ -982,26 +974,6 @@ struct Foo(#[reflect(ignore)] T); struct Foo(#[reflect(ignore)] T); ``` -### [bevy_reflect: Split `#[reflect(where)]`](https://github.com/bevyengine/bevy/pull/11597) - -
    -
    Reflection
    -
    - -> -[!important] -This PR shouldn’t be a breaking change relative to the current version of Bevy (v0.12). And since it removes the breaking parts of #9046, that PR also won’t need a migration guide. - -### [Add the ability to manually create ParsedPaths (+ cleanup)](https://github.com/bevyengine/bevy/pull/11029) - -
    -
    Reflection
    -
    - - - -`bevy::reflect::AccessError` has been refactored. - ### [Explicit color conversion methods](https://github.com/bevyengine/bevy/pull/10321)
    @@ -1049,7 +1021,7 @@ let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { label: Some("post_process_bind_group_layout"), entries: &[ BindGroupLayoutEntry { - // ... + // ... }, ], }); @@ -1059,7 +1031,7 @@ let layout = render_device.create_bind_group_layout( "post_process_bind_group_layout", &[ BindGroupLayoutEntry { - // ... + // ... }, ], ); @@ -1213,14 +1185,6 @@ The trait `GetBatchData` no longer hold associated type `Data` and `Filter` `get_batch_data` `query_item` type from `Self::Data` to `Entity` and return `Option<(Self::BufferData, Option)>` `batch_and_prepare_render_phase` should not have a query -### [add `storage_texture` option to as_bind_group macro](https://github.com/bevyengine/bevy/pull/9943) - -
    -
    Rendering
    -
    - - - ### [Update to wgpu 0.19 and raw-window-handle 0.6](https://github.com/bevyengine/bevy/pull/11280)
    @@ -1440,7 +1404,12 @@ Some render graph and Node related types and methods now have additional lifetim
    Rendering
    - +Many default lighting values were changed: + +- `PointLight`'s default intensity is now 2000.0 +- `SpotLight`'s default intensity is now 2000.0 +- `DirectionalLight`'s default illuminance is now light_consts::lux::OVERCAST_DAY (1000.) +- `AmbientLight`'s default brightness is now 20.0 ### [New Exposure and Lighting Defaults (and calibrate examples)](https://github.com/bevyengine/bevy/pull/11868) @@ -1646,7 +1615,7 @@ Remove `UiCameraConfig` component from all cameras. If it was used to control UI
    Windowing
    - +If manipulating scale_factor, some conversion from f64 to f32 may be necessary. ### [Update winit dependency to 0.29](https://github.com/bevyengine/bevy/pull/10702) @@ -1713,7 +1682,7 @@ App::new()
    No area label
    - +Many methods that were tagged as deprecated in 0.12 have now been removed. You should consider fixing the deprecation warnings before migrating to 0.13. ### [Renamed Accessibility plugin to AccessKitPlugin in bevy_winit](https://github.com/bevyengine/bevy/pull/10914) @@ -1723,14 +1692,6 @@ App::new() `bevy_winit::AccessibilityPlugin` has been renamed to `AccessKitPlugin`. -### [Use EntityHashMap whenever possible](https://github.com/bevyengine/bevy/pull/11353) - -
    -
    No area label
    -
    - - - ### [Use TypeIdMap whenever possible](https://github.com/bevyengine/bevy/pull/11684)
    From 9ae5bb35e68d90e68882dd82aa34d51cbfcc0a17 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Fri, 16 Feb 2024 15:22:05 -0500 Subject: [PATCH 7/9] Delete non-flat migration guide --- content/learn/migration-guides/0.12-0.13/_index.md | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 content/learn/migration-guides/0.12-0.13/_index.md diff --git a/content/learn/migration-guides/0.12-0.13/_index.md b/content/learn/migration-guides/0.12-0.13/_index.md deleted file mode 100644 index ac8e6df5a5..0000000000 --- a/content/learn/migration-guides/0.12-0.13/_index.md +++ /dev/null @@ -1,14 +0,0 @@ -+++ -title = "0.12 to 0.13" -weight = 8 -sort_by = "weight" -template = "docs-section.html" -page_template = "docs-section.html" -insert_anchor_links = "right" -[extra] -long_title = "Migration Guide: 0.12 to 0.13" -+++ - -Bevy relies heavily on improvements in the Rust language and compiler. -As a result, the Minimum Supported Rust Version (MSRV) is "the latest stable release" of Rust. -
    From f9e0c6d50e6ec3e597867203e761d27248429e72 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Sat, 17 Feb 2024 03:20:19 -0800 Subject: [PATCH 8/9] Fix Render Graph Labels --- .../learn/migration-guides/0.12-to-0.13.md | 47 +++++++------------ 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/content/learn/migration-guides/0.12-to-0.13.md b/content/learn/migration-guides/0.12-to-0.13.md index 9fccc1270d..5f104065d8 100644 --- a/content/learn/migration-guides/0.12-to-0.13.md +++ b/content/learn/migration-guides/0.12-to-0.13.md @@ -353,8 +353,6 @@ fn my_system(query: Query, Or<(With, WithECS
    - - - Rename `WorldQueryData` & `WorldQueryFilter` trait usages to `QueryData` & `QueryFilter` and their respective derive macro attributes `world_query_data` & `world_query_filter` to `query_data` & `query_filter`. - Rename the following trait type usages: - Trait’s `ExtractComponent` type `Query` to `Data`. @@ -1256,7 +1254,7 @@ render_app ); // 0.13 -use bevy::core_pipeline::core_3d::graph::{Labels3d, SubGraph3d}; +use bevy::core_pipeline::core_3d::graph::{Node3d, Core3d}; #[derive(Debug, Hash, PartialEq, Eq, Clone, RenderLabel)] pub struct MyRenderLabel; @@ -1266,15 +1264,15 @@ struct MyRenderNode; render_app .add_render_graph_node::>( - SubGraph3d, + Core3d, MyRenderLabel, ) .add_render_graph_edges( - SubGraph3d, + Core3d, ( - Labels3d::Tonemapping, + Node3d::Tonemapping, MyRenderLabel, - Labels3d::EndMainPassPostProcessing, + Node3d::EndMainPassPostProcessing, ), ); ``` @@ -1288,33 +1286,20 @@ pub struct MyDynamicLabel(&'static str); #### SubGraphs -__in `bevy_core_pipeline::core_2d::graph`__ -old string-based pathnew label`NAME``SubGraph2d` -__in `bevy_core_pipeline::core_3d::graph`__ -old string-based pathnew label`NAME``SubGraph3d` -__in `bevy_ui::render`__ -old string-based pathnew label`draw_ui_graph::NAME``graph::SubGraphUi` +- `bevy_core_pipeline::core_2d::graph`: `NAME -> Core2d` +- `bevy_core_pipeline::core_3d::graph`:`NAME -> Core3d` +- `bevy_ui::render`: `draw_ui_graph::NAME -> graph::SubGraphUi` #### Nodes -__in `bevy_core_pipeline::core_2d::graph`__ -old string-based path -new label `node::MSAA_WRITEBACK``Labels2d::MsaaWriteback``node::MAIN_PASS``Labels2d::MainPass``node::BLOOM``Labels2d::Bloom``node::TONEMAPPING``Labels2d::Tonemapping``node::FXAA``Labels2d::Fxaa``node::UPSCALING``Labels2d::Upscaling``node::CONTRAST_ADAPTIVE_SHARPENING``Labels2d::ConstrastAdaptiveSharpening``node::END_MAIN_PASS_POST_PROCESSING``Labels2d::EndMainPassPostProcessing` -__in `bevy_core_pipeline::core_3d::graph`__ -old string-based path -new label `node::MSAA_WRITEBACK``Labels3d::MsaaWriteback``node::PREPASS``Labels3d::Prepass``node::DEFERRED_PREPASS``Labels3d::DeferredPrepass``node::COPY_DEFERRED_LIGHTING_ID``Labels3d::CopyDeferredLightingId``node::END_PREPASSES``Labels3d::EndPrepasses``node::START_MAIN_PASS``Labels3d::StartMainPass``node::MAIN_OPAQUE_PASS``Labels3d::MainOpaquePass``node::MAIN_TRANSMISSIVE_PASS``Labels3d::MainTransmissivePass``node::MAIN_TRANSPARENT_PASS``Labels3d::MainTransparentPass``node::END_MAIN_PASS``Labels3d::EndMainPass``node::BLOOM``Labels3d::Bloom``node::TONEMAPPING``Labels3d::Tonemapping``node::FXAA``Labels3d::Fxaa``node::UPSCALING``Labels3d::Upscaling``node::CONTRAST_ADAPTIVE_SHARPENING``Labels3d::ContrastAdaptiveSharpening``node::END_MAIN_PASS_POST_PROCESSING``Labels3d::EndMainPassPostProcessing` -__in `bevy_core_pipeline`__ -old string-based path -new label`taa::draw_3d_graph::node::TAA``Labels3d::Taa` -__in `bevy_pbr`__ -old string-based path -new label `draw_3d_graph::node::SHADOW_PASS``LabelsPbr::ShadowPass``ssao::draw_3d_graph::node::SCREEN_SPACE_AMBIENT_OCCLUSION``LabelsPbr::ScreenSpaceAmbientOcclusion``deferred::DEFFERED_LIGHTING_PASS``LabelsPbr::DeferredLightingPass` -__in `bevy_render`__ -old string-based path -new label`main_graph::node::CAMERA_DRIVER``graph::CameraDriverLabel` -__in `bevy_ui::render`__ -old string-based path -new label`draw_ui_graph::node::UI_PASS``graph::LabelsUi::UiPass`--- +- `bevy_core_pipeline::core_2d::graph`: + - `node::MSAA_WRITEBACK -> Node2d::MsaaWriteback` `node::MAIN_PASS ->Node2d::MainPass` `node::BLOOM -> Node2d::Bloom` `node::TONEMAPPING -> Node2d::Tonemapping` `node::FXAA -> Node2d::Fxaa` `node::UPSCALING -> Node2d::Upscaling` `node::CONTRAST_ADAPTIVE_SHARPENING -> Node2d::ConstrastAdaptiveSharpening` `node::END_MAIN_PASS_POST_PROCESSING -> Node2d::EndMainPassPostProcessing` +- `bevy_core_pipeline::core_3d::graph`: + - `node::MSAA_WRITEBACK -> Node3d::MsaaWriteback` `node::PREPASS -> Node3d::Prepass` `node::DEFERRED_PREPASS -> Node3d::DeferredPrepass` `node::COPY_DEFERRED_LIGHTING_ID -> Node3d::CopyDeferredLightingId` `node::END_PREPASSES -> Node3d::EndPrepasses` `node::START_MAIN_PASS -> Node3d::StartMainPass` `node::MAIN_OPAQUE_PASS -> Node3d::MainOpaquePass` `node::MAIN_TRANSMISSIVE_PASS -> Node3d::MainTransmissivePass` `node::MAIN_TRANSPARENT_PASS -> Node3d::MainTransparentPass` `node::END_MAIN_PASS -> Node3d::EndMainPass` `node::BLOOM -> Node3d::Bloom` `node::TONEMAPPING -> Node3d::Tonemapping` `node::FXAA -> Node3d::Fxaa` `node::UPSCALING -> Node3d::Upscaling` `node::CONTRAST_ADAPTIVE_SHARPENING -> Node3d::ContrastAdaptiveSharpening` `node::END_MAIN_PASS_POST_PROCESSING -> Node3d::EndMainPassPostProcessing` +- `bevy_core_pipeline`: `taa::draw_3d_graph::node::TAA -> Node3d::Taa` +- `bevy_pbr`: `draw_3d_graph::node::SHADOW_PASS -> NodePbr::ShadowPass` `ssao::draw_3d_graph::node::SCREEN_SPACE_AMBIENT_OCCLUSION -> NodePbr::ScreenSpaceAmbientOcclusion` `deferred::DEFFERED_LIGHTING_PASS -> NodePbr::DeferredLightingPass` +- `bevy_render`: `main_graph::node::CAMERA_DRIVER -> graph::CameraDriverLabel` +- `bevy_ui::render`: `draw_ui_graph::node::UI_PASS -> graph::Nodeui::UiPass` ### [Gate diffuse and specular transmission behind shader defs](https://github.com/bevyengine/bevy/pull/11627) From f0645d65b7026d860dc6d871436c1a4f21b0b24f Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Sat, 17 Feb 2024 03:21:50 -0800 Subject: [PATCH 9/9] Add missing WorldQuery renames --- content/learn/migration-guides/0.12-to-0.13.md | 1 + 1 file changed, 1 insertion(+) diff --git a/content/learn/migration-guides/0.12-to-0.13.md b/content/learn/migration-guides/0.12-to-0.13.md index 5f104065d8..c5791fe3f0 100644 --- a/content/learn/migration-guides/0.12-to-0.13.md +++ b/content/learn/migration-guides/0.12-to-0.13.md @@ -358,6 +358,7 @@ fn my_system(query: Query, Or<(With, With