diff --git a/.github/workflows/build-wasm-examples.yml b/.github/workflows/build-wasm-examples.yml new file mode 100644 index 0000000000..83301bce53 --- /dev/null +++ b/.github/workflows/build-wasm-examples.yml @@ -0,0 +1,86 @@ +name: Build WASM Examples + +on: + workflow_dispatch: + +env: + PER_PAGE: 50 + +jobs: + wasm-examples: + name: Build WASM Examples + runs-on: macos-latest + strategy: + matrix: + # if all examples are not built, add a new page here + page: [0, 1, 2] + api: [webgl2, webgpu] + steps: + + - name: Checkout Bevy latest tag + uses: actions/checkout@master + with: + repository: 'bevyengine/bevy' + ref: 'latest' + + # temporary: fetch tools from main branch + - name: Checkout Bevy Tools + uses: actions/checkout@master + with: + repository: 'bevyengine/bevy' + ref: 'main' + path: 'bevy-tools' + - name: Copy Bevy tools to latest + run: | + cp -r bevy-tools/tools/ tools + rm -rf bevy-tools + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + target: wasm32-unknown-unknown,x86_64-apple-darwin + + - name: Install WASM tooling + run: | + cargo install --force wasm-bindgen-cli + mkdir ./binaryen + wget -qO- https://github.com/WebAssembly/binaryen/releases/download/version_114/binaryen-version_114-x86_64-macos.tar.gz | tar xvz --strip-components 1 -C ./binaryen binaryen-version_114 + + - name: Build WASM Examples + run: | + export PATH=$PATH:`pwd`/binaryen/bin + 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 + with: + name: ${{ matrix.api }}-examples-${{ matrix.page }} + path: wasm-examples + + cloudflare-upload: + name: Upload to Cloudflare + runs-on: ubuntu-latest + needs: wasm-examples + strategy: + matrix: + api: [webgl2, webgpu] + steps: + + - name: Download all artifacts + uses: actions/download-artifact@v3 + + - name: Group examples in one folder + run: | + mkdir ${{ matrix.api }} + for file in ${{ matrix.api }}-examples-* + do + rsync -a $file/* ${{ matrix.api }}/ + done + + - name: Publish to Cloudflare Pages + uses: cloudflare/pages-action@v1 + with: + apiToken: ${{ secrets.CLOUDFLARE_PAGES }} + accountId: 0e862a54d5c283c78d8d56adb6159df8 + projectName: bevy-${{ matrix.api }}-examples + directory: ${{ matrix.api }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e26ee5b67..793aa9c72b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,6 +2,7 @@ name: CI on: pull_request: + merge_group: push: branches: - 'staging' @@ -95,14 +96,12 @@ jobs: content/examples/**/*.wasm key: ${{ runner.os }}-generate-wasm-examples-${{ hashFiles('generate-wasm-examples/bevy/Cargo.toml') }} - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@stable with: - toolchain: stable target: wasm32-unknown-unknown - name: "Build Bevy Examples" - run: > - cargo install --force wasm-bindgen-cli && + run: | cd generate-wasm-examples && ./generate_wasm_examples.sh @@ -112,6 +111,12 @@ jobs: path: content/examples retention-days: 1 + - uses: actions/upload-artifact@master + with: + name: generated-wasm-examples-webgpu + path: content/examples-webgpu + retention-days: 1 + generate-community: needs: [markdownlint, test-code] runs-on: ubuntu-latest @@ -142,7 +147,7 @@ jobs: markdownlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v2 with: # Full git history is needed to get a proper list of changed files within `super-linter` fetch-depth: 0 @@ -151,7 +156,7 @@ jobs: env: VALIDATE_ALL_CODEBASE: false VALIDATE_MARKDOWN: true - DEFAULT_BRANCH: master + DEFAULT_BRANCH: main test-code: runs-on: ubuntu-latest @@ -172,7 +177,7 @@ jobs: build-website: runs-on: ubuntu-latest - needs: [generate-assets, generate-errors, generate-wasm-examples, generate-community] + needs: [markdownlint, generate-assets, generate-errors, generate-wasm-examples, generate-community] steps: - uses: actions/checkout@master @@ -191,13 +196,18 @@ jobs: name: generated-wasm-examples path: content/examples + - uses: actions/download-artifact@master + with: + name: generated-wasm-examples-webgpu + path: content/examples-webgpu + - uses: actions/download-artifact@master with: name: generated-community path: content/community/people - name: "Build website" - uses: shalzz/zola-deploy-action@master + uses: shalzz/zola-deploy-action@v0.16.1-1 env: PAGES_BRANCH: gh-pages BUILD_DIR: . diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f7ddef23b7..8284efe396 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -2,7 +2,7 @@ name: Deploy on: push: - branches: [master] + branches: [main] schedule: - cron: '0 0 * * *' workflow_dispatch: @@ -34,17 +34,16 @@ jobs: - name: "Build Bevy Community" run: cd generate-community && ./generate_community.sh - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@stable with: - toolchain: stable target: wasm32-unknown-unknown - name: "Build Bevy Examples" - run: cargo install wasm-bindgen-cli && cd generate-wasm-examples && ./generate_wasm_examples.sh + run: cd generate-wasm-examples && ./generate_wasm_examples.sh - name: "Build and deploy website" if: github.repository_owner == 'bevyengine' - uses: shalzz/zola-deploy-action@master + uses: shalzz/zola-deploy-action@v0.16.1-1 env: PAGES_BRANCH: gh-pages BUILD_DIR: . diff --git a/.github/workflows/update-screenshots.yml b/.github/workflows/update-screenshots.yml new file mode 100644 index 0000000000..7e343ab64b --- /dev/null +++ b/.github/workflows/update-screenshots.yml @@ -0,0 +1,97 @@ +name: Update Screenshots + +on: + workflow_dispatch: + +env: + PER_PAGE: 20 + +jobs: + take-screenshots: + name: Take Screenshots + runs-on: ubuntu-latest + strategy: + matrix: + # if all examples are not built, add a new page here + page: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + steps: + + - name: Checkout Bevy latest tag + uses: actions/checkout@master + with: + repository: 'bevyengine/bevy' + ref: 'latest' + + # temporary: fetch tools from main branch + - name: Checkout Bevy Tools + uses: actions/checkout@master + with: + repository: 'bevyengine/bevy' + ref: 'main' + path: 'bevy-tools' + - name: Copy Bevy tools to latest + run: | + rm -rf tools + cp -r bevy-tools/tools/ tools + rm -rf bevy-tools + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + + - name: Install Bevy dependencies + run: | + sudo apt-get update; + DEBIAN_FRONTEND=noninteractive sudo apt-get install --no-install-recommends -yq \ + libasound2-dev libudev-dev; + + - name: install xvfb, llvmpipe and lavapipe + run: | + sudo apt-get update -y -qq + sudo add-apt-repository ppa:oibaf/graphics-drivers -y + sudo apt-get update + sudo apt install -y xvfb libegl1-mesa libgl1-mesa-dri libxcb-xfixes0-dev mesa-vulkan-drivers + + - name: Take Screenshots + run: | + 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 + with: + name: screenshots-${{ matrix.page }} + path: screenshots + + prepare-pr: + name: Prepare Screenshots Update PR + runs-on: ubuntu-latest + needs: take-screenshots + permissions: + pull-requests: write + contents: write + steps: + + - name: Clone bevy-website repo + uses: actions/checkout@master + + - name: Download all artifacts + uses: actions/download-artifact@v3 + + - name: Move examples to the correct folder + run: | + rm -rf static/screenshots + mkdir static/screenshots + for file in screenshots-* + do + rsync -a $file/* static/screenshots/ + rm -rf $file + done + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v5 + with: + delete-branch: true + branch-suffix: random + title: Update Examples Screenshots + body: | + This PR updates the screenshots of the examples with latest version from Bevy. + It was automatically generated by a GitHub Action. diff --git a/.gitignore b/.gitignore index bf6709cc90..dd5ca563f9 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,9 @@ public content/assets content/learn/errors content/examples +content/examples-webgpu content/community/people +content/community/donate static/assets/examples static/processed_images .vscode/ diff --git a/ROADMAP.md b/ROADMAP.md deleted file mode 100644 index 7277106331..0000000000 --- a/ROADMAP.md +++ /dev/null @@ -1,4 +0,0 @@ -# Roadmap - -* Automatically run / test code in Book docs using -* Remove/merge `content/learn/book/getting-started`? diff --git a/code-validation/src/lib.rs b/code-validation/src/lib.rs index d8a75179ad..03d76c7742 100644 --- a/code-validation/src/lib.rs +++ b/code-validation/src/lib.rs @@ -4,6 +4,11 @@ //! 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/next-steps/_index.md")] + mod next_steps {} + } #[doc = include_str!("../../content/learn/book/_index.md")] mod book { #[doc = include_str!("../../content/learn/book/assets/_index.md")] @@ -126,9 +131,6 @@ mod learn { // Not testing migration guides, because of breaking api changes. mod migration_guides {} - #[doc = include_str!("../../content/learn/book/next-steps/_index.md")] - mod next_steps {} - #[doc = include_str!("../../content/learn/book/performance-optimizations/_index.md")] mod performance_optimizations { #[doc = include_str!("../../content/learn/book/performance-optimizations/component-storage/_index.md")] diff --git a/content/community/_index.md b/content/community/_index.md index 3f9525b7a6..dfab92a9ec 100644 --- a/content/community/_index.md +++ b/content/community/_index.md @@ -1,5 +1,5 @@ +++ -title = "Community" +title = "Bevy Community" template = "community.html" [extra] header_message = "Community" diff --git a/content/community/links.toml b/content/community/links.toml new file mode 100644 index 0000000000..711b1ee832 --- /dev/null +++ b/content/community/links.toml @@ -0,0 +1,69 @@ +[[links]] +title = "GitHub" +subtitle = "bevyengine" +url = "https://github.com/bevyengine/bevy" +image = "/assets/github.svg" +image_alt = "GitHub logo" +description = "Interact with Bevy's source code, report issues, and suggest changes" + +[[links]] +title = "Bevy People" +url = "/community/people/" +image = "/assets/people.svg" +image_alt = "People image" +description = "Members of The Bevy Organization and the Bevy Community" + +[[links]] +title = "Bevy Q&A" +subtitle = "bevyengine" +url = "https://github.com/bevyengine/bevy/discussions/categories/q-a" +image = "/assets/q_and_a.svg" +image_alt = "Q and A logo" +description = "The go-to place to ask Bevy questions and get Bevy answers" + +[[links]] +title = "Bevy Assets" +url = "/assets/" +image = "/assets/bevy_icon_dark.svg" +image_alt = "Bevy logo" +description = "List of community projects in Bevy, including plugins, games, books, and tutorials." + +[[links]] +title = "Discord" +subtitle = "Bevy Engine" +url = "https://discord.gg/bevy" +image = "/assets/discord.svg" +image_alt = "Discord logo" +description = "A community to discuss Bevy, Rust, and game development" + +[[links]] +title = "Twitter" +subtitle = "bevyengine" +url = "https://twitter.com/BevyEngine" +image = "/assets/twitter.svg" +image_alt = "Twitter logo" +description = "Quick updates and shared Bevy content from the community" + +[[links]] +title = "Reddit" +subtitle = "/r/bevy" +url = "https://www.reddit.com/r/bevy/" +image = "/assets/reddit.svg" +image_alt = "Reddit logo" +description = "Stay up to date on Bevy news, share your games or plugins, and discuss Bevy." + +[[links]] +title = "itch.io" +subtitle = "bevy" +url = "https://itch.io/games/tag-bevy" +image = "/assets/itchio-textless.svg" +image_alt = "itch.io logo" +description = 'Games tagged with "bevy" on itch.io.' + +[[links]] +title = "Mastodon" +subtitle = "bevy" +url = "https://mastodon.social/@bevy" +image = "/assets/mastodon-logo-purple.svg" +image_alt = "Mastodon logo" +description = "News, boosted community creations and chatter on the short-form Fediverse network." diff --git a/content/faq/index.md b/content/faq/index.md index fc5bb463b0..c25b7d9430 100644 --- a/content/faq/index.md +++ b/content/faq/index.md @@ -1,4 +1,5 @@ +++ -title = "FAQ" +title = "Bevy FAQ" template = "faq.html" +aliases = ["learn/book/faq"] +++ \ No newline at end of file diff --git a/content/learn/index.md b/content/learn/_index.md similarity index 70% rename from content/learn/index.md rename to content/learn/_index.md index 36202f3bc9..c06b9fdc29 100644 --- a/content/learn/index.md +++ b/content/learn/_index.md @@ -1,6 +1,6 @@ +++ -title = "Learn" +title = "Learn Bevy" template = "learn.html" [extra] header_message = "Learn" -+++ \ No newline at end of file ++++ diff --git a/content/learn/book/_index.md b/content/learn/book/_index.md index 991191a56e..b2828cdfae 100644 --- a/content/learn/book/_index.md +++ b/content/learn/book/_index.md @@ -1,8 +1,8 @@ +++ title = "Book" sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" redirect_to = "learn/book/welcome" insert_anchor_links = "right" +++ diff --git a/content/learn/book/assets/_index.md b/content/learn/book/assets/_index.md index 5414bab70e..37625309ff 100644 --- a/content/learn/book/assets/_index.md +++ b/content/learn/book/assets/_index.md @@ -2,8 +2,8 @@ title = "Assets" weight = 5 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/assets/custom-assets/_index.md b/content/learn/book/assets/custom-assets/_index.md index a47ab4cbfc..043a283858 100644 --- a/content/learn/book/assets/custom-assets/_index.md +++ b/content/learn/book/assets/custom-assets/_index.md @@ -2,8 +2,8 @@ title = "Custom assets" weight = 3 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/assets/hot-reloading/_index.md b/content/learn/book/assets/hot-reloading/_index.md index 38153c8a30..d0e5caee4d 100644 --- a/content/learn/book/assets/hot-reloading/_index.md +++ b/content/learn/book/assets/hot-reloading/_index.md @@ -2,8 +2,8 @@ title = "Hot reloading" weight = 4 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/assets/loading-assets/_index.md b/content/learn/book/assets/loading-assets/_index.md index f28ea535d4..e49354c734 100644 --- a/content/learn/book/assets/loading-assets/_index.md +++ b/content/learn/book/assets/loading-assets/_index.md @@ -2,8 +2,8 @@ title = "Loading assets" weight = 1 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/assets/scenes/_index.md b/content/learn/book/assets/scenes/_index.md index 00051842c9..ebd533dac1 100644 --- a/content/learn/book/assets/scenes/_index.md +++ b/content/learn/book/assets/scenes/_index.md @@ -2,8 +2,8 @@ title = "Scenes and reflection" weight = 5 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/assets/working-with-handles/_index.md b/content/learn/book/assets/working-with-handles/_index.md index 5d3d1c3b6a..0d7f1026da 100644 --- a/content/learn/book/assets/working-with-handles/_index.md +++ b/content/learn/book/assets/working-with-handles/_index.md @@ -2,8 +2,8 @@ title = "Working with handles" weight = 2 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/audio/_index.md b/content/learn/book/audio/_index.md index fc4c3fc929..9c8e6d3afe 100644 --- a/content/learn/book/audio/_index.md +++ b/content/learn/book/audio/_index.md @@ -2,8 +2,8 @@ title = "Audio" weight = 7 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/audio/audio-basics/_index.md b/content/learn/book/audio/audio-basics/_index.md index 14c0f7c1f4..aa641cc0c6 100644 --- a/content/learn/book/audio/audio-basics/_index.md +++ b/content/learn/book/audio/audio-basics/_index.md @@ -2,8 +2,8 @@ title = "Audio basics" weight = 1 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/development-practices/_index.md b/content/learn/book/development-practices/_index.md index 7071343d01..759bd370f6 100644 --- a/content/learn/book/development-practices/_index.md +++ b/content/learn/book/development-practices/_index.md @@ -2,8 +2,8 @@ title = "Development practices" weight = 9 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/development-practices/boilerplate-reduction/_index.md b/content/learn/book/development-practices/boilerplate-reduction/_index.md index 9710336862..0f4afbdf15 100644 --- a/content/learn/book/development-practices/boilerplate-reduction/_index.md +++ b/content/learn/book/development-practices/boilerplate-reduction/_index.md @@ -2,8 +2,8 @@ title = "Boilerplate reduction" weight = 5 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/development-practices/error-handling/_index.md b/content/learn/book/development-practices/error-handling/_index.md index 861bf101a5..00f6add69a 100644 --- a/content/learn/book/development-practices/error-handling/_index.md +++ b/content/learn/book/development-practices/error-handling/_index.md @@ -2,8 +2,8 @@ title = "Error handling" weight = 4 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/development-practices/fast-compiles/_index.md b/content/learn/book/development-practices/fast-compiles/_index.md index 10f1850344..c834b986d2 100644 --- a/content/learn/book/development-practices/fast-compiles/_index.md +++ b/content/learn/book/development-practices/fast-compiles/_index.md @@ -2,8 +2,8 @@ title = "Fast compiles" weight = 2 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/development-practices/organizing-your-code/_index.md b/content/learn/book/development-practices/organizing-your-code/_index.md index 6a2d85c7b2..3b2b34f02b 100644 --- a/content/learn/book/development-practices/organizing-your-code/_index.md +++ b/content/learn/book/development-practices/organizing-your-code/_index.md @@ -2,8 +2,8 @@ title = "Organizing your code" weight = 1 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/development-practices/testing/_index.md b/content/learn/book/development-practices/testing/_index.md index 5a5fde8f58..f785e28d3e 100644 --- a/content/learn/book/development-practices/testing/_index.md +++ b/content/learn/book/development-practices/testing/_index.md @@ -2,8 +2,8 @@ title = "Testing" weight = 3 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/ecs/_index.md b/content/learn/book/ecs/_index.md index c8e87786e3..f6500c58a9 100644 --- a/content/learn/book/ecs/_index.md +++ b/content/learn/book/ecs/_index.md @@ -2,8 +2,8 @@ title = "Entities, components and systems" weight = 2 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/ecs/commands/_index.md b/content/learn/book/ecs/commands/_index.md index 54bc282f45..035b6576a7 100644 --- a/content/learn/book/ecs/commands/_index.md +++ b/content/learn/book/ecs/commands/_index.md @@ -1,7 +1,7 @@ +++ title = "Commands queue up work" weight = 5 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/ecs/detecting-changes/_index.md b/content/learn/book/ecs/detecting-changes/_index.md index b456af0b73..c97d48ffdc 100644 --- a/content/learn/book/ecs/detecting-changes/_index.md +++ b/content/learn/book/ecs/detecting-changes/_index.md @@ -1,7 +1,7 @@ +++ title = "Detecting changes" weight = 6 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" -+++ \ No newline at end of file ++++ diff --git a/content/learn/book/ecs/ecs-magic/_index.md b/content/learn/book/ecs/ecs-magic/_index.md index fc9b440a59..56a9008352 100644 --- a/content/learn/book/ecs/ecs-magic/_index.md +++ b/content/learn/book/ecs/ecs-magic/_index.md @@ -1,7 +1,7 @@ +++ title = "Understanding the magic" weight = 8 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" -+++ \ No newline at end of file ++++ diff --git a/content/learn/book/ecs/entities-components/_index.md b/content/learn/book/ecs/entities-components/_index.md index a87cbc7797..3ca99bba1d 100644 --- a/content/learn/book/ecs/entities-components/_index.md +++ b/content/learn/book/ecs/entities-components/_index.md @@ -1,8 +1,8 @@ +++ title = "Entities have components" weight = 1 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ @@ -310,7 +310,7 @@ 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] + // #[bundle] // commenting out to make code validator run; should be looked at TODO attackable_bundle: AttackableBundle, allegiance: Allegiance, } diff --git a/content/learn/book/ecs/exclusive-world-access/_index.md b/content/learn/book/ecs/exclusive-world-access/_index.md index 3dc6470583..e0fc967c0d 100644 --- a/content/learn/book/ecs/exclusive-world-access/_index.md +++ b/content/learn/book/ecs/exclusive-world-access/_index.md @@ -1,8 +1,8 @@ +++ title = "Exclusive world access" weight = 7 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/ecs/queries/_index.md b/content/learn/book/ecs/queries/_index.md index edc16b65a3..c5104dcaad 100644 --- a/content/learn/book/ecs/queries/_index.md +++ b/content/learn/book/ecs/queries/_index.md @@ -1,7 +1,7 @@ +++ title = "Fetching data with queries" weight = 2 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/ecs/resources/_index.md b/content/learn/book/ecs/resources/_index.md index c44e17f5ce..3fe42a2f3b 100644 --- a/content/learn/book/ecs/resources/_index.md +++ b/content/learn/book/ecs/resources/_index.md @@ -1,8 +1,8 @@ +++ title = "Resources are global singletons" weight = 3 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/ecs/systems/_index.md b/content/learn/book/ecs/systems/_index.md index d130159102..b88c35026f 100644 --- a/content/learn/book/ecs/systems/_index.md +++ b/content/learn/book/ecs/systems/_index.md @@ -1,8 +1,8 @@ +++ title = "Systems do work" weight = 4 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/game-logic/_index.md b/content/learn/book/game-logic/_index.md index 6e71f0d636..aa45e897e3 100644 --- a/content/learn/book/game-logic/_index.md +++ b/content/learn/book/game-logic/_index.md @@ -2,8 +2,8 @@ title = "Game logic" weight = 3 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/game-logic/async-tasks/_index.md b/content/learn/book/game-logic/async-tasks/_index.md index dceb248d1e..c591988081 100644 --- a/content/learn/book/game-logic/async-tasks/_index.md +++ b/content/learn/book/game-logic/async-tasks/_index.md @@ -2,8 +2,8 @@ title = "Async tasks" weight = 6 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/game-logic/custom-execution/_index.md b/content/learn/book/game-logic/custom-execution/_index.md index e8777434d9..8a2c1b446e 100644 --- a/content/learn/book/game-logic/custom-execution/_index.md +++ b/content/learn/book/game-logic/custom-execution/_index.md @@ -2,8 +2,8 @@ title = "Custom execution" weight = 7 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/game-logic/events/_index.md b/content/learn/book/game-logic/events/_index.md index fa05c86b94..2fb1845052 100644 --- a/content/learn/book/game-logic/events/_index.md +++ b/content/learn/book/game-logic/events/_index.md @@ -2,8 +2,8 @@ title = "Events" weight = 2 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/game-logic/run-criteria/_index.md b/content/learn/book/game-logic/run-criteria/_index.md index 57d3e89a96..e7e78540ca 100644 --- a/content/learn/book/game-logic/run-criteria/_index.md +++ b/content/learn/book/game-logic/run-criteria/_index.md @@ -2,8 +2,8 @@ title = "Run criteria" weight = 5 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/game-logic/states/_index.md b/content/learn/book/game-logic/states/_index.md index 5c2b40f8da..e9163a0d84 100644 --- a/content/learn/book/game-logic/states/_index.md +++ b/content/learn/book/game-logic/states/_index.md @@ -2,8 +2,8 @@ title = "States" weight = 3 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/game-logic/system-ordering/_index.md b/content/learn/book/game-logic/system-ordering/_index.md index d4ec6f0227..ea3df13268 100644 --- a/content/learn/book/game-logic/system-ordering/_index.md +++ b/content/learn/book/game-logic/system-ordering/_index.md @@ -1,8 +1,8 @@ +++ title = "System ordering" weight = 1 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/game-logic/time/_index.md b/content/learn/book/game-logic/time/_index.md index 5e8cd09709..19977d6a4a 100644 --- a/content/learn/book/game-logic/time/_index.md +++ b/content/learn/book/game-logic/time/_index.md @@ -2,8 +2,8 @@ title = "Time and timers" weight = 4 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/getting-started/_index.md b/content/learn/book/getting-started/_index.md index 7d0d87bda2..0b9aa4934e 100644 --- a/content/learn/book/getting-started/_index.md +++ b/content/learn/book/getting-started/_index.md @@ -1,64 +1,7 @@ +++ title = "Getting Started" weight = 2 -sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ - -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.9.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.9" # 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/graphics/2d/_index.md b/content/learn/book/graphics/2d/_index.md index 407452217e..c00ca7d5aa 100644 --- a/content/learn/book/graphics/2d/_index.md +++ b/content/learn/book/graphics/2d/_index.md @@ -2,8 +2,8 @@ title = "2D" weight = 5 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/graphics/2d/sprite-sheets/_index.md b/content/learn/book/graphics/2d/sprite-sheets/_index.md index d74b1a865c..4abe11dd17 100644 --- a/content/learn/book/graphics/2d/sprite-sheets/_index.md +++ b/content/learn/book/graphics/2d/sprite-sheets/_index.md @@ -2,8 +2,8 @@ title = "Sprite Sheets" weight = 2 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/graphics/2d/sprites/_index.md b/content/learn/book/graphics/2d/sprites/_index.md index c70adbed5f..364864eb05 100644 --- a/content/learn/book/graphics/2d/sprites/_index.md +++ b/content/learn/book/graphics/2d/sprites/_index.md @@ -2,8 +2,8 @@ title = "Sprites" weight = 1 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/graphics/3d/_index.md b/content/learn/book/graphics/3d/_index.md index 815cf1fefe..ec54d2991f 100644 --- a/content/learn/book/graphics/3d/_index.md +++ b/content/learn/book/graphics/3d/_index.md @@ -2,8 +2,8 @@ title = "3d" weight = 6 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/graphics/3d/meshes/_index.md b/content/learn/book/graphics/3d/meshes/_index.md index 9715819c30..0ac3350220 100644 --- a/content/learn/book/graphics/3d/meshes/_index.md +++ b/content/learn/book/graphics/3d/meshes/_index.md @@ -2,8 +2,8 @@ title = "Meshes" weight = 1 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/graphics/3d/pbr/_index.md b/content/learn/book/graphics/3d/pbr/_index.md index a54b0953c6..9c6b90525d 100644 --- a/content/learn/book/graphics/3d/pbr/_index.md +++ b/content/learn/book/graphics/3d/pbr/_index.md @@ -2,8 +2,8 @@ title = "Physically-based rendering" weight = 2 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/graphics/_index.md b/content/learn/book/graphics/_index.md index 00d30e92cc..ad53047c29 100644 --- a/content/learn/book/graphics/_index.md +++ b/content/learn/book/graphics/_index.md @@ -2,8 +2,8 @@ title = "Graphics" weight = 4 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/graphics/cameras/_index.md b/content/learn/book/graphics/cameras/_index.md index ed9b452428..03f69cd25b 100644 --- a/content/learn/book/graphics/cameras/_index.md +++ b/content/learn/book/graphics/cameras/_index.md @@ -2,8 +2,8 @@ title = "Cameras" weight = 2 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/graphics/parent-child-hierarchy/_index.md b/content/learn/book/graphics/parent-child-hierarchy/_index.md index 92e08b12e4..e765547cd0 100644 --- a/content/learn/book/graphics/parent-child-hierarchy/_index.md +++ b/content/learn/book/graphics/parent-child-hierarchy/_index.md @@ -2,8 +2,8 @@ title = "Parent-child hierarchy" weight = 3 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/graphics/rendering-internals/_index.md b/content/learn/book/graphics/rendering-internals/_index.md index 068fc830f6..74f7038ed4 100644 --- a/content/learn/book/graphics/rendering-internals/_index.md +++ b/content/learn/book/graphics/rendering-internals/_index.md @@ -2,8 +2,8 @@ title = "Rendering internals" weight = 7 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/graphics/rendering-internals/shader-basics/_index.md b/content/learn/book/graphics/rendering-internals/shader-basics/_index.md index 96a69de013..38feaef484 100644 --- a/content/learn/book/graphics/rendering-internals/shader-basics/_index.md +++ b/content/learn/book/graphics/rendering-internals/shader-basics/_index.md @@ -2,8 +2,8 @@ title = "Shader Basics" weight = 1 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/graphics/transforms/_index.md b/content/learn/book/graphics/transforms/_index.md index 8175d39c1c..41c3c1e815 100644 --- a/content/learn/book/graphics/transforms/_index.md +++ b/content/learn/book/graphics/transforms/_index.md @@ -2,8 +2,8 @@ title = "Transforms" weight = 1 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/graphics/windowing/_index.md b/content/learn/book/graphics/windowing/_index.md index 703cfa1c3d..8e47b3de57 100644 --- a/content/learn/book/graphics/windowing/_index.md +++ b/content/learn/book/graphics/windowing/_index.md @@ -2,8 +2,8 @@ title = "Configuring your window(s)" weight = 4 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/input/_index.md b/content/learn/book/input/_index.md index 39a33274f1..eaca0d989e 100644 --- a/content/learn/book/input/_index.md +++ b/content/learn/book/input/_index.md @@ -2,8 +2,8 @@ title = "Input" weight = 6 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/input/gamepad/_index.md b/content/learn/book/input/gamepad/_index.md index 0af58b73ae..536c9a1685 100644 --- a/content/learn/book/input/gamepad/_index.md +++ b/content/learn/book/input/gamepad/_index.md @@ -2,8 +2,8 @@ title = "Gamepad" weight = 5 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/input/input-basics/_index.md b/content/learn/book/input/input-basics/_index.md index fe25e53e3a..2f2c9fe9b5 100644 --- a/content/learn/book/input/input-basics/_index.md +++ b/content/learn/book/input/input-basics/_index.md @@ -2,8 +2,8 @@ title = "Input basics" weight = 1 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/input/keyboard/_index.md b/content/learn/book/input/keyboard/_index.md index 193495b216..6b5679042e 100644 --- a/content/learn/book/input/keyboard/_index.md +++ b/content/learn/book/input/keyboard/_index.md @@ -2,8 +2,8 @@ title = "Keyboard" weight = 2 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/input/mouse/_index.md b/content/learn/book/input/mouse/_index.md index 3bd4269d26..f84e4124ad 100644 --- a/content/learn/book/input/mouse/_index.md +++ b/content/learn/book/input/mouse/_index.md @@ -2,8 +2,8 @@ title = "Mouse" weight = 3 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/input/touch/_index.md b/content/learn/book/input/touch/_index.md index 5fc0b2cb53..c45e8640dc 100644 --- a/content/learn/book/input/touch/_index.md +++ b/content/learn/book/input/touch/_index.md @@ -2,8 +2,8 @@ title = "Touch" weight = 4 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/performance-optimizations/_index.md b/content/learn/book/performance-optimizations/_index.md index e1398b127e..736095fa75 100644 --- a/content/learn/book/performance-optimizations/_index.md +++ b/content/learn/book/performance-optimizations/_index.md @@ -1,8 +1,8 @@ +++ title = "Performance optimizations" weight = 10 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/performance-optimizations/component-storage/_index.md b/content/learn/book/performance-optimizations/component-storage/_index.md index 842fad1d25..da429526f4 100644 --- a/content/learn/book/performance-optimizations/component-storage/_index.md +++ b/content/learn/book/performance-optimizations/component-storage/_index.md @@ -1,8 +1,8 @@ +++ title = "Component storage" weight = 4 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/performance-optimizations/diagnostics-benchmarking/_index.md b/content/learn/book/performance-optimizations/diagnostics-benchmarking/_index.md index 82ed67bfc6..f5017cd7ca 100644 --- a/content/learn/book/performance-optimizations/diagnostics-benchmarking/_index.md +++ b/content/learn/book/performance-optimizations/diagnostics-benchmarking/_index.md @@ -1,8 +1,8 @@ +++ title = "Diagnostics and benchmarking" weight = 1 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/performance-optimizations/indexes/_index.md b/content/learn/book/performance-optimizations/indexes/_index.md index 5f00ac4d8e..0b93386e38 100644 --- a/content/learn/book/performance-optimizations/indexes/_index.md +++ b/content/learn/book/performance-optimizations/indexes/_index.md @@ -1,8 +1,8 @@ +++ title = "Indexes" weight = 3 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/performance-optimizations/parallel-iteration/_index.md b/content/learn/book/performance-optimizations/parallel-iteration/_index.md index 2d4100ac9b..165dbf44e5 100644 --- a/content/learn/book/performance-optimizations/parallel-iteration/_index.md +++ b/content/learn/book/performance-optimizations/parallel-iteration/_index.md @@ -1,8 +1,8 @@ +++ title = "Parallel iteration" weight = 2 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/platforms/_index.md b/content/learn/book/platforms/_index.md index 4ee26bcc1e..5a06e7829b 100644 --- a/content/learn/book/platforms/_index.md +++ b/content/learn/book/platforms/_index.md @@ -1,8 +1,8 @@ +++ title = "Platforms" weight = 11 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/platforms/android/_index.md b/content/learn/book/platforms/android/_index.md index 6c508a20ef..0f6fc289ac 100644 --- a/content/learn/book/platforms/android/_index.md +++ b/content/learn/book/platforms/android/_index.md @@ -1,8 +1,8 @@ +++ title = "iOS" weight = 3 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/platforms/ios/_index.md b/content/learn/book/platforms/ios/_index.md index f1cbc9c64f..2480d2ae0c 100644 --- a/content/learn/book/platforms/ios/_index.md +++ b/content/learn/book/platforms/ios/_index.md @@ -1,8 +1,8 @@ +++ title = "Android" weight = 2 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/platforms/web/_index.md b/content/learn/book/platforms/web/_index.md index 27213773e6..39950f7752 100644 --- a/content/learn/book/platforms/web/_index.md +++ b/content/learn/book/platforms/web/_index.md @@ -1,8 +1,8 @@ +++ title = "Web" weight = 1 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/ui/_index.md b/content/learn/book/ui/_index.md index 8478d419e8..c28e666030 100644 --- a/content/learn/book/ui/_index.md +++ b/content/learn/book/ui/_index.md @@ -2,8 +2,8 @@ title = "User interfaces" weight = 8 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/ui/ui-basics/_index.md b/content/learn/book/ui/ui-basics/_index.md index f45af34aad..c6d5aeae0b 100644 --- a/content/learn/book/ui/ui-basics/_index.md +++ b/content/learn/book/ui/ui-basics/_index.md @@ -2,8 +2,8 @@ title = "UI basics" weight = 1 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/welcome/_index.md b/content/learn/book/welcome/_index.md index 1fde699661..8f7aade86e 100644 --- a/content/learn/book/welcome/_index.md +++ b/content/learn/book/welcome/_index.md @@ -2,8 +2,8 @@ title = "Welcome" weight = 1 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/book/welcome/apps/_index.md b/content/learn/book/welcome/apps/_index.md index 3d254ad301..c2c79a3bc5 100644 --- a/content/learn/book/welcome/apps/_index.md +++ b/content/learn/book/welcome/apps/_index.md @@ -1,8 +1,8 @@ +++ title = "Apps" weight = 2 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ @@ -18,7 +18,7 @@ use bevy::prelude::*; fn main() { App::new() - .add_system(hello) + .add_systems(Update, hello) .run(); } @@ -54,7 +54,7 @@ fn main() { // Resources are global singleton data stored in the `World` .insert_resource(Message {string: "Welcome to Bevy!".to_string()}) // Systems run every pass of the game loop and perform logic - .add_system(read_message_system) + .add_systems(Update, read_message_system) .run(); } diff --git a/content/learn/book/welcome/plugins/_index.md b/content/learn/book/welcome/plugins/_index.md index 4c26e07704..542de5b070 100644 --- a/content/learn/book/welcome/plugins/_index.md +++ b/content/learn/book/welcome/plugins/_index.md @@ -1,8 +1,8 @@ +++ title = "Plugins" weight = 3 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ @@ -27,7 +27,7 @@ fn main(){ // We'll cover this in the next section. .add_plugins(DefaultPlugins) // Adds our new `Plugin` to the `App` - .add_plugin(ScorePlugin) + .add_plugins(ScorePlugin) .run(); } @@ -40,9 +40,9 @@ impl Plugin for ScorePlugin { // beginning at the default value of 0 .init_resource::() // Increments the score by 1 every pass of the game loop - .add_system(increment_score) + .add_systems(Update, increment_score) // Prints the current value of the score - .add_system(report_score); + .add_systems(Update, report_score); } } diff --git a/content/learn/book/welcome/setup/_index.md b/content/learn/book/welcome/setup/_index.md index e5293e17e9..8e64c91b76 100644 --- a/content/learn/book/welcome/setup/_index.md +++ b/content/learn/book/welcome/setup/_index.md @@ -1,8 +1,8 @@ +++ title = "Setup" weight = 1 -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ diff --git a/content/learn/links.toml b/content/learn/links.toml new file mode 100644 index 0000000000..518e865298 --- /dev/null +++ b/content/learn/links.toml @@ -0,0 +1,48 @@ +[[links]] +title = "The Bevy Book" +url = "/learn/book/introduction" +image = "/assets/book.svg" +image_alt = "Bevy book" +description = "Learn how to use Bevy using this step-by-step guide. If you are new to Bevy, you should probably start here." + +[[links]] +title = "Migration Guides" +url = "/learn/migration-guides/introduction" +image = "/assets/migration-guides.svg" +image_alt = "Versions diff" +description = "Every Bevy update brings new functionality and improvements. Follow these guides to migrate your project to the latest Bevy has to offer!" + +[[links]] +title = "Bevy Rust API Docs" +url = "https://docs.rs/bevy" +image = "/assets/rust-logo-light.svg" +image_alt = "Rust logo" +description = "Learn how to use Bevy's types, traits and methods using the in-depth reference documentation, complete with inline examples." + +[[links]] +title = "Official Examples" +url = "https://github.com/bevyengine/bevy/tree/latest/examples#examples" +image = "/assets/github.svg" +image_alt = "GitHub logo" +description = "Examples that show how to use the various features of Bevy." + +[[links]] +title = "Bevy Assets" +url = "/assets" +image = "/assets/bevy_icon_dark.svg" +image_alt = "Bevy logo" +description = "Find Assets to use in your games. Learn by example with a list of cool Bevy projects. Read community-made tutorials and documentation." + +[[links]] +title = "Bevy Web Examples" +url = "/examples" +image = "/assets/bevy_icon_dark.svg" +image_alt = "Bevy logo" +description = "Browse bevy examples compiled to wasm and running directly in your browser!" + +[[links]] +title = "Frequently Asked Questions" +url = "/faq" +image = "/assets/bevy_icon_dark.svg" +image_alt = "Bevy logo" +description = "A curated list of answers to questions Bevy users frequently ask." diff --git a/content/learn/migration-guides/0.10-0.11/_index.md b/content/learn/migration-guides/0.10-0.11/_index.md new file mode 100644 index 0000000000..a55775b58c --- /dev/null +++ b/content/learn/migration-guides/0.10-0.11/_index.md @@ -0,0 +1,1551 @@ ++++ +title = "0.10 to 0.11" +weight = 6 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +long_title = "Migration Guide: 0.10 to 0.11" ++++ + +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. +
+ +### [Schedule-First: the new and improved add_systems](https://github.com/bevyengine/bevy/pull/8079) + +
+
ECS
+
+ +We have [unified adding systems to schedules under a single API](https://github.com/bevyengine/bevy/pull/8079)! `add_systems` now accepts a `ScheduleLabel` as the first parameter. `app.add_system`, `app.add_startup_system`, `app.add_startup_systems`, `system.on_startup()`, and `system.in_schedule()` have been deprecated in favor of the unified `app.add_systems` API. + +“base sets” have been removed entirely in favor of Schedules. The built in `CoreSet` and `StartupSet` base sets have been replaced with top level schedules. (ex: `CoreSet::Update` is now the `Update` schedule). + +This removes a ton of redundant APIs, removes implicit defaults entirely, and clears up a lot of the confusion introduced by base sets. We believe the consistency and ergonomics of the new `add_systems` API speaks for itself: + +```rust +// 0.10 +app.add_system(a) +// 0.11 +app.add_systems(Update, a) + +// 0.10 +app.add_systems((a, b).in_schedule(CoreSchedule::Startup)) +// 0.11 +app.add_systems(Startup, (a, b)) + +// 0.10 +app.add_systems((a, b).in_schedule(CoreSchedule::Startup).in_base_set(StartupSet::PreStartup)) +// 0.11 +app.add_systems(PreStartup, (a, b)) + +// 0.10 +app.add_startup_systems((a, b)) +// 0.11 +app.add_systems(Startup, (a, b)) + +// 0.10 +app.add_systems((a, b).on_startup()) +// 0.11 +app.add_systems(Startup, (a, b)) + +// 0.10 +app.add_systems((c, d, e)) +// 0.11 (Update is no longer implied by default) +app.add_systems(Update, (c, d, e)) + +// 0.10 +app.add_systems((f, g).in_schedule(CoreSchedule::FixedUpdate)) +// 0.11 +app.add_systems(FixedUpdate, (f, g)) + +// 0.10 +app.add_systems(h.in_base_set(CoreSet::PostUpdate)) +// 0.11 +app.add_systems(PostUpdate, h) + +// 0.10 +app.add_systems(enter_menu.in_schedule(OnEnter(AppState::Menu))) +// 0.11 +app.add_systems(OnEnter(AppState::Menu), enter_menu) + +// 0.10 +app.add_systems(exit_menu.in_schedule(OnExit(AppState::Menu))) +// 0.11 +app.add_systems(OnExit(AppState::Menu), exit_menu) + +// 0.10 +render_app.add_systems((a, b).in_set(RenderSet::Queue)) +// 0.11 +render_app.add_systems(Render, (a, b).in_set(RenderSet::Queue)) +``` + +Set configuration now also accepts a schedule: + +```rust +// 0.10 +app.configure_set(A.in_schedule(PostUpdate).after(B)) +// 0.11 +app.configure_set(PostUpdate, A.after(B)) + +// 0.10 +app.configure_set(A.after(B)) +// 0.11 (Update is no longer implied by default) +app.configure_set(Update, A.after(B)) + +// 0.10 +app.configure_sets((A, B).in_schedule(PostUpdate).after(C)) +// 0.11 +app.configure_sets(PostUpdate, (A, B).after(C)) + +// 0.10 +app.configure_sets((A, B).after(C)) +// 0.11 (Update is no longer implied by default) +app.configure_sets(Update, (A, B).after(C)) +``` + +### [bevy_audio: ECS-based API redesign](https://github.com/bevyengine/bevy/pull/8424) + +
+
Audio
+
+ +```rust +// 0.10 + +/// Need to store handles somewhere +#[derive(Resource)] +struct MyMusic { + sink: Handle, +} + +fn play_music( + asset_server: Res, + audio: Res
diff --git a/content/learn/migration-guides/0.11-0.12/_index.md b/content/learn/migration-guides/0.11-0.12/_index.md new file mode 100644 index 0000000000..a6bfdb330a --- /dev/null +++ b/content/learn/migration-guides/0.11-0.12/_index.md @@ -0,0 +1,1538 @@ ++++ +title = "0.11 to 0.12" +weight = 7 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +long_title = "Migration Guide: 0.11 to 0.12" ++++ + +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. +
+ +### [API updates to the AnimationPlayer](https://github.com/bevyengine/bevy/pull/9002) + +
+
Animation
+
+ +Some methods on [`AnimationPlayer`](https://docs.rs/bevy/0.12.0/bevy/animation/struct.AnimationPlayer.html) have changed. + +- `elapsed` was removed. Use `seek_time`. +- `set_elapsed` was removed. Use `seek_to`. +- `stop_repeating` was removed. Use `set_repeat(RepeatAnimation::Never)`. + +If you were manually resetting animation state, you can use the new `replay` method instead. + +### [Fix run-once runners](https://github.com/bevyengine/bevy/pull/10195) + +
+
App
+
+ +`app.ready()` has been replaced by `app.plugins_state()` which will return more details on the current state of plugins in the app + +### [Add support for KHR_materials_emissive_strength](https://github.com/bevyengine/bevy/pull/9553) + +
+
Assets
+
+ +The GLTF asset loader will now factor in `emissiveStrength` when converting to Bevy’s `StandardMaterial::emissive`. Blender will export emissive materials using this field. Remove the field from your GLTF files or manually modify your materials post-asset-load to match how Bevy would load these files in previous versions. + +### [Bevy Asset V2](https://github.com/bevyengine/bevy/pull/8624) + +
+
Assets
+
+ +#### Migrating a custom asset loader + +Existing asset loaders will need a few small changes to get them to work with Bevy Assets V2. + +First, you’ll need to add the asset type as an associated type of the loader. This type is called `Asset` and represents the type of the “default asset” produced by the loader. + +You’ll also need to add a `Settings` type which represents options that can be passed to the loader when you request an asset. If your asset has no settings, then you can just set it to the unit type. + +```rust +pub struct MyAssetLoader; + +impl AssetLoader for MyAssetLoader { + type Asset = MyAsset; + type Settings = (); +``` + +You’ll need to make a couple small changes to the `load` function as well. The load function now takes a `settings` parameter whose type is, you guessed it, `Settings`: + +```rust + fn load<'a>( + &'a self, + reader: &'a mut Reader, + settings: &'a Self::Settings, + load_context: &'a mut LoadContext, + ) -> BoxedFuture<'a, Result> { +``` + +Again, if you are not using settings, then you can just ignore the parameter (prefix it with “_”). + +Also, the second argument is now a reader rather than vector of bytes. If your existing code expects bytes, you can simply read the entire stream: + +```rust + fn load<'a>( + &'a self, + reader: &'a mut Reader, + _settings: &'a Self::Settings, + load_context: &'a mut LoadContext, + ) -> BoxedFuture<'a, Result> { + Box::pin(async move { + let mut bytes = Vec::new(); + reader.read_to_end(&mut bytes).await?; +``` + +Finally, you’ll need to write the code which returns the default asset. This used to be done via a call to `load_context.set_default_asset()`, however in V2 you simply return the asset from the `load` function: + +```rust + fn load<'a>( + &'a self, + reader: &'a mut Reader, + _settings: &'a Self::Settings, + load_context: &'a mut LoadContext, + ) -> BoxedFuture<'a, Result> { + Box::pin(async move { + let mut bytes = Vec::new(); + reader.read_to_end(&mut bytes).await?; + let mut asset: MyAsset = + serde_json::from_slice(&bytes).expect("unable to decode asset"); + Ok(asset) + } +``` + +To use the new loader, make sure you register both the loader and the asset type: + +```rust +app.register_asset_loader(MyAssetLoader) + .init_asset::() +``` + +#### Asset hot-reloading + +The feature `filesystem_watcher` has been renamed to `file_watcher`. +In addition, you no longer need to manually configure the `ChangeWatcher` in the `AssetPlugin` as it is now configured automatically when the feature is enabled. + +#### Labeled assets + +If your loader allows labeled assets, there are a couple of different ways to handle them. The simplest is to call `load_context.labeled_asset_scope`: + +```rust +// Assume `asset.children` is a HashMap or something. +// Using `drain` here so that we take ownership and don't end up with +// multiple references to the same asset. +asset.children.drain().for_each(|(label, mut item)| { + load_context.labeled_asset_scope(label, |lc| { + // Do any additional processing on the item + // Use 'lc' to load dependencies + item + }); +}); +``` + +You can use the provided load context (`lc`) to load additional assets. These will automatically be registered as dependencies of the labeled asset. + +#### Using assets + +The actual call to `load` hasn’t changed: + +```rust +let handle = server.load("path/to/my/asset.json"); + +// ... + +let data = assets.get(&handle).unwrap(); +``` + +#### Asset events + +There are a few changes to asset events. The event no longer contains a `handle` field, instead the event contains a field called `id`: + +```rust +for ev in ev_template.read() { + match ev { + AssetEvent::Added { id } => { + println!("Asset added"); + } + AssetEvent::LoadedWithDependencies { id } => { + println!("Asset loaded"); + } + AssetEvent::Modified { id } => { + println!("Asset modified"); + } + AssetEvent::Removed { id } => { + println!("Asset removed"); + } + } +} +``` + +The `id` can be used to get access to the asset data, the asset’s path or load status. Asset handles also contain an `id` field which can be used to compare for equality: + +```rust +AssetEvent::Modified { id } => { + for cmp in query.iter() { + if cmp.handle.id() == id { + println!("Found it!"); + } + } +} +``` + +Also, as you may have noticed, the set of events has changed. The most important of these is `LoadedWithDependencies` which tells you that the asset and all its dependencies have finished loading into memory. + +### [Copy on Write AssetPaths](https://github.com/bevyengine/bevy/pull/9729) + +
+
Assets
+
+ +```rust +// 0.11 +AssetPath::new("logo.png", None); + +// 0.12 +AssetPath::from("logo.png"); + +// 0.11 +AssetPath::new("scene.gltf", Some("Mesh0")); + +// 0.12 +AssetPath::from("scene.gltf").with_label("Mesh0"); +``` + +`AssetPath` now serializes as `AssetPath("some_path.extension#Label")` instead of as `AssetPath { path: "some_path.extension", label: Some("Label) }` + +### [Removed `anyhow`](https://github.com/bevyengine/bevy/pull/10003) + +
+
Assets
+
+ +- `anyhow` is no longer exported by `bevy_asset`; Add it to your own project (if required). +- `AssetLoader` and `AssetSaver` have an associated type `Error`; Define an appropriate error type (e.g., using `thiserror`), or use a pre-made error type (e.g., `anyhow::Error`). Note that using `anyhow::Error` is a drop-in replacement. +- `AssetLoaderError` has been removed; Define a new error type, or use an alternative (e.g., `anyhow::Error`) +- All the first-party `AssetLoader`s and `AssetSaver`s now return relevant (and narrow) error types instead of a single ambiguous type; Match over the specific error type, or encapsulate (`Box`, `thiserror`, `anyhow`, etc.) + +### [Non-blocking load_untyped using a wrapper asset](https://github.com/bevyengine/bevy/pull/10198) + +
+
Assets
+
+ +Whenever possible use the typed API in order to directly get a handle to your asset. If you do not know the type or need to use `load_untyped` for a different reason, Bevy 0.12 introduces an additional layer of indirection. The asset server will return a handle to a `LoadedUntypedAsset`, which will load in the background. Once it is loaded, the untyped handle to the asset file can be retrieved from the `LoadedUntypedAsset`s field `handle`. + +### [reflect: `TypePath` part 2](https://github.com/bevyengine/bevy/pull/8768) + +
+
Assets
+
Reflection
+
+ +- Rely on `TypePath` instead of `std::any::type_name` for all stability guarantees and for use in all reflection contexts, this is used through with one of the following APIs: + - `TypePath::type_path` if you have a concrete type and not a value. + - `DynamicTypePath::reflect_type_path` if you have an `dyn Reflect` value without a concrete type. + - `TypeInfo::type_path` for use through the registry or if you want to work with the represented type of a `DynamicFoo`. +- Remove `type_name` from manual `Reflect` implementations. +- Use `type_path` and `type_path_table` in place of `type_name` on `TypeInfo`-like structs. +- Use `get_with_type_path(_mut)` over `get_with_type_name(_mut)`. + +### [More ergonomic spatial audio](https://github.com/bevyengine/bevy/pull/9800) + +
+
Audio
+
+ +Spatial audio now automatically uses the transform of the `AudioBundle` and of an entity with a `SpatialListener` component. + +If you were manually scaling emitter/listener positions, you can use the `spatial_scale` field of `AudioPlugin` instead. + +```rust +// 0.11 +commands.spawn( + SpatialAudioBundle { + source: asset_server.load("sounds/Windless Slopes.ogg"), + settings: PlaybackSettings::LOOP, + spatial: SpatialSettings::new(listener_position, gap, emitter_position), + }, +); + +fn update( + emitter_query: Query<(&Transform, &SpatialAudioSink)>, + listener_query: Query<&Transform, With>, +) { + let listener = listener_query.single(); + + for (transform, sink) in &emitter_query { + sink.set_emitter_position(transform.translation); + sink.set_listener_position(*listener, gap); + } +} + +// 0.12 +commands.spawn(( + SpatialBundle::from_transform(Transform::from_translation(emitter_position)), + AudioBundle { + source: asset_server.load("sounds/Windless Slopes.ogg"), + settings: PlaybackSettings::LOOP.with_spatial(true), + }, +)); + +commands.spawn(( + SpatialBundle::from_transform(Transform::from_translation(listener_position)), + SpatialListener::new(gap), +)); +``` + +### [Simplify parallel iteration methods](https://github.com/bevyengine/bevy/pull/8854) + +
+
ECS
+
+ +The method `QueryParIter::for_each_mut` has been deprecated and is no longer functional. Use `for_each` instead, which now supports mutable queries. + +```rust +// 0.11 +query.par_iter_mut().for_each_mut(|x| ...); + +// 0.12 +query.par_iter_mut().for_each(|x| ...); +``` + +The method `QueryParIter::for_each` now takes ownership of the `QueryParIter`, rather than taking a shared reference. + +```rust +// 0.11 +let par_iter = my_query.par_iter().batching_strategy(my_batching_strategy); +par_iter.for_each(|x| { + // ...Do stuff with x... + par_iter.for_each(|y| { + // ...Do nested stuff with y... + }); +}); + +// 0.12 +my_query.par_iter().batching_strategy(my_batching_strategy).for_each(|x| { + // ...Do stuff with x... + my_query.par_iter().batching_strategy(my_batching_strategy).for_each(|y| { + // ...Do nested stuff with y... + }); +}); +``` + +### [Fix safety invariants for `WorldQuery::fetch` and simplify cloning](https://github.com/bevyengine/bevy/pull/8246) + +
+
ECS
+
+ +**`fetch` invariants** + +The function `WorldQuery::fetch` has had the following safety invariant added: + +> If `update_component_access` includes any mutable accesses, then the caller must ensure that `fetch` is called no more than once for each `entity`/`table_row` in each archetype. +>
+> If `Self` implements `ReadOnlyWorldQuery`, then this can safely be called multiple times. + +This invariant was always required for soundness, but was previously undocumented. If you called this function manually anywhere, you should check to make sure that this invariant is not violated. + +**Removed `clone_fetch`** + +The function `WorldQuery::clone_fetch` has been removed. The associated type `WorldQuery::Fetch` now has the bound `Clone`. + +```rust +// 0.11 +struct MyFetch<'w> { ... } + +unsafe impl WorldQuery for MyQuery { + ... + type Fetch<'w> = MyFetch<'w> + unsafe fn clone_fetch<'w>(fetch: &Self::Fetch<'w>) -> Self::Fetch<'w> { + MyFetch { + field1: fetch.field1, + field2: fetch.field2.clone(), + ... + } + } +} + +// 0.12 +#[derive(Clone)] +struct MyFetch<'w> { ... } + +unsafe impl WorldQuery for MyQuery { + ... + type Fetch<'w> = MyFetch<'w>; +} +``` + +### [Opt-out `multi-threaded` feature flag](https://github.com/bevyengine/bevy/pull/9269) + +
+
ECS
+
+ +The `multi-threaded` feature in `bevy_ecs` and `bevy_tasks` is no longer enabled by default. However, this remains a default feature for the umbrella `bevy` crate. + +if you are using `bevy` without `default-features`, or if you depend on `bevy_ecs` or `bevy_tasks` directly, you most likely want to enable this to allow systems to run in parallel. + +### [Refactor build_schedule and related errors](https://github.com/bevyengine/bevy/pull/9579) + +
+
ECS
+
+ +`ScheduleBuildError` now has strings in more of its variants. You may need to adjust code that is handling these variants. + +### [Add `system.map(...)` for transforming the output of a system](https://github.com/bevyengine/bevy/pull/8526) + +
+
ECS
+
+ +The `system_adapter` functions have been deprecated: use `.map` instead, which is a lightweight alternative to `.pipe`. + +```rust +// 0.11 +my_system.pipe(system_adapter::ignore) +my_system.pipe(system_adapter::unwrap) +my_system.pipe(system_adapter::new(T::from)) + +// 0.12 +my_system.map(std::mem::drop) +my_system.map(Result::unwrap) +my_system.map(T::from) + +// 0.11 +my_system.pipe(system_adapter::info) +my_system.pipe(system_adapter::dbg) +my_system.pipe(system_adapter::warn) +my_system.pipe(system_adapter::error) + +// 0.12 +my_system.map(bevy_utils::info) +my_system.map(bevy_utils::dbg) +my_system.map(bevy_utils::warn) +my_system.map(bevy_utils::error) +``` + +### [Replaced EntityMap with HashMap](https://github.com/bevyengine/bevy/pull/9461) + +
+
ECS
+
+ +- Calls to `EntityMap::world_scope` can be directly replaced with the following: +`map.world_scope(&mut world)` -> `world.world_scope(&mut map)` +- Calls to legacy `EntityMap` methods such as `EntityMap::get` must explicitly include de/reference symbols: +`let entity = map.get(parent);` -> `let &entity = map.get(&parent);` + +### [Rename `ManualEventIterator`](https://github.com/bevyengine/bevy/pull/9592) + +
+
ECS
+
+ +The type `ManualEventIterator` has been renamed to `EventIterator`. Additionally, `ManualEventIteratorWithId` has been renamed to `EventIteratorWithId`. + +### [Replaced `EntityCommand` Implementation for `FnOnce`](https://github.com/bevyengine/bevy/pull/9604) + +
+
ECS
+
+ +**1. New-Type `FnOnce`** + +Create an `EntityCommand` type which implements the method you previously wrote: + +```rust +pub struct ClassicEntityCommand(pub F); + +impl EntityCommand for ClassicEntityCommand +where + F: FnOnce(Entity, &mut World) + Send + 'static, +{ + fn apply(self, id: Entity, world: &mut World) { + (self.0)(id, world); + } +} + +commands.add(ClassicEntityCommand(|id: Entity, world: &mut World| { + /* ... */ +})); +``` + +**2. Extract `(Entity, &mut World)` from `EntityMut`** + +The method `into_world_mut` can be used to gain access to the `World` from an `EntityMut`. + +```rust +let old = |id: Entity, world: &mut World| { + /* ... */ +}; + +let new = |mut entity: EntityWorldMut| { + let id = entity.id(); + let world = entity.into_world_mut(); + /* ... */ +}; +``` + +### [Move schedule name into `Schedule`](https://github.com/bevyengine/bevy/pull/9600) + +
+
ECS
+
+ +`Schedule::new` and `App::add_schedule` + +```rust +// 0.11 +let schedule = Schedule::new(); +app.add_schedule(MyLabel, schedule); + +// 0.12 +let schedule = Schedule::new(MyLabel); +app.add_schedule(schedule); +``` + +if you aren’t inserting the schedule into the world and are using the schedule directly you can use the default constructor which reuses a default label. + +```rust +// 0.11 +let schedule = Schedule::new(); +schedule.run(world); + +// 0.12 +let schedule = Schedule::default(); +schedule.run(world); +``` + +`Schedules::insert` + +```rust +// 0.11 +let schedule = Schedule::new(); +schedules.insert(MyLabel, schedule); + +// 0.12 +let schedule = Schedule::new(MyLabel); +schedules.insert(schedule); +``` + +`World::add_schedule` + +```rust +// 0.11 +let schedule = Schedule::new(); +world.add_schedule(MyLabel, schedule); + +// 0.12 +let schedule = Schedule::new(MyLabel); +world.add_schedule(schedule); +``` + +### [Refactor `EventReader::iter` to `read`](https://github.com/bevyengine/bevy/pull/9631) + +
+
ECS
+
+ +- Existing usages of `EventReader::iter` and `EventReader::iter_with_id` will have to be changed to `EventReader::read` and `EventReader::read_with_id` respectively. +- Existing usages of `ManualEventReader::iter` and `ManualEventReader::iter_with_id` will have to be changed to `ManualEventReader::read` and `ManualEventReader::read_with_id` respectively. + +### [Replace `IntoSystemSetConfig` with `IntoSystemSetConfigs`](https://github.com/bevyengine/bevy/pull/9247) + +
+
ECS
+
+ +- Use `App::configure_sets` instead of `App::configure_set` +- Use `Schedule::configure_sets` instead of `Schedule::configure_set` + +### [Moved `get_component(_unchecked_mut)` from `Query` to `QueryState`](https://github.com/bevyengine/bevy/pull/9686) + +
+
ECS
+
+ +`use bevy_ecs::system::QueryComponentError;` -> `use bevy_ecs::query::QueryComponentError;` + +### [Fix naming on "tick" Column and ComponentSparseSet methods](https://github.com/bevyengine/bevy/pull/9744) + +
+
ECS
+
+ +The following method names were renamed, from `foo_ticks_bar` to `foo_tick_bar` (`ticks` is now singular, `tick`): + +- `ComponentSparseSet::get_added_ticks` → `get_added_tick` +- `ComponentSparseSet::get_changed_ticks` → `get_changed_tick` +- `Column::get_added_ticks` → `get_added_tick` +- `Column::get_changed_ticks` → `get_changed_tick` +- `Column::get_added_ticks_unchecked` → `get_added_tick_unchecked` +- `Column::get_changed_ticks_unchecked` → `get_changed_tick_unchecked` + +### [Return a boolean from `set_if_neq`](https://github.com/bevyengine/bevy/pull/9801) + +
+
ECS
+
+ +The trait method `DetectChangesMut::set_if_neq` now returns a boolean value indicating whether or not the value was changed. If you were implementing this function manually, you must now return `true` if the value was overwritten and `false` if the value was not. + +### [Rename RemovedComponents::iter/iter_with_id to read/read_with_id](https://github.com/bevyengine/bevy/pull/9778) + +
+
ECS
+
+ +```rust +fn react_on_removal(mut removed: RemovedComponents) { + // 0.11 + for entity in removed.iter() { /* ... */ } + for (entity, id) in removed.iter_with_id() { /* ... */ } + for entity in &mut removed { /* ... */ } + + // 0.12 + for entity in removed.read() { /* ... */ } + for (entity, id) in removed.read_with_id() { /* ... */ } + for entity in removed.read() { /* ... */ } +} +``` + +### [Remove States::variants and remove enum-only restriction its derive](https://github.com/bevyengine/bevy/pull/9945) + +
+
ECS
+
+ +`States::variants` no longer exists. If you relied on this function, consider using a library that provides enum iterators. + +### [Replace all labels with interned labels](https://github.com/bevyengine/bevy/pull/7762) + +
+
ECS
+
+ +- Replace `BoxedScheduleLabel` and `Box` with `InternedScheduleLabel` or `Interned`. +- Replace `BoxedSystemSet` and `Box` with `InternedSystemSet` or `Interned`. +- Replace `AppLabelId` with `InternedAppLabel` or `Interned`. +- Types manually implementing `ScheduleLabel`, `AppLabel` or `SystemSet` need to implement: + - `dyn_hash` directly instead of implementing `DynHash` + - `as_dyn_eq` + +- Pass labels to `World::try_schedule_scope`, `World::schedule_scope`, `World::try_run_schedule`. `World::run_schedule`, `Schedules::remove`, `Schedules::remove_entry`, `Schedules::contains`, `Schedules::get` and `Schedules::get_mut` by value instead of by reference. + +### [Add configure_schedules to App and Schedules to apply `ScheduleBuildSettings` to all schedules](https://github.com/bevyengine/bevy/pull/9514) + +
+
ECS
+
App
+
+ +- No breaking changes. +- Adds `Schedule::get_build_settings()` getter for the schedule’s `ScheduleBuildSettings`. +- Can replaced manual configuration of all schedules: + +```rust +// 0.11 +for (_, schedule) in app.world.resource_mut::().iter_mut() { + schedule.set_build_settings(build_settings); +} + +// 0.l2 +app.configure_schedules(build_settings); +``` + +### [Only run event systems if they have tangible work to do](https://github.com/bevyengine/bevy/pull/7728) + +
+
ECS
+
App
+
+ +`Events::update_system` has been split off from the the type and can be found at `bevy_ecs::event::event_update_system`. + +### [Allow disjoint mutable world access via `EntityMut`](https://github.com/bevyengine/bevy/pull/9419) + +
+
ECS
+
Reflection
+
+ +Removed the method `EntityRef::world`, to fix a soundness issue with queries. If you need access to `&World` while using an `EntityRef`, consider passing the world as a separate parameter. + +`EntityMut` can no longer perform ‘structural’ world mutations, such as adding or removing components, or despawning the entity. Additionally, `EntityMut::world`, `EntityMut::world_mut`, `EntityMut::into_world_mut`, and `EntityMut::world_scope` have been removed. +Instead, use the newly-added type `EntityWorldMut`, which is a helper type for working with `&mut World`. + +### [Make builder types take and return `Self`](https://github.com/bevyengine/bevy/pull/10001) + +
+
ECS
+
Scenes
+
+ +When using `bevy_ecs::DynamicSceneBuilder` and `bevy_ecs::SceneBuilder`, instead of binding the builder to a variable, directly use it. Methods on those types now consume `Self`, so you will need to re-bind the builder if you don’t `build` it immediately. + +```rust +// 0.11 +let mut scene_builder = DynamicSceneBuilder::from_world(&world); +let scene = scene_builder.extract_entity(a).extract_entity(b).build(); + +// 0.12 +let scene = DynamicSceneBuilder::from_world(&world) + .extract_entity(a) + .extract_entity(b) + .build(); +``` + +### [Change `AxisSettings` livezone default](https://github.com/bevyengine/bevy/pull/10090) + +
+
Input
+
+ +The default live zone bounds have been changed from `-0.95..=0.95` to `-1.0..=1.0` to align with more common usage. If you were relying on the old default, you can change change this by modifying [`GamepadSettings::default_axis_settings`](https://docs.rs/bevy/0.12.0/bevy/input/gamepad/struct.GamepadSettings.html#structfield.default_axis_settings). + +### [Rename bevy_math::rects conversion methods](https://github.com/bevyengine/bevy/pull/9159) + +
+
Math
+
+ +Replace `Rect::as_urect` with `Rect::as_irect`, `Rect::as_rect` with `Rect::as_urect`, and `URect::as_urect` with `URect::as_irect`. + +### [Rename `Bezier` to `CubicBezier` for clarity](https://github.com/bevyengine/bevy/pull/9554) + +
+
Math
+
+ +Change all `Bezier` references to `CubicBezier` + +### [Add `Cubic` prefix to all cubic curve generators](https://github.com/bevyengine/bevy/pull/10299) + +
+
Math
+
+ +- Rename: `BSpline` -> `CubicBSpline` +- Rename: `CardinalSpline` -> `CubicCardinalSpline` +- Rename: `Hermite` -> `CubicHermite` + +### [Remove the bevy_dylib feature](https://github.com/bevyengine/bevy/pull/9516) + +
+
Meta
+
+ +If you were using Bevy’s `bevy_dylib` feature, use Bevy’s `dynamic_linking` feature instead. + +```shell +# 0.11 +cargo run --features bevy/bevy_dylib + +# 0.12 +cargo run --features bevy/dynamic_linking +``` + +```toml +[dependencies] +# 0.11 +bevy = { version = "0.11", features = ["bevy_dylib"] } + +# 0.12 +bevy = { version = "0.12", features = ["dynamic_linking"] } +``` + +### [Refactor `path` module of `bevy_reflect`](https://github.com/bevyengine/bevy/pull/8887) + +
+
Reflection
+
+ +If you were matching on the `Err(ReflectPathError)` value returned by `GetPath` and `ParsedPath` methods, now only the parse-related errors and the offset are publicly accessible. You can always use the `fmt::Display` to get a clear error message, but if you need programmatic access to the error types, please open an issue. + +### [Make it so `ParsedPath` can be passed to GetPath](https://github.com/bevyengine/bevy/pull/9373) + +
+
Reflection
+
+ +`GetPath` now requires `Reflect`. This reduces a lot of boilerplate on bevy’s side. If you were implementing manually `GetPath` on your own type, please get in touch! + +`ParsedPath::element[_mut]` isn’t an inherent method of `ParsedPath`, you must now import `ReflectPath`. This is only relevant if you weren’t importing the bevy prelude. + +```diff +-use bevy::reflect::ParsedPath; ++use bevy::reflect::{ParsedPath, ReflectPath}; + +parsed_path.element(reflect_type).unwrap() +``` + +### [Remove TypeRegistry re-export rename](https://github.com/bevyengine/bevy/pull/9807) + +
+
Reflection
+
+ +- `TypeRegistry` as re-exported by the wrapper `bevy` crate is now `TypeRegistryArc` +- `TypeRegistryInternal` as re-exported by the wrapper `bevy` crate is now `TypeRegistry` + +### [Provide getters for fields of ReflectFromPtr](https://github.com/bevyengine/bevy/pull/9748) + +
+
Reflection
+
+ +- `ReflectFromPtr::as_reflect_ptr` is now `ReflectFromPtr::as_reflect` +- `ReflectFromPtr::as_reflect_ptr_mut` is now `ReflectFromPtr::as_reflect_mut` + +### [bevy_reflect: Fix ignored/skipped field order](https://github.com/bevyengine/bevy/pull/7575) + +
+
Reflection
+
+ +- Fields marked `#[reflect(skip_serializing)]` now must implement `Default` or specify a custom default function with `#[reflect(default = "path::to::some_func")]` + +```rust +#[derive(Reflect)] +struct MyStruct { + #[reflect(skip_serializing)] + #[reflect(default = "get_foo_default")] + foo: Foo, // <- `Foo` does not impl `Default` so requires a custom function + #[reflect(skip_serializing)] + bar: Bar, // <- `Bar` impls `Default` +} + +#[derive(Reflect)] +struct Foo(i32); + +#[derive(Reflect, Default)] +struct Bar(i32); + +fn get_foo_default() -> Foo { + Foo(123) +} +``` + +- `SerializationData::new` has been changed to expect an iterator of `(usize, SkippedField)` rather than one of just `usize` + +```rust +// 0.11 +SerializationData::new([0, 3].into_iter()); + +// 0.12 +SerializationData::new([ + (0, SkippedField::new(field_0_default_fn)), + (3, SkippedField::new(field_3_default_fn)), +].into_iter()); +``` + +- `Serialization::is_ignored_field` has been renamed to `Serialization::is_field_skipped` +- Fields marked `#[reflect(skip_serializing)]` are now included in deserialization output. This may affect logic that expected those fields to be absent. + +### [Return URect instead of (UVec2, UVec2) in Camera::physical_viewport_rect](https://github.com/bevyengine/bevy/pull/9085) + +
+
Rendering
+
+ +```rust +// 0.11 +fn view_physical_camera_rect(camera_query: Query<&Camera>) { + let camera = camera_query.single(); + let Some((min, max)) = camera.physical_viewport_rect() else { return }; + dbg!(min, max); +} + +// 0.12 +fn view_physical_camera_rect(camera_query: Query<&Camera>) { + let camera = camera_query.single(); + let Some(URect { min, max }) = camera.physical_viewport_rect() else { return }; + dbg!(min, max); +} +``` + +### [Update `bevy_window::PresentMode` to mirror `wgpu::PresentMode`](https://github.com/bevyengine/bevy/pull/9230) + +
+
Rendering
+
+ +Handle `bevy_window::PresentMode::FifoRelaxed` when tweaking window present mode manually. + +### [Use GpuArrayBuffer for MeshUniform](https://github.com/bevyengine/bevy/pull/9254) + +
+
Rendering
+
+ +Accessing the `model` member of an individual mesh object’s shader `Mesh` struct the old way where each `MeshUniform` was stored at its own dynamic offset: + +```rust +struct Vertex { + @location(0) position: vec3, +}; + +fn vertex(vertex: Vertex) -> VertexOutput { + var out: VertexOutput; + out.clip_position = mesh_position_local_to_clip( + mesh.model, + vec4(vertex.position, 1.0) + ); + return out; +} +``` + +The new way where one needs to index into the array of `Mesh`es for the batch: + +```rust +struct Vertex { + @builtin(instance_index) instance_index: u32, + @location(0) position: vec3, +}; + +fn vertex(vertex: Vertex) -> VertexOutput { + var out: VertexOutput; + out.clip_position = mesh_position_local_to_clip( + mesh[vertex.instance_index].model, + vec4(vertex.position, 1.0) + ); + return out; +} +``` + +Note that using the instance_index is the default way to pass the per-object index into the shader, but if you wish to do custom rendering approaches you can pass it in however you like. + +### [Reduce the size of MeshUniform to improve performance](https://github.com/bevyengine/bevy/pull/9416) + +
+
Rendering
+
+ +`Sphere::intersects_obb` and `Frustum::intersects_obb` now take an `Affine3A` instead of a `Mat4`. You can use `Affine3A::from_mat4` or `Transform::compute_affine` to get an `Affine3A`. + +`MeshUniform` now stores its current and previous model transforms as 4x3 matrices. Helper functions were added to bevy_pbr::mesh_functions to unpack the data. + +```rust +// 0.11 +var model = mesh[instance_index].model; + +// 0.12 +#import bevy_pbr::mesh_functions::affine_to_square + +var model = affine_to_square(mesh[instance_index].model); +``` + +### [Reorder render sets, refactor bevy_sprite to take advantage](https://github.com/bevyengine/bevy/pull/9236) + +
+
Rendering
+
+ +- Assets such as materials and meshes should now be created in `PrepareAssets` e.g. `prepare_assets` +- Queueing entities to `RenderPhase`s continues to be done in `Queue` e.g. `queue_sprites` +- Preparing resources (textures, buffers, etc.) should now be done in `PrepareResources`, e.g. `prepare_prepass_textures`, `prepare_mesh_uniforms` +- Prepare bind groups should now be done in `PrepareBindGroups` e.g. `prepare_mesh_bind_group` +- Any batching or instancing can now be done in `Prepare` where the order of the phase items is known e.g. `prepare_sprites` + +### [Split `ComputedVisibility` into two components to allow for accurate change detection and speed up visibility propagation](https://github.com/bevyengine/bevy/pull/9497) + +
+
Rendering
+
+ +The `ComputedVisibility` component has been split into `InheritedVisibility` and +`ViewVisibility`. Replace any usages of `ComputedVisibility::is_visible_in_hierarchy` +with `InheritedVisibility::get`, and replace `ComputedVisibility::is_visible_in_view` +with `ViewVisibility::get`. + +```rust +// 0.11: +commands.spawn(VisibilityBundle { + visibility: Visibility::Inherited, + computed_visibility: ComputedVisibility::default(), +}); + +// 0.12: +commands.spawn(VisibilityBundle { + visibility: Visibility::Inherited, + inherited_visibility: InheritedVisibility::default(), + view_visibility: ViewVisibility::default(), +}); +``` + +```rust +// 0.11: +fn my_system(q: Query<&ComputedVisibility>) { + for vis in &q { + if vis.is_visible_in_hierarchy() { + +// 0.12: +fn my_system(q: Query<&InheritedVisibility>) { + for inherited_visibility in &q { + if inherited_visibility.get() { +``` + +```rust +// 0.11: +fn my_system(q: Query<&ComputedVisibility>) { + for vis in &q { + if vis.is_visible_in_view() { + +// 0.12: +fn my_system(q: Query<&ViewVisibility>) { + for view_visibility in &q { + if view_visibility.get() { +``` + +```rust +// 0.11: +fn my_system(mut q: Query<&mut ComputedVisibility>) { + for vis in &mut q { + vis.set_visible_in_view(); + +// 0.12: +fn my_system(mut q: Query<&mut ViewVisibility>) { + for view_visibility in &mut q { + view_visibility.set(); +``` + +### [Cleanup `visibility` module](https://github.com/bevyengine/bevy/pull/9850) + +
+
Rendering
+
+ +The `check_visibility` system’s `Option<&NoFrustumCulling>` parameter has been replaced by `Has`, if you were calling it manually, you should change the type to match it + +### [Allow other plugins to create renderer resources](https://github.com/bevyengine/bevy/pull/9925) + +
+
Rendering
+
+ +The `RenderPlugin` now takes a `RenderCreation` enum instead of `WgpuSettings`. `RenderSettings::default()` returns `RenderSettings::Automatic(WgpuSettings::default())`. `RenderSettings` also implements `From`. + +```rust +// 0.11 +RenderPlugin { + wgpu_settings: WgpuSettings { + ... + }, +} + +// 0.12 +RenderPlugin { + render_creation: RenderCreation::Automatic(WgpuSettings { + ... + }), +} +// or +RenderPlugin { + render_creation: WgpuSettings { + ... + }.into(), +} +``` + +### [Use EntityHashMap for render world entity storage for better performance](https://github.com/bevyengine/bevy/pull/9903) + +
+
Rendering
+
+ +Previously the render app extracted mesh entities and their component data from the main world and stored them as entities and components in the render world. Now they are extracted into essentially `EntityHashMap` where `T` are structs containing an appropriate group of data. This means that while extract set systems will continue to run extract queries against the main world they will store their data in hash maps. Also, systems in later sets will either need to look up entities in the available resources such as `RenderMeshInstances`, or maintain their own `EntityHashMap` for their own data. + +```rust +// 0.11 +fn queue_custom( + material_meshes: Query<(Entity, &MeshTransforms, &Handle), With>, +) { + ... + for (entity, mesh_transforms, mesh_handle) in &material_meshes { + ... + } +} + +// 0.12 +fn queue_custom( + render_mesh_instances: Res, + instance_entities: Query>, +) { + ... + for entity in &instance_entities { + let Some(mesh_instance) = render_mesh_instances.get(&entity) else { continue; }; + // The mesh handle in `AssetId` form, and the `MeshTransforms` can now + // be found in `mesh_instance` which is a `RenderMeshInstance` + ... + } +} +``` + +### [PCF For DirectionalLight/SpotLight Shadows](https://github.com/bevyengine/bevy/pull/8006) + +
+
Rendering
+
+ +Shadows cast by directional lights or spotlights now have smoother edges. To revert to the old behavior, add `ShadowFilteringMethod::Hardware2x2` to your cameras. + +### [use `Material` for wireframes](https://github.com/bevyengine/bevy/pull/5314) + +
+
Rendering
+
+ +`WireframePipeline` was removed. If you were using it directly, please create an issue explaining your use case. + +### [Deferred Renderer](https://github.com/bevyengine/bevy/pull/9258) + +
+
Rendering
+
+ + + +### [pbr shader cleanup](https://github.com/bevyengine/bevy/pull/10105) + +
+
Rendering
+
+ +in custom material shaders: + +- `pbr_functions::pbr` no longer calls to `pbr_functions::alpha_discard`. if you were using the `pbr` function in a custom shader with alpha mask mode you now also need to call alpha_discard manually +- rename imports of `bevy_pbr::mesh_vertex_output` to `bevy_pbr::forward_io` +- rename instances of `MeshVertexOutput` to `VertexOutput` + +in custom material prepass shaders: + +- rename instances of `VertexOutput::clip_position` to `VertexOutput::position` + +### [`*_PREPASS` Shader Def Cleanup](https://github.com/bevyengine/bevy/pull/10136) + +
+
Rendering
+
+ +When using functions from `bevy_pbr::prepass_utils` (`prepass_depth()`, `prepass_normal()`, `prepass_motion_vector()`) in contexts where these prepasses might be disabled, you should now wrap your calls with the appropriate `#ifdef` guards, (`#ifdef DEPTH_PREPASS`, `#ifdef NORMAL_PREPASS`, `#ifdef MOTION_VECTOR_PREPASS`) providing fallback logic where applicable. + +### [Allow extensions to StandardMaterial](https://github.com/bevyengine/bevy/pull/7820) + +
+
Rendering
+
+ +Manual implementations of `AsBindGroup` will need to be adjusted, the changes are pretty straightforward and can be seen in the diff for e.g. the `texture_binding_array` example. + +### [Variable `MeshPipeline` View Bind Group Layout](https://github.com/bevyengine/bevy/pull/10156) + +
+
Rendering
+
+ +`MeshPipeline::view_layout` and `MeshPipeline::view_layout_multisampled` have been replaced with a private array to accommodate for variable view bind group layouts. To obtain a view bind group layout for the current pipeline state, use the new `MeshPipeline::get_view_layout()` or `MeshPipeline::get_view_layout_from_key()` methods. + +### [Update shader imports](https://github.com/bevyengine/bevy/pull/10180) + +
+
Rendering
+
+ +naga_oil 0.10 reworks the import mechanism to support more syntax to make it more rusty, and test for item use before importing to determine which imports are modules and which are items, which allows: + +- use rust-style imports + +```rust +#import bevy_pbr::{ + pbr_functions::{alpha_discard as discard, apply_pbr_lighting}, + mesh_bindings, +} +``` + +- import partial paths: + +```rust +#import part::of::path +// ... +path::remainder::function(); +``` + +which will call to `part::of::path::remainder::function` + +- use fully qualified paths without importing: + +```rust +// #import bevy_pbr::pbr_functions +bevy_pbr::pbr_functions::pbr() +``` + +- use imported items without qualifying + +```rust +#import bevy_pbr::pbr_functions::pbr +// for backwards compatibility the old style is still supported: +// #import bevy_pbr::pbr_functions pbr +// ... +pbr() +``` + +- allows most imported items to end with `_` and numbers (naga_oil#30). still doesn’t allow struct members to end with `_` or numbers but it’s progress. +- the vast majority of existing shader code will work without changes, but will emit “deprecated” warnings for old-style imports. these can be suppressed with the `allow-deprecated` feature. +- partly breaks overrides (as far as i’m aware nobody uses these yet) - now overrides will only be applied if the overriding module is added as an additional import in the arguments to `Composer::make_naga_module` or `Composer::add_composable_module`. this is necessary to support determining whether imports are modules or items. + +### [Bind group entries](https://github.com/bevyengine/bevy/pull/9694) + +
+
Rendering
+
+ +- Calls to `RenderDevice::create_bind_group({BindGroupDescriptor { label, layout, entries })` must be amended to `RenderDevice::create_bind_group(label, layout, entries)`. +- If `label`s have been specified as `"bind_group_name".into()`, they need to change to just `"bind_group_name"`. `Some("bind_group_name")` and `None` will still work, but `Some("bind_group_name")` can optionally be simplified to just `"bind_group_name"`. + +### [Detect cubemap for dds textures](https://github.com/bevyengine/bevy/pull/10222) + +
+
Rendering
+
+ +If you are matching on a `TextureError`, you will need to add a new branch to handle `TextureError::IncompleteCubemap`. + +### [Add convenient methods for Image](https://github.com/bevyengine/bevy/pull/10221) + +
+
Rendering
+
+ +Replace calls to the `Image::size()` method with `size_f32()`. +Replace calls to the `Image::aspect_2d()` method with `aspect_ratio()`. + +### [Use “specular occlusion” term to consistently extinguish fresnel on Ambient and Environment Map lights](https://github.com/bevyengine/bevy/pull/10182) + +
+
Rendering
+
+ +- If Fresnel highlights from Ambient and Environment Map lights are no longer visible in your materials, make sure you’re using a higher, physically plausible value of `reflectance` (⪆ 0.35). + +### [Fix fog color being inaccurate](https://github.com/bevyengine/bevy/pull/10226) + +
+
Rendering
+
+ +Colors in `FogSettings` struct (`color` and `directional_light_color`) are now sent to the GPU in linear space. If you were using `Color::rgb()`/`Color::rgba()` and would like to retain the previous colors, you can quickly fix it by switching to `Color::rgb_linear()`/`Color::rgba_linear()`. + +### [Image Sampler Improvements](https://github.com/bevyengine/bevy/pull/10254) + +
+
Rendering
+
+ +- When using the `Image` API, use `ImageSamplerDescriptor` instead of `wgpu::SamplerDescriptor` +- If writing custom wgpu renderer features that work with `Image`, call `&image_sampler.as_wgpu()` to convert to a wgpu descriptor. + +### [`StandardMaterial` Light Transmission](https://github.com/bevyengine/bevy/pull/8015) + +
+
Rendering
+
+ +- `SsaoPipelineKey::temporal_noise` has been renamed to `SsaoPipelineKey::temporal_jitter` +- The `TAA` shader def (controlled by the presence of the `TemporalAntiAliasSettings` component in the camera) has been replaced with the `TEMPORAL_JITTER` shader def (controlled by the presence of the `TemporalJitter` component in the camera) +- `MeshPipelineKey::TAA` has been replaced by `MeshPipelineKey::TEMPORAL_JITTER` +- The `TEMPORAL_NOISE` shader def has been consolidated with `TEMPORAL_JITTER` + +### [Increase default normal bias to avoid common artifacts](https://github.com/bevyengine/bevy/pull/10346) + +
+
Rendering
+
+ +The default `shadow_normal_bias` value for `DirectionalLight` and `SpotLight` has changed to accommodate artifacts introduced with the new shadow PCF changes. It is unlikely (especially given the new PCF shadow behaviors with these values), but you might need to manually tweak this value if your scene requires a lower bias and it relied on the previous default value. + +### [Make `DirectionalLight` `Cascades` computation generic over `CameraProjection`](https://github.com/bevyengine/bevy/pull/9226) + +
+
Rendering
+
+ +If you have a component `MyCustomProjection` that implements `CameraProjection`: + +- You need to implement a new required associated method, `get_frustum_corners`, returning an array of the corners of a subset of the frustum with given `z_near` and `z_far`, in local camera space. +- You can now add the `build_directional_light_cascades::` system in `SimulationLightSystems::UpdateDirectionalLightCascades` after `clear_directional_light_cascades` for your projection to work with directional lights. + +### [Move skin code to a separate module](https://github.com/bevyengine/bevy/pull/9899) + +
+
Rendering
+
Animation
+
+ +Renamed skinning systems, resources and components: + +- extract_skinned_meshes -> extract_skins +- prepare_skinned_meshes -> prepare_skins +- SkinnedMeshUniform -> SkinUniform +- SkinnedMeshJoints -> SkinIndex + +### [Move scene spawner systems to SpawnScene schedule](https://github.com/bevyengine/bevy/pull/9260) + +
+
Scenes
+
+ +`scene_spawner_system` was moved to a new `SpawnScene` schedule which is run between `Update` and `PostUpdate`. + +If you were ordering your own systems to run before `scene_spawner_system` in `Update`, that might no longer be necessary. If your system needs to run after `scene_spawner_system`, it should be moved to the `SpawnScene` or `PostUpdate` schedule. + +### [Remove Resource and add Debug to TaskPoolOptions](https://github.com/bevyengine/bevy/pull/9485) + +
+
Tasks
+
+ +If for some reason anyone is still using `TaskPoolOptions` as a Resource, they would now have to use a wrapper type: + +```rust +#[derive(Resource)] +pub struct MyTaskPoolOptions(pub TaskPoolOptions); +``` + +### [Global TaskPool API improvements](https://github.com/bevyengine/bevy/pull/10008) + +
+
Tasks
+
+ +Uses of `ComputeTaskPool::init`, `AsyncComputeTaskPool::init` and `IoTaskPool::init` should be changed to `::get_or_init`. + +### [Unify `FixedTime` and `Time` while fixing several problems](https://github.com/bevyengine/bevy/pull/8964) + +
+
Time
+
+ +- Change all `Res
diff --git a/content/learn/book/migration-guides/0.4-0.5/_index.md b/content/learn/migration-guides/0.4-0.5/_index.md similarity index 98% rename from content/learn/book/migration-guides/0.4-0.5/_index.md rename to content/learn/migration-guides/0.4-0.5/_index.md index 02c54ea4e7..e906ff529b 100644 --- a/content/learn/book/migration-guides/0.4-0.5/_index.md +++ b/content/learn/migration-guides/0.4-0.5/_index.md @@ -1,10 +1,9 @@ +++ title = "0.4 to 0.5" -weight = 1 -sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +weight = 0 +template = "docs-section.html" insert_anchor_links = "right" +aliases = ["learn/book/migration-guides/0.4-0.5"] [extra] long_title = "Migration Guide: 0.4 to 0.5" +++ @@ -67,11 +66,11 @@ Similarly, rather than using `with(some_component)` to spawn an object with mult // 0.4 commands.spawn(some_bundle) .with(some_component); - + // 0.5 commands.spawn_bundle(some_bundle) .insert(some_component); - + // or... commands.spawn() .insert_bundle(some_bundle) diff --git a/content/learn/book/migration-guides/0.5-0.6/_index.md b/content/learn/migration-guides/0.5-0.6/_index.md similarity index 97% rename from content/learn/book/migration-guides/0.5-0.6/_index.md rename to content/learn/migration-guides/0.5-0.6/_index.md index 2a98437a8c..8408d4c8aa 100644 --- a/content/learn/book/migration-guides/0.5-0.6/_index.md +++ b/content/learn/migration-guides/0.5-0.6/_index.md @@ -1,10 +1,9 @@ +++ title = "0.5 to 0.6" -weight = 2 -sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +weight = 1 +template = "docs-section.html" insert_anchor_links = "right" +aliases = ["learn/book/migration-guides/0.5-0.6"] [extra] long_title = "Migration Guide: 0.5 to 0.6" +++ @@ -244,7 +243,9 @@ struct SystemParamDerive<'w, 's> { ### QuerySet declare "QueryState" instead of "Query" -Due to the [System Param Lifetime Split](#system-param-lifetime-split), [`QuerySet`] system parameters now need to specify their Queries with [`QuerySet`] instead of [`Query`]. + + +Due to the [System Param Lifetime Split](#system-param-lifetime-split), [`QuerySet`] system parameters now need to specify their Queries with [`QueryState`] instead of [`Query`]. ```rust // 0.5 @@ -259,6 +260,7 @@ fn query_set(mut queries: QuerySet<(QueryState<&mut Transform>, QueryState<&Tran ``` [`QuerySet`]: https://docs.rs/bevy/0.6.0/bevy/ecs/system/struct.QuerySet.html +[`QueryState`]: https://docs.rs/bevy_ecs/0.6.0/bevy_ecs/query/struct.QueryState.html [`Query`]: https://docs.rs/bevy/0.6.0/bevy/ecs/system/struct.Query.html ### "Input\.update()" is renamed to "Input\.clear()" diff --git a/content/learn/book/migration-guides/0.6-0.7/_index.md b/content/learn/migration-guides/0.6-0.7/_index.md similarity index 98% rename from content/learn/book/migration-guides/0.6-0.7/_index.md rename to content/learn/migration-guides/0.6-0.7/_index.md index 64608089f3..df28cbfffd 100644 --- a/content/learn/book/migration-guides/0.6-0.7/_index.md +++ b/content/learn/migration-guides/0.6-0.7/_index.md @@ -1,10 +1,9 @@ +++ title = "0.6 to 0.7" -weight = 3 -sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +weight = 2 +template = "docs-section.html" insert_anchor_links = "right" +aliases = ["learn/book/migration-guides/0.6-0.7"] [extra] long_title = "Migration Guide: 0.6 to 0.7" +++ @@ -207,7 +206,7 @@ fn camera_system(cameras: Query<&Camera, With>) { } ``` -### [Remove the config api](https://github.com/bevyengine/bevy/pull/3633) +### [Remove the config API](https://github.com/bevyengine/bevy/pull/3633) ```rs // 0.6 diff --git a/content/learn/book/migration-guides/0.7-0.8/_index.md b/content/learn/migration-guides/0.7-0.8/_index.md similarity index 99% rename from content/learn/book/migration-guides/0.7-0.8/_index.md rename to content/learn/migration-guides/0.7-0.8/_index.md index d7a63c94fe..2d60ebdc45 100644 --- a/content/learn/book/migration-guides/0.7-0.8/_index.md +++ b/content/learn/migration-guides/0.7-0.8/_index.md @@ -1,10 +1,9 @@ +++ title = "0.7 to 0.8" -weight = 4 -sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +weight = 3 +template = "docs-section.html" insert_anchor_links = "right" +aliases = ["learn/book/migration-guides/0.7-0.8"] [extra] long_title = "Migration Guide: 0.7 to 0.8" +++ diff --git a/content/learn/book/migration-guides/0.8-0.9/_index.md b/content/learn/migration-guides/0.8-0.9/_index.md similarity index 97% rename from content/learn/book/migration-guides/0.8-0.9/_index.md rename to content/learn/migration-guides/0.8-0.9/_index.md index 5fbdba8980..21d11d1f46 100644 --- a/content/learn/book/migration-guides/0.8-0.9/_index.md +++ b/content/learn/migration-guides/0.8-0.9/_index.md @@ -1,10 +1,9 @@ +++ title = "0.8 to 0.9" -weight = 5 -sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +weight = 4 +template = "docs-section.html" insert_anchor_links = "right" +aliases = ["learn/book/migration-guides/0.8-0.9"] [extra] long_title = "Migration Guide: 0.8 to 0.9" +++ diff --git a/content/learn/migration-guides/0.9-0.10/_index.md b/content/learn/migration-guides/0.9-0.10/_index.md new file mode 100644 index 0000000000..a8e8e4cdcb --- /dev/null +++ b/content/learn/migration-guides/0.9-0.10/_index.md @@ -0,0 +1,1234 @@ ++++ +title = "0.9 to 0.10" +weight = 5 +template = "docs-section.html" +insert_anchor_links = "right" +aliases = ["learn/book/migration-guides/0.9-0.10"] +[extra] +long_title = "Migration Guide: 0.9 to 0.10" ++++ + +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. +
+ +### [Migrate engine to Schedule v3 (stageless)](https://github.com/bevyengine/bevy/pull/7267) + +
+
Rendering
+
ECS
+
+ +- Calls to `.label(MyLabel)` should be replaced with `.in_set(MySet)` +- `SystemLabel` derives should be replaced with `SystemSet`. You will also need to add the `Debug`, `PartialEq`, `Eq`, and `Hash` traits to satisfy the new trait bounds. +- Stages have been removed. Replace these with system sets, and then add command flushes using the `apply_system_buffers` exclusive system where needed. +- The `CoreStage`, `StartupStage`, `RenderStage`, and `AssetStage` enums have been replaced with `CoreSet`, `StartupSet`, `RenderSet` and `AssetSet`. The same scheduling guarantees have been preserved. +- `with_run_criteria` has been renamed to `run_if`. Run criteria have been renamed to run conditions for clarity, and should now simply return a `bool` instead of `schedule::ShouldRun`. +- Looping run criteria and state stacks have been removed. Use an exclusive system that runs a schedule if you need this level of control over system control flow. +- `App::add_state` now takes 0 arguments: the starting state is set based on the `Default` impl. +- Instead of creating `SystemSet` containers for systems that run in stages, use `my_system.in_schedule(OnEnter(State::Variant))` or its `OnExit` sibling. +- For app-level control flow over which schedules get run when (such as for rollback networking), create your own schedule and insert it under the `CoreSchedule::Outer` label. +- Fixed timesteps are now evaluated in a schedule, rather than controlled via run criteria. The `run_fixed_timestep` system runs this schedule between `CoreSet::First` and `CoreSet::PreUpdate` by default. +- Command flush points introduced by `AssetStage` have been removed. If you were relying on these, add them back manually. +- The `calculate_bounds` system, with the `CalculateBounds` label, is now in `CoreSet::Update`, rather than in `CoreSet::PostUpdate` before commands are applied. You may need to order your movement systems to occur before this system in order to avoid system order ambiguities in culling behavior. +- The `RenderLabel` `AppLabel` was renamed to `RenderApp` for clarity +- When testing systems or otherwise running them in a headless fashion, simply construct and run a schedule using `Schedule::new()` and `World::run_schedule` rather than constructing stages + +- States have been dramatically simplified: there is no longer a “state stack”. To queue a transition to the next state, call `NextState::set` +- Strings can no longer be used as a `SystemLabel` or `SystemSet`. Use a type, or use the system function instead. + +#### Stages + +Stages had two key elements: they ran one after another, and they applied commands at their end. + +The former can be replaced by system sets (unless you need branching or looping scheduling logic, in which case you should use a schedule), and the latter can be controlled manually via `apply_system_buffers`. + +To migrate from Bevy's built-in stages, we've provided the [`CoreSet`](https://docs.rs/bevy/0.10/bevy/app/enum.CoreSet.html), [`StartupSet`](https://docs.rs/bevy/0.10/bevy/app/enum.StartupSet.html) and [`RenderSet`](https://docs.rs/bevy/latest/0.10/render/enum.RenderSet.html) system sets. +Command flushes have already been added to these, but if you have added custom stages you may need to add your own if you were relying on that behavior. + +Before: + +```rust +app + .add_system_to_stage(CoreStage::PostUpdate, my_system) + .add_startup_system_to_stage(StartupStage::PostStartup, my_startup_system); +``` + +After: + +```rust +app + .add_system(my_system.in_base_set(CoreSet::PostUpdate)) + .add_startup_system(my_startup_system.in_base_set(StartupSet::PostStartup)); +``` + +If you had your own stage: + +```rust +// Bevy 0.9 +#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)] +pub struct AfterUpdate; + +app.add_stage_after(CoreStage::Update, AfterUpdate, SystemStage::parallel()); + +// Bevy 0.10, no command flush +#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] +#[system_set(base)] +pub struct AfterUpdate; + +app.configure_set( + AfterUpdate + .after(CoreSet::UpdateFlush) + .before(CoreSet::PostUpdate), +); + +// Bevy 0.10, with a command flush +#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] +#[system_set(base)] +pub enum AfterUpdate { + Parallel, + CommandFlush +} + +app.configure_sets( + ( + CoreSet::UpdateFlush, + AfterUpdate::Parallel, + AfterUpdate::CommandFlush, + CoreSet::PostUpdate, + ).chain() +).add_system(apply_system_buffers.in_base_set(AfterUpdate::CommandFlush)); + +``` + +#### Label types + +System labels have been renamed to systems sets and unified with stage labels. +The `StageLabel` trait should be replaced by a system set, using the `SystemSet` trait as dicussed immediately below. + +Before: + +```rust +#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)] +enum MyStage { + BeforeRound, + AfterRound, +} + +#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemLabel)] +enum MySystem { + ComputeForces, + FindCollisions, +} +``` + +After: + +```rust +#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] +enum MySet { + BeforeRound, + AfterRound, +} + +#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] +enum MySystem { + ComputeForces, + FindCollisions, +} +``` + +#### System sets (Bevy 0.9) + +In Bevy 0.9, you could use the `SystemSet` type and various methods to configure many systems at once. +Additionally, this was the _only_ way to interact with various scheduling APIs like run criteria. + +Before: + +```rust +app.add_system_set(SystemSet::new().with_system(a).with_system(b).with_run_criteria(my_run_criteria)); +``` + +After: + +```rust +app.add_systems((a, b).run_if(my_run_condition)); +``` + +#### Ambiguity detection + +The `ReportExecutionOrderAmbiguities` resource has been removed. +Instead, this is configured on a per-schedule basis. + +```rust +app.edit_schedule(CoreSchedule::Main, |schedule| { + schedule.set_build_settings(ScheduleBuildSettings { + ambiguity_detection: LogLevel::Warn, + ..default() + }); +}) +``` + +#### Fixed timesteps + +The `FixedTimestep` run criteria has been removed, and is now handled by either a schedule or the `on_timer` / `on_fixed_timer` run conditions. + +Before: + +```rust +app.add_stage_after( + CoreStage::Update, + FixedUpdateStage, + SystemStage::parallel() + .with_run_criteria( + FixedTimestep::step(0.5) + ) + .with_system(fixed_update), +); +``` + +After: + +```rust +// This will affect the update frequency of fixed time for your entire app +app.insert_resource(FixedTime::new_from_secs(0.5)) + + // This schedule is automatically added with DefaultPlugins + .add_system(fixed_update.in_schedule(CoreSchedule::FixedUpdate)); +``` + +Apps may now only have one unified fixed timestep. `CoreSchedule::FixedTimestep` is intended to be used for determinism and stability during networks, physics and game mechanics. +Unlike timers, it will run repeatedly if more than a single period of time has elapsed since it was last run. + +It is _not_ intended to serve as a looping timer to regularly perform work or poll. +If you were relying on multiple `FixedTimestep` run criteria with distinct periods, you should swap to using timers, via the `on_timer(MY_PERIOD)` or `on_fixed_timer(MY_PERIOD)` run conditions. + +Before: + +```rust +app.add_system_set( + SystemSet::new() + .with_run_criteria(FixedTimestep::step(0.5)) + .with_system(update_pathfinding), +) +.add_system_set( + SystemSet::new() + .with_run_criteria(FixedTimestep::step(0.1)) + .with_system(apply_damage_over_time), +); +``` + +After: + +```rust +app +.add_system(update_pathfinding.run_if(on_timer(Duration::from_secs_f32(0.5)))) +.add_system(apply_damage_over_time.run_if(on_timer(Duration::from_secs_f32(0.1)))); +``` + +#### States + +States have been significantly simplied and no longer have a state stack. Each state type (usually an enum), requires the [`States`](https://docs.rs/bevy/0.10/bevy/ecs/schedule/trait.States.html) trait, typically implemented via the derive macro. + +For example: + +```rust +#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)] +enum AppState { + #[default] + Menu, + InGame, +} +``` + +`App::add_state` no longer takes an argument: the starting state is now controlled via the `Default` impl for your state type. + +To access the current state of the the `States` type above, use `Res`, and access the tuple field via `.0`. +To queue up a state transition, use `ResMut>` and call [`.set(AppState::Menu)`](https://docs.rs/bevy/latest/bevy/ecs/schedule/struct.NextState.html#method.set). + +State transitions are now applied via the `apply_state_transitions` exclusive system, a copy of which is added [`CoreSet::StateTransitions`](https://docs.rs/bevy/latest/bevy/app/enum.CoreSet.html) when you call `App::add_state`. You can add more copies as needed, specific to the state being applied. + +`OnEnter` and `OnExit` systems now live in schedules, run on the `World` via the `apply_state_transitions` system. +By contrast, `OnUpdate` is now a system set which is nested within `CoreSet::Update`. + +Before: + +```rust +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +enum AppState { + Menu, + InGame, +} + +app.add_state(AppState::Menu) + .add_system_set(SystemSet::on_enter(AppState::Menu).with_system(setup_menu)) + .add_system_set(SystemSet::on_update(AppState::Menu).with_system(menu)) + .add_system_set(SystemSet::on_exit(AppState::Menu).with_system(cleanup_menu)) +``` + +After: + +```rust +#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)] +enum AppState { + #[default] + Menu, + InGame, +} + +app.add_state::() + .add_system(setup_menu.in_schedule(OnEnter(AppState::Menu))) + .add_system(menu.in_set(OnUpdate(AppState::Menu))) + .add_system(cleanup_menu.in_schedule(OnExit(AppState::Menu))); +``` + +When you need to run your state-specific systems outside of `CoreSet::Update`, you can use the built-in [`in_state`](https://docs.rs/bevy/latest/bevy/ecs/prelude/fn.in_state.html) run condition. + +### [Windows as Entities](https://github.com/bevyengine/bevy/pull/5589) + +
+
Windowing
+
+ +Replace `WindowDescriptor` with `Window`. + +Change `width` and `height` fields into a `WindowResolution`, either by doing + +```rust +WindowResolution::new(width, height) // Explicitly +// or using From<_> for tuples for convenience +(1920., 1080.).into() +``` + +Replace any `WindowCommand` code to just modify the `Window`’s fields directly and creating/closing windows is now by spawning/despawning an entity with a `Window` component like so: + +```rust +let window = commands.spawn(Window { ... }).id(); // open window +commands.entity(window).despawn(); // close window +``` + +To get a window, you now need to use a `Query` instead of a `Res` + +```rust +// 0.9 +fn count_pixels(windows: Res) { + let Some(primary) = windows.get_primary() else { + return; + }; + println!("{}", primary.width() * primary.height()); +} + +// 0.10 +fn count_pixels(primary_query: Query<&Window, With>) { + let Ok(primary) = primary_query.get_single() else { + return; + }; + println!("{}", primary.width() * primary.height()); +} +``` + +### [Make the `SystemParam` derive macro more flexible](https://github.com/bevyengine/bevy/pull/6694) + +
+
ECS
+
+ +The lifetime `'s` has been removed from `EventWriter`. Any code that explicitly specified the lifetimes for this type will need to be updated. + +```rust +// 0.9 +#[derive(SystemParam)] +struct MessageWriter<'w, 's> { + events: EventWriter<'w, 's, Message>, +} + +// 0.10 +#[derive(SystemParam)] +struct MessageWriter<'w> { + events: EventWriter<'w, Message>, +} +``` + +### [Basic adaptive batching for parallel query iteration](https://github.com/bevyengine/bevy/pull/4777) + +
+
ECS
+
+ +The `batch_size` parameter for `Query(State)::par_for_each(_mut)` has been removed. These calls will automatically compute a batch size for you. Remove these parameters from all calls to these functions. + +```rust +// 0.9 +fn parallel_system(query: Query<&MyComponent>) { + query.par_for_each(32, |comp| { + ... + }); +} + +// 0.10 +fn parallel_system(query: Query<&MyComponent>) { + query.par_iter().for_each(|comp| { + ... + }); +} +``` + +### [Enum `Visibility` component](https://github.com/bevyengine/bevy/pull/6320) + +
+
Rendering
+
+ +- Evaluation of the `visibility.is_visible` field should now check for `visibility == Visibility::Inherited`. +- Setting the `visibility.is_visible` field should now directly set the value: `*visibility = Visibility::Inherited`. +- Usage of `Visibility::VISIBLE` or `Visibility::INVISIBLE` should now use `Visibility::Inherited` or `Visibility::Hidden` respectively. +- `ComputedVisibility::INVISIBLE` and `SpatialBundle::VISIBLE_IDENTITY` have been renamed to `ComputedVisibility::HIDDEN` and `SpatialBundle::INHERITED_IDENTITY` respectively. + +### [bevy_reflect: Pre-parsed paths](https://github.com/bevyengine/bevy/pull/7321) + +
+
Animation
+
Reflection
+
+ +`GetPath` methods have been renamed according to the following: + +- `path` -> `reflect_path` +- `path_mut` -> `reflect_path_mut` +- `get_path` -> `path` +- `get_path_mut` -> `path_mut` + +### [Remove App::add_sub_app](https://github.com/bevyengine/bevy/pull/7290) + +
+
App
+
+ +`App::add_sub_app` has been removed in favor of `App::insert_sub_app`. Use `SubApp::new` and insert it via `App::insert_sub_app` + +```rust +// 0.9 +let mut sub_app = App::new() +// Build subapp here +app.add_sub_app(MySubAppLabel, sub_app, extract_fn); + +// 0.10 +let mut sub_app = App::new() +// Build subapp here +app.insert_sub_app(MySubAppLabel, SubApp::new(sub_app, extract_fn)); +``` + +### [Make HandleUntyped::id private](https://github.com/bevyengine/bevy/pull/7076) + +
+
Assets
+
+ +Instead of directly accessing the ID of a `HandleUntyped` as `handle.id`, use the new getter `handle.id()`. + +### [Break `CorePlugin` into `TaskPoolPlugin`, `TypeRegistrationPlugin`, `FrameCountPlugin`.](https://github.com/bevyengine/bevy/pull/7083) + +
+
Core
+
+ +`CorePlugin` was broken into separate plugins. If not using `DefaultPlugins` or `MinimalPlugins` `PluginGroup`s, the replacement for `CorePlugin` is now to add `TaskPoolPlugin`, `TypeRegistrationPlugin`, and `FrameCountPlugin` to the app. + +### [Immutable sparse sets for metadata storage](https://github.com/bevyengine/bevy/pull/4928) + +
+
ECS
+
+ +`Table::component_capacity()` has been removed as Tables do not support adding/removing columns after construction. + +### [Split Component Ticks](https://github.com/bevyengine/bevy/pull/6547) + +
+
ECS
+
+ +Various low level APIs interacting with the change detection ticks no longer return `&UnsafeCell`, instead returning `TickCells` which contains two separate `&UnsafeCell`s instead. + +```rust +// 0.9 +column.get_ticks(row).deref().changed + +// 0.10 +column.get_ticks(row).changed.deref() +``` + +### [Document and lock down types in bevy_ecs::archetype](https://github.com/bevyengine/bevy/pull/6742) + +
+
ECS
+
+ +`ArchetypeId`, `ArchetypeGeneration`, and `ArchetypeComponentId` are all now opaque IDs and cannot be turned into a numeric value. Please file an issue if this does not work for your use case or check [bevy_ecs is excessively public](https://github.com/bevyengine/bevy/issues/3362) for more info. + +`Archetype` and `Archetypes` are not constructible outside of `bevy_ecs` now. Use `World::archetypes` to get a read-only reference to either of these types. + +### [Lock down access to Entities](https://github.com/bevyengine/bevy/pull/6740) + +
+
ECS
+
+ +`Entities`’s `Default` implementation has been removed. You can fetch a reference to a `World`’s `Entities` via `World::entities` and `World::entities_mut`. + +`Entities::alloc_at_without_replacement` and `AllocAtWithoutReplacement` has been made private due to difficulty in using it properly outside of `bevy_ecs`. If you still need use of this API, please file an issue or check [bevy_ecs is excessively public](https://github.com/bevyengine/bevy/issues/3362) for more info. + +### [Borrow instead of consuming in `EventReader::clear`](https://github.com/bevyengine/bevy/pull/6851) + +
+
ECS
+
+ +`EventReader::clear` now takes a mutable reference instead of consuming the event reader. This means that `clear` now needs explicit mutable access to the reader variable, which previously could have been omitted in some cases: + +```rust +// Old (0.9) +fn clear_events(reader: EventReader) { + reader.clear(); +} + +// New (0.10) +fn clear_events(mut reader: EventReader) { + reader.clear(); +} +``` + +### [Newtype ArchetypeRow and TableRow](https://github.com/bevyengine/bevy/pull/4878) + +
+
ECS
+
+ +`Archetype` indices and `Table` rows have been newtyped as `ArchetypeRow` and `TableRow`. + +### [Round out the untyped APIs](https://github.com/bevyengine/bevy/pull/7009) + +
+
ECS
+
+ +`MutUntyped::into_inner` now marks things as changed. + +### [Extend EntityLocation with TableId and TableRow](https://github.com/bevyengine/bevy/pull/6681) + +
+
ECS
+
+ +A `World` can only hold a maximum of 232 - 1 archetypes and tables now. If your use case requires more than this, please file an issue explaining your use case. + +### [Remove `ExclusiveSystemParam::apply`](https://github.com/bevyengine/bevy/pull/7489) + +
+
ECS
+
+ +The trait method `ExclusiveSystemParamState::apply` has been removed. If you have an exclusive system with buffers that must be applied, you should apply them within the body of the exclusive system. + +### [Remove the `SystemParamState` trait and remove types like `ResState`](https://github.com/bevyengine/bevy/pull/6919) + +
+
ECS
+
+ +The traits `SystemParamState` and `SystemParamFetch` have been removed, and their functionality has been transferred to `SystemParam`. + +The trait `ReadOnlySystemParamFetch` has been replaced with `ReadOnlySystemParam`. + +```rust +// 0.9 +impl SystemParam for MyParam<'_, '_> { + type State = MyParamState; +} +unsafe impl SystemParamState for MyParamState { + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... } +} +unsafe impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState { + type Item = MyParam<'w, 's>; + fn get_param(&mut self, ...) -> Self::Item; +} +unsafe impl ReadOnlySystemParamFetch for MyParamState { } + +// 0.10 +unsafe impl SystemParam for MyParam<'_, '_> { + type State = MyParamState; + type Item<'w, 's> = MyParam<'w, 's>; + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { ... } + fn get_param<'w, 's>(state: &mut Self::State, ...) -> Self::Item<'w, 's>; +} +unsafe impl ReadOnlySystemParam for MyParam<'_, '_> { } +``` + +### [Panic on dropping NonSend in non-origin thread.](https://github.com/bevyengine/bevy/pull/6534) + +
+
ECS
+
+ +Normal resources and `NonSend` resources no longer share the same backing storage. If `R: Resource`, then `NonSend` and `Res` will return different instances from each other. If you are using both `Res` and `NonSend` (or their mutable variants), to fetch the same resources, it’s strongly advised to use `Res`. + +### [Document alignment requirements of `Ptr`, `PtrMut` and `OwningPtr`](https://github.com/bevyengine/bevy/pull/7151) + +
+
ECS
+
+ +Safety invariants on `bevy_ptr` types’ `new` `byte_add` and `byte_offset` methods have been changed. All callers should re-audit for soundness. + +### [Added `resource_id` and changed `init_resource` and `init_non_send_resource` to return `ComponentId`](https://github.com/bevyengine/bevy/pull/7284) + +
+
ECS
+
+ +- Added `Components::resource_id`. +- Changed `World::init_resource` to return the generated `ComponentId`. +- Changed `World::init_non_send_resource` to return the generated `ComponentId`. + +### [Replace `RemovedComponents` backing with `Events`](https://github.com/bevyengine/bevy/pull/5680) + +
+
ECS
+
+ +- Add a `mut` for `removed: RemovedComponents` since we are now modifying an event reader internally. +- Iterating over removed components now requires `&mut removed_components` or `removed_components.iter()` instead of `&removed_components`. + +### [Remove broken `DoubleEndedIterator` impls on event iterators](https://github.com/bevyengine/bevy/pull/7469) + +
+
ECS
+
+ +`ManualEventIterator` and `ManualEventIteratorWithId` are no longer `DoubleEndedIterator`s since the impls didn't work correctly, and any code using this was likely broken. + +### [Rename `Tick::is_older_than` to `Tick::is_newer_than`](https://github.com/bevyengine/bevy/pull/7561) + +
+
ECS
+
+ +Replace usages of `Tick::is_older_than` with `Tick::is_newer_than`. + +### [Cleanup system sets called labels](https://github.com/bevyengine/bevy/pull/7678) + +
+
ECS
+
+ +`PrepareAssetLabel` is now called `PrepareAssetSet` + +### [Simplify generics for the `SystemParamFunction` trait](https://github.com/bevyengine/bevy/pull/7675) + +
+
ECS
+
+ +For the `SystemParamFunction` trait, the type parameters `In`, `Out`, and `Param` have been turned into associated types. + +```rust +// 0.9 +fn my_generic_system(system_function: T) +where + T: SystemParamFunction, + Param: SystemParam, +{ ... } + +// 0.10 +fn my_generic_system(system_function: T) +where + T: SystemParamFunction, +{ ... } +``` + +For the `ExclusiveSystemParamFunction` trait, the type parameter `Param` has been turned into an associated type. +Also, `In` and `Out` associated types have been added, since exclusive systems now support system piping. + +```rust +// 0.9 +fn my_exclusive_system(system_function: T) +where + T: ExclusiveSystemParamFunction, + T: Param: ExclusiveSystemParam, +{ ... } + +// 0.10 +fn my_exclusive_system(system_function: T) +where + T: ExclusiveSystemParamFunction, +{ ... } +``` + +### [Deprecate `ChangeTrackers` in favor of `Ref`](https://github.com/bevyengine/bevy/pull/7306) + +
+
ECS
+
+ +`ChangeTrackers` has been deprecated, and will be removed in the next release. Any usage should be replaced with `Ref`. + +```rust +// 0.9 +fn my_system(q: Query<(&MyComponent, ChangeTrackers)>) { + for (value, trackers) in &q { + if trackers.is_changed() { + // Do something with `value`. + } + } +} + +// 0.10 +fn my_system(q: Query>) { + for value in &q { + if value.is_changed() { + // Do something with `value`. + } + } +} +``` + +### [`EntityMut`: rename `remove_intersection` to `remove` and `remove` to `take`](https://github.com/bevyengine/bevy/pull/7810) + +
+
ECS
+
+ +```rust +// 0.9 +fn clear_children(parent: Entity, world: &mut World) { + if let Some(children) = world.entity_mut(parent).remove::() { + for &child in &children.0 { + world.entity_mut(child).remove_intersection::(); + } + } +} + +// 0.10 +fn clear_children(parent: Entity, world: &mut World) { + if let Some(children) = world.entity_mut(parent).take::() { + for &child in &children.0 { + world.entity_mut(child).remove::(); + } + } +} +``` + +### [bevy_ecs: ReflectComponentFns without World](https://github.com/bevyengine/bevy/pull/7206) + +
+
ECS
+
Reflection
+
+ +Call `World::entity` before calling into the changed `ReflectComponent` methods, most likely user already has a `EntityRef` or `EntityMut` which was being queried redundantly. + +### [Allow iterating over with EntityRef over the entire World](https://github.com/bevyengine/bevy/pull/6843) + +
+
ECS
+
Scenes
+
+ +`World::iter_entities` now returns an iterator of `EntityRef` instead of `Entity`. To get the actual ID, use `EntityRef::id` from the returned `EntityRef`s. + +### [Remove `BuildWorldChildren` impl from `WorldChildBuilder`](https://github.com/bevyengine/bevy/pull/6727) + +
+
Hierarchy
+
+ +Hierarchy editing methods such as `with_children` and `push_children` have been removed from `WorldChildBuilder`. +You can edit the hierarchy via `EntityMut` instead. + +### [Rename dynamic feature](https://github.com/bevyengine/bevy/pull/7340) + +
+
Meta
+
+ +`dynamic` feature was renamed to `dynamic_linking` + +### [bevy_reflect: add `insert` and `remove` methods to `List`](https://github.com/bevyengine/bevy/pull/7063) + +
+
Reflection
+
+ +Manual implementors of `List` need to implement the new methods `insert` and `remove` and +consider whether to use the new default implementation of `push` and `pop`. + +### [bevy_reflect: Decouple `List` and `Array` traits](https://github.com/bevyengine/bevy/pull/7467) + +
+
Reflection
+
+ +The `List` trait is no longer dependent on `Array`. Implementors of `List` can remove the `Array` impl and move its methods into the `List` impl (with only a couple tweaks). + +```rust +// 0.9 +impl Array for Foo { + fn get(&self, index: usize) -> Option<&dyn Reflect> {/* ... */} + fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {/* ... */} + fn len(&self) -> usize {/* ... */} + fn is_empty(&self) -> bool {/* ... */} + fn iter(&self) -> ArrayIter {/* ... */} + fn drain(self: Box) -> Vec> {/* ... */} + fn clone_dynamic(&self) -> DynamicArray {/* ... */} +} + +impl List for Foo { + fn insert(&mut self, index: usize, element: Box) {/* ... */} + fn remove(&mut self, index: usize) -> Box {/* ... */} + fn push(&mut self, value: Box) {/* ... */} + fn pop(&mut self) -> Option> {/* ... */} + fn clone_dynamic(&self) -> DynamicList {/* ... */} +} + +// 0.10 +impl List for Foo { + fn get(&self, index: usize) -> Option<&dyn Reflect> {/* ... */} + fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {/* ... */} + fn insert(&mut self, index: usize, element: Box) {/* ... */} + fn remove(&mut self, index: usize) -> Box {/* ... */} + fn push(&mut self, value: Box) {/* ... */} + fn pop(&mut self) -> Option> {/* ... */} + fn len(&self) -> usize {/* ... */} + fn is_empty(&self) -> bool {/* ... */} + fn iter(&self) -> ListIter {/* ... */} + fn drain(self: Box) -> Vec> {/* ... */} + fn clone_dynamic(&self) -> DynamicList {/* ... */} +} +``` + +Some other small tweaks that will need to be made include: + +- Use `ListIter` for `List::iter` instead of `ArrayIter` (the return type from `Array::iter`) +- Replace `array_hash` with `list_hash` in `Reflect::reflect_hash` for implementors of `List` + +### [bevy_reflect: Remove `ReflectSerialize` and `ReflectDeserialize` registrations from most glam types](https://github.com/bevyengine/bevy/pull/6580) + +
+
Reflection
+
Scenes
+
+ +This PR removes `ReflectSerialize` and `ReflectDeserialize` registrations from most glam types. This means any code relying on either of those type data existing for those glam types will need to not do that. + +This also means that some serialized glam types will need to be updated. For example, here is `Affine3A`: + +```rust +// 0.9 +( + "glam::f32::affine3a::Affine3A": (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0), + +// 0.10 + "glam::f32::affine3a::Affine3A": ( + matrix3: ( + x_axis: ( + x: 1.0, + y: 0.0, + z: 0.0, + ), + y_axis: ( + x: 0.0, + y: 1.0, + z: 0.0, + ), + z_axis: ( + x: 0.0, + y: 0.0, + z: 1.0, + ), + ), + translation: ( + x: 0.0, + y: 0.0, + z: 0.0, + ), + ) +) +``` + +### [Add AutoMax next to ScalingMode::AutoMin](https://github.com/bevyengine/bevy/pull/6496) + +
+
Rendering
+
+ +Rename `ScalingMode::Auto` to `ScalingMode::AutoMin`. + +### [Change `From` to `TryFrom`](https://github.com/bevyengine/bevy/pull/6484) + +
+
Rendering
+
+ +```rust +// 0.9 +shape::Icosphere { + radius: 0.5, + subdivisions: 5, +} +.into() + +// 0.10 +shape::Icosphere { + radius: 0.5, + subdivisions: 5, +} +.try_into() +.unwrap() +``` + +### [Add try_* to add_slot_edge, add_node_edge](https://github.com/bevyengine/bevy/pull/6720) + +
+
Rendering
+
+ +Remove `.unwrap()` from `add_node_edge` and `add_slot_edge`. +For cases where the error was handled, use `try_add_node_edge` and `try_add_slot_edge` instead. + +Remove `.unwrap()` from `input_node`. +For cases where the option was handled, use `get_input_node` instead. + +### [Shader defs can now have a value](https://github.com/bevyengine/bevy/pull/5900) + +
+
Rendering
+
+ +- Replace `shader_defs.push(String::from("NAME"));` by `shader_defs.push("NAME".into());` +- If you used shader def `NO_STORAGE_BUFFERS_SUPPORT`, check how `AVAILABLE_STORAGE_BUFFER_BINDINGS` is now used in [Bevy default shaders](https://github.com/bevyengine/bevy/blob/3ec87e49ca49767fad658e72fbae353f6687198c/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl#L28) + +### [Get pixel size from wgpu](https://github.com/bevyengine/bevy/pull/6820) + +
+
Rendering
+
+ +`PixelInfo` has been removed. `PixelInfo::components` is equivalent to `texture_format.describe().components`. `PixelInfo::type_size` can be gotten from `texture_format.describe().block_size/ texture_format.describe().components`. But note this can yield incorrect results for some texture types like Rg11b10Float. + +### [Run clear trackers on render world](https://github.com/bevyengine/bevy/pull/6878) + +
+
Rendering
+
+ +The call to `clear_trackers` in `App` has been moved from the schedule to `App::update` for the main world and calls to `clear_trackers` have been added for `sub_apps` in the same function. This was due to needing stronger guarantees. If `clear_trackers` isn’t called on a world it can lead to memory leaks in `RemovedComponents`. If you were ordering systems with `clear_trackers` this is no longer possible. + +### [Rename camera "priority" to "order"](https://github.com/bevyengine/bevy/pull/6908) + +
+
Rendering
+
+ +Rename `priority` to `order` in usage of `Camera`. + +### [Reduce branching in TrackedRenderPass](https://github.com/bevyengine/bevy/pull/7053) + +
+
Rendering
+
+ +`TrackedRenderPass` now requires a `RenderDevice` to construct. To make this easier, use `RenderContext.begin_tracked_render_pass` instead. + +```rust +// 0.9 +TrackedRenderPass::new(render_context.command_encoder.begin_render_pass( + &RenderPassDescriptor { + ... + }, +)); + +// 0.10 +render_context.begin_tracked_render_pass(RenderPassDescriptor { + ... +}); +``` + +### [Make PipelineCache internally mutable.](https://github.com/bevyengine/bevy/pull/7205) + +
+
Rendering
+
+ +Most usages of `resource_mut::` and `ResMut` can be changed to `resource::` and `Res` as long as they don’t use any methods requiring mutability - the only public method requiring it is `process_queue`. + +### [Changed Msaa to Enum](https://github.com/bevyengine/bevy/pull/7292) + +
+
Rendering
+
+ +```rust +// 0.9 +let multi = Msaa { samples: 4 } +// 0.10 +let multi = Msaa::Sample4 + +// 0.9 +multi.samples +// 0.10 +multi.samples() +``` + +### [Support recording multiple CommandBuffers in RenderContext](https://github.com/bevyengine/bevy/pull/7248) + +
+
Rendering
+
+ +`RenderContext`’s fields are now private. Use the accessors on `RenderContext` instead, and construct it with `RenderContext::new`. + +### [Improve `OrthographicCamera` consistency and usability](https://github.com/bevyengine/bevy/pull/6201) + +
+
Rendering
+
+ +- Change `window_origin` to `viewport_origin`; replace `WindowOrigin::Center` with `Vec2::new(0.5, 0.5)` and `WindowOrigin::BottomLeft` with `Vec2::new(0.0, 0.0)` +- For shadow projections and such, replace `left`, `right`, `bottom`, and `top` with `area: Rect::new(left, bottom, right, top)` +- For camera projections, remove l/r/b/t values from `OrthographicProjection` instantiations, as they no longer have any effect in any `ScalingMode` +- Change `ScalingMode::None` to `ScalingMode::Fixed` + - Replace manual changes of l/r/b/t with: + - Arguments in `ScalingMode::Fixed` to specify size + - `viewport_origin` to specify offset + +- Change `ScalingMode::WindowSize` to `ScalingMode::WindowSize(1.0)` + +### [Changed `&mut PipelineCache` to `&PipelineCache`](https://github.com/bevyengine/bevy/pull/7598) + +
+
Rendering
+
+ +`SpecializedComputePipelines::specialize` now takes a `&PipelineCache` instead of a `&mut PipelineCache` + +### [Introduce detailed_trace macro, use in TrackedRenderPass](https://github.com/bevyengine/bevy/pull/7639) + +
+
Rendering
+
+ +Some detailed bevy trace events now require the use of the cargo feature `detailed_trace` in addition to enabling `TRACE` level logging to view. Should you wish to see these logs, please compile your code with the bevy feature `detailed_trace`. Currently, the only logs that are affected are the renderer logs pertaining to `TrackedRenderPass` functions + +### [Added subdivisions to shape::Plane](https://github.com/bevyengine/bevy/pull/7546) + +
+
Rendering
+
+ +`shape::Plane` now takes an additional `subdivisions` parameter so users should provide it or use the new `shape::Plane::from_size()`. + +### [Change standard material defaults and update docs](https://github.com/bevyengine/bevy/pull/7664) + +
+
Rendering
+
+ +`StandardMaterial`’s default have now changed to be a fully dielectric material with medium roughness. If you want to use the old defaults, you can set `perceptual_roughness = 0.089` and `metallic = 0.01` (though metallic should generally only be set to 0.0 or 1.0). + +### [Remove dead code after #7784](https://github.com/bevyengine/bevy/pull/7875) + +
+
Rendering
+
+ +Removed `SetShadowViewBindGroup`, `queue_shadow_view_bind_group()`, and `LightMeta::shadow_view_bind_group` in favor of reusing the prepass view bind group. + +### [Directly extract joints into SkinnedMeshJoints](https://github.com/bevyengine/bevy/pull/6833) + +
+
Rendering
+
Animation
+
+ +`ExtractedJoints` has been removed. Read the bound bones from `SkinnedMeshJoints` instead. + +### [Intepret glTF colors as linear instead of sRGB](https://github.com/bevyengine/bevy/pull/6828) + +
+
Rendering
+
Assets
+
+ +No API changes are required, but it's possible that your gltf meshes look different + +### [Send emissive color to uniform as linear instead of sRGB](https://github.com/bevyengine/bevy/pull/7897) + +- If you have previously manually specified emissive values with `Color::rgb()` and would like to retain the old visual results, you must now use `Color::rgb_linear()` instead; +- If you have previously manually specified emissive values with `Color::rgb_linear()` and would like to retain the old visual results, you'll need to apply a one-time gamma calculation to your channels manually to get the _actual_ linear RGB value: + - For channel values greater than `0.0031308`, use `(1.055 * value.powf(1.0 / 2.4)) - 0.055`; + - For channel values lower than or equal to `0.0031308`, use `value * 12.92`; +- Otherwise, the results should now be more consistent with other tools/engines. + +### [The `update_frame_count` system should be placed in CorePlugin](https://github.com/bevyengine/bevy/pull/6676) + +
+
Rendering
+
Core
+
Time
+
+ +The `FrameCount` resource was previously only updated when using the `bevy_render` feature. If you are not using this feature but still want the `FrameCount` it will now be updated correctly. + +### [Pipelined Rendering](https://github.com/bevyengine/bevy/pull/6503) + +
+
Rendering
+
Tasks
+
+ +__App `runner` and SubApp `extract` functions are now required to be Send__ + +This was changed to enable pipelined rendering. If this breaks your use case please report it as these new bounds might be able to be relaxed. + +### [Remove ImageMode](https://github.com/bevyengine/bevy/pull/6674) + +
+
Rendering
+
UI
+
+ +`ImageMode` never worked, if you were using it please create an issue. + +### [Rename the `background_color` of 'ExtractedUiNode` to `color`](https://github.com/bevyengine/bevy/pull/7452) + +
+
Rendering
+
UI
+
+ +The `background_color` field of `ExtractedUiNode` is now named `color`. + +### [Remove the `GlobalTransform::translation_mut` method](https://github.com/bevyengine/bevy/pull/7134) + +
+
Transform
+
Hierarchy
+
+ +`GlobalTransform::translation_mut` has been removed without alternative, +if you were relying on this, update the `Transform` instead. If the given entity +had children or parent, you may need to remove its parent to make its transform +independent (in which case the new `Commands::set_parent_in_place` and +`Commands::remove_parent_in_place` may be of interest) + +Bevy may add in the future a way to toggle transform propagation on +an entity basis. + +### [Flip UI image](https://github.com/bevyengine/bevy/pull/6292) + +
+
UI
+
+ +- `UiImage` is a struct now, so use `UiImage::new(handler)` instead of `UiImage(handler)` +- `UiImage` no longer implements `Deref` and `DerefMut`, so use `&image.texture` or `&mut image.texture` instead + +### [Remove `TextError::ExceedMaxTextAtlases(usize)` variant](https://github.com/bevyengine/bevy/pull/6796) + +
+
UI
+
+ +`TextError::ExceedMaxTextAtlases(usize)` was never thrown so if you were matching on this variant you can simply remove it. + +### [Change default FocusPolicy to Pass](https://github.com/bevyengine/bevy/pull/7161) + +
+
UI
+
+ +`FocusPolicy` default has changed from `FocusPolicy::Block` to `FocusPolicy::Pass` + +### [Remove VerticalAlign from TextAlignment](https://github.com/bevyengine/bevy/pull/6807) + +
+
UI
+
+ +The `alignment` field of `Text` now only affects the text’s internal alignment. + +__Change `TextAlignment` to TextAlignment` which is now an enum. Replace:__ + +- `TextAlignment::TOP_LEFT`, `TextAlignment::CENTER_LEFT`, `TextAlignment::BOTTOM_LEFT` with `TextAlignment::Left` +- `TextAlignment::TOP_CENTER`, `TextAlignment::CENTER_LEFT`, `TextAlignment::BOTTOM_CENTER` with `TextAlignment::Center` +- `TextAlignment::TOP_RIGHT`, `TextAlignment::CENTER_RIGHT`, `TextAlignment::BOTTOM_RIGHT` with `TextAlignment::Right` + +__Changes for `Text2dBundle`__ + +`Text2dBundle` has a new field `text_anchor` that takes an `Anchor` component that controls its position relative to its transform. + +`Text2dSize` was removed. Use `TextLayoutInfo` instead. + +### [Remove `QueuedText`](https://github.com/bevyengine/bevy/pull/7414) + +
+
UI
+
+ +`QueuedText` was never meant to be user facing. If you relied on it, please make an issue. + +### [Change the default `width` and `height` of `Size` to `Val::Auto`](https://github.com/bevyengine/bevy/pull/7475) + +
+
UI
+
+ +The default values for `Size` `width` and `height` have been changed from `Val::Undefined` to `Val::Auto`. +It’s unlikely to cause any issues with existing code. + +### [Fix the `Size` helper functions using the wrong default value and improve the UI examples](https://github.com/bevyengine/bevy/pull/7626) + +
+
UI
+
+ +The `Size::width` constructor function now sets the `height` to `Val::Auto` instead of `Val::Undefined`. +The `Size::height` constructor function now sets the `width` to `Val::Auto` instead of `Val::Undefined`. + +### [The `size` field of `CalculatedSize` should not be a `Size`](https://github.com/bevyengine/bevy/pull/7641) + +
+
UI
+
+ +The size field of `CalculatedSize` has been changed to a `Vec2`. + +### [Update winit to 0.28](https://github.com/bevyengine/bevy/pull/7480) + +
+
Windowing
+
+ +```rust +// 0.9 +app.new() + .add_plugins(DefaultPlugins.set(WindowPlugin { + primary_window: Some(Window { + always_on_top: true, + ..default() + }), + ..default() + })); + +// 0.10 +app.new() + .add_plugins(DefaultPlugins.set(WindowPlugin { + primary_window: Some(Window { + window_level: bevy::window::WindowLevel::AlwaysOnTop, + ..default() + }), + ..default() + })); +``` + +
diff --git a/content/learn/migration-guides/_index.md b/content/learn/migration-guides/_index.md new file mode 100644 index 0000000000..1238021729 --- /dev/null +++ b/content/learn/migration-guides/_index.md @@ -0,0 +1,8 @@ ++++ +title = "Migration Guides" +sort_by = "weight" +page_template = "docs-section.html" +redirect_to = "learn/migration-guides/introduction" +aliases = ["learn/book/migration-guides"] +insert_anchor_links = "right" ++++ \ No newline at end of file diff --git a/content/learn/migration-guides/introduction/_index.md b/content/learn/migration-guides/introduction/_index.md new file mode 100644 index 0000000000..36a9bf2061 --- /dev/null +++ b/content/learn/migration-guides/introduction/_index.md @@ -0,0 +1,9 @@ ++++ +title = "Introduction" +weight = 8 +template = "docs-section.html" +insert_anchor_links = "right" +aliases = ["learn/book/migration-guides/introduction"] ++++ + +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. diff --git a/content/learn/quick-start/_index.md b/content/learn/quick-start/_index.md new file mode 100644 index 0000000000..5c1210a0fb --- /dev/null +++ b/content/learn/quick-start/_index.md @@ -0,0 +1,5 @@ ++++ +title = "Quick Start" +template = "docs-section.html" +weight = 1 ++++ diff --git a/content/learn/quick-start/contributing/_index.md b/content/learn/quick-start/contributing/_index.md new file mode 100644 index 0000000000..2ed13c2326 --- /dev/null +++ b/content/learn/quick-start/contributing/_index.md @@ -0,0 +1,17 @@ ++++ +title = "Contributing" +weight = 4 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +subtitle = "join the bevy" ++++ + +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](/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/_index.md b/content/learn/quick-start/contributing/code/_index.md new file mode 100644 index 0000000000..8109b24e1c --- /dev/null +++ b/content/learn/quick-start/contributing/code/_index.md @@ -0,0 +1,32 @@ ++++ +title = "Code" +weight = 1 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +long_title = "Contributing Code" ++++ + +Would you like to contribute code to Bevy? Here's how! + +## How to Contribute + +1. Fork the [`bevyengine/bevy` repository on GitHub][bevy], you'll need to create a GitHub account if you don't have one already.* +2. Make your changes in a local clone of your fork +3. For a higher chance of CI passing the first time, consider locally running `cargo run -p ci`. You can run the commands manually: + 1. `cargo fmt --all -- --check` (remove `--check` to let the command fix found problems) + 2. `cargo clippy --workspace --all-targets --all-features -- -D warnings -A clippy::type_complexity -A clippy::manual-strip` + 3. `cargo test --all-targets --workspace` +4. Push your changes to your fork and open a [Pull Request][pull] +5. Respond to any CI failures or review feedback. + +Remember to follow Bevy's [Code of Conduct][coc], and thanks for contributing! + +*The same steps apply for any other repository in the [Bevy organization][bevyorg] that you would like to contribute to. + +[bevy]: https://github.com/bevyengine/bevy +[bevyorg]: https://github.com/bevyengine +[coc]: https://github.com/bevyengine/bevy/blob/main/CODE_OF_CONDUCT.md +[pull]: https://github.com/bevyengine/bevy/compare diff --git a/content/learn/quick-start/contributing/docs/_index.md b/content/learn/quick-start/contributing/docs/_index.md new file mode 100644 index 0000000000..c542cc4a30 --- /dev/null +++ b/content/learn/quick-start/contributing/docs/_index.md @@ -0,0 +1,51 @@ ++++ +title = "Docs" +weight = 2 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" +[extra] +long_title = "Contributing Docs" ++++ + +## The Bevy Book + +The Bevy Book is open source, along with the rest of this website. Check out the [Bevy Website repository on GitHub](https://github.com/bevyengine/bevy-website). The Bevy Book content is written in Markdown. + +### Building the Website + +The website is built using the [Zola static site generator](https://www.getzola.org/). Download Zola, then do the following: + +1. Clone the Bevy Website git repo and move to that directory: + + ```sh + git clone https://github.com/bevyengine/bevy-website.git + cd bevy-website + ``` + +2. Start the Zola server + + ```sh + zola serve + ``` + +A local server should start and you should be able to access a local version of the website from there. + +### Rust API Doc Syntax + +We use Markdown reference-style links to nicely link to the Rust API docs: + +* [`HashMap`] + + ```md + [`Hashmap`]: https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html + ``` + +## Rust API Docs + +Bevy's Rust API Docs are automatically generated from the latest Bevy source code. If you add [Rust documentation comments](https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html#making-useful-documentation-comments) to the Bevy codebase, the API docs will be automatically updated. + +## Bevy Markdown Docs + +Bevy's CI will check markdown files like Readmes using [markdownlint](https://github.com/DavidAnson/markdownlint). If you contribute to markdown files consider installing [markdownlint-cli](https://github.com/igorshubovych/markdownlint-cli) to locally lint your changes. Running `markdownlint -f -c .github/linters/.markdown-lint.yml .` in the root directory of the Bevy project will apply the same linting rules to your changes as the CI workflow. diff --git a/content/learn/quick-start/getting-started/_index.md b/content/learn/quick-start/getting-started/_index.md new file mode 100644 index 0000000000..1de686807c --- /dev/null +++ b/content/learn/quick-start/getting-started/_index.md @@ -0,0 +1,64 @@ ++++ +title = "Getting Started" +weight = 2 +sort_by = "weight" +template = "docs-section.html" +page_template = "docs-section.html" +insert_anchor_links = "right" ++++ + +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/quick-start/getting-started/apps/_index.md b/content/learn/quick-start/getting-started/apps/_index.md new file mode 100644 index 0000000000..98831bffa1 --- /dev/null +++ b/content/learn/quick-start/getting-started/apps/_index.md @@ -0,0 +1,28 @@ ++++ +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 [`App`]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. + +[`App`]: https://docs.rs/bevy/latest/bevy/app/struct.App.html diff --git a/content/learn/book/getting-started/ecs/_index.md b/content/learn/quick-start/getting-started/ecs/_index.md similarity index 54% rename from content/learn/book/getting-started/ecs/_index.md rename to content/learn/quick-start/getting-started/ecs/_index.md index 7ca3175e24..fa1271f571 100644 --- a/content/learn/book/getting-started/ecs/_index.md +++ b/content/learn/quick-start/getting-started/ecs/_index.md @@ -2,8 +2,8 @@ title = "ECS" weight = 3 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ @@ -27,9 +27,9 @@ Bevy ECS is Bevy's implementation of the ECS pattern. Unlike other Rust ECS impl * **Systems**: normal Rust functions ```rs - fn print_position_system(query: Query<&Transform>) { - for transform in query.iter() { - println!("position: {:?}", transform.translation); + fn print_position_system(query: Query<&Position>) { + for position in &query { + println!("position: {} {}", position.x, position.y); } } ``` @@ -52,21 +52,24 @@ fn 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::*; + fn main() { App::new() - .add_system(hello_world) + .add_systems(Update, hello_world) .run(); } ``` -The [`add_system`] function adds the system to your App's [`Schedule`], but we'll cover that more later. +The [`add_system`] function adds the system to your App's [`Update`] [`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. +Now run your app again using `cargo run`. You should see `hello world!` printed once in your terminal. [`add_system`]: https://docs.rs/bevy_app/latest/bevy_app/struct.App.html#method.add_system +[`Update`]: https://docs.rs/bevy/latest/bevy/app/struct.Update.html [`Schedule`]: https://docs.rs/bevy_ecs/latest/bevy_ecs/schedule/struct.Schedule.html ## Your First Components @@ -87,7 +90,7 @@ But what if we want our people to have a name? In a more traditional design, we 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 [`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`]\: ```rs fn add_people(mut commands: Commands) { @@ -102,34 +105,38 @@ Now register the startup system like this: ```rs fn main() { App::new() - .add_startup_system(add_people) - .add_system(hello_world) + .add_systems(Startup, add_people) + .add_systems(Update, hello_world) .run(); } ``` -We could run this App 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`]: +[`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`]: ```rs fn greet_people(query: Query<&Name, With>) { - for name in query.iter() { + for name in &query { println!("hello {}!", name.0); } } ``` -The parameters we pass in to 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. +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: +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! ```rs fn main() { App::new() - .add_startup_system(add_people) - .add_system(hello_world) - .add_system(greet_people) + .add_systems(Startup, add_people) + .add_systems(Update, (hello_world, greet_people)) .run(); } ``` @@ -147,5 +154,35 @@ Marvelous! **Quick Note**: "hello world!" might show up in a different order than it does above. This is because systems run in parallel by default whenever possible. -[`Commands`]: https://docs.rs/bevy_ecs/latest/bevy_ecs/system/struct.Commands.html -[`World`]: https://docs.rs/bevy_ecs/latest/bevy_ecs/world/struct.World.html +### Your First mutable Query + +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 +fn update_people(mut query: Query<&mut Name, With>) { + for mut name in &mut query { + if name.0 == "Elaina Proctor" { + name.0 = "Elaina Hume".to_string(); + break; // We don’t need to change any other names + } + } +} +``` + +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: + +```rs +fn main() { + App::new() + .add_systems(Startup, add_people) + .add_systems(Update, (hello_world, (update_people, greet_people).chain())) + .run(); +} +``` + +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`. +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/quick-start/getting-started/plugins/_index.md b/content/learn/quick-start/getting-started/plugins/_index.md new file mode 100644 index 0000000000..4d39e7e811 --- /dev/null +++ b/content/learn/quick-start/getting-started/plugins/_index.md @@ -0,0 +1,88 @@ ++++ +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 [`UiPlugin`]. Want to build a headless server? Don't register the [`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 [`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 [`WindowPlugin`], which defines the window interface (but doesn't actually know how to make windows), and [`WininitPlugin`] 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 [`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 [`Plugin`] 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. + +[`UiPlugin`]: https://docs.rs/bevy/latest/bevy/ui/struct.UiPlugin.html +[`RenderPlugin`]: https://docs.rs/bevy/latest/bevy/render/struct.RenderPlugin.html +[`WindowPlugin`]: https://docs.rs/bevy/latest/bevy/window/struct.WindowPlugin.html +[`WininitPlugin`]: https://docs.rs/bevy/latest/bevy/winit/struct.WinitPlugin.html +[`DefaultPlugins`]: https://docs.rs/bevy/latest/bevy/struct.DefaultPlugins.html +[`Plugin`]: https://docs.rs/bevy/latest/bevy/app/trait.Plugin.html diff --git a/content/learn/book/getting-started/resources/_index.md b/content/learn/quick-start/getting-started/resources/_index.md similarity index 91% rename from content/learn/book/getting-started/resources/_index.md rename to content/learn/quick-start/getting-started/resources/_index.md index f3322f024c..d124e61e5a 100644 --- a/content/learn/book/getting-started/resources/_index.md +++ b/content/learn/quick-start/getting-started/resources/_index.md @@ -2,8 +2,8 @@ title = "Resources" weight = 5 sort_by = "weight" -template = "book-section.html" -page_template = "book-section.html" +template = "docs-section.html" +page_template = "docs-section.html" insert_anchor_links = "right" +++ @@ -25,7 +25,7 @@ Resources are accessed in much the same way that we access components. You can a ```rs fn greet_people(time: Res
()` * legion (system): A system with `SubWorld` access using `let entry = world.entry(entity); entry.get_component_mut::()` -It's worth noting that using `query.get_component::(entity)` instead of `query.get(entity)` does require safety checks, for the same reason the legion entry api does. We cannot know ahead of time what component type a caller will pass into the method, which means we _must_ check it to make sure it matches the `Query`. +It's worth noting that using `query.get_component::(entity)` instead of `query.get(entity)` does require safety checks, for the same reason the legion entry API does. We cannot know ahead of time what component type a caller will pass into the method, which means we _must_ check it to make sure it matches the `Query`. Additionally, here are some relevant [ecs_bench_suite](https://github.com/rust-gamedev/ecs_bench_suite) results (omitted benchmarks had no significant change): @@ -312,7 +312,7 @@ Additionally, here are some relevant [ecs_bench_suite](https://github.com/rust-g ### Thread Local Resources -Some resource types cannot (or should not) be passed between threads. This is often true for low level apis like windowing, input, and audio. It is now possible to add "thread local resources" to the `Resources` collection, which can only be accessed from the main thread using "thread local systems": +Some resource types cannot (or should not) be passed between threads. This is often true for low level APIs like windowing, input, and audio. It is now possible to add "thread local resources" to the `Resources` collection, which can only be accessed from the main thread using "thread local systems": ```rust // in your app setup @@ -324,11 +324,11 @@ fn system(world: &mut World, resources: &mut Resources) { } ``` -### Query Api Changes +### Query API Changes First, to improve clarity we renamed `query.get::(entity)` to `query.get_component::(entity)`. We now return the "full" query result for a specific entity using `query.get(entity)`. -To allow multiple concurrent reads of Queries (where it is safe), we added separate `query.iter()` and `query.iter_mut()` apis, as well as `query.get(entity)` and `query.get_mut(entity)`. Queries that are "read only" can now retrieve their results via an immutable borrow. +To allow multiple concurrent reads of Queries (where it is safe), we added separate `query.iter()` and `query.iter_mut()` APIs, as well as `query.get(entity)` and `query.get_mut(entity)`. Queries that are "read only" can now retrieve their results via an immutable borrow. ## Mesh Improvements @@ -354,17 +354,17 @@ Rendering meshes often involves using vertex "indices" to cut down on duplicate Transforms are important to get right. They are used in many slices of the engine, user code touches them constantly, and they are relatively expensive to compute: especially transform hierarchies. -In the last release, we vastly simplified Bevy's transform system to use a consolidated `Transform` and `GlobalTransform` instead of multiple separate `Translation`, `Rotation`, and `Scale` components (which were synced to `Transform` and `GlobalTransform`). This made the user-facing api/dataflow simpler, as well as the underlying implementation. The `Transform` component was backed by a 4x4 matrix. I pressed the big green "merge" button ... happy that we had solved the Transform problem once and for all! +In the last release, we vastly simplified Bevy's transform system to use a consolidated `Transform` and `GlobalTransform` instead of multiple separate `Translation`, `Rotation`, and `Scale` components (which were synced to `Transform` and `GlobalTransform`). This made the user-facing API/dataflow simpler, as well as the underlying implementation. The `Transform` component was backed by a 4x4 matrix. I pressed the big green "merge" button ... happy that we had solved the Transform problem once and for all! -It turns out there was still more work to be done! [@AThilenius pointed out](https://github.com/bevyengine/bevy/issues/229#issuecomment-698953161) that using a 4x4 matrix as the source of truth for an affine transform accumulates error over time. Additionally, the Transform api was still a little cumbersome to use. [At the suggestion of @termhn](https://github.com/bevyengine/bevy/issues/229#issuecomment-699172675) we decided to investigate using a "similarity" as the source of truth. This had the following benefits: +It turns out there was still more work to be done! [@AThilenius pointed out](https://github.com/bevyengine/bevy/issues/229#issuecomment-698953161) that using a 4x4 matrix as the source of truth for an affine transform accumulates error over time. Additionally, the Transform API was still a little cumbersome to use. [At the suggestion of @termhn](https://github.com/bevyengine/bevy/issues/229#issuecomment-699172675) we decided to investigate using a "similarity" as the source of truth. This had the following benefits: 1. no more error accumulation -2. we could directly expose translation/rotation/scale fields, which simplified the api significantly +2. we could directly expose translation/rotation/scale fields, which simplified the API significantly 3. cheaper to store and cheaper to compute hierarchies in some cases -We collectively decided this was a good path forward and now we have a re-rewrite that is even better. Yes this is _another_ breaking change, but thats why we label Bevy as being in the "experimentation phase". Now is the time to break things as often as possible to ensure that we find good apis that will stand the test of time. +We collectively decided this was a good path forward and now we have a re-rewrite that is even better. Yes this is _another_ breaking change, but thats why we label Bevy as being in the "experimentation phase". Now is the time to break things as often as possible to ensure that we find good APIs that will stand the test of time. -This is what the new `Transform` api looks like in a Bevy ECS system: +This is what the new `Transform` API looks like in a Bevy ECS system: ```rust fn system(mut transform: Mut) { @@ -444,7 +444,7 @@ app.add_plugins(HelloWorldPlugins);
authors: @mockersf
-Bevy provides a backend-agnostic windowing api. Up until this point, window settings could only be set once at app startup. If you wanted to set window settings dynamically, you had to directly interact with window backends (ex: winit). +Bevy provides a backend-agnostic windowing API. Up until this point, window settings could only be set once at app startup. If you wanted to set window settings dynamically, you had to directly interact with window backends (ex: winit). In this release we added the ability to dynamically set window properties at runtime using the Bevy window abstraction: diff --git a/content/news/2020-12-19-bevy-0.4/index.md b/content/news/2020-12-19-bevy-0.4/index.md index 4c611819e1..b44d8ccaf4 100644 --- a/content/news/2020-12-19-bevy-0.4/index.md +++ b/content/news/2020-12-19-bevy-0.4/index.md @@ -493,7 +493,7 @@ The new text layout system uses glyph_brush_layout, which fixes the layout bugs
authors: @cart
-Bevy's render api was built to be easy to use and extend. I wanted to nail down a good api first, but that resulted in a number of performance TODOs that caused some pretty serious overhead. +Bevy's render API was built to be easy to use and extend. I wanted to nail down a good API first, but that resulted in a number of performance TODOs that caused some pretty serious overhead. For **Bevy 0.4** I decided to resolve as many of those TODOs as I could. There is still plenty more to do (like instancing and batching), but Bevy already performs _much_ better than it did before. @@ -753,7 +753,7 @@ There is still a bit more work to be done here. While Bevy UI renders images and Bevy's Timer component/resource got a number of quality-of-life improvements: pausing, field accessor methods, ergonomics improvements, and internal refactoring / code quality improvements. Timer Components also no longer tick by default. Timer resources and newtyped Timer components couldn't tick by default, so it was a bit inconsistent to have the (relatively uncommon) "unwrapped component Timer" auto-tick. -The timer api now looks like this: +The timer API now looks like this: ```rust @@ -793,7 +793,7 @@ Bevy now runs on Apple silicon thanks to upstream work on winit (@scoopr) and co ## New Examples -### Contributors Visualization +### Bevy Contributors
author: @karroffel
diff --git a/content/news/2021-04-06-bevy-0.5/index.md b/content/news/2021-04-06-bevy-0.5/index.md index ebef25a1bc..8d065f527a 100644 --- a/content/news/2021-04-06-bevy-0.5/index.md +++ b/content/news/2021-04-06-bevy-0.5/index.md @@ -16,7 +16,7 @@ Thanks to **88** contributors, **283** pull requests, and our [**generous sponso For those who don't know, Bevy is a refreshingly simple data-driven game engine built in Rust. You can check out [Quick Start Guide](/learn/book/getting-started/) to get started. Bevy is also free and open source forever! You can grab the full [source code](https://github.com/bevyengine/bevy) on GitHub. Check out [Awesome Bevy](https://github.com/bevyengine/awesome-bevy) for a list of community-developed plugins, games, and learning resources. -**Bevy 0.5** is quite a bit bigger than our past few releases (and took a bit longer) as we have made a number of foundational changes. If you plan on updating your App or Plugin to **Bevy 0.5**, check out our [0.4 to 0.5 Migration Guide](/learn/book/migration-guides/0.4-0.5/). +**Bevy 0.5** is quite a bit bigger than our past few releases (and took a bit longer) as we have made a number of foundational changes. If you plan on updating your App or Plugin to **Bevy 0.5**, check out our [0.4 to 0.5 Migration Guide](/learn/migration-guides/0.4-0.5/). Here are some of the highlights from this release: @@ -162,7 +162,7 @@ You may have noticed that **Bevy 0.5 (Table)** is also _way_ faster than **Bevy 3. Incrementally build up state * When new archetypes are added, we only process the new archetypes (no need to rebuild state for old archetypes) -As a result, the direct [`World`] query api now looks like this: +As a result, the direct [`World`] query API now looks like this: ```rust let mut query = world.query::<(&A, &mut B)>(); @@ -449,7 +449,7 @@ We are also actively seeking feedback on the new executor. We believe that the n Global change detection, the ability to run queries on the Changed/Added status of any ECS component or resource, just got a major usability boost: changes are now detected across frames/updates: ```rust -// This is still the same change detection api we all know and love, +// This is still the same change detection API we all know and love, // the only difference is that it "just works" in every situation. fn system(query: Query>) { // iterates all entities whose A component has changed since @@ -473,7 +473,7 @@ The [last Bevy release](https://bevyengine.org/news/bevy-0-4) added States, whic The old implementation largely worked, but it had a number of quirks and limitations. First and foremost, it required adding a new `StateStage`, which cut down on parallelism, increased boilerplate, and forced ordering where it wasn't required. Additionally, some of the lifecycle events didn't always behave as expected. -The new [`State`] implementation is built on top of the new parallel executor's SystemSet and RunCriteria features, for a much more natural, flexible, and parallel api that builds on existing concepts instead of creating new ones: +The new [`State`] implementation is built on top of the new parallel executor's SystemSet and RunCriteria features, for a much more natural, flexible, and parallel API that builds on existing concepts instead of creating new ones: ```rust #[derive(Debug, Clone, Eq, PartialEq, Hash)] @@ -543,7 +543,7 @@ fn system(mut reader: EventReader) { } ``` -There is also now a symmetrical `EventWriter` api: +There is also now a symmetrical `EventWriter` API: ```rust fn system(mut writer: EventWriter) { @@ -568,7 +568,7 @@ Text can now have "sections", each with their own style / formatting. This makes ![rich_text](rich_text.png) -This is accomplished using the new "text section" api: +This is accomplished using the new "text section" API: ```rust commands @@ -788,7 +788,7 @@ This example serves as a quick introduction to building 3D games in Bevy. It sho
authors: @kokounet
-The [`Timer`] struct now internally uses [`Duration`] instead of using `f32` representations of seconds. This both increases precision and makes the api a bit nicer to look at. +The [`Timer`] struct now internally uses [`Duration`] instead of using `f32` representations of seconds. This both increases precision and makes the API a bit nicer to look at. ```rust fn system(mut timer: ResMut, time: Res
| { This temporarily removes the `A` resource from `World`, provides mutable pointers to both, and re-adds A to World when finished. Thanks to the move to ComponentIds/sparse sets, this is a cheap operation. -If multiple resources are required, scopes can be nested. We could also consider adding a "resource tuple" to the api if this pattern becomes common and the boilerplate gets nasty. +If multiple resources are required, scopes can be nested. We could also consider adding a "resource tuple" to the API if this pattern becomes common and the boilerplate gets nasty. ### Query Conflicts Use ComponentId Instead of ArchetypeComponentId @@ -1311,7 +1311,7 @@ A huge thanks to the **88 contributors** that made this release (and associated * [add scene instance entity iteration][1058] * [Make Commands and World apis consistent][1703] * [Add `insert_children` and `push_children` to EntityMut][1728] -* [Extend AppBuilder api with `add_system_set` and similar methods][1453] +* [Extend AppBuilder API with `add_system_set` and similar methods][1453] * [add labels and ordering for transform and parent systems in POST_UPDATE stage][1456] * [Explicit execution order ambiguities API][1469] * [Resolve (most) internal system ambiguities][1606] diff --git a/content/news/2021-08-10-bevys-first-birthday/index.md b/content/news/2021-08-10-bevys-first-birthday/index.md index a1d109d9e0..6f973fe26d 100644 --- a/content/news/2021-08-10-bevys-first-birthday/index.md +++ b/content/news/2021-08-10-bevys-first-birthday/index.md @@ -39,7 +39,7 @@ For those who don't know, Bevy is a refreshingly simple data-driven game engine * **December 19**: [Bevy 0.4](/news/bevy-0-4/) * We somehow still managed to keep up the "approximately once a month" release cadence. We added a WebGL2 render backend, cross platform main functions, live shader reloading, flexible ECS parameter orders, simplified query filters, system inputs, outputs, and chaining, a more featureful and flexible ECS schedule implementation, "fixed timesteps", states, gltf improvements, spawning scenes as children, dynamic linking for _drastically_ faster iterative compile times, a new text layout implementation, renderer optimizations, a new rust reflection crate (filling a major gap in the rust ecosystem), 3d texture assets, logging and profiling, hidpi rendering, timer improvements, task system improvements, and apple silicon support. * **April 6**: [Bevy 0.5](/news/bevy-0-5/) - * The almost-one-release-a-month streak finally ended. But thats not because we slowed down our pace! This release was a big one. It added Physically Based Rendering (PBR), GLTF asset improvements, Bevy ECS V2: a complete from-scratch rewrite with a novel archetype/sparse-set hybrid storage model, an "archetype graph" for faster archetype changes, query caching, uber fast for-each iterators, a new system executor with system labels, explicit system ordering/dependencies, system sets, and increased parallelism, "reliable" change detection, and a full rewrite of the State system). We also added a rich text api, hidpi and 2d-world space text, world-to-screen coordinate conversions, a 3d orthographic camera and new scaling modes, flexible camera bindings in shaders, render layers, sprite flipping, color spaces, wireframe rendering, and more smaller tweaks that I don't have room for here. + * The almost-one-release-a-month streak finally ended. But thats not because we slowed down our pace! This release was a big one. It added Physically Based Rendering (PBR), GLTF asset improvements, Bevy ECS V2: a complete from-scratch rewrite with a novel archetype/sparse-set hybrid storage model, an "archetype graph" for faster archetype changes, query caching, uber fast for-each iterators, a new system executor with system labels, explicit system ordering/dependencies, system sets, and increased parallelism, "reliable" change detection, and a full rewrite of the State system). We also added a rich text API, hidpi and 2d-world space text, world-to-screen coordinate conversions, a 3d orthographic camera and new scaling modes, flexible camera bindings in shaders, render layers, sprite flipping, color spaces, wireframe rendering, and more smaller tweaks that I don't have room for here. * **April 14**: [The Bevy RFC process is unveiled](https://github.com/bevyengine/rfcs) * Inspired by the Rust RFC process, we added a way to collaboratively design and review Bevy APIs prior to implementing them. This generally isn't required, but for bigger changes it ensures we think deeply about what we are building, mitigates risk, and encodes designs and intents for future Bevy developers. * **June 1**: [First public release of Bevy Assets](https://twitter.com/BevyEngine/status/1399891316939448320) @@ -134,7 +134,7 @@ As a result of (1), (2), and Bevy being free and open source, we foster a feelin ### Bevy ECS -**Content Warning:** I'm going to boast a lot here and make some hard-to-verify claims, which might offend some peoples' sensibilities :) +**Content Warning**: I'm going to boast a lot here and make some hard-to-verify claims, which might offend some peoples' sensibilities :) Bevy ECS is the interface we use to build both engine features and apps, so it was natural to give it focus last year. I honestly don't think it is controversial to say that Bevy ECS has pushed the envelope of what an ECS can be. Bevy ECS is the "secret sauce" (well ... \*\*cough\*\* ... "open sauce") that I believe uniquely positions us in the engine market. This is a result of meticulous experimentation, benchmarking, collaboration with other experts in the field, and unification of a lot of good ideas in the wider ECS ecosystem. @@ -176,7 +176,7 @@ Immediately after the initial Bevy release, I [said we needed to focus](https:// * [**Scenes**](https://github.com/bevyengine/bevy/issues/255): better scene format, inline assets, enabling / disabling systems * [**PBR / Clustered Forward Rendering**](https://github.com/bevyengine/bevy/issues/179): PBR shaders, HDR, bloom, shadowing, all using clustered-forward rendering -* [**Editor-Ready UI**](https://github.com/bevyengine/bevy/issues/254): iterate on the current Bevy UI, add a canvas style drawing api, implement core widgets, theme-ability +* [**Editor-Ready UI**](https://github.com/bevyengine/bevy/issues/254): iterate on the current Bevy UI, add a canvas style drawing API, implement core widgets, theme-ability If you have been paying any attention to what we've built over the past year, we clearly _haven't_ focused exclusively on these things, and in some cases chose to go in completely different directions. Here is what we _actually_ focused on (at various points during the year): @@ -201,12 +201,12 @@ Going forward I plan on changing my approach to focus areas in the following way The old renderer (pre Bevy 0.6) did a number of things right: -* User-friendly ECS-driven high level apis for custom shaders with very little boilerplate. For example, check out this ["custom shader material" app](https://github.com/bevyengine/bevy/blob/main/examples/shader/shader_custom_material.rs) +* User-friendly ECS-driven high level APIs for custom shaders with very little boilerplate. For example, check out this ["custom shader material" app](https://github.com/bevyengine/bevy/blob/main/examples/shader/shader_custom_material.rs) * A modular "low level" Render Graph that enabled developers to easily slot new features into the render pipeline without centralized top-level orchestration, or to create entirely new render pipelines. -However the mid-level apis between the render graph and the high level apis were complicated, full of abstractions and jargon, and in some cases, inefficient. As a result, this made the system hard to reason about and new developers struggled to understand it. I attribute this largely to focusing on making the high level and low level apis "good UX" and treating the mid level apis as "glue". +However the mid-level APIs between the render graph and the high level APIs were complicated, full of abstractions and jargon, and in some cases, inefficient. As a result, this made the system hard to reason about and new developers struggled to understand it. I attribute this largely to focusing on making the high level and low level APIs "good UX" and treating the mid level APIs as "glue". -I consider the old design of the mid-level apis to be a pretty costly "mistake". The new renderer will solve these problems, largely by flattening out abstractions and clarifying dataflow. I'm really excited about it. Live and learn I guess. Things are rarely perfect on your first try. +I consider the old design of the mid-level APIs to be a pretty costly "mistake". The new renderer will solve these problems, largely by flattening out abstractions and clarifying dataflow. I'm really excited about it. Live and learn I guess. Things are rarely perfect on your first try. ### Issue and Pull Request Response Times @@ -241,7 +241,7 @@ Here are some of my plans for the next year: * **Animation**: We will build a unified animation system that makes 2D and 3D animation easier and integrates naturally with the Bevy Editor * **2D Features**: Sprite batching, more tileset features, layers, visual / interactive tooling in the Bevy Editor * **3D Features**: Skeletal animation (that integrates with the Animation system), configurable / flexible / good looking shadows, at least one form of global illumination, more PBR properties, and visual / interactive tooling in the Bevy Editor -* **Bevy Game Jam**: We will have at least one official Bevy Game Jam to promote Bevy, battle test apis, and give users more examples to build off of. +* **Bevy Game Jam**: We will have at least one official Bevy Game Jam to promote Bevy, battle test APIs, and give users more examples to build off of. I am relatively confident that we can make these things happen. We already have working prototypes for many of the features above and have started reaching consensus in a number of areas. @@ -252,7 +252,7 @@ Here are some predictions about Bevy's trajectory over the next year: * By the end of the year, I expect people to start taking us seriously for 3D applications, thanks to a solid set of built in "advanced rendering features" and our extremely competitive renderer modularity. * I expect the number of people getting paid to develop Bevy Engine, build Bevy apps, and make Bevy content to go way up. * If the "Next Generation Bevy UI" effort is successful, people wanting to build "Rust GUI apps" will start reaching for Bevy. -* We will break out of the "Rust gamedev enthusiast" circles. By the end of the year, Bevy will be brought up more regularly in the wider gamedev community alongside conversations about Unity, Unreal, and Godot. Not necessarily as a _direct_ competitor yet, but as a viable alternative for people that (1) want something new / innovative / different and (2) are willing to work around a smaller feature set and slightly less stable apis. +* We will break out of the "Rust gamedev enthusiast" circles. By the end of the year, Bevy will be brought up more regularly in the wider gamedev community alongside conversations about Unity, Unreal, and Godot. Not necessarily as a _direct_ competitor yet, but as a viable alternative for people that (1) want something new / innovative / different and (2) are willing to work around a smaller feature set and slightly less stable APIs. If any of this excites you, we would love your help! Check out our code on [Github](https://github.com/bevyengine/bevy), start participating in the [Bevy Community](https://bevyengine.org/community/), and consider [sponsoring my work](https://github.com/sponsors/cart) to ensure I can continue building and leading this wildly ambitious project. diff --git a/content/news/2022-01-08-bevy-0.6/index.md b/content/news/2022-01-08-bevy-0.6/index.md index 3b2e665f7b..15206111a6 100644 --- a/content/news/2022-01-08-bevy-0.6/index.md +++ b/content/news/2022-01-08-bevy-0.6/index.md @@ -16,7 +16,7 @@ Thanks to **170** contributors, **623** pull requests, and our [**generous spons For those who don't know, Bevy is a refreshingly simple data-driven game engine built in Rust. You can check out [Quick Start Guide](/learn/book/getting-started/) to get started. Bevy is also free and open source forever! You can grab the full [source code](https://github.com/bevyengine/bevy) on GitHub. Check out [Bevy Assets](https://bevyengine.org/assets) for a collection of community-developed plugins, games, and learning resources. -To update an existing Bevy App or Plugin to **Bevy 0.6**, check out our [0.5 to 0.6 Migration Guide](/learn/book/migration-guides/0.5-0.6/). +To update an existing Bevy App or Plugin to **Bevy 0.6**, check out our [0.5 to 0.6 Migration Guide](/learn/migration-guides/0.5-0.6/). There are a _ton_ of improvements, bug fixes and quality of life tweaks in this release. Here are some of the highlights: @@ -130,12 +130,12 @@ The truth of the matter is that wgpu already occupies _exactly_ the space we wan However, initially there were a couple of reasons not to make it our "public facing API": * **Complexity**: wgpu used to be built on top of gfx-hal (an older GPU abstraction layer also built and managed by the wgpu team). These multiple layers of abstraction in multiple repos made contributing to and reasoning about the internals difficult. Additionally, I have a rule for "3rd party dependencies publicly exposed in Bevy APIs": we must feel comfortable forking and maintaining them if we need to (ex: upstream stops being maintained, visions diverge, etc). I wasn't particularly comfortable with doing that with the old architecture. -* **Licensing**: wgpu used to be licensed under the "copyleft" MPL license, which created concerns about integration with proprietary graphics apis (such as consoles like the Switch). +* **Licensing**: wgpu used to be licensed under the "copyleft" MPL license, which created concerns about integration with proprietary graphics APIs (such as consoles like the Switch). * **WebGL2 Support**: wgpu used to not have a WebGL2 backend. Bevy's old renderer had a custom WebGL2 backend and we weren't willing to give up support for the Web as a platform. _Almost immediately_ after we voiced these concerns, @kvark kicked off a [relicensing effort](https://github.com/gfx-rs/wgpu/issues/392) that switched wgpu to the Rust-standard dual MIT/Apache-2.0 license. They also removed gfx-hal in favor of a [much simpler and flatter architecture](https://gfx-rs.github.io/2021/08/18/release-0.10.html). Soon after, @zicklag [added a WebGL2 backend](https://github.com/gfx-rs/wgpu/pull/1686). Having resolved all of my remaining hangups, it was clear to me that @kvark's priorities were aligned with mine and that I could trust them to adjust to community feedback. -The New Bevy Renderer tosses out our old intermediate GPU abstraction layer in favor of using wgpu directly as our "low-level" GPU api. The result is a simpler (and faster) architecture with full and direct access to wgpu. Feedback from Bevy Renderer feature developers so far has been _very positive_. +The New Bevy Renderer tosses out our old intermediate GPU abstraction layer in favor of using wgpu directly as our "low-level" GPU API. The result is a simpler (and faster) architecture with full and direct access to wgpu. Feedback from Bevy Renderer feature developers so far has been _very positive_. Bevy was also updated to use the latest and greatest wgpu version: [0.12](https://github.com/gfx-rs/wgpu/blob/master/CHANGELOG.md#wgpu-012-2021-12-18). diff --git a/content/news/2022-04-15-bevy-0.7/index.md b/content/news/2022-04-15-bevy-0.7/index.md index c4e0255340..d497cecb01 100644 --- a/content/news/2022-04-15-bevy-0.7/index.md +++ b/content/news/2022-04-15-bevy-0.7/index.md @@ -16,7 +16,7 @@ Thanks to **123** contributors, **349** pull requests, and our [**generous spons For those who don't know, Bevy is a refreshingly simple data-driven game engine built in Rust. You can check out [Quick Start Guide](/learn/book/getting-started/) to get started. Bevy is also free and open source forever! You can grab the full [source code](https://github.com/bevyengine/bevy) on GitHub. Check out [Bevy Assets](https://bevyengine.org/assets) for a collection of community-developed plugins, games, and learning resources. -To update an existing Bevy App or Plugin to **Bevy 0.7**, check out our [0.6 to 0.7 Migration Guide](/learn/book/migration-guides/0.6-0.7/). +To update an existing Bevy App or Plugin to **Bevy 0.7**, check out our [0.6 to 0.7 Migration Guide](/learn/migration-guides/0.6-0.7/). As always, there are a _ton_ of new features, bug fixes, and quality of life tweaks in this release, but here are some of the highlights: @@ -65,7 +65,7 @@ fn start_dancing(mut query: Query<(&Animations, &mut AnimationPlayer)>) { This critical feature has been a long time coming, but we wanted to build it in a way that meshed nicely with the [new Bevy renderer](/news/bevy-0-6/#the-new-bevy-renderer) and didn't just "hack things in". This builds on our new [Flexible Mesh Vertex Layouts](/news/bevy-0-7/#flexible-mesh-vertex-layouts), [Shader Imports](/news/bevy-0-6/#shader-imports), and [Material](/news/bevy-0-6/#materials) systems, which ensures that this logic is flexible and reusable, even with non-standard meshes and custom render pipelines. -And we're just getting started! Multi-track animation blending and higher level animation state management should arrive in the very near future. Now is a great time to start contributing animation features to Bevy. We've smashed through most of the foundational technical hurdles and what remains is largely high level api design choices. We already have a couple of draft RFCs open in these areas: [Animation Composition](https://github.com/bevyengine/rfcs/pull/51) and [Animation Primitives](https://github.com/bevyengine/rfcs/pull/49). Feel free to join the conversation! +And we're just getting started! Multi-track animation blending and higher level animation state management should arrive in the very near future. Now is a great time to start contributing animation features to Bevy. We've smashed through most of the foundational technical hurdles and what remains is largely high level API design choices. We already have a couple of draft RFCs open in these areas: [Animation Composition](https://github.com/bevyengine/rfcs/pull/51) and [Animation Primitives](https://github.com/bevyengine/rfcs/pull/49). Feel free to join the conversation! [`AnimationPlayer`]: https://docs.rs/bevy/0.7.0/bevy/animation/struct.AnimationPlayer.html [`AnimationClip`]: https://docs.rs/bevy/0.7.0/bevy/animation/struct.AnimationClip.html @@ -342,7 +342,7 @@ fn system(mut query: Query<&mut Transform>, entities: Res) { } ``` -However, to respect Rust's mutability rules, we need to disallow apis that might produce "aliased mutability". Seasoned Bevy users will probably recognize this Rust borrow checker error: +However, to respect Rust's mutability rules, we need to disallow APIs that might produce "aliased mutability". Seasoned Bevy users will probably recognize this Rust borrow checker error: ```rust fn system(mut query: Query<&mut Transform>, entities: Res) { @@ -354,7 +354,7 @@ fn system(mut query: Query<&mut Transform>, entities: Res) { _You_ know Entity A and Entity B are different entities at runtime. But Rust's borrow checker has no way to know that at compile time! I'm sure you can imagine game development scenarios that would benefit from having mutable access to multiple components at the same time. This borrow checker restriction was a common pain point and the workarounds were ... not fun (using scopes to ensure conflicting accesses are dropped, copying data, re-querying things, etc). -Fortunately, **Bevy 0.7** introduces a brand new set of apis to save the day! +Fortunately, **Bevy 0.7** introduces a brand new set of APIs to save the day! ```rust fn system(mut query: Query<&mut Transform>, entities: Res) { @@ -436,9 +436,9 @@ fn give_sword(mut query: Query<&mut Items>) { } ``` -This works just fine, but that `0` at the end of `items.0` sticks out like a sore thumb. Many of us in the Bevy Org think `.0` has no place in public apis. But the newtype pattern is still useful! Ideally, Rust would provide a way to express that `Items` is a new type, while transparently provided access to the `Vec` stored within. There are designs being discussed by the Rust team, but we don't want to wait for nice things! +This works just fine, but that `0` at the end of `items.0` sticks out like a sore thumb. Many of us in the Bevy Org think `.0` has no place in public APIs. But the newtype pattern is still useful! Ideally, Rust would provide a way to express that `Items` is a new type, while transparently provided access to the `Vec` stored within. There are designs being discussed by the Rust team, but we don't want to wait for nice things! -Fortunately, the Deref / DerefMut traits in std provide the behavior we want. Users can already manually implement these traits, but for such a common pattern, we decided that providing our own trait derives was worth it. In **Bevy 0.7**, you can now derive Deref and DerefMut, enabling much nicer public apis: +Fortunately, the Deref / DerefMut traits in std provide the behavior we want. Users can already manually implement these traits, but for such a common pattern, we decided that providing our own trait derives was worth it. In **Bevy 0.7**, you can now derive Deref and DerefMut, enabling much nicer public APIs: ```rust #[derive(Component, Deref, DerefMut)] @@ -970,7 +970,7 @@ A huge thanks to the **123 contributors** that made this release (and associated * [Increment last event count on next instead of iter][2382] * [Obviate the need for `RunSystem`, and remove it][3817] * [Cleanup some things which shouldn't be components][2982] -* [Remove the config api][3633] +* [Remove the config API][3633] * [Deprecate `.system`][3302] * [Hide docs for concrete impls of Fetch, FetchState, and SystemParamState][4250] * [Move the CoreStage::Startup to a seperate StartupSchedule label][2434] diff --git a/content/news/2022-07-30-bevy-0.8/index.md b/content/news/2022-07-30-bevy-0.8/index.md index 89e5ea8303..a8b74dca38 100644 --- a/content/news/2022-07-30-bevy-0.8/index.md +++ b/content/news/2022-07-30-bevy-0.8/index.md @@ -16,7 +16,7 @@ Thanks to **130** contributors, **461** pull requests, community reviewers, and For those who don't know, Bevy is a refreshingly simple data-driven game engine built in Rust. You can check out our [Quick Start Guide](/learn/book/getting-started/) to try it today. It's free and open source forever! You can grab the full [source code](https://github.com/bevyengine/bevy) on GitHub. Check out [Bevy Assets](https://bevyengine.org/assets) for a collection of community-developed plugins, games, and learning resources. -To update an existing Bevy App or Plugin to **Bevy 0.8**, check out our [0.7 to 0.8 Migration Guide](/learn/book/migration-guides/0.7-0.8/). +To update an existing Bevy App or Plugin to **Bevy 0.8**, check out our [0.7 to 0.8 Migration Guide](/learn/migration-guides/0.7-0.8/). Since our last release a few months ago we've added a _ton_ of new features, bug fixes, and quality of life tweaks, but here are some of the highlights: @@ -583,7 +583,7 @@ Bevy officially only supports Rust as the "one true way to define app logic". We When we [released Bevy ECS V2](https://bevyengine.org/news/bevy-0-5/#bevy-ecs-v2), we intentionally built our internal ECS storage with these cases in mind. But we didn't expose public APIs that made it possible to interact with ECS data without normal Rust types. -**Bevy 0.8** adds public "untyped" ECS apis that enable retrieving [lifetimed pointers](#ecs-lifetimed-pointers) to component and resource data using [`ComponentId`] instead of actual Rust types. +**Bevy 0.8** adds public "untyped" ECS APIs that enable retrieving [lifetimed pointers](#ecs-lifetimed-pointers) to component and resource data using [`ComponentId`] instead of actual Rust types. ```rust let health_ptr: Ptr = world.entity(player).get_by_id(heath_component_id).unwrap(); @@ -835,7 +835,7 @@ Bevy's "Rust reflection" system `bevy_reflect` is a core, foundational piece of
authors: @jakobhellermann
-The [`Reflect`] derives now automatically add a new [`ReflectFromPtr`] struct to the [`TypeRegistry`] for each reflected type. This enables using the new [untyped ECS apis](#scripting-and-modding-progress-untyped-ecs-apis) in combination with the reflection system. This helps enable things like 3rd party scripting and modding. +The [`Reflect`] derives now automatically add a new [`ReflectFromPtr`] struct to the [`TypeRegistry`] for each reflected type. This enables using the new [untyped ECS APIs](#scripting-and-modding-progress-untyped-ecs-apis) in combination with the reflection system. This helps enable things like 3rd party scripting and modding. [`Reflect`]: https://docs.rs/bevy/0.8.0/bevy/reflect/trait.Reflect.html [`ReflectFromPtr`]: https://docs.rs/bevy/0.8.0/bevy/reflect/struct.ReflectFromPtr.html @@ -1023,7 +1023,7 @@ Bevy's [new renderer](/news/bevy-0-6/#the-new-bevy-renderer) "extracts" data nee This accomplished the goal, but it: -1. **Was confusing**: render feature developers had to "know" that this stage behaved differently from the other "normal" ECS stages in the schedule. Implicitly, [`Commands`] behaved differently and the ECS data access was "flipped". Using "normal" entity spawning apis _would not work as expected_ because the [`Commands`] parameter internally still used the main app's Entities collection. +1. **Was confusing**: render feature developers had to "know" that this stage behaved differently from the other "normal" ECS stages in the schedule. Implicitly, [`Commands`] behaved differently and the ECS data access was "flipped". Using "normal" entity spawning APIs _would not work as expected_ because the [`Commands`] parameter internally still used the main app's Entities collection. 2. **Prevented parallelism**: directly modifying existing "render world" resources required exclusive access to `ResMut`, which prevented these systems from running in parallel. Making this access parallel required unnecessary allocations using [`Commands`], which for "large" (or incrementally updated) extractions was inefficient. ```rust @@ -1203,7 +1203,7 @@ Being a "maintainer" now works like this: 1. **Maintainers now have no (hard) limits on the "area" of PRs they can merge**. No more limits on "docs only", "rendering only", etc. It is now each maintainers' responsibility to evaluate their areas of comfort. This does increase risk to an extent, but I think it's an important step to allow maintainers to grow organically. 2. **Maintainers can merge "relatively uncontroversial" PRs with at least two community approvals**. Maintainers will collectively decide and enforce what is uncontroversial. Controversial PRs should be labeled with the `S-Controversial` label. Note that "two community approvals" is the minimum requirement. Maintainers are responsible for ensuring the appropriate people have approved a PR. -3. **Maintainers can merge "completely trivial" PRs without two community approvals**. Some examples of "completely trivial": typo fixes, removing unused dependencies or code, and small "api consistency" fixes. +3. **Maintainers can merge "completely trivial" PRs without two community approvals**. Some examples of "completely trivial": typo fixes, removing unused dependencies or code, and small "API consistency" fixes. 4. **Controversial Decision Making on a Timer**: For all controversial PRs (including RFCs), if two maintainers approve, the PR can be labeled with a `S-Ready-For-Final-Review` label. As soon as this label is added and I have been pinged, a clock starts. If I have not responded with actionable feedback, a "snooze button" / "we aren't ready for this yet", or a veto within a month and a half (45 days), maintainers are free to merge the PR. This gives me the ability to dictate project direction in areas where that is important while also empowering maintainers to move things forward in parallel when that makes sense. We will be calibrating this approach as we go to make sure we strike the right balance between progress, quality, and consistent vision. 5. **I still reserve the right to veto all code changes and make unilateral code changes**. This includes reverting "controversial changes" merged via (4). diff --git a/content/news/2022-08-10-bevys-second-birthday/index.md b/content/news/2022-08-10-bevys-second-birthday/index.md index 857026b727..0b01353619 100644 --- a/content/news/2022-08-10-bevys-second-birthday/index.md +++ b/content/news/2022-08-10-bevys-second-birthday/index.md @@ -178,7 +178,7 @@ For our last birthday, I [made some predictions for the next year](/news/bevys-f * **Break Ground on The Bevy Editor**: We did not break ground on the Bevy Editor. As mentioned above, we _need_ to start prioritizing this work. * **Predicted Scene Improvements**: We did not get support for nested scenes, make the scene format prettier, or add property overloading. We have a new PR for a [prettier scene format](https://github.com/bevyengine/bevy/pull/4561) that builds on all of the Bevy Reflect work we did last year, but we are still reviewing it. * **The New Bevy Book**: We did make progress on the new Bevy Book, but we have not released it yet. -* **Predicted Bevy ECS Features**: We invested heavily in Bevy ECS, but we did not get "reactive ECS" / entity-relationship indexing. The parallel system scheduling api _was_ improved, but we did not make it more granular (ex: "stageless ECS" is nearly ready, but we haven't merged it yet). +* **Predicted Bevy ECS Features**: We invested heavily in Bevy ECS, but we did not get "reactive ECS" / entity-relationship indexing. The parallel system scheduling API _was_ improved, but we did not make it more granular (ex: "stageless ECS" is nearly ready, but we haven't merged it yet). * **Unified Property Animation System**: We did do some design work ([RFC 49](https://github.com/bevyengine/rfcs/pull/49), [RFC 51](https://github.com/bevyengine/rfcs/pull/51)) and there were some proposed implementations ([PR 1429](https://github.com/bevyengine/bevy/pull/1429)), but we have not merged an implementation yet. * **Predicted 2D Features**: We did implement sprite batching and sprite render layers! We didn't meaningfully add tileset workflow improvements (3rd party crates like [bevy_ecs_tilemap](https://github.com/StarArawn/bevy_ecs_tilemap) are often still preferable). And we also didn't add visual editor workflows (because the Bevy Editor doesn't exist yet). * **Predicted 3D Features**: We did implement skeletal animation, configurable / flexible / good looking shadows, and added a few more PBR Material configuration options! We did not add a global illumination implementation (although 3rd party plugins like [bevy-hikari](https://github.com/cryscan/bevy-hikari) now exist). We also didn't add visual editor workflows (again, because the Bevy Editor doesn't exist yet). diff --git a/content/news/2022-11-12-bevy-0.9/index.md b/content/news/2022-11-12-bevy-0.9/index.md index 663b504767..8d57d5989e 100644 --- a/content/news/2022-11-12-bevy-0.9/index.md +++ b/content/news/2022-11-12-bevy-0.9/index.md @@ -14,7 +14,7 @@ Thanks to **159** contributors, **430** pull requests, community reviewers, and For those who don't know, Bevy is a refreshingly simple data-driven game engine built in Rust. You can check out our [Quick Start Guide](/learn/book/getting-started/) to try it today. It's free and open source forever! You can grab the full [source code](https://github.com/bevyengine/bevy) on GitHub. Check out [Bevy Assets](https://bevyengine.org/assets) for a collection of community-developed plugins, games, and learning resources. -To update an existing Bevy App or Plugin to **Bevy 0.9**, check out our [0.8 to 0.9 Migration Guide](/learn/book/migration-guides/0.8-0.9/). +To update an existing Bevy App or Plugin to **Bevy 0.9**, check out our [0.8 to 0.9 Migration Guide](/learn/migration-guides/0.8-0.9/). Since our last release a few months ago we've added a _ton_ of new features, bug fixes, and quality of life tweaks, but here are some of the highlights: @@ -520,7 +520,7 @@ struct PlayerBundle { } ``` -In **Bevy 0.9**, [`Component`] types now _also_ automatically implement the [`Bundle`] trait, which allows us to consolidate all entity component operations under new `spawn`, `insert`, and `remove` apis. Previously, we had separate variants for [`Bundle`] (ex: `insert_bundle(SomeBundle)`) and [`Component`] (ex: `.insert(SomeComponent)`). +In **Bevy 0.9**, [`Component`] types now _also_ automatically implement the [`Bundle`] trait, which allows us to consolidate all entity component operations under new `spawn`, `insert`, and `remove` APIs. Previously, we had separate variants for [`Bundle`] (ex: `insert_bundle(SomeBundle)`) and [`Component`] (ex: `.insert(SomeComponent)`). The [`Bundle`] trait is now also implemented for tuples of [`Bundles`][`Bundle`] instead of just tuples of [`Components`][`Component`]. The value of this will be made clear in a moment. @@ -566,7 +566,7 @@ commands.spawn(( This is _much_ easier to type and read. And on top of that, from the perspective of Bevy ECS this is a single "bundle spawn" instead of multiple operations, which cuts down on ["archetype moves"](/news/bevy-0-5/#component-storage-the-problem). This makes this single spawn operation much more efficient! -These principles apply to the insert apis as well: +These principles apply to the insert APIs as well: ```rust // Old @@ -578,7 +578,7 @@ commands commands.insert((PlayerBundle::default(), ActivePlayer)); ``` -They also apply to the remove apis: +They also apply to the remove APIs: ```rust // Old @@ -757,7 +757,7 @@ app We had some _huge_ performance wins in **Bevy 0.9** thanks to `@james7132`: * The Query fetch abstraction [was reworked](https://github.com/bevyengine/bevy/pull/4800) to hoist common parts out of individual iteration, improving iterator performance on some benchmarks by ~10-20%. `Query::get` performance also saw some improvements. -* [Some unnecessary branches were removed](https://github.com/bevyengine/bevy/pull/6461) from our data access apis, improving performance across most of our ECS benchmarks by ~5-20%! +* [Some unnecessary branches were removed](https://github.com/bevyengine/bevy/pull/6461) from our data access APIs, improving performance across most of our ECS benchmarks by ~5-20%! * The parallel executor [now starts running systems](https://github.com/bevyengine/bevy/pull/4919) while the `prepare_systems` step is running, cutting out a lot of delay when there are many systems with very little work to do. This cut almost 1 millisecond from our `many_foxes` animation benchmark (~12% improvement). That is a _very_ big deal! * Iterators now [skip empty archetypes and tables](https://github.com/bevyengine/bevy/pull/4724) when iterating over queries, which significantly reduces per-archetype iteration overhead when the archetype is empty. @@ -897,7 +897,7 @@ if let ReflectOwned::Struct(owned) = value.reflect_owned() { } ``` -Arrays in the "reflection path api" can now use list syntax: +Arrays in the "reflection path API" can now use list syntax: ```rust #[derive(Reflect)] @@ -1004,7 +1004,7 @@ In a previous release we [made it possible to make vertex attributes optional by
authors: @Neo-Zhixing
-Wgpu has opt-in support for "multi draw indirect" apis on platforms that support them, which are a key piece of implementing efficient "gpu driven rendering". Bevy now exposes these apis through its "tracked render pass" abstraction, enabling developers to build render features using these apis. +Wgpu has opt-in support for "multi draw indirect" APIs on platforms that support them, which are a key piece of implementing efficient "gpu driven rendering". Bevy now exposes these APIs through its "tracked render pass" abstraction, enabling developers to build render features using these APIs. ## KTX2 Array / Cubemap / Cubemap Array Textures @@ -1079,7 +1079,7 @@ In past versions of Bevy, "immutable" Plugin settings were represented as normal These were especially problematic and confusing for the `WindowDescriptor` resource, but it was a general problem. -To resolve this, in **Bevy 0.9** we moved plugin settings onto the plugins themselves, and created new apis for overriding the default settings: +To resolve this, in **Bevy 0.9** we moved plugin settings onto the plugins themselves, and created new APIs for overriding the default settings: ```rust app.add_plugins(DefaultPlugins @@ -1313,7 +1313,7 @@ let wrapped = time.seconds_since_startup_wrapped_f32(); Here are some of the things -* **High Level Post Processing Stack**: Now that we have the core post processing pipeline in place, we need to make a higher level system that makes it easier for users to select, configure, and re-order post processing effects on a per-camera basis. Additionally for performance reasons we want to combine as many post processing effects into a single pass as we can, so we need an opinionated set of post processing apis that facilitate this. +* **High Level Post Processing Stack**: Now that we have the core post processing pipeline in place, we need to make a higher level system that makes it easier for users to select, configure, and re-order post processing effects on a per-camera basis. Additionally for performance reasons we want to combine as many post processing effects into a single pass as we can, so we need an opinionated set of post processing APIs that facilitate this. * **More Post Processing Effects**: More anti-aliasing options (TAA, SMAA), more tonemapping algorithm options (Ex: ACES), SSAO * **Asset Preprocessing**: We will be investing heavily in our asset pipeline, with a focus on: 1. Pre-processing assets to do expensive work "during development time", so Bevy Apps can be deployed with assets that are prettier, smaller, and/or faster to load. diff --git a/content/news/2023-01-14-scaling-bevy-development/bevy_people.png b/content/news/2023-01-14-scaling-bevy-development/bevy_people.png new file mode 100644 index 0000000000..f5044b0e60 Binary files /dev/null and b/content/news/2023-01-14-scaling-bevy-development/bevy_people.png differ diff --git a/content/news/2023-01-14-scaling-bevy-development/index.md b/content/news/2023-01-14-scaling-bevy-development/index.md new file mode 100644 index 0000000000..24f1159e05 --- /dev/null +++ b/content/news/2023-01-14-scaling-bevy-development/index.md @@ -0,0 +1,90 @@ ++++ +title = "Scaling Bevy Development" +date = 2023-01-14 +[extra] +author = "Carter Anderson" +twitter = "cart_cart" +github = "cart" +youtube = "cartdev" +image = "scaling_bevy.svg" +show_image = true ++++ + +The Bevy community has grown a lot over the past couple of years. We've had over 3,642 pull requests, 599 contributors, 357,917 downloads, and 21,200 github stars. Together we've built the most popular, most used Rust game engine on the market and the [second most popular game engine on GitHub](https://github.com/topics/game-engine). Up until now, in the interest of maintaining a consistent vision and quality bar, I've kept our decision making process as small and centralized as possible. And I scaled out our leadership roles as slowly as possible. I believe this was the right call for Bevy's early days, but we are overdue for changes that bias toward more trust and development agility. + + + +## The Current State Of Things + +I _have_ been slowly delegating responsibility over time, and each time I placed trust in someone it yielded massive benefits to both the project and my personal well being. We now have 3 more fantastic Maintainers: Alice (@alice-i-cecile), François (@mockersf), and Rob (@superdump). And their scope has grown over time. + +But even today, I must personally approve _every_ "controversial" change to Bevy, where "controversial" is basically anything that meaningfully expands our features, user experience, or scope. With the volume of controversial changes we're seeing now, and the number of things I would still like to personally design and build, this is untenable. I have long since reached the limits of my bandwidth and the community has felt those limits for long enough. + +When Bevy was younger and the community was newer, this level of conservativeness made sense. I knew what I wanted to build, how the pieces fit together, and what my capabilities were. What I didn't know as well was what everyone else wanted to build, what their capabilities were, and how that all fit into my personal vision. + +I can now happily report that the situation has changed. We have proven technical experts in a variety of areas. They regularly design and build huge pieces of Bevy in a way that aligns with our collective vision for the future. Sometimes we have different ideas about what the future should look like, but we almost always reach consensus eventually. They have done outstanding technical work, built trust, and made Bevy amazing. They deserve a seat at the table. + +With that preamble out of the way, I am excited to announce two major changes to the Bevy Organization. + +## A New Role: Subject Matter Expert + +Subject Matter Experts (SME for short) are Bevy developers that have consistently demonstrated technical expertise and synchronized vision within a given "subject area" (ex: Rendering, ECS, Reflection, Animation). They must have contributed and reviewed significant pieces of Bevy within their area. These people have the ability to vote on controversial pull requests in their subject area (both [code changes](https://github.com/bevyengine/bevy) and [RFCs](https://github.com/bevyengine/rfcs)). SMEs are also great people to reach out to if you have questions about a given subject area in Bevy. + +If two SMEs within a given subject area approve a "controversial" PR, a maintainer can now merge it. We are intentionally keeping the number of SMEs within a subject area small to make establishing consensus and enforcing a consistent vision easier. For now, 2 SMEs is the bare minimum to allow voting to occur, 3 is the "sweet spot", and 4 will be allowed under some circumstances, but is the "upper limit". + +As Project Lead, I can still merge controversial PRs. Consider 2 SME approvals as equivalent to a Project Lead approval. As a last line of defense for cohesion, the Project Lead maintains final say on changes. While I will by default defer to the SMEs, if they approve a PR that I firmly believe is the wrong direction for Bevy, I will still block or revert the change. Preserving consistent vision and quality is critically important to me. But I intend to bias toward trust and consensus as much as possible. + +It is the job of SMEs to strive for consensus amongst themselves, the wider Bevy community, and Project Leads. They can merge controversial changes without me, but they still must do their best to anticipate my reaction to those changes (and discuss the changes with me ahead of time when that feels relevant). Likewise, I will try to establish consensus with SMEs and the wider community before making changes myself. + +We are rolling out SMEs slowly so we can tweak the process over time and avoid changing too much too quickly. We've largely started with subject areas that have the most activity and the clearest subject matter experts. Join me in welcoming our initial set of SMEs! + +* **Rendering**: @superdump (Rob Swain), @robtfm (Rob Macdonald) +* **ECS**: @BoxyUwU (Boxy), @james7132 (James Liu), @maniwani (Joy) +* **Reflection**: @MrGVSV (Gino Valente), @jakobhellermann (Jakob Hellermann) +* **Animation**: @james7132 (James Liu), @mockersf (François Mockers) + +Hopefully there aren't too many surprises here. These people have been building fantastic things in their areas for a long time now. + +We will be rolling out more subject areas (and the SMEs inside them) as SMEs prove themselves within the Bevy project and express interest. New areas are largely defined by the experts doing work inside them. We expect areas like UI, Editor, and Audio to be populated in reasonably short order. + +We have also left spots open in each of the subject areas above. If you believe you meet our SME criteria for any current or proposed subject area and have interest in the role, don't hesitate to reach out to myself or any of the other maintainers. We will consider new candidates regularly. Just because you weren't included in this first batch doesn't mean we don't think you would be a good fit! + +## A New Maintainer + +We also want to improve our velocity for merging uncontroversial pull requests. And there will be new maintainership load associated with facilitating the SME process. The current maintainers and I have unanimously agreed that it is time to bring on one more maintainer. + +Join me in welcoming James Liu (@james7132) as our latest maintainer! James has proven themselves to be a technical expert across many of Bevy's systems (especially ECS, animation, parallelization / task scheduling, and optimization). You may have noticed that they also have the SME role for ECS and Animation. They have contributed huge volumes of code changes, provided solid reviews, are easy to work with, and have a vision for Bevy's future that aligns with ours. + +## A New Bevy Organization Document + +We have a new [Bevy Organization Document](https://github.com/cart/bevy/blob/sme/docs/the_bevy_organization.md), which describes how the Bevy Organization will work going forward. It outlines the functionality of each role, as well as the expectations we have for them. The previously existing roles (Project Lead, Maintainer) still work the same way, but their definition and scope have been made much clearer. + +The biggest changes to the organization are the new SME role and an initial description of "role rotation": + +Roles like Project Lead, Maintainer, and SME are intentionally kept in limited supply to ensure a cohesive project vision. However these roles can be taxing, sometimes other aspects of life need to take priority, and qualified motivated people deserve a chance to lead. To resolve these issues, we plan on building in "role rotation". What this looks like hasn't yet been determined (as this issue hasn't come up yet and we are still in the process of scaling out our team), but we will try to appropriately balance the needs and desires of both current and future leaders, while also ensuring consistent vision and continuity for Bevy. + +## The Bevy People Page + +Bevy is a community-driven project. It makes sense for the people behind Bevy and the roles they fill to be easily discoverable. + +To make that happen, François (@mockersf) and I built a new [Bevy People](https://bevyengine.org/community/people/) page. "Bevy people" can opt-in to listing their name and/or pseudonym, their social information (GitHub, Discord, Mastodon, Twitter, personal website, itch.io, etc), a sponsorship link, and a personal bio describing who they are and what they work on. + +It also displays the current Bevy Organization roles these people occupy. You _could_ call it an "org chart" if you wanted to, but my anti-bureaucracy reflexes prevent me from doing so. The Bevy community will always be as flat and "people first" as possible. + +It is open to anyone (both Bevy Organization members and the wider Bevy community). If you would like to see yourself on this page, [create a pull request here](https://github.com/bevyengine/bevy-community). + +This is what it looks like! +![bevy people](bevy_people.png) + +## Looking Forward + +The next Bevy release (Bevy 0.10) is roughly a month away and I'm very excited for the changes we have in the pipeline. I can't guarantee all of these will make it in, but they're all shaping up nicely: + +* **The New "Stageless" ECS Scheduler**: We've fully rebuilt our scheduler to be more flexible. We no longer need "stages" to handle "exclusive system scheduling". Any system of any type can be ordered relative to any other system (even if they have exclusive access to the ECS `World`. Many scheduling APIs are now cleaner and easier to use. And we've taken the chance to improve related APIs like States as well. +* **Depth and Normal Prepass**: This will give rendering feature developers access to the depth buffer and normals during the main render phase, which enables a variety of render features and optimizations. +* **Screen Space Ambient Occlusion**: This is a popular, relatively cheap illumination technique that can make scenes look much more natural. It builds on the Depth Prepass work. +* **Asset Preprocessing**: We're reworking our asset system to allow for pre processing assets into more efficient forms, which can make deployed games faster to load, prettier, and faster. This is a full asset system rework that improves a good portion of our asset APIs. +* **Windows as Entities**: Windows are now ECS Entities instead of Resources, which makes them more natural to construct and query, more extensible, and opens the doors to including them in Bevy Scenes. +* **UI Style Split**: Breaks the monolithic UI style type out into smaller pieces, embracing a less centralized and more extensible pattern. + +See you in about a month! diff --git a/content/news/2023-01-14-scaling-bevy-development/scaling_bevy.svg b/content/news/2023-01-14-scaling-bevy-development/scaling_bevy.svg new file mode 100644 index 0000000000..e15ed31eae --- /dev/null +++ b/content/news/2023-01-14-scaling-bevy-development/scaling_bevy.svg @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/news/2023-03-06-bevy-0.10/alpha_mask_shadows.png b/content/news/2023-03-06-bevy-0.10/alpha_mask_shadows.png new file mode 100644 index 0000000000..bff75c90ae Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/alpha_mask_shadows.png differ diff --git a/content/news/2023-03-06-bevy-0.10/android emulator.png b/content/news/2023-03-06-bevy-0.10/android emulator.png new file mode 100644 index 0000000000..f1557a3f0d Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/android emulator.png differ diff --git a/content/news/2023-03-06-bevy-0.10/animation_transition.mp4 b/content/news/2023-03-06-bevy-0.10/animation_transition.mp4 new file mode 100644 index 0000000000..cf78f7b9a2 Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/animation_transition.mp4 differ diff --git a/content/news/2023-03-06-bevy-0.10/atmospheric-fog.png b/content/news/2023-03-06-bevy-0.10/atmospheric-fog.png new file mode 100644 index 0000000000..ba9643d901 Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/atmospheric-fog.png differ diff --git a/content/news/2023-03-06-bevy-0.10/blend-modes.png b/content/news/2023-03-06-bevy-0.10/blend-modes.png new file mode 100644 index 0000000000..544cf22486 Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/blend-modes.png differ diff --git a/content/news/2023-03-06-bevy-0.10/bloom_example.png b/content/news/2023-03-06-bevy-0.10/bloom_example.png new file mode 100644 index 0000000000..3fbd236514 Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/bloom_example.png differ diff --git a/content/news/2023-03-06-bevy-0.10/cubic_curves.mp4 b/content/news/2023-03-06-bevy-0.10/cubic_curves.mp4 new file mode 100644 index 0000000000..4a6e8da8c4 Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/cubic_curves.mp4 differ diff --git a/content/news/2023-03-06-bevy-0.10/demo-ruins.mp4 b/content/news/2023-03-06-bevy-0.10/demo-ruins.mp4 new file mode 100644 index 0000000000..7ade5f5a0b Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/demo-ruins.mp4 differ diff --git a/content/news/2023-03-06-bevy-0.10/edge_detection.png b/content/news/2023-03-06-bevy-0.10/edge_detection.png new file mode 100644 index 0000000000..04aca55c8f Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/edge_detection.png differ diff --git a/content/news/2023-03-06-bevy-0.10/edge_detection_prepass.png b/content/news/2023-03-06-bevy-0.10/edge_detection_prepass.png new file mode 100644 index 0000000000..9051a992b1 Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/edge_detection_prepass.png differ diff --git a/content/news/2023-03-06-bevy-0.10/env_map_after.png b/content/news/2023-03-06-bevy-0.10/env_map_after.png new file mode 100644 index 0000000000..9c0904692b Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/env_map_after.png differ diff --git a/content/news/2023-03-06-bevy-0.10/env_map_before.png b/content/news/2023-03-06-bevy-0.10/env_map_before.png new file mode 100644 index 0000000000..b9a3dbda71 Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/env_map_before.png differ diff --git a/content/news/2023-03-06-bevy-0.10/exposure_005.png b/content/news/2023-03-06-bevy-0.10/exposure_005.png new file mode 100644 index 0000000000..af0aa2fbe0 Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/exposure_005.png differ diff --git a/content/news/2023-03-06-bevy-0.10/exposure_225.png b/content/news/2023-03-06-bevy-0.10/exposure_225.png new file mode 100644 index 0000000000..7568e77a1b Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/exposure_225.png differ diff --git a/content/news/2023-03-06-bevy-0.10/fog.png b/content/news/2023-03-06-bevy-0.10/fog.png new file mode 100644 index 0000000000..a6b8bfbebc Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/fog.png differ diff --git a/content/news/2023-03-06-bevy-0.10/force_field.mp4 b/content/news/2023-03-06-bevy-0.10/force_field.mp4 new file mode 100644 index 0000000000..7f4f662ad2 Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/force_field.mp4 differ diff --git a/content/news/2023-03-06-bevy-0.10/ime.mp4 b/content/news/2023-03-06-bevy-0.10/ime.mp4 new file mode 100644 index 0000000000..fe911b4a97 Binary files /dev/null and b/content/news/2023-03-06-bevy-0.10/ime.mp4 differ diff --git a/content/news/2023-03-06-bevy-0.10/index.md b/content/news/2023-03-06-bevy-0.10/index.md new file mode 100644 index 0000000000..cf04989224 --- /dev/null +++ b/content/news/2023-03-06-bevy-0.10/index.md @@ -0,0 +1,2886 @@ ++++ +title = "Bevy 0.10" +date = 2023-03-06 +[extra] +author = "Bevy Contributors" +image = "ruins.png" +show_image = true +image_subtitle = "Ruins scene illustrating Bevy's new material blend modes and fog. Based on original scene by Casey Hardy (CC Attribution)" +image_subtitle_link = "https://github.com/coreh/bevy-demo-ruins" ++++ + +Thanks to **173** contributors, **689** pull requests, community reviewers, and our [**generous sponsors**](/community/donate), we're happy to announce the **Bevy 0.10** release on [crates.io](https://crates.io/crates/bevy)! + +For those who don't know, Bevy is a refreshingly simple data-driven game engine built in Rust. You can check out our [Quick Start Guide](/learn/book/getting-started/) to try it today. It's free and open source forever! You can grab the full [source code](https://github.com/bevyengine/bevy) on GitHub. Check out [Bevy Assets](https://bevyengine.org/assets) for a collection of community-developed plugins, games, and learning resources. + +To update an existing Bevy App or Plugin to **Bevy 0.10**, check out our [0.9 to 0.10 Migration Guide](/learn/migration-guides/0.9-0.10/). + +Since our last release a few months ago we've added a _ton_ of new features, bug fixes, and quality of life tweaks, but here are some of the highlights: + + + +* **ECS Schedule v3**: Bevy now has much simpler, more flexible scheduling. Systems are now stored in a unified schedule, commands can be applied explicitly via `apply_system_buffers`, and a whole lot of quality of life and bug fixes. +* **Cascaded Shadow Maps**: Higher quality shadow maps that cover larger distances, where the quality follows the camera. +* **Environment Map Lighting**: 360 degree ambient image based lighting that can cheaply and drastically improve the visual quality of a scene. +* **Depth and Normal Prepass**: Render depth and normal textures for a scene prior to the main pass, enabling new effects and (in some cases) improved performance. Shadow mapping uses the prepass shaders, which enables transparent textures to cast shadows. +* **Smooth Skeletal Animation Transitions**: Smoothly transition between two skeletal animations playing at the same time! +* **Improved Android Support**: Bevy now works out of the box on more Android devices (with a couple of caveats) +* **Revamped Bloom**: Bloom now looks better, is easier to control, and has fewer visual artifacts. +* **Distance and Atmospheric Fog**: Add depth and ambiance to your scene with 3D distance and atmospheric fog effects! +* **StandardMaterial Blend Modes**: Achieve a variety of interesting effects with more PBR material blend modes. +* **More Tonemapping Choices**: Choose one of 7 popular tonemapping algorithms for your HDR scenes to achieve the visual style you are looking for. +* **Color Grading**: Control per-camera exposure, gamma, "pre-tonemapping saturation", and "post-tonemapping saturation". +* **Parallel Pipelined Rendering**: App logic and render logic now run in parallel automatically, yielding significant performance wins. +* **Windows as Entities**: Windows are now represented as entities instead of resources, improving the user experience and unlocking new scenarios. +* **Renderer Optimizations**: We spent a _ton_ of effort optimizing the renderer this cycle. Bevy's renderer is snappier than ever! +* **ECS Optimizations**: Likewise, we've turbocharged many common ECS operations. Bevy apps get a nice speed boost! + +## ECS Schedule v3 + +
authors: @alice-i-cecile, @maniwani, @WrongShoe, @cart, @jakobhellermann, @JoJoJet, @geieredgar and a whole lot more
+ +Thanks to the fantastic work of our ECS team, the hotly awaited ["stageless" scheduling RFC](https://github.com/bevyengine/rfcs/blob/main/rfcs/45-stageless.md) has been implemented! + +**Schedule v3** is the culmination of significant design and implementation work. Scheduling APIs are a central and defining part of the Bevy developer experience, so we had to be very thoughtful and meticulous about this next evolution of the API. In addition to the [RFC PR](https://github.com/bevyengine/rfcs/pull/45), the [initial implementation PR](https://github.com/bevyengine/bevy/pull/6587) by `@maniwani` and the [Bevy Engine internals port PR](https://github.com/bevyengine/bevy/pull/7267) by `@alice-i-cecile` are great places to start if you would like a view into our process and rationale. As we all know, plans and implementations are two different things. Our final implementation is a bit different from the initial RFC (in a good way). + +There are a ton of changes, but we've put a lot of care into ensuring the [migration path](/learn/migration-guides/0.9-0.10/#migrate-engine-to-schedule-v3-stageless) for existing applications is relatively straightforward. Don't sweat it! + +Let's take a look at what shipped in 0.10! + +### A Single Unified Schedule + +Have you ever wanted to specify that `system_a` runs before `system_b`, only to be met with confusing warnings that `system_b` isn't found because it's in a different stage? + +No more! All systems within a single [`Schedule`] are now stored in a single data structure with a global awareness of what's going on. + +This simplifies our internal logic, makes your code more robust to refactoring, and allows plugin authors to specify high-level invariants (e.g. "movement must occur before collision checking") without locking themselves into an exact schedule location. + +[![main_schedule_diagram](main_schedule_diagram.svg)](main_schedule_diagram.svg) + +This diagram made with [@jakobhellermann's `bevy_mod_debugdump` crate](https://github.com/jakobhellermann/bevy_mod_debugdump) shows a simplified version of Bevy's default schedule. + +[`Schedule`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/struct.Schedule.html + +### Adding Systems + +[`Systems`] (which are just [normal Rust functions!](https://github.com/bevyengine/bevy/tree/v0.10.0/crates/bevy_ecs#systems)) are how you define game logic in Bevy ECS. With **Schedule v3**, you can add systems to your [`App`] just like you did in previous versions: + +```rust +app.add_system(gravity) +``` + +However **Schedule v3** has some new tricks up its sleeve! You can now add multiple systems at once: + +```rust +app.add_systems((apply_acceleration, apply_velocity)) +``` + +By default, Bevy runs systems in parallel to each other. In previous versions of Bevy, you ordered systems like this: + +```rust +app + .add_system(walk.before(jump)) + .add_system(jump) + .add_system(collide.after(jump)) +``` + +You can still do that! But you can now compress this using `add_systems`: + +```rust +// much cleaner! +app.add_systems(( + walk.before(jump), + jump, + collide.after(jump), +)) +``` + +`before()` and `after()` are definitely useful tools! However, thanks to the new `chain()` function, it is now _much easier_ to run systems in a specific order: + +```rust +// This is equivalent to the previous example +app.add_systems((walk, jump, collide).chain()) +``` + +`chain()` will run the systems in the order they were defined. Chaining also pairs with per-system configuration: + +```rust +app.add_systems((walk.after(input), jump, collide).chain()) +``` + +[`App`]: https://docs.rs/bevy/0.10.0/bevy/app/struct.App.html +[`Systems`]: https://docs.rs/bevy/0.10.0/bevy/ecs/system/trait.System.html + +### Configurable System Sets + +In **Schedule v3**, the idea of the "system set" has been redefined to support more natural and flexible control over how systems are run and scheduled. The old "system label" concept has been combined with the "set" concept, resulting in one straightforward but powerful abstraction. + +[`SystemSets`] are named collections of systems that share system configuration across all of their members. Ordering systems relative to a [`SystemSet`] applies that ordering to _all_ systems in that set, in addition to any configuration on each individual system. + +Let's jump right into what this would look like. You define [`SystemSets`] like this: + +```rust +#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)] +enum PhysicsSet { + Movement, + CollisionDetection, +} +``` + +You can add systems to sets by calling the [`in_set`] method: + +```rust +app.add_system(gravity.in_set(PhysicsSet::Movement)) +``` + +You can combine this with the new system features mentioned above: + +```rust +app.add_systems( + (apply_acceleration, apply_velocity) + .chain() + .in_set(PhysicsSet::Movement) +) +``` + +Systems can belong to any number of sets: + +```rust +app.add_system( + move_player + .in_set(MoveSet::Player) + .in_set(PhysicsSet::Movement) +) +``` + +Configuration is added to sets like this: + +```rust +app.configure_set( + // Run systems in the Movement set before systems in the CollisionDetection set + PhysicsSet::Movement.before(PhysicsSet::CollisionDetection) +) +``` + +Sets can be nested inside other sets, which will cause them to inherit the configuration of their parent set: + +```rust +app.configure_set(MoveSet::Enemy.in_set(PhysicsSet::Movement)) +``` + +Sets can be configured multiple times: + +```rust +// In PlayerPlugin: +app.configure_set(MoveSet::Player.before(MoveSet::Enemy)) + +// In PlayerTeleportPlugin +app.configure_set(MoveSet::Player.after(PortalSet::Teleport)) +``` + +Crucially system configuration is strictly additive: you cannot _remove_ rules added elsewhere. This is both an "anti-spaghetti" and "plugin privacy" consideration. When this rule is combined with Rust's robust type privacy rules, plugin authors can make careful decisions about which exact invariants need to be upheld, and reorganize code and systems internally without breaking consumers. + +Configuration rules _must be compatible with each other_: any paradoxes (like a system set inside of itself, a system that must run both before and after a set, order cycles, etc) will result in a runtime panic with a helpful error message. + +[`SystemSet`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/trait.SystemSet.html +[`SystemSets`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/trait.SystemSet.html +[`in_set`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/trait.IntoSystemConfig.html#method.in_set + +### Directly Schedule Exclusive Systems + +"Exclusive systems" are [`Systems`] that have mutable direct access to the entire ECS [`World`]. For this reason, they cannot be run in parallel with other [`Systems`]. + +Since Bevy's inception, Bevy devs have wanted to schedule exclusive systems (and flush commands) relative to normal systems. + +Now you can! Exclusive systems can now be scheduled and ordered like any other system. + +```rust +app + .add_system(ordinary_system) + // This works! + .add_system(exclusive_system.after(ordinary_system)) +``` + +This is particularly powerful, as **command flushes** (which apply queued-up [`Commands`] added in systems to do things like spawn and despawn entities) are now simply performed in the `apply_system_buffers` exclusive system. + +```rust +app.add_systems( + ( + // This system produces some commands + system_a, + // This will apply the queued commands from system_a + apply_system_buffers, + // This system will have access to the results of + // system_a's commands + system_b, + // This chain ensures the systems above run in the order + // they are defined + ).chain() +) +``` + +Do be careful with this pattern though: it's easy to quickly end up with many poorly ordered exclusive systems, creating bottlenecks and chaos. + +What will you do with this much power? We're keen to find out! + +### Managing Complex Control Flow with Schedules + +But what if you want to do something _weird_ with your [`Schedule`]? Something non-linear, branching, or looping. What should you reach for? + +It turns out, Bevy already _had_ a great tool for this: schedules that run inside of an exclusive system. The idea is pretty simple: + +1. Construct a schedule, that stores whatever complex logic you want to run. +2. Store that schedule inside of a resource. +3. In an exclusive system, perform any arbitrary Rust logic you want to decide if and how your schedule runs. +4. Temporarily take the schedule out of the [`World`], run it on the rest of the world to mutate both the schedule and the world, and then put it back in. + +With the addition of the new [`Schedules`] resource and the `world.run_schedule()` API it's more ✨ ergonomic ✨ than ever. + +```rust +// A Schedule! +let mut my_schedule = Schedule::new(); +schedule.add_system(my_system); + +// A label for our new Schedule! +#[derive(ScheduleLabel, Debug, Hash, PartialEq, Eq, Clone)] +struct MySchedule; + +// An exclusive system to run this schedule +fn run_my_schedule(world: &mut World) { + while very_complex_logic() { + world.run_schedule(MySchedule); + } +} + +// Behold the ergonomics! +app + .add_schedule(MySchedule, my_schedule) + .add_system(run_my_schedule); +``` + +Bevy uses this pattern for five rather different things in **Bevy 0.10**: + +1. **Startup systems:** these now live in their own schedule, which is run once at the start of the app. +2. **Fixed timestep systems:** another schedule?! The exclusive system that runs this schedule accumulates time, running a while loop that repeatedly runs `CoreSchedule::FixedUpdate` until all of the accumulated time has been spent. +3. **Entering and exiting states:** a bonanza of schedules. Each collection of systems that runs logic to enter and exit a state variant is stored in its own schedule, which is called based on the change in state in the `apply_state_transitions::` exclusive system. +4. **Rendering:** all rendering logic is stored in its own schedule to allow it to run asynchronously relative to gameplay logic. +5. **Controlling the outermost loop:** in order to handle the "startup schedule first, then main schedule" logic, we wrap it all up in a minimal overhead `CoreSchedule::Outer` and then run our schedules as the sole exclusive system there. + +Follow the breadcrumbs starting at [`CoreSchedule`](https://docs.rs/bevy/0.10.0/bevy/app/enum.CoreSchedule.html) for more info. + +[`Schedules`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/struct.Schedules.html + +### Run Conditions + +[`Systems`] can have any number of **run conditions**, which are "just" systems that return a `bool`. If the `bool`s returned by _all_ of a system's **run conditions** are `true`, the system will run. Otherwise the system will be skipped for the current run of the schedule: + +```rust +// Let's make our own run condition +fn game_win_condition(query: Query<&Player>, score: Res) -> bool { + let player = query.single(); + player.is_alive() && score.0 > 9000 +} + +app.add_system(win_game.run_if(game_win_condition)); +``` + +**Run conditions** also have a number of "combinator" operations, thanks to [@JoJoJet](https://github.com/bevyengine/bevy/pull/7547) and [@Shatur](https://github.com/bevyengine/bevy/pull/7559): + +They can be negated with `not()`: + +```rust +app.add_system(continue_game.run_if(not(game_win_condition))) +``` + +They can also be combined with `and_then` and `or_else`: + +```rust +app.add_system(move_player.run_if(is_alive.or_else(is_zombie))) +``` + +Bevy 0.10 is shipping with a lovely collection of built-in [common run conditions](https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/common_conditions/index.html). You can easily run systems if there are events to process, timers that elapsed, resources that changed, input state changes, states that changed, and more (thanks to [`@maniwani`](https://github.com/bevyengine/bevy/pull/6587), [`@inodentry`](https://github.com/bevyengine/bevy/pull/7579), [`@jakobhellermann`](https://github.com/bevyengine/bevy/pull/7806), and [`@jabuwu`](https://github.com/bevyengine/bevy/pull/7866)). + +**Run conditions** can also serve as a lightweight optimization tool. Run conditions are evaluated on the main thread, and each run criteria is evaluated exactly once each schedule update, at the time of the first system in the set that relies on it. Systems disabled by run conditions don't spawn a task, which can add up across many systems. Like always though: benchmark! + +**Run conditions** have replaced the "run criteria" in previous versions of Bevy. We can finally get rid of the dreaded "looping run criteria"! [`ShouldRun::YesAndCheckAgain`](https://docs.rs/bevy/0.9.1/bevy/ecs/schedule/enum.ShouldRun.html) was not exactly straightforward to reason about, either for engine devs or users. It's always a bad sign when your bool-like enums have four possible values. If you crave more complex control flow: use the "schedules in exclusive systems" pattern in the [section above](#directly-schedule-exclusive-systems). For the other 99% of use cases, enjoy the simpler `bool`-based run conditions! + +### Simpler States + +**Schedule v3** adds a new, much simpler "state system". [`States`] allow you to easily configure different [`App`] logic to run based on the current "state" of the [`App`]. + +You define [`States`] like this: + +```rust +#[derive(States, PartialEq, Eq, Debug, Clone, Hash, Default)] +enum AppState { + #[default] + MainMenu, + InGame, +} +``` + +Each variant of the enum corresponds to a different state the [`App`] can be in. + +You add [`States`] to your [`App`] like this: + +```rust +app.add_state::() +``` + +This will setup your [`App`] to use the given state. It adds the [`State`] resource, which can be used to find the current state the [`App`] is in: + +```rust +fn check_state(state: Res>) { + info!("We are in the {} state", state.0); +} +``` + +Additionally, `add_state` will create an `OnUpdate` set for each possible value, which you can then add your systems to. These sets run as part of the normal app update, but only when the app is in a given state: + +```rust +app + .add_systems( + (main_menu, start_game) + .in_set(OnUpdate(AppState::MainMenu)) + ) + .add_system(fun_gameplay.in_set(OnUpdate(AppState::InGame))); +``` + +It will also create `OnEnter` and `OnExit` schedules for each state, which will only run when transitioning from one state to another: + +```rust +app + .add_system(load_main_menu.in_schedule(OnEnter(AppState::MainMenu))) + .add_system(cleanup_main_menu.in_schedule(OnExit(AppState::MainMenu))) +``` + +`add_state` also adds the [`NextState`] resource, which can be used to queue a state change: + +```rust +fn start_game( + button_query: Query<&Interaction, With>, + mut next_state: ResMut>, +){ + if button_query.single() == Interaction::Pressed { + next_state.set(AppState::InGame); + } +} +``` + +This replaces Bevy's previous state system, which was very hard to deal with. It had state stacks, elaborate queued transitions, and error handling (that most people just unwrapped). The state stack was very complex to learn, very prone to exasperating bugs, and mostly ignored. + +As a result, in **Bevy 0.10** states are now "stackless": only one queued state of each type at a time. After lots of alpha testing, we're reasonably confident that this shouldn't be too bad to migrate away from. If you were relying on the state stack, you have plenty of options: + +* Build the "stack" logic on top of the core state system +* Split your state into multiple states, which capture orthogonal elements of your app's status +* Build your own state stack abstraction using the same patterns as Bevy's first-party version. None of the new state logic is hard coded! If you build something, [let the rest of the community know](/assets) so you can collaborate! + +[`States`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/trait.States.html +[`State`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/struct.State.html +[`NextState`]: https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/struct.NextState.html + +### Base Sets: Getting Default Behavior Right + +An astute reader may point out that: + +1. Bevy automatically runs its systems in parallel. +2. [The order of systems is nondeterministic unless there is an explicit ordering relationship between them](https://github.com/bevyengine/bevy/blob/latest/examples/ecs/nondeterministic_system_order.rs) +3. All of the systems are now stored in a single `Schedule` object with no barriers between them +4. Systems can belong to any number of system sets, each of which can add their own behavior +5. Bevy is a powerful engine with many internal systems. + +Won't this lead to utter chaos and tedious spaghetti-flavored work to resolve every last ordering ambiguity? +Many users _liked_ stages, they were helpful for understanding the structure of an [`App`]! + +Well, we're glad you asked, rhetorical skeptic. To reduce this chaos (and ease migration), **Bevy 0.10** comes with a brand new collection of system sets provided by [`DefaultPlugins`]: [`CoreSet`](https://docs.rs/bevy/0.10.0/bevy/app/enum.CoreSet.html), [`StartupSet`](https://docs.rs/bevy/0.10.0/bevy/app/enum.StartupSet.html), and [`RenderSet`](https://docs.rs/bevy/0.10.0/bevy/render/enum.RenderSet.html). The similarity of their names to the old [`CoreStage`](https://docs.rs/bevy/0.9.1/bevy/app/enum.CoreStage.html), [`StartupStage`](https://docs.rs/bevy/0.9.1/bevy/app/enum.StartupStage.html), and [`RenderStage`](https://docs.rs/bevy/0.9.1/bevy/render/enum.RenderStage.html) is not a coincidence. Much like stages, there are command flush points between each set, and existing systems have been migrated directly. + +Some parts of the stage-centric architecture were appealing: a clear high-level structure, coordination on flush points (to reduce excessive bottlenecks), and good default behavior. +To keep those bits (while excising the frustrating ones), we've introduced the concept of **Base Sets** ([added by @cart](https://github.com/bevyengine/bevy/pull/7466)). **Base Sets** are just normal [`SystemSets`], except: + +1. Every system can belong to at most one base set. +2. Systems that do not specify a base set will be added to the default base set for the schedule (if the schedule has one). + +```rust +// You define base sets exactly like normal sets, with the +// addition of the system_set(base) attribute +#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] +#[system_set(base)] +enum MyBaseSet { + Early, + Late, +} + +app + // This ends up in CoreSet::Update by default + .add_system(no_explicit_base_set) + // You must use .in_base_set rather than .in_set for explicitness + // This is a high-impact decision! + .add_system(post_update.in_base_set(CoreSet::PostUpdate)) + // Look, it works! + .add_system(custom_base_set.in_base_set(MyBaseSet::Early)) + // Ordering your base sets relative to CoreSet is probably wise + .configure_set(MyBaseSet::Early.before(CoreSet::Update)) + .configure_set(MyBaseSet::Late.after(CoreSet::Update)); +``` + +Let me tell you a story, set in a world without **Base Sets**: + +1. A new user adds the `make_player_run` system to their app. +2. Sometimes this system runs before input handling, leading to randomly dropped inputs. Sometimes it runs after rendering, leading to strange flickers. +3. After much frustration, the user discovers that these are due to "system execution order ambiguities". +4. The user runs a specialized detection tool, digs into the source code of the engine, figures out what order their system should run in relative to the engine's system sets, and then continues on their merry way, doing this for each new system. +5. Bevy (or one of their third-party plugins) updates, breaking all of our poor users system ordering once again. + +The clear problem this illustrates is that _most_ gameplay systems should not need to know or care about "internal systems". + +We've found that in practice, there are three broad classes of systems: gameplay logic (the majority of all end user systems), stuff that needs to happen before gameplay logic (like event cleanup and input handling), and stuff that needs to happen after gameplay logic (like rendering and audio). + +By broadly ordering the schedule via **Base Sets**, Bevy apps can have good default behavior and clear high-level structure without compromising on the scheduling flexibility and explicitness that advanced users crave. +Let us know how it works out for you! + +### Improved System Ambiguity Detection + +When multiple systems interact with an ECS resource in conflicting ways, but don't have an ordering constraint between them, we call this an "ambiguity". If your [`App`] has ambiguities, this can cause bugs. We've significantly improved our ambiguity reporting, which can be configured in the new [`ScheduleBuildSettings`](https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/struct.ScheduleBuildSettings.html). Check out the docs for more info. If you haven't tried this out on your app yet: you should take a look! + +### Single Threaded Execution + +You can now easily switch a [`Schedule`] to single-threaded evaluation via the [`SingleThreadedExecutor`](https://docs.rs/bevy/0.10.0/bevy/ecs/schedule/struct.SingleThreadedExecutor.html) for users who don't want or need parallelism. + +```rust +schedule.set_executor_kind(ExecutorKind::SingleThreaded); +``` + +## Cascaded Shadow Maps + +
authors: @danchia, Rob Swain (@superdump)
+ +Bevy uses "shadow maps" to cast shadows for lights / objects. Previous versions of Bevy used a simple but limited shadow map implementation for directional light sources. For a given light, you would define the resolution of the shadow map _and_ a manual "view projection" that would determine how the shadow is cast. This had a number of downsides: + +* The resolution of the shadow map was fixed. You had to choose something between "cover a large area, but have a lower resolution" and "cover a smaller area, but have a higher resolution". +* The resolution didn't adapt to camera positioning. Shadows might look great in one position, but terrible in another position. +* The "shadow projection" had to be manually defined. This made it hard and unapproachable to configure shadows to match a given scene. + +**Bevy 0.10** adds "cascaded shadow maps", which breaks up the camera's view frustum into a series of configurable "cascades", which each have their own shadow map. This enables shadows in the cascade "close to the camera" to be highly detailed, while allowing shadows "far from the camera" to cover a wider area with less detail. Because it uses the camera's view frustum to define the shadow projections, the shadow quality remains consistent as the camera moves through the scene. This also means that users don't need to manually configure shadow projections anymore. They are automatically calculated! + + + +Notice how the nearby shadows are highly detailed whereas the shadows in the distance become less detailed as they get farther away (which doesn't matter as much because they are far away). + +While shadow cascades solve important problems, they also introduce new ones. How many cascades should you use? What is the minimum and maximum distance from the camera where shadows should appear? How much overlap should there be between cascades? Be sure to dial in these parameters to fit your scenes. + +## Environment Map Lighting + +
authors: @JMS55
+ +Environment maps are a popular and computationally cheap way to significantly improve the quality of a scene's lighting. It uses a cube map texture to provide 360 degree lighting "from all directions". This is especially apparent for reflective surfaces, but it applies to all lit materials. + +This is what the PBR material looks like without environment map lighting: + +![env map before](env_map_before.png) + +And this is what the PBR material looks like with environment map lighting: + +![env map after](env_map_after.png) + +For scenes that need constant lighting (especially outdoor scenes), environment maps are a great solution. And because environment maps are arbitrary images, artists have a lot of control over the character of the scene's lighting. + +## Depth and Normal Prepass + +
authors: @icesentry, Rob Swain (@superdump), @robtfm, @JMS55
+ + +

This effect uses the depth from the prepass to find the intersection between the ground and the force field

+ +Bevy now has the ability to run a depth and/or normal prepass. This means the depth and normal textures will be generated in a render pass that runs before the main pass and can therefore be used during the main pass. This enables various special effects like Screen Space Ambient Occlusion, Temporal Anti Aliasing, and many more. These are currently being worked on and should be [available in the next release of Bevy](#what-s-next). + +![Edge detection](edge_detection.png) +

In the image on the right, green lines are edges detected in the normal texture and blue lines are edges detected in the depth texture

+ +![Edge detection prepass](edge_detection_prepass.png) +

The depth and normal textures generated by the prepass

+ +Using the prepass essentially means rendering everything twice. The prepass itself is much faster since it does a lot less work than the main pass. The result of the prepass can be used to reduce overdraw in the main pass, but if your scene didn't already suffer from overdraw then enabling the prepass will negatively affect performance. There are many things that can be done to improve this and we will keep working towards this goal. Like with anything performance related, make sure to measure it for your use case and see if it helps or not. + +The prepass is still very useful when working on special effects that require a depth or normal texture, so if you want to use it you can simply add the `DepthPrepass` or `NormalPrepass` components to your camera. + +## Shadow Mapping using Prepass Shaders + +
authors: @geieredgar
+ +Previously, the shader used for shadow mapping was hard-coded and had no knowledge of the material, only meshes. Now in **Bevy 0.10**, a `Material`'s depth prepass shaders are used for shadow mapping. This means that the shaders used to do the shadow mapping for a `Material` are customizable! + +As a bonus, the availability of `Material` information during shadow mapping means that we could instantly enable alpha mask shadows allowing foliage to cast shadows according to the alpha values in their texture rather than only based on their geometry. + +![Alpha mask shadows](alpha_mask_shadows.png) +
+ +## Smooth Skeletal Animation Transitions + +
authors: @smessmer
+ +You can now smoothly transition between two (or more) skeletal animations! + + + +
Character model and animations are royalty free assets from Mixamo. +
+ +With the new [`play_with_transition`] method on the [`AnimationPlayer`] component, you can now specify a transition duration during which the new animation will be linearly blended with the currently playing animation, whose weight will decrease during that duration until it reaches `0.0`. + +```rust +#[derive(Component, Default)] +struct ActionTimer(Timer); + +#[derive(Component)] +struct Animations { + run: Handle, + attack: Handle, +} + +fn run_or_attack( + mut query: Query<(&mut AnimationPlayer, &mut ActionTimer, &Animations)>, + keyboard_input: Res>, + animation_clips: Res>, + time: Res
NVIDIA ORCA Emerald Square scene (CC BY-NC-SA 3.0) with alpha mask shadow support